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

View File

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

View File

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