1
0
Fork 0

Merge branch 'master' into master

master
Gordon Williams 2021-12-13 09:06:12 +00:00 committed by GitHub
commit af293b3e7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 526 additions and 222 deletions

View File

@ -538,7 +538,7 @@
"icon": "clock-impword.png", "icon": "clock-impword.png",
"type": "clock", "type": "clock",
"tags": "clock", "tags": "clock",
"supports": ["BANGLEJS"], "supports": ["BANGLEJS","BANGLEJS2"],
"screenshots": [{"url":"bangle1-impercise-word-clock-screenshot.png"}], "screenshots": [{"url":"bangle1-impercise-word-clock-screenshot.png"}],
"allow_emulator": true, "allow_emulator": true,
"storage": [ "storage": [
@ -4829,9 +4829,10 @@
"id": "ptlaunch", "id": "ptlaunch",
"name": "Pattern Launcher", "name": "Pattern Launcher",
"shortName": "Pattern Launcher", "shortName": "Pattern Launcher",
"version": "0.02", "version": "0.10",
"description": "Directly launch apps from the clock screen with custom patterns.", "description": "Directly launch apps from the clock screen with custom patterns.",
"icon": "app.png", "icon": "app.png",
"screenshots": [{"url":"main_menu_add.png"}, {"url":"add_pattern.png"}, {"url":"select_app.png"}, {"url":"main_menu_manage.png"}, {"url":"manage_patterns.png"}],
"tags": "tools", "tags": "tools",
"supports": ["BANGLEJS2"], "supports": ["BANGLEJS2"],
"readme": "README.md", "readme": "README.md",
@ -4845,7 +4846,7 @@
{ "id": "clicompleteclk", { "id": "clicompleteclk",
"name": "CLI complete clock", "name": "CLI complete clock",
"shortName":"CLI cmplt clock", "shortName":"CLI cmplt clock",
"version":"0.02", "version":"0.03",
"description": "Command line styled clock with lots of information", "description": "Command line styled clock with lots of information",
"icon": "app.png", "icon": "app.png",
"allow_emulator": true, "allow_emulator": true,
@ -4854,9 +4855,10 @@
"supports" : ["BANGLEJS", "BANGLEJS2"], "supports" : ["BANGLEJS", "BANGLEJS2"],
"readme": "README.md", "readme": "README.md",
"storage": [ "storage": [
{"name":"clicompleteclk.app.js","url":"app.js"}, {"name":"clicompleteclk.img","url":"app-icon.js","evaluate":true},
{"name":"clicompleteclk.img","url":"app-icon.js","evaluate":true} {"name":"clicompleteclk.settings.js","url":"settings.js"}
] ],
"data": [{"name":"clicompleteclk.json"}]
}, },
{ {
"id":"awairmonitor", "id":"awairmonitor",
@ -4873,4 +4875,5 @@
{"name":"awairmonitor.img","url":"app-icon.js","evaluate":true} {"name":"awairmonitor.img","url":"app-icon.js","evaluate":true}
] ]
} }
}
] ]

View File

