1
0
Fork 0

Fix #134: Paginate notifications. (#136)

This commit is contained in:
Nicolas Perriault 2017-05-05 23:35:54 +02:00 committed by GitHub
parent 102210aebb
commit 56ade98158
7 changed files with 86 additions and 71 deletions

View File

@ -121,15 +121,14 @@ saveRegistration registration =
|> Ports.saveRegistration
loadNotifications : Maybe Client -> Cmd Msg
loadNotifications client =
-- TODO: handle link (see loadUserTimeline)
loadNotifications : Maybe Client -> Maybe String -> Cmd Msg
loadNotifications client url =
case client of
Just client ->
HttpBuilder.get ApiUrl.notifications
HttpBuilder.get (Maybe.withDefault ApiUrl.notifications url)
|> withClient client
|> withBodyDecoder (Decode.list notificationDecoder)
|> send (MastodonEvent << Notifications)
|> send (MastodonEvent << Notifications (url /= Nothing))
Nothing ->
Cmd.none
@ -312,26 +311,29 @@ loadTimelines client =
[ loadUserTimeline client Nothing
, loadLocalTimeline client Nothing
, loadGlobalTimeline client Nothing
, loadNotifications client
, loadNotifications client Nothing
]
loadNextTimeline : Maybe Client -> CurrentView -> Timeline -> Cmd Msg
loadNextTimeline client currentView { id, links } =
loadNextTimeline : Maybe Client -> CurrentView -> String -> String -> Cmd Msg
loadNextTimeline client currentView id next =
case id of
"notifications" ->
loadNotifications client (Just next)
"home-timeline" ->
loadUserTimeline client links.next
loadUserTimeline client (Just next)
"local-timeline" ->
loadLocalTimeline client links.next
loadLocalTimeline client (Just next)
"global-timeline" ->
loadGlobalTimeline client links.next
loadGlobalTimeline client (Just next)
"account-timeline" ->
case currentView of
AccountView account ->
loadAccountTimeline client account.id links.next
loadAccountTimeline client account.id (Just next)
_ ->
Cmd.none

View File

