From a4501d5cb530dbce5ea58f55dcb677e850fcdc11 Mon Sep 17 00:00:00 2001 From: Alexander Kobjolke Date: Tue, 12 Dec 2023 09:43:51 +0100 Subject: [PATCH] Switch to json encoded meta data Instead of parsing a comma separated list of photo urls, we retrieve a json array of meta data (url, title, size). --- app.js | 150 +++++++++++++++++++++++++++++++++++--------- elm.json | 3 +- list | 32 +++++++++- src/PhotoGroove.elm | 33 ++++++---- 4 files changed, 174 insertions(+), 44 deletions(-) diff --git a/app.js b/app.js index 8a5af86..589318d 100644 --- a/app.js +++ b/app.js @@ -5420,6 +5420,7 @@ var $elm$browser$Browser$element = _Browser_element; var $author$project$PhotoGroove$GotPhotos = function (a) { return {$: 'GotPhotos', a: a}; }; +var $elm$json$Json$Decode$decodeString = _Json_runOnString; var $elm$http$Http$BadStatus_ = F2( function (a, b) { return {$: 'BadStatus_', a: a, b: b}; @@ -5975,17 +5976,6 @@ var $elm$http$Http$expectStringResponse = F2( $elm$core$Basics$identity, A2($elm$core$Basics$composeR, toResult, toMsg)); }); -var $elm$http$Http$BadBody = function (a) { - return {$: 'BadBody', a: a}; -}; -var $elm$http$Http$BadStatus = function (a) { - return {$: 'BadStatus', a: a}; -}; -var $elm$http$Http$BadUrl = function (a) { - return {$: 'BadUrl', a: a}; -}; -var $elm$http$Http$NetworkError = {$: 'NetworkError'}; -var $elm$http$Http$Timeout = {$: 'Timeout'}; var $elm$core$Result$mapError = F2( function (f, result) { if (result.$ === 'Ok') { @@ -5997,6 +5987,17 @@ var $elm$core$Result$mapError = F2( f(e)); } }); +var $elm$http$Http$BadBody = function (a) { + return {$: 'BadBody', a: a}; +}; +var $elm$http$Http$BadStatus = function (a) { + return {$: 'BadStatus', a: a}; +}; +var $elm$http$Http$BadUrl = function (a) { + return {$: 'BadUrl', a: a}; +}; +var $elm$http$Http$NetworkError = {$: 'NetworkError'}; +var $elm$http$Http$Timeout = {$: 'Timeout'}; var $elm$http$Http$resolve = F2( function (toResult, response) { switch (response.$) { @@ -6020,12 +6021,19 @@ var $elm$http$Http$resolve = F2( toResult(body)); } }); -var $elm$http$Http$expectString = function (toMsg) { - return A2( - $elm$http$Http$expectStringResponse, - toMsg, - $elm$http$Http$resolve($elm$core$Result$Ok)); -}; +var $elm$http$Http$expectJson = F2( + function (toMsg, decoder) { + return A2( + $elm$http$Http$expectStringResponse, + toMsg, + $elm$http$Http$resolve( + function (string) { + return A2( + $elm$core$Result$mapError, + $elm$json$Json$Decode$errorToString, + A2($elm$json$Json$Decode$decodeString, decoder, string)); + })); + }); var $elm$http$Http$emptyBody = _Http_emptyBody; var $elm$http$Http$Request = function (a) { return {$: 'Request', a: a}; @@ -6199,9 +6207,99 @@ var $elm$http$Http$get = function (r) { return $elm$http$Http$request( {body: $elm$http$Http$emptyBody, expect: r.expect, headers: _List_Nil, method: 'GET', timeout: $elm$core$Maybe$Nothing, tracker: $elm$core$Maybe$Nothing, url: r.url}); }; +var $elm$json$Json$Decode$list = _Json_decodeList; +var $author$project$PhotoGroove$Photo = F3( + function (url, size, title) { + return {size: size, title: title, url: url}; + }); +var $elm$json$Json$Decode$int = _Json_decodeInt; +var $NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$custom = $elm$json$Json$Decode$map2($elm$core$Basics$apR); +var $elm$json$Json$Decode$andThen = _Json_andThen; +var $elm$json$Json$Decode$field = _Json_decodeField; +var $elm$json$Json$Decode$at = F2( + function (fields, decoder) { + return A3($elm$core$List$foldr, $elm$json$Json$Decode$field, decoder, fields); + }); +var $elm$json$Json$Decode$decodeValue = _Json_run; +var $elm$json$Json$Decode$null = _Json_decodeNull; +var $elm$json$Json$Decode$oneOf = _Json_oneOf; +var $elm$json$Json$Decode$value = _Json_decodeValue; +var $NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$optionalDecoder = F3( + function (path, valDecoder, fallback) { + var nullOr = function (decoder) { + return $elm$json$Json$Decode$oneOf( + _List_fromArray( + [ + decoder, + $elm$json$Json$Decode$null(fallback) + ])); + }; + var handleResult = function (input) { + var _v0 = A2( + $elm$json$Json$Decode$decodeValue, + A2($elm$json$Json$Decode$at, path, $elm$json$Json$Decode$value), + input); + if (_v0.$ === 'Ok') { + var rawValue = _v0.a; + var _v1 = A2( + $elm$json$Json$Decode$decodeValue, + nullOr(valDecoder), + rawValue); + if (_v1.$ === 'Ok') { + var finalResult = _v1.a; + return $elm$json$Json$Decode$succeed(finalResult); + } else { + return A2( + $elm$json$Json$Decode$at, + path, + nullOr(valDecoder)); + } + } else { + return $elm$json$Json$Decode$succeed(fallback); + } + }; + return A2($elm$json$Json$Decode$andThen, handleResult, $elm$json$Json$Decode$value); + }); +var $NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$optional = F4( + function (key, valDecoder, fallback, decoder) { + return A2( + $NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$custom, + A3( + $NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$optionalDecoder, + _List_fromArray( + [key]), + valDecoder, + fallback), + decoder); + }); +var $NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$required = F3( + function (key, valDecoder, decoder) { + return A2( + $NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$custom, + A2($elm$json$Json$Decode$field, key, valDecoder), + decoder); + }); +var $elm$json$Json$Decode$string = _Json_decodeString; +var $author$project$PhotoGroove$photoDecoder = A4( + $NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$optional, + 'title', + $elm$json$Json$Decode$string, + '(untitled)', + A3( + $NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$required, + 'size', + $elm$json$Json$Decode$int, + A3( + $NoRedInk$elm_json_decode_pipeline$Json$Decode$Pipeline$required, + 'url', + $elm$json$Json$Decode$string, + $elm$json$Json$Decode$succeed($author$project$PhotoGroove$Photo)))); var $author$project$PhotoGroove$initialCommand = $elm$http$Http$get( { - expect: $elm$http$Http$expectString($author$project$PhotoGroove$GotPhotos), + expect: A2( + $elm$http$Http$expectJson, + $author$project$PhotoGroove$GotPhotos, + $elm$json$Json$Decode$list($author$project$PhotoGroove$photoDecoder)), url: 'list' }); var $author$project$PhotoGroove$Large = {$: 'Large'}; @@ -6219,9 +6317,6 @@ var $author$project$PhotoGroove$Loaded = F2( function (a, b) { return {$: 'Loaded', a: a, b: b}; }); -var $author$project$PhotoGroove$Photo = function (url) { - return {url: url}; -}; var $elm$random$Random$Generate = function (a) { return {$: 'Generate', a: a}; }; @@ -6500,17 +6595,14 @@ var $author$project$PhotoGroove$update = F2( $elm$core$Platform$Cmd$none); default: if (msg.a.$ === 'Ok') { - var str = msg.a.a; - var _v3 = A2($elm$core$String$split, ',', str); - if (_v3.b) { - var urls = _v3; - var x = urls.a; - var photos = A2($elm$core$List$map, $author$project$PhotoGroove$Photo, urls); + if (msg.a.a.b) { + var photos = msg.a.a; + var firstPhoto = photos.a; return _Utils_Tuple2( _Utils_update( model, { - status: A2($author$project$PhotoGroove$Loaded, photos, x) + status: A2($author$project$PhotoGroove$Loaded, photos, firstPhoto.url) }), $elm$core$Platform$Cmd$none); } else { @@ -6518,7 +6610,7 @@ var $author$project$PhotoGroove$update = F2( _Utils_update( model, { - status: $author$project$PhotoGroove$Errored('No photos: ' + str) + status: $author$project$PhotoGroove$Errored('No photos!') }), $elm$core$Platform$Cmd$none); } diff --git a/elm.json b/elm.json index 73e3cff..0e317c3 100644 --- a/elm.json +++ b/elm.json @@ -6,16 +6,17 @@ "elm-version": "0.19.1", "dependencies": { "direct": { + "NoRedInk/elm-json-decode-pipeline": "1.0.1", "elm/browser": "1.0.2", "elm/core": "1.0.5", "elm/html": "1.0.0", "elm/http": "2.0.0", + "elm/json": "1.1.3", "elm/random": "1.0.0" }, "indirect": { "elm/bytes": "1.0.8", "elm/file": "1.0.5", - "elm/json": "1.1.3", "elm/time": "1.0.0", "elm/url": "1.0.0", "elm/virtual-dom": "1.0.3" diff --git a/list b/list index 30e46e3..c91b6f0 100644 --- a/list +++ b/list @@ -1 +1,31 @@ -1.jpeg,2.jpeg,3.jpeg,4.jpeg +[ + { + "url": "1.jpeg", + "size": 36, + "title": "Beachside" + }, + { + "url": "2.jpeg", + "size": 19, + "title": "Epica, live at the Agora" + }, + { + "url": "3.jpeg", + "size": 41 + }, + { + "url": "4.jpeg", + "size": 41, + "title": "City Museum" + }, + { + "url": "5.jpeg", + "size": 25, + "title": null + }, + { + "url": "6.jpeg", + "size": 37, + "title": "Boat in Glass" + } +] diff --git a/src/PhotoGroove.elm b/src/PhotoGroove.elm index 27a4304..dd908ad 100644 --- a/src/PhotoGroove.elm +++ b/src/PhotoGroove.elm @@ -5,6 +5,8 @@ import Html exposing (Html, button, div, h1, h3, img, input, label, text) import Html.Attributes exposing (..) import Html.Events exposing (onClick) import Http +import Json.Decode as D exposing (Decoder) +import Json.Decode.Pipeline as D import Random @@ -21,7 +23,18 @@ type alias Model = type alias Photo = - { url : String } + { url : String + , size : Int + , title : String + } + + +photoDecoder : Decoder Photo +photoDecoder = + D.succeed Photo + |> D.required "url" D.string + |> D.required "size" D.int + |> D.optional "title" D.string "(untitled)" type ThumbnailSize @@ -41,7 +54,7 @@ initialCommand : Cmd Message initialCommand = Http.get { url = "list" - , expect = Http.expectString GotPhotos + , expect = Http.expectJson GotPhotos (D.list photoDecoder) } @@ -129,7 +142,7 @@ type Message | ClickedSurpriseMe | ClickedSize ThumbnailSize | GotRandomPhoto Photo - | GotPhotos (Result Http.Error String) + | GotPhotos (Result Http.Error (List Photo)) update : Message -> Model -> ( Model, Cmd Message ) @@ -160,17 +173,11 @@ update msg model = GotRandomPhoto photo -> ( { model | status = selectUrl photo.url model.status }, Cmd.none ) - GotPhotos (Ok str) -> - case String.split "," str of - (x :: _) as urls -> - let - photos = - List.map Photo urls - in - ( { model | status = Loaded photos x }, Cmd.none ) + GotPhotos (Ok ((firstPhoto :: _) as photos)) -> + ( { model | status = Loaded photos firstPhoto.url }, Cmd.none ) - [] -> - ( { model | status = Errored ("No photos: " ++ str) }, Cmd.none ) + GotPhotos (Ok []) -> + ( { model | status = Errored "No photos!" }, Cmd.none ) GotPhotos (Err httpError) -> ( { model | status = Errored <| ("Failed to load photos: " ++ httpErrorToString httpError) }, Cmd.none )