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.

Add passcode screen

+300 -65
+8
src/Applications/Brain/Authentication.elm
··· 141 141 ( model 142 142 , case model.method of 143 143 -- 🚀 144 + Just Ipfs -> 145 + Cmd.none 146 + 147 + -- TODO 144 148 Just Local -> 145 149 Ports.requestCache (Alien.trigger Alien.AuthAnonymous) 146 150 ··· 183 187 ( model 184 188 , case model.method of 185 189 -- 🚀 190 + Just Ipfs -> 191 + Cmd.none 192 + 193 + -- TODO 186 194 Just Local -> 187 195 Ports.toCache (Alien.broadcast Alien.AuthAnonymous json) 188 196
+15 -10
src/Applications/UI.elm
··· 70 70 , url = url 71 71 72 72 -- Children 73 + , authentication = UI.Authentication.initialModel 73 74 , backdrop = UI.Backdrop.initialModel 74 75 , sources = UI.Sources.initialModel 75 76 , tracks = UI.Tracks.initialModel ··· 180 181 |> Ports.toBrain 181 182 |> Return2.withModel model 182 183 183 - SignIn method -> 184 - ( model 185 - , method 186 - |> Authentication.methodToString 187 - |> Encode.string 188 - |> Alien.broadcast Alien.SignIn 189 - |> Ports.toBrain 190 - ) 191 - 192 184 SignOut -> 193 185 -- TODO: Reset user data 194 186 ( { model | isAuthenticated = False } ··· 200 192 ----------------------------------------- 201 193 -- Children 202 194 ----------------------------------------- 195 + AuthenticationMsg sub -> 196 + updateChild 197 + { mapCmd = AuthenticationMsg 198 + , mapModel = \child -> { model | authentication = child } 199 + , update = UI.Authentication.update 200 + } 201 + { model = model.authentication 202 + , msg = sub 203 + } 204 + 203 205 BackdropMsg sub -> 204 206 updateChild 205 207 { mapCmd = BackdropMsg ··· 389 391 defaultScreen model 390 392 391 393 else 392 - [ UI.Authentication.signInScreen ] 394 + [ model.authentication 395 + |> UI.Authentication.view 396 + |> Html.map AuthenticationMsg 397 + ] 393 398 ) 394 399 ] 395 400
+238 -51
src/Applications/UI/Authentication.elm
··· 1 - module UI.Authentication exposing (signInScreen) 1 + module UI.Authentication exposing (Model, Msg(..), initialModel, update, view) 2 2 3 + import Alien 3 4 import Authentication 4 5 import Chunky exposing (..) 5 - import Color 6 - import Css exposing (backgroundColor, minWidth, px, transparent) 6 + import Color exposing (Color) 7 + import Color.Ext as Color 8 + import Conditional exposing (..) 9 + import Css exposing (pct, px, solid, transparent) 7 10 import Html.Styled as Html exposing (Html, a, button, div, em, fromUnstyled, img, span, text) 8 - import Html.Styled.Attributes exposing (css, href, src, style, width) 11 + import Html.Styled.Attributes exposing (attribute, css, href, src, style, type_, width) 9 12 import Html.Styled.Events exposing (onClick) 13 + import Json.Encode as Encode 10 14 import Material.Icons.Action as Icons 15 + import Replying exposing (R3D3) 16 + import Svg exposing (Svg) 11 17 import Tachyons.Classes as T 12 - import UI.Core 13 18 import UI.Kit 19 + import UI.Ports as Ports 20 + import UI.Reply exposing (Reply(..)) 21 + 22 + 23 + 24 + -- 🌳 25 + 26 + 27 + type alias Model = 28 + { privateKeyInputFor : Maybe Authentication.Method 29 + } 30 + 31 + 32 + initialModel : Model 33 + initialModel = 34 + { privateKeyInputFor = Nothing 35 + } 36 + 37 + 38 + 39 + -- 📣 40 + 41 + 42 + type Msg 43 + = Bypass 44 + | HidePrivateKeyScreen 45 + | ShowPrivateKeyScreen Authentication.Method 46 + | SignIn Authentication.Method 47 + 48 + 49 + update : Msg -> Model -> R3D3 Model Msg Reply 50 + update msg model = 51 + case msg of 52 + Bypass -> 53 + ( model 54 + , Cmd.none 55 + , Nothing 56 + ) 57 + 58 + HidePrivateKeyScreen -> 59 + ( { model | privateKeyInputFor = Nothing } 60 + , Cmd.none 61 + , Nothing 62 + ) 63 + 64 + ShowPrivateKeyScreen method -> 65 + ( { model | privateKeyInputFor = Just method } 66 + , Cmd.none 67 + , Nothing 68 + ) 69 + 70 + SignIn method -> 71 + ( model 72 + , method 73 + |> Authentication.methodToString 74 + |> Encode.string 75 + |> Alien.broadcast Alien.SignIn 76 + |> Ports.toBrain 77 + , Nothing 78 + ) 14 79 15 80 16 81 17 82 -- 🗺 18 83 19 84 20 - signInScreen : Html UI.Core.Msg 21 - signInScreen = 85 + view : Model -> Html Msg 86 + view model = 22 87 chunk 23 88 [ T.flex 24 89 , T.flex_column ··· 30 95 [ T.flex 31 96 , T.items_center 32 97 ] 33 - [ img 34 - [ src "/images/diffuse-light.svg", width 190 ] 35 - [] 98 + [ chunk 99 + [ T.relative ] 100 + [ img 101 + [ onClick HidePrivateKeyScreen 102 + , src "/images/diffuse-light.svg" 103 + , width 190 104 + 105 + -- 106 + , case model.privateKeyInputFor of 107 + Just _ -> 108 + style "cursor" "pointer" 109 + 110 + Nothing -> 111 + style "cursor" "default" 112 + ] 113 + [] 114 + 115 + -- Speech bubble 116 + ---------------- 117 + , case model.privateKeyInputFor of 118 + Just _ -> 119 + [ text "I need a passcode" 120 + , lineBreak 121 + , text "to encrypt your data." 122 + ] 123 + |> chunk [] 124 + |> speechBubble 125 + 126 + Nothing -> 127 + empty 128 + ] 36 129 ] 37 130 38 131 ----------------------------------------- 39 - -- Choices 132 + -- Content 40 133 ----------------------------------------- 41 - , brick 42 - [] 43 - [ T.bg_white 44 - , T.br2 45 - , T.ph3 46 - , T.pv2 47 - ] 48 - (let 49 - borderStyle = 50 - "1px solid " ++ Color.toCssString UI.Kit.colors.subtleBorder 51 - in 52 - [ -- Local 53 - -------- 54 - slab 55 - button 56 - [ css choiceButtonStyles 57 - , onClick (UI.Core.SignIn Authentication.Local) 58 - ] 59 - [ T.b__none 60 - , T.f6 61 - , T.flex 62 - , T.items_center 63 - , T.lh_solid 64 - , T.pointer 65 - , T.pv3 66 - , T.tl 67 - ] 68 - [ slab 69 - span 70 - [] 71 - [ T.inline_flex, T.mr3 ] 72 - [ fromUnstyled (Icons.lock UI.Kit.colors.text 16) ] 73 - , text "Sign in anonymously" 74 - ] 75 - ] 76 - ) 134 + , case model.privateKeyInputFor of 135 + Just method -> 136 + chunk 137 + [ T.flex 138 + , T.flex_column 139 + , T.items_center 140 + ] 141 + [ UI.Kit.textArea 142 + [ attribute "autocomplete" "off" 143 + , attribute "autocorrect" "off" 144 + , attribute "spellcheck" "false" 145 + , Html.Styled.Attributes.value "4AVTfKTYio3rfVBQKkfiioRFur2pnbdMMGeWmkwPdGAQ32XV" 146 + ] 147 + , UI.Kit.button 148 + UI.Kit.WithText 149 + Bypass 150 + (text "Continue") 151 + ] 152 + 153 + Nothing -> 154 + chunk 155 + [ T.bg_white 156 + , T.br2 157 + , T.ph3 158 + , T.pv2 159 + ] 160 + [ choiceButton 161 + { action = SignIn Authentication.Local 162 + , icon = Icons.lock_open 163 + , isLast = False 164 + , label = "Store data in the browser" 165 + } 166 + , choiceButton 167 + { action = ShowPrivateKeyScreen Authentication.Ipfs 168 + , icon = Icons.fingerprint 169 + , isLast = True 170 + , label = "Store encrypted data on IPFS" 171 + } 172 + ] 77 173 78 174 ----------------------------------------- 79 175 -- Link to about page ··· 85 181 , T.items_end 86 182 , T.lh_solid 87 183 , T.pb4 184 + , T.pt3 88 185 ] 89 186 [ slab 90 187 a ··· 97 194 ] 98 195 99 196 197 + choiceButton : 198 + { action : msg 199 + , icon : Color -> Int -> Svg msg 200 + , isLast : Bool 201 + , label : String 202 + } 203 + -> Html msg 204 + choiceButton { action, icon, isLast, label } = 205 + slab 206 + button 207 + [ css (choiceButtonStyles { border = not isLast }) 208 + , onClick action 209 + ] 210 + [ T.b__none 211 + , T.f6 212 + , T.flex 213 + , T.items_center 214 + , T.lh_solid 215 + , T.outline_0 -- TODO 216 + , T.pointer 217 + , T.pv3 218 + , T.tl 219 + ] 220 + [ slab 221 + span 222 + [] 223 + [ T.inline_flex, T.mr3 ] 224 + [ fromUnstyled (icon UI.Kit.colors.text 16) ] 225 + , text label 226 + ] 227 + 228 + 229 + speechBubble : Html msg -> Html msg 230 + speechBubble contents = 231 + brick 232 + [ css speechBubbleStyles ] 233 + [ T.absolute 234 + , T.br2 235 + , T.f6 236 + , T.lh_copy 237 + , T.mt3 238 + , T.nowrap 239 + , T.ph3 240 + , T.pv2 241 + , T.tc 242 + , T.white 243 + ] 244 + [ contents 245 + 246 + -- 247 + , brick 248 + [ css speechBubbleArrowStyles ] 249 + [ T.absolute, T.top_0 ] 250 + [] 251 + ] 252 + 253 + 100 254 101 255 -- 🖼 102 256 103 257 104 - choiceButtonStyles : List Css.Style 105 - choiceButtonStyles = 106 - [ backgroundColor transparent 107 - , minWidth (px 260) 258 + choiceButtonStyles : { border : Bool } -> List Css.Style 259 + choiceButtonStyles { border } = 260 + [ Css.backgroundColor transparent 261 + , Css.borderBottom3 262 + (ifThenElse border (px 1) (px 0)) 263 + solid 264 + (Color.toElmCssColor UI.Kit.colors.subtleBorder) 265 + , Css.minWidth (px 260) 266 + ] 267 + 268 + 269 + speechBubbleStyles : List Css.Style 270 + speechBubbleStyles = 271 + [ Css.backgroundColor (Color.toElmCssColor UI.Kit.colors.background) 272 + , Css.borderBottom3 (px 1) solid transparent 273 + , Css.left (pct 50) 274 + , Css.lineHeight (Css.num 1.4) 275 + , Css.top (pct 100) 276 + , Css.transform (Css.translateX <| pct -50) 277 + ] 278 + 279 + 280 + speechBubbleArrowStyles : List Css.Style 281 + speechBubbleArrowStyles = 282 + let 283 + color = 284 + Color.toCssString UI.Kit.colors.background 285 + in 286 + [ Css.height (px 0) 287 + , Css.left (pct 50) 288 + , Css.transform (Css.translate2 (pct -50) (pct -100)) 289 + , Css.width (px 0) 290 + 291 + -- 292 + , Css.property "border-color" ("transparent transparent " ++ color ++ " transparent") 293 + , Css.property "border-style" "solid" 294 + , Css.property "border-width" "0 6px 5px 6px" 108 295 ]
+3 -2
src/Applications/UI/Core.elm
··· 1 1 module UI.Core exposing (Flags, Model, Msg(..), Switch(..)) 2 2 3 3 import Alien 4 - import Authentication 5 4 import Browser 6 5 import Browser.Navigation as Nav 7 6 import Json.Encode as Json 8 7 import Time 8 + import UI.Authentication 9 9 import UI.Backdrop 10 10 import UI.Page exposing (Page) 11 11 import UI.Sources ··· 35 35 ----------------------------------------- 36 36 -- Children 37 37 ----------------------------------------- 38 + , authentication : UI.Authentication.Model 38 39 , backdrop : UI.Backdrop.Model 39 40 , sources : UI.Sources.Model 40 41 , tracks : UI.Tracks.Model ··· 59 60 | SaveFavourites 60 61 | SaveSources 61 62 | SaveTracks 62 - | SignIn Authentication.Method 63 63 | SignOut 64 64 ----------------------------------------- 65 65 -- Children 66 66 ----------------------------------------- 67 + | AuthenticationMsg UI.Authentication.Msg 67 68 | BackdropMsg UI.Backdrop.Msg 68 69 | SourcesMsg UI.Sources.Msg 69 70 | TracksMsg UI.Tracks.Msg
+28 -1
src/Applications/UI/Kit.elm
··· 1 - module UI.Kit exposing (ButtonType(..), button, buttonFocus, canister, centeredContent, colorKit, colors, defaultFontFamilies, h1, h2, h3, headerFontFamilies, inputFocus, insulationWidth, intro, label, link, logoBackdrop, navFocus, receptacle, select, textField, textFocus, vessel) 1 + module UI.Kit exposing (ButtonType(..), button, buttonFocus, canister, centeredContent, colorKit, colors, defaultFontFamilies, h1, h2, h3, headerFontFamilies, inputFocus, insulationWidth, intro, label, link, logoBackdrop, navFocus, receptacle, select, textArea, textField, textFocus, vessel) 2 2 3 3 import Chunky exposing (..) 4 4 import Color ··· 361 361 ] 362 362 363 363 364 + textArea : List (Html.Attribute msg) -> Html msg 365 + textArea attributes = 366 + slab 367 + Html.textarea 368 + (css textAreaStyles :: attributes) 369 + [ T.bn 370 + , T.bg_white 371 + , T.br2 372 + , T.db 373 + , T.f6 374 + , T.lh_copy 375 + , T.mb3 376 + , T.pa3 377 + , T.w_100 378 + ] 379 + [] 380 + 381 + 364 382 textField : List (Html.Attribute msg) -> Html msg 365 383 textField attributes = 366 384 slab ··· 465 483 , inputFocus 466 484 ] 467 485 } 486 + 487 + 488 + textAreaStyles : List Css.Style 489 + textAreaStyles = 490 + [ Css.color (Color.toElmCssColor colors.text) 491 + , Css.height (px 90) 492 + , Css.resize Css.none 493 + , Css.width (px 320) 494 + ] 468 495 469 496 470 497 textFieldStyles : List Css.Style
+8 -1
src/Library/Authentication.elm
··· 13 13 14 14 15 15 type Method 16 - = Local 16 + = Ipfs 17 + | Local 17 18 18 19 19 20 type alias EnclosedUserData = ··· 42 43 methodToString : Method -> String 43 44 methodToString method = 44 45 case method of 46 + Ipfs -> 47 + "IPFS" 48 + 45 49 Local -> 46 50 "LOCAL" 47 51 ··· 49 53 methodFromString : String -> Maybe Method 50 54 methodFromString string = 51 55 case string of 56 + "IPFS" -> 57 + Just Ipfs 58 + 52 59 "LOCAL" -> 53 60 Just Local 54 61