3 Commits ca9cb34dd7 ... b463dcdf0f

Author SHA1 Message Date
  Toby Chui b463dcdf0f Updated zooming behavior on Photo app mobile 3 weeks ago
  Toby Chui 1206983980 Added system clock webapp 3 weeks ago
  Toby Chui f7987becc1 Renamed agi code to match filename style 3 weeks ago

+ 41 - 1
src/mod/agi/systemFunc.go → src/mod/agi/agi.system.go

@@ -6,6 +6,7 @@ import (
 	"log"
 	"os"
 	"path/filepath"
+	"strings"
 	"time"
 
 	"github.com/robertkrimen/otto"
@@ -236,8 +237,47 @@ func (g *Gateway) injectStandardLibs(vm *otto.Otto, scriptFile string, scriptSco
 			reply, _ := vm.ToValue(false)
 			return reply
 		}
+
+		//Parse the module config JSON to convert relative paths to absolute paths
+		var moduleConfig map[string]interface{}
+		err = json.Unmarshal([]byte(jsonModuleConfig), &moduleConfig)
+		if err != nil {
+			g.RaiseError(err)
+			reply, _ := vm.ToValue(false)
+			return reply
+		}
+
+		//Get the module directory from the script file path
+		//For example: ./web/Label Maker/init.agi -> Label Maker
+		if scriptFile != "" && scriptScope != "" {
+			moduleDir := static.GetScriptRoot(scriptFile, scriptScope)
+
+			//Convert relative paths to absolute paths for IconPath, StartDir, and LaunchFWDir
+			pathFields := []string{"IconPath", "StartDir", "LaunchFWDir", "LaunchEmb"}
+			for _, field := range pathFields {
+				if value, exists := moduleConfig[field]; exists {
+					if strValue, ok := value.(string); ok && strValue != "" {
+						//Check if the path is relative (doesn't start with module name)
+						if !filepath.IsAbs(strValue) && !strings.HasPrefix(strValue, moduleDir+"/") {
+							//Convert relative path to absolute path
+							moduleConfig[field] = filepath.ToSlash(filepath.Join(moduleDir, strValue))
+						}
+					}
+				}
+			}
+
+			//Re-encode the modified config
+			modifiedJSON, err := json.Marshal(moduleConfig)
+			if err != nil {
+				g.RaiseError(err)
+				reply, _ := vm.ToValue(false)
+				return reply
+			}
+			jsonModuleConfig = string(modifiedJSON)
+		}
+
 		//Try to decode it to a module Info
-		g.Option.ModuleRegisterParser(jsonModuleConfig)
+		err = g.Option.ModuleRegisterParser(jsonModuleConfig)
 		if err != nil {
 			g.RaiseError(err)
 			reply, _ := vm.ToValue(false)

+ 0 - 0
src/mod/agi/userFunc.go → src/mod/agi/agi.user.go


+ 0 - 0
src/mod/agi/websocket.go → src/mod/agi/agi.websocket.go


+ 2 - 0
src/mod/agi/moduleManager.go

@@ -52,6 +52,8 @@ func (g *Gateway) LoadAllFunctionalModules() {
 	g.ShareLibRegister()
 	g.IoTLibRegister()
 	g.AppdataLibRegister()
+	//g.AudioLibRegister() //work in progress
+	g.ZipLibRegister()
 
 	//Only register ffmpeg lib if host OS have ffmpeg installed
 	ffmpegExists, _ := apt.PackageExists("ffmpeg")

BIN
src/web/Clock/img/cat-dark.jpg


BIN
src/web/Clock/img/cat-dark.psd


BIN
src/web/Clock/img/cat.jpg


BIN
src/web/Clock/img/cat.psd


+ 1 - 0
src/web/Clock/img/dark-mode.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 -960 960 960" width="48px" fill="#000000"><path d="M480-120q-150 0-255-105T120-480q0-150 105-255t255-105q8 0 17 .5t23 1.5q-36 32-56 79t-20 99q0 90 63 153t153 63q52 0 99-18.5t79-51.5q1 12 1.5 19.5t.5 14.5q0 150-105 255T480-120Zm0-60q109 0 190-67.5T771-406q-25 11-53.67 16.5Q688.67-384 660-384q-114.69 0-195.34-80.66Q384-545.31 384-660q0-24 5-51.5t18-62.5q-98 27-162.5 109.5T180-480q0 125 87.5 212.5T480-180Zm-4-297Z"/></svg>

BIN
src/web/Clock/img/desktop_icon.png


BIN
src/web/Clock/img/desktop_icon.psd


+ 1 - 0
src/web/Clock/img/light-mode.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 -960 960 960" width="48px" fill="#F3f3f3"><path d="M480-340q58 0 99-41t41-99q0-58-41-99t-99-41q-58 0-99 41t-41 99q0 58 41 99t99 41Zm0 60q-83 0-141.5-58.5T280-480q0-83 58.5-141.5T480-680q83 0 141.5 58.5T680-480q0 83-58.5 141.5T480-280ZM200-450H40v-60h160v60Zm720 0H760v-60h160v60ZM450-760v-160h60v160h-60Zm0 720v-160h60v160h-60ZM262-658l-100-97 43-44 96 100-39 41Zm494 496-98-100 41-41 99 98-42 43Zm-99-537 98-99 44 42-99 98-43-41ZM162-205l99-98 42 42-98 99-43-43Zm318-275Z"/></svg>

BIN
src/web/Clock/img/module_icon.png


BIN
src/web/Clock/img/module_icon.psd


+ 252 - 0
src/web/Clock/index.html

@@ -0,0 +1,252 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Clock</title>
+    <link rel="stylesheet" href="../../script/semantic/semantic.min.css">
+    <style>
+        body {
+            margin: 0;
+            padding: 0;
+            height: 100vh;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+            transition: background-color 0.3s ease, color 0.3s ease;
+        }
+
+        body.light-mode {
+            background-color: #f5f5f5;
+            color: #333;
+        }
+
+        body.dark-mode {
+            background-color: #1a1a1a;
+            color: #ffffff;
+        }
+
+        .cat-background {
+            position: fixed;
+            top: 0;
+            left: 0;
+            width: 100%;
+            height: 100%;
+            background-image: url('./img/cat.jpg');
+            background-size: cover;
+            background-position: center;
+            background-repeat: no-repeat;
+            z-index: -1;
+            display: none;
+        }
+
+        .cat-background.active {
+            display: block;
+        }
+
+        .clock-container {
+            text-align: center;
+            padding: 40px;
+            background: rgba(255, 255, 255, 0.1);
+            backdrop-filter: blur(10px);
+            border-radius: 20px;
+            box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
+        }
+
+        body.dark-mode .clock-container {
+            background: rgba(0, 0, 0, 0.3);
+        }
+
+        .cat-background.active ~ * .clock-container,
+        .cat-background.active ~ .clock-container {
+            background: rgba(255, 255, 255, 0.5);
+        }
+
+        body.dark-mode .cat-background.active ~ * .clock-container,
+        body.dark-mode .cat-background.active ~ .clock-container {
+            background: rgba(0, 0, 0, 0.4);
+        }
+
+        .time {
+            font-size: 72px;
+            font-weight: 300;
+            letter-spacing: 2px;
+            margin: 0;
+            line-height: 1.2;
+        }
+
+        .date {
+            font-size: 24px;
+            font-weight: 400;
+            margin-top: 20px;
+            opacity: 0.8;
+        }
+
+        .toggle-container {
+            position: fixed;
+            padding: 20px;
+        }
+
+        .dark-mode-toggle {
+            top: 0;
+            left: 0;
+        }
+
+        .cat-mode-toggle {
+            bottom: 0;
+            left: 0;
+        }
+
+        .toggle-label {
+            display: flex;
+            align-items: center;
+            gap: 10px;
+            font-size: 14px;
+            cursor: pointer;
+        }
+
+        body.dark-mode .toggle-label {
+            color: #ffffff;
+        }
+
+        .cat-background.active ~ * .toggle-label,
+        .cat-background.active ~ .toggle-label {
+            text-shadow: 0 0 3px rgba(255, 255, 255, 0.8);
+        }
+
+        .mode-icon {
+            width: 24px;
+            height: 24px;
+            display: inline-block;
+        }
+    </style>
+    <script src="../script/jquery.min.js"></script>
+    <script src="../script/ao_module.js"></script>
+</head>
+<body class="light-mode">
+    <!-- Cat Background -->
+    <div class="cat-background" id="catBackground"></div>
+
+    <!-- Dark Mode Toggle -->
+    <div class="toggle-container dark-mode-toggle">
+        <div class="toggle-label">
+            <div class="ui toggle checkbox" id="darkModeToggle">
+                <input type="checkbox" name="darkMode">
+                <label><img src="./img/light-mode.svg" class="mode-icon" id="modeIcon" alt="Mode" style="margin-top: -0.3em;"></label>
+            </div>
+        </div>
+    </div>
+
+    <!-- Cat Mode Toggle -->
+    <div class="toggle-container cat-mode-toggle">
+        <div class="toggle-label">
+            <div class="ui toggle checkbox" id="catModeToggle">
+                <input type="checkbox" name="catMode">
+                <label>Cat Mode</label>
+            </div>
+        </div>
+    </div>
+
+    <!-- Clock Display -->
+    <div class="clock-container">
+        <div class="time" id="time">00:00:00 AM</div>
+        <div class="date" id="date">Loading...</div>
+    </div>
+
+    <script src="../../script/jquery.min.js"></script>
+    <script src="../../script/semantic/semantic.min.js"></script>
+    <script>
+        // Initialize Semantic UI checkboxes
+        $('.ui.checkbox').checkbox();
+
+        // Fix the window size
+        //ao_module_setFixedWindowSize();
+
+        // Update cat background based on dark mode
+        function updateCatBackground() {
+            const isDarkMode = document.body.classList.contains('dark-mode');
+            const catBg = $('#catBackground');
+            if (isDarkMode) {
+                catBg.css('background-image', 'url("./img/cat-dark.jpg")');
+            } else {
+                catBg.css('background-image', 'url("./img/cat.jpg")');
+            }
+        }
+
+        // Update clock function
+        function updateClock() {
+            const now = new Date();
+            
+            // Format time
+            let hours = now.getHours();
+            const minutes = String(now.getMinutes()).padStart(2, '0');
+            const seconds = String(now.getSeconds()).padStart(2, '0');
+            const ampm = hours >= 12 ? 'PM' : 'AM';
+            hours = hours % 12;
+            hours = hours ? hours : 12; // 0 should be 12
+            const hoursStr = String(hours).padStart(2, '0');
+            
+            document.getElementById('time').textContent = `${hoursStr}:${minutes}:${seconds} ${ampm}`;
+            
+            // Format date
+            const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
+            const dayOfWeek = days[now.getDay()];
+            const day = String(now.getDate()).padStart(2, '0');
+            const month = String(now.getMonth() + 1).padStart(2, '0');
+            const year = now.getFullYear();
+            
+            document.getElementById('date').textContent = `${dayOfWeek}, ${day}/${month}/${year}`;
+        }
+
+        // Dark mode toggle
+        $('#darkModeToggle').checkbox({
+            onChecked: function() {
+                document.body.classList.remove('light-mode');
+                document.body.classList.add('dark-mode');
+                $('#modeIcon').attr('src', './img/light-mode.svg');
+                updateCatBackground();
+                localStorage.setItem('darkMode', 'true');
+            },
+            onUnchecked: function() {
+                document.body.classList.remove('dark-mode');
+                document.body.classList.add('light-mode');
+                $('#modeIcon').attr('src', './img/dark-mode.svg');
+                updateCatBackground();
+                localStorage.setItem('darkMode', 'false');
+            }
+        });
+
+        // Cat mode toggle
+        $('#catModeToggle').checkbox({
+            onChecked: function() {
+                updateCatBackground();
+                $('#catBackground').addClass('active');
+                localStorage.setItem('catMode', 'true');
+            },
+            onUnchecked: function() {
+                $('#catBackground').removeClass('active');
+                localStorage.setItem('catMode', 'false');
+            }
+        });
+
+        // Load saved preferences
+        if (localStorage.getItem('darkMode') === 'true') {
+            $('#darkModeToggle').checkbox('check');
+            $('#modeIcon').attr('src', './img/light-mode.svg');
+        } else {
+            $('#modeIcon').attr('src', './img/dark-mode.svg');
+        }
+        
+        if (localStorage.getItem('catMode') === 'true') {
+            $('#catModeToggle').checkbox('check');
+            updateCatBackground();
+            $('#catBackground').addClass('active');
+        }
+
+        // Update clock immediately and then every second
+        updateClock();
+        setInterval(updateClock, 1000);
+    </script>
+</body>
+</html>

+ 22 - 0
src/web/Clock/init.agi

@@ -0,0 +1,22 @@
+/*
+	Clock Module Register Script
+*/
+
+//Setup the module information
+var moduleLaunchInfo = {
+    Name: "Clock",
+	Desc: "A date and time telling tool",
+	Group: "Utilities",
+	IconPath: "img/module_icon.png",
+	Version: "0.1.0",
+	StartDir: "index.html",
+	SupportFW: true,
+	LaunchFWDir: "index.html",
+	SupportEmb: false,
+	InitFWSize: [600, 400],
+	SupportedExt: []
+}
+
+//Register the module
+console.log("Registering clock module");
+registerModule(JSON.stringify(moduleLaunchInfo));

+ 48 - 221
src/web/Photo/index.html

@@ -3,7 +3,7 @@
 
 <head>
     <meta charset="utf-8" />
-    <meta name="viewport" content="width=device-width,initial-scale=1" />
+    <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=yes" />
     <meta name="theme-color" content="#f76c5d" />
     <meta name="description" content="ArozOS Photo" />
     <link rel="manifest" crossorigin="use-credentials" href="manifest.json">
@@ -411,6 +411,16 @@
             .zoom-snackbar {
                 display: none !important;
             }
+            .zoom-controls {
+                display: none !important;
+            }
+            .viewer-left {
+                cursor: default;
+                touch-action: auto;
+            }
+            .viewer-left img {
+                cursor: default;
+            }
         }
 
         /* Loading Progress Indicator */
@@ -844,239 +854,56 @@
     function initZoomPan() {
         const img = document.getElementById('fullImage');
         const container = document.querySelector('.viewer-left');
+        const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
         
         // Reset zoom state
         resetZoom();
 
-        let handleMouseDown = function(e) {
-            if (zoomLevel > 1) {
-                e.preventDefault();
-                isDragging = true;
-                lastMouseX = e.clientX;
-                lastMouseY = e.clientY;
-                img.classList.add('dragging');
-            }
-        };
-
-        let handleMouseMove = function(e) {
-            if (isDragging && zoomLevel > 1) {
-                const deltaX = e.clientX - lastMouseX;
-                const deltaY = e.clientY - lastMouseY;
-                
-                panX += deltaX / zoomLevel;
-                panY += deltaY / zoomLevel;
-                
-                constrainPan();
-                updateImageTransform();
-                
-                lastMouseX = e.clientX;
-                lastMouseY = e.clientY;
-            }
-        };
-
-        let handleMouseUp = function() {
-            if (isDragging) {
-                isDragging = false;
-                img.classList.remove('dragging');
-            }
-        };
-
-        let handleTouchStart = function(e) {
-            if (e.touches.length === 1) {
-                // Single touch - prepare for pan
-                touchStartX = e.touches[0].clientX;
-                touchStartY = e.touches[0].clientY;
+        // Only enable custom zoom/pan on desktop
+        if (!isMobile) {
+            let handleMouseDown = function(e) {
                 if (zoomLevel > 1) {
+                    e.preventDefault();
                     isDragging = true;
+                    lastMouseX = e.clientX;
+                    lastMouseY = e.clientY;
                     img.classList.add('dragging');
                 }
-            } else if (e.touches.length === 2) {
-                // Two touches - prepare for pinch zoom
-                e.preventDefault();
-                const touch1 = e.touches[0];
-                const touch2 = e.touches[1];
-                touchStartDistance = Math.sqrt(
-                    Math.pow(touch2.clientX - touch1.clientX, 2) + 
-                    Math.pow(touch2.clientY - touch1.clientY, 2)
-                );
-                initialZoom = zoomLevel;
-                isDragging = false;
-            }
-        };
+            };
 
-        let handleTouchMove = function(e) {
-            e.preventDefault();
-            
-            if (e.touches.length === 1 && isDragging && zoomLevel > 1) {
-                // Single touch pan
-                const deltaX = e.touches[0].clientX - touchStartX;
-                const deltaY = e.touches[0].clientY - touchStartY;
-                
-                panX += deltaX / zoomLevel;
-                panY += deltaY / zoomLevel;
-                
-                constrainPan();
-                updateImageTransform();
-                
-                touchStartX = e.touches[0].clientX;
-                touchStartY = e.touches[0].clientY;
-            } else if (e.touches.length === 2) {
-                // Two touches pinch zoom
-                const touch1 = e.touches[0];
-                const touch2 = e.touches[1];
-                const currentDistance = Math.sqrt(
-                    Math.pow(touch2.clientX - touch1.clientX, 2) + 
-                    Math.pow(touch2.clientY - touch1.clientY, 2)
-                );
-                
-                if (touchStartDistance > 0) {
-                    const scale = currentDistance / touchStartDistance;
-                    const newZoom = Math.max(1, Math.min(5, initialZoom * scale));
+            let handleMouseMove = function(e) {
+                if (isDragging && zoomLevel > 1) {
+                    const deltaX = e.clientX - lastMouseX;
+                    const deltaY = e.clientY - lastMouseY;
+                    
+                    panX += deltaX / zoomLevel;
+                    panY += deltaY / zoomLevel;
+                    
+                    constrainPan();
+                    updateImageTransform();
                     
-                    if (newZoom !== zoomLevel) {
-                        // Zoom at center point between touches
-                        const centerX = (touch1.clientX + touch2.clientX) / 2;
-                        const centerY = (touch1.clientY + touch2.clientY) / 2;
-                        zoomAtPoint(newZoom, centerX, centerY);
-                    }
+                    lastMouseX = e.clientX;
+                    lastMouseY = e.clientY;
                 }
-            }
-        };
+            };
 
-        let handleTouchEnd = function(e) {
-            if (e.touches.length === 0) {
-                isDragging = false;
-                img.classList.remove('dragging');
-            }
-        };
-
-        // Remove existing listeners to prevent double triggering
-        img.removeEventListener('mousedown', handleMouseDown);
-        document.removeEventListener('mousemove', handleMouseMove);
-        document.removeEventListener('mouseup', handleMouseUp);
-        img.removeEventListener('touchstart', handleTouchStart);
-        img.removeEventListener('touchmove', handleTouchMove);
-        img.removeEventListener('touchend', handleTouchEnd);
-
-        // Add listeners back
-        img.addEventListener('mousedown', handleMouseDown);
-        document.addEventListener('mousemove', handleMouseMove);
-        document.addEventListener('mouseup', handleMouseUp);
-        img.addEventListener('touchstart', handleTouchStart);
-        img.addEventListener('touchmove', handleTouchMove);
-        img.addEventListener('touchend', handleTouchEnd);
-        
-        // Double-click zoom removed - use +/- buttons instead
-        
-        // Mouse wheel zoom removed - use +/- buttons instead
-        
-        // Mouse drag pan
-        img.addEventListener('mousedown', function(e) {
-            if (zoomLevel > 1) {
-                e.preventDefault();
-                isDragging = true;
-                lastMouseX = e.clientX;
-                lastMouseY = e.clientY;
-                img.classList.add('dragging');
-            }
-        });
-        
-        document.addEventListener('mousemove', function(e) {
-            if (isDragging && zoomLevel > 1) {
-                const deltaX = e.clientX - lastMouseX;
-                const deltaY = e.clientY - lastMouseY;
-                
-                panX += deltaX / zoomLevel;
-                panY += deltaY / zoomLevel;
-                
-                constrainPan();
-                updateImageTransform();
-                
-                lastMouseX = e.clientX;
-                lastMouseY = e.clientY;
-            }
-        });
-        
-        document.addEventListener('mouseup', function() {
-            if (isDragging) {
-                isDragging = false;
-                img.classList.remove('dragging');
-            }
-        });
-        
-        // Touch events for mobile
-        let touchStartX = 0;
-        let touchStartY = 0;
-        let touchStartDistance = 0;
-        
-        img.addEventListener('touchstart', function(e) {
-            if (e.touches.length === 1) {
-                // Single touch - prepare for pan
-                touchStartX = e.touches[0].clientX;
-                touchStartY = e.touches[0].clientY;
-                if (zoomLevel > 1) {
-                    isDragging = true;
-                    img.classList.add('dragging');
+            let handleMouseUp = function() {
+                if (isDragging) {
+                    isDragging = false;
+                    img.classList.remove('dragging');
                 }
-            } else if (e.touches.length === 2) {
-                // Two touches - prepare for pinch zoom
-                e.preventDefault();
-                const touch1 = e.touches[0];
-                const touch2 = e.touches[1];
-                touchStartDistance = Math.sqrt(
-                    Math.pow(touch2.clientX - touch1.clientX, 2) + 
-                    Math.pow(touch2.clientY - touch1.clientY, 2)
-                );
-                initialZoom = zoomLevel;
-                isDragging = false;
-            }
-        });
-        
-        img.addEventListener('touchmove', function(e) {
-            e.preventDefault();
-            
-            if (e.touches.length === 1 && isDragging && zoomLevel > 1) {
-                // Single touch pan
-                const deltaX = e.touches[0].clientX - touchStartX;
-                const deltaY = e.touches[0].clientY - touchStartY;
-                
-                panX += deltaX / zoomLevel;
-                panY += deltaY / zoomLevel;
-                
-                constrainPan();
-                updateImageTransform();
-                
-                touchStartX = e.touches[0].clientX;
-                touchStartY = e.touches[0].clientY;
-            } else if (e.touches.length === 2) {
-                // Two touches pinch zoom
-                const touch1 = e.touches[0];
-                const touch2 = e.touches[1];
-                const currentDistance = Math.sqrt(
-                    Math.pow(touch2.clientX - touch1.clientX, 2) + 
-                    Math.pow(touch2.clientY - touch1.clientY, 2)
-                );
-                
-                if (touchStartDistance > 0) {
-                    const scale = currentDistance / touchStartDistance;
-                    const newZoom = Math.max(1, Math.min(5, initialZoom * scale));
-                    
-                    if (newZoom !== zoomLevel) {
-                        // Zoom at center point between touches
-                        const centerX = (touch1.clientX + touch2.clientX) / 2;
-                        const centerY = (touch1.clientY + touch2.clientY) / 2;
-                        zoomAtPoint(newZoom, centerX, centerY);
-                    }
-                }
-            }
-        });
-        
-        img.addEventListener('touchend', function(e) {
-            if (e.touches.length === 0) {
-                isDragging = false;
-                img.classList.remove('dragging');
-            }
-        });
+            };
+
+            // Remove existing listeners to prevent double triggering
+            img.removeEventListener('mousedown', handleMouseDown);
+            document.removeEventListener('mousemove', handleMouseMove);
+            document.removeEventListener('mouseup', handleMouseUp);
+
+            // Add listeners back
+            img.addEventListener('mousedown', handleMouseDown);
+            document.addEventListener('mousemove', handleMouseMove);
+            document.addEventListener('mouseup', handleMouseUp);
+        }
     }
 
     // Initialize zoom and pan when modal is shown

+ 4 - 4
src/web/Photo/init.agi

@@ -7,13 +7,13 @@ var moduleLaunchInfo = {
     Name: "Photo",
 	Desc: "The worst photo webapp",
 	Group: "Media",
-	IconPath: "Photo/img/module_icon.png",
+	IconPath: "img/module_icon.png",
 	Version: "0.0.1",
-	StartDir: "Photo/index.html",
+	StartDir: "index.html",
 	SupportFW: true,
-	LaunchFWDir: "Photo/index.html",
+	LaunchFWDir: "index.html",
 	SupportEmb: true,
-	LaunchEmb: "Photo/embedded.html",
+	LaunchEmb: "embedded.html",
 	InitFWSize: [900, 550],
 	InitEmbSize: [900, 500],
 	SupportedExt: [".jpg",".jpeg",".gif",".png",".webp", ".arw", ".cr2", ".dng", ".nef", ".raf", ".orf"]

+ 1 - 0
src/web/Photo/photo.js

@@ -10,6 +10,7 @@ let photoList = [];
 let prePhoto = "";
 let nextPhoto = "";
 let currentModel = "";
+let isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
 
 // Check if image should use compression (only JPG/PNG)
 function shouldUseCompression(filepath, filesize) {