A music player that connects to your cloud/distributed storage.
1module UI.Page exposing (Page(..), fromUrl, rewriteUrl, sameBase, sources, toString)
2
3import Maybe.Extra as Maybe
4import Sources exposing (Service(..))
5import UI.Playlists.Page as Playlists
6import UI.Queue.Page as Queue
7import UI.Settings.Page as Settings
8import UI.Sources.Page as Sources
9import Url exposing (Url)
10import Url.Ext as Url
11import Url.Parser exposing (..)
12import Url.Parser.Query as Query
13
14
15
16-- 🌳
17
18
19type Page
20 = Index
21 | Queue Queue.Page
22 | Playlists Playlists.Page
23 | Settings Settings.Page
24 | Sources Sources.Page
25
26
27
28-- 🔱
29
30
31fromUrl : Url -> Maybe Page
32fromUrl =
33 parse route
34
35
36rewriteUrl : Url -> Url
37rewriteUrl url =
38 if Maybe.unwrap False (String.contains "path=") url.query then
39 -- Sometimes we have to use this kind of routing when doing redirections
40 let
41 maybePath =
42 Url.extractQueryParam "path" url
43
44 path =
45 Maybe.withDefault "" maybePath
46 in
47 if
48 Maybe.unwrap
49 False
50 (\f -> String.contains "token=" f || String.contains "code=" f)
51 url.fragment
52 then
53 -- For some oauth stuff, replace the query with the fragment
54 { url | path = path, query = url.fragment }
55
56 else
57 { url | path = path }
58
59 else
60 -- Otherwise do hash-based routing and replace the path with the fragment
61 { url | path = Maybe.withDefault "" url.fragment }
62
63
64toString : Page -> String
65toString =
66 toString_ >> (++) "#/"
67
68
69toString_ : Page -> String
70toString_ page =
71 case page of
72 Index ->
73 ""
74
75 -----------------------------------------
76 -- Playlists
77 -----------------------------------------
78 Playlists Playlists.Index ->
79 "playlists"
80
81 Playlists Playlists.NewCollection ->
82 "playlists/new/collection"
83
84 Playlists Playlists.NewPlaylist ->
85 "playlists/new/playlist"
86
87 Playlists (Playlists.Edit playlistName) ->
88 "playlists/edit/" ++ playlistName
89
90 -----------------------------------------
91 -- Queue
92 -----------------------------------------
93 Queue Queue.History ->
94 "queue/history"
95
96 Queue Queue.Index ->
97 "queue"
98
99 -----------------------------------------
100 -- Settings
101 -----------------------------------------
102 Settings Settings.Data ->
103 "settings/data"
104
105 Settings Settings.Index ->
106 "settings"
107
108 Settings Settings.Sync ->
109 "settings/sync"
110
111 -----------------------------------------
112 -- Sources
113 -----------------------------------------
114 Sources (Sources.Edit sourceId) ->
115 "sources/edit/" ++ sourceId
116
117 Sources Sources.Index ->
118 "sources"
119
120 Sources Sources.New ->
121 "sources/new"
122
123 Sources Sources.NewOnboarding ->
124 "sources/welcome"
125
126 Sources (Sources.NewThroughRedirect Dropbox _) ->
127 "sources/new/dropbox"
128
129 Sources (Sources.NewThroughRedirect Google _) ->
130 "sources/new/google"
131
132 Sources (Sources.NewThroughRedirect _ _) ->
133 "sources/new"
134
135 Sources (Sources.Rename sourceId) ->
136 "sources/rename/" ++ sourceId
137
138
139{-| Are the bases of these two pages the same?
140-}
141sameBase : Page -> Page -> Bool
142sameBase a b =
143 case ( a, b ) of
144 ( Playlists _, Playlists _ ) ->
145 True
146
147 ( Queue _, Queue _ ) ->
148 True
149
150 ( Settings _, Settings _ ) ->
151 True
152
153 ( Sources _, Sources _ ) ->
154 True
155
156 ( Index, Playlists _ ) ->
157 True
158
159 ( Index, Queue _ ) ->
160 True
161
162 _ ->
163 a == b
164
165
166
167-- 🔱 ░░ SPECIFIC
168
169
170sources : Page -> Maybe Sources.Page
171sources page =
172 case page of
173 Sources s ->
174 Just s
175
176 _ ->
177 Nothing
178
179
180
181-- ⚗️
182
183
184route : Parser (Page -> a) a
185route =
186 oneOf
187 [ map Index top
188
189 -----------------------------------------
190 -- Playlists
191 -----------------------------------------
192 , map (Playlists Playlists.Index) (s "playlists")
193 , map (Playlists << Playlists.Edit) (s "playlists" </> s "edit" </> string)
194 , map (Playlists Playlists.NewCollection) (s "playlists" </> s "new" </> s "collection")
195 , map (Playlists Playlists.NewPlaylist) (s "playlists" </> s "new" </> s "playlist")
196
197 -----------------------------------------
198 -- Queue
199 -----------------------------------------
200 , map (Queue Queue.Index) (s "queue")
201 , map (Queue Queue.History) (s "queue" </> s "history")
202
203 -----------------------------------------
204 -- Settings
205 -----------------------------------------
206 , map (Settings Settings.Data) (s "settings" </> s "data")
207 , map (Settings Settings.Sync) (s "settings" </> s "sync")
208 , map (Settings Settings.Index) (s "settings")
209
210 -----------------------------------------
211 -- Sources
212 -----------------------------------------
213 , map (Sources Sources.Index) (s "sources")
214 , map (Sources << Sources.Edit) (s "sources" </> s "edit" </> string)
215 , map (Sources Sources.New) (s "sources" </> s "new")
216 , map (Sources Sources.NewOnboarding) (s "sources" </> s "welcome")
217 , map (Sources << Sources.Rename) (s "sources" </> s "rename" </> string)
218
219 -- Oauth
220 --------
221 , map
222 (\token state ->
223 { codeOrToken = token, state = state }
224 |> Sources.NewThroughRedirect Dropbox
225 |> Sources
226 )
227 (s "sources"
228 </> s "new"
229 </> s "dropbox"
230 <?> Query.string "access_token"
231 <?> Query.string "state"
232 )
233 , map
234 (\code state ->
235 { codeOrToken = code, state = state }
236 |> Sources.NewThroughRedirect Google
237 |> Sources
238 )
239 (s "sources"
240 </> s "new"
241 </> s "google"
242 <?> Query.string "code"
243 <?> Query.string "state"
244 )
245 ]