Aggregate notifications. (#37)
This commit is contained in:
parent
3a697f07bb
commit
6b75c90ef6
@ -9,6 +9,7 @@
|
||||
"exposed-modules": [],
|
||||
"dependencies": {
|
||||
"NoRedInk/elm-decode-pipeline": "3.0.0 <= v < 4.0.0",
|
||||
"elm-community/list-extra": "6.0.0 <= v < 7.0.0",
|
||||
"elm-lang/core": "5.1.1 <= v < 6.0.0",
|
||||
"elm-lang/dom": "1.1.1 <= v < 2.0.0",
|
||||
"elm-lang/html": "2.0.0 <= v < 3.0.0",
|
||||
|
@ -17,16 +17,32 @@ body {
|
||||
color: #999;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.reblog > p:first-of-type > a,
|
||||
.notification > p:first-of-type > a {
|
||||
|
||||
.status-info, .status-info a {
|
||||
color: #ccc;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
|
||||
.status-info > .avatars {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.status-info > .avatars img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 5px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.notification.reblog,
|
||||
.notification.favourite {
|
||||
opacity: .75;
|
||||
}
|
||||
|
||||
.notification.follow > p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.notification .spoiled,
|
||||
.notification .attachments {
|
||||
.notification .spoiled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ module Mastodon
|
||||
, Error(..)
|
||||
, Mention
|
||||
, Notification
|
||||
, NotificationAggregate
|
||||
, Reblog(..)
|
||||
, Status
|
||||
, StatusRequestBody
|
||||
@ -19,6 +20,7 @@ module Mastodon
|
||||
, extractReblog
|
||||
, register
|
||||
, registrationEncoder
|
||||
, aggregateNotifications
|
||||
, clientEncoder
|
||||
, getAuthorizationUrl
|
||||
, getAccessToken
|
||||
@ -36,6 +38,7 @@ import HttpBuilder
|
||||
import Json.Decode.Pipeline as Pipe
|
||||
import Json.Decode as Decode
|
||||
import Json.Encode as Encode
|
||||
import List.Extra exposing (groupWhile)
|
||||
|
||||
|
||||
-- Types
|
||||
@ -148,6 +151,14 @@ type alias Notification =
|
||||
}
|
||||
|
||||
|
||||
type alias NotificationAggregate =
|
||||
{ type_ : String
|
||||
, status : Maybe Status
|
||||
, accounts : List Account
|
||||
, created_at : String
|
||||
}
|
||||
|
||||
|
||||
type alias Tag =
|
||||
{ name : String
|
||||
, url : String
|
||||
@ -437,6 +448,53 @@ fetch client endpoint decoder =
|
||||
-- Public API
|
||||
|
||||
|
||||
aggregateNotifications : List Notification -> List NotificationAggregate
|
||||
aggregateNotifications notifications =
|
||||
let
|
||||
only type_ notifications =
|
||||
List.filter (\n -> n.type_ == type_) notifications
|
||||
|
||||
sameStatus n1 n2 =
|
||||
case ( n1.status, n2.status ) of
|
||||
( Just r1, Just r2 ) ->
|
||||
r1.id == r2.id
|
||||
|
||||
_ ->
|
||||
False
|
||||
|
||||
sameAccount n1 n2 =
|
||||
n1.account.id == n2.account.id
|
||||
|
||||
extractAggregate statusGroup =
|
||||
let
|
||||
accounts =
|
||||
List.map .account statusGroup
|
||||
in
|
||||
case statusGroup of
|
||||
notification :: _ ->
|
||||
[ NotificationAggregate
|
||||
notification.type_
|
||||
notification.status
|
||||
accounts
|
||||
notification.created_at
|
||||
]
|
||||
|
||||
[] ->
|
||||
[]
|
||||
|
||||
aggregate statusGroups =
|
||||
List.map extractAggregate statusGroups |> List.concat
|
||||
in
|
||||
[ notifications |> only "reblog" |> groupWhile sameStatus |> aggregate
|
||||
, notifications |> only "favourite" |> groupWhile sameStatus |> aggregate
|
||||
, notifications |> only "mention" |> groupWhile sameStatus |> aggregate
|
||||
, notifications |> only "follow" |> groupWhile sameAccount |> aggregate
|
||||
]
|
||||
|> List.concat
|
||||
|> List.sortBy .created_at
|
||||
|> List.reverse
|
||||
|
||||
|
||||
clientEncoder : Client -> Encode.Value
|
||||
clientEncoder client =
|
||||
Encode.object
|
||||
|
@ -58,11 +58,6 @@ type
|
||||
| UserTimeline (Result Mastodon.Error (List Mastodon.Status))
|
||||
|
||||
|
||||
type Crud
|
||||
= Add
|
||||
| Remove
|
||||
|
||||
|
||||
type alias Draft =
|
||||
{ status : String
|
||||
, in_reply_to : Maybe Mastodon.Status
|
||||
@ -79,7 +74,7 @@ type alias Model =
|
||||
, userTimeline : List Mastodon.Status
|
||||
, localTimeline : List Mastodon.Status
|
||||
, publicTimeline : List Mastodon.Status
|
||||
, notifications : List Mastodon.Notification
|
||||
, notifications : List Mastodon.NotificationAggregate
|
||||
, draft : Draft
|
||||
, account : Maybe Mastodon.Account
|
||||
, errors : List String
|
||||
@ -499,7 +494,7 @@ update msg model =
|
||||
Notifications result ->
|
||||
case result of
|
||||
Ok notifications ->
|
||||
{ model | notifications = notifications } ! []
|
||||
{ model | notifications = Mastodon.aggregateNotifications notifications } ! []
|
||||
|
||||
Err error ->
|
||||
{ model | notifications = [], errors = (errorText error) :: model.errors } ! []
|
||||
|
50
src/View.elm
50
src/View.elm
@ -54,6 +54,16 @@ accountLink account =
|
||||
[ text <| "@" ++ account.username ]
|
||||
|
||||
|
||||
accountAvatarLink : Mastodon.Account -> Html Msg
|
||||
accountAvatarLink account =
|
||||
a
|
||||
[ href account.url
|
||||
, ViewHelper.onClickWithPreventAndStop (OnLoadUserAccount account.id)
|
||||
, title <| "@" ++ account.username
|
||||
]
|
||||
[ img [ src account.avatar ] [] ]
|
||||
|
||||
|
||||
attachmentPreview : Maybe Bool -> Mastodon.Attachment -> Html Msg
|
||||
attachmentPreview sensitive ({ url, preview_url } as attachment) =
|
||||
let
|
||||
@ -146,10 +156,10 @@ statusView ({ account, content, media_attachments, reblog, mentions } as status)
|
||||
case reblog of
|
||||
Just (Mastodon.Reblog reblog) ->
|
||||
div [ class "reblog" ]
|
||||
[ p []
|
||||
[ p [ class "status-info" ]
|
||||
[ icon "fire"
|
||||
, a (accountLinkAttributes ++ [ class "reblogger" ])
|
||||
[ text <| " " ++ account.username ]
|
||||
[ text <| " @" ++ account.username ]
|
||||
, text " boosted"
|
||||
]
|
||||
, statusView reblog
|
||||
@ -297,22 +307,28 @@ timelineView statuses label iconName =
|
||||
]
|
||||
|
||||
|
||||
notificationHeading : Mastodon.Account -> String -> String -> Html Msg
|
||||
notificationHeading account str iconType =
|
||||
p [] <|
|
||||
List.intersperse (text " ")
|
||||
[ icon iconType, accountLink account, text str ]
|
||||
notificationHeading : List Mastodon.Account -> String -> String -> Html Msg
|
||||
notificationHeading accounts str iconType =
|
||||
div [ class "status-info" ]
|
||||
[ div [ class "avatars" ] <| List.map accountAvatarLink accounts
|
||||
, p [] <|
|
||||
List.intersperse (text " ")
|
||||
[ icon iconType
|
||||
, span [] <| List.intersperse (text ", ") (List.map accountLink accounts)
|
||||
, text str
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
notificationStatusView : Mastodon.Status -> Mastodon.Notification -> Html Msg
|
||||
notificationStatusView status { type_, account } =
|
||||
div [ class "notification" ]
|
||||
notificationStatusView : Mastodon.Status -> Mastodon.NotificationAggregate -> Html Msg
|
||||
notificationStatusView status { type_, accounts } =
|
||||
div [ class <| "notification " ++ type_ ]
|
||||
[ case type_ of
|
||||
"reblog" ->
|
||||
notificationHeading account "boosted your toot" "fire"
|
||||
notificationHeading accounts "boosted your toot" "fire"
|
||||
|
||||
"favourite" ->
|
||||
notificationHeading account "favourited your toot" "star"
|
||||
notificationHeading accounts "favourited your toot" "star"
|
||||
|
||||
_ ->
|
||||
text ""
|
||||
@ -321,13 +337,13 @@ notificationStatusView status { type_, account } =
|
||||
]
|
||||
|
||||
|
||||
notificationFollowView : Mastodon.Notification -> Html Msg
|
||||
notificationFollowView { account } =
|
||||
notificationFollowView : Mastodon.NotificationAggregate -> Html Msg
|
||||
notificationFollowView { accounts } =
|
||||
div [ class "notification follow" ]
|
||||
[ notificationHeading account "started following you" "user" ]
|
||||
[ notificationHeading accounts "started following you" "user" ]
|
||||
|
||||
|
||||
notificationEntryView : Mastodon.Notification -> Html Msg
|
||||
notificationEntryView : Mastodon.NotificationAggregate -> Html Msg
|
||||
notificationEntryView notification =
|
||||
li [ class "list-group-item" ]
|
||||
[ case notification.status of
|
||||
@ -339,7 +355,7 @@ notificationEntryView notification =
|
||||
]
|
||||
|
||||
|
||||
notificationListView : List Mastodon.Notification -> Html Msg
|
||||
notificationListView : List Mastodon.NotificationAggregate -> Html Msg
|
||||
notificationListView notifications =
|
||||
div [ class "col-md-3" ]
|
||||
[ div [ class "panel panel-default" ]
|
||||
|
Loading…
Reference in New Issue
Block a user