1
0
Fork 0
tooty/src/Update/Draft.elm

318 lines
11 KiB
Elm
Raw Normal View History

module Update.Draft
exposing
( empty
, showAutoMenu
, update
)
import Autocomplete
import Command
2017-05-11 08:55:15 +00:00
import Json.Decode as Decode
import Mastodon.Decoder exposing (attachmentDecoder)
import Mastodon.Helper
import Mastodon.Model exposing (..)
import String.Extra
2017-05-11 08:55:15 +00:00
import Update.Error exposing (addErrorNotification)
import Types exposing (..)
import Util
autocompleteUpdateConfig : Autocomplete.UpdateConfig Msg Account
autocompleteUpdateConfig =
Autocomplete.updateConfig
{ toId = .id
, onKeyDown =
\code maybeId ->
if code == 38 || code == 40 then
Nothing
else if code == 13 then
Maybe.map (DraftEvent << SelectAccount) maybeId
else
Just <| (DraftEvent << ResetAutocomplete) False
, onTooLow = Just <| (DraftEvent << ResetAutocomplete) True
, onTooHigh = Just <| (DraftEvent << ResetAutocomplete) False
, onMouseEnter = \_ -> Nothing
, onMouseLeave = \_ -> Nothing
, onMouseClick = \id -> Just <| (DraftEvent << SelectAccount) id
, separateSelections = False
}
empty : Draft
empty =
{ status = ""
, inReplyTo = Nothing
, spoilerText = Nothing
, sensitive = False
, visibility = "public"
2017-05-11 08:55:15 +00:00
, attachments = []
2017-05-11 10:23:10 +00:00
, mediaUploading = False
, statusLength = 0
, autoState = Autocomplete.empty
, autoAtPosition = Nothing
, autoQuery = ""
, autoCursorPosition = 0
, autoMaxResults = 4
, autoAccounts = []
, showAutoMenu = False
}
showAutoMenu : List Account -> Maybe Int -> String -> Bool
showAutoMenu accounts atPosition query =
case ( List.isEmpty accounts, atPosition, query ) of
( _, Nothing, _ ) ->
False
( True, _, _ ) ->
False
( _, _, "" ) ->
False
( False, Just _, _ ) ->
True
update : DraftMsg -> Account -> Model -> ( Model, Cmd Msg )
2017-05-11 08:55:15 +00:00
update draftMsg currentUser ({ draft } as model) =
case draftMsg of
ClearDraft ->
{ model | draft = empty }
! [ Command.updateDomStatus empty.status ]
ToggleSpoiler enabled ->
let
newDraft =
{ draft
| spoilerText =
if enabled then
Just ""
else
Nothing
2017-05-11 08:55:15 +00:00
}
in
{ model | draft = newDraft } ! []
2017-05-11 08:55:15 +00:00
UpdateSensitive sensitive ->
{ model | draft = { draft | sensitive = sensitive } } ! []
2017-05-11 08:55:15 +00:00
UpdateSpoiler spoilerText ->
{ model | draft = { draft | spoilerText = Just spoilerText } } ! []
2017-05-11 08:55:15 +00:00
UpdateVisibility visibility ->
{ model | draft = { draft | visibility = visibility } } ! []
2017-05-11 08:55:15 +00:00
UpdateReplyTo status ->
let
newStatus =
Mastodon.Helper.getReplyPrefix currentUser status
in
{ model
| draft =
{ draft
2017-05-11 08:55:15 +00:00
| inReplyTo = Just status
, status = newStatus
, sensitive = Maybe.withDefault False status.sensitive
, spoilerText =
if status.spoiler_text == "" then
Nothing
else
Just status.spoiler_text
, visibility = status.visibility
}
2017-05-11 08:55:15 +00:00
}
! [ Command.focusId "status"
, Command.updateDomStatus newStatus
]
2017-05-11 08:55:15 +00:00
UpdateInputInformation { status, selectionStart } ->
let
stringToPos =
String.slice 0 selectionStart status
2017-05-11 08:55:15 +00:00
atPosition =
case (String.right 1 stringToPos) of
"@" ->
Just selectionStart
" " ->
Nothing
_ ->
2017-05-11 08:55:15 +00:00
model.draft.autoAtPosition
query =
case atPosition of
Just position ->
String.slice position (String.length stringToPos) stringToPos
Nothing ->
""
newDraft =
{ draft
| status = status
, statusLength = String.length status
, autoCursorPosition = selectionStart
, autoAtPosition = atPosition
, autoQuery = query
, showAutoMenu =
showAutoMenu
draft.autoAccounts
draft.autoAtPosition
draft.autoQuery
}
in
{ model | draft = newDraft }
! if query /= "" && atPosition /= Nothing then
[ Command.searchAccounts (List.head model.clients) query model.draft.autoMaxResults False ]
else
[]
SelectAccount id ->
let
account =
List.filter (\account -> account.id == id) draft.autoAccounts
2017-05-11 08:55:15 +00:00
|> List.head
stringToAtPos =
case draft.autoAtPosition of
Just atPosition ->
String.slice 0 atPosition draft.status
2017-05-11 08:55:15 +00:00
_ ->
""
stringToPos =
String.slice 0 draft.autoCursorPosition draft.status
newStatus =
case draft.autoAtPosition of
Just atPosition ->
String.Extra.replaceSlice
(case account of
Just a ->
a.acct ++ " "
Nothing ->
""
)
atPosition
((String.length draft.autoQuery) + atPosition)
draft.status
2017-05-11 08:55:15 +00:00
_ ->
""
newDraft =
{ draft
| status = newStatus
, autoAtPosition = Nothing
, autoQuery = ""
, autoState = Autocomplete.empty
, autoAccounts = []
, showAutoMenu = False
}
in
{ model | draft = newDraft }
-- As we are using defaultValue, we need to update the textarea
-- using a port.
! [ Command.updateDomStatus newStatus ]
SetAutoState autoMsg ->
let
( newState, maybeMsg ) =
Autocomplete.update
autocompleteUpdateConfig
autoMsg
draft.autoMaxResults
draft.autoState
(Util.acceptableAccounts draft.autoQuery draft.autoAccounts)
newModel =
{ model | draft = { draft | autoState = newState } }
in
case maybeMsg of
Just (DraftEvent updateMsg) ->
update updateMsg currentUser newModel
_ ->
newModel ! []
CloseAutocomplete ->
let
newDraft =
{ draft
| showAutoMenu = False
, autoState = Autocomplete.reset autocompleteUpdateConfig draft.autoState
}
in
{ model | draft = newDraft } ! []
ResetAutocomplete toTop ->
let
newDraft =
{ draft
| autoState =
if toTop then
Autocomplete.resetToFirstItem
autocompleteUpdateConfig
(Util.acceptableAccounts draft.autoQuery draft.autoAccounts)
draft.autoMaxResults
draft.autoState
else
Autocomplete.resetToLastItem
autocompleteUpdateConfig
(Util.acceptableAccounts draft.autoQuery draft.autoAccounts)
draft.autoMaxResults
draft.autoState
}
in
{ model | draft = newDraft } ! []
RemoveMedia id ->
let
newDraft =
{ draft | attachments = List.filter (\a -> a.id /= id) draft.attachments }
in
{ model | draft = newDraft } ! []
UploadMedia id ->
2017-05-11 10:23:10 +00:00
{ model | draft = { draft | mediaUploading = True } }
! [ Command.uploadMedia (List.head model.clients) id ]
2017-05-11 08:55:15 +00:00
UploadError error ->
2017-05-11 10:23:10 +00:00
{ model
| draft = { draft | mediaUploading = False }
, errors = addErrorNotification error model
}
! []
2017-05-11 08:55:15 +00:00
UploadResult encoded ->
if encoded == "" then
-- user has likely pressed "Cancel" in the file input dialog
model ! []
else
let
2017-05-11 08:55:15 +00:00
decodedAttachment =
Decode.decodeString attachmentDecoder encoded
in
2017-05-11 08:55:15 +00:00
case decodedAttachment of
Ok attachment ->
{ model
| draft =
{ draft
2017-05-11 10:23:10 +00:00
| mediaUploading = False
, attachments = List.append draft.attachments [ attachment ]
2017-05-11 08:55:15 +00:00
}
}
! []
Err error ->
2017-05-11 10:23:10 +00:00
{ model
| draft = { draft | mediaUploading = False }
, errors = addErrorNotification error model
}
! []