diff --git a/README.md b/README.md index a5abf83..dd48a4e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ -# Federalé +# Hashbang fediverse client for feds by feds. uses the mastodon client API diff --git a/go.mod b/go.mod index 978553d..b45834c 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module federale +module hashbang go 1.24.3 diff --git a/main.go b/main.go index 51164f4..1c79191 100644 --- a/main.go +++ b/main.go @@ -1,3 +1,4 @@ +// TODO: RENAME ALL OCCURENCES OF FEDERALE WITH HASHBANG package main import ( @@ -18,6 +19,7 @@ import ( "encoding/json" "path/filepath" + _ "net/http" "context" "errors" @@ -36,17 +38,17 @@ var Version string = "25w47a" // Client used for posting, getting posts, etc. var Client *mastodon.Client -// Federale config settings apply to all profiles. +// Hashbang config settings apply to all profiles. // The config stores the name of the profile to launch, // as well as if the profile selection screen should // show when the program is next launched. -type FederaleConfig struct { +type HashbangConfig struct { ProfileName string DoNotDropToProfileSelection bool } -type FederaleProfile struct { // Blueprint for a Federale profile +type HashbangProfile struct { // Blueprint for a Hashbang profile Name string // Name displayed to user InternalName string // Filename @@ -61,29 +63,29 @@ type FederaleProfile struct { // Blueprint for a Federale profile Running bool // Whether the profile is currently running } -var LoadedProfile *FederaleProfile // Profile currently loaded into memory for this Federale instance -var LoadedConfig *FederaleConfig // Config currently loaded into memory -var Profiles []*FederaleProfile // Profiles loaded from FS go here. +var LoadedProfile *HashbangProfile // Profile currently loaded into memory for this Hashbang instance +var LoadedConfig *HashbangConfig // Config currently loaded into memory +var Profiles []*HashbangProfile // Profiles loaded from FS go here. var ProfileSetupDone bool = false -var ProfileSetupProfile *FederaleProfile +var ProfileSetupProfile *HashbangProfile var ProfileSelectionDone bool = false -var ProfileSelectionProfile *FederaleProfile +var ProfileSelectionProfile *HashbangProfile // The visibility that the post is going to be posted with var PostVisibility string // This function saves the config in memory to disk. func SaveConfigToDisk() error { - ConfigPath := configdir.LocalConfig("federale") // Federale foler in the user's config directory + ConfigPath := configdir.LocalConfig("hashbang") // Hashbang foler in the user's config directory err := configdir.MakePath(ConfigPath) // Ensure it exists. if err != nil { return err } - ConfigFilePath := filepath.Join(ConfigPath, "federale.json") + ConfigFilePath := filepath.Join(ConfigPath, "hashbang.json") b, err := json.MarshalIndent(LoadedConfig, "", "\t") if err != nil { return err @@ -99,9 +101,9 @@ func SaveConfigToDisk() error { return nil } -// This function asks for the profile to launch Federale with. +// This function asks for the profile to launch Hashbang with. func ProfileLaunch() { - ConfigPath := configdir.LocalConfig("federale") // Federale foler in the user's config directory + ConfigPath := configdir.LocalConfig("hashbang") // Hashbang foler in the user's config directory err := configdir.MakePath(ConfigPath) // Ensure it exists. if err != nil { @@ -115,10 +117,10 @@ func ProfileLaunch() { for _, v := range Files { if !v.IsDir() { - if v.Name() == "federale.json" { + if v.Name() == "hashbang.json" { continue } - Profile := new(FederaleProfile) + Profile := new(HashbangProfile) dat, err := os.ReadFile(filepath.Join(ConfigPath, v.Name())) if err != nil { log.Println("ERR - " + err.Error()) @@ -158,9 +160,9 @@ func ProfileLaunch() { // Step one: register the application AppConfig := &mastodon.AppConfig{ Server: Domain, - ClientName: "Federalé", + ClientName: "Hashbang", Scopes: "read write push", - Website: "https://forge.sunglocto.net", + Website: "https://forge.sunglocto.net/sunglocto/Hashbang", RedirectURIs: "urn:ietf:wg:oauth:2.0:oob", } @@ -184,7 +186,7 @@ func ProfileLaunch() { // Step three: get the authorization code from the user dialog.ShowConfirm("Confirm", "Do you have an authorisation code?", func(b bool) { if b { - NewProfile := new(FederaleProfile) + NewProfile := new(HashbangProfile) NewProfile.Name = fmt.Sprintf("Profile %d", len(Profiles)+1) NewProfile.InternalName = uuid.New().String() NewProfile.Server = Domain @@ -238,7 +240,7 @@ func ProfileLaunch() { }) GoButton.Importance = widget.HighImportance - AddProfileBox.Add(widget.NewLabel("Federalé will log in via OAuth2\nInstance:")) + AddProfileBox.Add(widget.NewLabel("Hashbang will log in via OAuth2\nInstance:")) AddProfileBox.Add(InstanceEntry) AddProfileBox.Add(GoButton) @@ -294,23 +296,23 @@ func ProfileLaunch() { func main() { - log.Println("Checking for federale config") + log.Println("Checking for hashbang config") - ConfigPath := configdir.LocalConfig("federale") // Federale foler in the user's config directory + ConfigPath := configdir.LocalConfig("hashbang") // Hashbang foler in the user's config directory err := configdir.MakePath(ConfigPath) // Ensure it exists. - log.Println("Creating federale folder if it does not exist") + log.Println("Creating hashbang folder if it does not exist") if err != nil { panic(err) } log.Println("Checking if configuration file exists") - // Check if the Federale configuration file exists - _, err = os.Stat(filepath.Join(ConfigPath, "federale.json")) + // Check if the Hashbang configuration file exists + _, err = os.Stat(filepath.Join(ConfigPath, "hashbang.json")) if errors.Is(err, os.ErrNotExist) { log.Println("Creating new configuration") // Create a new configuration - EmptyConfig := new(FederaleConfig) + EmptyConfig := new(HashbangConfig) EmptyConfig.DoNotDropToProfileSelection = false log.Println("Converting configuration to JSON") b, err := json.MarshalIndent(EmptyConfig, "", "\t") @@ -320,7 +322,7 @@ func main() { log.Println("Saving configuration to disk") - err = os.WriteFile(filepath.Join(ConfigPath, "federale.json"), b, 0644) + err = os.WriteFile(filepath.Join(ConfigPath, "hashbang.json"), b, 0644) if err != nil { panic(err) } @@ -330,7 +332,7 @@ func main() { // Read the config from disk log.Println("Grabbing config from disk") - b, err := os.ReadFile(filepath.Join(ConfigPath, "federale.json")) + b, err := os.ReadFile(filepath.Join(ConfigPath, "hashbang.json")) // You get the gist by now if err != nil { panic(err) @@ -338,7 +340,7 @@ func main() { log.Println("Unmarshalling JSON") - tempconf := new(FederaleConfig) + tempconf := new(HashbangConfig) err = json.Unmarshal(b, tempconf) fmt.Println(tempconf) if err != nil { @@ -359,7 +361,7 @@ func main() { panic(err) } - tempprof := new(FederaleProfile) + tempprof := new(HashbangProfile) log.Println("Unmarshalling config to RAM") err = json.Unmarshal(b, tempprof) if err != nil { @@ -381,11 +383,11 @@ func main() { log.Println(Client) App = app.New() - MainWindow = App.NewWindow("Federalé") + MainWindow = App.NewWindow("Hashbang") TootEntry := widget.NewMultiLineEntry() ReplyIDEntry := widget.NewEntry() ReplyIDLabel := widget.NewLabel("In reply to") - ReplyBox := container.NewHBox(ReplyIDLabel, ReplyIDEntry) + ReplyBox := container.NewGridWithColumns(2, ReplyIDLabel, ReplyIDEntry) Timeline := container.NewGridWithColumns(4) @@ -393,7 +395,8 @@ func main() { PostVisibility = value }) - go func() { + ShowNotifications := func() { + Timeline.RemoveAll() pg := new(mastodon.Pagination) //NewTimeline := container.NewVBox(widget.NewLabel("Notifications")) notis, err := Client.GetNotifications(context.Background(), pg) @@ -408,9 +411,14 @@ func main() { continue } timestring := string(timeb) - label := widget.NewLabel(html2text.HTML2Text(v.Status.Content)) + var label *widget.Label + if v.Status != nil { + label = widget.NewLabel(html2text.HTML2Text(v.Status.Content)) + } else { + label = widget.NewLabel("No content set") + } label.Truncation = fyne.TextTruncateEllipsis - avatar_uri := v.Account.AvatarStatic + avatar_uri := v.Account.Avatar u, err := storage.ParseURI(avatar_uri) if err != nil { continue @@ -419,13 +427,18 @@ func main() { im := canvas.NewImageFromURI(u) im.FillMode = canvas.ImageFillContain - Timeline.Add(im) + fyne.Do(func(){Timeline.Add(im) Timeline.Add(widget.NewRichTextFromMarkdown(fmt.Sprintf("%s %s your post", v.Account.Username, v.Type))) Timeline.Add(label) Timeline.Add(widget.NewLabel(timestring)) + }) } //Timeline = NewTimeline - }() + } + + go ShowNotifications() + + RefreshNotis := widget.NewButton("Refresh", ShowNotifications) MainWindow.SetContent(container.NewHSplit(container.NewVBox(TootEntry, ReplyBox, VisibilitySelector, widget.NewButton("Post", func() { toot := mastodon.Toot{ @@ -438,6 +451,6 @@ func main() { if err != nil { dialog.ShowError(err, MainWindow) } - })), container.NewVScroll(Timeline))) + }), RefreshNotis), container.NewVScroll(Timeline))) MainWindow.ShowAndRun() }