1module UI.Routing.State exposing (linkClicked, openUrlOnNewPage, resetUrl, transition, urlChanged)
2
3import Browser exposing (UrlRequest)
4import Browser.Navigation as Nav
5import List.Extra as List
6import Monocle.Lens as Lens
7import Return exposing (return)
8import Sources
9import Sources.Services.Dropbox
10import Sources.Services.Google
11import UI.Common.State as Common
12import UI.Page as Page exposing (Page)
13import UI.Ports as Ports
14import UI.Sources.Form
15import UI.Sources.Page
16import UI.Sources.State as Sources
17import UI.Sources.Types as Sources
18import UI.Types as UI exposing (Manager)
19import Url exposing (Url)
20
21
22
23-- 🔱
24
25
26linkClicked : UrlRequest -> Manager
27linkClicked urlRequest model =
28 case urlRequest of
29 Browser.Internal urlWithFragment ->
30 let
31 url =
32 if urlWithFragment.fragment == Just "/" then
33 { urlWithFragment | fragment = Nothing }
34
35 else
36 urlWithFragment
37 in
38 if url.path /= model.url.path then
39 return model (Nav.load url.path)
40
41 else
42 return model (Nav.pushUrl model.navKey <| Url.toString url)
43
44 Browser.External href ->
45 return model (Nav.load href)
46
47
48openUrlOnNewPage : String -> Manager
49openUrlOnNewPage url model =
50 url
51 |> Ports.openUrlOnNewPage
52 |> return model
53
54
55urlChanged : Url -> Manager
56urlChanged url model =
57 let
58 rewrittenUrl =
59 Page.rewriteUrl { url | query = Nothing }
60 in
61 case ( url.query, Page.fromUrl rewrittenUrl ) of
62 ( Nothing, Just page ) ->
63 transition page { model | page = page, url = url }
64
65 ( Just _, Just page ) ->
66 return model (resetUrl model.navKey url page)
67
68 _ ->
69 return model (resetUrl model.navKey url Page.Index)
70
71
72
73-- TRANSITIONING
74
75
76transition : Page -> Manager
77transition page model =
78 case page of
79 -----------------------------------------
80 -- Sources.NewThroughRedirect
81 -----------------------------------------
82 Page.Sources (UI.Sources.Page.NewThroughRedirect service args) ->
83 let
84 ( form, defaultContext ) =
85 ( model.sourceForm
86 , UI.Sources.Form.defaultContext
87 )
88 in
89 { defaultContext
90 | data =
91 case service of
92 Sources.Dropbox ->
93 Sources.Services.Dropbox.authorizationSourceData args
94
95 Sources.Google ->
96 Sources.Services.Google.authorizationSourceData args
97
98 _ ->
99 defaultContext.data
100 , service =
101 service
102 }
103 |> (\c -> { form | context = c, step = Sources.By })
104 |> (\f -> { model | sourceForm = f })
105 |> Return.singleton
106
107 -----------------------------------------
108 -- Sources.Edit
109 -----------------------------------------
110 Page.Sources (UI.Sources.Page.Edit sourceId) ->
111 loadSourceForForm sourceId model
112
113 -----------------------------------------
114 -- Sources.Rename
115 -----------------------------------------
116 Page.Sources (UI.Sources.Page.Rename sourceId) ->
117 loadSourceForForm sourceId model
118
119 -----------------------------------------
120 -- 📭
121 -----------------------------------------
122 _ ->
123 Return.singleton model
124
125
126
127-- 🚀
128
129
130resetUrl : Nav.Key -> Url -> Page.Page -> Cmd UI.Msg
131resetUrl key url page =
132 Nav.replaceUrl key (url.path ++ Page.toString page)
133
134
135
136-- ㊙️
137
138
139loadSourceForForm : String -> Manager
140loadSourceForForm sourceId model =
141 let
142 isLoading =
143 model.isLoading
144
145 maybeSource =
146 List.find (.id >> (==) sourceId) model.sources
147 in
148 case ( isLoading, maybeSource ) of
149 ( False, Just source ) ->
150 model
151 |> Lens.modify Sources.formLens (\m -> { m | context = source })
152 |> Return.singleton
153
154 ( False, Nothing ) ->
155 Return.singleton model
156
157 ( True, _ ) ->
158 -- Redirect away from edit-source page
159 Common.changeUrlUsingPage
160 (Page.Sources UI.Sources.Page.Index)
161 model