parent
868490abab
commit
dfc0362242
|
@ -62,19 +62,30 @@ body {
|
|||
.timeline {
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
max-height: calc(100vh - 45px);
|
||||
max-height: calc(100vh - 44px);
|
||||
overflow: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.timeline > .list-group-item {
|
||||
.timeline .list-group-item {
|
||||
padding: 8px 12px;
|
||||
}
|
||||
|
||||
.empty-timeline-text {
|
||||
font-size: 30px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
line-height: 35px;
|
||||
opacity: .5;
|
||||
padding: 100px 20px;
|
||||
}
|
||||
|
||||
#blocks-timeline,
|
||||
#favorite-timeline,
|
||||
#global-timeline,
|
||||
#local-timeline,
|
||||
#global-timeline {
|
||||
max-height: calc(100vh - 80px);
|
||||
#mutes-timeline {
|
||||
max-height: calc(100vh - 81px);
|
||||
}
|
||||
|
||||
|
||||
|
@ -83,7 +94,7 @@ li.load-more {
|
|||
}
|
||||
|
||||
.notifications-panel .timeline {
|
||||
max-height: calc(100vh - 80px);
|
||||
max-height: calc(100vh - 81px);
|
||||
}
|
||||
|
||||
.panel a {
|
||||
|
@ -223,8 +234,9 @@ span.applink {
|
|||
order: 0;
|
||||
flex: 0 1 auto;
|
||||
align-self: auto;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.acct {
|
||||
|
@ -618,7 +630,7 @@ input.form-control[type=file] {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
.account-detail .opacity-layer{
|
||||
.account-detail .opacity-layer {
|
||||
background: rgba(49,53,67,0.9);
|
||||
}
|
||||
|
||||
|
@ -631,13 +643,21 @@ input.form-control[type=file] {
|
|||
|
||||
.account-detail .btn {
|
||||
position: absolute;
|
||||
top: 1em;
|
||||
left: 1em;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
opacity: .8;
|
||||
}
|
||||
|
||||
.account-detail .btn-mute {
|
||||
top: 54px;
|
||||
}
|
||||
|
||||
.account-detail .btn-block {
|
||||
top: 98px;
|
||||
}
|
||||
|
||||
.account-detail .account-display-name {
|
||||
display: block;
|
||||
font-size: 130%;
|
||||
|
|
|
@ -15,6 +15,8 @@ module Command
|
|||
, loadGlobalTimeline
|
||||
, loadAccountTimeline
|
||||
, loadFavoriteTimeline
|
||||
, loadMutes
|
||||
, loadBlocks
|
||||
, loadNextTimeline
|
||||
, loadRelationships
|
||||
, loadThread
|
||||
|
@ -28,6 +30,10 @@ module Command
|
|||
, unfavouriteStatus
|
||||
, follow
|
||||
, unfollow
|
||||
, mute
|
||||
, unmute
|
||||
, block
|
||||
, unblock
|
||||
, uploadMedia
|
||||
, focusId
|
||||
, scrollColumnToTop
|
||||
|
@ -332,6 +338,34 @@ loadFavoriteTimeline client url =
|
|||
Cmd.none
|
||||
|
||||
|
||||
loadMutes : Maybe Client -> Maybe String -> Cmd Msg
|
||||
loadMutes client url =
|
||||
case client of
|
||||
Just client ->
|
||||
HttpBuilder.get (Maybe.withDefault ApiUrl.mutes url)
|
||||
|> withClient client
|
||||
|> withBodyDecoder (Decode.list accountDecoder)
|
||||
|> withQueryParams [ ( "limit", "60" ) ]
|
||||
|> send (MastodonEvent << Mutes (url /= Nothing))
|
||||
|
||||
Nothing ->
|
||||
Cmd.none
|
||||
|
||||
|
||||
loadBlocks : Maybe Client -> Maybe String -> Cmd Msg
|
||||
loadBlocks client url =
|
||||
case client of
|
||||
Just client ->
|
||||
HttpBuilder.get (Maybe.withDefault ApiUrl.blocks url)
|
||||
|> withClient client
|
||||
|> withBodyDecoder (Decode.list accountDecoder)
|
||||
|> withQueryParams [ ( "limit", "60" ) ]
|
||||
|> send (MastodonEvent << Blocks (url /= Nothing))
|
||||
|
||||
Nothing ->
|
||||
Cmd.none
|
||||
|
||||
|
||||
loadTimelines : Maybe Client -> Cmd Msg
|
||||
loadTimelines client =
|
||||
Cmd.batch
|
||||
|
@ -498,6 +532,58 @@ unfollow client account =
|
|||
Cmd.none
|
||||
|
||||
|
||||
mute : Maybe Client -> Account -> Cmd Msg
|
||||
mute client account =
|
||||
case client of
|
||||
Just client ->
|
||||
HttpBuilder.post (ApiUrl.mute account.id)
|
||||
|> withClient client
|
||||
|> withBodyDecoder relationshipDecoder
|
||||
|> send (MastodonEvent << (AccountMuted account))
|
||||
|
||||
Nothing ->
|
||||
Cmd.none
|
||||
|
||||
|
||||
unmute : Maybe Client -> Account -> Cmd Msg
|
||||
unmute client account =
|
||||
case client of
|
||||
Just client ->
|
||||
HttpBuilder.post (ApiUrl.unmute account.id)
|
||||
|> withClient client
|
||||
|> withBodyDecoder relationshipDecoder
|
||||
|> send (MastodonEvent << (AccountUnmuted account))
|
||||
|
||||
Nothing ->
|
||||
Cmd.none
|
||||
|
||||
|
||||
block : Maybe Client -> Account -> Cmd Msg
|
||||
block client account =
|
||||
case client of
|
||||
Just client ->
|
||||
HttpBuilder.post (ApiUrl.block account.id)
|
||||
|> withClient client
|
||||
|> withBodyDecoder relationshipDecoder
|
||||
|> send (MastodonEvent << (AccountBlocked account))
|
||||
|
||||
Nothing ->
|
||||
Cmd.none
|
||||
|
||||
|
||||
unblock : Maybe Client -> Account -> Cmd Msg
|
||||
unblock client account =
|
||||
case client of
|
||||
Just client ->
|
||||
HttpBuilder.post (ApiUrl.unblock account.id)
|
||||
|> withClient client
|
||||
|> withBodyDecoder relationshipDecoder
|
||||
|> send (MastodonEvent << (AccountUnblocked account))
|
||||
|
||||
Nothing ->
|
||||
Cmd.none
|
||||
|
||||
|
||||
uploadMedia : Maybe Client -> String -> Cmd Msg
|
||||
uploadMedia client fileInputId =
|
||||
case client of
|
||||
|
|
|
@ -18,6 +18,8 @@ init { registration, clients } location =
|
|||
, localTimeline = Update.Timeline.empty "local-timeline"
|
||||
, globalTimeline = Update.Timeline.empty "global-timeline"
|
||||
, favoriteTimeline = Update.Timeline.empty "favorite-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"
|
||||
|
|
|
@ -12,6 +12,8 @@ module Mastodon.ApiUrl
|
|||
, homeTimeline
|
||||
, publicTimeline
|
||||
, favouriteTimeline
|
||||
, mutes
|
||||
, blocks
|
||||
, notifications
|
||||
, relationships
|
||||
, statuses
|
||||
|
@ -22,6 +24,10 @@ module Mastodon.ApiUrl
|
|||
, unfavourite
|
||||
, follow
|
||||
, unfollow
|
||||
, mute
|
||||
, unmute
|
||||
, block
|
||||
, unblock
|
||||
, uploadMedia
|
||||
, streaming
|
||||
, searchAccount
|
||||
|
@ -68,6 +74,26 @@ unfollow id =
|
|||
accounts ++ (toString id) ++ "/unfollow"
|
||||
|
||||
|
||||
mute : Int -> String
|
||||
mute id =
|
||||
accounts ++ (toString id) ++ "/mute"
|
||||
|
||||
|
||||
unmute : Int -> String
|
||||
unmute id =
|
||||
accounts ++ (toString id) ++ "/unmute"
|
||||
|
||||
|
||||
block : Int -> String
|
||||
block id =
|
||||
accounts ++ (toString id) ++ "/block"
|
||||
|
||||
|
||||
unblock : Int -> String
|
||||
unblock id =
|
||||
accounts ++ (toString id) ++ "/unblock"
|
||||
|
||||
|
||||
userAccount : String
|
||||
userAccount =
|
||||
accounts ++ "verify_credentials"
|
||||
|
@ -113,6 +139,16 @@ favouriteTimeline =
|
|||
apiPrefix ++ "/favourites"
|
||||
|
||||
|
||||
mutes : String
|
||||
mutes =
|
||||
apiPrefix ++ "/mutes"
|
||||
|
||||
|
||||
blocks : String
|
||||
blocks =
|
||||
apiPrefix ++ "/blocks"
|
||||
|
||||
|
||||
notifications : String
|
||||
notifications =
|
||||
apiPrefix ++ "/notifications"
|
||||
|
|
|
@ -45,13 +45,18 @@ type MastodonMsg
|
|||
| AccountFollowed Account (MastodonResult Relationship)
|
||||
| AccountFollowers Bool (MastodonResult (List Account))
|
||||
| AccountFollowing Bool (MastodonResult (List Account))
|
||||
| AccountBlocked Account (MastodonResult Relationship)
|
||||
| AccountMuted Account (MastodonResult Relationship)
|
||||
| AccountReceived (MastodonResult Account)
|
||||
| AccountRelationship (MastodonResult (List Relationship))
|
||||
| AccountRelationships (MastodonResult (List Relationship))
|
||||
| AccountTimeline Bool (MastodonResult (List Status))
|
||||
| AccountUnfollowed Account (MastodonResult Relationship)
|
||||
| AccountUnblocked Account (MastodonResult Relationship)
|
||||
| AccountUnmuted Account (MastodonResult Relationship)
|
||||
| AppRegistered (MastodonResult AppRegistration)
|
||||
| AutoSearch (MastodonResult (List Account))
|
||||
| Blocks Bool (MastodonResult (List Account))
|
||||
| ContextLoaded Status (MastodonResult Context)
|
||||
| CurrentUser (MastodonResult Account)
|
||||
| FavoriteAdded (MastodonResult Status)
|
||||
|
@ -60,6 +65,7 @@ type MastodonMsg
|
|||
| GlobalTimeline Bool (MastodonResult (List Status))
|
||||
| HomeTimeline Bool (MastodonResult (List Status))
|
||||
| LocalTimeline Bool (MastodonResult (List Status))
|
||||
| Mutes Bool (MastodonResult (List Account))
|
||||
| Notifications Bool (MastodonResult (List Notification))
|
||||
| Reblogged (MastodonResult Status)
|
||||
| StatusDeleted (MastodonResult Int)
|
||||
|
@ -76,9 +82,9 @@ type WebSocketMsg
|
|||
type Msg
|
||||
= AddFavorite Status
|
||||
| AskConfirm String Msg Msg
|
||||
| Block Account
|
||||
| ClearError Int
|
||||
| CloseAccount
|
||||
| CloseAccountSelector
|
||||
| CloseThread
|
||||
| ConfirmCancelled Msg
|
||||
| Confirmed Msg
|
||||
|
@ -90,6 +96,7 @@ type Msg
|
|||
| LogoutClient Client
|
||||
| TimelineLoadNext String String
|
||||
| MastodonEvent MastodonMsg
|
||||
| Mute Account
|
||||
| NoOp
|
||||
| OpenThread Status
|
||||
| ReblogStatus Status
|
||||
|
@ -102,8 +109,10 @@ type Msg
|
|||
| SwitchClient Client
|
||||
| Tick Time
|
||||
| UnfollowAccount Account
|
||||
| UrlChange Navigation.Location
|
||||
| Unblock Account
|
||||
| Unmute Account
|
||||
| UnreblogStatus Status
|
||||
| UrlChange Navigation.Location
|
||||
| ViewAccountFollowing Account
|
||||
| ViewAccountFollowers Account
|
||||
| ViewAccountStatuses Account
|
||||
|
@ -124,9 +133,11 @@ type CurrentView
|
|||
| AccountFollowingView Account (Timeline Account)
|
||||
| AccountView Account
|
||||
| AccountSelectorView
|
||||
| BlocksView
|
||||
| FavoriteTimelineView
|
||||
| GlobalTimelineView
|
||||
| LocalTimelineView
|
||||
| MutesView
|
||||
| ThreadView Thread
|
||||
|
||||
|
||||
|
@ -200,6 +211,8 @@ type alias Model =
|
|||
, localTimeline : Timeline Status
|
||||
, globalTimeline : Timeline Status
|
||||
, favoriteTimeline : Timeline Status
|
||||
, mutes : Timeline Account
|
||||
, blocks : Timeline Account
|
||||
, accountTimeline : Timeline Status
|
||||
, accountFollowers : Timeline Account
|
||||
, accountFollowing : Timeline Account
|
||||
|
|
|
@ -60,9 +60,26 @@ update msg model =
|
|||
{ model | currentView = view, server = "" } ! []
|
||||
|
||||
FavoriteTimelineView ->
|
||||
{ model | currentView = view }
|
||||
{ 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 ]
|
||||
|
||||
_ ->
|
||||
{ model | currentView = view } ! []
|
||||
|
||||
|
@ -141,6 +158,18 @@ update msg model =
|
|||
UnfollowAccount account ->
|
||||
model ! [ Command.unfollow (List.head model.clients) account ]
|
||||
|
||||
Mute account ->
|
||||
model ! [ Command.mute (List.head model.clients) account ]
|
||||
|
||||
Unmute account ->
|
||||
model ! [ Command.unmute (List.head model.clients) account ]
|
||||
|
||||
Block account ->
|
||||
model ! [ Command.block (List.head model.clients) account ]
|
||||
|
||||
Unblock account ->
|
||||
model ! [ Command.unblock (List.head model.clients) account ]
|
||||
|
||||
DeleteStatus id ->
|
||||
model ! [ Command.deleteStatus (List.head model.clients) id ]
|
||||
|
||||
|
@ -221,9 +250,6 @@ update msg model =
|
|||
}
|
||||
! []
|
||||
|
||||
CloseAccountSelector ->
|
||||
{ model | currentView = LocalTimelineView } ! []
|
||||
|
||||
FilterNotifications filter ->
|
||||
{ model | notificationFilter = filter } ! []
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ update msg model =
|
|||
AccountFollowed _ result ->
|
||||
case result of
|
||||
Ok { decoded } ->
|
||||
processFollowEvent decoded True model ! []
|
||||
processFollowEvent decoded model ! []
|
||||
|
||||
Err error ->
|
||||
{ model | errors = addErrorNotification (errorText error) model } ! []
|
||||
|
@ -63,6 +63,38 @@ update msg model =
|
|||
Err error ->
|
||||
{ model | errors = addErrorNotification (errorText error) model } ! []
|
||||
|
||||
AccountMuted account result ->
|
||||
case result of
|
||||
Ok { decoded } ->
|
||||
processMuteEvent account decoded model ! []
|
||||
|
||||
Err error ->
|
||||
{ model | errors = addErrorNotification (errorText error) model } ! []
|
||||
|
||||
AccountUnmuted account result ->
|
||||
case result of
|
||||
Ok { decoded } ->
|
||||
processMuteEvent account decoded model ! []
|
||||
|
||||
Err error ->
|
||||
{ model | errors = addErrorNotification (errorText error) model } ! []
|
||||
|
||||
AccountBlocked account result ->
|
||||
case result of
|
||||
Ok { decoded } ->
|
||||
processBlockEvent account decoded model ! []
|
||||
|
||||
Err error ->
|
||||
{ model | errors = addErrorNotification (errorText error) model } ! []
|
||||
|
||||
AccountUnblocked account result ->
|
||||
case result of
|
||||
Ok { decoded } ->
|
||||
processBlockEvent account decoded model ! []
|
||||
|
||||
Err error ->
|
||||
{ model | errors = addErrorNotification (errorText error) model } ! []
|
||||
|
||||
AppRegistered result ->
|
||||
case result of
|
||||
Ok { decoded } ->
|
||||
|
@ -157,6 +189,22 @@ update msg model =
|
|||
Err error ->
|
||||
{ model | errors = addErrorNotification (errorText error) model } ! []
|
||||
|
||||
Mutes append result ->
|
||||
case result of
|
||||
Ok { decoded, links } ->
|
||||
{ model | mutes = Update.Timeline.update append decoded links model.mutes } ! []
|
||||
|
||||
Err error ->
|
||||
{ model | errors = addErrorNotification (errorText error) model } ! []
|
||||
|
||||
Blocks append result ->
|
||||
case result of
|
||||
Ok { decoded, links } ->
|
||||
{ model | blocks = Update.Timeline.update append decoded links model.blocks } ! []
|
||||
|
||||
Err error ->
|
||||
{ model | errors = addErrorNotification (errorText error) model } ! []
|
||||
|
||||
Reblogged result ->
|
||||
case result of
|
||||
Ok _ ->
|
||||
|
@ -301,12 +349,12 @@ update msg model =
|
|||
{-| Update viewed account relationships as well as the relationship with the
|
||||
current connected user, both according to the "following" status provided.
|
||||
-}
|
||||
processFollowEvent : Relationship -> Bool -> Model -> Model
|
||||
processFollowEvent relationship flag model =
|
||||
processFollowEvent : Relationship -> Model -> Model
|
||||
processFollowEvent relationship model =
|
||||
let
|
||||
updateRelationship r =
|
||||
if r.id == relationship.id then
|
||||
{ r | following = flag }
|
||||
{ r | following = relationship.following }
|
||||
else
|
||||
r
|
||||
|
||||
|
@ -317,7 +365,7 @@ processFollowEvent relationship flag model =
|
|||
case model.accountRelationship of
|
||||
Just accountRelationship ->
|
||||
if accountRelationship.id == relationship.id then
|
||||
Just { relationship | following = flag }
|
||||
Just { relationship | following = relationship.following }
|
||||
else
|
||||
model.accountRelationship
|
||||
|
||||
|
@ -334,7 +382,7 @@ processUnfollowEvent : Account -> Relationship -> Model -> Model
|
|||
processUnfollowEvent account relationship model =
|
||||
let
|
||||
newModel =
|
||||
processFollowEvent relationship False model
|
||||
processFollowEvent relationship model
|
||||
in
|
||||
case model.currentUser of
|
||||
Just currentUser ->
|
||||
|
@ -344,3 +392,76 @@ processUnfollowEvent account relationship model =
|
|||
|
||||
Nothing ->
|
||||
newModel
|
||||
|
||||
|
||||
{-| Update viewed account relationships as well as the relationship with the
|
||||
current connected user, both according to the "muting" status provided.
|
||||
-}
|
||||
processMuteEvent : Account -> Relationship -> Model -> Model
|
||||
processMuteEvent account relationship model =
|
||||
let
|
||||
updateRelationship r =
|
||||
if r.id == relationship.id then
|
||||
{ r | muting = relationship.muting }
|
||||
else
|
||||
r
|
||||
|
||||
accountRelationships =
|
||||
model.accountRelationships |> List.map updateRelationship
|
||||
|
||||
accountRelationship =
|
||||
case model.accountRelationship of
|
||||
Just accountRelationship ->
|
||||
if accountRelationship.id == relationship.id then
|
||||
Just { relationship | muting = relationship.muting }
|
||||
else
|
||||
model.accountRelationship
|
||||
|
||||
Nothing ->
|
||||
Nothing
|
||||
in
|
||||
{ model
|
||||
| accountRelationships = accountRelationships
|
||||
, accountRelationship = accountRelationship
|
||||
, homeTimeline = Update.Timeline.dropAccountStatuses account model.homeTimeline
|
||||
, localTimeline = Update.Timeline.dropAccountStatuses account model.localTimeline
|
||||
, globalTimeline = Update.Timeline.dropAccountStatuses account model.globalTimeline
|
||||
, mutes = Update.Timeline.removeMute account model.mutes
|
||||
}
|
||||
|
||||
|
||||
{-| Update viewed account relationships as well as the relationship with the
|
||||
current connected user, both according to the "blocking" status provided.
|
||||
-}
|
||||
processBlockEvent : Account -> Relationship -> Model -> Model
|
||||
processBlockEvent account relationship model =
|
||||
let
|
||||
updateRelationship r =
|
||||
if r.id == relationship.id then
|
||||
{ r | blocking = relationship.blocking }
|
||||
else
|
||||
r
|
||||
|
||||
accountRelationships =
|
||||
model.accountRelationships |> List.map updateRelationship
|
||||
|
||||
accountRelationship =
|
||||
case model.accountRelationship of
|
||||
Just accountRelationship ->
|
||||
if accountRelationship.id == relationship.id then
|
||||
Just { relationship | blocking = relationship.blocking }
|
||||
else
|
||||
model.accountRelationship
|
||||
|
||||
Nothing ->
|
||||
Nothing
|
||||
in
|
||||
{ model
|
||||
| accountRelationships = accountRelationships
|
||||
, accountRelationship = accountRelationship
|
||||
, homeTimeline = Update.Timeline.dropAccountStatuses account model.homeTimeline
|
||||
, localTimeline = Update.Timeline.dropAccountStatuses account model.localTimeline
|
||||
, globalTimeline = Update.Timeline.dropAccountStatuses account model.globalTimeline
|
||||
, blocks = Update.Timeline.removeBlock account model.blocks
|
||||
, notifications = Update.Timeline.dropNotificationsFromAccount account model.notifications
|
||||
}
|
||||
|
|
|
@ -3,11 +3,16 @@ module Update.Timeline
|
|||
( cleanUnfollow
|
||||
, deleteStatusFromAllTimelines
|
||||
, deleteStatus
|
||||
, dropAccountStatuses
|
||||
, dropNotificationsFromAccount
|
||||
, empty
|
||||
, markAsLoading
|
||||
, prepend
|
||||
, processReblog
|
||||
, processFavourite
|
||||
, removeBlock
|
||||
, removeMute
|
||||
, setLoading
|
||||
, update
|
||||
, updateWithBoolFlag
|
||||
)
|
||||
|
@ -101,6 +106,29 @@ deleteStatus statusId ({ entries } as timeline) =
|
|||
}
|
||||
|
||||
|
||||
dropAccountStatuses : Account -> Timeline Status -> Timeline Status
|
||||
dropAccountStatuses account timeline =
|
||||
let
|
||||
keep status =
|
||||
not <| Mastodon.Helper.sameAccount account status.account
|
||||
in
|
||||
{ timeline | entries = List.filter keep timeline.entries }
|
||||
|
||||
|
||||
dropNotificationsFromAccount : Account -> Timeline NotificationAggregate -> Timeline NotificationAggregate
|
||||
dropNotificationsFromAccount account timeline =
|
||||
let
|
||||
keepNotification notification =
|
||||
case notification.status of
|
||||
Just status ->
|
||||
status.account /= account
|
||||
|
||||
Nothing ->
|
||||
True
|
||||
in
|
||||
{ timeline | entries = List.filter keepNotification timeline.entries }
|
||||
|
||||
|
||||
empty : String -> Timeline a
|
||||
empty id =
|
||||
{ id = id
|
||||
|
@ -197,6 +225,29 @@ processReblog status added model =
|
|||
model
|
||||
|
||||
|
||||
removeBlock : Account -> Timeline Account -> Timeline Account
|
||||
removeBlock account timeline =
|
||||
let
|
||||
keep blockedAccount =
|
||||
not <| Mastodon.Helper.sameAccount account blockedAccount
|
||||
in
|
||||
{ timeline | entries = List.filter keep timeline.entries }
|
||||
|
||||
|
||||
removeMute : Account -> Timeline Account -> Timeline Account
|
||||
removeMute account timeline =
|
||||
let
|
||||
keep mutedAccount =
|
||||
not <| Mastodon.Helper.sameAccount account mutedAccount
|
||||
in
|
||||
{ timeline | entries = List.filter keep timeline.entries }
|
||||
|
||||
|
||||
setLoading : Bool -> Timeline a -> Timeline a
|
||||
setLoading flag timeline =
|
||||
{ timeline | loading = flag }
|
||||
|
||||
|
||||
update : Bool -> List a -> Links -> Timeline a -> Timeline a
|
||||
update append entries links timeline =
|
||||
let
|
||||
|
|
|
@ -51,7 +51,7 @@ followButton currentUser relationship account =
|
|||
case relationship of
|
||||
Nothing ->
|
||||
( NoOp
|
||||
, "btn btn-default btn-disabled"
|
||||
, "btn btn-default btn-follow btn-disabled"
|
||||
, "question-sign"
|
||||
, "Unknown relationship"
|
||||
)
|
||||
|
@ -59,13 +59,13 @@ followButton currentUser relationship account =
|
|||
Just relationship ->
|
||||
if relationship.following then
|
||||
( UnfollowAccount account
|
||||
, "btn btn-default btn-primary"
|
||||
, "btn btn-default btn-follow btn-primary"
|
||||
, "eye-close"
|
||||
, "Unfollow"
|
||||
)
|
||||
else
|
||||
( FollowAccount account
|
||||
, "btn btn-default"
|
||||
, "btn btn-default btn-follow"
|
||||
, "eye-open"
|
||||
, "Follow"
|
||||
)
|
||||
|
@ -94,10 +94,77 @@ followView currentUser relationship account =
|
|||
, br [] []
|
||||
, text <| "@" ++ account.acct
|
||||
]
|
||||
, muteButton currentUser relationship account
|
||||
, followButton currentUser relationship account
|
||||
]
|
||||
|
||||
|
||||
muteButton : CurrentUser -> CurrentUserRelation -> Account -> Html Msg
|
||||
muteButton currentUser relationship account =
|
||||
if Mastodon.Helper.sameAccount account currentUser then
|
||||
text ""
|
||||
else
|
||||
let
|
||||
( muteEvent, btnClasses, iconName, tooltip ) =
|
||||
case relationship of
|
||||
Nothing ->
|
||||
( NoOp
|
||||
, "btn btn-default btn-mute btn-disabled"
|
||||
, "question-sign"
|
||||
, "Unknown relationship"
|
||||
)
|
||||
|
||||
Just relationship ->
|
||||
if relationship.muting then
|
||||
( Unmute account
|
||||
, "btn btn-default btn-mute btn-primary"
|
||||
, "volume-up"
|
||||
, "Unmute"
|
||||
)
|
||||
else
|
||||
( Mute account
|
||||
, "btn btn-default btn-mute"
|
||||
, "volume-off"
|
||||
, "Mute"
|
||||
)
|
||||
in
|
||||
button [ class btnClasses, title tooltip, onClick muteEvent ]
|
||||
[ Common.icon iconName ]
|
||||
|
||||
|
||||
blockButton : CurrentUser -> CurrentUserRelation -> Account -> Html Msg
|
||||
blockButton currentUser relationship account =
|
||||
if Mastodon.Helper.sameAccount account currentUser then
|
||||
text ""
|
||||
else
|
||||
let
|
||||
( blockEvent, btnClasses, iconName, tooltip ) =
|
||||
case relationship of
|
||||
Nothing ->
|
||||
( NoOp
|
||||
, "btn btn-default btn-block btn-disabled"
|
||||
, "question-sign"
|
||||
, "Unknown relationship"
|
||||
)
|
||||
|
||||
Just relationship ->
|
||||
if relationship.blocking then
|
||||
( Unblock account
|
||||
, "btn btn-default btn-block btn-primary"
|
||||
, "ok-circle"
|
||||
, "Unblock"
|
||||
)
|
||||
else
|
||||
( Block account
|
||||
, "btn btn-default btn-block"
|
||||
, "ban-circle"
|
||||
, "Block"
|
||||
)
|
||||
in
|
||||
button [ class btnClasses, title tooltip, onClick blockEvent ]
|
||||
[ Common.icon iconName ]
|
||||
|
||||
|
||||
accountFollowView :
|
||||
CurrentUser
|
||||
-> Timeline Account
|
||||
|
@ -157,16 +224,30 @@ accountView currentUser account relationship panelContent =
|
|||
]
|
||||
[ 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 ->
|
||||
if relationship.followed_by then
|
||||
span [ class "badge followed-by" ] [ text "Follows you" ]
|
||||
else
|
||||
text ""
|
||||
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 ""
|
||||
|
|
|
@ -80,7 +80,7 @@ accountSelectorView : Model -> Html Msg
|
|||
accountSelectorView model =
|
||||
div [ class "col-md-3 column" ]
|
||||
[ div [ class "panel panel-default" ]
|
||||
[ closeablePanelheading "account-selector" "user" "Account selector" CloseAccountSelector
|
||||
[ closeablePanelheading "account-selector" "user" "Account selector" (SetView LocalTimelineView)
|
||||
, contextualTimelineMenu model.currentView
|
||||
, ul [ class "list-group " ] <|
|
||||
List.map (accountIdentityView model.currentUser) model.clients
|
||||
|
|
|
@ -8,9 +8,11 @@ import Types exposing (..)
|
|||
import View.Account exposing (accountFollowView, accountTimelineView)
|
||||
import View.AccountSelector exposing (accountSelectorView)
|
||||
import View.Auth exposing (authView)
|
||||
import View.Blocks exposing (blocksView)
|
||||
import View.Common as Common
|
||||
import View.Draft exposing (draftView)
|
||||
import View.Error exposing (errorsListView)
|
||||
import View.Mutes exposing (mutesView)
|
||||
import View.Notification exposing (notificationListView)
|
||||
import View.Thread exposing (threadView)
|
||||
import View.Timeline exposing (contextualTimelineView, homeTimelineView)
|
||||
|
@ -58,6 +60,12 @@ homepageView model =
|
|||
AccountSelectorView ->
|
||||
accountSelectorView model
|
||||
|
||||
MutesView ->
|
||||
mutesView model
|
||||
|
||||
BlocksView ->
|
||||
blocksView model
|
||||
|
||||
AccountFollowersView account followers ->
|
||||
accountFollowView
|
||||
currentUser
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
module View.Blocks exposing (blocksView)
|
||||
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (..)
|
||||
import Html.Keyed as Keyed
|
||||
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)
|
||||
|
||||
|
||||
type alias CurrentUser =
|
||||
Maybe Account
|
||||
|
||||
|
||||
blockView : CurrentUser -> Account -> Html Msg
|
||||
blockView currentUser account =
|
||||
let
|
||||
( isCurrentUser, entryClass ) =
|
||||
case currentUser of
|
||||
Just currentUser ->
|
||||
if sameAccount account currentUser then
|
||||
( True, "active" )
|
||||
else
|
||||
( False, "" )
|
||||
|
||||
Nothing ->
|
||||
( False, "" )
|
||||
in
|
||||
li [ class <| "list-group-item status " ++ entryClass ]
|
||||
[ div [ class "follow-entry" ]
|
||||
[ Common.accountAvatarLink False account
|
||||
, div [ class "userinfo" ]
|
||||
[ strong []
|
||||
[ a
|
||||
[ href account.url
|
||||
, onClickWithPreventAndStop <| LoadAccount account.id
|
||||
]
|
||||
[ text <|
|
||||
if account.display_name /= "" then
|
||||
account.display_name
|
||||
else
|
||||
account.username
|
||||
]
|
||||
]
|
||||
, br [] []
|
||||
, text <| "@" ++ account.acct
|
||||
]
|
||||
, button
|
||||
[ class "btn btn-default btn-block btn-primary"
|
||||
, title "Unblock"
|
||||
, onClick <| Unblock account
|
||||
]
|
||||
[ Common.icon "ok-circle" ]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
blocksView : Model -> Html Msg
|
||||
blocksView model =
|
||||
let
|
||||
keyedEntry account =
|
||||
( toString account.id
|
||||
, blockView model.currentUser account
|
||||
)
|
||||
|
||||
entries =
|
||||
List.map keyedEntry model.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." ]
|
||||
else
|
||||
Keyed.ul [ id "blocks-timeline", class "list-group timeline" ] <|
|
||||
(entries ++ [ ( "load-more", Common.loadMoreBtn model.blocks ) ])
|
||||
]
|
||||
]
|
|
@ -0,0 +1,83 @@
|
|||
module View.Mutes exposing (mutesView)
|
||||
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (..)
|
||||
import Html.Keyed as Keyed
|
||||
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)
|
||||
|
||||
|
||||
type alias CurrentUser =
|
||||
Maybe Account
|
||||
|
||||
|
||||
muteView : CurrentUser -> Account -> Html Msg
|
||||
muteView currentUser account =
|
||||
let
|
||||
( isCurrentUser, entryClass ) =
|
||||
case currentUser of
|
||||
Just currentUser ->
|
||||
if sameAccount account currentUser then
|
||||
( True, "active" )
|
||||
else
|
||||
( False, "" )
|
||||
|
||||
Nothing ->
|
||||
( False, "" )
|
||||
in
|
||||
li [ class <| "list-group-item status " ++ entryClass ]
|
||||
[ div [ class "follow-entry" ]
|
||||
[ Common.accountAvatarLink False account
|
||||
, div [ class "userinfo" ]
|
||||
[ strong []
|
||||
[ a
|
||||
[ href account.url
|
||||
, onClickWithPreventAndStop <| LoadAccount account.id
|
||||
]
|
||||
[ text <|
|
||||
if account.display_name /= "" then
|
||||
account.display_name
|
||||
else
|
||||
account.username
|
||||
]
|
||||
]
|
||||
, br [] []
|
||||
, text <| "@" ++ account.acct
|
||||
]
|
||||
, button
|
||||
[ class "btn btn-default btn-mute btn-primary"
|
||||
, title "Unmute"
|
||||
, onClick <| Unmute account
|
||||
]
|
||||
[ Common.icon "volume-up" ]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
mutesView : Model -> Html Msg
|
||||
mutesView model =
|
||||
let
|
||||
keyedEntry account =
|
||||
( toString account.id
|
||||
, muteView model.currentUser account
|
||||
)
|
||||
|
||||
entries =
|
||||
List.map keyedEntry model.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." ]
|
||||
else
|
||||
Keyed.ul [ id "mutes-timeline", class "list-group timeline" ] <|
|
||||
(entries ++ [ ( "load-more", Common.loadMoreBtn model.mutes ) ])
|
||||
]
|
||||
]
|
|
@ -81,6 +81,8 @@ contextualTimelineMenu currentView =
|
|||
[ 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
|
||||
]
|
||||
|
||||
|
|
Loading…
Reference in New Issue