Fix #168: List user favorites.
- Favorite timeline model and commands. - 4th column navigation bar. - Use of SetView for account selector. - Move timeline views to their own view module. - Handle favorite timeline updates. - Integrate contextual menu in account selector view.
This commit is contained in:
parent
8e187efc10
commit
4d8757ad7c
|
@ -46,6 +46,10 @@ body {
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.panel-default .panel-heading {
|
||||||
|
background-color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
.timeline {
|
.timeline {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
@ -54,6 +58,13 @@ body {
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#favorite-timeline,
|
||||||
|
#local-timeline,
|
||||||
|
#global-timeline {
|
||||||
|
max-height: calc(100vh - 102px);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
li.load-more {
|
li.load-more {
|
||||||
cursor: wait;
|
cursor: wait;
|
||||||
}
|
}
|
||||||
|
@ -119,7 +130,7 @@ li.load-more {
|
||||||
padding-top: 6px;
|
padding-top: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.notifications-panel .btn-group-justified .btn {
|
.panel .btn-group-justified .btn {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
|
|
|
@ -14,6 +14,7 @@ module Command
|
||||||
, loadLocalTimeline
|
, loadLocalTimeline
|
||||||
, loadGlobalTimeline
|
, loadGlobalTimeline
|
||||||
, loadAccountTimeline
|
, loadAccountTimeline
|
||||||
|
, loadFavoriteTimeline
|
||||||
, loadNextTimeline
|
, loadNextTimeline
|
||||||
, loadRelationships
|
, loadRelationships
|
||||||
, loadThread
|
, loadThread
|
||||||
|
@ -317,6 +318,20 @@ loadAccountTimeline client accountId url =
|
||||||
Cmd.none
|
Cmd.none
|
||||||
|
|
||||||
|
|
||||||
|
loadFavoriteTimeline : Maybe Client -> Maybe String -> Cmd Msg
|
||||||
|
loadFavoriteTimeline client url =
|
||||||
|
case client of
|
||||||
|
Just client ->
|
||||||
|
HttpBuilder.get (Maybe.withDefault ApiUrl.favouriteTimeline url)
|
||||||
|
|> withClient client
|
||||||
|
|> withBodyDecoder (Decode.list statusDecoder)
|
||||||
|
|> withQueryParams [ ( "limit", "60" ) ]
|
||||||
|
|> send (MastodonEvent << FavoriteTimeline (url /= Nothing))
|
||||||
|
|
||||||
|
Nothing ->
|
||||||
|
Cmd.none
|
||||||
|
|
||||||
|
|
||||||
loadTimelines : Maybe Client -> Cmd Msg
|
loadTimelines : Maybe Client -> Cmd Msg
|
||||||
loadTimelines client =
|
loadTimelines client =
|
||||||
Cmd.batch
|
Cmd.batch
|
||||||
|
@ -342,6 +357,9 @@ loadNextTimeline client currentView id next =
|
||||||
"global-timeline" ->
|
"global-timeline" ->
|
||||||
loadGlobalTimeline client (Just next)
|
loadGlobalTimeline client (Just next)
|
||||||
|
|
||||||
|
"favorite-timeline" ->
|
||||||
|
loadFavoriteTimeline client (Just next)
|
||||||
|
|
||||||
"account-timeline" ->
|
"account-timeline" ->
|
||||||
case currentView of
|
case currentView of
|
||||||
AccountView account ->
|
AccountView account ->
|
||||||
|
|
|
@ -17,6 +17,7 @@ init { registration, clients } location =
|
||||||
, homeTimeline = Update.Timeline.empty "home-timeline"
|
, homeTimeline = Update.Timeline.empty "home-timeline"
|
||||||
, localTimeline = Update.Timeline.empty "local-timeline"
|
, localTimeline = Update.Timeline.empty "local-timeline"
|
||||||
, globalTimeline = Update.Timeline.empty "global-timeline"
|
, globalTimeline = Update.Timeline.empty "global-timeline"
|
||||||
|
, favoriteTimeline = Update.Timeline.empty "favorite-timeline"
|
||||||
, accountTimeline = Update.Timeline.empty "account-timeline"
|
, accountTimeline = Update.Timeline.empty "account-timeline"
|
||||||
, accountFollowers = Update.Timeline.empty "account-followers"
|
, accountFollowers = Update.Timeline.empty "account-followers"
|
||||||
, accountFollowing = Update.Timeline.empty "account-following"
|
, accountFollowing = Update.Timeline.empty "account-following"
|
||||||
|
@ -26,7 +27,6 @@ init { registration, clients } location =
|
||||||
, draft = Update.Draft.empty
|
, draft = Update.Draft.empty
|
||||||
, errors = []
|
, errors = []
|
||||||
, location = location
|
, location = location
|
||||||
, useGlobalTimeline = False
|
|
||||||
, viewer = Nothing
|
, viewer = Nothing
|
||||||
, currentView = LocalTimelineView
|
, currentView = LocalTimelineView
|
||||||
, currentUser = Nothing
|
, currentUser = Nothing
|
||||||
|
|
|
@ -11,6 +11,7 @@ module Mastodon.ApiUrl
|
||||||
, status
|
, status
|
||||||
, homeTimeline
|
, homeTimeline
|
||||||
, publicTimeline
|
, publicTimeline
|
||||||
|
, favouriteTimeline
|
||||||
, notifications
|
, notifications
|
||||||
, relationships
|
, relationships
|
||||||
, statuses
|
, statuses
|
||||||
|
@ -107,6 +108,11 @@ accountTimeline id =
|
||||||
(account id) ++ "/statuses"
|
(account id) ++ "/statuses"
|
||||||
|
|
||||||
|
|
||||||
|
favouriteTimeline : String
|
||||||
|
favouriteTimeline =
|
||||||
|
apiPrefix ++ "/favourites"
|
||||||
|
|
||||||
|
|
||||||
notifications : String
|
notifications : String
|
||||||
notifications =
|
notifications =
|
||||||
apiPrefix ++ "/notifications"
|
apiPrefix ++ "/notifications"
|
||||||
|
|
|
@ -56,14 +56,15 @@ type MastodonMsg
|
||||||
| CurrentUser (MastodonResult Account)
|
| CurrentUser (MastodonResult Account)
|
||||||
| FavoriteAdded (MastodonResult Status)
|
| FavoriteAdded (MastodonResult Status)
|
||||||
| FavoriteRemoved (MastodonResult Status)
|
| FavoriteRemoved (MastodonResult Status)
|
||||||
|
| FavoriteTimeline Bool (MastodonResult (List Status))
|
||||||
| GlobalTimeline Bool (MastodonResult (List Status))
|
| GlobalTimeline Bool (MastodonResult (List Status))
|
||||||
|
| HomeTimeline Bool (MastodonResult (List Status))
|
||||||
| LocalTimeline Bool (MastodonResult (List Status))
|
| LocalTimeline Bool (MastodonResult (List Status))
|
||||||
| Notifications Bool (MastodonResult (List Notification))
|
| Notifications Bool (MastodonResult (List Notification))
|
||||||
| Reblogged (MastodonResult Status)
|
| Reblogged (MastodonResult Status)
|
||||||
| StatusDeleted (MastodonResult Int)
|
| StatusDeleted (MastodonResult Int)
|
||||||
| StatusPosted (MastodonResult Status)
|
| StatusPosted (MastodonResult Status)
|
||||||
| Unreblogged (MastodonResult Status)
|
| Unreblogged (MastodonResult Status)
|
||||||
| HomeTimeline Bool (MastodonResult (List Status))
|
|
||||||
|
|
||||||
|
|
||||||
type WebSocketMsg
|
type WebSocketMsg
|
||||||
|
@ -73,7 +74,7 @@ type WebSocketMsg
|
||||||
|
|
||||||
|
|
||||||
type Msg
|
type Msg
|
||||||
= AddFavorite Int
|
= AddFavorite Status
|
||||||
| AskConfirm String Msg Msg
|
| AskConfirm String Msg Msg
|
||||||
| ClearError Int
|
| ClearError Int
|
||||||
| CloseAccount
|
| CloseAccount
|
||||||
|
@ -91,19 +92,18 @@ type Msg
|
||||||
| MastodonEvent MastodonMsg
|
| MastodonEvent MastodonMsg
|
||||||
| NoOp
|
| NoOp
|
||||||
| OpenThread Status
|
| OpenThread Status
|
||||||
| OpenAccountSelector
|
| ReblogStatus Status
|
||||||
| ReblogStatus Int
|
|
||||||
| Register
|
| Register
|
||||||
| RemoveFavorite Int
|
| RemoveFavorite Status
|
||||||
| ScrollColumn ScrollDirection String
|
| ScrollColumn ScrollDirection String
|
||||||
| ServerChange String
|
| ServerChange String
|
||||||
|
| SetView CurrentView
|
||||||
| SubmitDraft
|
| SubmitDraft
|
||||||
| SwitchClient Client
|
| SwitchClient Client
|
||||||
| Tick Time
|
| Tick Time
|
||||||
| UnfollowAccount Int
|
| UnfollowAccount Int
|
||||||
| UrlChange Navigation.Location
|
| UrlChange Navigation.Location
|
||||||
| UseGlobalTimeline Bool
|
| UnreblogStatus Status
|
||||||
| UnreblogStatus Int
|
|
||||||
| ViewAccountFollowing Account
|
| ViewAccountFollowing Account
|
||||||
| ViewAccountFollowers Account
|
| ViewAccountFollowers Account
|
||||||
| ViewAccountStatuses Account
|
| ViewAccountStatuses Account
|
||||||
|
@ -124,6 +124,7 @@ type CurrentView
|
||||||
| AccountFollowingView Account (Timeline Account)
|
| AccountFollowingView Account (Timeline Account)
|
||||||
| AccountView Account
|
| AccountView Account
|
||||||
| AccountSelectorView
|
| AccountSelectorView
|
||||||
|
| FavoriteTimelineView
|
||||||
| GlobalTimelineView
|
| GlobalTimelineView
|
||||||
| LocalTimelineView
|
| LocalTimelineView
|
||||||
| ThreadView Thread
|
| ThreadView Thread
|
||||||
|
@ -198,6 +199,7 @@ type alias Model =
|
||||||
, homeTimeline : Timeline Status
|
, homeTimeline : Timeline Status
|
||||||
, localTimeline : Timeline Status
|
, localTimeline : Timeline Status
|
||||||
, globalTimeline : Timeline Status
|
, globalTimeline : Timeline Status
|
||||||
|
, favoriteTimeline : Timeline Status
|
||||||
, accountTimeline : Timeline Status
|
, accountTimeline : Timeline Status
|
||||||
, accountFollowers : Timeline Account
|
, accountFollowers : Timeline Account
|
||||||
, accountFollowing : Timeline Account
|
, accountFollowing : Timeline Account
|
||||||
|
@ -207,7 +209,6 @@ type alias Model =
|
||||||
, draft : Draft
|
, draft : Draft
|
||||||
, errors : List ErrorNotification
|
, errors : List ErrorNotification
|
||||||
, location : Navigation.Location
|
, location : Navigation.Location
|
||||||
, useGlobalTimeline : Bool
|
|
||||||
, viewer : Maybe Viewer
|
, viewer : Maybe Viewer
|
||||||
, currentUser : Maybe Account
|
, currentUser : Maybe Account
|
||||||
, currentView : CurrentView
|
, currentView : CurrentView
|
||||||
|
|
|
@ -54,6 +54,18 @@ update msg model =
|
||||||
Confirmed onConfirm ->
|
Confirmed onConfirm ->
|
||||||
update onConfirm { model | confirm = Nothing }
|
update onConfirm { model | confirm = Nothing }
|
||||||
|
|
||||||
|
SetView view ->
|
||||||
|
case view of
|
||||||
|
AccountSelectorView ->
|
||||||
|
{ model | currentView = view, server = "" } ! []
|
||||||
|
|
||||||
|
FavoriteTimelineView ->
|
||||||
|
{ model | currentView = view }
|
||||||
|
! [ Command.loadFavoriteTimeline (List.head model.clients) Nothing ]
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
{ model | currentView = view } ! []
|
||||||
|
|
||||||
SwitchClient client ->
|
SwitchClient client ->
|
||||||
let
|
let
|
||||||
newClients =
|
newClients =
|
||||||
|
@ -64,13 +76,14 @@ update msg model =
|
||||||
, homeTimeline = Update.Timeline.empty "home-timeline"
|
, homeTimeline = Update.Timeline.empty "home-timeline"
|
||||||
, localTimeline = Update.Timeline.empty "local-timeline"
|
, localTimeline = Update.Timeline.empty "local-timeline"
|
||||||
, globalTimeline = Update.Timeline.empty "global-timeline"
|
, globalTimeline = Update.Timeline.empty "global-timeline"
|
||||||
|
, favoriteTimeline = Update.Timeline.empty "favorite-timeline"
|
||||||
, accountTimeline = Update.Timeline.empty "account-timeline"
|
, accountTimeline = Update.Timeline.empty "account-timeline"
|
||||||
, accountFollowers = Update.Timeline.empty "account-followers"
|
, accountFollowers = Update.Timeline.empty "account-followers"
|
||||||
, accountFollowing = Update.Timeline.empty "account-following"
|
, accountFollowing = Update.Timeline.empty "account-following"
|
||||||
, notifications = Update.Timeline.empty "notifications"
|
, notifications = Update.Timeline.empty "notifications"
|
||||||
, accountRelationships = []
|
, accountRelationships = []
|
||||||
, accountRelationship = Nothing
|
, accountRelationship = Nothing
|
||||||
, currentView = Update.Timeline.preferred model
|
, currentView = LocalTimelineView
|
||||||
}
|
}
|
||||||
! [ Command.loadUserAccount <| Just client
|
! [ Command.loadUserAccount <| Just client
|
||||||
, Command.loadTimelines <| Just client
|
, Command.loadTimelines <| Just client
|
||||||
|
@ -86,7 +99,7 @@ update msg model =
|
||||||
in
|
in
|
||||||
{ model
|
{ model
|
||||||
| clients = newClients
|
| clients = newClients
|
||||||
, currentView = Update.Timeline.preferred model
|
, currentView = LocalTimelineView
|
||||||
}
|
}
|
||||||
! [ Command.saveClients newClients
|
! [ Command.saveClients newClients
|
||||||
, Command.loadUserAccount newClient
|
, Command.loadUserAccount newClient
|
||||||
|
@ -119,11 +132,8 @@ update msg model =
|
||||||
OpenThread status ->
|
OpenThread status ->
|
||||||
model ! [ Command.loadThread (List.head model.clients) status ]
|
model ! [ Command.loadThread (List.head model.clients) status ]
|
||||||
|
|
||||||
OpenAccountSelector ->
|
|
||||||
{ model | currentView = AccountSelectorView, server = "" } ! []
|
|
||||||
|
|
||||||
CloseThread ->
|
CloseThread ->
|
||||||
{ model | currentView = Update.Timeline.preferred model } ! []
|
{ model | currentView = LocalTimelineView } ! []
|
||||||
|
|
||||||
FollowAccount id ->
|
FollowAccount id ->
|
||||||
model ! [ Command.follow (List.head model.clients) id ]
|
model ! [ Command.follow (List.head model.clients) id ]
|
||||||
|
@ -134,21 +144,21 @@ update msg model =
|
||||||
DeleteStatus id ->
|
DeleteStatus id ->
|
||||||
model ! [ Command.deleteStatus (List.head model.clients) id ]
|
model ! [ Command.deleteStatus (List.head model.clients) id ]
|
||||||
|
|
||||||
ReblogStatus id ->
|
ReblogStatus status ->
|
||||||
Update.Timeline.processReblog id True model
|
Update.Timeline.processReblog status True model
|
||||||
! [ Command.reblogStatus (List.head model.clients) id ]
|
! [ Command.reblogStatus (List.head model.clients) status.id ]
|
||||||
|
|
||||||
UnreblogStatus id ->
|
UnreblogStatus status ->
|
||||||
Update.Timeline.processReblog id False model
|
Update.Timeline.processReblog status False model
|
||||||
! [ Command.unreblogStatus (List.head model.clients) id ]
|
! [ Command.unreblogStatus (List.head model.clients) status.id ]
|
||||||
|
|
||||||
AddFavorite id ->
|
AddFavorite status ->
|
||||||
Update.Timeline.processFavourite id True model
|
Update.Timeline.processFavourite status True model
|
||||||
! [ Command.favouriteStatus (List.head model.clients) id ]
|
! [ Command.favouriteStatus (List.head model.clients) status.id ]
|
||||||
|
|
||||||
RemoveFavorite id ->
|
RemoveFavorite status ->
|
||||||
Update.Timeline.processFavourite id False model
|
Update.Timeline.processFavourite status False model
|
||||||
! [ Command.unfavouriteStatus (List.head model.clients) id ]
|
! [ Command.unfavouriteStatus (List.head model.clients) status.id ]
|
||||||
|
|
||||||
DraftEvent draftMsg ->
|
DraftEvent draftMsg ->
|
||||||
case model.currentUser of
|
case model.currentUser of
|
||||||
|
@ -199,16 +209,9 @@ update msg model =
|
||||||
ViewAccountStatuses account ->
|
ViewAccountStatuses account ->
|
||||||
{ model | currentView = AccountView account } ! []
|
{ model | currentView = AccountView account } ! []
|
||||||
|
|
||||||
UseGlobalTimeline flag ->
|
|
||||||
let
|
|
||||||
newModel =
|
|
||||||
{ model | useGlobalTimeline = flag }
|
|
||||||
in
|
|
||||||
{ newModel | currentView = Update.Timeline.preferred newModel } ! []
|
|
||||||
|
|
||||||
CloseAccount ->
|
CloseAccount ->
|
||||||
{ model
|
{ model
|
||||||
| currentView = Update.Timeline.preferred model
|
| currentView = LocalTimelineView
|
||||||
, accountTimeline = Update.Timeline.empty "account-timeline"
|
, accountTimeline = Update.Timeline.empty "account-timeline"
|
||||||
, accountFollowing = Update.Timeline.empty "account-following"
|
, accountFollowing = Update.Timeline.empty "account-following"
|
||||||
, accountFollowers = Update.Timeline.empty "account-followers"
|
, accountFollowers = Update.Timeline.empty "account-followers"
|
||||||
|
@ -216,7 +219,7 @@ update msg model =
|
||||||
! []
|
! []
|
||||||
|
|
||||||
CloseAccountSelector ->
|
CloseAccountSelector ->
|
||||||
{ model | currentView = Update.Timeline.preferred model } ! []
|
{ model | currentView = LocalTimelineView } ! []
|
||||||
|
|
||||||
FilterNotifications filter ->
|
FilterNotifications filter ->
|
||||||
{ model | notificationFilter = filter } ! []
|
{ model | notificationFilter = filter } ! []
|
||||||
|
|
|
@ -82,7 +82,7 @@ update msg model =
|
||||||
|
|
||||||
Err error ->
|
Err error ->
|
||||||
{ model
|
{ model
|
||||||
| currentView = Update.Timeline.preferred model
|
| currentView = LocalTimelineView
|
||||||
, errors = addErrorNotification (errorText error) model
|
, errors = addErrorNotification (errorText error) model
|
||||||
}
|
}
|
||||||
! []
|
! []
|
||||||
|
@ -149,6 +149,14 @@ update msg model =
|
||||||
Err error ->
|
Err error ->
|
||||||
{ model | errors = addErrorNotification (errorText error) model } ! []
|
{ model | errors = addErrorNotification (errorText error) model } ! []
|
||||||
|
|
||||||
|
FavoriteTimeline append result ->
|
||||||
|
case result of
|
||||||
|
Ok { decoded, links } ->
|
||||||
|
{ model | favoriteTimeline = Update.Timeline.update append decoded links model.favoriteTimeline } ! []
|
||||||
|
|
||||||
|
Err error ->
|
||||||
|
{ model | errors = addErrorNotification (errorText error) model } ! []
|
||||||
|
|
||||||
Reblogged result ->
|
Reblogged result ->
|
||||||
case result of
|
case result of
|
||||||
Ok _ ->
|
Ok _ ->
|
||||||
|
@ -200,7 +208,7 @@ update msg model =
|
||||||
|
|
||||||
Err error ->
|
Err error ->
|
||||||
{ model
|
{ model
|
||||||
| currentView = Update.Timeline.preferred model
|
| currentView = LocalTimelineView
|
||||||
, errors = addErrorNotification (errorText error) model
|
, errors = addErrorNotification (errorText error) model
|
||||||
}
|
}
|
||||||
! []
|
! []
|
||||||
|
|
|
@ -4,7 +4,6 @@ module Update.Timeline
|
||||||
, deleteStatus
|
, deleteStatus
|
||||||
, empty
|
, empty
|
||||||
, markAsLoading
|
, markAsLoading
|
||||||
, preferred
|
|
||||||
, prepend
|
, prepend
|
||||||
, processReblog
|
, processReblog
|
||||||
, processFavourite
|
, processFavourite
|
||||||
|
@ -25,7 +24,7 @@ deleteStatusFromCurrentView id model =
|
||||||
ThreadView thread ->
|
ThreadView thread ->
|
||||||
if thread.status.id == id then
|
if thread.status.id == id then
|
||||||
-- the current thread status as been deleted, close it
|
-- the current thread status as been deleted, close it
|
||||||
preferred model
|
LocalTimelineView
|
||||||
else
|
else
|
||||||
let
|
let
|
||||||
update statuses =
|
update statuses =
|
||||||
|
@ -49,6 +48,7 @@ deleteStatusFromAllTimelines id model =
|
||||||
| homeTimeline = deleteStatus id model.homeTimeline
|
| homeTimeline = deleteStatus id model.homeTimeline
|
||||||
, localTimeline = deleteStatus id model.localTimeline
|
, localTimeline = deleteStatus id model.localTimeline
|
||||||
, globalTimeline = deleteStatus id model.globalTimeline
|
, globalTimeline = deleteStatus id model.globalTimeline
|
||||||
|
, favoriteTimeline = deleteStatus id model.favoriteTimeline
|
||||||
, accountTimeline = deleteStatus id model.accountTimeline
|
, accountTimeline = deleteStatus id model.accountTimeline
|
||||||
, notifications = deleteStatusFromNotifications id model.notifications
|
, notifications = deleteStatusFromNotifications id model.notifications
|
||||||
, currentView = deleteStatusFromCurrentView id model
|
, currentView = deleteStatusFromCurrentView id model
|
||||||
|
@ -104,6 +104,9 @@ markAsLoading loading id model =
|
||||||
"global-timeline" ->
|
"global-timeline" ->
|
||||||
{ model | globalTimeline = mark model.globalTimeline }
|
{ model | globalTimeline = mark model.globalTimeline }
|
||||||
|
|
||||||
|
"favorite-timeline" ->
|
||||||
|
{ model | favoriteTimeline = mark model.favoriteTimeline }
|
||||||
|
|
||||||
"account-timeline" ->
|
"account-timeline" ->
|
||||||
case model.currentView of
|
case model.currentView of
|
||||||
AccountView account ->
|
AccountView account ->
|
||||||
|
@ -116,47 +119,49 @@ markAsLoading loading id model =
|
||||||
model
|
model
|
||||||
|
|
||||||
|
|
||||||
preferred : Model -> CurrentView
|
|
||||||
preferred model =
|
|
||||||
if model.useGlobalTimeline then
|
|
||||||
GlobalTimelineView
|
|
||||||
else
|
|
||||||
LocalTimelineView
|
|
||||||
|
|
||||||
|
|
||||||
prepend : a -> Timeline a -> Timeline a
|
prepend : a -> Timeline a -> Timeline a
|
||||||
prepend entry timeline =
|
prepend entry timeline =
|
||||||
{ timeline | entries = entry :: timeline.entries }
|
{ timeline | entries = entry :: timeline.entries }
|
||||||
|
|
||||||
|
|
||||||
processFavourite : Int -> Bool -> Model -> Model
|
processFavourite : Status -> Bool -> Model -> Model
|
||||||
processFavourite statusId flag model =
|
processFavourite status added model =
|
||||||
updateWithBoolFlag statusId
|
let
|
||||||
flag
|
favoriteTimeline =
|
||||||
(\s ->
|
if added then
|
||||||
{ s
|
prepend status model.favoriteTimeline
|
||||||
| favourited = Just flag
|
else
|
||||||
, favourites_count =
|
deleteStatus status.id model.favoriteTimeline
|
||||||
if flag then
|
|
||||||
s.favourites_count + 1
|
newModel =
|
||||||
else if s.favourites_count > 0 then
|
{ model | favoriteTimeline = favoriteTimeline }
|
||||||
s.favourites_count - 1
|
in
|
||||||
else
|
updateWithBoolFlag status.id
|
||||||
0
|
added
|
||||||
}
|
(\s ->
|
||||||
)
|
{ s
|
||||||
model
|
| favourited = Just added
|
||||||
|
, favourites_count =
|
||||||
|
if added then
|
||||||
|
s.favourites_count + 1
|
||||||
|
else if s.favourites_count > 0 then
|
||||||
|
s.favourites_count - 1
|
||||||
|
else
|
||||||
|
0
|
||||||
|
}
|
||||||
|
)
|
||||||
|
newModel
|
||||||
|
|
||||||
|
|
||||||
processReblog : Int -> Bool -> Model -> Model
|
processReblog : Status -> Bool -> Model -> Model
|
||||||
processReblog statusId flag model =
|
processReblog status added model =
|
||||||
updateWithBoolFlag statusId
|
updateWithBoolFlag status.id
|
||||||
flag
|
added
|
||||||
(\s ->
|
(\s ->
|
||||||
{ s
|
{ s
|
||||||
| reblogged = Just flag
|
| reblogged = Just added
|
||||||
, reblogs_count =
|
, reblogs_count =
|
||||||
if flag then
|
if added then
|
||||||
s.reblogs_count + 1
|
s.reblogs_count + 1
|
||||||
else if s.reblogs_count > 0 then
|
else if s.reblogs_count > 0 then
|
||||||
s.reblogs_count - 1
|
s.reblogs_count - 1
|
||||||
|
@ -208,6 +213,7 @@ updateWithBoolFlag statusId flag statusUpdater model =
|
||||||
, accountTimeline = updateTimeline updateStatus model.accountTimeline
|
, accountTimeline = updateTimeline updateStatus model.accountTimeline
|
||||||
, localTimeline = updateTimeline updateStatus model.localTimeline
|
, localTimeline = updateTimeline updateStatus model.localTimeline
|
||||||
, globalTimeline = updateTimeline updateStatus model.globalTimeline
|
, globalTimeline = updateTimeline updateStatus model.globalTimeline
|
||||||
|
, favoriteTimeline = updateTimeline updateStatus model.favoriteTimeline
|
||||||
, notifications = updateTimeline updateNotification model.notifications
|
, notifications = updateTimeline updateNotification model.notifications
|
||||||
, currentView =
|
, currentView =
|
||||||
case model.currentView of
|
case model.currentView of
|
||||||
|
|
|
@ -9,6 +9,7 @@ import String.Extra exposing (replace)
|
||||||
import Types exposing (..)
|
import Types exposing (..)
|
||||||
import View.Auth exposing (authForm)
|
import View.Auth exposing (authForm)
|
||||||
import View.Common exposing (..)
|
import View.Common exposing (..)
|
||||||
|
import View.Timeline exposing (contextualTimelineMenu)
|
||||||
|
|
||||||
|
|
||||||
type alias CurrentUser =
|
type alias CurrentUser =
|
||||||
|
@ -80,6 +81,7 @@ accountSelectorView model =
|
||||||
div [ class "col-md-3 column" ]
|
div [ class "col-md-3 column" ]
|
||||||
[ div [ class "panel panel-default" ]
|
[ div [ class "panel panel-default" ]
|
||||||
[ closeablePanelheading "account-selector" "user" "Account selector" CloseAccountSelector
|
[ closeablePanelheading "account-selector" "user" "Account selector" CloseAccountSelector
|
||||||
|
, contextualTimelineMenu model.currentView
|
||||||
, ul [ class "list-group " ] <|
|
, ul [ class "list-group " ] <|
|
||||||
List.map (accountIdentityView model.currentUser) model.clients
|
List.map (accountIdentityView model.currentUser) model.clients
|
||||||
, div [ class "panel-body" ]
|
, div [ class "panel-body" ]
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
module View.App exposing (view)
|
module View.App exposing (view)
|
||||||
|
|
||||||
import Html exposing (..)
|
import Html exposing (..)
|
||||||
import Html.Keyed as Keyed
|
|
||||||
import Html.Lazy as Lazy
|
|
||||||
import Html.Attributes exposing (..)
|
import Html.Attributes exposing (..)
|
||||||
|
import Html.Lazy as Lazy
|
||||||
import Mastodon.Model exposing (..)
|
import Mastodon.Model exposing (..)
|
||||||
import Types exposing (..)
|
import Types exposing (..)
|
||||||
import View.Account exposing (accountFollowView, accountTimelineView)
|
import View.Account exposing (accountFollowView, accountTimelineView)
|
||||||
|
@ -12,11 +11,9 @@ import View.Auth exposing (authView)
|
||||||
import View.Common as Common
|
import View.Common as Common
|
||||||
import View.Draft exposing (draftView)
|
import View.Draft exposing (draftView)
|
||||||
import View.Error exposing (errorsListView)
|
import View.Error exposing (errorsListView)
|
||||||
import View.Events exposing (..)
|
|
||||||
import View.Notification exposing (notificationListView)
|
import View.Notification exposing (notificationListView)
|
||||||
import View.Settings exposing (settingsView)
|
|
||||||
import View.Status exposing (statusView, statusActionsView, statusEntryView)
|
|
||||||
import View.Thread exposing (threadView)
|
import View.Thread exposing (threadView)
|
||||||
|
import View.Timeline exposing (contextualTimelineView, homeTimelineView)
|
||||||
import View.Viewer exposing (viewerView)
|
import View.Viewer exposing (viewerView)
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,61 +25,10 @@ type alias CurrentUserRelation =
|
||||||
Maybe Relationship
|
Maybe Relationship
|
||||||
|
|
||||||
|
|
||||||
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.entries
|
|
||||||
in
|
|
||||||
div [ class "col-md-3 column" ]
|
|
||||||
[ div [ class "panel panel-default" ]
|
|
||||||
[ a
|
|
||||||
[ href "", onClickWithPreventAndStop <| ScrollColumn ScrollTop timeline.id ]
|
|
||||||
[ div [ class "panel-heading" ] [ Common.icon iconName, text label ] ]
|
|
||||||
, Keyed.ul [ id timeline.id, class "list-group timeline" ] <|
|
|
||||||
(entries ++ [ ( "load-more", Common.loadMoreBtn timeline ) ])
|
|
||||||
]
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
homeTimelineView : CurrentUser -> Timeline Status -> Html Msg
|
|
||||||
homeTimelineView currentUser timeline =
|
|
||||||
Lazy.lazy timelineView
|
|
||||||
( "Home timeline"
|
|
||||||
, "home"
|
|
||||||
, currentUser
|
|
||||||
, timeline
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
localTimelineView : CurrentUser -> Timeline Status -> Html Msg
|
|
||||||
localTimelineView currentUser timeline =
|
|
||||||
Lazy.lazy timelineView
|
|
||||||
( "Local timeline"
|
|
||||||
, "th-large"
|
|
||||||
, currentUser
|
|
||||||
, timeline
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
globalTimelineView : CurrentUser -> Timeline Status -> Html Msg
|
|
||||||
globalTimelineView currentUser timeline =
|
|
||||||
Lazy.lazy timelineView
|
|
||||||
( "Global timeline"
|
|
||||||
, "globe"
|
|
||||||
, currentUser
|
|
||||||
, timeline
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
sidebarView : Model -> Html Msg
|
sidebarView : Model -> Html Msg
|
||||||
sidebarView model =
|
sidebarView model =
|
||||||
div [ class "col-md-3 column" ]
|
div [ class "col-md-3 column" ]
|
||||||
[ Lazy.lazy draftView model
|
[ Lazy.lazy draftView model
|
||||||
, Lazy.lazy settingsView model
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -102,12 +48,6 @@ homepageView model =
|
||||||
model.notificationFilter
|
model.notificationFilter
|
||||||
model.notifications
|
model.notifications
|
||||||
, case model.currentView of
|
, case model.currentView of
|
||||||
LocalTimelineView ->
|
|
||||||
localTimelineView currentUser model.localTimeline
|
|
||||||
|
|
||||||
GlobalTimelineView ->
|
|
||||||
globalTimelineView currentUser model.globalTimeline
|
|
||||||
|
|
||||||
AccountView account ->
|
AccountView account ->
|
||||||
accountTimelineView
|
accountTimelineView
|
||||||
currentUser
|
currentUser
|
||||||
|
@ -136,6 +76,30 @@ homepageView model =
|
||||||
|
|
||||||
ThreadView thread ->
|
ThreadView thread ->
|
||||||
threadView currentUser thread
|
threadView currentUser thread
|
||||||
|
|
||||||
|
LocalTimelineView ->
|
||||||
|
contextualTimelineView
|
||||||
|
LocalTimelineView
|
||||||
|
"Local timeline"
|
||||||
|
"th-large"
|
||||||
|
currentUser
|
||||||
|
model.localTimeline
|
||||||
|
|
||||||
|
GlobalTimelineView ->
|
||||||
|
contextualTimelineView
|
||||||
|
GlobalTimelineView
|
||||||
|
"Global timeline"
|
||||||
|
"globe"
|
||||||
|
currentUser
|
||||||
|
model.globalTimeline
|
||||||
|
|
||||||
|
FavoriteTimelineView ->
|
||||||
|
contextualTimelineView
|
||||||
|
FavoriteTimelineView
|
||||||
|
"Favorites"
|
||||||
|
"star"
|
||||||
|
currentUser
|
||||||
|
model.favoriteTimeline
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ currentUserView currentUser =
|
||||||
[ Common.accountLink False currentUser
|
[ Common.accountLink False currentUser
|
||||||
, span []
|
, span []
|
||||||
[ text " ("
|
[ text " ("
|
||||||
, a [ href "", onClickWithPreventAndStop <| OpenAccountSelector ]
|
, a [ href "", onClickWithPreventAndStop <| SetView AccountSelectorView ]
|
||||||
[ text "switch account" ]
|
[ text "switch account" ]
|
||||||
, text ")"
|
, text ")"
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
module View.Settings exposing (settingsView)
|
|
||||||
|
|
||||||
import Html exposing (..)
|
|
||||||
import Html.Attributes exposing (..)
|
|
||||||
import Html.Events exposing (..)
|
|
||||||
import Types exposing (..)
|
|
||||||
import View.Common as Common
|
|
||||||
|
|
||||||
|
|
||||||
settingsView : Model -> Html Msg
|
|
||||||
settingsView model =
|
|
||||||
div [ class "panel panel-default options" ]
|
|
||||||
[ div [ class "panel-heading" ] [ Common.icon "cog", text "options" ]
|
|
||||||
, div [ class "panel-body" ]
|
|
||||||
[ div [ class "checkbox" ]
|
|
||||||
[ label []
|
|
||||||
[ input [ type_ "checkbox", onCheck UseGlobalTimeline ] []
|
|
||||||
, text " 4th column renders the global timeline"
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
||||||
]
|
|
|
@ -96,18 +96,18 @@ statusActionsView status currentUser =
|
||||||
( reblogClasses, reblogEvent ) =
|
( reblogClasses, reblogEvent ) =
|
||||||
case status.reblogged of
|
case status.reblogged of
|
||||||
Just True ->
|
Just True ->
|
||||||
( baseBtnClasses ++ " reblogged", UnreblogStatus sourceStatus.id )
|
( baseBtnClasses ++ " reblogged", UnreblogStatus sourceStatus )
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
( baseBtnClasses, ReblogStatus sourceStatus.id )
|
( baseBtnClasses, ReblogStatus sourceStatus )
|
||||||
|
|
||||||
( favClasses, favEvent ) =
|
( favClasses, favEvent ) =
|
||||||
case status.favourited of
|
case status.favourited of
|
||||||
Just True ->
|
Just True ->
|
||||||
( baseBtnClasses ++ " favourited", RemoveFavorite sourceStatus.id )
|
( baseBtnClasses ++ " favourited", RemoveFavorite sourceStatus )
|
||||||
|
|
||||||
_ ->
|
_ ->
|
||||||
( baseBtnClasses, AddFavorite sourceStatus.id )
|
( baseBtnClasses, AddFavorite sourceStatus )
|
||||||
|
|
||||||
statusDate =
|
statusDate =
|
||||||
Date.fromString status.created_at
|
Date.fromString status.created_at
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
module View.Timeline
|
||||||
|
exposing
|
||||||
|
( contextualTimelineView
|
||||||
|
, contextualTimelineMenu
|
||||||
|
, homeTimelineView
|
||||||
|
)
|
||||||
|
|
||||||
|
import Html exposing (..)
|
||||||
|
import Html.Attributes exposing (..)
|
||||||
|
import Html.Events exposing (..)
|
||||||
|
import Html.Keyed as Keyed
|
||||||
|
import Html.Lazy as Lazy
|
||||||
|
import Mastodon.Model exposing (..)
|
||||||
|
import Types exposing (..)
|
||||||
|
import View.Common as Common
|
||||||
|
import View.Events exposing (..)
|
||||||
|
import View.Status exposing (statusView, statusActionsView, statusEntryView)
|
||||||
|
|
||||||
|
|
||||||
|
type alias CurrentUser =
|
||||||
|
Account
|
||||||
|
|
||||||
|
|
||||||
|
type alias CurrentUserRelation =
|
||||||
|
Maybe Relationship
|
||||||
|
|
||||||
|
|
||||||
|
topScrollableColumn : ( String, String, String ) -> Html Msg -> Html Msg
|
||||||
|
topScrollableColumn ( label, iconName, timelineId ) content =
|
||||||
|
div [ class "col-md-3 column" ]
|
||||||
|
[ div [ class "panel panel-default" ]
|
||||||
|
[ a
|
||||||
|
[ href "", onClickWithPreventAndStop <| ScrollColumn ScrollTop timelineId ]
|
||||||
|
[ div [ class "panel-heading" ] [ Common.icon iconName, text label ] ]
|
||||||
|
, content
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
timelineView : CurrentUser -> Timeline Status -> Html Msg
|
||||||
|
timelineView currentUser timeline =
|
||||||
|
let
|
||||||
|
keyedEntry status =
|
||||||
|
( toString id, statusEntryView timeline.id "" currentUser status )
|
||||||
|
|
||||||
|
entries =
|
||||||
|
List.map keyedEntry timeline.entries
|
||||||
|
in
|
||||||
|
Keyed.ul [ id timeline.id, class "list-group timeline" ] <|
|
||||||
|
(entries ++ [ ( "load-more", Common.loadMoreBtn timeline ) ])
|
||||||
|
|
||||||
|
|
||||||
|
homeTimelineView : CurrentUser -> Timeline Status -> Html Msg
|
||||||
|
homeTimelineView currentUser timeline =
|
||||||
|
Lazy.lazy2 topScrollableColumn
|
||||||
|
( "Home timeline"
|
||||||
|
, "home"
|
||||||
|
, timeline.id
|
||||||
|
)
|
||||||
|
(timelineView currentUser timeline)
|
||||||
|
|
||||||
|
|
||||||
|
contextualTimelineMenu : CurrentView -> Html Msg
|
||||||
|
contextualTimelineMenu currentView =
|
||||||
|
let
|
||||||
|
btnView tooltip iconName view =
|
||||||
|
button
|
||||||
|
[ class <|
|
||||||
|
"btn "
|
||||||
|
++ (if currentView == view then
|
||||||
|
"btn-primary active"
|
||||||
|
else
|
||||||
|
"btn-default"
|
||||||
|
)
|
||||||
|
, onClick <| SetView view
|
||||||
|
, Html.Attributes.title tooltip
|
||||||
|
]
|
||||||
|
[ Common.icon iconName ]
|
||||||
|
in
|
||||||
|
Common.justifiedButtonGroup ""
|
||||||
|
[ btnView "Local timeline" "th-large" LocalTimelineView
|
||||||
|
, btnView "Global timeline" "globe" GlobalTimelineView
|
||||||
|
, btnView "Favorites" "star" FavoriteTimelineView
|
||||||
|
, btnView "Accounts" "user" AccountSelectorView
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
contextualTimelineView : CurrentView -> String -> String -> CurrentUser -> Timeline Status -> Html Msg
|
||||||
|
contextualTimelineView currentView title iconName currentUser timeline =
|
||||||
|
div []
|
||||||
|
[ contextualTimelineMenu currentView
|
||||||
|
, timelineView currentUser timeline
|
||||||
|
]
|
||||||
|
|> Lazy.lazy2 topScrollableColumn ( title, iconName, timeline.id )
|
Loading…
Reference in New Issue