Browse Source

Updated embedded photo module with wip zoom func

Toby Chui 3 years ago
parent
commit
5c37576ec8
44 changed files with 904 additions and 19 deletions
  1. 1 0
      documents/distribution policy
  2. BIN
      documents/distribution policy.png
  3. 25 0
      legacy/Photo/asset-manifest.json
  4. 22 0
      legacy/Photo/backend/config.js
  5. 60 0
      legacy/Photo/backend/listFile.js
  6. 33 0
      legacy/Photo/backend/listFolder.js
  7. 2 0
      legacy/Photo/backend/search.js
  8. 195 0
      legacy/Photo/embedded.html
  9. 27 0
      legacy/Photo/embedded/arrow-left.ai
  10. 8 0
      legacy/Photo/embedded/arrow-left.svg
  11. 27 0
      legacy/Photo/embedded/arrow-right.ai
  12. 8 0
      legacy/Photo/embedded/arrow-right.svg
  13. 34 0
      legacy/Photo/embedded/listNearbyImage.js
  14. BIN
      legacy/Photo/favicon.ico
  15. BIN
      legacy/Photo/img/desktop_icon.png
  16. BIN
      legacy/Photo/img/module_icon.png
  17. BIN
      legacy/Photo/img/pwa/128.png
  18. BIN
      legacy/Photo/img/pwa/192.png
  19. BIN
      legacy/Photo/img/pwa/256.png
  20. BIN
      legacy/Photo/img/pwa/512.png
  21. 114 0
      legacy/Photo/index.html
  22. 23 0
      legacy/Photo/init.agi
  23. BIN
      legacy/Photo/logo192.png
  24. BIN
      legacy/Photo/logo512.png
  25. 25 0
      legacy/Photo/manifest.json
  26. 30 0
      legacy/Photo/precache-manifest.d3a7041c695a5d6712b5464105f686a9.js
  27. 3 0
      legacy/Photo/robots.txt
  28. 39 0
      legacy/Photo/service-worker.js
  29. 2 0
      legacy/Photo/static/css/2.c301f1a7.chunk.css
  30. 0 0
      legacy/Photo/static/css/2.c301f1a7.chunk.css.map
  31. 2 0
      legacy/Photo/static/css/main.5ecd60fb.chunk.css
  32. 1 0
      legacy/Photo/static/css/main.5ecd60fb.chunk.css.map
  33. 1 0
      legacy/Photo/static/js/2.09744fc4.chunk.js
  34. 70 0
      legacy/Photo/static/js/2.09744fc4.chunk.js.LICENSE.txt
  35. 0 0
      legacy/Photo/static/js/2.09744fc4.chunk.js.map
  36. 0 0
      legacy/Photo/static/js/main.dba51531.chunk.js
  37. 0 0
      legacy/Photo/static/js/main.dba51531.chunk.js.map
  38. 2 0
      legacy/Photo/static/js/runtime-main.f6bee5bd.js
  39. 0 0
      legacy/Photo/static/js/runtime-main.f6bee5bd.js.map
  40. 146 17
      web/Photo/embedded.html
  41. 1 0
      web/Photo/embedded/zoom-in.svg
  42. 1 0
      web/Photo/embedded/zoom-out.svg
  43. 2 2
      web/SystemAO/updates/index.html
  44. 0 0
      web/script/alpine.min.js

+ 1 - 0
documents/distribution policy

@@ -0,0 +1 @@
+<mxfile host="Electron" modified="2022-02-06T06:51:54.360Z" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/12.4.2 Chrome/78.0.3904.130 Electron/7.1.4 Safari/537.36" etag="JK7aocsvij5jBY_Q6S9h" version="12.4.2" type="device" pages="1"><diagram id="a14dWgHCCI1vJhH2N-CP" name="Page-1">5Vpdc9o4FP01zKQPyWAbyc5jAknbnW2bnTyk6cuOQNdYjW15ZJmP/PqVLGFj7FDaEigbGIR1LMnSPfdcfUDPGyaL94Jk0SdOIe65fbroeaOe6/qDS5VqYGkAhLABpoJRAzk1cM+ewYJ9ixaMQt4oKDmPJcua4ISnKUxkAyNC8HmzWMjj5lMzMoUWcD8hcRt9YFRGBg1cv8Y/AJtGqyc72A44IavCdiR5RCifr0HeTc8bCs6luUoWQ4i17VZ2MfVuX7hbdUxAKnepEAf/TOZ3D+f/wvnj+e031/30NT0f2L7J5WrAQNX4bZYLGfEpT0l8U6PXghcpBd1qX+XqMn9zninQUeB3kHJpySSF5AqKZBLbu6rDYvlV179Aq+yjba7MjBaN3NLmTF91B180gYVyXogJbBn3ypWImILcUs6riFIODjwB1R9VT0BMJJs1+0Gsq02rcjUb6sIS8hPk2HZnJC7sk0Zc5T+qTwqKAC0FlfAM0nrMyvN0D68Ef/5yXwojY1pAty2max41KfOISbjPSGm2udJyk7OQxfGQx1yUdb0Q6bfCcyn4E6zdweVL1+CpXMPNq2JxBkLCYjuPbbvbCp5vNWWDShUt5rVEHWyxaE2eqP9aVPVb5j2AkPYoCHdHQQRHFYRzDCv/AeFqV3Yuj8mO2wpXH8hMB6QlL3RY4pSFujdMdkajiCfjIv/5SBSG7mTSFYkoHmOE9xNxBqgZcVBXxLnsiDj41SKO+0a14O2oBXzUSOWd+Hywq5X9o1oZvxEro2Na2WvHdbWPUVs6XsV2ylT0ZeNCwonGdw85F6gR4b1+V4T3DxnhgxP3brSjdztHDSKo5d5XuX6O+jzAWKX3IGas3FmdfUljluqrItcpT2P1/KHej6ld/JoMWDpV2XdtEfzGlosSCMJOIeBJAONwP0JwNrZWgy4ZDA66tXqrZxR4R/m4v6mesuqVEGS5ViDjLJX5Wst3Gnh5QTzwN06fNsqjAdpWXl2YHtR+Ug3l110Ht6RtFD3i8zTmhJJxXMo6K4euO+P2QwGwX+GCQxH4XcK9xL5H9jWDBf7GDNYpXRcdUrrojUrX/5Oli4MTkK7fku5dtMzZhOiao2qe5frk8+yjTiEZA6XlsWhEBJ0r2szcPBzpqVroREagvxOgjOSnqHLc32F6PujJZ9Ai6hFyY3izN9h2VK1KlHzooyFWFlPWyQ2rPOzVx9j7XEchCOigi6jAHXt4XwdGuCkaPNiRqFfbTly2iPrMLxTwV5FrsT8BZJqmSPOiVrlPK84MUlFGUrpWbAJpuRKeMzWoFWx/ctgnacf9vQH7+MJ3fswnOugBYDtEfuZGeCoyVvJLDL0CMsFpUVK4Sd5ZWJSPUwaS70wLP3QDltbyzZe5hER3heXMrqnKOqRsVqOSi/+TQ1TK3eIN7kHV7XTJu2VxzXDTrCRm01RdK1+Qam70rrVd9DR7ZW8kjFKzLoOcPZfsmuWSXWaodtF1D420YVVzajWWm4WZ82raQ27b2l6Hsd3XMvaq4c1J7/StjQbBxi4CBW1jd+3/f8HYKlv//cEsHOv/kHg3/wE=</diagram></mxfile>

