From 9c27ec1694295de71354b677b78a9a70f0fb3756 Mon Sep 17 00:00:00 2001 From: stweedo Date: Fri, 16 Jun 2023 20:14:27 -0500 Subject: [PATCH] Update app for new menu, change screenshot --- apps/boxclk/app.js | 477 ++++++++++++++++++----------------- apps/boxclk/screenshot-1.png | Bin 5936 -> 6060 bytes apps/boxclk/settings.js | 37 ++- 3 files changed, 258 insertions(+), 256 deletions(-) diff --git a/apps/boxclk/app.js b/apps/boxclk/app.js index 9fbb9777a..1647bd731 100644 --- a/apps/boxclk/app.js +++ b/apps/boxclk/app.js @@ -1,239 +1,242 @@ { // 1. Module dependencies and initial configurations - let storage = require("Storage"); - let locale = require("locale"); - let date = new Date(); - let bgImage; - let boxesConfig = storage.readJSON('boxclk.json', 1) || {}; - let boxes = {}; - let boxPos = {}; - let isDragging = {}; - let wasDragging = {}; - - // 2. Graphical and visual configurations - let w = g.getWidth(); - let h = g.getHeight(); - let totalWidth, totalHeight; - let enableSuffix = true; - let drawTimeout; - - // 3. Handlers - let touchHandler; - let dragHandler; - - // 4. Font loading function - let loadCustomFont = function() { - Graphics.prototype.setFontBrunoAce = function() { - // Actual height 23 (24 - 2) - return this.setFontCustom( - E.toString(require('heatshrink').decompress(atob('ABMHwADBh4DKg4bKgIPDAYUfAYV/AYX/AQMD/gmC+ADBn/AByE/GIU8AYUwLxcfAYX/8AnB//4JIP/FgMP4F+CQQBBjwJBFYRbBAd43DHoJpBh/g/xPEK4ZfDgEEORKDDAY8////wADLfZrTCgITBnhEBAYJMBAYMPw4DCM4QDjhwDCjwDBn0+AYMf/gDBh/4AYMH+ADBLpc4ToK/NGYZfnAYcfL4U/x5fBW4LvB/7vC+LvBgHAsBfIn76Cn4WBcYQDFEgJ+CQQYDyH4L/BAZbHLNYjjCAZc8ngDunycBZ4KkBa4KwBnEHY4UB+BfMgf/ZgMH/4XBc4cf4F/gE+ZgRjwAYcfj5jBM4U4M4RQBM4UA8BjIngDFEYJ8BAYUDAYQvCM4ZxBC4V+AYQvBnkBQ4M8gabBJQPAI4WAAYM/GYQaBAYJKCnqyCn5OCn4aBAYIaBAYJPCU4IABnBhIuDXCFAMD+Z/BY4IDBQwOPwEfv6TDAYUPAcwrDAYQ7BAYY/BI4cD8bLCK4RfEAA0BRYTeDcwIrFn0Pw43Bg4DugYDBjxBBU4SvDMYMH/5QBgP/LAQAP8EHN4UPwADHB4YAHA'))), - 46, - atob("CBEdChgYGhgaGBsaCQ=="), - 32|65536 - ); - }; - }; - - // 5. Initial settings of boxes and their positions - for (let key in boxesConfig) { - if (key === 'bg' && boxesConfig[key].img) { - bgImage = storage.read(boxesConfig[key].img); - } else { - boxes[key] = Object.assign({}, boxesConfig[key]); - } - } - - Object.keys(boxes).forEach((boxKey) => { - let boxConfig = boxes[boxKey]; - boxPos[boxKey] = { - x: w * boxConfig.boxPos.x, - y: h * boxConfig.boxPos.y - }; - isDragging[boxKey] = false; - wasDragging[boxKey] = false; - }); - - // 6. Text and drawing functions - let g_drawString = g.drawString; - g.drawString = function(box, str, x, y) { - outlineText(box, str, x, y); - g.setColor(box.color); - g_drawString.call(g, str, x, y); - }; - - let outlineText = function(box, str, x, y) { - let px = box.outline; - let dx = [-px, 0, px, -px, px, -px, 0, px]; - let dy = [-px, -px, -px, 0, 0, px, px, px]; - g.setColor(box.outlineColor); - for (let i = 0; i < dx.length; i++) { - g_drawString.call(g, str, x + dx[i], y + dy[i]); - } - }; - - let calcBoxSize = function(boxItem) { - g.reset(); - g.setFontAlign(0,0); - g.setFont(boxItem.font, boxItem.fontSize); - let strWidth = g.stringWidth(boxItem.string) + 2 * boxItem.outline; - let fontHeight = g.getFontHeight() + 2 * boxItem.outline; - totalWidth = strWidth + 2 * boxItem.xPadding; - totalHeight = fontHeight + 2 * boxItem.yPadding; - }; - - let calcBoxPos = function(boxKey) { - return { - x1: boxPos[boxKey].x - totalWidth / 2, - y1: boxPos[boxKey].y - totalHeight / 2, - x2: boxPos[boxKey].x + totalWidth / 2, - y2: boxPos[boxKey].y + totalHeight / 2 - }; - }; - - // 7. Date and time related functions - let getDate = function() { - const date = new Date(); - const dayOfMonth = date.getDate(); - const month = locale.month(date, 1); - const year = date.getFullYear(); - let suffix; - if ([1, 21, 31].includes(dayOfMonth)) { - suffix = "st"; - } else if ([2, 22].includes(dayOfMonth)) { - suffix = "nd"; - } else if ([3, 23].includes(dayOfMonth)) { - suffix = "rd"; - } else { - suffix = "th"; - } - let dayOfMonthStr = enableSuffix ? dayOfMonth + suffix : dayOfMonth; - return month + " " + dayOfMonthStr + ", " + year; - }; - - let getDayOfWeek = function(date) { - return locale.dow(date, 0); - }; - - // 8. Main draw function - let draw = function(boxes) { - date = new Date(); - g.clear(); - if (bgImage) { - g.drawImage(bgImage, 0, 0); - } - if (boxes.time) { - boxes.time.string = locale.time(date, 1); - } - if (boxes.date) { - boxes.date.string = getDate(); - } - if (boxes.dow) { - boxes.dow.string = getDayOfWeek(date); - } - if (boxes.batt) { - boxes.batt.string = E.getBattery() + "%"; - } - Object.keys(boxes).forEach((boxKey) => { - let boxItem = boxes[boxKey]; - calcBoxSize(boxItem); - const pos = calcBoxPos(boxKey); - if (isDragging[boxKey]) { - g.setColor(boxItem.border); - g.drawRect(pos.x1, pos.y1, pos.x2, pos.y2); - } - g.drawString( - boxItem, - boxItem.string, - boxPos[boxKey].x + boxItem.xOffset, - boxPos[boxKey].y + boxItem.yOffset - ); - }); - if (!Object.values(isDragging).some(Boolean)) { - if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = setTimeout(() => draw(boxes), 60000 - (Date.now() % 60000)); - } - }; - - // 9. Helper function for touch event - let touchInText = function(e, boxItem, boxKey) { - calcBoxSize(boxItem); - const pos = calcBoxPos(boxKey); - return e.x >= pos.x1 && - e.x <= pos.x2 && - e.y >= pos.y1 && - e.y <= pos.y2; - }; - - // 10. Setup function to configure event handlers - let setup = function() { - // Define the touchHandler function - touchHandler = function(zone, e) { - wasDragging = Object.assign({}, isDragging); - let boxTouched = false; - Object.keys(boxes).forEach((boxKey) => { - if (touchInText(e, boxes[boxKey], boxKey)) { - isDragging[boxKey] = true; - wasDragging[boxKey] = true; - boxTouched = true; - } - }); - if (!boxTouched) { - Object.keys(isDragging).forEach((boxKey) => { - isDragging[boxKey] = false; - }); - require("widget_utils").show(); - require("widget_utils").swipeOn(); - } - if (Object.values(wasDragging).some(Boolean) || !boxTouched) { - draw(boxes); - } - }; - - // Define the dragHandler function - dragHandler = function(e) { - Object.keys(boxes).forEach((boxKey) => { - if (isDragging[boxKey]) { - require("widget_utils").hide(); - let boxItem = boxes[boxKey]; - calcBoxSize(boxItem); - let newX = boxPos[boxKey].x + e.dx; - let newY = boxPos[boxKey].y + e.dy; - if (newX - totalWidth / 2 >= 0 && - newX + totalWidth / 2 <= w && - newY - totalHeight / 2 >= 0 && - newY + totalHeight / 2 <= h ) { - boxPos[boxKey].x = newX; - boxPos[boxKey].y = newY; - } - const pos = calcBoxPos(boxKey); - g.clearRect(pos.x1, pos.y1, pos.x2, pos.y2); - } - }); - draw(boxes); - }; - - Bangle.on('touch', touchHandler); - Bangle.on('drag', dragHandler); - - Bangle.setUI({ - mode : "clock", - remove : function() { - // Remove event handlers, stop draw timer, remove custom font if used - Bangle.removeListener('touch', touchHandler); - Bangle.removeListener('drag', dragHandler); - if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = undefined; - delete Graphics.prototype.setFontBrunoAce; - g.drawString = g_drawString; // Return to original without outlines - require("widget_utils").show(); - } - }); - loadCustomFont(); - draw(boxes); - }; - - // 11. Main execution part - Bangle.loadWidgets(); - require("widget_utils").swipeOn(); - setup(); -} + let storage = require("Storage"); + let locale = require("locale"); + let date = new Date(); + let bgImage; + let configNumber = (storage.readJSON("boxclk.json", 1) || {}).selectedConfig || 0; + let fileName = 'boxclk' + (configNumber > 0 ? `-${configNumber}` : '') + '.json'; + let boxesConfig = storage.readJSON(fileName, 1) || {}; + let boxes = {}; + let boxPos = {}; + let isDragging = {}; + let wasDragging = {}; + + // 2. Graphical and visual configurations + let w = g.getWidth(); + let h = g.getHeight(); + let totalWidth, totalHeight; + let enableSuffix = true; + let drawTimeout; + + // 3. Handlers + let touchHandler; + let dragHandler; + + // 4. Font loading function + let loadCustomFont = function() { + Graphics.prototype.setFontBrunoAce = function() { + // Actual height 23 (24 - 2) + return this.setFontCustom( + E.toString(require('heatshrink').decompress(atob('ABMHwADBh4DKg4bKgIPDAYUfAYV/AYX/AQMD/gmC+ADBn/AByE/GIU8AYUwLxcfAYX/8AnB//4JIP/FgMP4F+CQQBBjwJBFYRbBAd43DHoJpBh/g/xPEK4ZfDgEEORKDDAY8////wADLfZrTCgITBnhEBAYJMBAYMPw4DCM4QDjhwDCjwDBn0+AYMf/gDBh/4AYMH+ADBLpc4ToK/NGYZfnAYcfL4U/x5fBW4LvB/7vC+LvBgHAsBfIn76Cn4WBcYQDFEgJ+CQQYDyH4L/BAZbHLNYjjCAZc8ngDunycBZ4KkBa4KwBnEHY4UB+BfMgf/ZgMH/4XBc4cf4F/gE+ZgRjwAYcfj5jBM4U4M4RQBM4UA8BjIngDFEYJ8BAYUDAYQvCM4ZxBC4V+AYQvBnkBQ4M8gabBJQPAI4WAAYM/GYQaBAYJKCnqyCn5OCn4aBAYIaBAYJPCU4IABnBhIuDXCFAMD+Z/BY4IDBQwOPwEfv6TDAYUPAcwrDAYQ7BAYY/BI4cD8bLCK4RfEAA0BRYTeDcwIrFn0Pw43Bg4DugYDBjxBBU4SvDMYMH/5QBgP/LAQAP8EHN4UPwADHB4YAHA'))), + 46, + atob("CBEdChgYGhgaGBsaCQ=="), + 32|65536 + ); + }; + }; + + // 5. Initial settings of boxes and their positions + for (let key in boxesConfig) { + if (key === 'bg' && boxesConfig[key].img) { + bgImage = storage.read(boxesConfig[key].img); + } else if (key !== 'selectedConfig') { + boxes[key] = Object.assign({}, boxesConfig[key]); + } + } + + Object.keys(boxes).forEach((key) => { + let boxConfig = boxes[key]; + boxPos[key] = { + x: w * boxConfig.boxPos.x, + y: h * boxConfig.boxPos.y + }; + isDragging[key] = false; + wasDragging[key] = false; + }); + + // 6. Text and drawing functions + let g_drawString = g.drawString; + g.drawString = function(box, str, x, y) { + outlineText(box, str, x, y); + g.setColor(box.color); + g_drawString.call(g, str, x, y); + }; + + let outlineText = function(box, str, x, y) { + let px = box.outline; + let dx = [-px, 0, px, -px, px, -px, 0, px]; + let dy = [-px, -px, -px, 0, 0, px, px, px]; + g.setColor(box.outlineColor); + for (let i = 0; i < dx.length; i++) { + g_drawString.call(g, str, x + dx[i], y + dy[i]); + } + }; + + let calcBoxSize = function(boxItem) { + g.reset(); + g.setFontAlign(0,0); + g.setFont(boxItem.font, boxItem.fontSize); + let strWidth = g.stringWidth(boxItem.string) + 2 * boxItem.outline; + let fontHeight = g.getFontHeight() + 2 * boxItem.outline; + totalWidth = strWidth + 2 * boxItem.xPadding; + totalHeight = fontHeight + 2 * boxItem.yPadding; + }; + + let calcBoxPos = function(boxKey) { + return { + x1: boxPos[boxKey].x - totalWidth / 2, + y1: boxPos[boxKey].y - totalHeight / 2, + x2: boxPos[boxKey].x + totalWidth / 2, + y2: boxPos[boxKey].y + totalHeight / 2 + }; + }; + + // 7. Date and time related functions + let getDate = function() { + const date = new Date(); + const dayOfMonth = date.getDate(); + const month = locale.month(date, 1); + const year = date.getFullYear(); + let suffix; + if ([1, 21, 31].includes(dayOfMonth)) { + suffix = "st"; + } else if ([2, 22].includes(dayOfMonth)) { + suffix = "nd"; + } else if ([3, 23].includes(dayOfMonth)) { + suffix = "rd"; + } else { + suffix = "th"; + } + let dayOfMonthStr = enableSuffix ? dayOfMonth + suffix : dayOfMonth; + return month + " " + dayOfMonthStr + ", " + year; + }; + + let getDayOfWeek = function(date) { + return locale.dow(date, 0); + }; + + // 8. Main draw function + let draw = function(boxes) { + date = new Date(); + g.clear(); + if (bgImage) { + g.drawImage(bgImage, 0, 0); + } + if (boxes.time) { + boxes.time.string = locale.time(date, 1); + } + if (boxes.date) { + boxes.date.string = getDate(); + } + if (boxes.dow) { + boxes.dow.string = getDayOfWeek(date); + } + if (boxes.batt) { + boxes.batt.string = E.getBattery() + "%"; + } + Object.keys(boxes).forEach((boxKey) => { + let boxItem = boxes[boxKey]; + calcBoxSize(boxItem); + const pos = calcBoxPos(boxKey); + if (isDragging[boxKey]) { + g.setColor(boxItem.border); + g.drawRect(pos.x1, pos.y1, pos.x2, pos.y2); + } + g.drawString( + boxItem, + boxItem.string, + boxPos[boxKey].x + boxItem.xOffset, + boxPos[boxKey].y + boxItem.yOffset + ); + }); + if (!Object.values(isDragging).some(Boolean)) { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(() => draw(boxes), 60000 - (Date.now() % 60000)); + } + }; + + // 9. Helper function for touch event + let touchInText = function(e, boxItem, boxKey) { + calcBoxSize(boxItem); + const pos = calcBoxPos(boxKey); + return e.x >= pos.x1 && + e.x <= pos.x2 && + e.y >= pos.y1 && + e.y <= pos.y2; + }; + + // 10. Setup function to configure event handlers + let setup = function() { + // Define the touchHandler function + touchHandler = function(zone, e) { + wasDragging = Object.assign({}, isDragging); + let boxTouched = false; + Object.keys(boxes).forEach((boxKey) => { + if (touchInText(e, boxes[boxKey], boxKey)) { + isDragging[boxKey] = true; + wasDragging[boxKey] = true; + boxTouched = true; + } + }); + if (!boxTouched) { + Object.keys(isDragging).forEach((boxKey) => { + isDragging[boxKey] = false; + }); + require("widget_utils").show(); + require("widget_utils").swipeOn(); + } + if (Object.values(wasDragging).some(Boolean) || !boxTouched) { + draw(boxes); + } + }; + + // Define the dragHandler function + dragHandler = function(e) { + Object.keys(boxes).forEach((boxKey) => { + if (isDragging[boxKey]) { + require("widget_utils").hide(); + let boxItem = boxes[boxKey]; + calcBoxSize(boxItem); + let newX = boxPos[boxKey].x + e.dx; + let newY = boxPos[boxKey].y + e.dy; + if (newX - totalWidth / 2 >= 0 && + newX + totalWidth / 2 <= w && + newY - totalHeight / 2 >= 0 && + newY + totalHeight / 2 <= h ) { + boxPos[boxKey].x = newX; + boxPos[boxKey].y = newY; + } + const pos = calcBoxPos(boxKey); + g.clearRect(pos.x1, pos.y1, pos.x2, pos.y2); + } + }); + draw(boxes); + }; + + Bangle.on('touch', touchHandler); + Bangle.on('drag', dragHandler); + + Bangle.setUI({ + mode : "clock", + remove : function() { + // Remove event handlers, stop draw timer, remove custom font if used + Bangle.removeListener('touch', touchHandler); + Bangle.removeListener('drag', dragHandler); + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + delete Graphics.prototype.setFontBrunoAce; + g.drawString = g_drawString; // Return to original without outlines + require("widget_utils").show(); + } + }); + loadCustomFont(); + draw(boxes); + }; + + // 11. Main execution part + Bangle.loadWidgets(); + require("widget_utils").swipeOn(); + setup(); + } + \ No newline at end of file diff --git a/apps/boxclk/screenshot-1.png b/apps/boxclk/screenshot-1.png index 91bf880c0bfb3a7d138f49c59280f6e11d6d0cb1..9b270178ec7f7429be099d26a6da548a8994af58 100644 GIT binary patch literal 6060 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 Scg@=X0000 { - let match = file.match(fileRegex); - if (match) { - let number = parseInt(match[1]); - if (number > maxNumber) { - maxNumber = number; - } - } - }); - return maxNumber + 1; -} - (function () { + let storage = require("Storage"); + let fileRegex = /^boxclk-(\d+)\.json$/; + let selectedConfig; let configs = {}; let hasDefaultConfig = false; + function getNextConfigNumber() { + let maxNumber = 0; + storage.list().forEach(file => { + let match = file.match(fileRegex); + if (match) { + let number = parseInt(match[1]); + if (number > maxNumber) { + maxNumber = number; + } + } + }); + return maxNumber + 1; + } + function handleSelection(config) { return function () { selectedConfig = config === "Default" ? 0 : config; @@ -72,4 +71,4 @@ function getNextConfigNumber() { }); E.showMenu(menu); -})(); +});