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

Configure Feed

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

Merge pull request #46 from icidasset/remotestorage

Add remoteStorage integration

authored by

Steven Vandevelde and committed by
GitHub
25b3fdfe 18eb3995

+305 -18
+13
package-lock.json
··· 4248 4248 "integrity": "sha1-mxpsNdTQ3871cRrmUejp09cRQUU=", 4249 4249 "dev": true 4250 4250 }, 4251 + "remotestoragejs": { 4252 + "version": "github:remotestorage/remotestorage.js#6c32e7b0c387c96838ee5dab332e584eedffc807" 4253 + }, 4251 4254 "remove-trailing-separator": { 4252 4255 "version": "1.1.0", 4253 4256 "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", ··· 4642 4645 "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", 4643 4646 "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=" 4644 4647 }, 4648 + "tv4": { 4649 + "version": "1.3.0", 4650 + "resolved": "https://registry.npmjs.org/tv4/-/tv4-1.3.0.tgz", 4651 + "integrity": "sha1-0CDIRvrdUMhVq7JeuuzGj8EPeWM=" 4652 + }, 4645 4653 "tweetnacl": { 4646 4654 "version": "0.14.5", 4647 4655 "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", ··· 4734 4742 "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", 4735 4743 "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", 4736 4744 "dev": true 4745 + }, 4746 + "webfinger.js": { 4747 + "version": "2.6.6", 4748 + "resolved": "https://registry.npmjs.org/webfinger.js/-/webfinger.js-2.6.6.tgz", 4749 + "integrity": "sha512-dQpuL01XtluQ9Ndgu62o3pEmIe/ssDoIE0CQsOyavGl04xyHal+Ge4gFerw5V0BFoLTQpD8ZZqaDzb43hG9atw==" 4737 4750 }, 4738 4751 "whatwg-fetch": { 4739 4752 "version": "2.0.3",
+1
package.json
··· 14 14 "elasticlunr": "^0.9.5", 15 15 "elm-doctest": "^0.3.5", 16 16 "jsmediatags": "^3.8.0", 17 + "remotestoragejs": "github:remotestorage/remotestorage.js#master", 17 18 "tocca": "^2.0.1" 18 19 } 19 20 }
+18 -3
src/App/Authentication/State.elm
··· 218 218 ] 219 219 220 220 Ok _ -> 221 - handleError model "Invalid response from SignIn" 221 + (!) 222 + model 223 + [ afterwards 224 + , displayError "Invalid response from SignIn" 225 + , issue MethodUnset 226 + ] 222 227 223 228 Err err -> 224 - handleError model err 229 + (!) 230 + model 231 + [ afterwards 232 + , displayError err 233 + , issue MethodUnset 234 + ] 225 235 226 236 Incoming SignIn (Err err) -> 227 - handleError model err 237 + (!) 238 + model 239 + [ afterwards 240 + , displayError err 241 + , issue MethodUnset 242 + ] 228 243 229 244 ------------------------------------ 230 245 -- Sign out
+6
src/App/Authentication/Transformers.elm
··· 16 16 "LOCAL" -> 17 17 Local 18 18 19 + "REMOTE_STORAGE" -> 20 + RemoteStorage 21 + 19 22 _ -> 20 23 Debug.crash "Invalid authentication method" 21 24 ··· 28 31 29 32 Local -> 30 33 "LOCAL" 34 + 35 + RemoteStorage -> 36 + "REMOTE_STORAGE" 31 37 32 38 33 39
+1
src/App/Authentication/Types.elm
··· 67 67 type Method 68 68 = Blockstack 69 69 | Local 70 + | RemoteStorage 70 71 71 72 72 73 type alias UserData =
+3
src/App/Settings/View.elm
··· 69 69 70 70 Local -> 71 71 text "anonymous" 72 + 73 + RemoteStorage -> 74 + text "RemoteStorage" 72 75 , text " authentication mode." 73 76 ] 74 77 , Html.map SettingsMsg (theForm model)
+32
src/App/View.elm
··· 231 231 ] 232 232 ] 233 233 [ authButton Blockstack 234 + , authButton RemoteStorage 234 235 , authButton Local 235 236 ] 236 237 ] ··· 294 295 [ blockstackLogo ] 295 296 , text "Sign in with Blockstack" 296 297 ] 298 + 299 + RemoteStorage -> 300 + [ span 301 + [ style [ ( "fontSize", intoRem 17 ) ] ] 302 + [ remoteStorageLogo ] 303 + , text "Sign in with Remote Storage" 304 + ] 297 305 ) 298 306 299 307 ··· 322 330 ] 323 331 [] 324 332 ] 333 + ] 334 + 335 + 336 + remoteStorageLogo : Svg Msg 337 + remoteStorageLogo = 338 + Svg.svg 339 + [ height "0.739008in" 340 + , width "0.853339in" 341 + 342 + -- 343 + , viewBox "0 0 739 853" 344 + , style 345 + [ ( "shape-rendering", "geometricPrecision" ) 346 + , ( "text-rendering", "geometricPrecision" ) 347 + , ( "image-rendering", "optimizeQuality" ) 348 + , ( "clip-rule", "evenodd" ) 349 + , ( "fill-rule", "evenodd" ) 350 + ] 351 + ] 352 + [ Svg.polygon 353 + [ Svg.Attributes.fill "#FF4B03" 354 + , Svg.Attributes.points "370,754 0,542 0,640 185,747 370,853 554,747 739,640 739,525 739,525 739,476 739,427 739,378 653,427 370,589 86,427 86,427 86,361 185,418 370,524 554,418 653,361 739,311 739,213 739,213 554,107 370,0 185,107 58,180 144,230 228,181 370,100 511,181 652,263 370,425 87,263 87,263 0,213 0,213 0,311 0,378 0,427 0,476 86,525 185,582 370,689 554,582 653,525 653,590 653,592" 355 + ] 356 + [] 325 357 ] 326 358 327 359
+1
src/Css/Styles.elm
··· 321 321 , lineHeight (gr 3) 322 322 , padding2 (basem 15) zero 323 323 , property "padding-top" ("calc(" ++ .value (basem 15) ++ " + 1px)") 324 + , textAlign left 324 325 , width (basem 260) 325 326 326 327 --
+62
src/Js/Workers/Authentication/remoteStorage.js
··· 1 + importScripts("/vendor/package.js"); 2 + 3 + 4 + const KEY = "isotach"; 5 + const rs = new RemoteStorage({ cache: false }); 6 + 7 + 8 + rs.access.claim(KEY, "rw"); 9 + 10 + 11 + const client = rs.scope(`/${KEY}/`); 12 + 13 + 14 + self.postMessage({ action: "CONSTRUCT_SUCCESS" }); 15 + 16 + 17 + 18 + // 19 + // Incoming messages 20 + 21 + self.onmessage = event => { 22 + if (!rs.remote.connected) { 23 + rs.on("connected", () => tackle(event)); 24 + rs.connect(event.data.data.userAddress, event.data.data.token); 25 + 26 + } else { 27 + tackle(event); 28 + 29 + } 30 + }; 31 + 32 + 33 + function tackle(event) { 34 + switch (event.data.action) { 35 + case "GET": return get(); 36 + case "SET": return set(event.data.data.json); 37 + } 38 + } 39 + 40 + 41 + 42 + // 43 + // Get 44 + 45 + function get() { 46 + client.getFile(`${KEY}.json`).then( 47 + res => self.postMessage({ action: "GET_SUCCESS", data: res.data }), 48 + err => self.postMessage({ action: "GET_SUCCESS", data: null }) 49 + ); 50 + } 51 + 52 + 53 + 54 + // 55 + // Set 56 + 57 + function set(json) { 58 + client.storeFile("application/json", `${KEY}.json`, json).then( 59 + res => self.postMessage({ action: "SET_SUCCESS" }), 60 + err => self.postMessage({ action: "SET_FAILURE", data: err }) 61 + ); 62 + }
+166 -15
src/Js/authentication.js
··· 5 5 // Different integrations for authentication: 6 6 // 1. Local (indexedDB) 7 7 // 2. Blockstack 8 + // 3. Remote Storage 8 9 9 10 const AUTH_SYSTEM = {}; 10 11 11 12 12 13 13 14 // 14 - // > Utilities 15 + // 🖍 Utensils 16 + 17 + function construct(workerName) { 18 + return new Promise((resolve, reject) => { 19 + let worker; 20 + 21 + worker = new Worker(`/workers/authentication/${workerName}.js`); 22 + worker.onmessage = event => { 23 + worker.onmessage = null; 24 + 25 + switch (event.data.action) { 26 + case "CONSTRUCT_SUCCESS": return resolve(worker); 27 + case "CONSTRUCT_FAILURE": return reject(); 28 + } 29 + }; 30 + }); 31 + } 32 + 15 33 16 34 function doWork(worker, requisites) { 17 35 const timeoutId = setTimeout(_ => { ··· 68 86 69 87 AUTH_SYSTEM.LOCAL = { 70 88 71 - construct: promised((resolve, reject) => { 72 - worker = new Worker("/workers/authentication/local.js"); 73 - worker.onmessage = event => { 74 - worker.onmessage = null; 75 - 76 - switch (event.data.action) { 77 - case "CONSTRUCT_SUCCESS": return resolve(); 78 - case "CONSTRUCT_FAILURE": return reject(); 79 - } 80 - }; 81 - }), 89 + construct: () => ( 90 + construct("local").then(w => worker = w) 91 + ), 82 92 83 93 deconstruct: resolved(() => { 84 94 worker.terminate(); ··· 168 178 169 179 AUTH_SYSTEM.BLOCKSTACK = { 170 180 171 - construct: resolved(() => { 172 - worker = new Worker("/workers/authentication/blockstack.js"); 173 - }), 181 + construct: () => ( 182 + construct("blockstack").then(w => worker = w) 183 + ), 174 184 175 185 deconstruct: resolved(() => { 176 186 worker.terminate(); ··· 224 234 } 225 235 226 236 })(); 237 + 238 + 239 + 240 + // 241 + // 3. Remote Storage 242 + 243 + (() => { 244 + 245 + const KEY = "isotach"; 246 + 247 + let isConstructed = false; 248 + let rs; 249 + let worker; 250 + 251 + 252 + function setInstance() { 253 + if (!rs) { 254 + rs = new RemoteStorage({ cache: false }); 255 + rs.access.claim(KEY, "rw"); 256 + } 257 + } 258 + 259 + function destroyInstance() { 260 + if (rs) { 261 + rs.disconnect(); 262 + rs = null; 263 + } 264 + } 265 + 266 + 267 + AUTH_SYSTEM.REMOTE_STORAGE = { 268 + 269 + construct: () => ( 270 + construct("remoteStorage").then(w => worker = w) 271 + ), 272 + 273 + deconstruct: resolved(() => { 274 + worker.terminate(); 275 + worker = null; 276 + }), 277 + 278 + // In & Out 279 + 280 + isSignedIn: promised((resolve, reject) => { 281 + let timeoutId; 282 + 283 + setInstance(); 284 + 285 + rs.on( 286 + "connected", 287 + () => { 288 + clearTimeout(timeoutId); 289 + resolve(true); 290 + rs.off("connected"); 291 + } 292 + ); 293 + 294 + timeoutId = setTimeout( 295 + () => { 296 + resolve(false); 297 + rs.off("connected"); 298 + }, 299 + 10000 300 + ); 301 + }), 302 + 303 + isSigningIn: Promise.resolve( 304 + false 305 + ), 306 + 307 + handleSignInProcess: Promise.resolve( 308 + "KeepUrl" 309 + ), 310 + 311 + signIn: promised((resolve, reject) => { 312 + const userAddress = prompt( 313 + "Which user address would you like to use?" 314 + ); 315 + 316 + if (!userAddress || userAddress.length === 0) { 317 + return reject("You need to fill in a user address in order to use this service."); 318 + } 319 + 320 + setInstance(); 321 + 322 + rs.on("connected", _ => resolve("Redirect")); 323 + rs.on("error", err => reject(err.message)); 324 + rs.connect(userAddress); 325 + }), 326 + 327 + signOut: resolved(() => { 328 + setInstance(); 329 + destroyInstance(); 330 + }), 331 + 332 + // Get data 333 + 334 + getData: promised((resolve, reject) => { 335 + const handler = event => { 336 + switch (event.data.action) { 337 + case "GET_SUCCESS": return event.data.data 338 + ? resolve( event.data.data ) 339 + : resolve( null ); 340 + 341 + case "GET_FAILURE": return reject(`Failed to get data, ${event.data.data}.`); 342 + default: return reject("Unavailable"); 343 + } 344 + }; 345 + 346 + doWork(worker, { 347 + action: "GET", 348 + data: { token: rs.remote.token, userAddress: rs.remote.userAddress }, 349 + resolve: resolve, 350 + reject: reject, 351 + handler: handler 352 + }); 353 + }), 354 + 355 + // Store data 356 + 357 + storeData: json => new Promise((resolve, reject) => { 358 + const handler = event => { 359 + switch (event.data.action) { 360 + case "SET_SUCCESS": return resolve(); 361 + case "SET_FAILURE": return reject(`Failed to store data, ${event.data.data}.`); 362 + default: return reject("Unavailable"); 363 + } 364 + }; 365 + 366 + doWork(worker, { 367 + action: "SET", 368 + data: { json: json, token: rs.remote.token, userAddress: rs.remote.userAddress }, 369 + resolve: resolve, 370 + reject: reject, 371 + handler: handler 372 + }); 373 + }) 374 + 375 + } 376 + 377 + })();
+2
src/Vendor/package.js
··· 6 6 self.camelcase = require("camelcase"); 7 7 self.elasticlunr = require("elasticlunr"); 8 8 9 + self.RemoteStorage = require("remotestoragejs"); 10 + 9 11 if (self.document) { 10 12 self.tocca = require("tocca"); 11 13 }