BIN
documents/distribution policy.png


+ 25 - 0
legacy/Photo/asset-manifest.json

@@ -0,0 +1,25 @@
+{
+  "files": {
+    "main.css": "/Photo/static/css/main.5ecd60fb.chunk.css",
+    "main.js": "/Photo/static/js/main.dba51531.chunk.js",
+    "main.js.map": "/Photo/static/js/main.dba51531.chunk.js.map",
+    "runtime-main.js": "/Photo/static/js/runtime-main.f6bee5bd.js",
+    "runtime-main.js.map": "/Photo/static/js/runtime-main.f6bee5bd.js.map",
+    "static/css/2.c301f1a7.chunk.css": "/Photo/static/css/2.c301f1a7.chunk.css",
+    "static/js/2.09744fc4.chunk.js": "/Photo/static/js/2.09744fc4.chunk.js",
+    "static/js/2.09744fc4.chunk.js.map": "/Photo/static/js/2.09744fc4.chunk.js.map",
+    "index.html": "/Photo/index.html",
+    "precache-manifest.d3a7041c695a5d6712b5464105f686a9.js": "/Photo/precache-manifest.d3a7041c695a5d6712b5464105f686a9.js",
+    "service-worker.js": "/Photo/service-worker.js",
+    "static/css/2.c301f1a7.chunk.css.map": "/Photo/static/css/2.c301f1a7.chunk.css.map",
+    "static/css/main.5ecd60fb.chunk.css.map": "/Photo/static/css/main.5ecd60fb.chunk.css.map",
+    "static/js/2.09744fc4.chunk.js.LICENSE.txt": "/Photo/static/js/2.09744fc4.chunk.js.LICENSE.txt"
+  },
+  "entrypoints": [
+    "static/js/runtime-main.f6bee5bd.js",
+    "static/css/2.c301f1a7.chunk.css",
+    "static/js/2.09744fc4.chunk.js",
+    "static/css/main.5ecd60fb.chunk.css",
+    "static/js/main.dba51531.chunk.js"
+  ]
+}

+ 22 - 0
legacy/Photo/backend/config.js

@@ -0,0 +1,22 @@
+var results = {};
+results["username"] = USERNAME;
+results["usericon"] = USERICON;
+results["unlimited"] = false;
+
+if (USERQUOTA_TOTAL == -1) {
+    results["unlimited"] = true;
+    results["quota"] = 0;
+    results["quota_human"] = bytesToSize(USERQUOTA_USED);
+} else {
+    results["quota"] = USERQUOTA_USED / USERQUOTA_TOTAL * 100;
+}
+sendJSONResp(JSON.stringify(results));
+
+//From stackoverflow.com
+//https://stackoverflow.com/questions/15900485/correct-way-to-convert-size-in-bytes-to-kb-mb-gb-in-javascript
+function bytesToSize(bytes) {
+    var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
+    if (bytes == 0) return '0 Byte';
+    var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
+    return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
+}

+ 60 - 0
legacy/Photo/backend/listFile.js

@@ -0,0 +1,60 @@
+/* 
+What to implemetenation
+-thumbnail
+-search
+*/
+//Help function for converting byte to human readable format
+function bytesToSize(bytes) {
+    var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
+    if (bytes == 0) return '0 Byte';
+    var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
+    return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
+}
+
+var loadedImage = requirelib("imagelib");
+if (!loadedImage) {
+    console.log("Failed to load lib imagelib, terminated.");
+}
+
+var loadedfile = requirelib("filelib");
+if (!loadedfile) {
+    console.log("Failed to load lib filelib, terminated.");
+}
+
+//Get all the files filesize on desktop
+//folder = "user:/Photo/Photo/uploads/"
+var folder = JSON.parse(POST_data)["folder"];
+var fileList = filelib.glob(folder + "*.*");
+var results = [];
+for (var i = 0; i < fileList.length; i++) {
+    if (!filelib.isDir(fileList[i])) { //Well I don't had isFile, then use !isDir have same effect.
+        var subFilename = fileList[i].split(".").pop().toLowerCase();
+        if (["jpg", "jpeg", "gif", "png"].indexOf(subFilename) >= 0) {
+            //imagelib.resizeImage(src, dest, width, height)
+            var filename = fileList[i].split("/").pop();
+            var fileSize = filelib.filesize(fileList[i]);
+            var dimension = imagelib.getImageDimension(folder + filename);
+            filelib.mkdir(folder + "thumbnails/");
+            var thumbnailsPath = folder + "thumbnails/" + filename;
+
+            if (!filelib.fileExists(thumbnailsPath)) {
+                var success = imagelib.resizeImage(fileList[i], thumbnailsPath, 200, 0);
+                if (success) {} else {
+                    sendResp("Failed to resize image");
+                }
+            }
+
+
+            results.push({
+                vsrc: folder + filename,
+                src: "/media/?file=" + folder + filename,
+                caption: filename,
+                Size: bytesToSize(fileSize),
+                thumbnail: "/media/?file=" + thumbnailsPath,
+                thumbnailHeight: dimension[1],
+                thumbnailWidth: dimension[0]
+            });
+        }
+    }
+}
+sendJSONResp(JSON.stringify(results));

