A music player that connects to your cloud/distributed storage.
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

Update source and save collection

+33 -16
+22 -7
src/Applications/Brain/Other/State.elm
··· 4 4 import Brain.Common.State as Common 5 5 import Brain.Ports as Ports 6 6 import Brain.Types exposing (..) 7 + import Dict 7 8 import Json.Decode as Json 8 - import Return 9 + import List.Extra as List 10 + import Return exposing (return) 9 11 import Return.Ext as Return 10 12 import Sources exposing (Service(..)) 13 + import Sources.Encoding 11 14 import Sources.Refresh.AccessToken 12 15 import Time 13 16 ··· 22 25 Ok portArguments -> 23 26 case portArguments.service of 24 27 Google -> 25 - -- TODO: 26 - -- 1. Find source 27 - -- 2. Add `access token` and `expires at` to source data 28 - -- 3. Replace source in collection 29 - -- 4. Save user data 30 - Return.singleton model 28 + model.hypaethralUserData.sources 29 + |> List.find (.id >> (==) portArguments.sourceId) 30 + |> Maybe.map 31 + (\source -> 32 + source.data 33 + |> Dict.insert "accessToken" portArguments.accessToken 34 + |> Dict.insert "expiresAt" (String.fromInt portArguments.expiresAt) 35 + |> (\newData -> { source | data = newData }) 36 + ) 37 + |> Maybe.map 38 + (\source -> 39 + source 40 + |> Sources.Encoding.encode 41 + |> Alien.broadcast Alien.UpdateSourceData 42 + |> Ports.toUI 43 + ) 44 + |> Maybe.withDefault Cmd.none 45 + |> return model 31 46 32 47 _ -> 33 48 Return.singleton model
+7 -5
src/Javascript/Workers/service.js
··· 13 13 14 14 const EXCLUDE = 15 15 [ "_headers" 16 - , "_redirects" 17 - , "CORS" 16 + , "_redirects" 17 + , "CORS" 18 18 ] 19 19 20 20 ··· 79 79 "Basic " + token 80 80 ) 81 81 82 - // When doing a request with access token in the url, put it in the headers instead 82 + // When doing a request with access token in the url, put it in the headers instead 83 83 } else if (event.request.url.includes("bearer_token=")) { 84 84 const url = new URL(event.request.url) 85 85 const token = url.searchParams.get("bearer_token") ··· 95 95 "Bearer " + token 96 96 ) 97 97 98 - // Use cache if internal request and not using native app 98 + // Use cache if internal request and not using native app 99 99 } else if (isInternal) { 100 100 event.respondWith( 101 101 isNativeWrapper ··· 152 152 request.headers.entries() 153 153 ) 154 154 155 - newHeaders["authorization"] = authToken 155 + newHeaders[ "authorization" ] = authToken 156 156 157 157 const newRequest = new Request( 158 158 new Request(urlWithoutToken, event.request), ··· 170 170 171 171 let retries = 0 172 172 173 + // TODO: When request fails because access token is expired, 174 + // refresh the token, and retry the request. 173 175 const makeFetch = () => fetch(newRequest).then(r => { 174 176 if (r.ok) { 175 177 retries = 0
+2 -2
src/Javascript/audio-engine.js
··· 214 214 n => n.parentNode.removeChild(n) 215 215 ) 216 216 217 - // audio element remains valid for 2 hours 217 + // audio element remains valid for 45 minutes 218 218 transformUrl(queueItem.url, orchestrion.app).then(url => { 219 219 const queueItemWithTransformedUrl = 220 220 Object.assign({}, queueItem, { url: url }) ··· 222 222 createAudioElement( 223 223 orchestrion, 224 224 queueItemWithTransformedUrl, 225 - Date.now() + 1000 * 60 * 60 * 2, 225 + Date.now() + 1000 * 60 * 45, 226 226 true 227 227 ) 228 228 })
+2 -2
src/Javascript/urls.js
··· 107 107 refreshToken 108 108 } 109 109 110 - app.ports.refreshAccessToken.send({ 111 - service: "google", 110 + app.ports.refreshedAccessToken.send({ 111 + service: "Google", 112 112 sourceId: srcId, 113 113 accessToken: newToken, 114 114 expiresAt: newExpiresAt