@ -64,7 +64,7 @@ init flags location =
, accountFollowing = []
, accountRelationships = []
, accountRelationship = Nothing
, notifications = []
, notifications = emptyTimeline "notifications"
, draft = defaultDraft
, errors = []
, location = location
@ -77,10 +77,10 @@ init flags location =
! [ Command.initCommands flags.registration flags.client authCode ]
emptyTimeline : String -> Timeline
emptyTimeline : String -> Timeline a
emptyTimeline id =
{ id = id
, statuses = []
, entries = []
, links = Links Nothing Nothing
}
@ -135,7 +135,7 @@ updateTimelinesWithBoolFlag statusId flag statusUpdater model =
status
updateTimeline timeline =
{ timeline | statuses = List.map update timeline.statuses }
{ timeline | entries = List.map update timeline.entries }
in
{ model
| userTimeline = updateTimeline model.userTimeline
@ -198,7 +198,7 @@ processReblog statusId flag model =
model
deleteStatusFromTimeline : Int -> Timeline -> Timeline
deleteStatusFromTimeline : Int -> Timeline Status -> Timeline Status
deleteStatusFromTimeline statusId timeline =
let
update status =
@ -207,7 +207,7 @@ deleteStatusFromTimeline statusId timeline =
&& (Mastodon.Helper.extractReblog status).id
/= statusId
in
{ timeline | statuses = List.filter update timeline.statuses }
{ timeline | entries = List.filter update timeline.entries }
deleteStatusFromAllTimelines : Int -> Model -> Model
@ -218,12 +218,13 @@ deleteStatusFromAllTimelines id model =
, localTimeline = deleteStatusFromTimeline id model.localTimeline
, globalTimeline = deleteStatusFromTimeline id model.globalTimeline
, accountTimeline = deleteStatusFromTimeline id model.accountTimeline
, currentView = deleteStatusFromThread id model
, currentView = deleteStatusFromCurrentView id model
}
deleteStatusFromThread : Int -> Model -> CurrentView
deleteStatusFromThread id model =
deleteStatusFromCurrentView : Int -> Model -> CurrentView
deleteStatusFromCurrentView id model =
-- TODO: delete from current account view
case model.currentView of
ThreadView thread ->
if thread.status.id == id then
@ -480,21 +481,21 @@ updateViewer viewerMsg viewer =
(Just <| Viewer attachments attachment) ! []
updateTimeline : Bool -> List Status -> Links -> Timeline -> Timeline
updateTimeline append statuses links timeline =
updateTimeline : Bool -> List a -> Links -> Timeline a -> Timeline a
updateTimeline append entries links timeline =
let
newStatuses =
newEntries =
if append then
List.concat [ timeline.statuses, statuses ]
List.concat [ timeline.entries, entries ]
else
statuses
entries
in
{ timeline | statuses = newStatuses, links = links }
{ timeline | entries = newEntries, links = links }
prependStatusToTimeline : Status -> Timeline -> Timeline
prependStatusToTimeline status timeline =
{ timeline | statuses = status :: timeline.statuses }
prependToTimeline : a -> Timeline a -> Timeline a
prependToTimeline entry timeline =
{ timeline | entries = entry :: timeline.entries }
processMastodonEvent : MastodonMsg -> Model -> ( Model, Cmd Msg )
@ -568,7 +569,7 @@ processMastodonEvent msg model =
FavoriteAdded result ->
case result of
Ok _ ->
model ! [ Command.loadNotifications model.client ]
model ! []
Err error ->
{ model | errors = (errorText error) :: model.errors } ! []
@ -576,7 +577,7 @@ processMastodonEvent msg model =
FavoriteRemoved result ->
case result of
Ok _ ->
model ! [ Command.loadNotifications model.client ]
model ! []
Err error ->
{ model | errors = (errorText error) :: model.errors } ! []
@ -589,11 +590,14 @@ processMastodonEvent msg model =
Err error ->
{ model | errors = (errorText error) :: model.errors } ! []
Notifications result ->
Notifications append result ->
case result of
Ok { decoded } ->
-- TODO: store next link
{ model | notifications = Mastodon.Helper.aggregateNotifications decoded } ! []
Ok { decoded, links } ->
let
aggregated =
Mastodon.Helper.aggregateNotifications decoded
in
{ model | notifications = updateTimeline append aggregated links model.notifications } ! []
Err error ->
{ model | errors = (errorText error) :: model.errors } ! []
@ -609,7 +613,7 @@ processMastodonEvent msg model =
Reblogged result ->
case result of
Ok _ ->
model ! [ Command.loadNotifications model.client ]
model ! []
Err error ->
{ model | errors = (errorText error) :: model.errors } ! []
@ -631,7 +635,7 @@ processMastodonEvent msg model =
Unreblogged result ->
case result of
Ok _ ->
model ! [ Command.loadNotifications model.client ]
model ! []
Err error ->
{ model | errors = (errorText error) :: model.errors } ! []
@ -764,7 +768,7 @@ processWebSocketMsg msg model =
Mastodon.WebSocket.StatusUpdateEvent result ->
case result of
Ok status ->
{ model | userTimeline = prependStatusToTimeline status model.userTimeline } ! []
{ model | userTimeline = prependToTimeline status model.userTimeline } ! []
Err error ->
{ model | errors = error :: model.errors } ! []
@ -781,12 +785,18 @@ processWebSocketMsg msg model =
case result of
Ok notification ->
let
notifications =
Mastodon.Helper.addNotificationToAggregates
notification
model.notifications
oldNotifications =
model.notifications
newNotifications =
{ oldNotifications
| entries =
Mastodon.Helper.addNotificationToAggregates
notification
oldNotifications.entries
}
in
{ model | notifications = notifications } ! []
{ model | notifications = newNotifications } ! []
Err error ->
{ model | errors = error :: model.errors } ! []
@ -799,7 +809,7 @@ processWebSocketMsg msg model =
Mastodon.WebSocket.StatusUpdateEvent result ->
case result of
Ok status ->
{ model | localTimeline = prependStatusToTimeline status model.localTimeline } ! []
{ model | localTimeline = prependToTimeline status model.localTimeline } ! []
Err error ->
{ model | errors = error :: model.errors } ! []
@ -823,7 +833,7 @@ processWebSocketMsg msg model =
Mastodon.WebSocket.StatusUpdateEvent result ->
case result of
Ok status ->
{ model | globalTimeline = prependStatusToTimeline status model.globalTimeline } ! []
{ model | globalTimeline = prependToTimeline status model.globalTimeline } ! []
Err error ->
{ model | errors = error :: model.errors } ! []
@ -924,8 +934,8 @@ update msg model =
}
! [ Command.loadAccount model.client accountId ]
LoadNext timeline ->
model ! [ Command.loadNextTimeline model.client model.currentView timeline ]
TimelineLoadNext id next ->
model ! [ Command.loadNextTimeline model.client model.currentView id next ]
ViewAccountFollowers account ->
{ model | currentView = AccountFollowersView account model.accountFollowers }

View File