+ 33 - 0
legacy/Photo/backend/listFolder.js

@@ -0,0 +1,33 @@
+var loadedfile = requirelib("filelib");
+if (!loadedfile) {
+    console.log("Failed to load lib filelib, terminated.");
+}
+
+var folderList = filelib.glob("user:/Photo/*");
+var arr = [];
+//add main folder
+var img = ChooseFirstImage("user:/Photo/");
+arr.push({ VPath: "user:/Photo/", Foldername: "Root folder", img: img })
+
+for (var i = 0; i < folderList.length; i++) {
+    var fldname = folderList[i].split("/")
+    if (filelib.isDir(folderList[i]) && folderList[i] != "user:/Photo/thumbnails" && fldname[fldname.length - 1].substring(0, 1) != ".") {
+        var img = ChooseFirstImage(folderList[i]);
+        arr.push({ VPath: folderList[i] + "/", Foldername: folderList[i].split("/").pop(), img: img })
+    }
+}
+
+function ChooseFirstImage(folder) {
+    var fileList = filelib.glob(folder + "/*.*");
+    for (var i = 0; i < fileList.length; i++) {
+        if (!filelib.isDir(fileList[i])) { //Well I don't had isFile, then use !isDir have same effect.
+            var subFilename = fileList[i].split(".").pop().toLowerCase();
+            if (["jpg", "jpeg", "gif", "png"].indexOf(subFilename) >= 0) {
+                return "/media/?file=" + fileList[i];
+            }
+        }
+    }
+    return "/Photo/img/desktop_icon.png";
+}
+
+sendJSONResp(JSON.stringify(arr))

+ 2 - 0
legacy/Photo/backend/search.js

@@ -0,0 +1,2 @@
+var results = [{ "name": "File: " + q, "value": "file:" + q }];
+sendJSONResp(JSON.stringify(results));

+ 195 - 0
legacy/Photo/embedded.html

@@ -0,0 +1,195 @@
+<!DOCTYPE html>
+<meta name="apple-mobile-web-app-capable" content="yes" />
+<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1" />
+<html>
+<head>
+    <meta charset="UTF-8">
+    <meta name="theme-color" content="#4b75ff">
+    <title>Photo Viewer</title>
+    <script src="../script/jquery.min.js"></script>
+    <script src="../script/ao_module.js"></script>
+    <link rel="manifest" href="manifest.json">
+    <style>
+        body{
+            margin: 0px !important;
+            background:rgba(34,34,34,1);
+            overflow: hidden;
+        }
+        .arrow{
+            width: 2em;
+            opacity: 0.5;
+            position: fixed;
+            top: calc(50% - 1em);
+            cursor: pointer;
+        }
+
+        .left.arrow{
+            left: 2em;
+        }
+
+        .right.arrow{
+            right: 2em;
+        }
+    </style>
+</head>
+<body>
+    <img id="img" style="max-height: 100vh;max-width: 100%;">
+    <img class="left arrow" onclick="previousImage();" src="embedded/arrow-left.svg">
+    <img class="right arrow" onclick="nextImage();" src="embedded/arrow-right.svg">
+    <script>
+        //Get file playback info from hash
+        var playbackFile = ao_module_loadInputFiles();
+        var nearbyFileList = [];
+        var currentViewingIndex = 0;
+        //Only handle one file
+        playbackFile = playbackFile[0];
+        loadImage(playbackFile.filename, playbackFile.filepath);
+        
+        $(window).on("resize ", function() {
+            updateImgSize();
+        });
+
+        //Load the nearby image files and allow swapping using <- and -> key
+        function loadNearbyFiles(filepath){
+            ao_module_agirun("Photo/embedded/listNearbyImage.js", {
+                path: filepath
+            }, function(data){
+                if (data.error != undefined){
+                    alert(data.error);
+                }else{
+                    nearbyFileList = data;
+
+                    //Track which index currently the user is viewing
+                    for (var i = 0; i < nearbyFileList.length; i++){
+                        var thisPath = nearbyFileList[i];
+                        if (thisPath == filepath.split("\\").join("/")){
+                            currentViewingIndex = i;
+                        }
+                    }
+                }
+            })
+        }
+
+        function nextImage(){
+            nextPhoto = currentViewingIndex + 1;
+            if (nextPhoto > nearbyFileList.length - 1){
+                nextPhoto = nearbyFileList.length - 1;
+            }
+
+            var filepath = nearbyFileList[nextPhoto];
+            var filename = filepath.split('/').pop();
+            if (nextPhoto != currentViewingIndex){
+                //Change in photo index
+                loadImage(filename, filepath);
+                 currentViewingIndex = nextPhoto;
+            }
+        }
+
+        function previousImage(){
+            nextPhoto = currentViewingIndex - 1;
+            if (nextPhoto < 0){
+                nextPhoto = 0;
+            }
+
+            var filepath = nearbyFileList[nextPhoto];
+            var filename = filepath.split('/').pop();
+            if (nextPhoto != currentViewingIndex){
+                //Change in photo index
+                loadImage(filename, filepath);
+                 currentViewingIndex = nextPhoto;
+            }
+        }
+
+        //Bind arrow key events
+        $("body").on("keydown", function(e){
+            var nextPhoto = currentViewingIndex;
+            if (e.keyCode == 37){
+                //<-
+                previousImage();
+            }else if (e.keyCode == 39){
+                //->
+                nextImage();
+            }else{
+                //Invalid keycode to operate
+                return;
+            }
+        })
+
+        loadNearbyFiles(playbackFile.filepath);
+
+        function loadImage(filename, filepath){
+            $("#img").hide();
+            ao_module_setWindowTitle("Photo - " + filename);
+            $("#img").attr("src", '../media?file=' + encodeURIComponent(filepath))
+            
+            //realigin to center
+            $('#img').on('load', function() {
+                updateImgSize();
+                $("#img").show();
+            });
+        }
+
+        function updateImgSize() {
+            $('#img').css("margin-top", (window.innerHeight - $("#img").height()) / 2);
+            $('#img').css("margin-left", (window.innerWidth - $("#img").width()) / 2);
+        }
+
+        //Touch gesture detections
+        document.addEventListener('touchstart', handleTouchStart, false);        
+        document.addEventListener('touchmove', handleTouchMove, false);
+
+        var xDown = null;                                                        
+        var yDown = null;
+
+        function getTouches(evt) {
+        return evt.touches ||             // browser API
+                evt.originalEvent.touches; // jQuery
+        }                                                     
+                                                                                
+        function handleTouchStart(evt) {
+            const firstTouch = getTouches(evt)[0];                                      
+            xDown = firstTouch.clientX;
+            yDown = firstTouch.clientY;
+        };
+
+
+        function handleTouchMove(evt) {
+            if ( ! xDown || ! yDown ) {
+                return;
+            }
+
+            var xUp = evt.touches[0].clientX;                                    
+            var yUp = evt.touches[0].clientY;
+
+            var xDiff = xDown - xUp;
+            var yDiff = yDown - yUp;
+                                                                                
+            if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {/*most significant*/
+                if ( xDiff > 0 ) {
+                    /* right swipe */ 
+                    nextImage();
+                } else {
+                    /* left swipe */
+                    previousImage();
+                }                       
+            } else {
+                if ( yDiff > 0 ) {
+                    /* down swipe */ 
+                } else { 
+                    /* up swipe */
+                }                                                                 
+            }
+
+            /* reset values */
+            xDown = null;
+            yDown = null;                        
+        };
+
+        function isZoomed(){
+            return window.matchMedia('(max--moz-device-pixel-ratio:0.99), (min--moz-device-pixel-ratio:1.01)').matches;
+        }
+
+    </script>
+</body>
+
+</html>

