diff --git a/app.js b/app.js index 90517b5..8a5af86 100644 --- a/app.js +++ b/app.js @@ -4373,6 +4373,181 @@ function _Browser_load(url) +// SEND REQUEST + +var _Http_toTask = F3(function(router, toTask, request) +{ + return _Scheduler_binding(function(callback) + { + function done(response) { + callback(toTask(request.expect.a(response))); + } + + var xhr = new XMLHttpRequest(); + xhr.addEventListener('error', function() { done($elm$http$Http$NetworkError_); }); + xhr.addEventListener('timeout', function() { done($elm$http$Http$Timeout_); }); + xhr.addEventListener('load', function() { done(_Http_toResponse(request.expect.b, xhr)); }); + $elm$core$Maybe$isJust(request.tracker) && _Http_track(router, xhr, request.tracker.a); + + try { + xhr.open(request.method, request.url, true); + } catch (e) { + return done($elm$http$Http$BadUrl_(request.url)); + } + + _Http_configureRequest(xhr, request); + + request.body.a && xhr.setRequestHeader('Content-Type', request.body.a); + xhr.send(request.body.b); + + return function() { xhr.c = true; xhr.abort(); }; + }); +}); + + +// CONFIGURE + +function _Http_configureRequest(xhr, request) +{ + for (var headers = request.headers; headers.b; headers = headers.b) // WHILE_CONS + { + xhr.setRequestHeader(headers.a.a, headers.a.b); + } + xhr.timeout = request.timeout.a || 0; + xhr.responseType = request.expect.d; + xhr.withCredentials = request.allowCookiesFromOtherDomains; +} + + +// RESPONSES + +function _Http_toResponse(toBody, xhr) +{ + return A2( + 200 <= xhr.status && xhr.status < 300 ? $elm$http$Http$GoodStatus_ : $elm$http$Http$BadStatus_, + _Http_toMetadata(xhr), + toBody(xhr.response) + ); +} + + +// METADATA + +function _Http_toMetadata(xhr) +{ + return { + url: xhr.responseURL, + statusCode: xhr.status, + statusText: xhr.statusText, + headers: _Http_parseHeaders(xhr.getAllResponseHeaders()) + }; +} + + +// HEADERS + +function _Http_parseHeaders(rawHeaders) +{ + if (!rawHeaders) + { + return $elm$core$Dict$empty; + } + + var headers = $elm$core$Dict$empty; + var headerPairs = rawHeaders.split('\r\n'); + for (var i = headerPairs.length; i--; ) + { + var headerPair = headerPairs[i]; + var index = headerPair.indexOf(': '); + if (index > 0) + { + var key = headerPair.substring(0, index); + var value = headerPair.substring(index + 2); + + headers = A3($elm$core$Dict$update, key, function(oldValue) { + return $elm$core$Maybe$Just($elm$core$Maybe$isJust(oldValue) + ? value + ', ' + oldValue.a + : value + ); + }, headers); + } + } + return headers; +} + + +// EXPECT + +var _Http_expect = F3(function(type, toBody, toValue) +{ + return { + $: 0, + d: type, + b: toBody, + a: toValue + }; +}); + +var _Http_mapExpect = F2(function(func, expect) +{ + return { + $: 0, + d: expect.d, + b: expect.b, + a: function(x) { return func(expect.a(x)); } + }; +}); + +function _Http_toDataView(arrayBuffer) +{ + return new DataView(arrayBuffer); +} + + +// BODY and PARTS + +var _Http_emptyBody = { $: 0 }; +var _Http_pair = F2(function(a, b) { return { $: 0, a: a, b: b }; }); + +function _Http_toFormData(parts) +{ + for (var formData = new FormData(); parts.b; parts = parts.b) // WHILE_CONS + { + var part = parts.a; + formData.append(part.a, part.b); + } + return formData; +} + +var _Http_bytesToBlob = F2(function(mime, bytes) +{ + return new Blob([bytes], { type: mime }); +}); + + +// PROGRESS + +function _Http_track(router, xhr, tracker) +{ + // TODO check out lengthComputable on loadstart event + + xhr.upload.addEventListener('progress', function(event) { + if (xhr.c) { return; } + _Scheduler_rawSpawn(A2($elm$core$Platform$sendToSelf, router, _Utils_Tuple2(tracker, $elm$http$Http$Sending({ + sent: event.loaded, + size: event.total + })))); + }); + xhr.addEventListener('progress', function(event) { + if (xhr.c) { return; } + _Scheduler_rawSpawn(A2($elm$core$Platform$sendToSelf, router, _Utils_Tuple2(tracker, $elm$http$Http$Receiving({ + received: event.loaded, + size: event.lengthComputable ? $elm$core$Maybe$Just(event.total) : $elm$core$Maybe$Nothing + })))); + }); +} + + var _Bitwise_and = F2(function(a, b) { return a & b; @@ -5242,23 +5417,810 @@ var $elm$core$Task$perform = F2( A2($elm$core$Task$map, toMessage, task))); }); var $elm$browser$Browser$element = _Browser_element; -var $author$project$PhotoGroove$Large = {$: 'Large'}; -var $author$project$PhotoGroove$initialModel = { - chosenSize: $author$project$PhotoGroove$Large, - photos: _List_fromArray( - [ - {url: '1.jpeg'}, - {url: '2.jpeg'}, - {url: '3.jpeg'} - ]), - selectedUrl: '1.jpeg' +var $author$project$PhotoGroove$GotPhotos = function (a) { + return {$: 'GotPhotos', a: a}; }; -var $elm$core$Platform$Cmd$batch = _Platform_batch; -var $elm$core$Platform$Cmd$none = $elm$core$Platform$Cmd$batch(_List_Nil); +var $elm$http$Http$BadStatus_ = F2( + function (a, b) { + return {$: 'BadStatus_', a: a, b: b}; + }); +var $elm$http$Http$BadUrl_ = function (a) { + return {$: 'BadUrl_', a: a}; +}; +var $elm$http$Http$GoodStatus_ = F2( + function (a, b) { + return {$: 'GoodStatus_', a: a, b: b}; + }); +var $elm$http$Http$NetworkError_ = {$: 'NetworkError_'}; +var $elm$http$Http$Receiving = function (a) { + return {$: 'Receiving', a: a}; +}; +var $elm$http$Http$Sending = function (a) { + return {$: 'Sending', a: a}; +}; +var $elm$http$Http$Timeout_ = {$: 'Timeout_'}; +var $elm$core$Dict$RBEmpty_elm_builtin = {$: 'RBEmpty_elm_builtin'}; +var $elm$core$Dict$empty = $elm$core$Dict$RBEmpty_elm_builtin; +var $elm$core$Maybe$isJust = function (maybe) { + if (maybe.$ === 'Just') { + return true; + } else { + return false; + } +}; +var $elm$core$Platform$sendToSelf = _Platform_sendToSelf; +var $elm$core$Basics$compare = _Utils_compare; +var $elm$core$Dict$get = F2( + function (targetKey, dict) { + get: + while (true) { + if (dict.$ === 'RBEmpty_elm_builtin') { + return $elm$core$Maybe$Nothing; + } else { + var key = dict.b; + var value = dict.c; + var left = dict.d; + var right = dict.e; + var _v1 = A2($elm$core$Basics$compare, targetKey, key); + switch (_v1.$) { + case 'LT': + var $temp$targetKey = targetKey, + $temp$dict = left; + targetKey = $temp$targetKey; + dict = $temp$dict; + continue get; + case 'EQ': + return $elm$core$Maybe$Just(value); + default: + var $temp$targetKey = targetKey, + $temp$dict = right; + targetKey = $temp$targetKey; + dict = $temp$dict; + continue get; + } + } + } + }); +var $elm$core$Dict$Black = {$: 'Black'}; +var $elm$core$Dict$RBNode_elm_builtin = F5( + function (a, b, c, d, e) { + return {$: 'RBNode_elm_builtin', a: a, b: b, c: c, d: d, e: e}; + }); +var $elm$core$Dict$Red = {$: 'Red'}; +var $elm$core$Dict$balance = F5( + function (color, key, value, left, right) { + if ((right.$ === 'RBNode_elm_builtin') && (right.a.$ === 'Red')) { + var _v1 = right.a; + var rK = right.b; + var rV = right.c; + var rLeft = right.d; + var rRight = right.e; + if ((left.$ === 'RBNode_elm_builtin') && (left.a.$ === 'Red')) { + var _v3 = left.a; + var lK = left.b; + var lV = left.c; + var lLeft = left.d; + var lRight = left.e; + return A5( + $elm$core$Dict$RBNode_elm_builtin, + $elm$core$Dict$Red, + key, + value, + A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Black, lK, lV, lLeft, lRight), + A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Black, rK, rV, rLeft, rRight)); + } else { + return A5( + $elm$core$Dict$RBNode_elm_builtin, + color, + rK, + rV, + A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Red, key, value, left, rLeft), + rRight); + } + } else { + if ((((left.$ === 'RBNode_elm_builtin') && (left.a.$ === 'Red')) && (left.d.$ === 'RBNode_elm_builtin')) && (left.d.a.$ === 'Red')) { + var _v5 = left.a; + var lK = left.b; + var lV = left.c; + var _v6 = left.d; + var _v7 = _v6.a; + var llK = _v6.b; + var llV = _v6.c; + var llLeft = _v6.d; + var llRight = _v6.e; + var lRight = left.e; + return A5( + $elm$core$Dict$RBNode_elm_builtin, + $elm$core$Dict$Red, + lK, + lV, + A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Black, llK, llV, llLeft, llRight), + A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Black, key, value, lRight, right)); + } else { + return A5($elm$core$Dict$RBNode_elm_builtin, color, key, value, left, right); + } + } + }); +var $elm$core$Dict$insertHelp = F3( + function (key, value, dict) { + if (dict.$ === 'RBEmpty_elm_builtin') { + return A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Red, key, value, $elm$core$Dict$RBEmpty_elm_builtin, $elm$core$Dict$RBEmpty_elm_builtin); + } else { + var nColor = dict.a; + var nKey = dict.b; + var nValue = dict.c; + var nLeft = dict.d; + var nRight = dict.e; + var _v1 = A2($elm$core$Basics$compare, key, nKey); + switch (_v1.$) { + case 'LT': + return A5( + $elm$core$Dict$balance, + nColor, + nKey, + nValue, + A3($elm$core$Dict$insertHelp, key, value, nLeft), + nRight); + case 'EQ': + return A5($elm$core$Dict$RBNode_elm_builtin, nColor, nKey, value, nLeft, nRight); + default: + return A5( + $elm$core$Dict$balance, + nColor, + nKey, + nValue, + nLeft, + A3($elm$core$Dict$insertHelp, key, value, nRight)); + } + } + }); +var $elm$core$Dict$insert = F3( + function (key, value, dict) { + var _v0 = A3($elm$core$Dict$insertHelp, key, value, dict); + if ((_v0.$ === 'RBNode_elm_builtin') && (_v0.a.$ === 'Red')) { + var _v1 = _v0.a; + var k = _v0.b; + var v = _v0.c; + var l = _v0.d; + var r = _v0.e; + return A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Black, k, v, l, r); + } else { + var x = _v0; + return x; + } + }); +var $elm$core$Dict$getMin = function (dict) { + getMin: + while (true) { + if ((dict.$ === 'RBNode_elm_builtin') && (dict.d.$ === 'RBNode_elm_builtin')) { + var left = dict.d; + var $temp$dict = left; + dict = $temp$dict; + continue getMin; + } else { + return dict; + } + } +}; +var $elm$core$Dict$moveRedLeft = function (dict) { + if (((dict.$ === 'RBNode_elm_builtin') && (dict.d.$ === 'RBNode_elm_builtin')) && (dict.e.$ === 'RBNode_elm_builtin')) { + if ((dict.e.d.$ === 'RBNode_elm_builtin') && (dict.e.d.a.$ === 'Red')) { + var clr = dict.a; + var k = dict.b; + var v = dict.c; + var _v1 = dict.d; + var lClr = _v1.a; + var lK = _v1.b; + var lV = _v1.c; + var lLeft = _v1.d; + var lRight = _v1.e; + var _v2 = dict.e; + var rClr = _v2.a; + var rK = _v2.b; + var rV = _v2.c; + var rLeft = _v2.d; + var _v3 = rLeft.a; + var rlK = rLeft.b; + var rlV = rLeft.c; + var rlL = rLeft.d; + var rlR = rLeft.e; + var rRight = _v2.e; + return A5( + $elm$core$Dict$RBNode_elm_builtin, + $elm$core$Dict$Red, + rlK, + rlV, + A5( + $elm$core$Dict$RBNode_elm_builtin, + $elm$core$Dict$Black, + k, + v, + A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Red, lK, lV, lLeft, lRight), + rlL), + A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Black, rK, rV, rlR, rRight)); + } else { + var clr = dict.a; + var k = dict.b; + var v = dict.c; + var _v4 = dict.d; + var lClr = _v4.a; + var lK = _v4.b; + var lV = _v4.c; + var lLeft = _v4.d; + var lRight = _v4.e; + var _v5 = dict.e; + var rClr = _v5.a; + var rK = _v5.b; + var rV = _v5.c; + var rLeft = _v5.d; + var rRight = _v5.e; + if (clr.$ === 'Black') { + return A5( + $elm$core$Dict$RBNode_elm_builtin, + $elm$core$Dict$Black, + k, + v, + A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Red, lK, lV, lLeft, lRight), + A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Red, rK, rV, rLeft, rRight)); + } else { + return A5( + $elm$core$Dict$RBNode_elm_builtin, + $elm$core$Dict$Black, + k, + v, + A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Red, lK, lV, lLeft, lRight), + A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Red, rK, rV, rLeft, rRight)); + } + } + } else { + return dict; + } +}; +var $elm$core$Dict$moveRedRight = function (dict) { + if (((dict.$ === 'RBNode_elm_builtin') && (dict.d.$ === 'RBNode_elm_builtin')) && (dict.e.$ === 'RBNode_elm_builtin')) { + if ((dict.d.d.$ === 'RBNode_elm_builtin') && (dict.d.d.a.$ === 'Red')) { + var clr = dict.a; + var k = dict.b; + var v = dict.c; + var _v1 = dict.d; + var lClr = _v1.a; + var lK = _v1.b; + var lV = _v1.c; + var _v2 = _v1.d; + var _v3 = _v2.a; + var llK = _v2.b; + var llV = _v2.c; + var llLeft = _v2.d; + var llRight = _v2.e; + var lRight = _v1.e; + var _v4 = dict.e; + var rClr = _v4.a; + var rK = _v4.b; + var rV = _v4.c; + var rLeft = _v4.d; + var rRight = _v4.e; + return A5( + $elm$core$Dict$RBNode_elm_builtin, + $elm$core$Dict$Red, + lK, + lV, + A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Black, llK, llV, llLeft, llRight), + A5( + $elm$core$Dict$RBNode_elm_builtin, + $elm$core$Dict$Black, + k, + v, + lRight, + A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Red, rK, rV, rLeft, rRight))); + } else { + var clr = dict.a; + var k = dict.b; + var v = dict.c; + var _v5 = dict.d; + var lClr = _v5.a; + var lK = _v5.b; + var lV = _v5.c; + var lLeft = _v5.d; + var lRight = _v5.e; + var _v6 = dict.e; + var rClr = _v6.a; + var rK = _v6.b; + var rV = _v6.c; + var rLeft = _v6.d; + var rRight = _v6.e; + if (clr.$ === 'Black') { + return A5( + $elm$core$Dict$RBNode_elm_builtin, + $elm$core$Dict$Black, + k, + v, + A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Red, lK, lV, lLeft, lRight), + A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Red, rK, rV, rLeft, rRight)); + } else { + return A5( + $elm$core$Dict$RBNode_elm_builtin, + $elm$core$Dict$Black, + k, + v, + A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Red, lK, lV, lLeft, lRight), + A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Red, rK, rV, rLeft, rRight)); + } + } + } else { + return dict; + } +}; +var $elm$core$Dict$removeHelpPrepEQGT = F7( + function (targetKey, dict, color, key, value, left, right) { + if ((left.$ === 'RBNode_elm_builtin') && (left.a.$ === 'Red')) { + var _v1 = left.a; + var lK = left.b; + var lV = left.c; + var lLeft = left.d; + var lRight = left.e; + return A5( + $elm$core$Dict$RBNode_elm_builtin, + color, + lK, + lV, + lLeft, + A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Red, key, value, lRight, right)); + } else { + _v2$2: + while (true) { + if ((right.$ === 'RBNode_elm_builtin') && (right.a.$ === 'Black')) { + if (right.d.$ === 'RBNode_elm_builtin') { + if (right.d.a.$ === 'Black') { + var _v3 = right.a; + var _v4 = right.d; + var _v5 = _v4.a; + return $elm$core$Dict$moveRedRight(dict); + } else { + break _v2$2; + } + } else { + var _v6 = right.a; + var _v7 = right.d; + return $elm$core$Dict$moveRedRight(dict); + } + } else { + break _v2$2; + } + } + return dict; + } + }); +var $elm$core$Dict$removeMin = function (dict) { + if ((dict.$ === 'RBNode_elm_builtin') && (dict.d.$ === 'RBNode_elm_builtin')) { + var color = dict.a; + var key = dict.b; + var value = dict.c; + var left = dict.d; + var lColor = left.a; + var lLeft = left.d; + var right = dict.e; + if (lColor.$ === 'Black') { + if ((lLeft.$ === 'RBNode_elm_builtin') && (lLeft.a.$ === 'Red')) { + var _v3 = lLeft.a; + return A5( + $elm$core$Dict$RBNode_elm_builtin, + color, + key, + value, + $elm$core$Dict$removeMin(left), + right); + } else { + var _v4 = $elm$core$Dict$moveRedLeft(dict); + if (_v4.$ === 'RBNode_elm_builtin') { + var nColor = _v4.a; + var nKey = _v4.b; + var nValue = _v4.c; + var nLeft = _v4.d; + var nRight = _v4.e; + return A5( + $elm$core$Dict$balance, + nColor, + nKey, + nValue, + $elm$core$Dict$removeMin(nLeft), + nRight); + } else { + return $elm$core$Dict$RBEmpty_elm_builtin; + } + } + } else { + return A5( + $elm$core$Dict$RBNode_elm_builtin, + color, + key, + value, + $elm$core$Dict$removeMin(left), + right); + } + } else { + return $elm$core$Dict$RBEmpty_elm_builtin; + } +}; +var $elm$core$Dict$removeHelp = F2( + function (targetKey, dict) { + if (dict.$ === 'RBEmpty_elm_builtin') { + return $elm$core$Dict$RBEmpty_elm_builtin; + } else { + var color = dict.a; + var key = dict.b; + var value = dict.c; + var left = dict.d; + var right = dict.e; + if (_Utils_cmp(targetKey, key) < 0) { + if ((left.$ === 'RBNode_elm_builtin') && (left.a.$ === 'Black')) { + var _v4 = left.a; + var lLeft = left.d; + if ((lLeft.$ === 'RBNode_elm_builtin') && (lLeft.a.$ === 'Red')) { + var _v6 = lLeft.a; + return A5( + $elm$core$Dict$RBNode_elm_builtin, + color, + key, + value, + A2($elm$core$Dict$removeHelp, targetKey, left), + right); + } else { + var _v7 = $elm$core$Dict$moveRedLeft(dict); + if (_v7.$ === 'RBNode_elm_builtin') { + var nColor = _v7.a; + var nKey = _v7.b; + var nValue = _v7.c; + var nLeft = _v7.d; + var nRight = _v7.e; + return A5( + $elm$core$Dict$balance, + nColor, + nKey, + nValue, + A2($elm$core$Dict$removeHelp, targetKey, nLeft), + nRight); + } else { + return $elm$core$Dict$RBEmpty_elm_builtin; + } + } + } else { + return A5( + $elm$core$Dict$RBNode_elm_builtin, + color, + key, + value, + A2($elm$core$Dict$removeHelp, targetKey, left), + right); + } + } else { + return A2( + $elm$core$Dict$removeHelpEQGT, + targetKey, + A7($elm$core$Dict$removeHelpPrepEQGT, targetKey, dict, color, key, value, left, right)); + } + } + }); +var $elm$core$Dict$removeHelpEQGT = F2( + function (targetKey, dict) { + if (dict.$ === 'RBNode_elm_builtin') { + var color = dict.a; + var key = dict.b; + var value = dict.c; + var left = dict.d; + var right = dict.e; + if (_Utils_eq(targetKey, key)) { + var _v1 = $elm$core$Dict$getMin(right); + if (_v1.$ === 'RBNode_elm_builtin') { + var minKey = _v1.b; + var minValue = _v1.c; + return A5( + $elm$core$Dict$balance, + color, + minKey, + minValue, + left, + $elm$core$Dict$removeMin(right)); + } else { + return $elm$core$Dict$RBEmpty_elm_builtin; + } + } else { + return A5( + $elm$core$Dict$balance, + color, + key, + value, + left, + A2($elm$core$Dict$removeHelp, targetKey, right)); + } + } else { + return $elm$core$Dict$RBEmpty_elm_builtin; + } + }); +var $elm$core$Dict$remove = F2( + function (key, dict) { + var _v0 = A2($elm$core$Dict$removeHelp, key, dict); + if ((_v0.$ === 'RBNode_elm_builtin') && (_v0.a.$ === 'Red')) { + var _v1 = _v0.a; + var k = _v0.b; + var v = _v0.c; + var l = _v0.d; + var r = _v0.e; + return A5($elm$core$Dict$RBNode_elm_builtin, $elm$core$Dict$Black, k, v, l, r); + } else { + var x = _v0; + return x; + } + }); +var $elm$core$Dict$update = F3( + function (targetKey, alter, dictionary) { + var _v0 = alter( + A2($elm$core$Dict$get, targetKey, dictionary)); + if (_v0.$ === 'Just') { + var value = _v0.a; + return A3($elm$core$Dict$insert, targetKey, value, dictionary); + } else { + return A2($elm$core$Dict$remove, targetKey, dictionary); + } + }); +var $elm$core$Basics$composeR = F3( + function (f, g, x) { + return g( + f(x)); + }); +var $elm$http$Http$expectStringResponse = F2( + function (toMsg, toResult) { + return A3( + _Http_expect, + '', + $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') { + var v = result.a; + return $elm$core$Result$Ok(v); + } else { + var e = result.a; + return $elm$core$Result$Err( + f(e)); + } + }); +var $elm$http$Http$resolve = F2( + function (toResult, response) { + switch (response.$) { + case 'BadUrl_': + var url = response.a; + return $elm$core$Result$Err( + $elm$http$Http$BadUrl(url)); + case 'Timeout_': + return $elm$core$Result$Err($elm$http$Http$Timeout); + case 'NetworkError_': + return $elm$core$Result$Err($elm$http$Http$NetworkError); + case 'BadStatus_': + var metadata = response.a; + return $elm$core$Result$Err( + $elm$http$Http$BadStatus(metadata.statusCode)); + default: + var body = response.b; + return A2( + $elm$core$Result$mapError, + $elm$http$Http$BadBody, + 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$emptyBody = _Http_emptyBody; +var $elm$http$Http$Request = function (a) { + return {$: 'Request', a: a}; +}; +var $elm$http$Http$State = F2( + function (reqs, subs) { + return {reqs: reqs, subs: subs}; + }); +var $elm$http$Http$init = $elm$core$Task$succeed( + A2($elm$http$Http$State, $elm$core$Dict$empty, _List_Nil)); +var $elm$core$Process$kill = _Scheduler_kill; +var $elm$core$Process$spawn = _Scheduler_spawn; +var $elm$http$Http$updateReqs = F3( + function (router, cmds, reqs) { + updateReqs: + while (true) { + if (!cmds.b) { + return $elm$core$Task$succeed(reqs); + } else { + var cmd = cmds.a; + var otherCmds = cmds.b; + if (cmd.$ === 'Cancel') { + var tracker = cmd.a; + var _v2 = A2($elm$core$Dict$get, tracker, reqs); + if (_v2.$ === 'Nothing') { + var $temp$router = router, + $temp$cmds = otherCmds, + $temp$reqs = reqs; + router = $temp$router; + cmds = $temp$cmds; + reqs = $temp$reqs; + continue updateReqs; + } else { + var pid = _v2.a; + return A2( + $elm$core$Task$andThen, + function (_v3) { + return A3( + $elm$http$Http$updateReqs, + router, + otherCmds, + A2($elm$core$Dict$remove, tracker, reqs)); + }, + $elm$core$Process$kill(pid)); + } + } else { + var req = cmd.a; + return A2( + $elm$core$Task$andThen, + function (pid) { + var _v4 = req.tracker; + if (_v4.$ === 'Nothing') { + return A3($elm$http$Http$updateReqs, router, otherCmds, reqs); + } else { + var tracker = _v4.a; + return A3( + $elm$http$Http$updateReqs, + router, + otherCmds, + A3($elm$core$Dict$insert, tracker, pid, reqs)); + } + }, + $elm$core$Process$spawn( + A3( + _Http_toTask, + router, + $elm$core$Platform$sendToApp(router), + req))); + } + } + } + }); +var $elm$http$Http$onEffects = F4( + function (router, cmds, subs, state) { + return A2( + $elm$core$Task$andThen, + function (reqs) { + return $elm$core$Task$succeed( + A2($elm$http$Http$State, reqs, subs)); + }, + A3($elm$http$Http$updateReqs, router, cmds, state.reqs)); + }); +var $elm$core$List$maybeCons = F3( + function (f, mx, xs) { + var _v0 = f(mx); + if (_v0.$ === 'Just') { + var x = _v0.a; + return A2($elm$core$List$cons, x, xs); + } else { + return xs; + } + }); +var $elm$core$List$filterMap = F2( + function (f, xs) { + return A3( + $elm$core$List$foldr, + $elm$core$List$maybeCons(f), + _List_Nil, + xs); + }); +var $elm$http$Http$maybeSend = F4( + function (router, desiredTracker, progress, _v0) { + var actualTracker = _v0.a; + var toMsg = _v0.b; + return _Utils_eq(desiredTracker, actualTracker) ? $elm$core$Maybe$Just( + A2( + $elm$core$Platform$sendToApp, + router, + toMsg(progress))) : $elm$core$Maybe$Nothing; + }); +var $elm$http$Http$onSelfMsg = F3( + function (router, _v0, state) { + var tracker = _v0.a; + var progress = _v0.b; + return A2( + $elm$core$Task$andThen, + function (_v1) { + return $elm$core$Task$succeed(state); + }, + $elm$core$Task$sequence( + A2( + $elm$core$List$filterMap, + A3($elm$http$Http$maybeSend, router, tracker, progress), + state.subs))); + }); +var $elm$http$Http$Cancel = function (a) { + return {$: 'Cancel', a: a}; +}; +var $elm$http$Http$cmdMap = F2( + function (func, cmd) { + if (cmd.$ === 'Cancel') { + var tracker = cmd.a; + return $elm$http$Http$Cancel(tracker); + } else { + var r = cmd.a; + return $elm$http$Http$Request( + { + allowCookiesFromOtherDomains: r.allowCookiesFromOtherDomains, + body: r.body, + expect: A2(_Http_mapExpect, func, r.expect), + headers: r.headers, + method: r.method, + timeout: r.timeout, + tracker: r.tracker, + url: r.url + }); + } + }); +var $elm$http$Http$MySub = F2( + function (a, b) { + return {$: 'MySub', a: a, b: b}; + }); +var $elm$http$Http$subMap = F2( + function (func, _v0) { + var tracker = _v0.a; + var toMsg = _v0.b; + return A2( + $elm$http$Http$MySub, + tracker, + A2($elm$core$Basics$composeR, toMsg, func)); + }); +_Platform_effectManagers['Http'] = _Platform_createManager($elm$http$Http$init, $elm$http$Http$onEffects, $elm$http$Http$onSelfMsg, $elm$http$Http$cmdMap, $elm$http$Http$subMap); +var $elm$http$Http$command = _Platform_leaf('Http'); +var $elm$http$Http$subscription = _Platform_leaf('Http'); +var $elm$http$Http$request = function (r) { + return $elm$http$Http$command( + $elm$http$Http$Request( + {allowCookiesFromOtherDomains: false, body: r.body, expect: r.expect, headers: r.headers, method: r.method, timeout: r.timeout, tracker: r.tracker, url: r.url})); +}; +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 $author$project$PhotoGroove$initialCommand = $elm$http$Http$get( + { + expect: $elm$http$Http$expectString($author$project$PhotoGroove$GotPhotos), + url: 'list' + }); +var $author$project$PhotoGroove$Large = {$: 'Large'}; +var $author$project$PhotoGroove$Loading = {$: 'Loading'}; +var $author$project$PhotoGroove$initialModel = {chosenSize: $author$project$PhotoGroove$Large, status: $author$project$PhotoGroove$Loading}; var $elm$core$Platform$Sub$batch = _Platform_batch; var $elm$core$Platform$Sub$none = $elm$core$Platform$Sub$batch(_List_Nil); -var $author$project$PhotoGroove$GotSelectedIndex = function (a) { - return {$: 'GotSelectedIndex', a: a}; +var $author$project$PhotoGroove$Errored = function (a) { + return {$: 'Errored', a: a}; +}; +var $author$project$PhotoGroove$GotRandomPhoto = function (a) { + return {$: 'GotRandomPhoto', a: a}; +}; +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}; @@ -5367,141 +6329,124 @@ var $elm$random$Random$generate = F2( $elm$random$Random$Generate( A2($elm$random$Random$map, tagger, generator))); }); -var $elm$core$Bitwise$and = _Bitwise_and; -var $elm$core$Array$bitMask = 4294967295 >>> (32 - $elm$core$Array$shiftStep); -var $elm$core$Basics$ge = _Utils_ge; -var $elm$core$Elm$JsArray$unsafeGet = _JsArray_unsafeGet; -var $elm$core$Array$getHelp = F3( - function (shift, index, tree) { - getHelp: - while (true) { - var pos = $elm$core$Array$bitMask & (index >>> shift); - var _v0 = A2($elm$core$Elm$JsArray$unsafeGet, pos, tree); - if (_v0.$ === 'SubTree') { - var subTree = _v0.a; - var $temp$shift = shift - $elm$core$Array$shiftStep, - $temp$index = index, - $temp$tree = subTree; - shift = $temp$shift; - index = $temp$index; - tree = $temp$tree; - continue getHelp; - } else { - var values = _v0.a; - return A2($elm$core$Elm$JsArray$unsafeGet, $elm$core$Array$bitMask & index, values); - } - } - }); -var $elm$core$Bitwise$shiftLeftBy = _Bitwise_shiftLeftBy; -var $elm$core$Array$tailIndex = function (len) { - return (len >>> 5) << 5; -}; -var $elm$core$Array$get = F2( - function (index, _v0) { - var len = _v0.a; - var startShift = _v0.b; - var tree = _v0.c; - var tail = _v0.d; - return ((index < 0) || (_Utils_cmp(index, len) > -1)) ? $elm$core$Maybe$Nothing : ((_Utils_cmp( - index, - $elm$core$Array$tailIndex(len)) > -1) ? $elm$core$Maybe$Just( - A2($elm$core$Elm$JsArray$unsafeGet, $elm$core$Array$bitMask & index, tail)) : $elm$core$Maybe$Just( - A3($elm$core$Array$getHelp, startShift, index, tree))); - }); -var $elm$core$Array$fromListHelp = F3( - function (list, nodeList, nodeListSize) { - fromListHelp: - while (true) { - var _v0 = A2($elm$core$Elm$JsArray$initializeFromList, $elm$core$Array$branchFactor, list); - var jsArray = _v0.a; - var remainingItems = _v0.b; - if (_Utils_cmp( - $elm$core$Elm$JsArray$length(jsArray), - $elm$core$Array$branchFactor) < 0) { - return A2( - $elm$core$Array$builderToArray, - true, - {nodeList: nodeList, nodeListSize: nodeListSize, tail: jsArray}); - } else { - var $temp$list = remainingItems, - $temp$nodeList = A2( - $elm$core$List$cons, - $elm$core$Array$Leaf(jsArray), - nodeList), - $temp$nodeListSize = nodeListSize + 1; - list = $temp$list; - nodeList = $temp$nodeList; - nodeListSize = $temp$nodeListSize; - continue fromListHelp; - } - } - }); -var $elm$core$Array$fromList = function (list) { - if (!list.b) { - return $elm$core$Array$empty; - } else { - return A3($elm$core$Array$fromListHelp, list, _List_Nil, 0); +var $author$project$PhotoGroove$httpErrorToString = function (err) { + switch (err.$) { + case 'BadUrl': + var msg = err.a; + return 'bad URL: ' + msg; + case 'Timeout': + return 'timeout'; + case 'NetworkError': + return 'network error'; + case 'BadStatus': + var status = err.a; + return 'bad status: ' + $elm$core$String$fromInt(status); + default: + var msg = err.a; + return 'bad body: ' + msg; } }; -var $author$project$PhotoGroove$photoArray = $elm$core$Array$fromList($author$project$PhotoGroove$initialModel.photos); -var $author$project$PhotoGroove$getPhotoUrl = function (id) { - var _v0 = A2($elm$core$Array$get, id, $author$project$PhotoGroove$photoArray); - if (_v0.$ === 'Just') { - var photo = _v0.a; - return photo.url; - } else { - return ''; - } +var $elm$core$Platform$Cmd$batch = _Platform_batch; +var $elm$core$Platform$Cmd$none = $elm$core$Platform$Cmd$batch(_List_Nil); +var $elm$core$Tuple$pair = F2( + function (a, b) { + return _Utils_Tuple2(a, b); + }); +var $author$project$PhotoGroove$selectUrl = F2( + function (url, status) { + switch (status.$) { + case 'Loading': + return status; + case 'Loaded': + var photos = status.a; + return A2($author$project$PhotoGroove$Loaded, photos, url); + default: + return status; + } + }); +var $elm$random$Random$addOne = function (value) { + return _Utils_Tuple2(1, value); }; var $elm$core$Basics$negate = function (n) { return -n; }; +var $elm$core$Basics$abs = function (n) { + return (n < 0) ? (-n) : n; +}; +var $elm$core$Bitwise$and = _Bitwise_and; var $elm$core$Bitwise$xor = _Bitwise_xor; var $elm$random$Random$peel = function (_v0) { var state = _v0.a; var word = (state ^ (state >>> ((state >>> 28) + 4))) * 277803737; return ((word >>> 22) ^ word) >>> 0; }; -var $elm$random$Random$int = F2( +var $elm$random$Random$float = F2( function (a, b) { return $elm$random$Random$Generator( function (seed0) { - var _v0 = (_Utils_cmp(a, b) < 0) ? _Utils_Tuple2(a, b) : _Utils_Tuple2(b, a); - var lo = _v0.a; - var hi = _v0.b; - var range = (hi - lo) + 1; - if (!((range - 1) & range)) { - return _Utils_Tuple2( - (((range - 1) & $elm$random$Random$peel(seed0)) >>> 0) + lo, - $elm$random$Random$next(seed0)); - } else { - var threshhold = (((-range) >>> 0) % range) >>> 0; - var accountForBias = function (seed) { - accountForBias: - while (true) { - var x = $elm$random$Random$peel(seed); - var seedN = $elm$random$Random$next(seed); - if (_Utils_cmp(x, threshhold) < 0) { - var $temp$seed = seedN; - seed = $temp$seed; - continue accountForBias; - } else { - return _Utils_Tuple2((x % range) + lo, seedN); - } - } - }; - return accountForBias(seed0); - } + var seed1 = $elm$random$Random$next(seed0); + var range = $elm$core$Basics$abs(b - a); + var n1 = $elm$random$Random$peel(seed1); + var n0 = $elm$random$Random$peel(seed0); + var lo = (134217727 & n1) * 1.0; + var hi = (67108863 & n0) * 1.0; + var val = ((hi * 134217728.0) + lo) / 9007199254740992.0; + var scaled = (val * range) + a; + return _Utils_Tuple2( + scaled, + $elm$random$Random$next(seed1)); }); }); -var $elm$core$Array$length = function (_v0) { - var len = _v0.a; - return len; +var $elm$random$Random$getByWeight = F3( + function (_v0, others, countdown) { + getByWeight: + while (true) { + var weight = _v0.a; + var value = _v0.b; + if (!others.b) { + return value; + } else { + var second = others.a; + var otherOthers = others.b; + if (_Utils_cmp( + countdown, + $elm$core$Basics$abs(weight)) < 1) { + return value; + } else { + var $temp$_v0 = second, + $temp$others = otherOthers, + $temp$countdown = countdown - $elm$core$Basics$abs(weight); + _v0 = $temp$_v0; + others = $temp$others; + countdown = $temp$countdown; + continue getByWeight; + } + } + } + }); +var $elm$core$List$sum = function (numbers) { + return A3($elm$core$List$foldl, $elm$core$Basics$add, 0, numbers); }; -var $author$project$PhotoGroove$randomPhotoPicker = A2( - $elm$random$Random$int, - 0, - $elm$core$Array$length($author$project$PhotoGroove$photoArray) - 1); +var $elm$random$Random$weighted = F2( + function (first, others) { + var normalize = function (_v0) { + var weight = _v0.a; + return $elm$core$Basics$abs(weight); + }; + var total = normalize(first) + $elm$core$List$sum( + A2($elm$core$List$map, normalize, others)); + return A2( + $elm$random$Random$map, + A2($elm$random$Random$getByWeight, first, others), + A2($elm$random$Random$float, 0, total)); + }); +var $elm$random$Random$uniform = F2( + function (value, valueList) { + return A2( + $elm$random$Random$weighted, + $elm$random$Random$addOne(value), + A2($elm$core$List$map, $elm$random$Random$addOne, valueList)); + }); var $author$project$PhotoGroove$update = F2( function (msg, model) { switch (msg.$) { @@ -5510,12 +6455,33 @@ var $author$project$PhotoGroove$update = F2( return _Utils_Tuple2( _Utils_update( model, - {selectedUrl: thumb}), + { + status: A2($author$project$PhotoGroove$selectUrl, thumb, model.status) + }), $elm$core$Platform$Cmd$none); case 'ClickedSurpriseMe': - return _Utils_Tuple2( - model, - A2($elm$random$Random$generate, $author$project$PhotoGroove$GotSelectedIndex, $author$project$PhotoGroove$randomPhotoPicker)); + var _v1 = model.status; + switch (_v1.$) { + case 'Loaded': + if (_v1.a.b) { + var _v2 = _v1.a; + var photo = _v2.a; + var morePhotos = _v2.b; + return A2( + $elm$core$Tuple$pair, + model, + A2( + $elm$random$Random$generate, + $author$project$PhotoGroove$GotRandomPhoto, + A2($elm$random$Random$uniform, photo, morePhotos))); + } else { + return _Utils_Tuple2(model, $elm$core$Platform$Cmd$none); + } + case 'Loading': + return _Utils_Tuple2(model, $elm$core$Platform$Cmd$none); + default: + return _Utils_Tuple2(model, $elm$core$Platform$Cmd$none); + } case 'ClickedSize': var size = msg.a; return _Utils_Tuple2( @@ -5523,21 +6489,52 @@ var $author$project$PhotoGroove$update = F2( model, {chosenSize: size}), $elm$core$Platform$Cmd$none); - default: - var idx = msg.a; + case 'GotRandomPhoto': + var photo = msg.a; return _Utils_Tuple2( _Utils_update( model, { - selectedUrl: $author$project$PhotoGroove$getPhotoUrl(idx) + status: A2($author$project$PhotoGroove$selectUrl, photo.url, model.status) }), $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); + return _Utils_Tuple2( + _Utils_update( + model, + { + status: A2($author$project$PhotoGroove$Loaded, photos, x) + }), + $elm$core$Platform$Cmd$none); + } else { + return _Utils_Tuple2( + _Utils_update( + model, + { + status: $author$project$PhotoGroove$Errored('No photos: ' + str) + }), + $elm$core$Platform$Cmd$none); + } + } else { + var httpError = msg.a.a; + return _Utils_Tuple2( + _Utils_update( + model, + { + status: $author$project$PhotoGroove$Errored( + 'Failed to load photos: ' + $author$project$PhotoGroove$httpErrorToString(httpError)) + }), + $elm$core$Platform$Cmd$none); + } } }); -var $author$project$PhotoGroove$ClickedSurpriseMe = {$: 'ClickedSurpriseMe'}; -var $author$project$PhotoGroove$Medium = {$: 'Medium'}; -var $author$project$PhotoGroove$Small = {$: 'Small'}; -var $elm$html$Html$button = _VirtualDom_node('button'); var $elm$json$Json$Encode$string = _Json_wrap; var $elm$html$Html$Attributes$stringProperty = F2( function (key, string) { @@ -5548,6 +6545,12 @@ var $elm$html$Html$Attributes$stringProperty = F2( }); var $elm$html$Html$Attributes$class = $elm$html$Html$Attributes$stringProperty('className'); var $elm$html$Html$div = _VirtualDom_node('div'); +var $elm$virtual_dom$VirtualDom$text = _VirtualDom_text; +var $elm$html$Html$text = $elm$virtual_dom$VirtualDom$text; +var $author$project$PhotoGroove$ClickedSurpriseMe = {$: 'ClickedSurpriseMe'}; +var $author$project$PhotoGroove$Medium = {$: 'Medium'}; +var $author$project$PhotoGroove$Small = {$: 'Small'}; +var $elm$html$Html$button = _VirtualDom_node('button'); var $elm$html$Html$h1 = _VirtualDom_node('h1'); var $elm$html$Html$h3 = _VirtualDom_node('h3'); var $elm$html$Html$Attributes$id = $elm$html$Html$Attributes$stringProperty('id'); @@ -5585,8 +6588,6 @@ var $elm$html$Html$Attributes$src = function (url) { 'src', _VirtualDom_noJavaScriptOrHtmlUri(url)); }; -var $elm$virtual_dom$VirtualDom$text = _VirtualDom_text; -var $elm$html$Html$text = $elm$virtual_dom$VirtualDom$text; var $author$project$PhotoGroove$urlPrefix = 'http://elm-in-action.com/'; var $author$project$PhotoGroove$ClickedSize = function (a) { return {$: 'ClickedSize', a: a}; @@ -5673,14 +6674,9 @@ var $author$project$PhotoGroove$viewThumbnail = F2( ]), _List_Nil); }); -var $author$project$PhotoGroove$view = function (model) { - return A2( - $elm$html$Html$div, - _List_fromArray( - [ - $elm$html$Html$Attributes$class('content') - ]), - _List_fromArray( +var $author$project$PhotoGroove$viewLoaded = F3( + function (photos, selected, size) { + return _List_fromArray( [ A2( $elm$html$Html$h1, @@ -5723,26 +6719,51 @@ var $author$project$PhotoGroove$view = function (model) { [ $elm$html$Html$Attributes$id('thumbnails'), $elm$html$Html$Attributes$class( - $author$project$PhotoGroove$sizeToClass(model.chosenSize)) + $author$project$PhotoGroove$sizeToClass(size)) ]), A2( $elm$core$List$map, - $author$project$PhotoGroove$viewThumbnail(model.selectedUrl), - model.photos)), + $author$project$PhotoGroove$viewThumbnail(selected), + photos)), A2( $elm$html$Html$img, _List_fromArray( [ $elm$html$Html$Attributes$class('large'), - $elm$html$Html$Attributes$src($author$project$PhotoGroove$urlPrefix + ('large/' + model.selectedUrl)) + $elm$html$Html$Attributes$src($author$project$PhotoGroove$urlPrefix + ('large/' + selected)) ]), _List_Nil) - ])); + ]); + }); +var $author$project$PhotoGroove$view = function (model) { + return A2( + $elm$html$Html$div, + _List_fromArray( + [ + $elm$html$Html$Attributes$class('content') + ]), + function () { + var _v0 = model.status; + switch (_v0.$) { + case 'Loading': + return _List_Nil; + case 'Loaded': + var photos = _v0.a; + var selected = _v0.b; + return A3($author$project$PhotoGroove$viewLoaded, photos, selected, model.chosenSize); + default: + var error = _v0.a; + return _List_fromArray( + [ + $elm$html$Html$text('Error: ' + error) + ]); + } + }()); }; var $author$project$PhotoGroove$main = $elm$browser$Browser$element( { init: function (_v0) { - return _Utils_Tuple2($author$project$PhotoGroove$initialModel, $elm$core$Platform$Cmd$none); + return _Utils_Tuple2($author$project$PhotoGroove$initialModel, $author$project$PhotoGroove$initialCommand); }, subscriptions: function (_v1) { return $elm$core$Platform$Sub$none; diff --git a/elm.json b/elm.json index d100bad..73e3cff 100644 --- a/elm.json +++ b/elm.json @@ -9,9 +9,12 @@ "elm/browser": "1.0.2", "elm/core": "1.0.5", "elm/html": "1.0.0", + "elm/http": "2.0.0", "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", diff --git a/index.html b/index.html index f900bca..25a8b19 100644 --- a/index.html +++ b/index.html @@ -1,7 +1,7 @@ - +
diff --git a/list b/list new file mode 100644 index 0000000..30e46e3 --- /dev/null +++ b/list @@ -0,0 +1 @@ +1.jpeg,2.jpeg,3.jpeg,4.jpeg diff --git a/src/PhotoGroove.elm b/src/PhotoGroove.elm index 2a0a9a9..27a4304 100644 --- a/src/PhotoGroove.elm +++ b/src/PhotoGroove.elm @@ -1,16 +1,21 @@ module PhotoGroove exposing (main) -import Array exposing (Array) import Browser import Html exposing (Html, button, div, h1, h3, img, input, label, text) import Html.Attributes exposing (..) import Html.Events exposing (onClick) +import Http import Random +type Status + = Loading + | Loaded (List Photo) String + | Errored String + + type alias Model = - { photos : List Photo - , selectedUrl : String + { status : Status , chosenSize : ThumbnailSize } @@ -27,51 +32,47 @@ type ThumbnailSize initialModel : Model initialModel = - { photos = - [ { url = "1.jpeg" } - , { url = "2.jpeg" } - , { url = "3.jpeg" } - ] - , selectedUrl = "1.jpeg" + { status = Loading , chosenSize = Large } -getPhotoUrl : Int -> String -getPhotoUrl id = - case Array.get id photoArray of - Just photo -> - photo.url - - Nothing -> - "" - - -photoArray : Array Photo -photoArray = - Array.fromList initialModel.photos - - -randomPhotoPicker : Random.Generator Int -randomPhotoPicker = - Random.int 0 (Array.length photoArray - 1) +initialCommand : Cmd Message +initialCommand = + Http.get + { url = "list" + , expect = Http.expectString GotPhotos + } view : Model -> Html Message view model = - div [ class "content" ] - [ h1 [] [ text "Photo Groove" ] - , button [ onClick ClickedSurpriseMe ] [ text "Surprise me!" ] - , h3 [] [ text "Thumbnail Size:" ] - , div [ id "choose-size" ] - (List.map viewSizeChooser [ Small, Medium, Large ]) - , div - [ id "thumbnails" - , class (sizeToClass model.chosenSize) - ] - (List.map (viewThumbnail model.selectedUrl) model.photos) - , img [ class "large", src (urlPrefix ++ "large/" ++ model.selectedUrl) ] [] + div [ class "content" ] <| + case model.status of + Loading -> + [] + + Loaded photos selected -> + viewLoaded photos selected model.chosenSize + + Errored error -> + [ text ("Error: " ++ error) ] + + +viewLoaded : List Photo -> String -> ThumbnailSize -> List (Html Message) +viewLoaded photos selected size = + [ h1 [] [ text "Photo Groove" ] + , button [ onClick ClickedSurpriseMe ] [ text "Surprise me!" ] + , h3 [] [ text "Thumbnail Size:" ] + , div [ id "choose-size" ] + (List.map viewSizeChooser [ Small, Medium, Large ]) + , div + [ id "thumbnails" + , class (sizeToClass size) ] + (List.map (viewThumbnail selected) photos) + , img [ class "large", src (urlPrefix ++ "large/" ++ selected) ] [] + ] viewThumbnail : String -> Photo -> Html Message @@ -127,23 +128,84 @@ type Message = ClickedThumbnail String | ClickedSurpriseMe | ClickedSize ThumbnailSize - | GotSelectedIndex Int + | GotRandomPhoto Photo + | GotPhotos (Result Http.Error String) update : Message -> Model -> ( Model, Cmd Message ) update msg model = case msg of ClickedThumbnail thumb -> - ( { model | selectedUrl = thumb }, Cmd.none ) + ( { model | status = selectUrl thumb model.status }, Cmd.none ) ClickedSurpriseMe -> - ( model, Random.generate GotSelectedIndex randomPhotoPicker ) + case model.status of + Loaded (photo :: morePhotos) _ -> + Random.uniform photo morePhotos + |> Random.generate GotRandomPhoto + |> Tuple.pair model + + Loaded [] _ -> + ( model, Cmd.none ) + + Loading -> + ( model, Cmd.none ) + + Errored _ -> + ( model, Cmd.none ) ClickedSize size -> ( { model | chosenSize = size }, Cmd.none ) - GotSelectedIndex idx -> - ( { model | selectedUrl = getPhotoUrl idx }, Cmd.none ) + 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 ) + + [] -> + ( { model | status = Errored ("No photos: " ++ str) }, Cmd.none ) + + GotPhotos (Err httpError) -> + ( { model | status = Errored <| ("Failed to load photos: " ++ httpErrorToString httpError) }, Cmd.none ) + + +selectUrl : String -> Status -> Status +selectUrl url status = + case status of + Loading -> + status + + Loaded photos _ -> + Loaded photos url + + Errored _ -> + status + + +httpErrorToString : Http.Error -> String +httpErrorToString err = + case err of + Http.BadUrl msg -> + "bad URL: " ++ msg + + Http.Timeout -> + "timeout" + + Http.NetworkError -> + "network error" + + Http.BadStatus status -> + "bad status: " ++ String.fromInt status + + Http.BadBody msg -> + "bad body: " ++ msg urlPrefix : String @@ -154,7 +216,7 @@ urlPrefix = main : Program () Model Message main = Browser.element - { init = \_ -> ( initialModel, Cmd.none ) + { init = \_ -> ( initialModel, initialCommand ) , subscriptions = \_ -> Sub.none , view = view , update = update diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..d9334b1 --- /dev/null +++ b/styles.css @@ -0,0 +1,184 @@ +body { font-family: Verdana; background-color: rgb(44, 44, 44); color: rgb(250, 250, 250); } +img, canvas { border: 1px solid white; margin: 5px; } +.large { width: 500px; float: right; } +.selected { margin: 0; border: 6px solid #60b5cc; } +.content { margin: 40px auto; width: 960px; } +#thumbnails { width: 440px; float: left; clear: both; } +#thumbnails.small img { width: 50px; } +#thumbnails.med img { width: 100px; } +#thumbnails.large img { width: 200px; } +#choose-size { float: left; margin-left: 20px; } +#choose-size > span { display: inline-block; margin: 0 10px; } +#activate-groove { float: right; margin-right: 20px; margin-top: 15px; } + +h1 { color: #60b5cc; margin-bottom: 0; } +h3 { float: left; margin: 0 } +label { vertical-align: bottom; } +button { + float: right; background-color: #60b5cc; border: 0; color: rgb(44, 44, 44); + font-size: 24px; + cursor: pointer; + padding: 10px 30px; +} + +button:hover { + background-color: white; +} +#thumbnails, img.large, #choose-size, h3 { margin-top: 20px; } + +.filters { + width: 318px; + float: right; +} + +.filter-slider { + width: 300px; +} + +.filter-slider label { + width: 70px; + display: inline-block; + padding-top: 5px; +} + +range-slider { + width: 120px; + margin-top: 5px; + margin-right: 15px; + display: inline-block; +} + +range-slider .jsr { + margin: 0; +} + +range-slider .jsr_rail-outer { + padding: 0; +} + +range-slider .jsr_rail { + background: none; +} + +range-slider .jsr_label { + display: none; +} + +range-slider .jsr_slider:focus::before { + background: rgb(96, 181, 204); +} + +.activity { + position: absolute; + top: 40px; + right: 100px; +} + +.folder { margin-left: 30px; } +.folder > label { + background-color: #555; + margin: 6px 8px; + padding: 6px 8px; + display: inline-block; + cursor: pointer; +} + +.folder > label:hover { + background-color: #60b5cc; +} + +.folder.expanded label::before { + content: "▸"; + margin-right: 12px; +} + +.folder.collapsed label::before { + content: "▾"; + margin-right: 12px; +} + +.photo { + padding: 6px 8px; + margin-left: 30px; + cursor: pointer; + color: white; + display: block; + text-decoration: none; +} + +.photo:hover { + background-color: #60b5cc; +} + +.folders, .selected-photo { + float: left; + min-height: 400px; + width: 360px; +} + +.selected-photo h3 { + margin-top: 60px; + margin-bottom: 20px; + color: #60b5cc; +} + +.selected-photo img { + display: block; +} + +.selected-photo { + width: 600px; +} + +.content::after { + content: ""; + display: table; + clear: both; +} + +.related-photos { + clear: both; +} + +.related-photo { + float: left; +} + +.related-photo:hover { + float: left; + border-color: #60b5cc; +} + +.related-photo { + cursor: pointer; +} + +nav ul { + list-style: none; + display: inline-block; +} + +nav li, nav h1 { + display: inline-block; +} + +nav a { + text-decoration: none; + padding: 5px 15px; + color: white; + font-weight: bold; +} + +nav .active { + text-decoration: underline; +} + +nav a:hover { + text-decoration: underline; +} + +footer { + color: #bbb; + margin: 20px; + margin-top: 60px; +}