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.

BackgroundImage setting and enclosed data

+185 -75
+5 -2
src/Applications/Brain.elm
··· 106 106 let 107 107 decodedData = 108 108 value 109 - |> Authentication.decode 109 + |> Authentication.decodeHypaethral 110 110 |> Result.withDefault model.hypaethralUserData 111 111 in 112 112 ( { model | hypaethralUserData = decodedData } ··· 233 233 saveHypaethralData : Model -> ( Model, Cmd Msg ) 234 234 saveHypaethralData model = 235 235 model.hypaethralUserData 236 - |> Authentication.encodeHypaethralUserData 236 + |> Authentication.encodeHypaethral 237 237 |> Authentication.SaveHypaethralData 238 238 |> AuthenticationMsg 239 239 |> (\msg -> update msg model) ··· 264 264 265 265 Just Alien.AuthMethod -> 266 266 AuthenticationMsg (Authentication.MethodRetrieved event.data) 267 + 268 + Just Alien.AuthEnclosedData -> 269 + AuthenticationMsg (Authentication.EnclosedDataRetrieved event.data) 267 270 268 271 Just Alien.ProcessSources -> 269 272 -- Only proceed to the processing if we got all the necessary data,
+16 -8
src/Applications/UI.elm
··· 76 76 , url = url 77 77 78 78 -- Children 79 + ----------- 79 80 , authentication = UI.Authentication.initialModel 80 81 , backdrop = UI.Backdrop.initialModel 81 82 , sources = UI.Sources.initialModel ··· 101 102 ) 102 103 103 104 LoadEnclosedUserData json -> 104 - ( model 105 - , Cmd.none 106 - ) 105 + model 106 + |> UI.UserData.importEnclosed json 107 + |> Replying.reducto update translateReply 107 108 108 109 LoadHypaethralUserData json -> 109 110 { model | isAuthenticated = True, isLoading = False } ··· 150 151 ) 151 152 152 153 Core.SaveEnclosedUserData -> 153 - ( model 154 - , Cmd.none 155 - ) 154 + model 155 + |> UI.UserData.exportEnclosed 156 + |> Alien.broadcast Alien.SaveEnclosedUserData 157 + |> Ports.toBrain 158 + |> R2.withModel model 156 159 157 160 Core.SaveFavourites -> 158 161 model ··· 257 260 , sources = model.sources.collection 258 261 , tracks = model.tracks.collection.untouched 259 262 } 260 - |> Authentication.encodeHypaethralUserData 263 + |> Authentication.encodeHypaethral 261 264 |> Json.Encode.encode 2 262 265 ) 263 266 ) ··· 399 402 Bypass 400 403 401 404 Just Alien.ReportProcessingError -> 402 - -- TODO 405 + let 406 + dbg = 407 + -- TODO 408 + Debug.log "error" event 409 + in 403 410 Bypass 404 411 405 412 Just Alien.SearchTracks -> ··· 498 505 -- Controls 499 506 ----------------------------------------- 500 507 , chunk 508 + -- TODO 501 509 [ T.h4 ] 502 510 [] 503 511 ]
+76 -45
src/Applications/UI/Backdrop.elm
··· 1 - module UI.Backdrop exposing (Model, Msg(..), initialModel, update, view) 1 + module UI.Backdrop exposing (Model, Msg(..), default, initialModel, options, update, view) 2 2 3 3 import Chunky exposing (..) 4 4 import Css exposing (..) 5 + import Css.Global 5 6 import Html.Styled as Html exposing (Html, div) 6 - import Html.Styled.Attributes exposing (css, src, style) 7 + import Html.Styled.Attributes exposing (class, css, src, style) 7 8 import Html.Styled.Events exposing (on) 8 9 import Html.Styled.Lazy as Lazy 9 10 import Json.Decode 10 11 import Replying exposing (R3D3) 11 - import Return3 12 + import Return2 as R2 13 + import Return3 as R3 12 14 import Tachyons.Classes as T 13 15 import UI.Animations 14 16 import UI.Reply as Reply exposing (Reply) ··· 23 25 "7.jpg" 24 26 25 27 28 + options : List ( String, String ) 29 + options = 30 + [ ( "1.jpg", "Option 1" ) 31 + , ( "2.jpg", "Option 2" ) 32 + , ( "3.jpg", "Option 3" ) 33 + , ( "4.jpg", "Option 4" ) 34 + , ( "5.jpg", "Option 5" ) 35 + , ( "6.jpg", "Option 6" ) 36 + , ( "7.jpg", "Option 7 (default)" ) 37 + , ( "8.jpg", "Option 8" ) 38 + , ( "9.jpg", "Option 9" ) 39 + , ( "10.jpg", "Option 10" ) 40 + , ( "11.jpg", "Option 11" ) 41 + , ( "12.jpg", "Option 12" ) 42 + ] 43 + 44 + 26 45 27 46 -- 🌳 28 47 ··· 47 66 48 67 49 68 type Msg 50 - = Load String 69 + = Choose String 70 + | Load String 51 71 52 72 53 73 update : Msg -> Model -> R3D3 Model Msg Reply 54 74 update msg model = 55 75 case msg of 76 + Choose backdrop -> 77 + { model | chosen = backdrop } 78 + |> R2.withNoCmd 79 + |> R3.withReply [ Reply.SaveEnclosedUserData ] 80 + 56 81 Load backdrop -> 57 82 [ backdrop ] 58 83 |> List.append model.loaded 59 84 |> (\list -> { model | loaded = list }) 60 - |> Return3.withNothing 85 + |> R3.withNothing 61 86 62 87 63 88 ··· 106 131 loaded list fadeIn = 107 132 let 108 133 amount = 109 - min (List.length list) 2 134 + List.length list 110 135 111 136 indexedMapFn idx item = 112 - div [ css (imageStyles fadeIn (idx + 1 < amount) item) ] [] 137 + div (imageStyles fadeIn (idx + 1 < amount) item) [] 113 138 in 114 139 list 115 - |> List.reverse 116 - |> List.take 2 117 - |> List.reverse 118 140 |> List.indexedMap indexedMapFn 119 - |> div [] 141 + |> div [ css imageContainerStyles ] 120 142 121 143 122 144 ··· 135 157 ] 136 158 137 159 160 + imageContainerStyles : List Css.Style 161 + imageContainerStyles = 162 + [ Css.Global.descendants 163 + [ Css.Global.selector 164 + ".bg-image--with-fadein" 165 + imageAnimation 166 + ] 167 + ] 168 + 169 + 138 170 imageAnimation : List Css.Style 139 171 imageAnimation = 140 172 [ animationName UI.Animations.fadeIn ··· 144 176 ] 145 177 146 178 147 - imageStyles : Bool -> Bool -> String -> List Css.Style 179 + imageStyles : Bool -> Bool -> String -> List (Html.Attribute msg) 148 180 imageStyles fadeIn isPrevious loadedBackdrop = 149 - List.append 150 - -- Animation 151 - ------------ 152 - (if not isPrevious && fadeIn then 153 - imageAnimation 181 + [ -- Animation 182 + ------------ 183 + if not isPrevious && fadeIn then 184 + class "bg-image--with-fadein" 185 + 186 + else 187 + class "" 154 188 155 - else 156 - [] 157 - ) 158 - [ -- Background 159 - ------------- 160 - case loadedBackdrop of 161 - "1.jpg" -> 162 - property "background-position" "center 30%" 189 + -- Background 190 + ------------- 191 + , case loadedBackdrop of 192 + "1.jpg" -> 193 + style "background-position" "center 30%" 163 194 164 - "9.jpg" -> 165 - property "background-position" "center 68%" 195 + "9.jpg" -> 196 + style "background-position" "center 68%" 166 197 167 - _ -> 168 - property "background-position" "center bottom" 198 + _ -> 199 + style "background-position" "center bottom" 169 200 170 - -- Opacity 171 - ---------- 172 - , if isPrevious || not fadeIn then 173 - opacity (int 1) 201 + -- Opacity 202 + ---------- 203 + , if isPrevious || not fadeIn then 204 + style "opacity" "1" 174 205 175 - else 176 - opacity zero 206 + else 207 + style "opacity" "0" 177 208 178 - -- 179 - , backgroundImage (url <| "/images/Background/" ++ loadedBackdrop) 180 - , backgroundSize cover 181 - , bottom (px -1) 182 - , left (px -1) 183 - , position fixed 184 - , right (px -1) 185 - , top (px -1) 186 - , zIndex (int -9) 187 - ] 209 + -- 210 + , style "background-image" ("url(/images/Background/" ++ loadedBackdrop ++ ")") 211 + , style "background-size" "cover" 212 + , style "bottom" "-1px" 213 + , style "left" "-1px" 214 + , style "position" "fixed" 215 + , style "right" "-1px" 216 + , style "top" "-1px" 217 + , style "z-index" "-9" 218 + ]
+1 -2
src/Applications/UI/Kit.elm
··· 361 361 select inputHandler options = 362 362 brick 363 363 [ css selectStyles.container ] 364 - [ T.center 365 - , T.mb4 364 + [ T.mb4 366 365 , T.relative 367 366 , T.w_100 368 367 ]
+16
src/Applications/UI/Settings.elm
··· 3 3 import Authentication exposing (Method(..)) 4 4 import Chunky exposing (..) 5 5 import Html.Styled as Html exposing (Html, text) 6 + import Html.Styled.Attributes exposing (selected, value) 6 7 import Material.Icons.Action as Icons 7 8 import Material.Icons.Communication as Icons 8 9 import Tachyons.Classes as T 10 + import UI.Backdrop 9 11 import UI.Core 10 12 import UI.Kit 11 13 import UI.Navigation exposing (..) ··· 68 70 ] 69 71 |> raw 70 72 |> UI.Kit.intro 73 + 74 + -- Background image 75 + ------------------- 76 + , chunk [ T.mb2, T.mt4 ] [ UI.Kit.label [] "Background Image" ] 77 + , UI.Kit.select 78 + (UI.Core.BackdropMsg << UI.Backdrop.Choose) 79 + (List.map 80 + (\( v, l ) -> 81 + Html.option 82 + [ selected (v == model.backdrop.chosen), value v ] 83 + [ text l ] 84 + ) 85 + UI.Backdrop.options 86 + ) 71 87 ] 72 88 ]
+1 -1
src/Applications/UI/Sources/Form.elm
··· 194 194 , Services.labels 195 195 |> List.map (\( k, l ) -> Html.option [ value k ] [ text l ]) 196 196 |> select SelectService 197 - |> chunky [ T.pv2, T.w_100 ] 197 + |> chunky [ T.flex, T.justify_center, T.pv2, T.w_100 ] 198 198 199 199 -- Button 200 200 ---------
+37 -3
src/Applications/UI/UserData.elm
··· 1 - module UI.UserData exposing (encodedFavourites, encodedSources, encodedTracks, importHypaethral) 1 + module UI.UserData exposing (encodedFavourites, encodedSources, encodedTracks, exportEnclosed, importEnclosed, importHypaethral) 2 2 3 3 import Authentication exposing (..) 4 4 import Json.Decode as Json 5 5 import Json.Decode.Pipeline exposing (..) 6 6 import Json.Encode 7 7 import Replying exposing (R3D3) 8 + import Return3 as R3 8 9 import Sources 9 10 import Sources.Encoding as Sources 10 11 import Tracks exposing (emptyCollection) ··· 17 18 18 19 19 20 20 - -- 🔱 21 + -- HYPAETHRAL 21 22 22 23 23 24 encodedFavourites : UI.Core.Model -> Json.Value ··· 41 42 -- TODO: The app should notify the user if it's trying to import faulty data. 42 43 -- (instead of doing nothing, like it is now) 43 44 data = 44 - Result.withDefault emptyHypaethralUserData (decode value) 45 + Result.withDefault emptyHypaethralUserData (decodeHypaethral value) 45 46 46 47 ( sourcesModel, sourcesCmd, sourcesReply ) = 47 48 importSources model.sources data ··· 92 93 |> Tracks.makeParcel 93 94 |> Tracks.identify 94 95 |> Tracks.resolveParcel adjustedModel 96 + 97 + 98 + 99 + -- ENCLOSED 100 + 101 + 102 + exportEnclosed : UI.Core.Model -> Json.Value 103 + exportEnclosed model = 104 + encodeEnclosed 105 + { backgroundImage = Just model.backdrop.chosen 106 + } 107 + 108 + 109 + importEnclosed : Json.Value -> UI.Core.Model -> R3D3 UI.Core.Model UI.Core.Msg UI.Reply 110 + importEnclosed value model = 111 + case decodeEnclosed value of 112 + Ok data -> 113 + let 114 + { backdrop } = 115 + model 116 + in 117 + R3.withNothing 118 + { model 119 + | backdrop = { backdrop | chosen = Maybe.withDefault backdrop.chosen data.backgroundImage } 120 + } 121 + 122 + Err err -> 123 + -- TODO: Show error 124 + R3.withNothing model 125 + 126 + 127 + 128 + -- ㊙️ 95 129 96 130 97 131 mergeReplies : List (Maybe (List UI.Reply)) -> Maybe (List UI.Reply)
+33 -14
src/Library/Authentication.elm
··· 1 - module Authentication exposing (EnclosedUserData, HypaethralUserData, Method(..), decode, decodeMethod, decoder, emptyHypaethralUserData, encodeHypaethralUserData, encodeMethod, methodFromString, methodToString) 1 + module Authentication exposing (EnclosedUserData, HypaethralUserData, Method(..), decodeEnclosed, decodeHypaethral, decodeMethod, emptyHypaethralUserData, enclosedDecoder, encodeEnclosed, encodeHypaethral, encodeMethod, hypaethralDecoder, methodFromString, methodToString) 2 2 3 3 import Json.Decode as Json 4 4 import Json.Decode.Ext as Json 5 - import Json.Decode.Pipeline exposing (optional) 5 + import Json.Decode.Pipeline exposing (optional, required) 6 6 import Json.Encode 7 7 import Maybe.Extra as Maybe 8 8 import Sources ··· 21 21 22 22 23 23 type alias EnclosedUserData = 24 - {} 24 + { backgroundImage : Maybe String 25 + } 25 26 26 27 27 28 type alias HypaethralUserData = ··· 70 71 -- 🔱 ░░ DECODING & ENCODING 71 72 72 73 73 - decode : Json.Value -> Result Json.Error HypaethralUserData 74 - decode = 75 - Json.decodeValue decoder 74 + decodeEnclosed : Json.Value -> Result Json.Error EnclosedUserData 75 + decodeEnclosed = 76 + Json.decodeValue enclosedDecoder 77 + 78 + 79 + decodeHypaethral : Json.Value -> Result Json.Error HypaethralUserData 80 + decodeHypaethral = 81 + Json.decodeValue hypaethralDecoder 76 82 77 83 78 84 decodeMethod : Json.Value -> Maybe Method ··· 80 86 Json.decodeValue (Json.map methodFromString Json.string) >> Result.toMaybe >> Maybe.join 81 87 82 88 83 - decoder : Json.Decoder HypaethralUserData 84 - decoder = 85 - Json.succeed HypaethralUserData 86 - |> optional "favourites" (Json.listIgnore Tracks.favouriteDecoder) [] 87 - |> optional "sources" (Json.listIgnore Sources.decoder) [] 88 - |> optional "tracks" (Json.listIgnore Tracks.trackDecoder) [] 89 + enclosedDecoder : Json.Decoder EnclosedUserData 90 + enclosedDecoder = 91 + Json.succeed EnclosedUserData 92 + |> required "backgroundImage" (Json.maybe Json.string) 93 + 94 + 95 + encodeEnclosed : EnclosedUserData -> Json.Value 96 + encodeEnclosed { backgroundImage } = 97 + Json.Encode.object 98 + [ ( "backgroundImage", Json.Encode.string (Maybe.withDefault "" backgroundImage) ) 99 + ] 89 100 90 101 91 - encodeHypaethralUserData : HypaethralUserData -> Json.Value 92 - encodeHypaethralUserData { favourites, sources, tracks } = 102 + encodeHypaethral : HypaethralUserData -> Json.Value 103 + encodeHypaethral { favourites, sources, tracks } = 93 104 Json.Encode.object 94 105 [ ( "favourites", Json.Encode.list Tracks.encodeFavourite favourites ) 95 106 , ( "sources", Json.Encode.list Sources.encode sources ) ··· 100 111 encodeMethod : Method -> Json.Value 101 112 encodeMethod = 102 113 methodToString >> Json.Encode.string 114 + 115 + 116 + hypaethralDecoder : Json.Decoder HypaethralUserData 117 + hypaethralDecoder = 118 + Json.succeed HypaethralUserData 119 + |> optional "favourites" (Json.listIgnore Tracks.favouriteDecoder) [] 120 + |> optional "sources" (Json.listIgnore Sources.decoder) [] 121 + |> optional "tracks" (Json.listIgnore Tracks.trackDecoder) []