File diff suppressed because it is too large
+ 27 - 0
legacy/Photo/embedded/arrow-left.ai


+ 8 - 0
legacy/Photo/embedded/arrow-left.svg

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="圖層_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="128px" height="128px" viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
+<polygon fill="#FFFFFF" stroke="#231815" stroke-width="3" stroke-miterlimit="10" points="105.518,113.641 20.981,64.833 
+	105.518,16.027 "/>
+</svg>

File diff suppressed because it is too large
+ 27 - 0
legacy/Photo/embedded/arrow-right.ai


+ 8 - 0
legacy/Photo/embedded/arrow-right.svg

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="圖層_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="128px" height="128px" viewBox="0 0 128 128" enable-background="new 0 0 128 128" xml:space="preserve">
+<polygon fill="#FFFFFF" stroke="#231815" stroke-width="3" stroke-miterlimit="10" points="20.981,16.026 105.518,64.833 
+	20.981,113.64 "/>
+</svg>

+ 34 - 0
legacy/Photo/embedded/listNearbyImage.js

@@ -0,0 +1,34 @@
+var loadedfile = requirelib("filelib");
+if (!loadedfile) {
+    console.log("Failed to load lib filelib, terminated.");
+}
+
+function listNearby(){
+    var result = [];
+    //Extract the path from the filepath
+    var dirpath = path.split("\\").join("/");
+    dirpath = dirpath.split("/");
+    dirpath.pop();
+    dirpath = dirpath.join("/");
+
+    //Get nearby files and filter out the one that is web supported photo format
+    var nearbyFiles = filelib.aglob(dirpath + "/*", "user")
+    for (var i = 0; i < nearbyFiles.length; i++){
+        var ext = nearbyFiles[i].split(".").pop();
+        ext = ext.toLowerCase();
+        if (ext == "png" || ext == "jpg" || ext == "jpeg" || ext == "gif" || ext == "webp"){
+            result.push(nearbyFiles[i]);
+        }
+    }
+
+    sendJSONResp(JSON.stringify(result))
+}
+
+
+if (typeof(path) == "undefined"){
+    sendJSONResp(JSON.stringify({
+        "error": "Invalid path given"
+    }));
+}else{
+    listNearby();
+}

BIN
legacy/Photo/favicon.ico


BIN
legacy/Photo/img/desktop_icon.png


BIN
legacy/Photo/img/module_icon.png


BIN
legacy/Photo/img/pwa/128.png


BIN
legacy/Photo/img/pwa/192.png


BIN
legacy/Photo/img/pwa/256.png


BIN
legacy/Photo/img/pwa/512.png


+ 114 - 0
legacy/Photo/index.html