@ -3,12 +3,14 @@
Command line styled clock with lots of information: Command line styled clock with lots of information:
It can show the following (depending on availability) information: It can show the following (depending on availability) information:
* Time * Time data:
* Day of week * Time
* Date * Day of week
* Weather conditions and temperature (requires app [Weather](https://banglejs.com/apps/#weather)) * Date
* Steps (requires app [Health Tracking](https://banglejs.com/apps/#health%20tracking) or a step widget) * Additional information (can be toggled via settings):
* Heart rate (when screen is on and unlocked) * Weather conditions and temperature (requires app [Weather](https://banglejs.com/apps/#weather))
* Steps (requires app [Health Tracking](https://banglejs.com/apps/#health%20tracking) or a step widget)
* Heart rate (when screen is on and unlocked)
## TODO ## TODO
* Make time font bigger * Make time font bigger

View File

@ -1,31 +1,60 @@
const storage = require('Storage'); const storage = require('Storage');
const locale = require("locale"); const locale = require("locale");
const font = "12x20"; const font12 = g.getFonts().includes("12x20");
const fontsize = 1; const font = font12 ? "12x20" : "6x8";
const fontsize = font12 ? 1: 2;
const fontheight = 19; const fontheight = 19;
const marginTop = 10; const marginTop = 5;
const marginLeftTopic = 3; // margin of topics const marginLeftTopic = 3; // margin of topics
const marginLeftData = 68; // margin of data values const marginLeftData = font12 ? 64 : 75; // margin of data values
const topicColor = g.theme.dark ? "#fff" : "#000"; const topicColor = g.theme.dark ? "#fff" : "#000";
const textColor = g.theme.dark ? "#0f0" : "#080"; const textColor = g.theme.dark ? "#0f0" : "#080";
const textColorRed = g.theme.dark ? "#FF0000" : "#FF0000";
let hrtValue; let hrtValue;
let hrtValueIsOld = false; let hrtValueIsOld = false;
let localTempValue; let localTempValue;
let weatherTempString; let weatherTempString;
let lastHeartRateRowIndex; let lastHeartRateRowIndex;
let lastStepsRowIndex;
let i = 2;
let settings;
function loadSettings() {
settings = storage.readJSON('clicompleteclk.json', 1) || {};
}
function setting(key) {
if (!settings) { loadSettings(); }
const DEFAULTS = {
'battery': true,
'batteryLvl': 30,
'weather': true,
'steps': true,
'heartrate': true
};
return (key in settings) ? settings[key] : DEFAULTS[key];
}
let showBattery = setting('battery');
let batteryWarnLevel = setting('batteryLvl');
let showWeather = setting('weather');
let showSteps = setting('steps');
let showHeartRate = setting('heartrate');
// timeout used to update every minute
var drawTimeout; var drawTimeout;
// schedule a draw for the next minute
function queueDraw() { function queueDraw() {
if (drawTimeout) clearTimeout(drawTimeout); if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = setTimeout(function() { drawTimeout = setTimeout(function() {
drawTimeout = undefined; drawTimeout = undefined;
drawAll(false); drawAll(true);
}, 60000 - (Date.now() % 60000)); }, 60000 - (Date.now() % 60000));
} }
@ -42,15 +71,13 @@ function updateTime(now){
if (!Bangle.isLCDOn()) return; if (!Bangle.isLCDOn()) return;
writeLineTopic("TIME", 1); writeLineTopic("TIME", 1);
writeLine(locale.time(now,1),1); writeLine(locale.time(now,1),1);
if(now.getMinutes() == 0)
drawInfo(now);
} }
function drawInfo(now) { function drawInfo(now) {
if (now == undefined) if (now == undefined)
now = new Date(); now = new Date();
let i = 2; i = 2;
writeLineTopic("DOWK", i); writeLineTopic("DOWK", i);
writeLine(locale.dow(now),i); writeLine(locale.dow(now),i);
@ -60,14 +87,28 @@ function drawInfo(now) {
writeLine(locale.date(now,1),i); writeLine(locale.date(now,1),i);
i++; i++;
/* if (showBattery) {
writeLineTopic("BAT", i); writeLineTopic("BATT", i);
const b = E.getBattery(); const b = E.getBattery();
writeLine(b + "%", i); // TODO make bars writeLine(b + "%", i, b < batteryWarnLevel ? textColorRed : textColor);
i++; i++;
*/ }
// weather if (showWeather) {
drawWeather();
}
if (showSteps) {
drawSteps(i);
i++;
}
if (showHeartRate) {
drawHeartRate(i);
}
}
function drawWeather() {
const weatherJson = getWeather(); const weatherJson = getWeather();
if(weatherJson && weatherJson.weather){ if(weatherJson && weatherJson.weather){
const currentWeather = weatherJson.weather; const currentWeather = weatherJson.weather;
@ -82,19 +123,22 @@ function drawInfo(now) {
writeLine(weatherTempValue,i); writeLine(weatherTempValue,i);
i++; i++;
} }
}
// steps function drawSteps(i) {
if (!showSteps) return;
if (i == undefined)
i = lastStepsRowIndex;
const steps = getSteps(); const steps = getSteps();
if (steps != undefined) { if (steps != undefined) {
writeLineTopic("STEP", i); writeLineTopic("STEP", i);
writeLine(steps, i); writeLine(steps, i);
i++;
} }
lastStepsRowIndex = i;
drawHeartRate(i);
} }
function drawHeartRate(i) { function drawHeartRate(i) {
if (!showHeartRate) return;
if (i == undefined) if (i == undefined)
i = lastHeartRateRowIndex; i = lastHeartRateRowIndex;
writeLineTopic("HRTM", i); writeLineTopic("HRTM", i);
@ -155,15 +199,21 @@ function getWeather() {
// turn on HRM when the LCD is unlocked // turn on HRM when the LCD is unlocked
Bangle.on('lock', function(isLocked) { Bangle.on('lock', function(isLocked) {
if (!isLocked) { if (!isLocked) {
Bangle.setHRMPower(1,"clicompleteclk"); if (showHeartRate) {
if (hrtValue == undefined) Bangle.setHRMPower(1,"clicompleteclk");
hrtValue = "..."; if (hrtValue == undefined)
else hrtValue = "...";
hrtValueIsOld = true; else
hrtValueIsOld = true;
}
} else { } else {
hrtValueIsOld = true; if (showHeartRate) {
Bangle.setHRMPower(0,"clicompleteclk"); hrtValueIsOld = true;
Bangle.setHRMPower(0,"clicompleteclk");
}
} }
// Update steps and heart rate
drawSteps();
drawHeartRate(); drawHeartRate();
}); });
@ -171,25 +221,30 @@ Bangle.on('lcdPower',function(on) {
if (on) { if (on) {
drawAll(true); drawAll(true);
} else { } else {
hrtValueIsOld = true; if (showHeartRate) {
hrtValueIsOld = true;
}
if (drawTimeout) clearTimeout(drawTimeout); if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = undefined; drawTimeout = undefined;
} }
}); });
Bangle.on('HRM', function(hrm) { if (showHeartRate) {
//if(hrm.confidence > 90){ Bangle.on('HRM', function(hrm) {
hrtValueIsOld = false; //if(hrm.confidence > 90){
hrtValue = hrm.bpm; hrtValueIsOld = false;
if (Bangle.isLCDOn()) hrtValue = hrm.bpm;
drawHeartRate(); if (Bangle.isLCDOn())
//} else { drawHeartRate();
// hrtValue = undefined; //} else {
//} // hrtValue = undefined;
}); //}
});
}
g.clear(); g.clear();
Bangle.setUI("clock"); Bangle.setUI("clock");
Bangle.loadWidgets(); Bangle.loadWidgets();
Bangle.drawWidgets(); Bangle.drawWidgets();
loadSettings();
drawAll(true); drawAll(true);

View File

@ -0,0 +1,54 @@
(function(back) {
const storage = require('Storage');
let settings = storage.readJSON('clicompleteclk.json', 1) || {};
function save(key, value) {
settings[key] = value;
storage.write('clicompleteclk.json', settings);
}
E.showMenu({
'': { 'title': 'CLI complete clk' },
'Show battery': {
value: "battery" in settings ? settings.battery : false,
format: () => (settings.battery ? 'Yes' : 'No'),
onchange: () => {
settings.battery = !settings.battery;
save('battery', settings.battery);
},
},
'Battery warn': {
value: "batteryLvl" in settings ? settings.batteryLvl : 30,
min: 0,
max : 100,
step: 10,
format: x => {
return x + "%";
},
onchange: x => save('batteryLvl', x),
},
'Show weather': {
value: "weather" in settings ? settings.weather : false,
format: () => (settings.weather ? 'Yes' : 'No'),
onchange: () => {
settings.weather = !settings.weather;
save('weather', settings.weather);
},
},
'Show steps': {
value: "steps" in settings ? settings.steps : false,
format: () => (settings.steps ? 'Yes' : 'No'),
onchange: () => {
settings.steps = !settings.steps;
save('steps', settings.steps);
},
},
'Show heartrate': {
value: "heartrate" in settings ? settings.heartrate : false,
format: () => (settings.heartrate ? 'Yes' : 'No'),
onchange: () => {
settings.heartrate = !settings.heartrate;
save('heartrate', settings.heartrate);
},
},
'< Back': back,
});
});

View File

@ -85,7 +85,7 @@ function checkForFileOnServer() {
}); });
} }
var regex = new RegExp("_banglejs2"); var regex = new RegExp("_banglejs2.*zip$");
var domFirmwareList = document.getElementById("latest-firmware-list"); var domFirmwareList = document.getElementById("latest-firmware-list");
var domFirmware = document.getElementById("latest-firmware"); var domFirmware = document.getElementById("latest-firmware");
@ -107,7 +107,7 @@ function checkForFileOnServer() {
}); });
console.log("Finished check for firmware files..."); console.log("Finished check for firmware files...");
var fwlinks = document.querySelectorAll(".fw-link"); var fwlinks = document.querySelectorAll(".fw-link");
for (var i=0;i<fwlinks.length;fwlinks++) for (var i=0;i<fwlinks.length;i++)
fwlinks[i].addEventListener("click", e => { fwlinks[i].addEventListener("click", e => {
e.preventDefault(); e.preventDefault();
var url = e.target.href; var url = e.target.href;

View File

@ -1,3 +1,4 @@
0.01: New App! 0.01: New App!
0.02: Stopped watchface from flashing every interval 0.02: Stopped watchface from flashing every interval
0.03: Move to Bangle.setUI to launcher support 0.03: Move to Bangle.setUI to launcher support
0.04: Tweaks for compatibility with BangleJS2

View File

@ -1,4 +1,4 @@
# Imprecise Word Clock # Imprecise Word Clock
This clock tells time in very rough approximation, as in "Late morning" or "Early afternoon." Good for vacations and weekends. Press button 1 to see the time in accurate, digital form. But do you really need to know the exact time? This clock tells time in very rough approximation, as in "Late morning" or "Early afternoon." Good for vacations and weekends. Touch the screen to see the time in accurate, digital form. But do you really need to know the exact time?

View File

@ -2,7 +2,7 @@
A remix of word clock A remix of word clock
by Gordon Williams https://github.com/gfwilliams by Gordon Williams https://github.com/gfwilliams
- Changes the representation of time to be more general - Changes the representation of time to be more general
- Shows accurate digital time when button 1 is pressed - Toggles showing of accurate digital time when screen touched.
*/ */
/* jshint esversion: 6 */ /* jshint esversion: 6 */
@ -34,14 +34,16 @@ const timeOfDay = {
}; };
var big = g.getWidth()>200;
// offsets and increments // offsets and increments
const xs = 35; const xs = big ? 35 : 20;
const ys = 31; const ys = big ? 31 : 28;
const dy = 22; const dx = big ? 25 : 20;
const dx = 25; const dy = big ? 22 : 16;
// font size and color // font size and color
const fontSize = 3; // "6x8" const fontSize = big ? 3 : 2; // "6x8"
const passivColor = 0x3186 /*grey*/ ; const passivColor = 0x3186 /*grey*/ ;
const activeColorNight = 0xF800 /*red*/ ; const activeColorNight = 0xF800 /*red*/ ;
const activeColorDay = 0xFFFF /* white */; const activeColorDay = 0xFFFF /* white */;
@ -115,6 +117,8 @@ function drawWordClock() {
// check whether we need to redraw the watchface // check whether we need to redraw the watchface
if (hidx !== hidxPrev) { if (hidx !== hidxPrev) {
// Turn off showDigitalTime
showDigitalTime = false;
// draw allWords // draw allWords
var c; var c;
var y = ys; var y = ys;
@ -138,15 +142,14 @@ function drawWordClock() {
hidxPrev = hidx; hidxPrev = hidx;
} }
// Display digital time while button 1 is pressed // Display digital time when button is pressed or screen touched
g.clearRect(0, 215, 240, 240); g.clearRect(0, big ? 215 : 160, big ? 240 : 176, big ? 240 : 176);
if (showDigitalTime){ if (showDigitalTime){
g.setColor(activeColor); g.setColor(activeColor);
g.drawString(time, 120, 215); g.drawString(time, big ? 120 : 90, big ? 215 : 160);
} }
} }
Bangle.on('lcdPower', function(on) { Bangle.on('lcdPower', function(on) {
if (on) drawWordClock(); if (on) drawWordClock();
}); });
@ -157,17 +160,14 @@ Bangle.drawWidgets();
setInterval(drawWordClock, 1E4); setInterval(drawWordClock, 1E4);
drawWordClock(); drawWordClock();
// Show digital time while top button is pressed (if we have physical buttons)
if (global.BTN3) setWatch(function() {
showDigitalTime = BTN1.read();
drawWordClock();
}, BTN1, {repeat:true,edge:"both"});
// If LCD pressed (on Bangle.js 2) draw digital time // If LCD pressed, toggle drawing digital time
Bangle.on('drag',e=>{ Bangle.on('touch',e=>{
var pressed = e.b!=0; if (showDigitalTime){
if (pressed!=showDigitalTime) { showDigitalTime = false;
showDigitalTime = pressed; drawWordClock();
} else {
showDigitalTime = true;
drawWordClock(); drawWordClock();
} }
}); });

View File

@ -1,2 +1,4 @@
0.01: Initial creation of the pattern launch app 0.01: Initial creation of the pattern launch app
0.02: Turn on lcd when launching an app if the lock screen was disabled in the settings 0.02: Turn on lcd when launching an app if the lock screen was disabled in the settings
0.03: Make tap to confirm new pattern more reliable. Also allow for easier creation of single circle patterns.
0.10: Improve the management of existing patterns: Draw the linked pattern on the left hand side of the app name within a scroller, similar to the default launcher. Slighlty clean up the code to make it less horrible.

View File

@ -8,25 +8,32 @@ Create patterns and link them to apps in the Pattern Launcher app.
Then launch the linked apps directly from the clock screen by simply drawing the desired pattern. Then launch the linked apps directly from the clock screen by simply drawing the desired pattern.
## Screenshots and detailed steps ## Add Pattern Screenshots
![](main_menu.png) ![](main_menu_add.png)
![](add_pattern.png) ![](add_pattern.png)
![](select_app.png) ![](select_app.png)
## Manage Pattern Screenshots
![](main_menu_manage.png)
![](manage_patterns.png)
## Detailed Steps
From the main menu you can: From the main menu you can:
- Add a new pattern and link it to an app (first entry) - Add a new pattern and link it to an app (first entry)
- To create a new pattern first select "Add Pattern" - To create a new pattern first select "Add Pattern"
- Now draw any pattern you like, this will later launch the linked app from the clock screen - Now draw any pattern you like, this will later launch the linked app from the clock screen
- You can also draw a single-circle pattern (meaning a single tap on one circle) instead of drawing a 'complex' pattern
- If you don't like the pattern, simply re-draw it. The previous pattern will be discarded. - If you don't like the pattern, simply re-draw it. The previous pattern will be discarded.
- If you are happy with the pattern tap on screen or press the button to continue - If you are happy with the pattern tap on screen or press the button to continue
- Now select the app you want to launch with the pattern. - Now select the app you want to launch with the pattern.
- Note, you can bind multiple patterns to the same app. - Note, you can bind multiple patterns to the same app.
- Remove linked patterns (second entry) - Manage created patterns (second entry)
- To remove a pattern first select "Remove Pattern" - To manage your patterns first select "Manage Patterns"
- You will now see a list of apps that have patterns linked to them - You will now see a scrollabe list of patterns + linked apps
- Simply select the app that you want to unlink. This will remove the saved pattern, but not the app itself! - If you want to deletion a pattern (and unlink the app) simply tap on it, and confirm the deletion
- Note, that you can not actually preview the patterns. This makes removing patterns that are linked to the same app annoying. sorry!
- Disable the lock screen on the clock screen from the settings (third entry) - Disable the lock screen on the clock screen from the settings (third entry)
- To launch the app from the pattern on the clock screen the watch must be unlocked. - To launch the app from the pattern on the clock screen the watch must be unlocked.
- If this annoys you, you can disable the lock on the clock screen from the setting here - If this annoys you, you can disable the lock on the clock screen from the setting here

View File

@ -1,26 +1,6 @@
var storage = require("Storage");
var DEBUG = false; var DEBUG = false;
var log = (message) => {
if (DEBUG) {
console.log(JSON.stringify(message));
}
};
var CIRCLE_RADIUS = 25; var storage = require("Storage");
var CIRCLE_RADIUS_2 = CIRCLE_RADIUS * CIRCLE_RADIUS;
var CIRCLES = [
{ x: 25, y: 25, i: 0 },
{ x: 87, y: 25, i: 1 },
{ x: 150, y: 25, i: 2 },
{ x: 25, y: 87, i: 3 },
{ x: 87, y: 87, i: 4 },
{ x: 150, y: 87, i: 5 },
{ x: 25, y: 150, i: 6 },
{ x: 87, y: 150, i: 7 },
{ x: 150, y: 150, i: 8 },
];
var showMainMenu = () => { var showMainMenu = () => {
log("loading patterns"); log("loading patterns");
@ -36,7 +16,7 @@ var showMainMenu = () => {
}, },
"Add Pattern": () => { "Add Pattern": () => {
log("creating pattern"); log("creating pattern");
createPattern().then((pattern) => { recognizeAndDrawPattern().then((pattern) => {
log("got pattern"); log("got pattern");
log(pattern); log(pattern);
log(pattern.length); log(pattern.length);
@ -73,17 +53,32 @@ var showMainMenu = () => {
}); });
}); });
}, },
"Remove Pattern": () => { "Manage Patterns": () => {
log("selecting pattern through app"); log("selecting pattern through app");
getStoredPatternViaApp(storedPatterns).then((pattern) => { showScrollerContainingAppsWithPatterns().then((selected) => {
E.showMessage("Deleting..."); var pattern = selected.pattern;
delete storedPatterns[pattern]; var appName = selected.appName;
storage.writeJSON("ptlaunch.patterns.json", storedPatterns); if (pattern === "back") {
showMainMenu(); showMainMenu();
} else {
E.showPrompt(appName + "\n\npattern:\n" + pattern, {
title: "Delete?",
buttons: { Yes: true, No: false },
}).then((confirm) => {
if (confirm) {
E.showMessage("Deleting...");
delete storedPatterns[pattern];
storage.writeJSON("ptlaunch.patterns.json", storedPatterns);
showMainMenu();
} else {
showMainMenu();
}
});
}
}); });
}, },
Settings: () => { Settings: () => {
var settings = storedPatterns["settings"] || {}; var settings = storedPatterns.settings || {};
var settingsmenu = { var settingsmenu = {
"": { "": {
@ -98,7 +93,7 @@ var showMainMenu = () => {
if (settings.lockDisabled) { if (settings.lockDisabled) {
settingsmenu["Enable lock"] = () => { settingsmenu["Enable lock"] = () => {
settings.lockDisabled = false; settings.lockDisabled = false;
storedPatterns["settings"] = settings; storedPatterns.settings = settings;
Bangle.setOptions({ lockTimeout: 1000 * 30 }); Bangle.setOptions({ lockTimeout: 1000 * 30 });
storage.writeJSON("ptlaunch.patterns.json", storedPatterns); storage.writeJSON("ptlaunch.patterns.json", storedPatterns);
showMainMenu(); showMainMenu();
@ -106,7 +101,7 @@ var showMainMenu = () => {
} else { } else {
settingsmenu["Disable lock"] = () => { settingsmenu["Disable lock"] = () => {
settings.lockDisabled = true; settings.lockDisabled = true;
storedPatterns["settings"] = settings; storedPatterns.settings = settings;
storage.writeJSON("ptlaunch.patterns.json", storedPatterns); storage.writeJSON("ptlaunch.patterns.json", storedPatterns);
Bangle.setOptions({ lockTimeout: 1000 * 60 * 60 * 24 * 365 }); Bangle.setOptions({ lockTimeout: 1000 * 60 * 60 * 24 * 365 });
showMainMenu(); showMainMenu();
@ -119,12 +114,8 @@ var showMainMenu = () => {
E.showMenu(mainmenu); E.showMenu(mainmenu);
}; };
var drawCircle = (circle) => {
g.fillCircle(circle.x, circle.y, CIRCLE_RADIUS);
};
var positions = []; var positions = [];
var createPattern = () => { var recognizeAndDrawPattern = () => {
return new Promise((resolve) => { return new Promise((resolve) => {
E.showMenu(); E.showMenu();
g.clear(); g.clear();
@ -147,13 +138,29 @@ var createPattern = () => {
setWatch(() => finishHandler(), BTN); setWatch(() => finishHandler(), BTN);
setTimeout(() => Bangle.on("tap", finishHandler), 250); setTimeout(() => Bangle.on("tap", finishHandler), 250);
positions = [];
var dragHandler = (position) => { var dragHandler = (position) => {
log(position);
positions.push(position); positions.push(position);
debounce().then(() => { debounce().then(() => {
if (isFinished) { if (isFinished) {
return; return;
} }
// This might actually be a 'tap' event.
// Use this check in addition to the actual tap handler to make it more reliable
if (pattern.length > 0 && positions.length === 2) {
if (
positions[0].x === positions[1].x &&
positions[0].y === positions[1].y
) {
finishHandler();
positions = [];
return;
}
}
E.showMessage("Calculating..."); E.showMessage("Calculating...");
var t0 = Date.now(); var t0 = Date.now();
@ -269,18 +276,7 @@ var createPattern = () => {
log("redrawing"); log("redrawing");
g.clear(); g.clear();
g.setColor(0, 0, 0); drawCirclesWithPattern(pattern);
CIRCLES.forEach((circle) => drawCircle(circle));
g.setColor(1, 1, 1);
g.setFontAlign(0, 0);
g.setFont("6x8", 4);
pattern.forEach((circleIndex, patternIndex) => {
var circle = CIRCLES[circleIndex];
g.drawString(patternIndex + 1, circle.x, circle.y);
});
var t2 = Date.now();
log(t2 - t0);
}); });
}; };
@ -341,56 +337,256 @@ var getSelectedApp = () => {
}); });
}; };
var getStoredPatternViaApp = (storedPatterns) => { //////
E.showMessage("Loading patterns..."); // manage pattern related variables and functions
log("getStoredPatternViaApp"); // - draws all saved patterns and their linked app names
// - uses the scroller to allow the user to browse through them
//////
var scrollerFont = g.getFonts().includes("12x20") ? "12x20" : "6x8:2";
var drawBackButton = (r) => {
g.clearRect(r.x, r.y, r.x + r.w - 1, r.y + r.h - 1);
g.setFont(scrollerFont)
.setFontAlign(-1, 0)
.drawString("< Back", 64, r.y + 32);
};
var drawAppWithPattern = (i, r, storedPatterns) => {
log("draw app with pattern");
log({ i: i, r: r, storedPatterns: storedPatterns });
var storedPattern = storedPatterns[i];
var pattern = storedPattern.pattern;
var app = storedPattern.app;
g.clearRect(r.x, r.y, r.x + r.w - 1, r.y + r.h - 1);
g.drawLine(r.x, r.y, 176, r.y);
drawCirclesWithPattern(pattern, {
enableCaching: true,
scale: 0.33,
offset: { x: 1, y: 3 + r.y },
});
g.setColor(0, 0, 0);
if (!storedPattern.wrappedAppName) {
storedPattern.wrappedAppName = g
.wrapString(app.name, g.getWidth() - 64)
.join("\n");
}
log(g.getWidth());
log(storedPattern.wrappedAppName);
g.setFont(scrollerFont)
.setFontAlign(-1, 0)
.drawString(storedPattern.wrappedAppName, 64, r.y + 32);
};
var showScrollerContainingAppsWithPatterns = () => {
var storedPatternsArray = getStoredPatternsArray();
log("drawing scroller for stored patterns");
log(storedPatternsArray);
log(storedPatternsArray.length);
g.clear();
var c = Math.max(storedPatternsArray.length + 1, 3);
return new Promise((resolve) => { return new Promise((resolve) => {
var selectPatternMenu = { E.showScroller({
"": { h: 64,
title: "Select App", c: c,
}, draw: (i, r) => {
"< Cancel": () => { log("draw");
log("cancel"); log({ i: i, r: r });
showMainMenu(); if (i <= 0) {
}, drawBackButton(r);
}; } else if (i <= storedPatternsArray.length) {
drawAppWithPattern(i - 1, r, storedPatternsArray);
log(storedPatterns);
var patterns = Object.keys(storedPatterns);
log(patterns);
patterns.forEach((pattern) => {
if (pattern) {
if (storedPatterns[pattern]) {
var app = storedPatterns[pattern].app;
if (!!app && !!app.name) {
var appName = app.name;
var i = 0;
while (appName in selectPatternMenu[app.name]) {
appName = app.name + i;
i++;
}
selectPatternMenu[appName] = () => {
log("pattern via app selected");
log(pattern);
log(app);
resolve(pattern);
};
}
} }
} },
select: (i) => {
log("selected: " + i);
var pattern = "back";
var appName = "";
if (i > 0) {
var storedPattern = storedPatternsArray[i - 1];
pattern = storedPattern.pattern.join("");
appName = storedPattern.app.name;
}
clearCircleDrawingCache();
resolve({ pattern: pattern, appName: appName });
},
}); });
E.showMenu(selectPatternMenu);
}); });
}; };
showMainMenu(); //////
// storage related functions:
// - stored patterns
// - stored settings
//////
var getStoredPatternsMap = () => {
log("loading stored patterns map");
var storedPatternsMap = storage.readJSON("ptlaunch.patterns.json", 1) || {};
delete storedPatternsMap.settings;
log(storedPatternsMap);
return storedPatternsMap;
};
var getStoredPatternsArray = () => {
var storedPatternsMap = getStoredPatternsMap();
log("converting stored patterns map to array");
var patterns = Object.keys(storedPatternsMap);
var storedPatternsArray = [];
for (var i = 0; i < patterns.length; i++) {
var pattern = "" + patterns[i];
storedPatternsArray.push({
pattern: pattern
.split("")
.map((circleIndex) => parseInt(circleIndex, 10)),
app: storedPatternsMap[pattern].app,
});
}
log(storedPatternsArray);
return storedPatternsArray;
};
////// //////
// lib functions // circle related variables and functions:
// - the circle array itself
// - the radius and the squared radius of the circles
// - circle draw function
////// //////
var CIRCLE_RADIUS = 25;
var CIRCLE_RADIUS_2 = CIRCLE_RADIUS * CIRCLE_RADIUS;
var CIRCLES = [
{ x: 25, y: 25, i: 0 },
{ x: 87, y: 25, i: 1 },
{ x: 150, y: 25, i: 2 },
{ x: 25, y: 87, i: 3 },
{ x: 87, y: 87, i: 4 },
{ x: 150, y: 87, i: 5 },
{ x: 25, y: 150, i: 6 },
{ x: 87, y: 150, i: 7 },
{ x: 150, y: 150, i: 8 },
];
var drawCircle = (circle, drawBuffer, scale) => {
if (!drawBuffer) {
drawBuffer = g;
}
if (!scale) {
scale = 1;
}
var x = circle.x * scale;
var y = circle.y * scale;
var r = CIRCLE_RADIUS * scale;
log("drawing circle");
log({ x: x, y: y, r: r });
drawBuffer.fillCircle(x, y, r);
};
var cachedCirclesDrawings = {};
var clearCircleDrawingCache = () => {
cachedCirclesDrawings = {};
};
var drawCirclesWithPattern = (pattern, options) => {
if (!pattern || pattern.length === 0) {
pattern = [];
}
if (!options) {
options = {};
}
var enableCaching = options.enableCaching;
var scale = options.scale;
var offset = options.offset;
if (!enableCaching) {
enableCaching = false;
}
if (!scale) {
scale = 1;
}
if (!offset) {
offset = { x: 0, y: 0 };
}
log("drawing circles with pattern, scale and offset");
log(pattern);
log(scale);
log(offset);
// cache drawn patterns. especially useful for the manage pattern menu
var image = cachedCirclesDrawings[pattern.join("")];
if (!image) {
log("circle image not cached");
var drawBuffer = Graphics.createArrayBuffer(
g.getWidth() * scale,
g.getHeight() * scale,
1,
{ msb: true }
);
drawBuffer.setColor(1);
CIRCLES.forEach((circle) => drawCircle(circle, drawBuffer, scale));
drawBuffer.setColor(0);
drawBuffer.setFontAlign(0, 0);
drawBuffer.setFont("6x8", 4 * scale);
pattern.forEach((circleIndex, patternIndex) => {
var circle = CIRCLES[circleIndex];
drawBuffer.drawString(
patternIndex + 1,
circle.x * scale,
circle.y * scale
);
});
image = {
width: drawBuffer.getWidth(),
height: drawBuffer.getHeight(),
bpp: 1,
buffer: drawBuffer.buffer,
};
if (enableCaching) {
cachedCirclesDrawings[pattern.join("")] = image;
}
} else {
log("using cached circle image");
}
g.drawImage(image, offset.x, offset.y);
};
var cloneCirclesArray = () => {
var circlesClone = Array(CIRCLES.length);
for (var i = 0; i < CIRCLES.length; i++) {
circlesClone[i] = CIRCLES[i];
}
return circlesClone;
};
//////
// misc lib functions
//////
var log = (message) => {
if (DEBUG) {
console.log(JSON.stringify(message));
}
};
var debounceTimeoutId; var debounceTimeoutId;
var debounce = (delay) => { var debounce = (delay) => {
if (debounceTimeoutId) { if (debounceTimeoutId) {
@ -405,12 +601,8 @@ var debounce = (delay) => {
}); });
}; };
var cloneCirclesArray = () => { //////
var circlesClone = Array(CIRCLES.length); // run main function
//////
for (var i = 0; i < CIRCLES.length; i++) { showMainMenu();
circlesClone[i] = CIRCLES[i];
}
return circlesClone;
};

View File

@ -5,21 +5,6 @@ var log = (message) => {
} }
}; };
var CIRCLE_RADIUS = 25;
var CIRCLE_RADIUS_2 = CIRCLE_RADIUS * CIRCLE_RADIUS;
var CIRCLES = [
{ x: 25, y: 25, i: 0 },
{ x: 87, y: 25, i: 1 },
{ x: 150, y: 25, i: 2 },
{ x: 25, y: 87, i: 3 },
{ x: 87, y: 87, i: 4 },
{ x: 150, y: 87, i: 5 },
{ x: 25, y: 150, i: 6 },
{ x: 87, y: 150, i: 7 },
{ x: 150, y: 150, i: 8 },
];
var storedPatterns; var storedPatterns;
var positions = []; var positions = [];
var dragHandler = (position) => { var dragHandler = (position) => {
@ -28,7 +13,20 @@ var dragHandler = (position) => {
debounce().then(() => { debounce().then(() => {
log(positions.length); log(positions.length);
var circlesClone = cloneCirclesArray(); var CIRCLE_RADIUS = 25;
var CIRCLE_RADIUS_2 = CIRCLE_RADIUS * CIRCLE_RADIUS;
var circles = [
{ x: 25, y: 25, i: 0 },
{ x: 87, y: 25, i: 1 },
{ x: 150, y: 25, i: 2 },
{ x: 25, y: 87, i: 3 },
{ x: 87, y: 87, i: 4 },
{ x: 150, y: 87, i: 5 },
{ x: 25, y: 150, i: 6 },
{ x: 87, y: 150, i: 7 },
{ x: 150, y: 150, i: 8 },
];
var pattern = []; var pattern = [];
var step = Math.floor(positions.length / 100) + 1; var step = Math.floor(positions.length / 100) + 1;
@ -38,92 +36,92 @@ var dragHandler = (position) => {
for (var i = 0; i < positions.length; i += step) { for (var i = 0; i < positions.length; i += step) {
p = positions[i]; p = positions[i];
circle = circlesClone[0]; circle = circles[0];
if (circle) { if (circle) {
a = p.x - circle.x; a = p.x - circle.x;
b = p.y - circle.y; b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i); pattern.push(circle.i);
circlesClone.splice(0, 1); circles.splice(0, 1);
} }
} }
circle = circlesClone[1]; circle = circles[1];
if (circle) { if (circle) {
a = p.x - circle.x; a = p.x - circle.x;
b = p.y - circle.y; b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i); pattern.push(circle.i);
circlesClone.splice(1, 1); circles.splice(1, 1);
} }
} }
circle = circlesClone[2]; circle = circles[2];
if (circle) { if (circle) {
a = p.x - circle.x; a = p.x - circle.x;
b = p.y - circle.y; b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i); pattern.push(circle.i);
circlesClone.splice(2, 1); circles.splice(2, 1);
} }
} }
circle = circlesClone[3]; circle = circles[3];
if (circle) { if (circle) {
a = p.x - circle.x; a = p.x - circle.x;
b = p.y - circle.y; b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i); pattern.push(circle.i);
circlesClone.splice(3, 1); circles.splice(3, 1);
} }
} }
circle = circlesClone[4]; circle = circles[4];
if (circle) { if (circle) {
a = p.x - circle.x; a = p.x - circle.x;
b = p.y - circle.y; b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i); pattern.push(circle.i);
circlesClone.splice(4, 1); circles.splice(4, 1);
} }
} }
circle = circlesClone[5]; circle = circles[5];
if (circle) { if (circle) {
a = p.x - circle.x; a = p.x - circle.x;
b = p.y - circle.y; b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i); pattern.push(circle.i);
circlesClone.splice(5, 1); circles.splice(5, 1);
} }
} }
circle = circlesClone[6]; circle = circles[6];
if (circle) { if (circle) {
a = p.x - circle.x; a = p.x - circle.x;
b = p.y - circle.y; b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i); pattern.push(circle.i);
circlesClone.splice(6, 1); circles.splice(6, 1);
} }
} }
circle = circlesClone[7]; circle = circles[7];
if (circle) { if (circle) {
a = p.x - circle.x; a = p.x - circle.x;
b = p.y - circle.y; b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i); pattern.push(circle.i);
circlesClone.splice(7, 1); circles.splice(7, 1);
} }
} }
circle = circlesClone[8]; circle = circles[8];
if (circle) { if (circle) {
a = p.x - circle.x; a = p.x - circle.x;
b = p.y - circle.y; b = p.y - circle.y;
if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) {
pattern.push(circle.i); pattern.push(circle.i);
circlesClone.splice(8, 1); circles.splice(8, 1);
} }
} }
} }
@ -163,16 +161,6 @@ var debounce = (delay) => {
}); });
}; };
var cloneCirclesArray = () => {
var circlesClone = Array(CIRCLES.length);
for (var i = 0; i < CIRCLES.length; i++) {
circlesClone[i] = CIRCLES[i];
}
return circlesClone;
};
(function () { (function () {
var sui = Bangle.setUI; var sui = Bangle.setUI;
Bangle.setUI = function (mode, cb) { Bangle.setUI = function (mode, cb) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB