1
0
Fork 0

Add websocket for local and global timeline (#66)

* Connect to the websocket API

* Enable user timeline update through websockets

* Update elm-html-parser to latest

* Listem to local and global timelines

* Subscribe to global timeline only if it's displayed

* Some review changes

* Add elm-test and test notification aggregates

* Add new follow notification

* Fex addNotificationToAggregates

* Add test

* Clarify logic

* Update local and global timelines using WS

I've renamed the "public" timeline to "global", and removed the HTTP
reload of the user timeline when posting a Toot. We only rely on
websockets now.
This commit is contained in:
Vincent Jousse 2017-04-25 23:33:37 +02:00 committed by GitHub
parent c72a9281df
commit 00ffcecf1d
3 changed files with 45 additions and 22 deletions

View File

@ -30,7 +30,7 @@ module Mastodon
, fetchAccount , fetchAccount
, fetchLocalTimeline , fetchLocalTimeline
, fetchNotifications , fetchNotifications
, fetchPublicTimeline , fetchGlobalTimeline
, fetchUserTimeline , fetchUserTimeline
, postStatus , postStatus
, send , send
@ -662,8 +662,8 @@ fetchLocalTimeline client =
fetch client "/api/v1/timelines/public?local=true" <| Decode.list statusDecoder fetch client "/api/v1/timelines/public?local=true" <| Decode.list statusDecoder
fetchPublicTimeline : Client -> Request (List Status) fetchGlobalTimeline : Client -> Request (List Status)
fetchPublicTimeline client = fetchGlobalTimeline client =
fetch client "/api/v1/timelines/public" <| Decode.list statusDecoder fetch client "/api/v1/timelines/public" <| Decode.list statusDecoder

View File

@ -37,7 +37,7 @@ type MastodonMsg
| FavoriteRemoved (Result Mastodon.Error Mastodon.Status) | FavoriteRemoved (Result Mastodon.Error Mastodon.Status)
| LocalTimeline (Result Mastodon.Error (List Mastodon.Status)) | LocalTimeline (Result Mastodon.Error (List Mastodon.Status))
| Notifications (Result Mastodon.Error (List Mastodon.Notification)) | Notifications (Result Mastodon.Error (List Mastodon.Notification))
| PublicTimeline (Result Mastodon.Error (List Mastodon.Status)) | GlobalTimeline (Result Mastodon.Error (List Mastodon.Status))
| Reblogged (Result Mastodon.Error Mastodon.Status) | Reblogged (Result Mastodon.Error Mastodon.Status)
| StatusPosted (Result Mastodon.Error Mastodon.Status) | StatusPosted (Result Mastodon.Error Mastodon.Status)
| Unreblogged (Result Mastodon.Error Mastodon.Status) | Unreblogged (Result Mastodon.Error Mastodon.Status)
@ -92,7 +92,7 @@ type alias Model =
, client : Maybe Mastodon.Client , client : Maybe Mastodon.Client
, userTimeline : List Mastodon.Status , userTimeline : List Mastodon.Status
, localTimeline : List Mastodon.Status , localTimeline : List Mastodon.Status
, publicTimeline : List Mastodon.Status , globalTimeline : List Mastodon.Status
, notifications : List Mastodon.NotificationAggregate , notifications : List Mastodon.NotificationAggregate
, draft : Draft , draft : Draft
, account : Maybe Mastodon.Account , account : Maybe Mastodon.Account
@ -134,7 +134,7 @@ init flags location =
, client = flags.client , client = flags.client
, userTimeline = [] , userTimeline = []
, localTimeline = [] , localTimeline = []
, publicTimeline = [] , globalTimeline = []
, notifications = [] , notifications = []
, draft = defaultDraft , draft = defaultDraft
, account = Nothing , account = Nothing
@ -217,7 +217,7 @@ loadTimelines client =
Cmd.batch Cmd.batch
[ Mastodon.fetchUserTimeline client |> Mastodon.send (MastodonEvent << UserTimeline) [ Mastodon.fetchUserTimeline client |> Mastodon.send (MastodonEvent << UserTimeline)
, Mastodon.fetchLocalTimeline client |> Mastodon.send (MastodonEvent << LocalTimeline) , Mastodon.fetchLocalTimeline client |> Mastodon.send (MastodonEvent << LocalTimeline)
, Mastodon.fetchPublicTimeline client |> Mastodon.send (MastodonEvent << PublicTimeline) , Mastodon.fetchGlobalTimeline client |> Mastodon.send (MastodonEvent << GlobalTimeline)
, loadNotifications <| Just client , loadNotifications <| Just client
] ]
@ -275,7 +275,7 @@ updateTimelinesWithBoolFlag statusId flag statusUpdater model =
{ model { model
| userTimeline = List.map (update flag) model.userTimeline | userTimeline = List.map (update flag) model.userTimeline
, localTimeline = List.map (update flag) model.localTimeline , localTimeline = List.map (update flag) model.localTimeline
, publicTimeline = List.map (update flag) model.publicTimeline , globalTimeline = List.map (update flag) model.globalTimeline
} }
@ -417,13 +417,13 @@ processMastodonEvent msg model =
Err error -> Err error ->
{ model | notifications = [], errors = (errorText error) :: model.errors } ! [] { model | notifications = [], errors = (errorText error) :: model.errors } ! []
PublicTimeline result -> GlobalTimeline result ->
case result of case result of
Ok publicTimeline -> Ok globalTimeline ->
{ model | publicTimeline = publicTimeline } ! [] { model | globalTimeline = globalTimeline } ! []
Err error -> Err error ->
{ model | publicTimeline = [], errors = (errorText error) :: model.errors } ! [] { model | globalTimeline = [], errors = (errorText error) :: model.errors } ! []
Reblogged result -> Reblogged result ->
case result of case result of
@ -434,7 +434,7 @@ processMastodonEvent msg model =
{ model | errors = (errorText error) :: model.errors } ! [] { model | errors = (errorText error) :: model.errors } ! []
StatusPosted _ -> StatusPosted _ ->
{ model | draft = defaultDraft } ! [ loadTimelines model.client ] { model | draft = defaultDraft } ! []
Unreblogged result -> Unreblogged result ->
case result of case result of
@ -601,12 +601,36 @@ update msg model =
{ model | errors = (logError "StatusResult" error message) :: model.errors } ! [] { model | errors = (logError "StatusResult" error message) :: model.errors } ! []
NewWebsocketLocalMessage message -> NewWebsocketLocalMessage message ->
-- @TODO case (Mastodon.decodeWebSocketMessage message) of
model ! [] Mastodon.EventError error ->
{ model | errors = error :: model.errors } ! []
Mastodon.StatusResult result ->
case result of
Ok status ->
{ model | localTimeline = status :: model.localTimeline } ! []
Err error ->
{ model | errors = error :: model.errors } ! []
_ ->
model ! []
NewWebsocketGlobalMessage message -> NewWebsocketGlobalMessage message ->
-- @TODO case (Mastodon.decodeWebSocketMessage message) of
model ! [] Mastodon.EventError error ->
{ model | errors = error :: model.errors } ! []
Mastodon.StatusResult result ->
case result of
Ok status ->
{ model | globalTimeline = status :: model.globalTimeline } ! []
Err error ->
{ model | errors = error :: model.errors } ! []
_ ->
model ! []
subscriptions : Model -> Sub Msg subscriptions : Model -> Sub Msg

View File

@ -153,10 +153,9 @@ statusView context ({ account, content, media_attachments, reblog, mentions } as
let let
accountLinkAttributes = accountLinkAttributes =
[ href account.url [ href account.url
-- When clicking on a status, we should not let the browser
-- When clicking on a status, we should not let the browser -- redirect to a new page. That's why we're preventing the default
-- redirect to a new page. That's why we're preventing the default -- behavior here
-- behavior here
, ViewHelper.onClickWithPreventAndStop (OnLoadUserAccount account.id) , ViewHelper.onClickWithPreventAndStop (OnLoadUserAccount account.id)
] ]
in in
@ -575,7 +574,7 @@ homepageView model =
Nothing -> Nothing ->
if model.useGlobalTimeline then if model.useGlobalTimeline then
timelineView "Global timeline" "globe" "global" model.publicTimeline timelineView "Global timeline" "globe" "global" model.globalTimeline
else else
timelineView "Local timeline" "th-large" "local" model.localTimeline timelineView "Local timeline" "th-large" "local" model.localTimeline
] ]