diff --git a/src/Command.elm b/src/Command.elm index c2485ff..fa1e600 100644 --- a/src/Command.elm +++ b/src/Command.elm @@ -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 diff --git a/src/Model.elm b/src/Model.elm index 496095a..90874ef 100644 --- a/src/Model.elm +++ b/src/Model.elm @@ -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 } diff --git a/src/Types.elm b/src/Types.elm index 8d5aff3..5639a19 100644 --- a/src/Types.elm +++ b/src/Types.elm @@ -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 diff --git a/src/View/Account.elm b/src/View/Account.elm index f4ae7c4..4e11f4a 100644 --- a/src/View/Account.elm +++ b/src/View/Account.elm @@ -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" ] <| diff --git a/src/View/App.elm b/src/View/App.elm index c781257..f379f81 100644 --- a/src/View/App.elm +++ b/src/View/App.elm @@ -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" diff --git a/src/View/Common.elm b/src/View/Common.elm index 3a07d59..7d908ff 100644 --- a/src/View/Common.elm +++ b/src/View/Common.elm @@ -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" ] ] diff --git a/src/View/Notification.elm b/src/View/Notification.elm index b4b2f09..ea526c3 100644 --- a/src/View/Notification.elm +++ b/src/View/Notification.elm @@ -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 ) ]) ] ]