|
|
|
|
@ -180,113 +180,134 @@ func (f *Feed) singleThread(fn apiThreadFunc, status *mastodon.Status) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (f *Feed) normalNewer(fn apiFunc) { |
|
|
|
|
f.itemsMux.RLock() |
|
|
|
|
pg := mastodon.Pagination{} |
|
|
|
|
if len(f.items) > 0 { |
|
|
|
|
switch item := f.items[0].Raw().(type) { |
|
|
|
|
case *mastodon.Status: |
|
|
|
|
pg.MinID = item.ID |
|
|
|
|
case *api.NotificationData: |
|
|
|
|
pg.MinID = item.Item.ID |
|
|
|
|
} |
|
|
|
|
f.apiDataMux.Lock() |
|
|
|
|
if f.apiData.MinID != mastodon.ID("") { |
|
|
|
|
pg.MinID = f.apiData.MinID |
|
|
|
|
} |
|
|
|
|
f.itemsMux.RUnlock() |
|
|
|
|
items, err := fn(&pg) |
|
|
|
|
if err != nil { |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
f.itemsMux.Lock() |
|
|
|
|
if len(items) > 0 { |
|
|
|
|
switch item := items[0].Raw().(type) { |
|
|
|
|
case *mastodon.Status: |
|
|
|
|
f.apiData.MinID = item.ID |
|
|
|
|
case *api.NotificationData: |
|
|
|
|
f.apiData.MinID = item.Item.ID |
|
|
|
|
} |
|
|
|
|
if f.apiData.MaxID == mastodon.ID("") { |
|
|
|
|
switch item := items[len(items)-1].Raw().(type) { |
|
|
|
|
case *mastodon.Status: |
|
|
|
|
f.apiData.MaxID = item.ID |
|
|
|
|
case *api.NotificationData: |
|
|
|
|
f.apiData.MaxID = item.Item.ID |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
f.items = append(items, f.items...) |
|
|
|
|
f.Updated(DekstopNotificationNone) |
|
|
|
|
} |
|
|
|
|
f.itemsMux.Unlock() |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (f *Feed) normalOlder(fn apiFunc) { |
|
|
|
|
f.itemsMux.RLock() |
|
|
|
|
pg := mastodon.Pagination{} |
|
|
|
|
if len(f.items) > 0 { |
|
|
|
|
switch item := f.items[len(f.items)-1].Raw().(type) { |
|
|
|
|
case *mastodon.Status: |
|
|
|
|
pg.MaxID = item.ID |
|
|
|
|
case *api.NotificationData: |
|
|
|
|
pg.MaxID = item.Item.ID |
|
|
|
|
} |
|
|
|
|
f.apiDataMux.Lock() |
|
|
|
|
if f.apiData.MaxID == mastodon.ID("") { |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
f.loadNewer() |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
f.itemsMux.RUnlock() |
|
|
|
|
pg.MaxID = f.apiData.MaxID |
|
|
|
|
items, err := fn(&pg) |
|
|
|
|
if err != nil { |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
f.itemsMux.Lock() |
|
|
|
|
if len(items) > 0 { |
|
|
|
|
switch item := items[len(items)-1].Raw().(type) { |
|
|
|
|
case *mastodon.Status: |
|
|
|
|
f.apiData.MaxID = item.ID |
|
|
|
|
case *api.NotificationData: |
|
|
|
|
f.apiData.MaxID = item.Item.ID |
|
|
|
|
} |
|
|
|
|
f.items = append(f.items, items...) |
|
|
|
|
f.Updated(DekstopNotificationNone) |
|
|
|
|
} |
|
|
|
|
f.itemsMux.Unlock() |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (f *Feed) newerSearchPG(fn apiSearchPGFunc, search string) { |
|
|
|
|
f.itemsMux.RLock() |
|
|
|
|
pg := mastodon.Pagination{} |
|
|
|
|
if len(f.items) > 0 { |
|
|
|
|
switch item := f.items[0].Raw().(type) { |
|
|
|
|
case *mastodon.Status: |
|
|
|
|
pg.MinID = item.ID |
|
|
|
|
} |
|
|
|
|
f.apiDataMux.Lock() |
|
|
|
|
if f.apiData.MinID != mastodon.ID("") { |
|
|
|
|
pg.MinID = f.apiData.MinID |
|
|
|
|
} |
|
|
|
|
f.itemsMux.RUnlock() |
|
|
|
|
items, err := fn(&pg, search) |
|
|
|
|
if err != nil { |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
f.itemsMux.Lock() |
|
|
|
|
if len(items) > 0 { |
|
|
|
|
item := items[0].Raw().(*mastodon.Status) |
|
|
|
|
f.apiData.MinID = item.ID |
|
|
|
|
f.items = append(items, f.items...) |
|
|
|
|
f.Updated(DekstopNotificationNone) |
|
|
|
|
if f.apiData.MaxID == mastodon.ID("") { |
|
|
|
|
item = items[len(items)-1].Raw().(*mastodon.Status) |
|
|
|
|
f.apiData.MaxID = item.ID |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
f.itemsMux.Unlock() |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (f *Feed) olderSearchPG(fn apiSearchPGFunc, search string) { |
|
|
|
|
f.itemsMux.RLock() |
|
|
|
|
pg := mastodon.Pagination{} |
|
|
|
|
if len(f.items) > 0 { |
|
|
|
|
switch item := f.items[len(f.items)-1].Raw().(type) { |
|
|
|
|
case *mastodon.Status: |
|
|
|
|
pg.MaxID = item.ID |
|
|
|
|
} |
|
|
|
|
f.apiDataMux.Lock() |
|
|
|
|
if f.apiData.MaxID == mastodon.ID("") { |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
f.loadNewer() |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
f.itemsMux.RUnlock() |
|
|
|
|
pg.MaxID = f.apiData.MaxID |
|
|
|
|
items, err := fn(&pg, search) |
|
|
|
|
if err != nil { |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
f.itemsMux.Lock() |
|
|
|
|
if len(items) > 0 { |
|
|
|
|
item := items[len(items)-1].Raw().(*mastodon.Status) |
|
|
|
|
f.apiData.MaxID = item.ID |
|
|
|
|
f.items = append(f.items, items...) |
|
|
|
|
f.Updated(DekstopNotificationNone) |
|
|
|
|
} |
|
|
|
|
f.itemsMux.Unlock() |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (f *Feed) normalNewerUser(fn apiIDFunc, id mastodon.ID) { |
|
|
|
|
f.itemsMux.RLock() |
|
|
|
|
pg := mastodon.Pagination{} |
|
|
|
|
if len(f.items) > 1 { |
|
|
|
|
switch item := f.items[1].Raw().(type) { |
|
|
|
|
case *mastodon.Status: |
|
|
|
|
pg.MinID = item.ID |
|
|
|
|
} |
|
|
|
|
f.apiDataMux.Lock() |
|
|
|
|
if f.apiData.MinID != mastodon.ID("") { |
|
|
|
|
pg.MinID = f.apiData.MinID |
|
|
|
|
} |
|
|
|
|
f.itemsMux.RUnlock() |
|
|
|
|
items, err := fn(&pg, id) |
|
|
|
|
if err != nil { |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
f.itemsMux.Lock() |
|
|
|
|
if len(items) > 0 { |
|
|
|
|
item := items[0].Raw().(*mastodon.Status) |
|
|
|
|
f.apiData.MinID = item.ID |
|
|
|
|
newItems := []api.Item{f.items[0]} |
|
|
|
|
newItems = append(newItems, items...) |
|
|
|
|
if len(f.items) > 1 { |
|
|
|
|
@ -294,74 +315,89 @@ func (f *Feed) normalNewerUser(fn apiIDFunc, id mastodon.ID) {
|
|
|
|
|
} |
|
|
|
|
f.items = newItems |
|
|
|
|
f.Updated(DekstopNotificationNone) |
|
|
|
|
if f.apiData.MaxID == mastodon.ID("") { |
|
|
|
|
item = items[len(items)-1].Raw().(*mastodon.Status) |
|
|
|
|
f.apiData.MaxID = item.ID |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
f.itemsMux.Unlock() |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (f *Feed) normalOlderUser(fn apiIDFunc, id mastodon.ID) { |
|
|
|
|
f.itemsMux.RLock() |
|
|
|
|
pg := mastodon.Pagination{} |
|
|
|
|
if len(f.items) > 1 { |
|
|
|
|
switch item := f.items[len(f.items)-1].Raw().(type) { |
|
|
|
|
case *mastodon.Status: |
|
|
|
|
pg.MaxID = item.ID |
|
|
|
|
} |
|
|
|
|
f.apiDataMux.Lock() |
|
|
|
|
if f.apiData.MaxID == mastodon.ID("") { |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
f.loadNewer() |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
f.itemsMux.RUnlock() |
|
|
|
|
pg.MaxID = f.apiData.MaxID |
|
|
|
|
items, err := fn(&pg, id) |
|
|
|
|
if err != nil { |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
f.itemsMux.Lock() |
|
|
|
|
if len(items) > 0 { |
|
|
|
|
item := items[len(items)-1].Raw().(*mastodon.Status) |
|
|
|
|
f.apiData.MaxID = item.ID |
|
|
|
|
f.items = append(f.items, items...) |
|
|
|
|
f.Updated(DekstopNotificationNone) |
|
|
|
|
} |
|
|
|
|
f.itemsMux.Unlock() |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (f *Feed) normalNewerID(fn apiIDFunc, id mastodon.ID) { |
|
|
|
|
f.itemsMux.RLock() |
|
|
|
|
pg := mastodon.Pagination{} |
|
|
|
|
if len(f.items) > 0 { |
|
|
|
|
switch item := f.items[0].Raw().(type) { |
|
|
|
|
case *mastodon.Status: |
|
|
|
|
pg.MinID = item.ID |
|
|
|
|
} |
|
|
|
|
f.apiDataMux.Lock() |
|
|
|
|
if f.apiData.MinID != mastodon.ID("") { |
|
|
|
|
pg.MinID = f.apiData.MinID |
|
|
|
|
} |
|
|
|
|
f.itemsMux.RUnlock() |
|
|
|
|
items, err := fn(&pg, id) |
|
|
|
|
if err != nil { |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
f.itemsMux.Lock() |
|
|
|
|
if len(items) > 0 { |
|
|
|
|
item := items[0].Raw().(*mastodon.Status) |
|
|
|
|
f.apiData.MinID = item.ID |
|
|
|
|
f.items = append(items, f.items...) |
|
|
|
|
f.Updated(DekstopNotificationNone) |
|
|
|
|
if f.apiData.MaxID == mastodon.ID("") { |
|
|
|
|
item = items[len(items)-1].Raw().(*mastodon.Status) |
|
|
|
|
f.apiData.MaxID = item.ID |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
f.itemsMux.Unlock() |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (f *Feed) normalOlderID(fn apiIDFunc, id mastodon.ID) { |
|
|
|
|
f.itemsMux.RLock() |
|
|
|
|
pg := mastodon.Pagination{} |
|
|
|
|
if len(f.items) > 0 { |
|
|
|
|
switch item := f.items[len(f.items)-1].Raw().(type) { |
|
|
|
|
case *mastodon.Status: |
|
|
|
|
pg.MaxID = item.ID |
|
|
|
|
} |
|
|
|
|
f.apiDataMux.Lock() |
|
|
|
|
if f.apiData.MaxID == mastodon.ID("") { |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
f.loadNewer() |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
f.itemsMux.RUnlock() |
|
|
|
|
pg.MaxID = f.apiData.MaxID |
|
|
|
|
items, err := fn(&pg, id) |
|
|
|
|
if err != nil { |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
f.itemsMux.Lock() |
|
|
|
|
if len(items) > 0 { |
|
|
|
|
item := items[len(items)-1].Raw().(*mastodon.Status) |
|
|
|
|
f.apiData.MaxID = item.ID |
|
|
|
|
f.items = append(f.items, items...) |
|
|
|
|
f.Updated(DekstopNotificationNone) |
|
|
|
|
} |
|
|
|
|
f.itemsMux.Unlock() |
|
|
|
|
f.apiDataMux.Unlock() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (f *Feed) normalEmpty(fn apiEmptyFunc) { |
|
|
|
|
@ -479,7 +515,7 @@ func (f *Feed) linkOlderID(fn apiIDFunc, id mastodon.ID) {
|
|
|
|
|
f.itemsMux.Unlock() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (f *Feed) startStream(rec *api.Receiver, err error) { |
|
|
|
|
func (f *Feed) startStream(rec *api.Receiver, timeline string, err error) { |
|
|
|
|
if err != nil { |
|
|
|
|
log.Fatalln("Couldn't open stream") |
|
|
|
|
} |
|
|
|
|
@ -488,17 +524,19 @@ func (f *Feed) startStream(rec *api.Receiver, err error) {
|
|
|
|
|
for e := range f.stream.Ch { |
|
|
|
|
switch t := e.(type) { |
|
|
|
|
case *mastodon.UpdateEvent: |
|
|
|
|
s := api.NewStatusItem(t.Status) |
|
|
|
|
f.itemsMux.Lock() |
|
|
|
|
f.items = append([]api.Item{s}, f.items...) |
|
|
|
|
f.Updated(DesktopNotificationPost) |
|
|
|
|
f.itemsMux.Unlock() |
|
|
|
|
s, filtered := api.NewStatusItem(t.Status, f.accountClient.Filters, timeline) |
|
|
|
|
if !filtered { |
|
|
|
|
f.itemsMux.Lock() |
|
|
|
|
f.items = append([]api.Item{s}, f.items...) |
|
|
|
|
f.Updated(DesktopNotificationPost) |
|
|
|
|
f.itemsMux.Unlock() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (f *Feed) startStreamNotification(rec *api.Receiver, err error) { |
|
|
|
|
func (f *Feed) startStreamNotification(rec *api.Receiver, timeline string, err error) { |
|
|
|
|
if err != nil { |
|
|
|
|
log.Fatalln("Couldn't open stream") |
|
|
|
|
} |
|
|
|
|
@ -515,30 +553,32 @@ func (f *Feed) startStreamNotification(rec *api.Receiver, err error) {
|
|
|
|
|
log.Fatalln(t.Notification.Account.Acct) |
|
|
|
|
continue |
|
|
|
|
} |
|
|
|
|
s := api.NewNotificationItem(t.Notification, |
|
|
|
|
s, filtered := api.NewNotificationItem(t.Notification, |
|
|
|
|
&api.User{ |
|
|
|
|
Data: &t.Notification.Account, |
|
|
|
|
Relation: rel[0], |
|
|
|
|
}) |
|
|
|
|
f.itemsMux.Lock() |
|
|
|
|
f.items = append([]api.Item{s}, f.items...) |
|
|
|
|
nft := DekstopNotificationNone |
|
|
|
|
switch t.Notification.Type { |
|
|
|
|
case "follow", "follow_request": |
|
|
|
|
nft = DesktopNotificationFollower |
|
|
|
|
case "favourite": |
|
|
|
|
nft = DesktopNotificationFollower |
|
|
|
|
case "reblog": |
|
|
|
|
nft = DesktopNotificationBoost |
|
|
|
|
case "mention": |
|
|
|
|
nft = DesktopNotificationMention |
|
|
|
|
case "status": |
|
|
|
|
nft = DesktopNotificationPost |
|
|
|
|
case "poll": |
|
|
|
|
nft = DesktopNotificationPoll |
|
|
|
|
}, f.accountClient.Filters) |
|
|
|
|
if !filtered { |
|
|
|
|
f.itemsMux.Lock() |
|
|
|
|
f.items = append([]api.Item{s}, f.items...) |
|
|
|
|
nft := DekstopNotificationNone |
|
|
|
|
switch t.Notification.Type { |
|
|
|
|
case "follow", "follow_request": |
|
|
|
|
nft = DesktopNotificationFollower |
|
|
|
|
case "favourite": |
|
|
|
|
nft = DesktopNotificationFollower |
|
|
|
|
case "reblog": |
|
|
|
|
nft = DesktopNotificationBoost |
|
|
|
|
case "mention": |
|
|
|
|
nft = DesktopNotificationMention |
|
|
|
|
case "status": |
|
|
|
|
nft = DesktopNotificationPost |
|
|
|
|
case "poll": |
|
|
|
|
nft = DesktopNotificationPoll |
|
|
|
|
} |
|
|
|
|
f.Updated(nft) |
|
|
|
|
f.itemsMux.Unlock() |
|
|
|
|
} |
|
|
|
|
f.Updated(nft) |
|
|
|
|
f.itemsMux.Unlock() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}() |
|
|
|
|
@ -599,7 +639,7 @@ func NewTimelineLocal(ac *api.AccountClient) *Feed {
|
|
|
|
|
feed.loadNewer = func() { feed.normalNewer(feed.accountClient.GetTimelineLocal) } |
|
|
|
|
feed.loadOlder = func() { feed.normalOlder(feed.accountClient.GetTimelineLocal) } |
|
|
|
|
feed.startStream(feed.accountClient.NewLocalStream()) |
|
|
|
|
feed.close = func() { feed.accountClient.RemoveFederatedReceiver(feed.stream) } |
|
|
|
|
feed.close = func() { feed.accountClient.RemoveLocalReceiver(feed.stream) } |
|
|
|
|
|
|
|
|
|
return feed |
|
|
|
|
} |
|
|
|
|
@ -619,7 +659,7 @@ func NewConversations(ac *api.AccountClient) *Feed {
|
|
|
|
|
feed.loadNewer = func() { feed.normalNewer(feed.accountClient.GetConversations) } |
|
|
|
|
feed.loadOlder = func() { feed.normalOlder(feed.accountClient.GetConversations) } |
|
|
|
|
feed.startStream(feed.accountClient.NewDirectStream()) |
|
|
|
|
feed.close = func() { feed.accountClient.RemoveFederatedReceiver(feed.stream) } |
|
|
|
|
feed.close = func() { feed.accountClient.RemoveConversationReceiver(feed.stream) } |
|
|
|
|
|
|
|
|
|
return feed |
|
|
|
|
} |
|
|
|
|
@ -763,8 +803,13 @@ func NewListList(ac *api.AccountClient) *Feed {
|
|
|
|
|
loadingNewer: &LoadingLock{}, |
|
|
|
|
loadingOlder: &LoadingLock{}, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
feed.loadNewer = func() { feed.normalEmpty(feed.accountClient.GetLists) } |
|
|
|
|
once := true |
|
|
|
|
feed.loadNewer = func() { |
|
|
|
|
if once { |
|
|
|
|
feed.normalEmpty(feed.accountClient.GetLists) |
|
|
|
|
} |
|
|
|
|
once = false |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return feed |
|
|
|
|
} |
|
|
|
|
|