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.

Enable encryption for all storage methods and add new auth screen

+198 -55
+3
src/Applications/Brain.elm
··· 411 411 translateAlienError : Alien.Event -> String -> Msg 412 412 translateAlienError event err = 413 413 case Alien.tagFromString event.tag of 414 + Just Alien.AuthAnonymous -> 415 + report Alien.AuthAnonymous "I couldn't decrypt your data, maybe you used the wrong passphrase?" 416 + 414 417 Just Alien.AuthIpfs -> 415 418 report Alien.AuthIpfs "Something went wrong regarding the IPFS storage. Maybe you used the wrong passphrase, or your IPFS node is offline?" 416 419
+1 -1
src/Applications/UI.elm
··· 833 833 834 834 loadingAnimation : Html msg 835 835 loadingAnimation = 836 - Html.map never UI.Svg.Elements.loading 836 + Html.map never (Html.fromUnstyled UI.Svg.Elements.loading) 837 837 838 838 839 839 overlay : Maybe (ContextMenu Msg) -> Html Msg
+55 -16
src/Applications/UI/Authentication.elm
··· 14 14 import Html.Styled.Events exposing (onClick, onSubmit) 15 15 import Json.Decode as Json 16 16 import Json.Encode 17 - import Material.Icons.Action as Icons 17 + import Material.Icons.Av as Icons 18 18 import Replying exposing (R3D3, andThen3) 19 19 import Return2 as R2 20 20 import Return3 as R3 ··· 23 23 import UI.Kit 24 24 import UI.Ports as Ports 25 25 import UI.Reply exposing (Reply(..)) 26 + import UI.Svg.Elements 26 27 27 28 28 29 ··· 195 196 , T.items_center 196 197 ] 197 198 [ brick 198 - [ style "height" "45%" ] 199 + [ style "height" "42%" ] 199 200 [ T.flex 200 201 , T.items_center 201 202 ] ··· 239 240 |> speechBubble 240 241 241 242 _ -> 242 - nothing 243 + [ text "Where would you like to" 244 + , lineBreak 245 + , text "store your encrypted data?" 246 + ] 247 + |> chunk [] 248 + |> speechBubble 243 249 ] 244 250 ] 245 251 ··· 321 327 , T.pv2 322 328 ] 323 329 [ choiceButton 324 - { action = SignIn Authentication.Local 325 - , icon = Icons.lock_open 330 + { action = ShowNewEncryptionKeyScreen Authentication.Local 331 + , icon = Icons.web 326 332 , isLast = False 327 - , label = "Store data in the browser" 333 + , label = "My Browser" 334 + , outOfOrder = False 335 + } 336 + , choiceButton 337 + { action = Bypass 338 + , icon = \_ _ -> Svg.map never UI.Svg.Elements.blockstackLogo 339 + , isLast = False 340 + , label = "Blockstack" 341 + , outOfOrder = True 328 342 } 329 343 , choiceButton 330 344 { action = ShowNewEncryptionKeyScreen Authentication.Ipfs 331 - , icon = Icons.fingerprint 345 + , icon = \_ _ -> Svg.map never UI.Svg.Elements.ipfsLogo 346 + , isLast = False 347 + , label = "IPFS" 348 + , outOfOrder = False 349 + } 350 + , choiceButton 351 + { action = Bypass 352 + , icon = \_ _ -> Svg.map never UI.Svg.Elements.remoteStorageLogo 353 + , isLast = False 354 + , label = "RemoteStorage" 355 + , outOfOrder = True 356 + } 357 + , choiceButton 358 + { action = Bypass 359 + , icon = \_ _ -> Svg.map never UI.Svg.Elements.solidLogo 332 360 , isLast = True 333 - , label = "Store encrypted data on IPFS" 361 + , label = "Solid" 362 + , outOfOrder = True 334 363 } 335 364 ] 336 365 ··· 340 369 , icon : Color -> Int -> Svg msg 341 370 , isLast : Bool 342 371 , label : String 372 + , outOfOrder : Bool 343 373 } 344 374 -> Html msg 345 - choiceButton { action, icon, isLast, label } = 375 + choiceButton { action, icon, isLast, label, outOfOrder } = 346 376 slab 347 377 button 348 378 [ css (choiceButtonStyles { border = not isLast }) ··· 358 388 , T.pv3 359 389 , T.tl 360 390 ] 361 - [ slab 362 - span 363 - [] 364 - [ T.inline_flex, T.mr3 ] 365 - [ fromUnstyled (icon UI.Kit.colors.text 16) ] 366 - , text label 391 + [ -- TODO: Remove `chunk` + outOfOrder when everything is implemented 392 + chunk 393 + [ T.flex 394 + , T.items_center 395 + 396 + -- 397 + , ifThenElse outOfOrder T.o_20 T.o_100 398 + ] 399 + [ slab 400 + span 401 + [] 402 + [ T.inline_flex, T.mr3 ] 403 + [ fromUnstyled (icon UI.Kit.colors.text 16) ] 404 + , text label 405 + ] 367 406 ] 368 407 369 408 ··· 407 446 (ifThenElse border (px 1) (px 0)) 408 447 solid 409 448 (Color.toElmCssColor UI.Kit.colors.subtleBorder) 410 - , Css.minWidth (px 260) 449 + , Css.minWidth (px 210) 411 450 ] 412 451 413 452
+11 -14
src/Applications/UI/Settings.elm
··· 62 62 , text "PS. You're storing the data for this application " 63 63 , case UI.Authentication.extractMethod model.authentication of 64 64 Just Ipfs -> 65 - inline 66 - [] 67 - [ text "on IPFS." 68 - , lineBreak 69 - , text "If you want to, you can " 70 - , UI.Kit.textButton 71 - { label = "change your passphrase" 72 - , onClick = 73 - Ipfs 74 - |> UI.Authentication.ShowUpdateEncryptionKeyScreen 75 - |> UI.Core.AuthenticationMsg 76 - } 77 - , text "." 78 - ] 65 + text "on IPFS." 79 66 80 67 Just Local -> 81 68 text "in this browser." 82 69 83 70 Nothing -> 84 71 text "on nothing, wtf?" 72 + , lineBreak 73 + , text "If you want to, you can " 74 + , UI.Kit.textButton 75 + { label = "change your passphrase" 76 + , onClick = 77 + Ipfs 78 + |> UI.Authentication.ShowUpdateEncryptionKeyScreen 79 + |> UI.Core.AuthenticationMsg 80 + } 81 + , text "." 85 82 ] 86 83 |> raw 87 84 |> UI.Kit.intro
+98 -19
src/Applications/UI/Svg/Elements.elm
··· 1 - module UI.Svg.Elements exposing (blockstackLogo, loading, remoteStorageLogo) 1 + module UI.Svg.Elements exposing (blockstackLogo, ipfsLogo, loading, remoteStorageLogo, solidLogo) 2 2 3 - import Html.Styled.Attributes as Attributes 4 - import Svg.Styled as Svg exposing (..) 5 - import Svg.Styled.Attributes exposing (..) 3 + import Color 4 + import Svg exposing (..) 5 + import Svg.Attributes exposing (..) 6 + import UI.Kit 6 7 7 8 8 9 ··· 12 13 blockstackLogo : Svg Never 13 14 blockstackLogo = 14 15 svg 15 - [ height "22" 16 - , viewBox "0 0 512 512" 17 - , width "22" 16 + [ height "16" 17 + , viewBox "0 0 80 80" 18 + , width "16" 18 19 ] 19 - [ g 20 - [ fill "none" 20 + [ Svg.path 21 + [ d "M0.986947 7.23422C-3.72529e-07 9.51492 -2.53999e-07 12.4233 2.57986e-10 18.24L9.51418e-07 40L1.90258e-06 61.76C2.15683e-06 67.5767 0 70.4851 0.986947 72.7658C2.19911 75.5669 4.43309 77.8009 7.23423 79.0131C9.51492 80 12.4233 80 18.24 80H40H61.76C67.5767 80 70.4851 80 72.7658 79.0131C75.5669 77.8009 77.8009 75.5669 79.0131 72.7658C80 70.4851 80 67.5767 80 61.76V40V18.24C80 12.4233 80 9.51492 79.0131 7.23422C77.8009 4.43309 75.5669 2.1991 72.7658 0.986942C70.4851 -4.47035e-07 67.5767 -2.53999e-07 61.76 2.58033e-10L40 9.51418e-07L18.24 1.90258e-06C12.4233 2.15684e-06 9.375 1.93715e-06 7.23423 0.986945C4.43309 2.19911 2.19911 4.43309 0.986947 7.23422ZM52.7711 34.4643C48.7788 34.4643 45.5416 31.2272 45.5416 27.2341C45.5416 23.2429 48.7788 20.0059 52.7711 20.0059C56.7633 20.0059 60.0005 23.2429 60.0005 27.2341C60.0005 31.2272 56.7633 34.4643 52.7711 34.4643ZM34.4525 27.2334C34.4525 31.2239 31.2169 34.4596 27.2255 34.4596C23.2361 34.4596 20.0005 31.2239 20.0005 27.2334C20.0005 23.2429 23.2361 20.0072 27.2255 20.0072C31.2169 20.0072 34.4525 23.2429 34.4525 27.2334ZM52.7718 45.5639C48.7786 45.5639 45.5415 48.8011 45.5415 52.7934C45.5415 56.7856 48.7786 60.0228 52.7718 60.0228C56.7629 60.0228 60 56.7856 60 52.7934C60 48.8011 56.7629 45.5639 52.7718 45.5639ZM27.2261 45.571C31.2166 45.571 34.4522 48.8066 34.4522 52.7979C34.4522 56.7872 31.2166 60.0228 27.2261 60.0228C23.2357 60.0228 20 56.7872 20 52.7979C20 48.8066 23.2357 45.571 27.2261 45.571Z" 22 + 23 + -- 24 + , fill (Color.toCssString UI.Kit.colors.text) 21 25 , fillRule "evenodd" 26 + , clipRule "evenodd" 22 27 ] 28 + [] 29 + ] 30 + 31 + 32 + ipfsLogo : Svg Never 33 + ipfsLogo = 34 + svg 35 + [ height "16" 36 + , viewBox "0 0 511.99999 511.99998" 37 + , width "16" 38 + ] 39 + [ -- Group 1 40 + ---------- 41 + g 42 + [ transform "translate(-50.017 -515.51)" ] 23 43 [ Svg.path 24 - [ d "M186.673352,210.979293 C163.559368,210.979293 144.821782,192.302202 144.821782,169.262843 C144.821782,146.223483 163.559368,127.546392 186.673352,127.546392 C209.787336,127.546392 228.524922,146.223483 228.524922,169.262843 C228.524922,192.302202 209.787336,210.979293 186.673352,210.979293 Z M354.079631,210.979293 C330.965647,210.979293 312.228061,192.302202 312.228061,169.262843 C312.228061,146.223483 330.965647,127.546392 354.079631,127.546392 C377.193615,127.546392 395.931201,146.223483 395.931201,169.262843 C395.931201,192.302202 377.193615,210.979293 354.079631,210.979293 Z M354.079631,377.845096 C330.965647,377.845096 312.228061,359.168005 312.228061,336.128646 C312.228061,313.089286 330.965647,294.412195 354.079631,294.412195 C377.193615,294.412195 395.931201,313.089286 395.931201,336.128646 C395.931201,359.168005 377.193615,377.845096 354.079631,377.845096 Z M186.673352,377.845096 C163.559368,377.845096 144.821782,359.168005 144.821782,336.128646 C144.821782,313.089286 163.559368,294.412195 186.673352,294.412195 C209.787336,294.412195 228.524922,313.089286 228.524922,336.128646 C228.524922,359.168005 209.787336,377.845096 186.673352,377.845096 Z" 25 - , fill "#2C96FF" 44 + [ d "m283.13 546.35-160.74 92.806c0.32126 2.8543 0.32125 5.7352 0 8.5894l160.75 92.806c13.554-10.001 32.043-10.001 45.597 0l160.75-92.807c-0.32126-2.8543-0.32293-5.7338-0.001-8.588l-160.74-92.806c-13.554 10.001-32.044 10.001-45.599 0zm221.79 127.03-160.92 93.84c1.884 16.739-7.3611 32.751-22.799 39.489l0.18062 184.58c2.6325 1.1489 5.1267 2.5886 7.438 4.294l160.75-92.805c-1.884-16.739 7.3611-32.752 22.799-39.49v-185.61c-2.6325-1.1489-5.1281-2.5886-7.4394-4.294zm-397.81 1.0315c-2.3112 1.7054-4.8054 3.1465-7.438 4.2954v185.61c15.438 6.7378 24.683 22.75 22.799 39.489l160.74 92.806c2.3112-1.7054 4.8069-3.1465 7.4394-4.2954v-185.61c-15.438-6.7378-24.683-22.75-22.799-39.489l-160.74-92.81z" 45 + , fill "#fff" 46 + ] 47 + [] 48 + ] 49 + 50 + -- Group 2 51 + ---------- 52 + , g 53 + [ fill (Color.toCssString UI.Kit.colors.text) 54 + , transform "translate(0 -196.66)" 55 + ] 56 + [ Svg.path 57 + [ d "m256 708.66 221.7-128v-256l-221.7 128v256z" 58 + , fillOpacity "1" 26 59 ] 27 60 [] 28 61 , Svg.path 29 - [ d "M158.85157,222.072077 C135.737586,222.072077 117,203.394986 117,180.355626 C117,157.316266 135.737586,138.639175 158.85157,138.639175 C181.965554,138.639175 200.70314,157.316266 200.70314,180.355626 C200.70314,203.394986 181.965554,222.072077 158.85157,222.072077 Z M326.257849,222.072077 C303.143865,222.072077 284.406279,203.394986 284.406279,180.355626 C284.406279,157.316266 303.143865,138.639175 326.257849,138.639175 C349.371833,138.639175 368.109419,157.316266 368.109419,180.355626 C368.109419,203.394986 349.371833,222.072077 326.257849,222.072077 Z M326.257849,388.93788 C303.143865,388.93788 284.406279,370.260789 284.406279,347.221429 C284.406279,324.18207 303.143865,305.504978 326.257849,305.504978 C349.371833,305.504978 368.109419,324.18207 368.109419,347.221429 C368.109419,370.260789 349.371833,388.93788 326.257849,388.93788 Z M158.85157,388.93788 C135.737586,388.93788 117,370.260789 117,347.221429 C117,324.18207 135.737586,305.504978 158.85157,305.504978 C181.965554,305.504978 200.70314,324.18207 200.70314,347.221429 C200.70314,370.260789 181.965554,388.93788 158.85157,388.93788 Z" 30 - , fill "#E91E63" 62 + [ d "m256 708.66v-256l-221.7-128v256l221.7 128z" 63 + , fillOpacity ".75" 31 64 ] 32 65 [] 33 66 , Svg.path 34 - [ d "M172.762461,205.432902 C149.648477,205.432902 130.910891,186.75581 130.910891,163.716451 C130.910891,140.677091 149.648477,122 172.762461,122 C195.876445,122 214.614031,140.677091 214.614031,163.716451 C214.614031,186.75581 195.876445,205.432902 172.762461,205.432902 Z M340.16874,205.432902 C317.054756,205.432902 298.31717,186.75581 298.31717,163.716451 C298.31717,140.677091 317.054756,122 340.16874,122 C363.282724,122 382.02031,140.677091 382.02031,163.716451 C382.02031,186.75581 363.282724,205.432902 340.16874,205.432902 Z M340.16874,372.298705 C317.054756,372.298705 298.31717,353.621614 298.31717,330.582254 C298.31717,307.542894 317.054756,288.865803 340.16874,288.865803 C363.282724,288.865803 382.02031,307.542894 382.02031,330.582254 C382.02031,353.621614 363.282724,372.298705 340.16874,372.298705 Z M172.762461,372.298705 C149.648477,372.298705 130.910891,353.621614 130.910891,330.582254 C130.910891,307.542894 149.648477,288.865803 172.762461,288.865803 C195.876445,288.865803 214.614031,307.542894 214.614031,330.582254 C214.614031,353.621614 195.876445,372.298705 172.762461,372.298705 Z" 35 - , fill "#270F34" 67 + [ d "m34.298 324.66 221.7 128 221.7-128-221.7-128-221.7 128z" 68 + , fillOpacity ".5" 36 69 ] 37 70 [] 38 71 ] ··· 44 77 svg 45 78 [ clipRule "evenodd" 46 79 , fillRule "evenodd" 47 - , height "17" 80 + , height "16" 48 81 , imageRendering "optimizeQuality" 49 82 , shapeRendering "geometricPrecision" 50 83 , textRendering "geometricPrecision" 51 84 , viewBox "0 0 739 853" 52 - , width "17" 85 + , width "16" 53 86 ] 54 87 [ polygon 55 - [ fill "#FF4B03" 56 - , 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" 88 + [ 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" 89 + 90 + -- 91 + , fill (Color.toCssString UI.Kit.colors.text) 92 + ] 93 + [] 94 + ] 95 + 96 + 97 + solidLogo : Svg Never 98 + solidLogo = 99 + svg 100 + [ height "16" 101 + , viewBox "0 0 1200 1200" 102 + , width "16" 103 + ] 104 + [ Svg.path 105 + [ fill (Color.toCssString UI.Kit.colors.text) 106 + , d "M280.6,1021.9L61.1,641.2c-20.4-35.3-20.4-78.8,0-114l219.5-380.8c20.5-35.4,58.2-57.1,98.9-57.1 h439c40.7,0,78.5,21.7,98.9,57.1L1137.1,527c20.4,35.3,20.4,78.8,0,114l-219.6,381c-20.5,35.4-58.2,57.1-98.9,57.1H379.7 C338.8,1079.1,301.1,1057.3,280.6,1021.9z" 107 + ] 108 + [] 109 + , Svg.path 110 + [ fill "#fff" 111 + , d "M377.9,510.9h451.7c5.7,0,10.2-4.6,10.2-10.2v-84.7c0-56.3-45.7-102-102-102H466.6 c-78.9-0.1-142.8,63.8-142.8,142.7l0,0C323.7,486.8,347.9,510.9,377.9,510.9z" 112 + ] 113 + [] 114 + , Svg.path 115 + [ fill "#fff" 116 + , d "M422.2,885.1h269.9c81.5,0,147.7-66.2,147.7-147.7l0,0c0-27.2-22-49.3-49.3-49.3H333.6 c-5.6,0-9.8,4.5-9.8,9.8v88.6C323.7,841,367.9,885.1,422.2,885.1z" 117 + ] 118 + [] 119 + , Svg.path 120 + [ fill "#fff" 121 + , d "M343.8,499.7l336.9,336.9c22.3,22.3,58.4,22.3,80.7,0l58.4-58.4c22.3-22.3,22.3-58.4,0-80.7 L483,360.6c-22.3-22.3-58.4-22.3-80.7,0L343.9,419C321.4,441.3,321.4,477.5,343.8,499.7z" 122 + ] 123 + [] 124 + 125 + -- 126 + , polygon 127 + [ fill "#444" 128 + , fillOpacity "0.3" 129 + , points "686.2,842.3 488.3,688.1 532.1,688.1" 130 + ] 131 + [] 132 + , polygon 133 + [ fill "#444" 134 + , fillOpacity "0.3" 135 + , points "477.4,355 633.3,510.9 686.2,510.9" 57 136 ] 58 137 [] 59 138 ]
+30 -5
src/Javascript/Workers/brain.js
··· 33 33 // Authentication 34 34 // -------------- 35 35 36 + const SECRET_KEY_LOCATION = "AUTH_SECRET_KEY" 37 + 38 + 36 39 app.ports.fabricateSecretKey.subscribe(event => { 37 40 keyFromPassphrase(event.data) 38 - .then(data => toCache("AUTH_SECRET_KEY", data)) 41 + .then(data => toCache(SECRET_KEY_LOCATION, data)) 39 42 .then(_ => { 40 43 app.ports.fromAlien.send({ 41 44 tag: event.tag, ··· 57 60 58 61 59 62 app.ports.requestCache.subscribe(event => { 60 - getFromIndex({ key: event.tag }) 63 + const dataPromise = (_ => { 64 + if (event.tag == "AUTH_ANONYMOUS") { 65 + return getFromIndex({ key: event.tag }) 66 + .then(r => getFromIndex({ key: SECRET_KEY_LOCATION }).then(s => [r, s])) 67 + .then(([r, s]) => r ? decrypt(s, r) : null) 68 + .then(d => d ? JSON.parse(d) : null) 69 + 70 + } else { 71 + return getFromIndex({ key: event.tag }) 72 + } 73 + })() 74 + 75 + dataPromise 61 76 .then(data => { 62 77 app.ports.fromAlien.send({ 63 78 tag: event.tag, ··· 76 91 77 92 78 93 function toCache(key, data) { 79 - return setInIndex({ key: key, data: data }) 94 + if (key == "AUTH_ANONYMOUS") { 95 + const json = JSON.stringify(data) 96 + 97 + return getFromIndex({ key: SECRET_KEY_LOCATION }) 98 + .then(secretKey => encrypt(secretKey, json)) 99 + .then(encryptedData => setInIndex({ key: key, data: encryptedData })) 100 + 101 + } else { 102 + return setInIndex({ key: key, data: data }) 103 + 104 + } 80 105 } 81 106 82 107 ··· 99 124 100 125 app.ports.requestIpfs.subscribe(event => { 101 126 const path = ipfsFilePath(event.tag) 102 - const secretKeyPromise = getFromIndex({ key: "AUTH_SECRET_KEY" }) 127 + const secretKeyPromise = getFromIndex({ key: SECRET_KEY_LOCATION }) 103 128 104 129 fetch("http://localhost:5001/api/v0/files/read?arg=" + path) 105 130 .then(r => r.ok ? r.text() : r.json()) ··· 128 153 truncate: true 129 154 }).toString() 130 155 131 - getFromIndex({ key: "AUTH_SECRET_KEY" }) 156 + getFromIndex({ key: SECRET_KEY_LOCATION }) 132 157 .then(secretKey => encrypt(secretKey, json)) 133 158 .then(data => { 134 159 const formData = new FormData()