module Page.Home.Update exposing (update) import Browser.Navigation as Nav import Comp.FixedDropdown import Comp.ItemCardList import Comp.SearchMenu import Data.Flags exposing (Flags) import Data.UiSettings exposing (UiSettings) import Page exposing (Page(..)) import Page.Home.Data exposing (..) import Process import Scroll import Task import Throttle import Time import Util.Html exposing (KeyCode(..)) import Util.ItemDragDrop as DD import Util.Maybe import Util.String import Util.Update update : Maybe String -> Nav.Key -> Flags -> UiSettings -> Msg -> Model -> ( Model, Cmd Msg, Sub Msg ) update mId key flags settings msg model = case msg of Init -> Util.Update.andThen2 [ update mId key flags settings (SearchMenuMsg Comp.SearchMenu.Init) , doSearch flags settings ] model ResetSearch -> let nm = { model | searchOffset = 0 , searchType = defaultSearchType flags } in update mId key flags settings (SearchMenuMsg Comp.SearchMenu.ResetForm) nm SearchMenuMsg m -> let nextState = Comp.SearchMenu.updateDrop model.dragDropData.model flags settings m model.searchMenuModel dropCmd = DD.makeUpdateCmd flags (\_ -> DoSearch) nextState.dragDrop.dropped newModel = { model | searchMenuModel = nextState.model , dragDropData = nextState.dragDrop } ( m2, c2, s2 ) = if nextState.stateChange && not model.searchInProgress then doSearch flags settings newModel else withSub ( newModel, Cmd.none ) in ( m2 , Cmd.batch [ c2 , Cmd.map SearchMenuMsg nextState.cmd , dropCmd ] , s2 ) ItemCardListMsg m -> let result = Comp.ItemCardList.updateDrag model.dragDropData.model flags m model.itemListModel in withSub ( { model | itemListModel = result.model , dragDropData = DD.DragDropData result.dragModel Nothing } , Cmd.batch [ Cmd.map ItemCardListMsg result.cmd ] ) ItemSearchResp (Ok list) -> let noff = settings.itemSearchPageSize m = { model | searchInProgress = False , searchOffset = noff , moreAvailable = list.groups /= [] } in Util.Update.andThen2 [ update mId key flags settings (ItemCardListMsg (Comp.ItemCardList.SetResults list)) , scrollToCard mId ] m ItemSearchAddResp (Ok list) -> let noff = model.searchOffset + settings.itemSearchPageSize m = { model | searchInProgress = False , moreInProgress = False , searchOffset = noff , moreAvailable = list.groups /= [] } in Util.Update.andThen2 [ update mId key flags settings (ItemCardListMsg (Comp.ItemCardList.AddResults list)) , scrollToCard mId ] m ItemSearchAddResp (Err _) -> withSub ( { model | moreInProgress = False } , Cmd.none ) ItemSearchResp (Err _) -> withSub ( { model | searchInProgress = False } , Cmd.none ) DoSearch -> let nm = { model | searchOffset = 0 } in if model.searchInProgress then withSub ( model, Cmd.none ) else doSearch flags settings nm ToggleSearchMenu -> withSub ( { model | menuCollapsed = not model.menuCollapsed } , Cmd.none ) LoadMore -> if model.moreAvailable then doSearchMore flags settings model |> withSub else withSub ( model, Cmd.none ) UpdateThrottle -> let ( newThrottle, cmd ) = Throttle.update model.throttle in withSub ( { model | throttle = newThrottle }, cmd ) SetBasicSearch str -> let smMsg = case model.searchTypeForm of BasicSearch -> SearchMenuMsg (Comp.SearchMenu.SetAllName str) ContentSearch -> SearchMenuMsg (Comp.SearchMenu.SetFulltext str) ContentOnlySearch -> SetContentOnly str in update mId key flags settings smMsg model SetContentOnly str -> withSub ( { model | contentOnlySearch = Util.Maybe.fromString str } , Cmd.none ) SearchTypeMsg lm -> let ( sm, mv ) = Comp.FixedDropdown.update lm model.searchTypeDropdown mvChange = Util.Maybe.filter (\a -> a /= model.searchTypeForm) mv m0 = { model | searchTypeDropdown = sm , searchTypeForm = Maybe.withDefault model.searchTypeForm mv } next = case mvChange of Just BasicSearch -> Just ( { m0 | contentOnlySearch = Nothing } , Maybe.withDefault "" model.contentOnlySearch ) Just ContentOnlySearch -> Just ( { m0 | contentOnlySearch = model.searchMenuModel.allNameModel } , "" ) _ -> Nothing in case next of Just ( m_, nstr ) -> update mId key flags settings (SearchMenuMsg (Comp.SearchMenu.SetAllName nstr)) m_ Nothing -> withSub ( m0, Cmd.none ) KeyUpMsg (Just Enter) -> update mId key flags settings DoSearch model KeyUpMsg _ -> withSub ( model, Cmd.none ) ScrollResult _ -> let cmd = Process.sleep 800 |> Task.perform (always ClearItemDetailId) in withSub ( model, cmd ) ClearItemDetailId -> noSub ( { model | scrollToCard = Nothing }, Cmd.none ) --- Helpers scrollToCard : Maybe String -> Model -> ( Model, Cmd Msg, Sub Msg ) scrollToCard mId model = let scroll id = Scroll.scroll id 0.5 0.5 0.5 0.5 in case mId of Just id -> ( { model | scrollToCard = mId } , Task.attempt ScrollResult (scroll id) , Sub.none ) Nothing -> ( model, Cmd.none, Sub.none ) doSearch : Flags -> UiSettings -> Model -> ( Model, Cmd Msg, Sub Msg ) doSearch flags settings model = let stype = if not model.menuCollapsed || Util.String.isNothingOrBlank model.contentOnlySearch then BasicSearch else model.searchTypeForm model_ = { model | searchType = stype } searchCmd = doSearchCmd flags settings 0 model_ ( newThrottle, cmd ) = Throttle.try searchCmd model.throttle in withSub ( { model_ | searchInProgress = cmd /= Cmd.none , searchOffset = 0 , throttle = newThrottle } , cmd ) doSearchMore : Flags -> UiSettings -> Model -> ( Model, Cmd Msg ) doSearchMore flags settings model = let cmd = doSearchCmd flags settings model.searchOffset model in ( { model | moreInProgress = True } , cmd ) withSub : ( Model, Cmd Msg ) -> ( Model, Cmd Msg, Sub Msg ) withSub ( m, c ) = ( m , c , Throttle.ifNeeded (Time.every 500 (\_ -> UpdateThrottle)) m.throttle ) noSub : ( Model, Cmd Msg ) -> ( Model, Cmd Msg, Sub Msg ) noSub ( m, c ) = ( m, c, Sub.none )