From e86d3f6358b55b0062b8a80d5b50bb2fe0135c82 Mon Sep 17 00:00:00 2001 From: Alina Marquardt Date: Tue, 4 Apr 2023 23:18:18 +0200 Subject: [PATCH] initial commit --- app/index.js | 164 +++++++++++++++++++++++++++++++++++++ common/characters.js | 80 +++++++++++++++++++ common/colors.js | 109 +++++++++++++++++++++++++ common/digits.js | 69 ++++++++++++++++ common/themes.js | 182 ++++++++++++++++++++++++++++++++++++++++++ companion/index.js | 47 +++++++++++ package.json | 18 +++++ resources/index.gui | 25 ++++++ resources/styles.css | 8 ++ resources/widgets.gui | 115 ++++++++++++++++++++++++++ settings/index.jsx | 101 +++++++++++++++++++++++ 11 files changed, 918 insertions(+) create mode 100644 app/index.js create mode 100644 common/characters.js create mode 100644 common/colors.js create mode 100644 common/digits.js create mode 100644 common/themes.js create mode 100644 companion/index.js create mode 100644 package.json create mode 100644 resources/index.gui create mode 100644 resources/styles.css create mode 100644 resources/widgets.gui create mode 100644 settings/index.jsx diff --git a/app/index.js b/app/index.js new file mode 100644 index 0000000..422e95b --- /dev/null +++ b/app/index.js @@ -0,0 +1,164 @@ +import document from "document"; +import clock from "clock"; +import { display } from "display"; +import { vibration } from "haptics"; +import { preferences } from "user-settings"; +import * as messaging from "messaging"; +import * as fs from "fs"; +import * as digits from "../common/digits"; +import * as colors from "../common/colors"; +import * as themes from "../common/themes"; + +var starttime, endtime; + +const debug = false; +const colorTemplate = false; + +const colorCount = 25; +var colorDef = [ + null, + themes.colors['whiteMarble'], + themes.colors['blackMarble'] +]; + +var storedColorDef; +var fileSuccess = true; +console.log('reading color def'); +try { + storedColorDef = fs.readFileSync("colordef.txt", "cbor"); +} +catch(err) { + fileSuccess = false; + console.log('color def not found'); +} +if (fileSuccess) { + colorDef = storedColorDef; +} + +var storedColorSet; +var fileSuccess = true; +console.log('reading colors file'); +try { + storedColorSet = fs.readFileSync("colors.txt", "cbor"); +} +catch(err) { + fileSuccess = false; + console.log('colors file not found, scheduling initial color generation'); +} +if (fileSuccess) { + colors.setCurrentColorSet(storedColorSet); +} + +if (debug) { + let touchArea = document.getElementById('touchArea'); + display.autoOff = false; + display.on = true; + colors.initColors(colorDef, colorCount); + touchArea.onclick = (e) => { + colors.initColors(colorDef, colorCount); + updateClock(true); + } +} + +function updateClock(forceRedraw) { + starttime = new Date(); + console.log('started updateClock with forceRedraw = '+forceRedraw); + let currDate = new Date(); + let hours = currDate.getHours(); + let displayHours = hours; + if (preferences.clockDisplay === '12h') { + displayHours = displayHours % 12; + displayHours = displayHours ? displayHours : 12; + } + let minutes = currDate.getMinutes(); + let day = currDate.getDate(); + let month = currDate.getMonth()+1; + + let newDigits = [ + Math.floor(displayHours/10), + displayHours%10, + Math.floor(minutes/10), + minutes%10, + Math.floor(day/10), + day%10, + Math.floor(month/10), + month%10, + ]; + + if (debug) { + newDigits[0] = 1; + newDigits[1] = 7; + newDigits[2] = 0; + newDigits[3] = 4; + newDigits[4] = 1; + newDigits[5] = 3; + newDigits[6] = 0; + newDigits[7] = 7; + } + if (colorTemplate) { + newDigits[0] = 'Ÿ'; + newDigits[1] = 'ÿ'; + newDigits[2] = 'Ÿ'; + newDigits[3] = 'ÿ'; + } + + endtime = new Date(); + console.log('updateClock is ready for setDigits at '+(endtime-starttime)+' ms'); + + digits.setDigits(newDigits, forceRedraw); + + endtime = new Date(); + console.log('updateClock finished setDigits at '+(endtime-starttime)+' ms'); +} + +display.onchange = () => { + if (!display.on) { + colors.initColors(colorDef, colorCount); + updateClock(true); + } +} + +clock.granularity = "minutes"; +clock.ontick = () => updateClock(); + +updateClock(); + +messaging.peerSocket.onmessage = e => { + console.log("Message received -> "+e.data.key+": "+e.data.newValue); + display.poke(); + vibration.start("bump"); + let updateColors = false + switch (e.data.key) { + case 'digitColor': + colorDef[1] = themes.colors[e.data.newValue]; + updateColors = true; + break; + case 'ornamentColor': + colorDef[2] = themes.colors[e.data.newValue]; + updateColors = true; + break; + }; + if (updateColors) { + colors.initColors(colorDef, colorCount); + updateClock(true); + vibration.start("bump"); + fs.writeFileSync("colordef.txt", colorDef, "cbor"); + } +} + +messaging.peerSocket.onopen = () => { + console.log("Clockface opened socket"); +}; + +messaging.peerSocket.close = () => { + console.log("Clockface closed socket"); +}; + +messaging.peerSocket.onerror = (err) => { + console.log("Clockface socket error: " + err.code + " - " + err.message); +} + +setTimeout(() => { + colors.initColors(colorDef, colorCount); + updateClock(true); +}, 200); \ No newline at end of file diff --git a/common/characters.js b/common/characters.js new file mode 100644 index 0000000..1421ff1 --- /dev/null +++ b/common/characters.js @@ -0,0 +1,80 @@ +export const charwidth = 5; + +export const chars = { + 'ÿ': [ + [1,1,1,1,1], + [1,1,1,1,1], + [1,1,1,1,1], + [1,1,1,1,1], + [1,1,1,1,1] + ], + 'Ÿ': [ + [2,2,2,2,2], + [2,2,2,2,2], + [2,2,2,2,2], + [2,2,2,2,2], + [2,2,2,2,2] + ] +}; + +export const numbers = [[ + [1,1,1,1,1], + [1,0,0,0,1], + [1,0,2,0,1], + [1,0,0,0,1], + [1,1,1,1,1] +], [ + [2,2,0,1,1], + [0,0,0,0,1], + [2,2,2,0,1], + [0,0,0,0,1], + [2,2,2,0,1] +], [ + [1,1,1,1,1], + [0,0,0,0,1], + [1,1,1,1,1], + [1,0,0,0,0], + [1,1,1,1,1] +], [ + [1,1,1,1,1], + [0,0,0,0,1], + [0,1,1,1,1], + [0,0,0,0,1], + [1,1,1,1,1] +], [ + [1,0,2,0,1], + [1,0,0,0,1], + [1,1,1,1,1], + [0,0,0,0,1], + [2,2,2,0,1] +], [ + [1,1,1,1,1], + [1,0,0,0,0], + [1,1,1,1,1], + [0,0,0,0,1], + [1,1,1,1,1] +], [ + [1,1,1,1,1], + [1,0,0,0,0], + [1,1,1,1,1], + [1,0,0,0,1], + [1,1,1,1,1] +], [ + [1,1,1,1,1], + [0,0,0,0,1], + [2,0,2,0,1], + [2,0,2,0,1], + [2,0,2,0,1] +], [ + [1,1,1,1,1], + [1,0,0,0,1], + [1,1,1,1,1], + [1,0,0,0,1], + [1,1,1,1,1] +], [ + [1,1,1,1,1], + [1,0,0,0,1], + [1,1,1,1,1], + [0,0,0,0,1], + [1,1,1,1,1] +]]; \ No newline at end of file diff --git a/common/colors.js b/common/colors.js new file mode 100644 index 0000000..2840dd2 --- /dev/null +++ b/common/colors.js @@ -0,0 +1,109 @@ +import * as themes from "themes"; +import * as fs from "fs"; + +let defaultColorSet = [ + '#666', + '#333' +] + +function hslToRgb(h, s, l) { + var r, g, b; + + if (s == 0) { + r = g = b = l; // achromatic + } else { + var hue2rgb = (p, q, t) => { + if(t < 0) t += 1; + if(t > 1) t -= 1; + if(t < 1/6) return p + (q - p) * 6 * t; + if(t < 1/2) return q; + if(t < 2/3) return p + (q - p) * (2/3 - t) * 6; + return p; + } + + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1/3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1/3); + } + + return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; +} + +function rgbToHex(r, g, b) { + return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1); +} + +const defaultRanges = [[0,1],[0.2,1],[0.2,0.8]]; + +var currentColorSet = defaultColorSet; +var colorPosition = [0, 0]; +var colorReverse = [false, false]; + +export function setCurrentColorSet(colorSet) { + currentColorSet = colorSet; +} + +function generateColors(hsl, variance, ranges, number) { + let colorArray = []; + for (let i=0; i ranges[i][1]) { + hsl[i] = ranges[i][1]; + } + } + } + let rgb = hslToRgb(hsl[0], hsl[1], hsl[2]); + return rgbToHex(rgb[0], rgb[1], rgb[2]); +} \ No newline at end of file diff --git a/common/digits.js b/common/digits.js new file mode 100644 index 0000000..a2cd83a --- /dev/null +++ b/common/digits.js @@ -0,0 +1,69 @@ +import document from "document"; +import * as colors from "colors"; +import * as characters from "characters"; + +var starttime, endtime; + +export let currentDigits = [-1,-1,-1,-1,-1,-1,-1,-1]; + +function getSquares(character) { + if (typeof character === 'string') { + return characters.chars[character]; + } else { + return characters.numbers[character]; + } +} + +export function setDigits(digits, forceRedraw) { + for(let i=0; i { +}; + +messaging.peerSocket.close = () => { +}; + +settingsStorage.onchange = evt => { + let data = {} + switch(evt.key) { + case 'digitColor': + case 'ornamentColor': + data = { + key: evt.key, + newValue: JSON.parse(evt.newValue).values[0].value + }; + break; + case 'elements': + let elements = []; + let newValue = JSON.parse(evt.newValue); + for(let i=0; i < newValue.length; i++) { + elements[i] = newValue[i].value; + } + data = { + key: evt.key, + newValue: elements + }; + default: + data = { + key: evt.key, + newValue: evt.newValue + }; + break; + } + + sendVal(data); +}; + +function sendVal(data) { + if (messaging.peerSocket.readyState === messaging.peerSocket.OPEN) { + messaging.peerSocket.send(data); + } +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..7e65975 --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "fitbit": { + "appUUID": "ded37ece-013f-4291-8704-da8374ffdae0", + "appType": "app", + "appDisplayName": "Squared", + "iconFile": "resources/icon.png", + "wipeColor": "#8bc34a", + "requestedPermissions": [], + "buildTargets": [ + "meson" + ], + "i18n": { + "en": { + "name": "Squared" + } + } + } +} \ No newline at end of file diff --git a/resources/index.gui b/resources/index.gui new file mode 100644 index 0000000..1010cf0 --- /dev/null +++ b/resources/index.gui @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/styles.css b/resources/styles.css new file mode 100644 index 0000000..88357b9 --- /dev/null +++ b/resources/styles.css @@ -0,0 +1,8 @@ +.background { + viewport-fill: black; +} + +.square { + fill: #444444; + display: inline; +} \ No newline at end of file diff --git a/resources/widgets.gui b/resources/widgets.gui new file mode 100644 index 0000000..5a9fda4 --- /dev/null +++ b/resources/widgets.gui @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/settings/index.jsx b/settings/index.jsx new file mode 100644 index 0000000..a0fa334 --- /dev/null +++ b/settings/index.jsx @@ -0,0 +1,101 @@ +function Squared(props) { + return ( + +
Color Settings}> + + + } + onSelection={(selection) => console.log(selection)} + /> +
+
Display Elements}> + + } + /> +
+
+ ); +} + +registerSettingsPage(Squared); \ No newline at end of file