Urlify app. (#186)
This commit is contained in:
parent
ba24f6a9cc
commit
6d7e9e9036
@ -688,8 +688,7 @@ input.form-control[type=file] {
|
||||
}
|
||||
|
||||
.account-infos a:hover,
|
||||
.account-infos a:focus,
|
||||
.account-infos a:active {
|
||||
.account-infos a.active {
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
}
|
||||
|
100
src/Command.elm
100
src/Command.elm
@ -256,14 +256,20 @@ loadRelationships client ids =
|
||||
Cmd.none
|
||||
|
||||
|
||||
loadThread : Maybe Client -> Status -> Cmd Msg
|
||||
loadThread client status =
|
||||
loadThread : Maybe Client -> Int -> Cmd Msg
|
||||
loadThread client id =
|
||||
case client of
|
||||
Just client ->
|
||||
HttpBuilder.get (ApiUrl.context status.id)
|
||||
|> withClient client
|
||||
|> withBodyDecoder contextDecoder
|
||||
|> send (MastodonEvent << (ContextLoaded status))
|
||||
Cmd.batch
|
||||
[ HttpBuilder.get (ApiUrl.status id)
|
||||
|> withClient client
|
||||
|> withBodyDecoder statusDecoder
|
||||
|> send (MastodonEvent << (ThreadStatusLoaded id))
|
||||
, HttpBuilder.get (ApiUrl.context id)
|
||||
|> withClient client
|
||||
|> withBodyDecoder contextDecoder
|
||||
|> send (MastodonEvent << (ThreadContextLoaded id))
|
||||
]
|
||||
|
||||
Nothing ->
|
||||
Cmd.none
|
||||
@ -391,58 +397,62 @@ loadTimelines client =
|
||||
]
|
||||
|
||||
|
||||
loadNextTimeline : Maybe Client -> CurrentView -> String -> String -> Cmd Msg
|
||||
loadNextTimeline client currentView id next =
|
||||
case id of
|
||||
"notifications" ->
|
||||
loadNotifications client (Just next)
|
||||
loadNextTimeline : Model -> String -> String -> Cmd Msg
|
||||
loadNextTimeline { clients, currentView, accountInfo } id next =
|
||||
let
|
||||
client =
|
||||
List.head clients
|
||||
in
|
||||
case id of
|
||||
"notifications" ->
|
||||
loadNotifications client (Just next)
|
||||
|
||||
"home-timeline" ->
|
||||
loadHomeTimeline client (Just next)
|
||||
"home-timeline" ->
|
||||
loadHomeTimeline client (Just next)
|
||||
|
||||
"local-timeline" ->
|
||||
loadLocalTimeline client (Just next)
|
||||
"local-timeline" ->
|
||||
loadLocalTimeline client (Just next)
|
||||
|
||||
"global-timeline" ->
|
||||
loadGlobalTimeline client (Just next)
|
||||
"global-timeline" ->
|
||||
loadGlobalTimeline client (Just next)
|
||||
|
||||
"favorite-timeline" ->
|
||||
loadFavoriteTimeline client (Just next)
|
||||
"favorite-timeline" ->
|
||||
loadFavoriteTimeline client (Just next)
|
||||
|
||||
"hashtag-timeline" ->
|
||||
case currentView of
|
||||
HashtagView hashtag ->
|
||||
loadHashtagTimeline client hashtag (Just next)
|
||||
"hashtag-timeline" ->
|
||||
case currentView of
|
||||
HashtagView hashtag ->
|
||||
loadHashtagTimeline client hashtag (Just next)
|
||||
|
||||
_ ->
|
||||
Cmd.none
|
||||
_ ->
|
||||
Cmd.none
|
||||
|
||||
"account-timeline" ->
|
||||
case currentView of
|
||||
AccountView account ->
|
||||
loadAccountTimeline client account.id (Just next)
|
||||
"account-timeline" ->
|
||||
case accountInfo.account of
|
||||
Just account ->
|
||||
loadAccountTimeline client account.id (Just next)
|
||||
|
||||
_ ->
|
||||
Cmd.none
|
||||
_ ->
|
||||
Cmd.none
|
||||
|
||||
"account-followers" ->
|
||||
case currentView of
|
||||
AccountFollowersView account timeline ->
|
||||
loadAccountFollowers client account.id (Just next)
|
||||
"account-followers" ->
|
||||
case accountInfo.account of
|
||||
Just account ->
|
||||
loadAccountFollowers client account.id (Just next)
|
||||
|
||||
_ ->
|
||||
Cmd.none
|
||||
_ ->
|
||||
Cmd.none
|
||||
|
||||
"account-following" ->
|
||||
case currentView of
|
||||
AccountFollowingView account timeline ->
|
||||
loadAccountFollowing client account.id (Just next)
|
||||
"account-following" ->
|
||||
case accountInfo.account of
|
||||
Just account ->
|
||||
loadAccountFollowing client account.id (Just next)
|
||||
|
||||
_ ->
|
||||
Cmd.none
|
||||
_ ->
|
||||
Cmd.none
|
||||
|
||||
_ ->
|
||||
Cmd.none
|
||||
_ ->
|
||||
Cmd.none
|
||||
|
||||
|
||||
postStatus : Maybe Client -> StatusRequestBody -> Cmd Msg
|
||||
|
57
src/Init.elm
57
src/Init.elm
@ -3,37 +3,40 @@ module Init exposing (init)
|
||||
import Command
|
||||
import Navigation
|
||||
import Types exposing (..)
|
||||
import Update.AccountInfo
|
||||
import Update.Draft
|
||||
import Update.Route
|
||||
import Update.Timeline
|
||||
import Util
|
||||
|
||||
|
||||
init : Flags -> Navigation.Location -> ( Model, Cmd Msg )
|
||||
init { registration, clients } location =
|
||||
{ server = ""
|
||||
, currentTime = 0
|
||||
, registration = registration
|
||||
, clients = clients
|
||||
, homeTimeline = Update.Timeline.empty "home-timeline"
|
||||
, localTimeline = Update.Timeline.empty "local-timeline"
|
||||
, globalTimeline = Update.Timeline.empty "global-timeline"
|
||||
, favoriteTimeline = Update.Timeline.empty "favorite-timeline"
|
||||
, hashtagTimeline = Update.Timeline.empty "hashtag-timeline"
|
||||
, mutes = Update.Timeline.empty "mutes-timeline"
|
||||
, blocks = Update.Timeline.empty "blocks-timeline"
|
||||
, accountTimeline = Update.Timeline.empty "account-timeline"
|
||||
, accountFollowers = Update.Timeline.empty "account-followers"
|
||||
, accountFollowing = Update.Timeline.empty "account-following"
|
||||
, accountRelationships = []
|
||||
, accountRelationship = Nothing
|
||||
, notifications = Update.Timeline.empty "notifications"
|
||||
, draft = Update.Draft.empty
|
||||
, errors = []
|
||||
, location = location
|
||||
, viewer = Nothing
|
||||
, currentView = LocalTimelineView
|
||||
, currentUser = Nothing
|
||||
, notificationFilter = NotificationAll
|
||||
, confirm = Nothing
|
||||
}
|
||||
! [ Command.initCommands registration (List.head clients) (Util.extractAuthCode location) ]
|
||||
let
|
||||
( model, commands ) =
|
||||
Update.Route.update
|
||||
{ server = ""
|
||||
, currentTime = 0
|
||||
, registration = registration
|
||||
, clients = clients
|
||||
, homeTimeline = Update.Timeline.empty "home-timeline"
|
||||
, localTimeline = Update.Timeline.empty "local-timeline"
|
||||
, globalTimeline = Update.Timeline.empty "global-timeline"
|
||||
, favoriteTimeline = Update.Timeline.empty "favorite-timeline"
|
||||
, hashtagTimeline = Update.Timeline.empty "hashtag-timeline"
|
||||
, mutes = Update.Timeline.empty "mutes-timeline"
|
||||
, blocks = Update.Timeline.empty "blocks-timeline"
|
||||
, accountInfo = Update.AccountInfo.empty
|
||||
, notifications = Update.Timeline.empty "notifications"
|
||||
, draft = Update.Draft.empty
|
||||
, errors = []
|
||||
, location = location
|
||||
, viewer = Nothing
|
||||
, currentView = LocalTimelineView
|
||||
, currentUser = Nothing
|
||||
, notificationFilter = NotificationAll
|
||||
, confirm = Nothing
|
||||
}
|
||||
in
|
||||
model
|
||||
! [ commands, Command.initCommands registration (List.head clients) (Util.extractAuthCode location) ]
|
||||
|
@ -57,7 +57,6 @@ type MastodonMsg
|
||||
| AppRegistered (MastodonResult AppRegistration)
|
||||
| AutoSearch (MastodonResult (List Account))
|
||||
| Blocks Bool (MastodonResult (List Account))
|
||||
| ContextLoaded Status (MastodonResult Context)
|
||||
| CurrentUser (MastodonResult Account)
|
||||
| FavoriteAdded (MastodonResult Status)
|
||||
| FavoriteRemoved (MastodonResult Status)
|
||||
@ -71,6 +70,8 @@ type MastodonMsg
|
||||
| Reblogged (MastodonResult Status)
|
||||
| StatusDeleted (MastodonResult Int)
|
||||
| StatusPosted (MastodonResult Status)
|
||||
| ThreadStatusLoaded Int (MastodonResult Status)
|
||||
| ThreadContextLoaded Int (MastodonResult Context)
|
||||
| Unreblogged (MastodonResult Status)
|
||||
|
||||
|
||||
@ -83,21 +84,20 @@ type WebSocketMsg
|
||||
type Msg
|
||||
= AddFavorite Status
|
||||
| AskConfirm String Msg Msg
|
||||
| Back
|
||||
| Block Account
|
||||
| ClearError Int
|
||||
| CloseAccount
|
||||
| CloseThread
|
||||
| ConfirmCancelled Msg
|
||||
| Confirmed Msg
|
||||
| DeleteStatus Int
|
||||
| DraftEvent DraftMsg
|
||||
| FilterNotifications NotificationFilter
|
||||
| FollowAccount Account
|
||||
| LoadAccount Int
|
||||
| LogoutClient Client
|
||||
| TimelineLoadNext String String
|
||||
| MastodonEvent MastodonMsg
|
||||
| Mute Account
|
||||
| Navigate String
|
||||
| NoOp
|
||||
| OpenThread Status
|
||||
| ReblogStatus Status
|
||||
@ -105,7 +105,6 @@ type Msg
|
||||
| RemoveFavorite Status
|
||||
| ScrollColumn ScrollDirection String
|
||||
| ServerChange String
|
||||
| SetView CurrentView
|
||||
| SubmitDraft
|
||||
| SwitchClient Client
|
||||
| Tick Time
|
||||
@ -114,13 +113,20 @@ type Msg
|
||||
| Unmute Account
|
||||
| UnreblogStatus Status
|
||||
| UrlChange Navigation.Location
|
||||
| ViewAccountFollowing Account
|
||||
| ViewAccountFollowers Account
|
||||
| ViewAccountStatuses Account
|
||||
| ViewerEvent ViewerMsg
|
||||
| WebSocketEvent WebSocketMsg
|
||||
|
||||
|
||||
type alias AccountInfo =
|
||||
{ account : Maybe Account
|
||||
, timeline : Timeline Status
|
||||
, followers : Timeline Account
|
||||
, following : Timeline Account
|
||||
, relationships : List Relationship
|
||||
, relationship : Maybe Relationship
|
||||
}
|
||||
|
||||
|
||||
type alias Confirm =
|
||||
{ message : String
|
||||
, onConfirm : Msg
|
||||
@ -130,9 +136,7 @@ type alias Confirm =
|
||||
|
||||
type CurrentView
|
||||
= -- Basically, what we should be displaying in the fourth column
|
||||
AccountFollowersView Account (Timeline Account)
|
||||
| AccountFollowingView Account (Timeline Account)
|
||||
| AccountView Account
|
||||
AccountView CurrentAccountView
|
||||
| AccountSelectorView
|
||||
| BlocksView
|
||||
| FavoriteTimelineView
|
||||
@ -143,6 +147,12 @@ type CurrentView
|
||||
| ThreadView Thread
|
||||
|
||||
|
||||
type CurrentAccountView
|
||||
= AccountStatusesView
|
||||
| AccountFollowersView
|
||||
| AccountFollowingView
|
||||
|
||||
|
||||
type alias Draft =
|
||||
{ status : String
|
||||
, inReplyTo : Maybe Status
|
||||
@ -179,8 +189,8 @@ type ScrollDirection
|
||||
|
||||
|
||||
type alias Thread =
|
||||
{ status : Status
|
||||
, context : Context
|
||||
{ status : Maybe Status
|
||||
, context : Maybe Context
|
||||
}
|
||||
|
||||
|
||||
@ -216,11 +226,7 @@ type alias Model =
|
||||
, hashtagTimeline : Timeline Status
|
||||
, mutes : Timeline Account
|
||||
, blocks : Timeline Account
|
||||
, accountTimeline : Timeline Status
|
||||
, accountFollowers : Timeline Account
|
||||
, accountFollowing : Timeline Account
|
||||
, accountRelationships : List Relationship
|
||||
, accountRelationship : Maybe Relationship
|
||||
, accountInfo : AccountInfo
|
||||
, notifications : Timeline NotificationAggregate
|
||||
, draft : Draft
|
||||
, errors : List ErrorNotification
|
||||
|
15
src/Update/AccountInfo.elm
Normal file
15
src/Update/AccountInfo.elm
Normal file
@ -0,0 +1,15 @@
|
||||
module Update.AccountInfo exposing (empty)
|
||||
|
||||
import Types exposing (..)
|
||||
import Update.Timeline
|
||||
|
||||
|
||||
empty : AccountInfo
|
||||
empty =
|
||||
{ account = Nothing
|
||||
, timeline = Update.Timeline.empty "account-timeline"
|
||||
, followers = Update.Timeline.empty "account-followers"
|
||||
, following = Update.Timeline.empty "account-following"
|
||||
, relationships = []
|
||||
, relationship = Nothing
|
||||
}
|
@ -3,10 +3,13 @@ module Update.Main exposing (update)
|
||||
import Command
|
||||
import List.Extra exposing (removeAt)
|
||||
import Mastodon.Model exposing (..)
|
||||
import Navigation
|
||||
import Types exposing (..)
|
||||
import Update.AccountInfo
|
||||
import Update.Draft
|
||||
import Update.Error
|
||||
import Update.Mastodon
|
||||
import Update.Route
|
||||
import Update.Timeline
|
||||
import Update.Viewer
|
||||
import Update.WebSocket
|
||||
@ -35,6 +38,19 @@ update msg model =
|
||||
NoOp ->
|
||||
model ! []
|
||||
|
||||
UrlChange location ->
|
||||
let
|
||||
newModel =
|
||||
{ model | location = location }
|
||||
in
|
||||
Update.Route.update newModel
|
||||
|
||||
Back ->
|
||||
model ! [ Navigation.back 1 ]
|
||||
|
||||
Navigate href ->
|
||||
model ! [ Navigation.newUrl href ]
|
||||
|
||||
Tick newTime ->
|
||||
{ model
|
||||
| currentTime = newTime
|
||||
@ -54,42 +70,6 @@ update msg model =
|
||||
Confirmed onConfirm ->
|
||||
update onConfirm { model | confirm = Nothing }
|
||||
|
||||
SetView view ->
|
||||
case view of
|
||||
AccountSelectorView ->
|
||||
{ model | currentView = view, server = "" } ! []
|
||||
|
||||
FavoriteTimelineView ->
|
||||
{ model
|
||||
| currentView = view
|
||||
, favoriteTimeline = Update.Timeline.setLoading True model.favoriteTimeline
|
||||
}
|
||||
! [ Command.loadFavoriteTimeline (List.head model.clients) Nothing ]
|
||||
|
||||
BlocksView ->
|
||||
{ model
|
||||
| currentView = view
|
||||
, blocks = Update.Timeline.setLoading True model.blocks
|
||||
}
|
||||
! [ Command.loadBlocks (List.head model.clients) Nothing ]
|
||||
|
||||
MutesView ->
|
||||
{ model
|
||||
| currentView = view
|
||||
, mutes = Update.Timeline.setLoading True model.mutes
|
||||
}
|
||||
! [ Command.loadMutes (List.head model.clients) Nothing ]
|
||||
|
||||
HashtagView hashtag ->
|
||||
{ model
|
||||
| currentView = view
|
||||
, hashtagTimeline = Update.Timeline.setLoading True model.hashtagTimeline
|
||||
}
|
||||
! [ Command.loadHashtagTimeline (List.head model.clients) hashtag Nothing ]
|
||||
|
||||
_ ->
|
||||
{ model | currentView = view } ! []
|
||||
|
||||
SwitchClient client ->
|
||||
let
|
||||
newClients =
|
||||
@ -101,16 +81,11 @@ update msg model =
|
||||
, localTimeline = Update.Timeline.empty "local-timeline"
|
||||
, globalTimeline = Update.Timeline.empty "global-timeline"
|
||||
, favoriteTimeline = Update.Timeline.empty "favorite-timeline"
|
||||
, hashtagTimeline = Update.Timeline.empty "hashtag-following"
|
||||
, accountTimeline = Update.Timeline.empty "account-timeline"
|
||||
, accountFollowers = Update.Timeline.empty "account-followers"
|
||||
, accountFollowing = Update.Timeline.empty "account-following"
|
||||
, accountInfo = Update.AccountInfo.empty
|
||||
, mutes = Update.Timeline.empty "mutes-timeline"
|
||||
, blocks = Update.Timeline.empty "blocks-timeline"
|
||||
, notifications = Update.Timeline.empty "notifications"
|
||||
, accountRelationships = []
|
||||
, accountRelationship = Nothing
|
||||
, currentView = LocalTimelineView
|
||||
, currentView = AccountSelectorView
|
||||
}
|
||||
! [ Command.loadUserAccount <| Just client
|
||||
, Command.loadTimelines <| Just client
|
||||
@ -150,17 +125,14 @@ update msg model =
|
||||
ServerChange server ->
|
||||
{ model | server = server } ! []
|
||||
|
||||
UrlChange location ->
|
||||
model ! []
|
||||
|
||||
Register ->
|
||||
model ! [ Command.registerApp model ]
|
||||
|
||||
OpenThread status ->
|
||||
model ! [ Command.loadThread (List.head model.clients) status ]
|
||||
|
||||
CloseThread ->
|
||||
{ model | currentView = LocalTimelineView } ! []
|
||||
{ model
|
||||
| currentView = ThreadView (Thread Nothing Nothing)
|
||||
}
|
||||
! [ Navigation.newUrl <| "#thread/" ++ (toString status.id) ]
|
||||
|
||||
FollowAccount account ->
|
||||
model ! [ Command.follow (List.head model.clients) account ]
|
||||
@ -220,45 +192,9 @@ update msg model =
|
||||
toStatusRequestBody model.draft
|
||||
]
|
||||
|
||||
LoadAccount accountId ->
|
||||
{ model
|
||||
| accountTimeline = Update.Timeline.empty "account-timeline"
|
||||
, accountFollowers = Update.Timeline.empty "account-followers"
|
||||
, accountFollowing = Update.Timeline.empty "account-following"
|
||||
, accountRelationships = []
|
||||
, accountRelationship = Nothing
|
||||
}
|
||||
! [ Command.loadAccount (List.head model.clients) accountId ]
|
||||
|
||||
TimelineLoadNext id next ->
|
||||
Update.Timeline.markAsLoading True id model
|
||||
! [ Command.loadNextTimeline (List.head model.clients) model.currentView id next ]
|
||||
|
||||
ViewAccountFollowers account ->
|
||||
{ model
|
||||
| currentView = AccountFollowersView account model.accountFollowers
|
||||
, accountRelationships = []
|
||||
}
|
||||
! [ Command.loadAccountFollowers (List.head model.clients) account.id Nothing ]
|
||||
|
||||
ViewAccountFollowing account ->
|
||||
{ model
|
||||
| currentView = AccountFollowingView account model.accountFollowing
|
||||
, accountRelationships = []
|
||||
}
|
||||
! [ Command.loadAccountFollowing (List.head model.clients) account.id Nothing ]
|
||||
|
||||
ViewAccountStatuses account ->
|
||||
{ model | currentView = AccountView account } ! []
|
||||
|
||||
CloseAccount ->
|
||||
{ model
|
||||
| currentView = LocalTimelineView
|
||||
, accountTimeline = Update.Timeline.empty "account-timeline"
|
||||
, accountFollowing = Update.Timeline.empty "account-following"
|
||||
, accountFollowers = Update.Timeline.empty "account-followers"
|
||||
}
|
||||
! []
|
||||
! [ Command.loadNextTimeline model id next ]
|
||||
|
||||
FilterNotifications filter ->
|
||||
{ model | notificationFilter = filter } ! []
|
||||
|
@ -28,7 +28,7 @@ errorText error =
|
||||
|
||||
|
||||
update : MastodonMsg -> Model -> ( Model, Cmd Msg )
|
||||
update msg model =
|
||||
update msg ({ accountInfo } as model) =
|
||||
case msg of
|
||||
AccessToken result ->
|
||||
case result of
|
||||
@ -106,11 +106,40 @@ update msg model =
|
||||
Err error ->
|
||||
{ model | errors = addErrorNotification (errorText error) model } ! []
|
||||
|
||||
ContextLoaded status result ->
|
||||
ThreadStatusLoaded id result ->
|
||||
case result of
|
||||
Ok { decoded } ->
|
||||
{ model | currentView = ThreadView (Thread status decoded) }
|
||||
! [ Command.scrollToThreadStatus <| toString status.id ]
|
||||
{ model
|
||||
| currentView =
|
||||
case model.currentView of
|
||||
ThreadView thread ->
|
||||
ThreadView { thread | status = Just decoded }
|
||||
|
||||
_ ->
|
||||
model.currentView
|
||||
}
|
||||
! [ Command.scrollToThreadStatus <| toString id ]
|
||||
|
||||
Err error ->
|
||||
{ model
|
||||
| currentView = LocalTimelineView
|
||||
, errors = addErrorNotification (errorText error) model
|
||||
}
|
||||
! []
|
||||
|
||||
ThreadContextLoaded id result ->
|
||||
case result of
|
||||
Ok { decoded } ->
|
||||
{ model
|
||||
| currentView =
|
||||
case model.currentView of
|
||||
ThreadView thread ->
|
||||
ThreadView { thread | context = Just decoded }
|
||||
|
||||
_ ->
|
||||
model.currentView
|
||||
}
|
||||
! [ Command.scrollToThreadStatus <| toString id ]
|
||||
|
||||
Err error ->
|
||||
{ model
|
||||
@ -249,27 +278,21 @@ update msg model =
|
||||
AccountReceived result ->
|
||||
case result of
|
||||
Ok { decoded } ->
|
||||
{ model
|
||||
| currentView = AccountView decoded
|
||||
, accountRelationships = []
|
||||
}
|
||||
! [ Command.loadAccountTimeline
|
||||
(List.head model.clients)
|
||||
decoded.id
|
||||
model.accountTimeline.links.next
|
||||
]
|
||||
{ model | accountInfo = { accountInfo | account = Just decoded, relationships = [] } } ! []
|
||||
|
||||
Err error ->
|
||||
{ model
|
||||
| currentView = LocalTimelineView
|
||||
, errors = addErrorNotification (errorText error) model
|
||||
}
|
||||
! []
|
||||
{ model | errors = addErrorNotification (errorText error) model } ! []
|
||||
|
||||
AccountTimeline append result ->
|
||||
case result of
|
||||
Ok { decoded, links } ->
|
||||
{ model | accountTimeline = Update.Timeline.update append decoded links model.accountTimeline } ! []
|
||||
{ model
|
||||
| accountInfo =
|
||||
{ accountInfo
|
||||
| timeline = Update.Timeline.update append decoded links accountInfo.timeline
|
||||
}
|
||||
}
|
||||
! []
|
||||
|
||||
Err error ->
|
||||
{ model | errors = addErrorNotification (errorText error) model } ! []
|
||||
@ -277,7 +300,12 @@ update msg model =
|
||||
AccountFollowers append result ->
|
||||
case result of
|
||||
Ok { decoded, links } ->
|
||||
{ model | accountFollowers = Update.Timeline.update append decoded links model.accountFollowers }
|
||||
{ model
|
||||
| accountInfo =
|
||||
{ accountInfo
|
||||
| followers = Update.Timeline.update append decoded links accountInfo.followers
|
||||
}
|
||||
}
|
||||
! [ Command.loadRelationships (List.head model.clients) <| List.map .id decoded ]
|
||||
|
||||
Err error ->
|
||||
@ -286,7 +314,12 @@ update msg model =
|
||||
AccountFollowing append result ->
|
||||
case result of
|
||||
Ok { decoded, links } ->
|
||||
{ model | accountFollowing = Update.Timeline.update append decoded links model.accountFollowing }
|
||||
{ model
|
||||
| accountInfo =
|
||||
{ accountInfo
|
||||
| following = Update.Timeline.update append decoded links accountInfo.following
|
||||
}
|
||||
}
|
||||
! [ Command.loadRelationships (List.head model.clients) <| List.map .id decoded ]
|
||||
|
||||
Err error ->
|
||||
@ -297,7 +330,7 @@ update msg model =
|
||||
Ok { decoded } ->
|
||||
case decoded of
|
||||
[ relationship ] ->
|
||||
{ model | accountRelationship = Just relationship } ! []
|
||||
{ model | accountInfo = { accountInfo | relationship = Just relationship } } ! []
|
||||
|
||||
_ ->
|
||||
model ! []
|
||||
@ -309,7 +342,10 @@ update msg model =
|
||||
case result of
|
||||
Ok { decoded } ->
|
||||
{ model
|
||||
| accountRelationships = List.concat [ model.accountRelationships, decoded ]
|
||||
| accountInfo =
|
||||
{ accountInfo
|
||||
| relationships = List.concat [ accountInfo.relationships, decoded ]
|
||||
}
|
||||
}
|
||||
! []
|
||||
|
||||
@ -358,7 +394,7 @@ update msg model =
|
||||
current connected user, both according to the "following" status provided.
|
||||
-}
|
||||
processFollowEvent : Relationship -> Model -> Model
|
||||
processFollowEvent relationship model =
|
||||
processFollowEvent relationship ({ accountInfo } as model) =
|
||||
let
|
||||
updateRelationship r =
|
||||
if r.id == relationship.id then
|
||||
@ -367,22 +403,25 @@ processFollowEvent relationship model =
|
||||
r
|
||||
|
||||
accountRelationships =
|
||||
model.accountRelationships |> List.map updateRelationship
|
||||
accountInfo.relationships |> List.map updateRelationship
|
||||
|
||||
accountRelationship =
|
||||
case model.accountRelationship of
|
||||
Just accountRelationship ->
|
||||
if accountRelationship.id == relationship.id then
|
||||
case accountInfo.relationship of
|
||||
Just relationship ->
|
||||
if relationship.id == relationship.id then
|
||||
Just { relationship | following = relationship.following }
|
||||
else
|
||||
model.accountRelationship
|
||||
accountInfo.relationship
|
||||
|
||||
Nothing ->
|
||||
Nothing
|
||||
in
|
||||
{ model
|
||||
| accountRelationships = accountRelationships
|
||||
, accountRelationship = accountRelationship
|
||||
| accountInfo =
|
||||
{ accountInfo
|
||||
| relationships = accountRelationships
|
||||
, relationship = accountRelationship
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -406,7 +445,7 @@ processUnfollowEvent account relationship model =
|
||||
current connected user, both according to the "muting" status provided.
|
||||
-}
|
||||
processMuteEvent : Account -> Relationship -> Model -> Model
|
||||
processMuteEvent account relationship model =
|
||||
processMuteEvent account relationship ({ accountInfo } as model) =
|
||||
let
|
||||
updateRelationship r =
|
||||
if r.id == relationship.id then
|
||||
@ -415,22 +454,25 @@ processMuteEvent account relationship model =
|
||||
r
|
||||
|
||||
accountRelationships =
|
||||
model.accountRelationships |> List.map updateRelationship
|
||||
accountInfo.relationships |> List.map updateRelationship
|
||||
|
||||
accountRelationship =
|
||||
case model.accountRelationship of
|
||||
Just accountRelationship ->
|
||||
if accountRelationship.id == relationship.id then
|
||||
case accountInfo.relationship of
|
||||
Just relationship ->
|
||||
if relationship.id == relationship.id then
|
||||
Just { relationship | muting = relationship.muting }
|
||||
else
|
||||
model.accountRelationship
|
||||
accountInfo.relationship
|
||||
|
||||
Nothing ->
|
||||
Nothing
|
||||
in
|
||||
{ model
|
||||
| accountRelationships = accountRelationships
|
||||
, accountRelationship = accountRelationship
|
||||
| accountInfo =
|
||||
{ accountInfo
|
||||
| relationship = accountRelationship
|
||||
, relationships = accountRelationships
|
||||
}
|
||||
, homeTimeline = Update.Timeline.dropAccountStatuses account model.homeTimeline
|
||||
, localTimeline = Update.Timeline.dropAccountStatuses account model.localTimeline
|
||||
, globalTimeline = Update.Timeline.dropAccountStatuses account model.globalTimeline
|
||||
@ -442,7 +484,7 @@ processMuteEvent account relationship model =
|
||||
current connected user, both according to the "blocking" status provided.
|
||||
-}
|
||||
processBlockEvent : Account -> Relationship -> Model -> Model
|
||||
processBlockEvent account relationship model =
|
||||
processBlockEvent account relationship ({ accountInfo } as model) =
|
||||
let
|
||||
updateRelationship r =
|
||||
if r.id == relationship.id then
|
||||
@ -451,22 +493,25 @@ processBlockEvent account relationship model =
|
||||
r
|
||||
|
||||
accountRelationships =
|
||||
model.accountRelationships |> List.map updateRelationship
|
||||
accountInfo.relationships |> List.map updateRelationship
|
||||
|
||||
accountRelationship =
|
||||
case model.accountRelationship of
|
||||
Just accountRelationship ->
|
||||
if accountRelationship.id == relationship.id then
|
||||
case accountInfo.relationship of
|
||||
Just relationship ->
|
||||
if relationship.id == relationship.id then
|
||||
Just { relationship | blocking = relationship.blocking }
|
||||
else
|
||||
model.accountRelationship
|
||||
accountInfo.relationship
|
||||
|
||||
Nothing ->
|
||||
Nothing
|
||||
in
|
||||
{ model
|
||||
| accountRelationships = accountRelationships
|
||||
, accountRelationship = accountRelationship
|
||||
| accountInfo =
|
||||
{ accountInfo
|
||||
| relationship = accountRelationship
|
||||
, relationships = accountRelationships
|
||||
}
|
||||
, homeTimeline = Update.Timeline.dropAccountStatuses account model.homeTimeline
|
||||
, localTimeline = Update.Timeline.dropAccountStatuses account model.localTimeline
|
||||
, globalTimeline = Update.Timeline.dropAccountStatuses account model.globalTimeline
|
||||
|
113
src/Update/Route.elm
Normal file
113
src/Update/Route.elm
Normal file
@ -0,0 +1,113 @@
|
||||
module Update.Route exposing (update)
|
||||
|
||||
import Command
|
||||
import Types exposing (..)
|
||||
import Update.AccountInfo
|
||||
import Update.Timeline
|
||||
import UrlParser exposing (..)
|
||||
|
||||
|
||||
type Route
|
||||
= AccountFollowersRoute Int
|
||||
| AccountFollowingRoute Int
|
||||
| AccountRoute Int
|
||||
| AccountSelectorRoute
|
||||
| BlocksRoute
|
||||
| FavoriteTimelineRoute
|
||||
| GlobalTimelineRoute
|
||||
| HashtagRoute String
|
||||
| LocalTimelineRoute
|
||||
| MutesRoute
|
||||
| ThreadRoute Int
|
||||
|
||||
|
||||
route : Parser (Route -> a) a
|
||||
route =
|
||||
oneOf
|
||||
[ map LocalTimelineRoute top
|
||||
, map GlobalTimelineRoute (s "global" </> top)
|
||||
, map FavoriteTimelineRoute (s "favorites" </> top)
|
||||
, map HashtagRoute (s "hashtag" </> string)
|
||||
, map ThreadRoute (s "thread" </> int)
|
||||
, map BlocksRoute (s "blocks" </> top)
|
||||
, map MutesRoute (s "mutes" </> top)
|
||||
, map AccountFollowersRoute (s "account" </> int </> s "followers")
|
||||
, map AccountFollowingRoute (s "account" </> int </> s "following")
|
||||
, map AccountRoute (s "account" </> int)
|
||||
, map AccountSelectorRoute (s "accounts")
|
||||
]
|
||||
|
||||
|
||||
update : Model -> ( Model, Cmd Msg )
|
||||
update ({ accountInfo } as model) =
|
||||
case parseHash route model.location of
|
||||
Just LocalTimelineRoute ->
|
||||
{ model | currentView = LocalTimelineView } ! []
|
||||
|
||||
Just GlobalTimelineRoute ->
|
||||
{ model | currentView = GlobalTimelineView } ! []
|
||||
|
||||
Just FavoriteTimelineRoute ->
|
||||
{ model
|
||||
| currentView = FavoriteTimelineView
|
||||
, favoriteTimeline = Update.Timeline.setLoading True model.favoriteTimeline
|
||||
}
|
||||
! [ Command.loadFavoriteTimeline (List.head model.clients) Nothing ]
|
||||
|
||||
Just BlocksRoute ->
|
||||
{ model
|
||||
| currentView = BlocksView
|
||||
, blocks = Update.Timeline.setLoading True model.blocks
|
||||
}
|
||||
! [ Command.loadBlocks (List.head model.clients) Nothing ]
|
||||
|
||||
Just MutesRoute ->
|
||||
{ model
|
||||
| currentView = MutesView
|
||||
, mutes = Update.Timeline.setLoading True model.mutes
|
||||
}
|
||||
! [ Command.loadMutes (List.head model.clients) Nothing ]
|
||||
|
||||
Just AccountSelectorRoute ->
|
||||
{ model | currentView = AccountSelectorView, server = "" } ! []
|
||||
|
||||
Just (AccountRoute accountId) ->
|
||||
{ model
|
||||
| currentView = AccountView AccountStatusesView
|
||||
, accountInfo = Update.AccountInfo.empty
|
||||
}
|
||||
! [ Command.loadAccount (List.head model.clients) accountId
|
||||
, Command.loadAccountTimeline (List.head model.clients) accountId Nothing
|
||||
]
|
||||
|
||||
Just (AccountFollowersRoute accountId) ->
|
||||
{ model
|
||||
| currentView = AccountView AccountFollowersView
|
||||
, accountInfo = { accountInfo | followers = Update.Timeline.empty "account-followers" }
|
||||
}
|
||||
! [ Command.loadAccount (List.head model.clients) accountId
|
||||
, Command.loadAccountFollowers (List.head model.clients) accountId Nothing
|
||||
]
|
||||
|
||||
Just (AccountFollowingRoute accountId) ->
|
||||
{ model
|
||||
| currentView = AccountView AccountFollowingView
|
||||
, accountInfo = { accountInfo | following = Update.Timeline.empty "account-following" }
|
||||
}
|
||||
! [ Command.loadAccount (List.head model.clients) accountId
|
||||
, Command.loadAccountFollowing (List.head model.clients) accountId Nothing
|
||||
]
|
||||
|
||||
Just (HashtagRoute hashtag) ->
|
||||
{ model
|
||||
| currentView = HashtagView hashtag
|
||||
, hashtagTimeline = Update.Timeline.setLoading True model.hashtagTimeline
|
||||
}
|
||||
! [ Command.loadHashtagTimeline (List.head model.clients) hashtag Nothing ]
|
||||
|
||||
Just (ThreadRoute id) ->
|
||||
{ model | currentView = ThreadView (Thread Nothing Nothing) }
|
||||
! [ Command.loadThread (List.head model.clients) id ]
|
||||
|
||||
_ ->
|
||||
{ model | currentView = LocalTimelineView } ! []
|
@ -52,21 +52,27 @@ deleteStatusFromCurrentView id model =
|
||||
-- Note: account timeline is already cleaned in deleteStatusFromAllTimelines
|
||||
case model.currentView of
|
||||
ThreadView thread ->
|
||||
if thread.status.id == id then
|
||||
-- the current thread status as been deleted, close it
|
||||
LocalTimelineView
|
||||
else
|
||||
let
|
||||
update statuses =
|
||||
List.filter (\s -> s.id /= id) statuses
|
||||
in
|
||||
ThreadView
|
||||
{ thread
|
||||
| context =
|
||||
{ ancestors = update thread.context.ancestors
|
||||
, descendants = update thread.context.descendants
|
||||
case ( thread.status, thread.context ) of
|
||||
( Just status, Just context ) ->
|
||||
if status.id == id then
|
||||
-- the current thread status as been deleted, close it
|
||||
LocalTimelineView
|
||||
else
|
||||
let
|
||||
update statuses =
|
||||
List.filter (\s -> s.id /= id) statuses
|
||||
in
|
||||
ThreadView
|
||||
{ thread
|
||||
| context =
|
||||
Just <|
|
||||
{ ancestors = update context.ancestors
|
||||
, descendants = update context.descendants
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ ->
|
||||
model.currentView
|
||||
|
||||
currentView ->
|
||||
currentView
|
||||
@ -74,15 +80,22 @@ deleteStatusFromCurrentView id model =
|
||||
|
||||
deleteStatusFromAllTimelines : Int -> Model -> Model
|
||||
deleteStatusFromAllTimelines id model =
|
||||
{ model
|
||||
| homeTimeline = deleteStatus id model.homeTimeline
|
||||
, localTimeline = deleteStatus id model.localTimeline
|
||||
, globalTimeline = deleteStatus id model.globalTimeline
|
||||
, favoriteTimeline = deleteStatus id model.favoriteTimeline
|
||||
, accountTimeline = deleteStatus id model.accountTimeline
|
||||
, notifications = deleteStatusFromNotifications id model.notifications
|
||||
, currentView = deleteStatusFromCurrentView id model
|
||||
}
|
||||
let
|
||||
accountInfo =
|
||||
model.accountInfo
|
||||
|
||||
accountTimeline =
|
||||
deleteStatus id accountInfo.timeline
|
||||
in
|
||||
{ model
|
||||
| homeTimeline = deleteStatus id model.homeTimeline
|
||||
, localTimeline = deleteStatus id model.localTimeline
|
||||
, globalTimeline = deleteStatus id model.globalTimeline
|
||||
, favoriteTimeline = deleteStatus id model.favoriteTimeline
|
||||
, accountInfo = { accountInfo | timeline = accountTimeline }
|
||||
, notifications = deleteStatusFromNotifications id model.notifications
|
||||
, currentView = deleteStatusFromCurrentView id model
|
||||
}
|
||||
|
||||
|
||||
deleteStatusFromNotifications : Int -> Timeline NotificationAggregate -> Timeline NotificationAggregate
|
||||
@ -166,7 +179,16 @@ markAsLoading loading id model =
|
||||
"account-timeline" ->
|
||||
case model.currentView of
|
||||
AccountView account ->
|
||||
{ model | accountTimeline = mark model.accountTimeline }
|
||||
let
|
||||
accountInfo =
|
||||
model.accountInfo
|
||||
in
|
||||
{ model
|
||||
| accountInfo =
|
||||
{ accountInfo
|
||||
| timeline = mark accountInfo.timeline
|
||||
}
|
||||
}
|
||||
|
||||
_ ->
|
||||
model
|
||||
@ -284,12 +306,15 @@ updateWithBoolFlag statusId flag statusUpdater model =
|
||||
Nothing ->
|
||||
notification
|
||||
|
||||
accountInfo =
|
||||
model.accountInfo
|
||||
|
||||
updateTimeline updateEntry timeline =
|
||||
{ timeline | entries = List.map updateEntry timeline.entries }
|
||||
in
|
||||
{ model
|
||||
| homeTimeline = updateTimeline updateStatus model.homeTimeline
|
||||
, accountTimeline = updateTimeline updateStatus model.accountTimeline
|
||||
, accountInfo = { accountInfo | timeline = updateTimeline updateStatus accountInfo.timeline }
|
||||
, localTimeline = updateTimeline updateStatus model.localTimeline
|
||||
, globalTimeline = updateTimeline updateStatus model.globalTimeline
|
||||
, favoriteTimeline = updateTimeline updateStatus model.favoriteTimeline
|
||||
@ -297,13 +322,19 @@ updateWithBoolFlag statusId flag statusUpdater model =
|
||||
, currentView =
|
||||
case model.currentView of
|
||||
ThreadView thread ->
|
||||
ThreadView
|
||||
{ status = updateStatus thread.status
|
||||
, context =
|
||||
{ ancestors = List.map updateStatus thread.context.ancestors
|
||||
, descendants = List.map updateStatus thread.context.descendants
|
||||
}
|
||||
}
|
||||
case ( thread.status, thread.context ) of
|
||||
( Just status, Just context ) ->
|
||||
ThreadView
|
||||
{ status = Just <| updateStatus status
|
||||
, context =
|
||||
Just <|
|
||||
{ ancestors = List.map updateStatus context.ancestors
|
||||
, descendants = List.map updateStatus context.descendants
|
||||
}
|
||||
}
|
||||
|
||||
_ ->
|
||||
model.currentView
|
||||
|
||||
currentView ->
|
||||
currentView
|
||||
|
@ -116,30 +116,38 @@ update msg model =
|
||||
|
||||
isThreadMember : Thread -> Status -> Bool
|
||||
isThreadMember thread status =
|
||||
case status.in_reply_to_id of
|
||||
Nothing ->
|
||||
False
|
||||
case ( thread.status, thread.context ) of
|
||||
( Just status, Just context ) ->
|
||||
case status.in_reply_to_id of
|
||||
Nothing ->
|
||||
False
|
||||
|
||||
Just inReplyToId ->
|
||||
let
|
||||
threadStatusIds =
|
||||
List.concat
|
||||
[ [ thread.status.id ]
|
||||
, List.map .id thread.context.ancestors
|
||||
, List.map .id thread.context.descendants
|
||||
]
|
||||
in
|
||||
List.member inReplyToId threadStatusIds
|
||||
Just inReplyToId ->
|
||||
let
|
||||
threadStatusIds =
|
||||
List.concat
|
||||
[ [ status.id ]
|
||||
, List.map .id context.ancestors
|
||||
, List.map .id context.descendants
|
||||
]
|
||||
in
|
||||
List.member inReplyToId threadStatusIds
|
||||
|
||||
_ ->
|
||||
False
|
||||
|
||||
|
||||
appendToThreadDescendants : Thread -> Status -> Thread
|
||||
appendToThreadDescendants ({ context } as thread) status =
|
||||
{ thread
|
||||
| context =
|
||||
{ context
|
||||
| descendants = List.append thread.context.descendants [ status ]
|
||||
case thread.context of
|
||||
Just context ->
|
||||
{ thread
|
||||
| context =
|
||||
Just { context | descendants = List.append context.descendants [ status ] }
|
||||
}
|
||||
}
|
||||
|
||||
_ ->
|
||||
thread
|
||||
|
||||
|
||||
updateCurrentViewWithStatus : Status -> Model -> Model
|
||||
@ -151,11 +159,25 @@ updateCurrentViewWithStatus status model =
|
||||
else
|
||||
model
|
||||
|
||||
AccountView account ->
|
||||
if Mastodon.Helper.sameAccount account status.account then
|
||||
{ model | accountTimeline = Update.Timeline.prepend status model.accountTimeline }
|
||||
else
|
||||
model
|
||||
AccountView _ ->
|
||||
case model.accountInfo.account of
|
||||
Just account ->
|
||||
if Mastodon.Helper.sameAccount account status.account then
|
||||
let
|
||||
accountInfo =
|
||||
model.accountInfo
|
||||
in
|
||||
{ model
|
||||
| accountInfo =
|
||||
{ accountInfo
|
||||
| timeline = Update.Timeline.prepend status accountInfo.timeline
|
||||
}
|
||||
}
|
||||
else
|
||||
model
|
||||
|
||||
Nothing ->
|
||||
model
|
||||
|
||||
_ ->
|
||||
model
|
||||
|
@ -1,9 +1,4 @@
|
||||
module View.Account
|
||||
exposing
|
||||
( accountFollowView
|
||||
, accountTimelineView
|
||||
, accountView
|
||||
)
|
||||
module View.Account exposing (accountView)
|
||||
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
@ -15,7 +10,6 @@ import Mastodon.Helper
|
||||
import Mastodon.Model exposing (..)
|
||||
import Types exposing (..)
|
||||
import View.Common as Common
|
||||
import View.Events exposing (..)
|
||||
import View.Status exposing (statusEntryView)
|
||||
import View.Formatter exposing (formatContent)
|
||||
|
||||
@ -28,19 +22,6 @@ type alias CurrentUserRelation =
|
||||
Maybe Relationship
|
||||
|
||||
|
||||
accountCounterLink : String -> Int -> (Account -> Msg) -> Account -> Html Msg
|
||||
accountCounterLink label count tagger account =
|
||||
a
|
||||
[ href ""
|
||||
, class "col-md-4"
|
||||
, onClickWithPreventAndStop <| tagger account
|
||||
]
|
||||
[ text label
|
||||
, br [] []
|
||||
, text <| toString count
|
||||
]
|
||||
|
||||
|
||||
followButton : CurrentUser -> CurrentUserRelation -> Account -> Html Msg
|
||||
followButton currentUser relationship account =
|
||||
if Mastodon.Helper.sameAccount account currentUser then
|
||||
@ -81,9 +62,7 @@ followView currentUser relationship account =
|
||||
, div [ class "userinfo" ]
|
||||
[ strong []
|
||||
[ a
|
||||
[ href account.url
|
||||
, onClickWithPreventAndStop <| LoadAccount account.id
|
||||
]
|
||||
[ href <| "#account/" ++ (toString account.id) ]
|
||||
[ text <|
|
||||
if account.display_name /= "" then
|
||||
account.display_name
|
||||
@ -165,35 +144,39 @@ blockButton currentUser relationship account =
|
||||
[ Common.icon iconName ]
|
||||
|
||||
|
||||
accountFollowView :
|
||||
CurrentUser
|
||||
-> Timeline Account
|
||||
-> List Relationship
|
||||
-> CurrentUserRelation
|
||||
-> Account
|
||||
-> Html Msg
|
||||
accountFollowView currentUser timeline relationships relationship account =
|
||||
accountFollowView : CurrentAccountView -> CurrentUser -> AccountInfo -> Html Msg
|
||||
accountFollowView view currentUser accountInfo =
|
||||
let
|
||||
keyedEntry account =
|
||||
( toString account.id
|
||||
, li [ class "list-group-item status" ]
|
||||
[ followView
|
||||
currentUser
|
||||
(find (\r -> r.id == account.id) relationships)
|
||||
(find (\r -> r.id == account.id) accountInfo.relationships)
|
||||
account
|
||||
]
|
||||
)
|
||||
|
||||
timeline =
|
||||
if view == AccountFollowersView then
|
||||
accountInfo.followers
|
||||
else
|
||||
accountInfo.following
|
||||
|
||||
entries =
|
||||
List.map keyedEntry timeline.entries
|
||||
in
|
||||
accountView currentUser account relationship <|
|
||||
Keyed.ul [ class "list-group" ] <|
|
||||
(entries ++ [ ( "load-more", Common.loadMoreBtn timeline ) ])
|
||||
case accountInfo.account of
|
||||
Just account ->
|
||||
Keyed.ul [ class "list-group" ] <|
|
||||
(entries ++ [ ( "load-more", Common.loadMoreBtn timeline ) ])
|
||||
|
||||
Nothing ->
|
||||
text ""
|
||||
|
||||
|
||||
accountTimelineView : CurrentUser -> Timeline Status -> CurrentUserRelation -> Account -> Html Msg
|
||||
accountTimelineView currentUser timeline relationship account =
|
||||
accountTimelineView : CurrentUser -> AccountInfo -> Html Msg
|
||||
accountTimelineView currentUser accountInfo =
|
||||
let
|
||||
keyedEntry status =
|
||||
( toString status.id
|
||||
@ -201,66 +184,115 @@ accountTimelineView currentUser timeline relationship account =
|
||||
)
|
||||
|
||||
entries =
|
||||
List.map keyedEntry timeline.entries
|
||||
List.map keyedEntry accountInfo.timeline.entries
|
||||
in
|
||||
accountView currentUser account relationship <|
|
||||
Keyed.ul [ id timeline.id, class "list-group" ] <|
|
||||
(entries ++ [ ( "load-more", Common.loadMoreBtn timeline ) ])
|
||||
case accountInfo.account of
|
||||
Just account ->
|
||||
Keyed.ul [ id accountInfo.timeline.id, class "list-group" ] <|
|
||||
(entries ++ [ ( "load-more", Common.loadMoreBtn accountInfo.timeline ) ])
|
||||
|
||||
Nothing ->
|
||||
text ""
|
||||
|
||||
|
||||
accountView : CurrentUser -> Account -> CurrentUserRelation -> Html Msg -> Html Msg
|
||||
accountView currentUser account relationship panelContent =
|
||||
counterLink : String -> String -> Int -> Bool -> Html Msg
|
||||
counterLink href_ label count active =
|
||||
a
|
||||
[ href href_
|
||||
, class <|
|
||||
"col-md-4"
|
||||
++ (if active then
|
||||
" active"
|
||||
else
|
||||
""
|
||||
)
|
||||
]
|
||||
[ text label
|
||||
, br [] []
|
||||
, text <| toString count
|
||||
]
|
||||
|
||||
|
||||
counterLinks : CurrentAccountView -> Account -> Html Msg
|
||||
counterLinks subView account =
|
||||
let
|
||||
{ statuses_count, following_count, followers_count } =
|
||||
account
|
||||
in
|
||||
div [ class "col-md-3 column" ]
|
||||
[ div [ class "panel panel-default" ]
|
||||
[ Common.closeablePanelheading "account" "user" "Account" CloseAccount
|
||||
, div [ id "account", class "timeline" ]
|
||||
[ div
|
||||
[ class "account-detail"
|
||||
, style [ ( "background-image", "url('" ++ account.header ++ "')" ) ]
|
||||
]
|
||||
[ div [ class "opacity-layer" ]
|
||||
[ followButton currentUser relationship account
|
||||
, muteButton currentUser relationship account
|
||||
, blockButton currentUser relationship account
|
||||
, Common.accountAvatarLink True account
|
||||
, span [ class "account-display-name" ] [ text account.display_name ]
|
||||
, span [ class "account-username" ]
|
||||
[ Common.accountLink True account
|
||||
, case relationship of
|
||||
Just relationship ->
|
||||
span []
|
||||
[ if relationship.followed_by then
|
||||
span [ class "badge followed-by" ] [ text "Follows you" ]
|
||||
else
|
||||
text ""
|
||||
, text " "
|
||||
, if relationship.muting then
|
||||
span [ class "badge muting" ] [ text "Muted" ]
|
||||
else
|
||||
text ""
|
||||
, text " "
|
||||
, if relationship.blocking then
|
||||
span [ class "badge blocking" ] [ text "Blocked" ]
|
||||
else
|
||||
text ""
|
||||
]
|
||||
div [ class "row account-infos" ]
|
||||
[ counterLink
|
||||
("#account/" ++ (toString account.id))
|
||||
"Statuses"
|
||||
statuses_count
|
||||
(subView == AccountStatusesView)
|
||||
, counterLink
|
||||
("#account/" ++ (toString account.id) ++ "/following")
|
||||
"Following"
|
||||
following_count
|
||||
(subView == AccountFollowingView)
|
||||
, counterLink
|
||||
("#account/" ++ (toString account.id) ++ "/followers")
|
||||
"Followers"
|
||||
followers_count
|
||||
(subView == AccountFollowersView)
|
||||
]
|
||||
|
||||
Nothing ->
|
||||
text ""
|
||||
]
|
||||
, span [ class "account-note" ] (formatContent account.note [])
|
||||
|
||||
accountView : CurrentAccountView -> CurrentUser -> AccountInfo -> Html Msg
|
||||
accountView subView currentUser accountInfo =
|
||||
case accountInfo.account of
|
||||
Nothing ->
|
||||
text ""
|
||||
|
||||
Just account ->
|
||||
div [ class "col-md-3 column" ]
|
||||
[ div [ class "panel panel-default" ]
|
||||
[ Common.closeablePanelheading "account" "user" "Account"
|
||||
, div [ id "account", class "timeline" ]
|
||||
[ div
|
||||
[ class "account-detail"
|
||||
, style [ ( "background-image", "url('" ++ account.header ++ "')" ) ]
|
||||
]
|
||||
[ div [ class "opacity-layer" ]
|
||||
[ followButton currentUser accountInfo.relationship account
|
||||
, muteButton currentUser accountInfo.relationship account
|
||||
, blockButton currentUser accountInfo.relationship account
|
||||
, Common.accountAvatarLink True account
|
||||
, span [ class "account-display-name" ] [ text account.display_name ]
|
||||
, span [ class "account-username" ]
|
||||
[ Common.accountLink True account
|
||||
, case accountInfo.relationship of
|
||||
Just relationship ->
|
||||
span []
|
||||
[ if relationship.followed_by then
|
||||
span [ class "badge followed-by" ] [ text "Follows you" ]
|
||||
else
|
||||
text ""
|
||||
, text " "
|
||||
, if relationship.muting then
|
||||
span [ class "badge muting" ] [ text "Muted" ]
|
||||
else
|
||||
text ""
|
||||
, text " "
|
||||
, if relationship.blocking then
|
||||
span [ class "badge blocking" ] [ text "Blocked" ]
|
||||
else
|
||||
text ""
|
||||
]
|
||||
|
||||
Nothing ->
|
||||
text ""
|
||||
]
|
||||
, span [ class "account-note" ] (formatContent account.note [])
|
||||
]
|
||||
]
|
||||
, counterLinks subView account
|
||||
, case subView of
|
||||
AccountStatusesView ->
|
||||
accountTimelineView currentUser accountInfo
|
||||
|
||||
_ ->
|
||||
accountFollowView subView currentUser accountInfo
|
||||
]
|
||||
, div [ class "row account-infos" ]
|
||||
[ accountCounterLink "Statuses" statuses_count ViewAccountStatuses account
|
||||
, accountCounterLink "Following" following_count ViewAccountFollowing account
|
||||
, accountCounterLink "Followers" followers_count ViewAccountFollowers account
|
||||
]
|
||||
, panelContent
|
||||
]
|
||||
]
|
||||
]
|
||||
|
@ -80,8 +80,8 @@ accountSelectorView : Model -> Html Msg
|
||||
accountSelectorView model =
|
||||
div [ class "col-md-3 column" ]
|
||||
[ div [ class "panel panel-default" ]
|
||||
[ closeablePanelheading "account-selector" "user" "Account selector" (SetView LocalTimelineView)
|
||||
, contextualTimelineMenu model.currentView
|
||||
[ div [] [ div [ class "panel-heading" ] [ icon "user", text "Accounts" ] ]
|
||||
, contextualTimelineMenu model.location.hash
|
||||
, ul [ class "list-group " ] <|
|
||||
List.map (accountIdentityView model.currentUser) model.clients
|
||||
, div [ class "panel-body" ]
|
||||
|
@ -5,7 +5,7 @@ import Html.Attributes exposing (..)
|
||||
import Html.Lazy as Lazy
|
||||
import Mastodon.Model exposing (..)
|
||||
import Types exposing (..)
|
||||
import View.Account exposing (accountFollowView, accountTimelineView)
|
||||
import View.Account exposing (accountView)
|
||||
import View.AccountSelector exposing (accountSelectorView)
|
||||
import View.Auth exposing (authView)
|
||||
import View.Blocks exposing (blocksView)
|
||||
@ -54,12 +54,8 @@ homepageView model =
|
||||
model.notificationFilter
|
||||
model.notifications
|
||||
, case model.currentView of
|
||||
AccountView account ->
|
||||
accountTimelineView
|
||||
currentUser
|
||||
model.accountTimeline
|
||||
model.accountRelationship
|
||||
account
|
||||
AccountView subView ->
|
||||
accountView subView currentUser model.accountInfo
|
||||
|
||||
AccountSelectorView ->
|
||||
accountSelectorView model
|
||||
@ -70,28 +66,12 @@ homepageView model =
|
||||
BlocksView ->
|
||||
blocksView model
|
||||
|
||||
AccountFollowersView account followers ->
|
||||
accountFollowView
|
||||
currentUser
|
||||
model.accountFollowers
|
||||
model.accountRelationships
|
||||
model.accountRelationship
|
||||
account
|
||||
|
||||
AccountFollowingView account following ->
|
||||
accountFollowView
|
||||
currentUser
|
||||
model.accountFollowing
|
||||
model.accountRelationships
|
||||
model.accountRelationship
|
||||
account
|
||||
|
||||
ThreadView thread ->
|
||||
threadView currentUser thread
|
||||
|
||||
LocalTimelineView ->
|
||||
contextualTimelineView
|
||||
LocalTimelineView
|
||||
model.location.hash
|
||||
"Local timeline"
|
||||
"th-large"
|
||||
currentUser
|
||||
@ -99,7 +79,7 @@ homepageView model =
|
||||
|
||||
GlobalTimelineView ->
|
||||
contextualTimelineView
|
||||
GlobalTimelineView
|
||||
model.location.hash
|
||||
"Global timeline"
|
||||
"globe"
|
||||
currentUser
|
||||
@ -107,7 +87,7 @@ homepageView model =
|
||||
|
||||
FavoriteTimelineView ->
|
||||
contextualTimelineView
|
||||
FavoriteTimelineView
|
||||
model.location.hash
|
||||
"Favorites"
|
||||
"star"
|
||||
currentUser
|
||||
@ -115,7 +95,7 @@ homepageView model =
|
||||
|
||||
HashtagView hashtag ->
|
||||
contextualTimelineView
|
||||
(HashtagView hashtag)
|
||||
model.location.hash
|
||||
("#" ++ hashtag)
|
||||
"tags"
|
||||
currentUser
|
||||
|
@ -8,8 +8,7 @@ import Mastodon.Helper exposing (..)
|
||||
import Mastodon.Model exposing (..)
|
||||
import Types exposing (..)
|
||||
import View.Common as Common
|
||||
import View.Events exposing (..)
|
||||
import View.Timeline exposing (contextualTimelineMenu)
|
||||
import View.Timeline exposing (contextualTimelineMenu, topScrollableColumn)
|
||||
|
||||
|
||||
type alias CurrentUser =
|
||||
@ -36,9 +35,7 @@ blockView currentUser account =
|
||||
, div [ class "userinfo" ]
|
||||
[ strong []
|
||||
[ a
|
||||
[ href account.url
|
||||
, onClickWithPreventAndStop <| LoadAccount account.id
|
||||
]
|
||||
[ href <| "#account/" ++ (toString account.id) ]
|
||||
[ text <|
|
||||
if account.display_name /= "" then
|
||||
account.display_name
|
||||
@ -60,24 +57,22 @@ blockView currentUser account =
|
||||
|
||||
|
||||
blocksView : Model -> Html Msg
|
||||
blocksView model =
|
||||
blocksView { currentUser, currentView, blocks, location } =
|
||||
let
|
||||
keyedEntry account =
|
||||
( toString account.id
|
||||
, blockView model.currentUser account
|
||||
, blockView currentUser account
|
||||
)
|
||||
|
||||
entries =
|
||||
List.map keyedEntry model.blocks.entries
|
||||
List.map keyedEntry blocks.entries
|
||||
in
|
||||
div [ class "col-md-3 column" ]
|
||||
[ div [ class "panel panel-default" ]
|
||||
[ Common.closeablePanelheading "blocks-timeline" "ban-circle" "Blocked accounts" (SetView LocalTimelineView)
|
||||
, contextualTimelineMenu model.currentView
|
||||
, if List.length model.blocks.entries == 0 then
|
||||
p [ class "empty-timeline-text" ] [ text "Nobody's muted here." ]
|
||||
topScrollableColumn ( "Blocks", "ban-circle", blocks.id ) <|
|
||||
div []
|
||||
[ contextualTimelineMenu location.hash
|
||||
, if (not blocks.loading && List.length blocks.entries == 0) then
|
||||
p [ class "empty-timeline-text" ] [ text "Nobody's blocked yet." ]
|
||||
else
|
||||
Keyed.ul [ id "blocks-timeline", class "list-group timeline" ] <|
|
||||
(entries ++ [ ( "load-more", Common.loadMoreBtn model.blocks ) ])
|
||||
(entries ++ [ ( "load-more", Common.loadMoreBtn blocks ) ])
|
||||
]
|
||||
]
|
||||
|
@ -32,7 +32,7 @@ accountLink external account =
|
||||
if external then
|
||||
target "_blank"
|
||||
else
|
||||
onClickWithPreventAndStop (LoadAccount account.id)
|
||||
href <| "#account/" ++ (toString account.id)
|
||||
in
|
||||
a
|
||||
[ href account.url
|
||||
@ -48,7 +48,7 @@ accountAvatarLink external account =
|
||||
if external then
|
||||
target "_blank"
|
||||
else
|
||||
onClickWithPreventAndStop (LoadAccount account.id)
|
||||
href <| "#account/" ++ (toString account.id)
|
||||
|
||||
avatarClass =
|
||||
if external then
|
||||
@ -79,8 +79,8 @@ appLink classes app =
|
||||
a [ href website, target "_blank", class classes ] [ text name ]
|
||||
|
||||
|
||||
closeablePanelheading : String -> String -> String -> Msg -> Html Msg
|
||||
closeablePanelheading context iconName label onClose =
|
||||
closeablePanelheading : String -> String -> String -> Html Msg
|
||||
closeablePanelheading context iconName label =
|
||||
div [ class "panel-heading" ]
|
||||
[ div [ class "row" ]
|
||||
[ a
|
||||
@ -88,7 +88,7 @@ closeablePanelheading context iconName label onClose =
|
||||
[ div [ class "col-xs-9 heading" ] [ icon iconName, text label ] ]
|
||||
, div [ class "col-xs-3 text-right" ]
|
||||
[ a
|
||||
[ href "", onClickWithPreventAndStop onClose ]
|
||||
[ href "", onClickWithPreventAndStop Back ]
|
||||
[ icon "remove" ]
|
||||
]
|
||||
]
|
||||
|
@ -81,8 +81,7 @@ currentUserView currentUser =
|
||||
[ Common.accountLink False currentUser
|
||||
, span []
|
||||
[ text " ("
|
||||
, a [ href "", onClickWithPreventAndStop <| SetView AccountSelectorView ]
|
||||
[ text "switch account" ]
|
||||
, a [ href "#accounts" ] [ text "switch account" ]
|
||||
, text ")"
|
||||
]
|
||||
]
|
||||
|
@ -29,23 +29,26 @@ toVirtualDom mentions nodes =
|
||||
List.map (toVirtualDomEach mentions) nodes
|
||||
|
||||
|
||||
replaceHref : String -> List ( String, String ) -> List (Attribute Msg)
|
||||
replaceHref newHref attrs =
|
||||
attrs
|
||||
|> List.map toAttribute
|
||||
|> List.append [ onClickWithPreventAndStop <| Navigate newHref ]
|
||||
|
||||
|
||||
createLinkNode : List ( String, String ) -> List HtmlParser.Node -> List Mention -> Html Msg
|
||||
createLinkNode attrs children mentions =
|
||||
case (getMentionForLink attrs mentions) of
|
||||
Just mention ->
|
||||
Html.node "a"
|
||||
((List.map toAttribute attrs)
|
||||
++ [ onClickWithPreventAndStop (LoadAccount mention.id) ]
|
||||
)
|
||||
(replaceHref ("#account/" ++ (toString mention.id)) attrs)
|
||||
(toVirtualDom mentions children)
|
||||
|
||||
Nothing ->
|
||||
case getHashtagForLink attrs of
|
||||
Just hashtag ->
|
||||
Html.node "a"
|
||||
((List.map toAttribute attrs)
|
||||
++ [ onClickWithPreventAndStop (SetView (HashtagView hashtag)) ]
|
||||
)
|
||||
(replaceHref ("#hashtag/" ++ hashtag) attrs)
|
||||
(toVirtualDom mentions children)
|
||||
|
||||
Nothing ->
|
||||
|
@ -8,8 +8,7 @@ import Mastodon.Helper exposing (..)
|
||||
import Mastodon.Model exposing (..)
|
||||
import Types exposing (..)
|
||||
import View.Common as Common
|
||||
import View.Events exposing (..)
|
||||
import View.Timeline exposing (contextualTimelineMenu)
|
||||
import View.Timeline exposing (contextualTimelineMenu, topScrollableColumn)
|
||||
|
||||
|
||||
type alias CurrentUser =
|
||||
@ -36,9 +35,7 @@ muteView currentUser account =
|
||||
, div [ class "userinfo" ]
|
||||
[ strong []
|
||||
[ a
|
||||
[ href account.url
|
||||
, onClickWithPreventAndStop <| LoadAccount account.id
|
||||
]
|
||||
[ href <| "#account/" ++ (toString account.id) ]
|
||||
[ text <|
|
||||
if account.display_name /= "" then
|
||||
account.display_name
|
||||
@ -60,24 +57,22 @@ muteView currentUser account =
|
||||
|
||||
|
||||
mutesView : Model -> Html Msg
|
||||
mutesView model =
|
||||
mutesView { currentUser, currentView, mutes, location } =
|
||||
let
|
||||
keyedEntry account =
|
||||
( toString account.id
|
||||
, muteView model.currentUser account
|
||||
, muteView currentUser account
|
||||
)
|
||||
|
||||
entries =
|
||||
List.map keyedEntry model.mutes.entries
|
||||
List.map keyedEntry mutes.entries
|
||||
in
|
||||
div [ class "col-md-3 column" ]
|
||||
[ div [ class "panel panel-default" ]
|
||||
[ Common.closeablePanelheading "mutes-timeline" "volume-off" "Muted accounts" (SetView LocalTimelineView)
|
||||
, contextualTimelineMenu model.currentView
|
||||
, if (not model.mutes.loading && List.length model.mutes.entries == 0) then
|
||||
p [ class "empty-timeline-text" ] [ text "Nobody's blocked here." ]
|
||||
topScrollableColumn ( "Mutes", "volume-off", mutes.id ) <|
|
||||
div []
|
||||
[ contextualTimelineMenu location.hash
|
||||
, if (not mutes.loading && List.length mutes.entries == 0) then
|
||||
p [ class "empty-timeline-text" ] [ text "Nobody's muted yet." ]
|
||||
else
|
||||
Keyed.ul [ id "mutes-timeline", class "list-group timeline" ] <|
|
||||
(entries ++ [ ( "load-more", Common.loadMoreBtn model.mutes ) ])
|
||||
(entries ++ [ ( "load-more", Common.loadMoreBtn mutes ) ])
|
||||
]
|
||||
]
|
||||
|
@ -112,7 +112,7 @@ notificationFollowView currentUser { accounts } =
|
||||
, div [ class "username" ] [ Common.accountLink False account ]
|
||||
, p
|
||||
[ class "status-text"
|
||||
, onClick <| LoadAccount account.id
|
||||
, onClick <| Navigate ("#account/" ++ (toString account.id))
|
||||
]
|
||||
<|
|
||||
formatContent account.note []
|
||||
|
@ -159,8 +159,8 @@ statusContentView : String -> Status -> Html Msg
|
||||
statusContentView context status =
|
||||
case status.spoiler_text of
|
||||
"" ->
|
||||
div [ class "status-text", onClickWithStop <| OpenThread status ]
|
||||
[ div [] <| formatContent status.content status.mentions
|
||||
div [ class "status-text" ]
|
||||
[ div [ onClickWithStop <| OpenThread status ] <| formatContent status.content status.mentions
|
||||
, attachmentListView context status
|
||||
]
|
||||
|
||||
@ -213,9 +213,7 @@ statusView : String -> Status -> Html Msg
|
||||
statusView context ({ account, content, media_attachments, reblog, mentions } as status) =
|
||||
let
|
||||
accountLinkAttributes =
|
||||
[ href account.url
|
||||
, onClickWithPreventAndStop (LoadAccount account.id)
|
||||
]
|
||||
[ href <| "#account/" ++ (toString account.id) ]
|
||||
in
|
||||
case reblog of
|
||||
Just (Reblog reblog) ->
|
||||
|
@ -13,33 +13,43 @@ type alias CurrentUser =
|
||||
Account
|
||||
|
||||
|
||||
threadStatuses : CurrentUser -> Thread -> Html Msg
|
||||
threadStatuses currentUser thread =
|
||||
case ( thread.status, thread.context ) of
|
||||
( Just threadStatus, Just context ) ->
|
||||
let
|
||||
statuses =
|
||||
List.concat
|
||||
[ context.ancestors
|
||||
, [ threadStatus ]
|
||||
, context.descendants
|
||||
]
|
||||
|
||||
threadEntry status =
|
||||
statusEntryView "thread"
|
||||
(if status == threadStatus then
|
||||
"thread-target"
|
||||
else
|
||||
""
|
||||
)
|
||||
currentUser
|
||||
status
|
||||
|
||||
keyedEntry status =
|
||||
( toString status.id, threadEntry status )
|
||||
in
|
||||
Keyed.ul [ id "thread", class "list-group timeline" ] <|
|
||||
List.map keyedEntry statuses
|
||||
|
||||
_ ->
|
||||
text ""
|
||||
|
||||
|
||||
threadView : CurrentUser -> Thread -> Html Msg
|
||||
threadView currentUser thread =
|
||||
let
|
||||
statuses =
|
||||
List.concat
|
||||
[ thread.context.ancestors
|
||||
, [ thread.status ]
|
||||
, thread.context.descendants
|
||||
]
|
||||
|
||||
threadEntry status =
|
||||
statusEntryView "thread"
|
||||
(if status == thread.status then
|
||||
"thread-target"
|
||||
else
|
||||
""
|
||||
)
|
||||
currentUser
|
||||
status
|
||||
|
||||
keyedEntry status =
|
||||
( toString status.id, threadEntry status )
|
||||
in
|
||||
div [ class "col-md-3 column" ]
|
||||
[ div [ class "panel panel-default" ]
|
||||
[ Common.closeablePanelheading "thread" "list" "Thread" CloseThread
|
||||
, Keyed.ul [ id "thread", class "list-group timeline" ] <|
|
||||
List.map keyedEntry statuses
|
||||
]
|
||||
div [ class "col-md-3 column" ]
|
||||
[ div [ class "panel panel-default" ]
|
||||
[ Common.closeablePanelheading "thread" "list" "Thread"
|
||||
, threadStatuses currentUser thread
|
||||
]
|
||||
]
|
||||
|
@ -3,11 +3,11 @@ module View.Timeline
|
||||
( contextualTimelineView
|
||||
, contextualTimelineMenu
|
||||
, homeTimelineView
|
||||
, topScrollableColumn
|
||||
)
|
||||
|
||||
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 (..)
|
||||
@ -60,37 +60,37 @@ homeTimelineView currentUser timeline =
|
||||
(timelineView currentUser timeline)
|
||||
|
||||
|
||||
contextualTimelineMenu : CurrentView -> Html Msg
|
||||
contextualTimelineMenu currentView =
|
||||
contextualTimelineMenu : String -> Html Msg
|
||||
contextualTimelineMenu hash =
|
||||
let
|
||||
btnView tooltip iconName view =
|
||||
button
|
||||
[ class <|
|
||||
btnView href_ iconName tooltip =
|
||||
a
|
||||
[ href href_
|
||||
, class <|
|
||||
"btn "
|
||||
++ (if currentView == view then
|
||||
++ (if hash == href_ || (hash == "" && href_ == "#") then
|
||||
"btn-primary active"
|
||||
else
|
||||
"btn-default"
|
||||
)
|
||||
, onClick <| SetView view
|
||||
, Html.Attributes.title tooltip
|
||||
, title tooltip
|
||||
]
|
||||
[ Common.icon iconName ]
|
||||
in
|
||||
Common.justifiedButtonGroup "column-menu"
|
||||
[ btnView "Local timeline" "th-large" LocalTimelineView
|
||||
, btnView "Global timeline" "globe" GlobalTimelineView
|
||||
, btnView "Favorites" "star" FavoriteTimelineView
|
||||
, btnView "Blocks" "ban-circle" BlocksView
|
||||
, btnView "Mutes" "volume-off" MutesView
|
||||
, btnView "Accounts" "user" AccountSelectorView
|
||||
[ btnView "#" "th-large" "Local timeline"
|
||||
, btnView "#global" "globe" "Global timeline"
|
||||
, btnView "#favorites" "star" "Favorites"
|
||||
, btnView "#blocks" "ban-circle" "Blocks"
|
||||
, btnView "#mutes" "volume-off" "Mutes"
|
||||
, btnView "#accounts" "user" "Accounts"
|
||||
]
|
||||
|
||||
|
||||
contextualTimelineView : CurrentView -> String -> String -> CurrentUser -> Timeline Status -> Html Msg
|
||||
contextualTimelineView currentView title iconName currentUser timeline =
|
||||
contextualTimelineView : String -> String -> String -> CurrentUser -> Timeline Status -> Html Msg
|
||||
contextualTimelineView hash title iconName currentUser timeline =
|
||||
div []
|
||||
[ contextualTimelineMenu currentView
|
||||
[ contextualTimelineMenu hash
|
||||
, timelineView currentUser timeline
|
||||
]
|
||||
|> Lazy.lazy2 topScrollableColumn ( title, iconName, timeline.id )
|
||||
|
Loading…
Reference in New Issue
Block a user