Aggregate notifications. (#37)

This commit is contained in:
Nicolas Perriault 2017-04-23 21:49:04 +02:00 committed by GitHub
parent 3a697f07bb
commit 6b75c90ef6
5 changed files with 114 additions and 28 deletions

View File

@ -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",

View File

@ -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;
}

View File

@ -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

View File

@ -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 } ! []

View File

@ -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" ]