@@ -0,0 +1,114 @@
+<!doctype html>
+<html lang="en">
+
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width,initial-scale=1" />
+    <meta name="theme-color" content="#000000" />
+    <meta name="description" content="Web site created using create-react-app" />
+    <link rel="apple-touch-icon" href="/Photo/logo192.png" />
+    <link rel="manifest" href="/Photo/manifest.json" />
+    <title>Photo</title>
+    <script src="../script/jquery.min.js"></script>
+    <style>
+        body {
+            background-color: #fff
+        }
+        
+        figcaption {
+            word-break: break-all;
+        }
+    </style>
+    <link href="/Photo/static/css/2.c301f1a7.chunk.css" rel="stylesheet">
+    <link href="/Photo/static/css/main.5ecd60fb.chunk.css" rel="stylesheet">
+    <script src="../script/ao_module.js"></script>
+</head>
+
+<body><noscript>You need to enable JavaScript to run this app.</noscript>
+    <div id="root"></div>
+    <script>
+        //Check if there are file dropped into this interface. If yes, redirect to embedded
+        var infile = ao_module_loadInputFiles();
+        if (infile != null) {
+            window.location.href = "embedded.html" + window.location.hash;
+        }
+
+        ! function(e) {
+            function t(t) {
+                for (var n, l, p = t[0], f = t[1], i = t[2], c = 0, s = []; c < p.length; c++) l = p[c], Object.prototype.hasOwnProperty.call(o, l) && o[l] && s.push(o[l][0]), o[l] = 0;
+                for (n in f) Object.prototype.hasOwnProperty.call(f, n) && (e[n] = f[n]);
+                for (a && a(t); s.length;) s.shift()();
+                return u.push.apply(u, i || []), r()
+            }
+
+            function r() {
+                for (var e, t = 0; t < u.length; t++) {
+                    for (var r = u[t], n = !0, p = 1; p < r.length; p++) {
+                        var f = r[p];
+                        0 !== o[f] && (n = !1)
+                    }
+                    n && (u.splice(t--, 1), e = l(l.s = r[0]))
+                }
+                return e
+            }
+            var n = {},
+                o = {
+                    1: 0
+                },
+                u = [];
+
+            function l(t) {
+                if (n[t]) return n[t].exports;
+                var r = n[t] = {
+                    i: t,
+                    l: !1,
+                    exports: {}
+                };
+                return e[t].call(r.exports, r, r.exports, l), r.l = !0, r.exports
+            }
+            l.m = e, l.c = n, l.d = function(e, t, r) {
+                l.o(e, t) || Object.defineProperty(e, t, {
+                    enumerable: !0,
+                    get: r
+                })
+            }, l.r = function(e) {
+                "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, {
+                    value: "Module"
+                }), Object.defineProperty(e, "__esModule", {
+                    value: !0
+                })
+            }, l.t = function(e, t) {
+                if (1 & t && (e = l(e)), 8 & t) return e;
+                if (4 & t && "object" == typeof e && e && e.__esModule) return e;
+                var r = Object.create(null);
+                if (l.r(r), Object.defineProperty(r, "default", {
+                        enumerable: !0,
+                        value: e
+                    }), 2 & t && "string" != typeof e)
+                    for (var n in e) l.d(r, n, function(t) {
+                        return e[t]
+                    }.bind(null, n));
+                return r
+            }, l.n = function(e) {
+                var t = e && e.__esModule ? function() {
+                    return e.default
+                } : function() {
+                    return e
+                };
+                return l.d(t, "a", t), t
+            }, l.o = function(e, t) {
+                return Object.prototype.hasOwnProperty.call(e, t)
+            }, l.p = "/Photo/";
+            var p = this.webpackJsonpphoto = this.webpackJsonpphoto || [],
+                f = p.push.bind(p);
+            p.push = t, p = p.slice();
+            for (var i = 0; i < p.length; i++) t(p[i]);
+            var a = f;
+            r()
+        }([])
+    </script>
+    <script src="/Photo/static/js/2.09744fc4.chunk.js"></script>
+    <script src="/Photo/static/js/main.dba51531.chunk.js"></script>
+</body>
+
+</html>

+ 23 - 0
legacy/Photo/init.agi

@@ -0,0 +1,23 @@
+/*
+	Photo Module Register Script
+*/
+
+//Setup the module information
+var moduleLaunchInfo = {
+    Name: "Photo",
+	Desc: "The worst photo webapp",
+	Group: "Media",
+	IconPath: "Photo/img/module_icon.png",
+	Version: "0.0.1",
+	StartDir: "Photo/index.html",
+	SupportFW: true,
+	LaunchFWDir: "Photo/index.html",
+	SupportEmb: true,
+	LaunchEmb: "Photo/embedded.html",
+	InitFWSize: [900, 550],
+	InitEmbSize: [900, 500],
+	SupportedExt: [".jpg",".jpeg",".gif",".png"]
+}
+
+//Register the module
+registerModule(JSON.stringify(moduleLaunchInfo));

BIN
legacy/Photo/logo192.png


BIN
legacy/Photo/logo512.png


+ 25 - 0
legacy/Photo/manifest.json

@@ -0,0 +1,25 @@
+{
+  "short_name": "React App",
+  "name": "Create React App Sample",
+  "icons": [
+    {
+      "src": "favicon.ico",
+      "sizes": "64x64 32x32 24x24 16x16",
+      "type": "image/x-icon"
+    },
+    {
+      "src": "logo192.png",
+      "type": "image/png",
+      "sizes": "192x192"
+    },
+    {
+      "src": "logo512.png",
+      "type": "image/png",
+      "sizes": "512x512"
+    }
+  ],
+  "start_url": ".",
+  "display": "standalone",
+  "theme_color": "#000000",
+  "background_color": "#ffffff"
+}

+ 30 - 0
legacy/Photo/precache-manifest.d3a7041c695a5d6712b5464105f686a9.js