@ -52,7 +52,7 @@ type MastodonMsg
| FavoriteRemoved (MastodonResult Status)
| GlobalTimeline Bool (MastodonResult (List Status))
| LocalTimeline Bool (MastodonResult (List Status))
| Notifications (MastodonResult (List Notification))
| Notifications Bool (MastodonResult (List Notification))
| Reblogged (MastodonResult Status)
| StatusDeleted (MastodonResult Int)
| StatusPosted (MastodonResult Status)
@ -75,7 +75,7 @@ type Msg
| FilterNotifications NotificationFilter
| FollowAccount Int
| LoadAccount Int
| LoadNext Timeline
| TimelineLoadNext String String
| MastodonEvent MastodonMsg
| NoOp
| OpenThread Status
@ -150,9 +150,9 @@ type alias Viewer =
}
type alias Timeline =
type alias Timeline a =
{ id : String
, statuses : List Status
, entries : List a
, links : Links
}
@ -161,15 +161,15 @@ type alias Model =
{ server : String
, registration : Maybe AppRegistration
, client : Maybe Client
, userTimeline : Timeline
, localTimeline : Timeline
, globalTimeline : Timeline
, accountTimeline : Timeline
, userTimeline : Timeline Status
, localTimeline : Timeline Status
, globalTimeline : Timeline Status
, accountTimeline : Timeline Status
, accountFollowers : List Account
, accountFollowing : List Account
, accountRelationships : List Relationship
, accountRelationship : Maybe Relationship
, notifications : List NotificationAggregate
, notifications : Timeline NotificationAggregate
, draft : Draft
, errors : List String
, location : Navigation.Location

View File

@ -122,7 +122,7 @@ accountFollowView currentUser accounts relationships relationship account =
List.map keyedEntry accounts
accountTimelineView : CurrentUser -> Timeline -> CurrentUserRelation -> Account -> Html Msg
accountTimelineView : CurrentUser -> Timeline Status -> CurrentUserRelation -> Account -> Html Msg
accountTimelineView currentUser timeline relationship account =
let
keyedEntry status =
@ -131,7 +131,7 @@ accountTimelineView currentUser timeline relationship account =
)
entries =
List.map keyedEntry timeline.statuses
List.map keyedEntry timeline.entries
in
accountView currentUser account relationship <|
Keyed.ul [ id timeline.id, class "list-group" ] <|

View File

@ -27,14 +27,14 @@ type alias CurrentUserRelation =
Maybe Relationship
timelineView : ( String, String, CurrentUser, Timeline ) -> Html Msg
timelineView : ( String, String, CurrentUser, Timeline Status ) -> Html Msg
timelineView ( label, iconName, currentUser, timeline ) =
let
keyedEntry status =
( toString id, statusEntryView timeline.id "" currentUser status )
entries =
List.map keyedEntry timeline.statuses
List.map keyedEntry timeline.entries
in
div [ class "col-md-3 column" ]
[ div [ class "panel panel-default" ]
@ -47,7 +47,7 @@ timelineView ( label, iconName, currentUser, timeline ) =
]
userTimelineView : CurrentUser -> Timeline -> Html Msg
userTimelineView : CurrentUser -> Timeline Status -> Html Msg
userTimelineView currentUser timeline =
Lazy.lazy timelineView
( "Home timeline"
@ -57,7 +57,7 @@ userTimelineView currentUser timeline =
)
localTimelineView : CurrentUser -> Timeline -> Html Msg
localTimelineView : CurrentUser -> Timeline Status -> Html Msg
localTimelineView currentUser timeline =
Lazy.lazy timelineView
( "Local timeline"
@ -67,7 +67,7 @@ localTimelineView currentUser timeline =
)
globalTimelineView : CurrentUser -> Timeline -> Html Msg
globalTimelineView : CurrentUser -> Timeline Status -> Html Msg
globalTimelineView currentUser timeline =
Lazy.lazy timelineView
( "Global timeline"

View File

@ -10,6 +10,7 @@ module View.Common
import Html exposing (..)
import Html.Attributes exposing (..)
import Mastodon.Http exposing (Links)
import Mastodon.Model exposing (..)
import Types exposing (..)
import View.Events exposing (..)
@ -81,14 +82,14 @@ justifiedButtonGroup cls buttons =
List.map (\b -> div [ class "btn-group" ] [ b ]) buttons
loadMoreBtn : Timeline -> Html Msg
loadMoreBtn : { timeline | id : String, links : Links } -> Html Msg
loadMoreBtn timeline =
case timeline.links.next of
Just next ->
li [ class "list-group-item load-more text-center" ]
[ a
[ href next
, onClickWithPreventAndStop <| LoadNext timeline
, onClickWithPreventAndStop <| TimelineLoadNext timeline.id next
]
[ text "Load more" ]
]

View File

@ -130,13 +130,18 @@ notificationFilterView filter =
]
notificationListView : CurrentUser -> NotificationFilter -> List NotificationAggregate -> Html Msg
notificationListView : CurrentUser -> NotificationFilter -> Timeline NotificationAggregate -> Html Msg
notificationListView currentUser filter notifications =
let
keyedEntry notification =
( toString notification.id
, Lazy.lazy2 notificationEntryView currentUser notification
)
entries =
notifications.entries
|> filterNotifications filter
|> List.map keyedEntry
in
div [ class "col-md-3 column" ]
[ div [ class "panel panel-default notifications-panel" ]
@ -145,9 +150,6 @@ notificationListView currentUser filter notifications =
[ div [ class "panel-heading" ] [ Common.icon "bell", text "Notifications" ] ]
, notificationFilterView filter
, Keyed.ul [ id "notifications", class "list-group timeline" ] <|
(notifications
|> filterNotifications filter
|> List.map keyedEntry
)
(entries ++ [ ( "load-more", Common.loadMoreBtn notifications ) ])
]
]