Store and load client settings

This commit is contained in:
Eike Kettner 2021-05-26 01:14:30 +02:00
parent 9f76357879
commit 9ccc3ce438
10 changed files with 309 additions and 245 deletions

View File

@ -7,6 +7,7 @@ module App.Data exposing
)
import Api.Model.AuthResult exposing (AuthResult)
import Api.Model.BasicResult exposing (BasicResult)
import Api.Model.VersionInfo exposing (VersionInfo)
import Browser exposing (UrlRequest)
import Browser.Navigation exposing (Key)
@ -155,11 +156,12 @@ type Msg
| SessionCheckResp (Result Http.Error AuthResult)
| ToggleNavMenu
| ToggleUserMenu
| GetUiSettings UiSettings
| GetUiSettings (Result Http.Error UiSettings)
| ToggleSidebar
| ToggleDarkMode
| ToggleLangMenu
| SetLanguage UiLanguage
| ClientSettingsSaveResp UiSettings (Result Http.Error BasicResult)
defaultPage : Flags -> Page

View File

@ -8,6 +8,7 @@ import App.Data exposing (..)
import Browser exposing (UrlRequest(..))
import Browser.Navigation as Nav
import Data.Flags
import Data.UiSettings exposing (UiSettings)
import Data.UiTheme
import Page exposing (Page(..))
import Page.CollectiveSettings.Data
@ -65,11 +66,11 @@ updateWithSub msg model =
{ settings | uiTheme = next }
in
-- when authenticated, store it in settings only
-- once new settings arrive via a subscription,
-- the ui is updated. so it is also updated on
-- page refresh
-- once new settings are successfully saved (the
-- response is arrived), the ui is updated. so it
-- is also updated on page refresh
( { model | userMenuOpen = False }
, Ports.storeUiSettings model.flags newSettings
, Api.saveClientSettings model.flags newSettings (ClientSettingsSaveResp newSettings)
, Sub.none
)
@ -84,6 +85,16 @@ updateWithSub msg model =
, Sub.none
)
ClientSettingsSaveResp settings (Ok res) ->
if res.success then
applyClientSettings model settings
else
( model, Cmd.none, Sub.none )
ClientSettingsSaveResp _ (Err _) ->
( model, Cmd.none, Sub.none )
ToggleLangMenu ->
( { model | langMenuOpen = not model.langMenuOpen }
, Cmd.none
@ -258,7 +269,15 @@ updateWithSub msg model =
, Sub.none
)
GetUiSettings settings ->
GetUiSettings (Ok settings) ->
applyClientSettings model settings
GetUiSettings (Err _) ->
( model, Cmd.none, Sub.none )
applyClientSettings : Model -> UiSettings -> ( Model, Cmd Msg, Sub Msg )
applyClientSettings model settings =
let
setTheme =
Ports.setUiTheme settings.uiTheme
@ -360,14 +379,26 @@ updateQueue lmsg model =
updateUserSettings : Page.UserSettings.Data.Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
updateUserSettings lmsg model =
let
( lm, lc, ls ) =
( lm, lc, newClientSettings ) =
Page.UserSettings.Update.update model.flags model.uiSettings lmsg model.userSettingsModel
model_ =
{ model | userSettingsModel = lm }
( lm2, lc2, s2 ) =
case newClientSettings of
Just sett ->
applyClientSettings model_ sett
Nothing ->
( model_, Cmd.none, Sub.none )
in
( { model
| userSettingsModel = lm
}
, Cmd.map UserSettingsMsg lc
, Sub.map UserSettingsMsg ls
( lm2
, Cmd.batch
[ Cmd.map UserSettingsMsg lc
, lc2
]
, s2
)
@ -415,14 +446,29 @@ updateHome lmsg model =
_ ->
Nothing
( lm, lc, ls ) =
result =
Page.Home.Update.update mid model.key model.flags model.uiSettings lmsg model.homeModel
model_ =
{ model | homeModel = result.model }
( lm, lc, ls ) =
case result.newSettings of
Just sett ->
applyClientSettings model_ sett
Nothing ->
( model_, Cmd.none, Sub.none )
in
( { model
| homeModel = lm
}
, Cmd.map HomeMsg lc
, Sub.map HomeMsg ls
( lm
, Cmd.batch
[ Cmd.map HomeMsg result.cmd
, lc
]
, Sub.batch
[ Sub.map HomeMsg result.sub
, ls
]
)

View File

@ -1,6 +1,7 @@
module Comp.UiSettingsManage exposing
( Model
, Msg(..)
, UpdateResult
, init
, update
, view2
@ -14,10 +15,8 @@ import Data.Flags exposing (Flags)
import Data.UiSettings exposing (UiSettings)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onClick)
import Http
import Messages.Comp.UiSettingsManage exposing (Texts)
import Ports
import Styles as S
@ -31,9 +30,8 @@ type alias Model =
type Msg
= UiSettingsFormMsg Comp.UiSettingsForm.Msg
| Submit
| SettingsSaved
| UpdateSettings
| SaveSettingsResp (Result Http.Error BasicResult)
| SaveSettingsResp UiSettings (Result Http.Error BasicResult)
init : Flags -> UiSettings -> ( Model, Cmd Msg )
@ -54,7 +52,14 @@ init flags settings =
--- update
update : Flags -> UiSettings -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
type alias UpdateResult =
{ model : Model
, cmd : Cmd Msg
, newSettings : Maybe UiSettings
}
update : Flags -> UiSettings -> Msg -> Model -> UpdateResult
update flags settings msg model =
case msg of
UiSettingsFormMsg lm ->
@ -65,7 +70,8 @@ update flags settings msg model =
( m_, sett ) =
Comp.UiSettingsForm.update inSettings lm model.formModel
in
( { model
{ model =
{ model
| formModel = m_
, settings =
if sett == Nothing then
@ -80,45 +86,42 @@ update flags settings msg model =
else
model.message
}
, Cmd.none
, Sub.none
)
, cmd = Cmd.none
, newSettings = Nothing
}
Submit ->
case model.settings of
Just s ->
( { model | message = Nothing }
, Api.saveClientSettings flags s SaveSettingsResp
, Ports.onUiSettingsSaved SettingsSaved
)
{ model = { model | message = Nothing }
, cmd = Api.saveClientSettings flags s (SaveSettingsResp s)
, newSettings = Nothing
}
Nothing ->
( { model | message = Just (BasicResult False "Settings unchanged or invalid.") }
, Cmd.none
, Sub.none
)
{ model = { model | message = Just (BasicResult False "Settings unchanged or invalid.") }
, cmd = Cmd.none
, newSettings = Nothing
}
SettingsSaved ->
( { model | message = Just (BasicResult True "Settings saved.") }
, Cmd.none
, Sub.none
)
SaveSettingsResp newSettings (Ok res) ->
{ model = { model | message = Just res }
, cmd = Cmd.none
, newSettings = Just newSettings
}
SaveSettingsResp (Ok res) ->
( { model | message = Just res }, Cmd.none, Sub.none )
SaveSettingsResp (Err err) ->
( model, Cmd.none, Sub.none )
SaveSettingsResp _ (Err err) ->
UpdateResult model Cmd.none Nothing
UpdateSettings ->
let
( fm, fc ) =
Comp.UiSettingsForm.init flags settings
in
( { model | formModel = fm }
, Cmd.map UiSettingsFormMsg fc
, Sub.none
)
{ model = { model | formModel = fm }
, cmd = Cmd.map UiSettingsFormMsg fc
, newSettings = Nothing
}

View File

@ -55,7 +55,7 @@ init flags url key =
else
Cmd.none
, Ports.getUiSettings flags
, Api.getClientSettings flags GetUiSettings
]
)
@ -85,5 +85,4 @@ subscriptions : Model -> Sub Msg
subscriptions model =
Sub.batch
[ model.subs
, Ports.loadUiSettings GetUiSettings
]

View File

@ -193,6 +193,7 @@ type Msg
| KeyUpPowerSearchbarMsg (Maybe KeyCode)
| RequestReprocessSelected
| ReprocessSelectedConfirmed
| ClientSettingsSaveResp UiSettings (Result Http.Error BasicResult)
type SearchType

View File

@ -1,4 +1,7 @@
module Page.Home.Update exposing (update)
module Page.Home.Update exposing
( UpdateResult
, update
)
import Api
import Api.Model.ItemLightList exposing (ItemLightList)
@ -16,7 +19,6 @@ import Data.Items
import Data.UiSettings exposing (UiSettings)
import Page exposing (Page(..))
import Page.Home.Data exposing (..)
import Ports
import Process
import Scroll
import Set exposing (Set)
@ -28,7 +30,15 @@ import Util.ItemDragDrop as DD
import Util.Update
update : Maybe String -> Nav.Key -> Flags -> UiSettings -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
type alias UpdateResult =
{ model : Model
, cmd : Cmd Msg
, sub : Sub Msg
, newSettings : Maybe UiSettings
}
update : Maybe String -> Nav.Key -> Flags -> UiSettings -> Msg -> Model -> UpdateResult
update mId key flags settings msg model =
case msg of
Init ->
@ -41,7 +51,8 @@ update mId key flags settings msg model =
, scroll = True
}
in
Util.Update.andThen2
makeResult <|
Util.Update.andThen3
[ update mId key flags settings (SearchMenuMsg Comp.SearchMenu.Init)
, doSearch searchParam
]
@ -79,21 +90,21 @@ update mId key flags settings msg model =
BasicSearch
}
( m2, c2, s2 ) =
result =
if nextState.stateChange && not model.searchInProgress then
doSearch (SearchParam flags BasicSearch settings.itemSearchPageSize 0 False) newModel
else
withSub ( newModel, Cmd.none )
in
( m2
, Cmd.batch
[ c2
{ result
| cmd =
Cmd.batch
[ result.cmd
, Cmd.map SearchMenuMsg nextState.cmd
, dropCmd
]
, s2
)
}
SetLinkTarget lt ->
case linkTargetMsg lt of
@ -101,7 +112,7 @@ update mId key flags settings msg model =
update mId key flags settings m model
Nothing ->
( model, Cmd.none, Sub.none )
makeResult ( model, Cmd.none, Sub.none )
ItemCardListMsg m ->
let
@ -144,13 +155,14 @@ update mId key flags settings msg model =
, moreAvailable = list.groups /= []
}
in
Util.Update.andThen2
makeResult <|
Util.Update.andThen3
[ update mId key flags settings (ItemCardListMsg (Comp.ItemCardList.SetResults list))
, if scroll then
scrollToCard mId
else
\next -> ( next, Cmd.none, Sub.none )
\next -> makeResult ( next, Cmd.none, Sub.none )
]
m
@ -167,10 +179,7 @@ update mId key flags settings msg model =
, moreAvailable = list.groups /= []
}
in
Util.Update.andThen2
[ update mId key flags settings (ItemCardListMsg (Comp.ItemCardList.AddResults list))
]
m
update mId key flags settings (ItemCardListMsg (Comp.ItemCardList.AddResults list)) m
ItemSearchAddResp (Err _) ->
withSub
@ -514,6 +523,7 @@ update mId key flags settings msg model =
res.change
(MultiUpdateResp res.change)
in
makeResult
( { model | viewMode = SelectView svm_ }
, Cmd.batch [ cmd_, upCmd ]
, sub_
@ -540,6 +550,7 @@ update mId key flags settings msg model =
noSub ( nm, Cmd.none )
MultiUpdateResp change (Err _) ->
makeResult
( updateSelectViewNameState False model change
, Cmd.none
, Sub.none
@ -592,10 +603,24 @@ update mId key flags settings msg model =
{ settings | cardPreviewFullWidth = not settings.cardPreviewFullWidth }
cmd =
Ports.storeUiSettings flags newSettings
Api.saveClientSettings flags newSettings (ClientSettingsSaveResp newSettings)
in
noSub ( model, cmd )
ClientSettingsSaveResp newSettings (Ok res) ->
if res.success then
{ model = model
, cmd = Cmd.none
, sub = Sub.none
, newSettings = Just newSettings
}
else
noSub ( model, Cmd.none )
ClientSettingsSaveResp _ (Err _) ->
noSub ( model, Cmd.none )
PowerSearchMsg lm ->
let
result =
@ -609,7 +634,7 @@ update mId key flags settings msg model =
in
case result.action of
Comp.PowerSearchInput.NoAction ->
( model_, cmd_, Sub.map PowerSearchMsg result.subs )
makeResult ( model_, cmd_, Sub.map PowerSearchMsg result.subs )
Comp.PowerSearchInput.SubmitSearch ->
update mId key flags settings (DoSearch model_.searchTypeDropdownValue) model_
@ -703,12 +728,13 @@ loadChangedItems flags ids =
Api.itemSearch flags search ReplaceChangedItemsResp
scrollToCard : Maybe String -> Model -> ( Model, Cmd Msg, Sub Msg )
scrollToCard : Maybe String -> Model -> UpdateResult
scrollToCard mId model =
let
scroll id =
Scroll.scrollElementY "item-card-list" id 0.5 0.5
in
makeResult <|
case mId of
Just id ->
( { model | scrollToCard = mId }
@ -725,7 +751,7 @@ loadEditModel flags =
Cmd.map EditMenuMsg (Comp.ItemDetail.MultiEditMenu.loadModel flags)
doSearch : SearchParam -> Model -> ( Model, Cmd Msg, Sub Msg )
doSearch : SearchParam -> Model -> UpdateResult
doSearch param model =
let
param_ =
@ -798,8 +824,9 @@ doSearchMore flags settings model =
)
withSub : ( Model, Cmd Msg ) -> ( Model, Cmd Msg, Sub Msg )
withSub : ( Model, Cmd Msg ) -> UpdateResult
withSub ( m, c ) =
makeResult
( m
, c
, Throttle.ifNeeded
@ -808,6 +835,15 @@ withSub ( m, c ) =
)
noSub : ( Model, Cmd Msg ) -> ( Model, Cmd Msg, Sub Msg )
noSub : ( Model, Cmd Msg ) -> UpdateResult
noSub ( m, c ) =
( m, c, Sub.none )
makeResult ( m, c, Sub.none )
makeResult : ( Model, Cmd Msg, Sub Msg ) -> UpdateResult
makeResult ( m, c, s ) =
{ model = m
, cmd = c
, sub = s
, newSettings = Nothing
}

View File

@ -11,7 +11,7 @@ import Data.UiSettings exposing (UiSettings)
import Page.UserSettings.Data exposing (..)
update : Flags -> UiSettings -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg )
update : Flags -> UiSettings -> Msg -> Model -> ( Model, Cmd Msg, Maybe UiSettings )
update flags settings msg model =
case msg of
SetTab t ->
@ -25,17 +25,23 @@ update flags settings msg model =
( em, c ) =
Comp.EmailSettingsManage.init flags
in
( { m | emailSettingsModel = em }, Cmd.map EmailSettingsMsg c, Sub.none )
( { m | emailSettingsModel = em }
, Cmd.map EmailSettingsMsg c
, Nothing
)
ImapSettingsTab ->
let
( em, c ) =
Comp.ImapSettingsManage.init flags
in
( { m | imapSettingsModel = em }, Cmd.map ImapSettingsMsg c, Sub.none )
( { m | imapSettingsModel = em }
, Cmd.map ImapSettingsMsg c
, Nothing
)
ChangePassTab ->
( m, Cmd.none, Sub.none )
( m, Cmd.none, Nothing )
NotificationTab ->
let
@ -43,7 +49,7 @@ update flags settings msg model =
Cmd.map NotificationMsg
(Tuple.second (Comp.NotificationManage.init flags))
in
( m, initCmd, Sub.none )
( m, initCmd, Nothing )
ScanMailboxTab ->
let
@ -51,31 +57,40 @@ update flags settings msg model =
Cmd.map ScanMailboxMsg
(Tuple.second (Comp.ScanMailboxManage.init flags))
in
( m, initCmd, Sub.none )
( m, initCmd, Nothing )
UiSettingsTab ->
( m, Cmd.none, Sub.none )
( m, Cmd.none, Nothing )
ChangePassMsg m ->
let
( m2, c2 ) =
Comp.ChangePasswordForm.update flags m model.changePassModel
in
( { model | changePassModel = m2 }, Cmd.map ChangePassMsg c2, Sub.none )
( { model | changePassModel = m2 }
, Cmd.map ChangePassMsg c2
, Nothing
)
EmailSettingsMsg m ->
let
( m2, c2 ) =
Comp.EmailSettingsManage.update flags m model.emailSettingsModel
in
( { model | emailSettingsModel = m2 }, Cmd.map EmailSettingsMsg c2, Sub.none )
( { model | emailSettingsModel = m2 }
, Cmd.map EmailSettingsMsg c2
, Nothing
)
ImapSettingsMsg m ->
let
( m2, c2 ) =
Comp.ImapSettingsManage.update flags m model.imapSettingsModel
in
( { model | imapSettingsModel = m2 }, Cmd.map ImapSettingsMsg c2, Sub.none )
( { model | imapSettingsModel = m2 }
, Cmd.map ImapSettingsMsg c2
, Nothing
)
NotificationMsg lm ->
let
@ -84,7 +99,7 @@ update flags settings msg model =
in
( { model | notificationModel = m2 }
, Cmd.map NotificationMsg c2
, Sub.none
, Nothing
)
ScanMailboxMsg lm ->
@ -94,17 +109,17 @@ update flags settings msg model =
in
( { model | scanMailboxModel = m2 }
, Cmd.map ScanMailboxMsg c2
, Sub.none
, Nothing
)
UiSettingsMsg lm ->
let
( m2, c2, s2 ) =
res =
Comp.UiSettingsManage.update flags settings lm model.uiSettingsModel
in
( { model | uiSettingsModel = m2 }
, Cmd.map UiSettingsMsg c2
, Sub.map UiSettingsMsg s2
( { model | uiSettingsModel = res.model }
, Cmd.map UiSettingsMsg res.cmd
, res.newSettings
)
UpdateSettings ->

View File

@ -1,20 +1,14 @@
port module Ports exposing
( checkSearchQueryString
, getUiSettings
, initClipboard
, loadUiSettings
, onUiSettingsSaved
, receiveCheckQueryResult
, removeAccount
, setAccount
, setUiTheme
, storeUiSettings
)
import Api.Model.AuthResult exposing (AuthResult)
import Data.Flags exposing (Flags)
import Data.QueryParseResult exposing (QueryParseResult)
import Data.UiSettings exposing (StoredUiSettings, UiSettings)
import Data.UiTheme exposing (UiTheme)
@ -26,18 +20,6 @@ port setAccount : AuthResult -> Cmd msg
port removeAccount : () -> Cmd msg
port saveUiSettings : ( AuthResult, StoredUiSettings ) -> Cmd msg
port receiveUiSettings : (StoredUiSettings -> msg) -> Sub msg
port requestUiSettings : ( AuthResult, StoredUiSettings ) -> Cmd msg
port uiSettingsSaved : (() -> msg) -> Sub msg
port internalSetUiTheme : String -> Cmd msg
@ -47,45 +29,9 @@ port checkSearchQueryString : String -> Cmd msg
port receiveCheckQueryResult : (QueryParseResult -> msg) -> Sub msg
port initClipboard : ( String, String ) -> Cmd msg
setUiTheme : UiTheme -> Cmd msg
setUiTheme theme =
internalSetUiTheme (Data.UiTheme.toString theme)
onUiSettingsSaved : msg -> Sub msg
onUiSettingsSaved m =
uiSettingsSaved (\_ -> m)
storeUiSettings : Flags -> UiSettings -> Cmd msg
storeUiSettings flags settings =
case flags.account of
Just ar ->
saveUiSettings
( ar
, Data.UiSettings.toStoredUiSettings settings
)
Nothing ->
Cmd.none
loadUiSettings : (UiSettings -> msg) -> Sub msg
loadUiSettings tagger =
receiveUiSettings (Data.UiSettings.mergeDefaults >> tagger)
getUiSettings : Flags -> Cmd msg
getUiSettings flags =
case flags.account of
Just ar ->
requestUiSettings
( ar
, Data.UiSettings.toStoredUiSettings Data.UiSettings.defaults
)
Nothing ->
Cmd.none
port initClipboard : ( String, String ) -> Cmd msg

View File

@ -1,6 +1,7 @@
module Util.Update exposing
( andThen1
, andThen2
, andThen3
, cmdUnit
)
@ -44,6 +45,21 @@ andThen2 fs m =
|> combine
andThen3 :
List (model -> { x | model : model, cmd : Cmd msg, sub : Sub msg })
-> model
-> ( model, Cmd msg, Sub msg )
andThen3 list m =
let
mkTuple r =
( r.model, r.cmd, r.sub )
list2 =
List.map (\e -> e >> mkTuple) list
in
andThen2 list2 m
cmdUnit : a -> Cmd a
cmdUnit a =
Task.perform (\_ -> a) (Task.succeed ())

View File

@ -51,42 +51,42 @@ elmApp.ports.removeAccount.subscribe(function() {
});
elmApp.ports.saveUiSettings.subscribe(function(args) {
if (Array.isArray(args) && args.length == 2) {
var authResult = args[0];
var settings = args[1];
if (authResult && settings) {
var key = authResult.collective + "/" + authResult.user + "/uiSettings";
console.log("Save ui settings to local storage");
localStorage.setItem(key, JSON.stringify(settings));
elmApp.ports.receiveUiSettings.send(settings);
elmApp.ports.uiSettingsSaved.send(null);
}
}
});
// elmApp.ports.saveUiSettings.subscribe(function(args) {
// if (Array.isArray(args) && args.length == 2) {
// var authResult = args[0];
// var settings = args[1];
// if (authResult && settings) {
// var key = authResult.collective + "/" + authResult.user + "/uiSettings";
// console.log("Save ui settings to local storage");
// localStorage.setItem(key, JSON.stringify(settings));
// elmApp.ports.receiveUiSettings.send(settings);
// elmApp.ports.uiSettingsSaved.send(null);
// }
// }
// });
elmApp.ports.requestUiSettings.subscribe(function(args) {
console.log("Requesting ui settings");
if (Array.isArray(args) && args.length == 2) {
var account = args[0];
var defaults = args[1];
var collective = account ? account.collective : null;
var user = account ? account.user : null;
if (collective && user) {
var key = collective + "/" + user + "/uiSettings";
var settings = localStorage.getItem(key);
var data = settings ? JSON.parse(settings) : null;
if (data && defaults) {
var defaults = extend(defaults, data);
elmApp.ports.receiveUiSettings.send(defaults);
} else if (defaults) {
elmApp.ports.receiveUiSettings.send(defaults);
}
} else if (defaults) {
elmApp.ports.receiveUiSettings.send(defaults);
}
}
});
// elmApp.ports.requestUiSettings.subscribe(function(args) {
// console.log("Requesting ui settings");
// if (Array.isArray(args) && args.length == 2) {
// var account = args[0];
// var defaults = args[1];
// var collective = account ? account.collective : null;
// var user = account ? account.user : null;
// if (collective && user) {
// var key = collective + "/" + user + "/uiSettings";
// var settings = localStorage.getItem(key);
// var data = settings ? JSON.parse(settings) : null;
// if (data && defaults) {
// var defaults = extend(defaults, data);
// elmApp.ports.receiveUiSettings.send(defaults);
// } else if (defaults) {
// elmApp.ports.receiveUiSettings.send(defaults);
// }
// } else if (defaults) {
// elmApp.ports.receiveUiSettings.send(defaults);
// }
// }
// });
var docspell_clipboards = {};