@@ -0,0 +1,30 @@
+self.__precacheManifest = (self.__precacheManifest || []).concat([
+  {
+    "revision": "b66a4d418e754e81111a2d31d7d539b2",
+    "url": "/Photo/index.html"
+  },
+  {
+    "revision": "5fde3124becd4b35f85f",
+    "url": "/Photo/static/css/2.c301f1a7.chunk.css"
+  },
+  {
+    "revision": "138294f0aac0f2e76a14",
+    "url": "/Photo/static/css/main.5ecd60fb.chunk.css"
+  },
+  {
+    "revision": "5fde3124becd4b35f85f",
+    "url": "/Photo/static/js/2.09744fc4.chunk.js"
+  },
+  {
+    "revision": "8b282241ff9a902c33d4eaa13d8e6903",
+    "url": "/Photo/static/js/2.09744fc4.chunk.js.LICENSE.txt"
+  },
+  {
+    "revision": "138294f0aac0f2e76a14",
+    "url": "/Photo/static/js/main.dba51531.chunk.js"
+  },
+  {
+    "revision": "974649fc032a02fdbb8f",
+    "url": "/Photo/static/js/runtime-main.f6bee5bd.js"
+  }
+]);

+ 3 - 0
legacy/Photo/robots.txt

@@ -0,0 +1,3 @@
+# https://www.robotstxt.org/robotstxt.html
+User-agent: *
+Disallow:

+ 39 - 0
legacy/Photo/service-worker.js

@@ -0,0 +1,39 @@
+/**
+ * Welcome to your Workbox-powered service worker!
+ *
+ * You'll need to register this file in your web app and you should
+ * disable HTTP caching for this file too.
+ * See https://goo.gl/nhQhGp
+ *
+ * The rest of the code is auto-generated. Please don't update this file
+ * directly; instead, make changes to your Workbox build configuration
+ * and re-run your build process.
+ * See https://goo.gl/2aRDsh
+ */
+
+importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
+
+importScripts(
+  "/Photo/precache-manifest.d3a7041c695a5d6712b5464105f686a9.js"
+);
+
+self.addEventListener('message', (event) => {
+  if (event.data && event.data.type === 'SKIP_WAITING') {
+    self.skipWaiting();
+  }
+});
+
+workbox.core.clientsClaim();
+
+/**
+ * The workboxSW.precacheAndRoute() method efficiently caches and responds to
+ * requests for URLs in the manifest.
+ * See https://goo.gl/S9QRab
+ */
+self.__precacheManifest = [].concat(self.__precacheManifest || []);
+workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
+
+workbox.routing.registerNavigationRoute(workbox.precaching.getCacheKeyForURL("/Photo/index.html"), {
+  
+  blacklist: [/^\/_/,/\/[^/?]+\.[^/]+$/],
+});

+ 2 - 0
legacy/Photo/static/css/2.c301f1a7.chunk.css

@@ -0,0 +1,2 @@
+.dzu-dropzone{display:flex;flex-direction:column;align-items:center;width:100%;min-height:120px;overflow:scroll;margin:0 auto;position:relative;box-sizing:border-box;transition:all .15s linear;border:2px solid #d9d9d9;border-radius:4px}.dzu-dropzoneActive{background-color:#deebff;border-color:#2484ff}.dzu-dropzoneDisabled{opacity:.5}.dzu-dropzoneDisabled :hover{cursor:unset}.dzu-input{display:none}.dzu-inputLabel{position:absolute;top:0;bottom:0;left:0;right:0;font-size:20px}.dzu-inputLabel,.dzu-inputLabelWithFiles{display:flex;justify-content:center;align-items:center;font-family:"Helvetica",sans-serif;font-weight:600;color:#2484ff;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;cursor:pointer}.dzu-inputLabelWithFiles{align-self:flex-start;padding:0 14px;min-height:32px;background-color:#e6e6e6;border:none;border-radius:4px;font-size:14px;margin-top:20px;margin-left:3%}.dzu-previewContainer{padding:40px 3%;flex-direction:row;justify-content:space-between;position:relative;width:100%;min-height:60px;z-index:1;border-bottom:1px solid #ececec;box-sizing:border-box}.dzu-previewContainer,.dzu-previewStatusContainer{display:flex;align-items:center}.dzu-previewFileName{font-family:"Helvetica",sans-serif;font-size:14px;font-weight:400;color:#333}.dzu-previewImage{width:auto;max-height:40px;max-width:140px;border-radius:4px}.dzu-previewButton{background-size:14px 14px;background-position:50%;background-repeat:no-repeat;width:14px;height:14px;cursor:pointer;opacity:.9;margin:0 0 2px 10px}.dzu-submitButtonContainer{margin:24px 0;z-index:1}.dzu-submitButton{padding:0 14px;min-height:32px;background-color:#2484ff;border:none;border-radius:4px;font-family:"Helvetica",sans-serif;font-size:14px;font-weight:600;color:#fff;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;cursor:pointer}.dzu-submitButton:disabled{background-color:#e6e6e6;color:#333;cursor:unset}
+/*# sourceMappingURL=2.c301f1a7.chunk.css.map */

File diff suppressed because it is too large
+ 0 - 0
legacy/Photo/static/css/2.c301f1a7.chunk.css.map


+ 2 - 0
legacy/Photo/static/css/main.5ecd60fb.chunk.css

@@ -0,0 +1,2 @@
+body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","Roboto","Oxygen","Ubuntu","Cantarell","Fira Sans","Droid Sans","Helvetica Neue",sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}code{font-family:source-code-pro,Menlo,Monaco,Consolas,"Courier New",monospace}
+/*# sourceMappingURL=main.5ecd60fb.chunk.css.map */

+ 1 - 0
legacy/Photo/static/css/main.5ecd60fb.chunk.css.map

@@ -0,0 +1 @@
+{"version":3,"sources":["index.css"],"names":[],"mappings":"AAAA,KACE,QAAS,CACT,mJAEY,CACZ,kCAAmC,CACnC,iCACF,CAEA,KACE,yEAEF","file":"main.5ecd60fb.chunk.css","sourcesContent":["body {\n  margin: 0;\n  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',\n    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',\n    sans-serif;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n  font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',\n    monospace;\n}\n"]}

File diff suppressed because it is too large
+ 1 - 0
legacy/Photo/static/js/2.09744fc4.chunk.js


+ 70 - 0
legacy/Photo/static/js/2.09744fc4.chunk.js.LICENSE.txt

@@ -0,0 +1,70 @@
+/*
+  object-assign
+  (c) Sindre Sorhus
+  @license MIT
+  */
+
+/*
+object-assign
+(c) Sindre Sorhus
+@license MIT
+*/
+
+/*!
+  Copyright (c) 2015 Jed Watson.
+  Based on code that is Copyright 2013-2015, Facebook, Inc.
+  All rights reserved.
+*/
+
+/**
+ * A better abstraction over CSS.
+ *
+ * @copyright Oleg Isonen (Slobodskoi) / Isonen 2014-present
+ * @website https://github.com/cssinjs/jss
+ * @license MIT
+ */
+
+/** @license React v0.19.1
+ * scheduler.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+/** @license React v16.13.1
+ * react-dom.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+/** @license React v16.13.1
+ * react-is.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+/** @license React v16.13.1
+ * react.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+/** @license React v16.8.6
+   * react.production.min.js
+   *
+   * Copyright (c) Facebook, Inc. and its affiliates.
+   *
+   * This source code is licensed under the MIT license found in the
+   * LICENSE file in the root directory of this source tree.
+   */

File diff suppressed because it is too large
+ 0 - 0
legacy/Photo/static/js/2.09744fc4.chunk.js.map


File diff suppressed because it is too large
+ 0 - 0
legacy/Photo/static/js/main.dba51531.chunk.js


File diff suppressed because it is too large
+ 0 - 0
legacy/Photo/static/js/main.dba51531.chunk.js.map


+ 2 - 0
legacy/Photo/static/js/runtime-main.f6bee5bd.js

@@ -0,0 +1,2 @@
+!function(e){function t(t){for(var n,l,p=t[0],f=t[1],i=t[2],c=0,s=[];c<p.length;c++)l=p[c],Object.prototype.hasOwnProperty.call(o,l)&&o[l]&&s.push(o[l][0]),o[l]=0;for(n in f)Object.prototype.hasOwnProperty.call(f,n)&&(e[n]=f[n]);for(a&&a(t);s.length;)s.shift()();return u.push.apply(u,i||[]),r()}function r(){for(var e,t=0;t<u.length;t++){for(var r=u[t],n=!0,p=1;p<r.length;p++){var f=r[p];0!==o[f]&&(n=!1)}n&&(u.splice(t--,1),e=l(l.s=r[0]))}return e}var n={},o={1:0},u=[];function l(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,l),r.l=!0,r.exports}l.m=e,l.c=n,l.d=function(e,t,r){l.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},l.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},l.t=function(e,t){if(1&t&&(e=l(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(l.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)l.d(r,n,function(t){return e[t]}.bind(null,n));return r},l.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(t,"a",t),t},l.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},l.p="/Photo/";var p=this.webpackJsonpphoto=this.webpackJsonpphoto||[],f=p.push.bind(p);p.push=t,p=p.slice();for(var i=0;i<p.length;i++)t(p[i]);var a=f;r()}([]);
+//# sourceMappingURL=runtime-main.f6bee5bd.js.map

File diff suppressed because it is too large
+ 0 - 0
legacy/Photo/static/js/runtime-main.f6bee5bd.js.map


+ 146 - 17
web/Photo/embedded.html

@@ -30,17 +30,40 @@
         .right.arrow{
             right: 2em;
         }
+
+        .zoom{
+            width: 2em;
+            opacity: 0.5;
+            position: fixed;
+            bottom: 1em;
+            cursor: pointer;
+        }
+
+        .zoom.out{
+            right: 1em;
+        }
+
+        .zoom.in{
+            right: 3.2em;
+        }
+
+
     </style>
 </head>
 <body>
     <img id="img" style="max-height: 100vh;max-width: 100%;">
     <img class="left arrow" onclick="previousImage();" src="embedded/arrow-left.svg">
     <img class="right arrow" onclick="nextImage();" src="embedded/arrow-right.svg">
+    <img class="zoom in" onclick="zoomIn();" src="embedded/zoom-in.svg">
+    <img class="zoom out" onclick="zoomOut();" src="embedded/zoom-out.svg">
     <script>
         //Get file playback info from hash
         var playbackFile = ao_module_loadInputFiles();
         var nearbyFileList = [];
         var currentViewingIndex = 0;
+        var zoomLevel = 1;
+        var initMargin = [];
+
         //Only handle one file
         playbackFile = playbackFile[0];
         loadImage(playbackFile.filename, playbackFile.filepath);
@@ -49,6 +72,94 @@
             updateImgSize();
         });
 
+        /*
+            Zooming related functions
+        */
+
+        function zoomIn(){
+            zoomLevel+= 0.5;
+            applyZoom();
+        }
+
+        function zoomOut(){
+            zoomLevel-= 0.5;
+            applyZoom();
+        }
+
+        $(window).bind('mousewheel DOMMouseScroll', function(event){
+            if (event.originalEvent.wheelDelta > 0 || event.originalEvent.detail < 0) {
+                // scroll up
+                zoomIn();
+            }
+            else {
+                // scroll down
+                zoomOut();
+            }
+        });
+
+        function applyZoom(){
+            if (zoomLevel < 1){
+                zoomLevel = 1;
+            }
+
+            if (zoomLevel == 1){
+                //Reset offsets
+                updateImgSize();
+            }
+            $("#img").css("transform", `scale(${zoomLevel})`);
+        }
+
+        //Event binding for photo draging
+        var isDragging = false;
+        var initPositions = [];
+        $("#img").mousedown(function(evt) {
+            evt.preventDefault();
+            handleZoomMousedown(evt.clientX, evt.clientY);
+        });
+
+        $("#img").mousemove(function(evt) {
+            handleZoomMouseMove(evt.clientX, evt.clientY);
+        });
+
+        $("#img").mouseup(function() {
+            handleZoomMouseUp();
+        });
+
+        function getCurrentImageMargins(){
+            var accLeft = $("#img").css("margin-left").replace("px","");
+            var accTop = $("#img").css("margin-top").replace("px","");
+            return [parseFloat(accLeft), parseFloat(accTop)];
+        }
+
+        function handleZoomMousedown(x,y){
+            if (zoomLevel > 1){
+                //Only allow dragging when zoomlv > 1
+                isDragging = true;
+                var accLeft = $("#img").css("margin-left").replace("px","");
+                var accTop = $("#img").css("margin-top").replace("px","");
+                initPositions = [JSON.parse(JSON.stringify(x - accLeft)), JSON.parse(JSON.stringify(y - accTop))];
+            }
+        }
+
+        function handleZoomMouseMove(x,y){
+            if (isDragging){
+                console.log("dragging");
+                var offsetsToStartPoint = [initPositions[0] - x, initPositions[1] - y];
+                MoveImage(-offsetsToStartPoint[0], -offsetsToStartPoint[1]);
+            }
+        }
+
+        function MoveImage(x,y){
+            $("#img").css("margin-left",  x + "px");
+            $("#img").css("margin-top", y + "px");
+        }
+
+        function handleZoomMouseUp(){
+            isDragging = false;
+        }
+
+
+
         //Load the nearby image files and allow swapping using <- and -> key
         function loadNearbyFiles(filepath){
             ao_module_agirun("Photo/embedded/listNearbyImage.js", {
@@ -124,6 +235,8 @@
             
             //realigin to center
             $('#img').on('load', function() {
+                zoomLevel = 1;
+                applyZoom();
                 updateImgSize();
                 $("#img").show();
             });
@@ -132,6 +245,7 @@
         function updateImgSize() {
             $('#img').css("margin-top", (window.innerHeight - $("#img").height()) / 2);
             $('#img').css("margin-left", (window.innerWidth - $("#img").width()) / 2);
+            initMargin = [(window.innerWidth - $("#img").width()) / 2, (window.innerHeight - $("#img").height()) / 2];
         }
 
         //Touch gesture detections
@@ -145,7 +259,7 @@
         return evt.touches ||             // browser API
                 evt.originalEvent.touches; // jQuery
         }                                                     
-                                                                                
+        
         function handleTouchStart(evt) {
             const firstTouch = getTouches(evt)[0];                                      
             xDown = firstTouch.clientX;
@@ -161,28 +275,43 @@
             var xUp = evt.touches[0].clientX;                                    
             var yUp = evt.touches[0].clientY;
 
+            var imgmg = getCurrentImageMargins();
             var xDiff = xDown - xUp;
+            var xDiffAcc = xDiff - imgmg[0];
             var yDiff = yDown - yUp;
-                                                                                
-            if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {/*most significant*/
-                if ( xDiff > 0 ) {
-                    /* right swipe */ 
-                    nextImage();
+            var yDiffAcc = yDiff - imgmg[1];
+            
+            if (zoomLevel == 1){
+                if ( Math.abs( xDiff ) > Math.abs( yDiff ) ) {/*most significant*/
+                    if ( xDiff > 0 ) {
+                        /* right swipe */ 
+                        nextImage();
+                    } else {
+                        /* left swipe */
+                        previousImage();
+                    }                       
                 } else {
-                    /* left swipe */
-                    previousImage();
-                }                       
-            } else {
-                if ( yDiff > 0 ) {
-                    /* down swipe */ 
-                } else { 
-                    /* up swipe */
-                }                                                                 
+                    if ( yDiff > 0 ) {
+                        /* down swipe */ 
+                    } else { 
+                        /* up swipe */
+    
+                    }                                                                 
+                }
+            }else{
+                MoveImage(-xDiffAcc, -yDiffAcc);
             }
+            
 
             /* reset values */
-            xDown = null;
-            yDown = null;                        
+            if (zoomLevel == 1){
+                xDown = null;
+                yDown = null;
+            }else{
+                xDown = xUp;
+                yDown = yUp;
+            }
+                              
         };
 
         function isZoomed(){

+ 1 - 0
web/Photo/embedded/zoom-in.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 0 24 24" width="48px" fill="#FFFFFF"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14zm.5-7H9v2H7v1h2v2h1v-2h2V9h-2z"/></svg>

+ 1 - 0
web/Photo/embedded/zoom-out.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#FFFFFF"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14zM7 9h5v1H7z"/></svg>

+ 2 - 2
web/SystemAO/updates/index.html

@@ -336,7 +336,7 @@
             };
         }
 
-        function downloadUpdateFallbackMode(binaryDownloadURL, webpackDownloadURL) {
+        function downloadUpdateFallbackMode(binaryDownloadURL, webpackDownloadURL, checksumDownloadURL) {
             hideAllStatus();
             $("#downloading").slideDown("fast");
             $("#downloadStatusText").text("Waiting for Download Complete (Fallback Mode)");
@@ -344,7 +344,7 @@
             $("#downloadProgressBar").find(".progress").text("Downloading");
             $("#downloadProgressBar").css("width", "50%");
             $(".updateBtn").addClass("disabled");
-            $.get(`../../system/update/download?webpack=${webpackDownloadURL}&binary=${binaryDownloadURL}`, function(data) {
+            $.get(`../../system/update/download?webpack=${webpackDownloadURL}&binary=${binaryDownloadURL}&checksum=${checksumDownloadURL}`, function(data) {
                 if (data.error !== undefined) {
                     hideAllStatus();
                     $("#failed").slideDown();

File diff suppressed because it is too large
+ 0 - 0
web/script/alpine.min.js


Some files were not shown because too many files changed in this diff