Merge branch 'espruino:master' into grandfather-clock
|
|
@ -270,7 +270,8 @@ and which gives information about the app for the Launcher.
|
|||
// 'notify' - provides 'notify' library for showing notifications
|
||||
// 'locale' - provides 'locale' library for language-specific date/distance/etc
|
||||
// (a version of 'locale' is included in the firmware)
|
||||
"tags": "", // comma separated tag list for searching
|
||||
// 'defaultconfig' - a set of apps that will can be installed and will wipe out all previously installed apps
|
||||
"tags": "", // comma separated tag list for searching (don't include uppercase or spaces)
|
||||
// common types are:
|
||||
// 'clock' - it's a clock
|
||||
// 'widget' - it is (or provides) a widget
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"version": "0.02",
|
||||
"description": "A UI/UX for espruino smartwatches, displays dinamically calc. x,y coordinates.",
|
||||
"icon": "app.png",
|
||||
"tags": "Color,input,buttons,touch,UI",
|
||||
"tags": "color,input,buttons,touch,ui",
|
||||
"supports": ["BANGLEJS"],
|
||||
"readme": "README.md",
|
||||
"screenshots": [{"url":"UI4swatch_icon.png"},{"url":"UI4swatch_s1.png"}],
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"version": "0.04",
|
||||
"description": "Wrist mounted ukulele chords",
|
||||
"icon": "app.png",
|
||||
"tags": "uke, chords",
|
||||
"tags": "uke,chords",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
"description": "A fully featured watch face with a playable game on the side.",
|
||||
"readme":"README.md",
|
||||
"type": "clock",
|
||||
"tags": "clock, game",
|
||||
"tags": "clock,game",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"storage": [
|
||||
{"name":"bblobface.app.js","url":"app.js"},
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"version": "0.01",
|
||||
"description": "Aerobic fitness test created by Léger & Lambert",
|
||||
"icon": "beeptest.png",
|
||||
"tags": "Health",
|
||||
"tags": "health",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
"description": "Bangle version of a popular word search game",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"tags": "game, text",
|
||||
"tags": "game,text",
|
||||
"storage": [
|
||||
{"name":"bordle.app.js","url":"bordle.app.js"},
|
||||
{"name":"wordlencr.txt","url":"wordlencr.txt"},
|
||||
|
|
|
|||
|
|
@ -33,3 +33,4 @@ clkinfo.addInteractive that would cause ReferenceError.
|
|||
0.31: Use clock_info module as an app
|
||||
0.32: Make the border of the clock_info box extend all the way to the right of the screen.
|
||||
0.33: Fix issue rendering ClockInfos with for fg+bg color set to the same (#2749)
|
||||
0.34: Support 12-hour time format
|
||||
|
|
|
|||
|
|
@ -239,11 +239,9 @@ let drawTime = function() {
|
|||
var y = y1;
|
||||
var date = new Date();
|
||||
|
||||
var hours = String(date.getHours());
|
||||
var minutes = date.getMinutes();
|
||||
minutes = minutes < 10 ? String("0") + minutes : minutes;
|
||||
var colon = settings.hideColon ? "" : ":";
|
||||
var timeStr = hours + colon + minutes;
|
||||
var timeStr = locale.time(date, 1);
|
||||
if (settings.hideColon)
|
||||
timeStr = timeStr.replace(":", "");
|
||||
|
||||
// Set y coordinates correctly
|
||||
y += parseInt((H - y)/2) + 5;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "bwclk",
|
||||
"name": "BW Clock",
|
||||
"version": "0.33",
|
||||
"version": "0.34",
|
||||
"description": "A very minimalistic clock.",
|
||||
"readme": "README.md",
|
||||
"icon": "app.png",
|
||||
|
|
|
|||
|
|
@ -36,3 +36,4 @@ clkinfo.addInteractive that would cause ReferenceError.
|
|||
Do an quick inital fillRect on theclock info area.
|
||||
0.33: Make the border of the clock_info box extend all the way to the right of the screen.
|
||||
0.34: Fix issue rendering ClockInfos with for fg+bg color set to the same (#2749)
|
||||
0.35: Support 12-hour time format
|
||||
|
|
|
|||
|
|
@ -199,11 +199,9 @@ let drawTime = function() {
|
|||
let y = y1;
|
||||
let date = new Date();
|
||||
|
||||
let hours = String(date.getHours());
|
||||
let minutes = date.getMinutes();
|
||||
minutes = minutes < 10 ? String("0") + minutes : minutes;
|
||||
let colon = settings.hideColon ? "" : ":";
|
||||
let timeStr = hours + colon + minutes;
|
||||
var timeStr = locale.time(date, 1);
|
||||
if (settings.hideColon)
|
||||
timeStr = timeStr.replace(":", "");
|
||||
|
||||
// Set y coordinates correctly
|
||||
y += parseInt((H - y)/2) + 5;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "bwclklite",
|
||||
"name": "BW Clock Lite",
|
||||
"version": "0.34",
|
||||
"version": "0.35",
|
||||
"description": "A very minimalistic clock. This version of BW Clock is quicker at the cost of the custom font.",
|
||||
"readme": "README.md",
|
||||
"icon": "app.png",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
"description": "Show the current and upcoming events synchronized from Gadgetbridge",
|
||||
"icon": "calclock.png",
|
||||
"type": "clock",
|
||||
"tags": "clock agenda",
|
||||
"tags": "clock,agenda",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
|
|
|
|||
|
|
@ -19,3 +19,4 @@
|
|||
Display Widgets in menus
|
||||
0.17: Load holidays before events so the latter is not overpainted
|
||||
0.18: Minor code improvements
|
||||
0.19: Read events synchronized from Gadgetbridge
|
||||
|
|
|
|||
|
|
@ -60,6 +60,12 @@ const loadEvents = () => {
|
|||
date.setSeconds(time.s);
|
||||
return {date: date, msg: a.msg, type: "e"};
|
||||
}));
|
||||
// all events synchronized from Gadgetbridge
|
||||
events = events.concat((require("Storage").readJSON("android.calendar.json",1) || []).map(a => {
|
||||
// timestamp is in seconds, Date requires milliseconds
|
||||
const date = new Date(a.timestamp * 1000);
|
||||
return {date: date, msg: a.title, type: "e"};
|
||||
}));
|
||||
};
|
||||
|
||||
const loadSettings = () => {
|
||||
|
|
@ -221,8 +227,8 @@ const drawCalendar = function(date) {
|
|||
}, []);
|
||||
let i = 0;
|
||||
g.setFont("8x12", fontSize);
|
||||
for (y = 0; y < rowN - 1; y++) {
|
||||
for (x = 0; x < colN; x++) {
|
||||
for (let y = 0; y < rowN - 1; y++) {
|
||||
for (let x = 0; x < colN; x++) {
|
||||
i++;
|
||||
const day = days[i];
|
||||
const curMonth = day < 15 ? month+1 : day < 50 ? month-1 : month;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "calendar",
|
||||
"name": "Calendar",
|
||||
"version": "0.18",
|
||||
"version": "0.19",
|
||||
"description": "Monthly calendar, displays holidays uploaded from the web interface and scheduled events.",
|
||||
"icon": "calendar.png",
|
||||
"screenshots": [{"url":"screenshot_calendar.png"}],
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
"icon": "app.png",
|
||||
"version": "0.13",
|
||||
"type": "clock",
|
||||
"tags": "clock, weather, cassio, retro",
|
||||
"tags": "clock,weather,cassio,retro",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"allow_emulator": true,
|
||||
"readme": "README.md",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
"version":"0.01",
|
||||
"description": "Record time active on a task, course, work or anything really.",
|
||||
"icon": "app.png",
|
||||
"tags": "logging, record, work, tasks",
|
||||
"tags": "logging,record,work,tasks",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"screenshots" : [ { "url":"dump.png"}, { "url":"dump1.png" }, { "url":"dump2.png" }, { "url":"dump3.png" }, { "url":"dump4.png" }, { "url":"dump5.png" }, { "url":"dump6.png" } ],
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
0.01: New app!
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
# Shortcuts
|
||||
|
||||
An app that allows you to create custom ClockInfos that act as shortcuts to your favourite apps.
|
||||
|
||||
## Create a Shortcut
|
||||
After installing the app, you can open the app to add and manage existing shortcuts. If no shortcuts exist, the app will display a ``[+] Shortcuts`` button as a ClockInfo on your Clock (see screenshots), which when clicked will quickly launch into the app so you can add new shortcuts.
|
||||
|
||||
When adding a shortcut, first select the app you wish to use, then select the icon you wish to register to the shortcut. If a keyboard is installed, you'll get the option to rename the shortcut before saving.
|
||||
|
||||
Once created, your shortcut will appear on any Clocks with ClockInfo support, and tapping the shortcut will launch the chosen app
|
||||
|
After Width: | Height: | Size: 471 B |
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEw4UB/4ACBIM889VAHmqAAwKCrQLH0oLCuBoFhoLCtJ1HtILBtYLH9ILBtALHlILQlRFCwALSnWwgECBY8O1gLJgeoBaojLHZfqAQILIFwMDBY8CFwMO2QLGhwuBlWuBY0K4ED1aDHBYJUBlQLGnRUChQLIKgJHHBYJUBZY8KgZUBBZHCKgILHh2CBZMC0fABZC+CBZBSBC5JUB14MDcY2q1YLIDAILGtY4EAAXpBYNpBY9pBYNauAKFhulBYWqAAwLCqoLHBQQA6A="))
|
||||
|
|
@ -0,0 +1,224 @@
|
|||
var storage = require("Storage");
|
||||
var keyboard = "textinput";
|
||||
try {
|
||||
keyboard = require(keyboard);
|
||||
} catch (e) {
|
||||
keyboard = null;
|
||||
}
|
||||
|
||||
var icons = [
|
||||
{name:"agenda", img :"GBiBAAAAAAA8AAB+AA/n8B/n+BgAGBgAGBn/mBn/mBgAGBgAGBn/mBn/+BgD/BgHDhn+Bhn8MxgMIxgMIx/8Ew/+BgAHDgAD/AAA8A=="},
|
||||
{name:"alarm", img:"GBiBAAAAAAAAAAYAYA4AcBx+ODn/nAOBwAcA4A4YcAwYMBgYGBgYGBgYGBgYGBgeGBgHGAwBMA4AcAcA4AOBwAH/gAB+AAAAAAAAAA=="},
|
||||
{name:"mail", img:"GBiBAAAAAAAAAAAAAAAAAB//+D///DAADDgAHDwAPDcA7DPDzDDnDDA8DDAYDDAADDAADDAADDAADD///B//+AAAAAAAAAAAAAAAAA=="},
|
||||
{name:"android", img: "GBiBAAAAAAEAgAD/AAD/AAHDgAGBgAMkwAMAwAP/wBv/2BsA2BsA2BsA2BsA2BsA2BsA2Bv/2AP/wADnAADnAADnAADnAADnAAAAAA=="},
|
||||
{name:"add", img:"GBiBAAAAAAAAAAAAAA//8B//+BgAGBgAGBgYGBgYGBgYGBgYGBn/mBn/mBgYGBgYGBgYGBgYGBgAGBgAGB//+A//8AAAAAAAAAAAAA=="},
|
||||
{name:"bangle", img:"GBiBAAD+AAH+AAH+AAH+AAH/AAOHAAYBgAwAwBgwYBgwYBgwIBAwOBAwOBgYIBgMYBgAYAwAwAYBgAOHAAH/AAH+AAH+AAH+AAD+AA=="},
|
||||
{name:"bike", img:"GBiBAAAAAAAAAAAAAAAD+AAD/AADjAABjAfhnAfjyAMDwAcGwB4O+H8M/GGZ5sD7c8fzM8fjM8DDA2GBhn8B/h4AeAAAAAAAAAAAAA=="},
|
||||
{name:"map", img:"GBiBAAAAAAAAAAAAAADgGAf8+B//+BjHGBjDGBjDGBjDGBjDGBjDGBjDGBjDGBjDGBjDGBjDGBjjGB//+B8/4BgHAAAAAAAAAAAAAA=="},
|
||||
{name:"play", img:"GBiBAAAAAAAAAAAAAA//8B//+BgAGBjAGBjwGBj8GBjeGBjHmBjB2BjB2BjHmBjeGBj8GBjwGBjAGBgAGB//+A//8AAAAAAAAAAAAA=="},
|
||||
{name:"fast forward", img:"GBiBAAAAAAAAAAAAAH///v///8AAA8YYA8eeA8f/g8b7w8Y488YYO8YYO8Y488b7w8f/g8eeA8YYA8AAA////3///gAAAAAAAAAAAA=="},
|
||||
{name:"rewind", img:"GBiBAAAAAAAAAAAAAH///v///8AAA8AYY8B548H/48PfY88cY9wYY9wYY88cY8PfY8H/48B548AYY8AAA////3///gAAAAAAAAAAAA=="},
|
||||
{name:"timer", img:"GBiBAAAAAAB+AAB+AAAAMAB+OAH/nAOByAcA4A4YcAwYMBgYGBgYGBgYGBgYGBgAGBgAGAwAMA4AcAcA4AOBwAH/gAB+AAAAAAAAAA=="},
|
||||
{name:"connected", img:"GBiBAAAAAAAAAAAAAA//8B//+BgAGBgAGBngGBn4GBgcGBgOGBnHGBnzGBgxmBgZmBmZmBmZmBgAGBgAGB//+A//8AAAAAAAAAAAAA=="},
|
||||
{name:"lock", img:"GBiBAAAAAAA8AAD/AAHDgAGBgAMAwAMAwAMAwAf/4A//8AwAMAwAMAwAMAwYMAw8MAw8MAwYMAwAMAwAMAwAMA//8Af/4AAAAAAAAA=="},
|
||||
{name:"battery", img:"GBiBAAAAAAAAAAB+AAB+AAHngAPnwAMAwAMAwAMIwAMIwAMYwAM4wAM+wAN8wAMcwAMYwAMQwAMQwAMAwAMAwAP/wAH/gAAAAAAAAA=="},
|
||||
{name:"game", img:"GBiBAAAAAAAAAAAAAAA8AAB+AABmAABmAAB+AAA8AAAYAAAYAAAYAAMYAA//8B//+BgAGBgAGBgAGBgAGB//+A//8AAAAAAAAAAAAA=="},
|
||||
{name:"dice", img:"GBiBAAAAAB//8D//+HAAPGMDHmeHnmeHnmMDHmAAHmMDHmeHnmeHnmMDHmAAHmMDHmeHnmeHnmMDHnAAPn///j///h///g///AAAAA=="},
|
||||
{name:"gear", img:"GBiBAAAAAAAAAAA8AAB+AABmAA3nsA/D8B8A+Dg8HBx+OAznMAzDMAzDMAznMBx+ODg8HB8A+A/D8A3nsABmAAB+AAA8AAAAAAAAAA=="},
|
||||
{name:"wrench", img:"GBiBAAAAAAAAAAAAAAAHgAAfwAA7gAAzEABjOABj+ABh+ABgGADgMAHAcAOP4AcfgA44AB9wADHgADHAADGAAB8AAA4AAAAAAAAAAA=="},
|
||||
{name:"calendar", img:"FhgBDADAMAMP/////////////////////8AADwAAPAAA8AADwAAPAAA8AADwAAPAAA8AADwAAPAAA8AADwAAP///////"},
|
||||
{name:"power", img:"GBiBAAAAAAAAAAB+AAH/gAeBwA4YcAwYMBjbGBnbmDGZjDMYzDMYzDMAzDMAzDGBjBnDmBj/GAw8MA4AcAeB4AH/gAB+AAAAAAAAAA=="},
|
||||
{name:"terminal", img:"GBiBAAAAAAAAAAAAAA//8B//+B//+B//+B//+BgAGBgAGBgAGBmAGBjAGBhgGBhgGBjAGBmPmBgAGBgAGB//+A//8AAAAAAAAAAAAA=="},
|
||||
{name:"camera", img:"GBiBAAAAAAAAAAD/AAH/gAMAwD8A/H8A/mA8BmD/BmHDhmGBhmMAxmMAxmMAxmMAxmGBhmHDhmD/BmA8BmAABn///j///AAAAAAAAA=="},
|
||||
{name:"phone", img:"GBiBAAAAAAAAAAOAAA/AABzgADBgADBgADBgABjgABjAABzAAAxgAA5wAAc58AMf+AGHHADgDABwDAA8GAAfGAAH8AAA4AAAAAAAAA=="},
|
||||
{name:"two prong plug", img:"GBiBAAABgAADwAAHwAAPgACfAAHOAAPkBgHwDwP4Hwf8Pg/+fB//OD//kD//wD//4D//8D//4B//QB/+AD/8AH/4APnwAHAAACAAAA=="},
|
||||
{name:"steps", img:"GBiBAAcAAA+AAA/AAA/AAB/AAB/gAA/g4A/h8A/j8A/D8A/D+AfH+AAH8AHn8APj8APj8AHj4AHg4AADAAAHwAAHwAAHgAAHgAADAA=="},
|
||||
{name:"graph", img:"GBiBAAAAAAAAAAAAAAAAAAAAAADAAADAAAHAAAHjAAHjgAPngH9n/n82/gA+AAA8AAA8AAAcAAAYAAAYAAAAAAAAAAAAAAAAAAAAAA=="},
|
||||
{name:"hills", img:"GBiBAAAAAAAAAAAAAAAAAAAAAAACAAAGAAAPAAEZgAOwwAPwQAZgYAwAMBgAGBAACDAADGAABv///////wAAAAAAAAAAAAAAAAAAAA=="},
|
||||
{name:"sun", img:"GBiBAAAYAAAYAAAYAAgAEBwAOAx+MAD/AAHDgAMAwAcA4AYAYOYAZ+YAZwYAYAcA4AMAwAHDgAD/AAx+MBwAOAgAEAAYAAAYAAAYAA=="},
|
||||
{name:"home", img:"GBiBAAAAAAAAAAAAAAH/gAP/wAdg4A5wYA44MBwf+DgP/BgAGBgAGBgAGBnnmBnnmBnnmBnnmBngGBngGB//+B//+AAAAAAAAAAAAA=="},
|
||||
{name:"bell", img:"GBiBAAAAAAAAAAAfgAB/2ADw+AHAMAOAGAcAGD4ADHgADDgADBwADA4AHAcAGAOAOAHAcAPg4ANxwAM5gAP/AAHvAAAHAAACAAAAAA=="},
|
||||
{name:"bin", img:"GBiBAAAAAAAAAAB+AB//+B//+AwAMAwAMAxmMAZmYAZmYAZmYAZmYAZmYAZmYAZmYAZmYAZmYANmwAMAwAMAwAP/wAH/gAAAAAAAAA=="},
|
||||
];
|
||||
|
||||
let storedApps;
|
||||
var showMainMenu = () => {
|
||||
storedApps = storage.readJSON("clkshortcuts.json", 1) || {};
|
||||
|
||||
var mainMenu = {
|
||||
"": {
|
||||
title: "Shortcuts",
|
||||
},
|
||||
"< Back": () => {
|
||||
load();
|
||||
},
|
||||
"New": () => {
|
||||
// Select the app
|
||||
getSelectedApp().then((app) => {
|
||||
getSelectedIcon().then((icon) => {
|
||||
promptForRename(app.name).then((name) => {
|
||||
E.showMessage("Saving...");
|
||||
storedApps[app.src] = {
|
||||
name: name, src: app.src, icon: icon
|
||||
};
|
||||
storage.writeJSON("clkshortcuts.json", storedApps);
|
||||
showMainMenu();
|
||||
}).catch(() => {
|
||||
E.showMessage("Saving...");
|
||||
storedApps[app.src] = {
|
||||
name: app.name, src: app.src, icon: icon
|
||||
};
|
||||
storage.writeJSON("clkshortcuts.json", storedApps);
|
||||
showMainMenu();
|
||||
} );
|
||||
}).catch(() => {showMainMenu();});
|
||||
}).catch(() => {showMainMenu();});
|
||||
},
|
||||
};
|
||||
getStoredAppsArray(storedApps).forEach((app) => {
|
||||
mainMenu[app.name] = {
|
||||
onchange: () => {
|
||||
showEditMenu(app).then((dirty) => {
|
||||
if (dirty) {
|
||||
E.showMessage("Saving...");
|
||||
storage.writeJSON("clkshortcuts.json", storedApps);
|
||||
}
|
||||
showMainMenu();
|
||||
});
|
||||
},
|
||||
format: v=>"\0" + atob(app.icon)
|
||||
};
|
||||
});
|
||||
E.showMenu(mainMenu);
|
||||
};
|
||||
|
||||
var showEditMenu = (app) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
var editMenu = {
|
||||
"": {
|
||||
title: "Edit " + app.name,
|
||||
},
|
||||
"< Back": () => {
|
||||
resolve(false);
|
||||
},
|
||||
"Name":{
|
||||
onchange: () => {
|
||||
promptForRename(app.name).then((name) => {
|
||||
storedApps[app.src].name = name;
|
||||
resolve(true);
|
||||
}).catch();
|
||||
},
|
||||
format: v=>app.name.substring(0, 7)
|
||||
},
|
||||
"Icon": {
|
||||
onchange: () => {
|
||||
getSelectedIcon().then((icon) => {
|
||||
storedApps[app.src].icon = icon;
|
||||
resolve(true);
|
||||
}).catch(() => resolve(false));
|
||||
},
|
||||
format: v=>"\0" + atob(app.icon)
|
||||
},
|
||||
"Delete": {
|
||||
onchange: () => {
|
||||
delete storedApps[app.src]
|
||||
resolve(true);
|
||||
},
|
||||
format: v=>"\0" + atob("GBiBAAAAAAAAAAB+AB//+B//+AwAMAwAMAxmMAZmYAZmYAZmYAZmYAZmYAZmYAZmYAZmYAZmYANmwAMAwAMAwAP/wAH/gAAAAAAAAA==")
|
||||
}
|
||||
};
|
||||
E.showMenu(editMenu);
|
||||
});
|
||||
};
|
||||
|
||||
var promptForRename = (name) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!keyboard) { reject("No textinput is available"); }
|
||||
else {
|
||||
return require("textinput").input({text:name}).then((result) => resolve(result));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var getStoredAppsArray = (apps) => {
|
||||
var appList = Object.keys(apps);
|
||||
var storedAppArray = [];
|
||||
for (var i = 0; i < appList.length; i++) {
|
||||
var app = "" + appList[i];
|
||||
storedAppArray.push(
|
||||
apps[app]
|
||||
);
|
||||
}
|
||||
return storedAppArray;
|
||||
};
|
||||
|
||||
var getSelectedIcon = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
var iconMenu = {
|
||||
"": {
|
||||
title: "Select Icon",
|
||||
},
|
||||
"< Back": () => {
|
||||
reject("The user cancelled the operation");
|
||||
},
|
||||
};
|
||||
|
||||
icons.forEach((icon) => {
|
||||
iconMenu["\0" + atob(icon.img) + " " + icon.name] = () => {
|
||||
resolve(icon.img);
|
||||
};
|
||||
});
|
||||
|
||||
E.showMenu(iconMenu);
|
||||
});
|
||||
};
|
||||
|
||||
var getAppList = () => {
|
||||
var appList = storage
|
||||
.list(/\.info$/)
|
||||
.map((appInfoFileName) => {
|
||||
var appInfo = storage.readJSON(appInfoFileName, 1);
|
||||
return (
|
||||
appInfo && {
|
||||
name: appInfo.name,
|
||||
sortorder: appInfo.sortorder,
|
||||
src: appInfo.src,
|
||||
}
|
||||
);
|
||||
})
|
||||
.filter((app) => app && !!app.src);
|
||||
appList.sort((a, b) => {
|
||||
var n = (0 | a.sortorder) - (0 | b.sortorder);
|
||||
if (n) return n;
|
||||
if (a.name < b.name) return -1;
|
||||
if (a.name > b.name) return 1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
return appList;
|
||||
};
|
||||
|
||||
var getSelectedApp = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
E.showMessage("Loading apps...");
|
||||
var selectAppMenu = {
|
||||
"": {
|
||||
title: "Select App",
|
||||
},
|
||||
"< Back": () => {
|
||||
reject("The user cancelled the operation");
|
||||
},
|
||||
};
|
||||
|
||||
var appList = getAppList();
|
||||
appList.forEach((app) => {
|
||||
selectAppMenu[app.name] = () => {
|
||||
resolve(app);
|
||||
};
|
||||
});
|
||||
|
||||
E.showMenu(selectAppMenu);
|
||||
});
|
||||
};
|
||||
|
||||
showMainMenu();
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -0,0 +1,45 @@
|
|||
(function() {
|
||||
var storage = require("Storage");
|
||||
var storedApps = storage.readJSON("clkshortcuts.json", 1) || {};
|
||||
var items = [];
|
||||
if (Object.keys(storedApps).length !== 0) {
|
||||
for (var key in storedApps) {
|
||||
var source = {
|
||||
name: storedApps[key].name,
|
||||
img: storedApps[key].icon,
|
||||
src: storedApps[key].src,
|
||||
get : function() {
|
||||
return {
|
||||
text : this.name,
|
||||
img : atob(this.img)
|
||||
}
|
||||
},
|
||||
run: function() { load(this.src);},
|
||||
show : function() {},
|
||||
hide : function() {},
|
||||
}
|
||||
items.push(source);
|
||||
}
|
||||
}
|
||||
else {
|
||||
var source = {
|
||||
name: "Shortcuts",
|
||||
img: "GBiBAAAAAAAAAAAAAA//8B//+BgAGBgAGBgYGBgYGBgYGBgYGBn/mBn/mBgYGBgYGBgYGBgYGBgAGBgAGB//+A//8AAAAAAAAAAAAA==",
|
||||
src: "clkshortcuts.app.js",
|
||||
get : function() {
|
||||
return {
|
||||
text : this.name,
|
||||
img : atob(this.img)
|
||||
}
|
||||
},
|
||||
run: function() { load(this.src);},
|
||||
show : function() {},
|
||||
hide : function() {},
|
||||
};
|
||||
items = [source];
|
||||
}
|
||||
return {
|
||||
name: "Shortcuts",
|
||||
items: items
|
||||
};
|
||||
})
|
||||
|
After Width: | Height: | Size: 622 B |
|
|
@ -0,0 +1,17 @@
|
|||
{ "id": "clkshortcuts",
|
||||
"name": "Shortcuts",
|
||||
"shortName": "Shortcuts",
|
||||
"version": "0.01",
|
||||
"description": "Add shortcuts to launch your favourite apps straight from the Clock",
|
||||
"icon": "app.png",
|
||||
"screenshots": [{"url":"add_shortcuts_screenshot.png"}, {"url":"example_shortcuts_screenshot.png"}],
|
||||
"tags": "clkinfo,clockinfo",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{ "name": "clkshortcuts.app.js", "url": "app.js" },
|
||||
{ "name": "clkshortcuts.img", "url": "app-icon.js", "evaluate": true },
|
||||
{"name":"clkshortcuts.clkinfo.js","url":"clkinfo.js"}
|
||||
],
|
||||
"data": [{"name":"clkshortcuts.json"}]
|
||||
}
|
||||
|
|
@ -13,3 +13,4 @@
|
|||
0.12: Add drawFilledImage to allow drawing icons with a separately coloured middle
|
||||
0.13: Cache loaded ClockInfos so if we have clockInfoWidget and a clock, we don't load them twice (saves ~300ms)
|
||||
0.14: Check for .clkinfocache and use that if exists (from boot 0.64)
|
||||
0.15: Fix error when displaying a category with only one clockinfo (fix #3728)
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ exports.addInteractive = function(menu, options) {
|
|||
//in the worst case we come back to 0
|
||||
} while(menu[options.menuA].items.length==0);
|
||||
// When we change, ensure we don't display the same thing as another clockinfo if we can avoid it
|
||||
while ((options.menuB < menu[options.menuA].items.length) &&
|
||||
while ((options.menuB < menu[options.menuA].items.length-1) &&
|
||||
exports.clockInfos.some(m => (m!=options) && m.menuA==options.menuA && m.menuB==options.menuB))
|
||||
options.menuB++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{ "id": "clock_info",
|
||||
"name": "Clock Info Module",
|
||||
"shortName": "Clock Info",
|
||||
"version":"0.14",
|
||||
"version":"0.15",
|
||||
"description": "A library used by clocks to provide extra information on the clock face (Altitude, BPM, etc)",
|
||||
"icon": "app.png",
|
||||
"type": "module",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"version": "0.03",
|
||||
"description": "Displays RGB565 and RGB888 colors, its name and code in screen.",
|
||||
"icon": "app.png",
|
||||
"tags": "Color,input,buttons,touch,UI",
|
||||
"tags": "color,input,buttons,touch,ui",
|
||||
"supports": ["BANGLEJS"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
0.01: New App!
|
||||
0.02: update to my current preferences.
|
||||
0.03: update app list
|
||||
0.04: change app name "mysetup" -> "anotherconf"
|
||||
0.05: remove apps that are not "core" to the experience.
|
||||
0.06: change name "anotherconf" -> "confthyttan"
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
# Thyttan's Default Config
|
||||
|
||||
A different default set of apps and configurations. Brings many quality of life improvements. Opinionated based on the creators taste. Read more below before installing.
|
||||
|
||||
## Usage
|
||||
|
||||
Before installing do this:
|
||||
|
||||
1. Backup your current setup (via the "More..." tab of the App Loader) so you can restore it later if you want.
|
||||
2. Install this app (you'll be prompted about all data being removed from your Bangle)
|
||||
3. Try it out, switch out apps to your favorites and tweak to your liking!
|
||||
|
||||
## Features
|
||||
|
||||
There will not be a trace of a "Thyttan's Default Config" app on your watch after installation. Only the apps it installed and the configurations.
|
||||
|
||||
On the clock face:
|
||||
- Swipe right on the screen to open the launcher (Desktop Launcher) - or press the hardware button.
|
||||
- Swipe left to open a flashlight app.
|
||||
- Swipe up to open the messages.
|
||||
- Swipe down for quick access to music and podcast controls.
|
||||
- (Do a subsequent left or right swipe to enter the listed apps)
|
||||
- (Check out the "Quick Launch" app readme for more info)
|
||||
|
||||
## Requests
|
||||
|
||||
Add to the espruino/BangleApps issue tracker and mention @thyttan for bug reports and suggestions.
|
||||
|
||||
## Creator
|
||||
|
||||
thyttan
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
|
|
@ -0,0 +1 @@
|
|||
{"mode":0,"apps":[{"name":"Run+","src":"runplus.app.js","files":"runplus.info,runplus.app.js,runplus.img,runplus.settings.js,runplus_karvonen"}],"timeout":10}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"mode":0,"apps":[{"name":"Calculator","src":"calculator.app.js"},{"name":"SleepLog","src":"sleeplog.app.js"},{"name":"Messages","sortorder":-9,"src":"messagegui.app.js"},{"name":"Messages","sortorder":-9,"src":"messagegui.app.js","files":"messagegui.info,messagegui,messagegui.app.js,messagegui.new.js,messagegui.boot.js,messagegui.img"}],"standardNumSwipeHandlers":5,"standardNumDragHandlers":1}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"showClocks":true,"showLaunchers":true,"direct":false,"swipeExit":false,"timeOut":"15s"}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"buzzOnCharge":true,"monthFirst":true,"twentyFourH":true,"showAmPm":false,"showSeconds":true,"showWeather":false,"stepGoal":10000,"stepBar":true,"weekBar":true,"mondayFirst":true,"dayBar":true,"redrawOnStep":false}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{useAppHistory:true,disregardQuicklaunch:true,hideLoading:true}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{"colors":"011","image":"heart","touchOn":"always","oversize":7,"dragDelay":500,"minValue":0.01,"tapToLock":false,"unlockSide":"","tapSide":"","tapOn":"always","tOut":2000,"minFlash":0.2,"isOn":true,"value":0.9109}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{vibrateTimeout:10,vibrate:":",vibrateCalls:":::",flash:false}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
{ "id": "confthyttan",
|
||||
"name": "Thyttan's Default Config",
|
||||
"version":"0.06",
|
||||
"description": "A different default set of apps and configurations. Brings many quality of life improvements. Opinionated based on the creators taste. Read more below before installing.",
|
||||
"icon": "app.png",
|
||||
"type": "defaultconfig",
|
||||
"tags": "system,configuration,config,anotherconfig,thyttan",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"dependencies" : {
|
||||
"sched":"app",
|
||||
"kbmulti":"app",
|
||||
"messageicons":"app",
|
||||
"widmsggrid":"app",
|
||||
"msgwakefup":"app",
|
||||
"delaylock":"app",
|
||||
"notify":"app",
|
||||
"health":"app",
|
||||
"widminbate":"app",
|
||||
"podadrem":"app",
|
||||
"spotrem":"app",
|
||||
"android":"app",
|
||||
"widanclk":"app",
|
||||
"backswipe":"app",
|
||||
"torch":"app",
|
||||
"calculator":"app",
|
||||
"widbt_notify":"app",
|
||||
"smpltmr":"app",
|
||||
"clkinfostopw":"app",
|
||||
"runplus":"app",
|
||||
"dtlaunch":"app",
|
||||
"quicklaunch":"app",
|
||||
"kineticscroll":"app",
|
||||
"alarm":"app",
|
||||
"recorder":"app",
|
||||
"agenda":"app",
|
||||
"edgeclk":"app",
|
||||
"autoreset":"app",
|
||||
"chargent":"app",
|
||||
"setting":"app",
|
||||
"fastload":"app",
|
||||
"boot":"app",
|
||||
"ateatimer":"app",
|
||||
"drained":"app"
|
||||
},
|
||||
"storage": [
|
||||
{"name":"backswipe.json",
|
||||
"url":"backswipe.json"},
|
||||
{"name":"autoreset.json",
|
||||
"url":"autoreset.json"},
|
||||
{"name":"dtlaunch.json",
|
||||
"url":"dtlaunch.json"},
|
||||
{"name":"fastload.json",
|
||||
"url":"fastload.json"},
|
||||
{"name":"quicklaunch.json",
|
||||
"url":"quicklaunch.json"},
|
||||
{"name":"messages.settings.json",
|
||||
"url":"messages.settings.json"},
|
||||
{"name":"widbt_notify.json",
|
||||
"url":"widbt_notify.json"},
|
||||
{"name":"recorder.json",
|
||||
"url":"recorder.json"},
|
||||
{"name":"edgeclk.settings.json",
|
||||
"url":"edgeclk.settings.json"},
|
||||
{"name":"setting.json",
|
||||
"url":"setting.json"}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{lapp:{name:"Show Launcher",sortorder:-12,src:"no source"},rapp:{name:"torch",type:"app",sortorder:-11,src:"torch.app.js"},uapp:{name:"Messages",sortorder:-9,src:"messagegui.app.js"},dapp:{name:"Extension",type:"app",sortorder:-11,src:"quicklaunch.app.js"},tapp:{name:""},dlapp:{name:"PA Remote",src:"podadrem.app.js"},drapp:{name:"Remote for Spotify",src:"spotrem.app.js"},duapp:{name:""},ddapp:{name:"Extension",type:"app",sortorder:-11,src:"quicklaunch.app.js"},dtapp:{name:""},ddlapp:{name:"Alarms",src:"alarm.app.js"},ddrapp:{name:"Run+",src:"runplus.app.js"},dduapp:{name:""},dddapp:{name:"Agenda",src:"agenda.app.js"},ddtapp:{name:""},rlapp:{name:""},rrapp:{name:""},ruapp:{name:""},rdapp:{name:""},rtapp:{name:""},trace:"dr"}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{recording:false,period:10,record:["gps","hrm","steps"],file:"recorder.log0.csv"}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{ble:true,blerepl:true,log:false,quiet:0,timeout:10,vibrate:true,beep:true,timezone:2,HID:false,clock:"edgeclk.app.js","12hour":false,firstDayOfWeek:1,brightness:0.5,options:{wakeOnBTN1:true,wakeOnBTN2:true,wakeOnBTN3:true,wakeOnFaceUp:false,wakeOnTouch:false,wakeOnTwist:false,twistThreshold:819.2,twistMaxY:-800,twistTimeout:1000,btnLoadTimeout:700},theme:{fg:65535,bg:0,fg2:65535,bg2:8,fgH:65535,bgH:31,dark:true},clockHasWidgets:true,launcher:"dtlaunch.app.js",touch:{x1:6,y1:14,x2:197,y2:178}}
|
||||
|
|
@ -0,0 +1 @@
|
|||
{showWidget:true,buzzOnConnect:false,buzzOnLoss:false,hideConnected:false,showMessage:false,nextBuzz:30000}
|
||||
|
|
@ -2,3 +2,4 @@
|
|||
0.02: Added Settings & readme
|
||||
0.03: Fix lint warnings
|
||||
0.04: Fix lint warnings
|
||||
0.05: Fix on not reading counter defaults in Settings
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "counter2",
|
||||
"name": "Counter2",
|
||||
"version": "0.04",
|
||||
"version": "0.05",
|
||||
"description": "Dual Counter",
|
||||
"readme":"README.md",
|
||||
"icon": "counter2-icon.png",
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
"": { "title": "Counter2" },
|
||||
"< Back": () => back(),
|
||||
'Default C1': {
|
||||
value: settings[0],
|
||||
value: settings.max0,
|
||||
min: -99, max: 99,
|
||||
onchange: v => {
|
||||
settings.max0 = v;
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
}
|
||||
},
|
||||
'Default C2': {
|
||||
value: settings[2],
|
||||
value: settings.max1,
|
||||
min: -99, max: 99,
|
||||
onchange: v => {
|
||||
settings.max1 = v;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
"version":"0.01",
|
||||
"description": "Delay the locking of the screen to 5 seconds after the backlight turns off.",
|
||||
"icon": "app.png",
|
||||
"tags": "settings, configuration, backlight, touchscreen, screen",
|
||||
"tags": "settings,configuration,backlight,touchscreen,screen",
|
||||
"type": "bootloader",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
"icon": "app.png",
|
||||
"version": "0.01",
|
||||
"type": "clock",
|
||||
"tags": "clock, weather, dino, trex, chrome",
|
||||
"tags": "clock,weather,dino,trex,chrome",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"allow_emulator": true,
|
||||
"readme": "README.md",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
"version": "0.02",
|
||||
"description": "Follow The Recipe (FTR) is a bangle.js app to follow a recipe step by step",
|
||||
"type": "app",
|
||||
"tags": "tool, tools, cook",
|
||||
"tags": "tool,tools,cook",
|
||||
"supports": [
|
||||
"BANGLEJS2"
|
||||
],
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"description": "A simple way to initiate Google Assistant on Android. Intents must be enabled in Gadgetbridge.",
|
||||
"icon": "app.png",
|
||||
"type": "app",
|
||||
"tags": "tool, voice, tasker",
|
||||
"tags": "tool,voice,tasker",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"allow_emulator": false,
|
||||
"storage": [
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"version":"0.01",
|
||||
"description": "Disconnect from your android device by running this app. The app will forward you to your clock face immediately after triggering the command. (Gadgetbridge nightly required until version 82 is released)",
|
||||
"icon": "app.png",
|
||||
"tags": "android, gadgetbridge, bluetooth, bt",
|
||||
"tags": "android,gadgetbridge,bluetooth,bt",
|
||||
"supports" : ["BANGLEJS", "BANGLEJS2"],
|
||||
"storage": [
|
||||
{"name":"gbdiscon.app.js","url":"app.js"},
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
"version": "0.03",
|
||||
"description": "This app will provide you with on course data to support your golf game!",
|
||||
"icon": "golfview.png",
|
||||
"tags": "outdoors, gps",
|
||||
"tags": "outdoors,gps",
|
||||
"allow_emulator": true,
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"version": "0.03",
|
||||
"description": "Wrist mounted guitar chords",
|
||||
"icon": "app.png",
|
||||
"tags": "guitar, chords",
|
||||
"tags": "guitar,chords",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"description": "Songs lyrics and guitar chords",
|
||||
"icon": "app.png",
|
||||
"screenshots": [{"url": "screenshot.png"}],
|
||||
"tags": "guitar, song, lyrics, chords",
|
||||
"tags": "guitar,song,lyrics,chords",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"interface": "manage_songs.html",
|
||||
"readme": "README.md",
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
/* eslint-env node */
|
||||
|
||||
var imageconverter = require("../../../webtools/imageconverter.js").imageconverter;
|
||||
var imageconverter = require("../../../webtools/imageconverter.js");
|
||||
var icons = JSON.parse(require("fs").readFileSync(__dirname+"/icon_names.json"));
|
||||
const imgOptions = {
|
||||
mode : "1bit",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"icon": "app.png",
|
||||
"version":"0.01",
|
||||
"description": "Interval Timer for workouts, HIIT, or whatever else.",
|
||||
"tags": "timer, interval, hiit, workout",
|
||||
"tags": "timer,interval,hiit,workout",
|
||||
"readme":"README.md",
|
||||
"supports":["BANGLEJS2"],
|
||||
"storage": [
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"version": "0.04",
|
||||
"description": "A clock that displays the great wave of kanagawa (image from wikipedia) with seconds in active mode.",
|
||||
"icon": "app.png",
|
||||
"tags": "clock, kanagawa, wave",
|
||||
"tags": "clock,kanagawa,wave",
|
||||
"type": "clock",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ var locales = {
|
|||
ampm: { 0: "am", 1: "pm" },
|
||||
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||
datePattern: { 0: "%d %B %Y", "1": "%d/%m/%Y" }, // 1 mars 2020 // 01/03/2020
|
||||
abmonth: "janv,févr,mars,avril,mai,juin,juil,août,sept,oct,nov,déc",
|
||||
abmonth: "janv,févr,mars,avr,mai,juin,juil,août,sept,oct,nov,déc",
|
||||
month: "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre",
|
||||
abday: "dim,lun,mar,mer,jeu,ven,sam",
|
||||
day: "dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi",
|
||||
|
|
@ -423,7 +423,7 @@ var locales = {
|
|||
ampm: { 0: "am", 1: "pm" },
|
||||
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||
datePattern: { 0: "%A %B %d %Y", "1": "%d/%m/%y" }, // dimanche 1 mars 2020 // 01/03/20
|
||||
abmonth: "janv.,févr.,mars,avril,mai,juin,juil.,août,sept.,oct.,nov.,déc.",
|
||||
abmonth: "janv,févr,mars,avr,mai,juin,juil,août,sept,oct,nov,déc",
|
||||
month: "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre",
|
||||
abday: "dim,lun,mar,mer,jeu,ven,sam",
|
||||
day: "dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi",
|
||||
|
|
@ -452,7 +452,7 @@ var locales = {
|
|||
speed: "kmh",
|
||||
distance: { 0: "m", 1: "km" },
|
||||
temperature: "°C",
|
||||
ampm: { 0: "vorm", 1: " nachm" },
|
||||
ampm: { 0: "vorm", 1: "nachm" },
|
||||
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||
datePattern: { 0: "%A, %d. %B %Y", "1": "%d.%m.%Y" }, // Sonntag, 1. März 2020 // 1.3.2020
|
||||
abmonth: "Jan,Feb,März,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez",
|
||||
|
|
@ -471,7 +471,7 @@ var locales = {
|
|||
ampm: { 0: "AM", 1: "PM" },
|
||||
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||
datePattern: { 0: "%A %d %B %Y", "1": "%d/%m/%y" }, // dimanche 1 mars 2020 // 01/03/20
|
||||
abmonth: "janv.,févr.,mars,avril,mai,juin,juil.,août,sept.,oct.,nov.,déc.",
|
||||
abmonth: "janv,févr,mars,avr,mai,juin,juil,août,sept,oct,nov,déc",
|
||||
month: "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre",
|
||||
abday: "dim,lun,mar,mer,jeu,ven,sam",
|
||||
day: "dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi",
|
||||
|
|
@ -567,7 +567,7 @@ var locales = {
|
|||
ampm: { 0: "am", 1: "pm" },
|
||||
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||
datePattern: { 0: "%A %d %B de %Y", "1": "%d/%m/%Y" }, // dimenge 1 de març de 2020 // 01/03/2020
|
||||
abmonth: "gen.,febr.,març,abril,mai,junh,julh,ago.,set.,oct.,nov.,dec.",
|
||||
abmonth: "gen,febr,març,abril,mai,junh,julh,ago,set,oct,nov,dec",
|
||||
month: "genièr,febrièr,març,abril,mai,junh,julhet,agost,setembre,octòbre,novembre,decembre",
|
||||
abday: "dg,dl,dm,dc,dj,dv,ds",
|
||||
day: "dimenge,diluns,dimars,dimècres,dijòus,divendres,dissabte",
|
||||
|
|
@ -612,10 +612,10 @@ var locales = {
|
|||
speed: "km/h",
|
||||
distance: { 0: "m", 1: "km" },
|
||||
temperature: "°C",
|
||||
ampm: { 0: "dop.", 1: "pop." },
|
||||
ampm: { 0: "dop", 1: "pop" },
|
||||
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||
datePattern: { 0: "%-d. %b %Y", 1: "%-d.%-m.%Y" }, // "3. jan. 2020" // "3.1.2020"(short)
|
||||
abmonth: "sij.,velj.,ožu.,tra.,svi,lip.,srp.,kol.,ruj.,lis.,stu.,pro.",
|
||||
abmonth: "sij,velj,ožu,tra,svi,lip,srp,kol,ruj,lis,stu,pro",
|
||||
month: "siječanj,veljača,ožujak,travanj,svibanj,lipanj,srpanj,kolovoz,rujan,listopad,studeni,prosinac",
|
||||
abday: "ned.,pon.,uto.,sri.,čet.,pet.,sub.",
|
||||
day: "nedjelja,ponedjeljak,utorak,srijeda,četvrtak,petak,subota",
|
||||
|
|
@ -628,7 +628,7 @@ var locales = {
|
|||
speed: "km/h",
|
||||
distance: { 0: "m", 1: "km" },
|
||||
temperature: "°C",
|
||||
ampm: { 0: "dop.", 1: "pop." },
|
||||
ampm: { 0: "dop", 1: "pop" },
|
||||
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||
datePattern: { 0: "%-d. %b %Y", 1: "%-d.%-m.%Y" }, // "3. jan. 2020" // "3.1.2020"(short)
|
||||
abmonth: "jan.,feb.,mar.,apr.,maj,jun.,jul.,avg.,sep.,okt.,nov.,dec.",
|
||||
|
|
@ -728,7 +728,7 @@ var locales = {
|
|||
ampm: { 0: "am", 1: "pm" },
|
||||
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||
datePattern: { 0: "%d %B %Y", "1": "%d/%m/%y" },
|
||||
abmonth: "gen.,febr.,març,abr.,maig,juny,jul.,ag.,set.,oct.,nov.,des.",
|
||||
abmonth: "gen,febr,març,abr,maig,juny,jul,ag,set,oct,nov,des",
|
||||
month: "gener,febrer,març,abril,maig,juny,juliol,agost,setembre,octubre,novembre,desembre",
|
||||
abday: "dg.,dl.,dt.,dc.,dj.,dv.,ds.",
|
||||
day: "diumenge,dilluns,dimarts,dimecres,dijous,divendres,dissabte",
|
||||
|
|
|
|||
|
|
@ -15,6 +15,6 @@
|
|||
{"name":"messagesoverlay.settings.js","url":"settings.js"},
|
||||
{"name":"messagesoverlay.default.json","url":"default.json"}
|
||||
],
|
||||
"data": [{"name":"bthrm.json"}],
|
||||
"data":[{"name":"messagesoverlay.json"}],
|
||||
"screenshots": [{"url":"screen_call.png"} ,{"url":"screen_message.png"} ]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,3 +30,8 @@
|
|||
1.28: increased vibration strength, added some comments, & some QOL
|
||||
1.29: changed image
|
||||
1.30: changed image, again
|
||||
1.40: added various settings for controlling when & how to throw dice
|
||||
1.41: fixed dumb mistake
|
||||
1.42: okay maby I should've read the *whole* error log
|
||||
1.43: playing whackamole with ESLint
|
||||
1.44: fixed (?) settings app
|
||||
|
|
|
|||
|
|
@ -1,12 +1,20 @@
|
|||
var menu = true; // default to have the selection menu open
|
||||
var settings = Object.assign({
|
||||
vibrate: true,
|
||||
shake: true,
|
||||
screen: false,
|
||||
shake_timeout: 200,
|
||||
shake_duration: 100,
|
||||
}, require('Storage').readJSON("multidice.json", true) || {});
|
||||
|
||||
var menu = true; // defaults to having the menu open
|
||||
const DICE_ARRAY = [0, 4, 6, 8, 10, 12, 20, 100]; // 0 means nothing selected
|
||||
const SELECTION_ARRAY = [6, 0, 0, 0, 0, 0, 0, 0]; // default to selecting a single d20
|
||||
|
||||
// function to draw the selection menu
|
||||
function drawMenu() {
|
||||
|
||||
stringArr = new Array ("", "", "", "", "", "", "", "");
|
||||
for (i = 0; i < 8; i++) {
|
||||
var stringArr = new Array ("", "", "", "", "", "", "", "");
|
||||
for (var i = 0; i < 8; i++) {
|
||||
|
||||
if (SELECTION_ARRAY [i] != 0) {
|
||||
|
||||
|
|
@ -41,6 +49,7 @@ function touchHandler (button, xy) {
|
|||
return;
|
||||
}
|
||||
|
||||
var selection;
|
||||
if (xy.x <= 87) { // left
|
||||
|
||||
if (xy.y <= 43) { // first
|
||||
|
|
@ -84,15 +93,30 @@ function touchHandler (button, xy) {
|
|||
drawMenu();
|
||||
}
|
||||
|
||||
var shaken = false;
|
||||
var last_shaken = null;
|
||||
function accelHandler (xyz) {
|
||||
|
||||
// if the screen should be on *and* it isn't, return
|
||||
if (settings.screen && ! Bangle.isBacklightOn()) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (xyz.diff >= 0.3) {
|
||||
|
||||
menu = false;
|
||||
mutex (rollDice).catch (() => {
|
||||
shaken = true;
|
||||
last_shaken = Date.now();
|
||||
} else if (shaken && last_shaken !== null) {
|
||||
|
||||
return; // not necessary, but prevents spamming the logs
|
||||
});
|
||||
if (Date.now() - last_shaken > settings.shake_timeout) {
|
||||
|
||||
last_shaken = null;
|
||||
shaken = false;
|
||||
menu = false;
|
||||
|
||||
mutex (rollDice).catch (() => { return; });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -123,8 +147,8 @@ function mutex (functionRef) {
|
|||
// function to roll all selected dice, and display them
|
||||
function rollDice() {
|
||||
|
||||
resultsArr = new Uint8Array (8);
|
||||
for (i = 0; i < 8; i++) {
|
||||
var resultsArr = new Uint8Array (8);
|
||||
for (var i = 0; i < 8; i++) {
|
||||
|
||||
if (SELECTION_ARRAY [i] != 0) {
|
||||
|
||||
|
|
@ -135,7 +159,7 @@ function rollDice() {
|
|||
g.clear();
|
||||
g.setFont ("Vector", 40);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (var i = 0; i < 4; i++) {
|
||||
|
||||
if (SELECTION_ARRAY [i] != 0) {
|
||||
|
||||
|
|
@ -143,7 +167,7 @@ function rollDice() {
|
|||
}
|
||||
}
|
||||
|
||||
for (i = 4; i < 8; i++) {
|
||||
for (var i = 4; i < 8; i++) {
|
||||
|
||||
if (SELECTION_ARRAY [i] != 0) {
|
||||
|
||||
|
|
@ -157,14 +181,19 @@ function rollDice() {
|
|||
// triggers the vibration, then pauses before returning
|
||||
function vibrate() {
|
||||
|
||||
if (! settings.vibrate) {
|
||||
|
||||
return (Promise.resolve (0));
|
||||
}
|
||||
|
||||
return new Promise ((resolve, reject) => {
|
||||
|
||||
return Bangle.buzz (50, 1).then ((value) => {
|
||||
return Bangle.buzz (settings.shake_duration, 1).then ((value) => {
|
||||
|
||||
setTimeout (() => {
|
||||
|
||||
resolve (value);
|
||||
}, 200);
|
||||
}, 2 * settings.shake_duration + settings.shake_timeout);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -177,7 +206,7 @@ function random (max) {
|
|||
|
||||
drawMenu();
|
||||
Bangle.on ('touch', touchHandler);
|
||||
Bangle.on ('accel', accelHandler);
|
||||
if (settings.shake) { Bangle.on ('accel', accelHandler); }
|
||||
setWatch (function() {
|
||||
|
||||
menu = false;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{ "id": "multidice",
|
||||
"name": "multiple dice roller",
|
||||
"shortName":"multidice",
|
||||
"version":"1.30",
|
||||
"version":"1.44",
|
||||
"description": "roll anywhere from 1-8 dice at the same time",
|
||||
"icon": "app.png",
|
||||
"tags": "tool,game",
|
||||
|
|
@ -10,6 +10,8 @@
|
|||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{"name":"multidice.app.js","url":"app.js"},
|
||||
{"name":"multidice.settings.js","url":"settings.js"},
|
||||
{"name":"multidice.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
],
|
||||
"data": [{"name": "multidice.json"}]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
(function(back) {
|
||||
var settings = Object.assign({
|
||||
vibrate: true,
|
||||
shake: true,
|
||||
screen: false,
|
||||
shake_timeout: 200,
|
||||
shake_duration: 100,
|
||||
}, require('Storage').readJSON("multidice.json", true) || {});
|
||||
|
||||
function writeSettings() {
|
||||
require('Storage').writeJSON("multidice.json", settings);
|
||||
}
|
||||
|
||||
// Show the menu
|
||||
E.showMenu({
|
||||
"" : { "title" : "multi dice roll" },
|
||||
"< Back" : () => back(),
|
||||
'vibrate on roll?': {
|
||||
value: !!settings.vibrate,
|
||||
onchange: v => {
|
||||
settings.vibrate = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'allow shaking?': {
|
||||
value: !!settings.shake,
|
||||
onchange: v => {
|
||||
settings.shake = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'screen on to shake?': {
|
||||
value: !!settings.screen,
|
||||
onchange: v => {
|
||||
settings.screen = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'shake timeout': {
|
||||
value: settings.shake_timeout / 5,
|
||||
min: 10, max: 40,
|
||||
format: v => v * 5,
|
||||
onchange: v => {
|
||||
settings.shake_timeout = v * 5;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'shake duration': {
|
||||
value: settings.shake_duration / 5,
|
||||
min: 10, max: 40,
|
||||
format: v => v * 5,
|
||||
onchange: v => {
|
||||
settings.shake_duration = v * 5;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
"description": "A smart and simple calculator for Ohm's Law calculations, designed specifically for Bangle.js 2 smartwatches. Handles voltage, current, resistance, and power calculations with smart logic to prevent invalid inputs.",
|
||||
"icon": "app.png",
|
||||
"type": "app",
|
||||
"tags": "calculator, utilities, electric",
|
||||
"tags": "calculator,utilities,electric",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
"dependencies": {"mylocation":"app","weather":"app"},
|
||||
"screenshots": [{"url":"screenshot_pastel.png"}, {"url":"weather_icons.png"}],
|
||||
"type": "clock",
|
||||
"tags": "clock, weather, tool",
|
||||
"tags": "clock,weather,tool",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"version": "0.05",
|
||||
"description": "Simple app to power off your Bangle.js",
|
||||
"icon": "app.png",
|
||||
"tags": "tool, poweroff, shutdown",
|
||||
"tags": "tool,poweroff,shutdown",
|
||||
"supports" : ["BANGLEJS", "BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"version": "0.16",
|
||||
"description": "Tap or swipe left/right/up/down on your clock face to launch up to five apps of your choice. Configurations can be accessed through Settings->Apps.",
|
||||
"type": "bootloader",
|
||||
"tags": "tools, system",
|
||||
"tags": "tools,system",
|
||||
"readme": "README.md",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"storage": [
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
{"url": "screenshot-2.png"}
|
||||
],
|
||||
"description": "An intuitive, easy-to-use app that aids in the interpretation of resistor color codes and calculation of resistance values.",
|
||||
"tags": "app, tool, electricity, ohms, converter",
|
||||
"tags": "app,tool,electricity,ohms,converter",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ Alarms are stored in an array in `sched.json`, and take the form:
|
|||
// e.g. repeat every 2 months: { interval: "month", num: 2 }.
|
||||
// Supported intervals: day, week, month, year
|
||||
vibrate : "...", // OPTIONAL pattern of '.', '-' and ' ' to use for when buzzing out this alarm (defaults to '..' if not set)
|
||||
hidden : false, // OPTIONAL if false, the widget should not show an icon for this alarm
|
||||
hidden : false, // OPTIONAL if true, the widget should not show an icon for this alarm
|
||||
as : false, // auto snooze
|
||||
timer : 5*60*1000, // OPTIONAL - if set, this is a timer and it's the time in ms
|
||||
del : false, // OPTIONAL - if true, delete the timer after expiration
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
"description": "A keyboard on your wrist! Swipe right for space, left for delete.",
|
||||
"icon": "app.png",
|
||||
"allow_emulator": true,
|
||||
"tags": "tools, keyboard, text, scribble",
|
||||
"tags": "tools,keyboard,text,scribble",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"description": "A basic implementation of the famous consice workout",
|
||||
"icon": "icon.png",
|
||||
"type":"app",
|
||||
"tags": "Training, Workout",
|
||||
"tags": "training,workout",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"allow_emulator":true,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"description": "Watch face in the style of Casio Prototype Space Resist",
|
||||
"icon": "app-icon.png",
|
||||
"type": "clock",
|
||||
"tags": "clock, casio, retro",
|
||||
"tags": "clock,casio,retro",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"description": "Navigate between clock and launcher with Swipe action",
|
||||
"icon": "swiperclocklaunch.png",
|
||||
"type": "bootloader",
|
||||
"tags": "tools, system",
|
||||
"tags": "tools,system",
|
||||
"supports": ["BANGLEJS", "BANGLEJS2"],
|
||||
"storage": [
|
||||
{"name":"swiperclocklaunch.boot.js","url":"boot.js"},
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
"description": "Tamagotchi WatchApp",
|
||||
"icon": "app.png",
|
||||
"allow_emulator": true,
|
||||
"tags": "clock, watch, virtual pet",
|
||||
"tags": "clock,watch,virtualpet",
|
||||
"supports": [
|
||||
"BANGLEJS2"
|
||||
],
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"version": "0.08",
|
||||
"description": "App to test the bangle.js input interface. It displays the user action in text, circle buttons or on/off switch UI elements.",
|
||||
"icon": "app.png",
|
||||
"tags": "input,interface,buttons,touch,UI",
|
||||
"tags": "input,interface,buttons,touch,ui",
|
||||
"supports": ["BANGLEJS"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
"description": "Conveniently record a series of date/time stamps",
|
||||
"screenshots": [ {"url": "screenshot.png" } ],
|
||||
"readme": "README.md",
|
||||
"tags": "timestamp, log",
|
||||
"tags": "timestamp,log",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"interface": "interface.html",
|
||||
"storage": [
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
"description": "Draw stuff in your wrist",
|
||||
"icon": "app.png",
|
||||
"allow_emulator": true,
|
||||
"tags": "tools, keyboard, text, scribble",
|
||||
"tags": "tools,keyboard,text,scribble",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
0.01: New App!
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# txtreader
|
||||
|
||||
Very basic text reader with an integrated file selector.
|
||||
|
||||
## Features
|
||||
|
||||
- select files from storage (.txt)
|
||||
- display their contents
|
||||
- browse pages
|
||||
|
||||
## Controls
|
||||
|
||||
Bangle.js 2
|
||||
- tap the right side of the screen to flip to the next page
|
||||
- tap the left side of the screen to flip to the previous page
|
||||
- exit by pressing the physical button
|
||||
|
||||
## Creator
|
||||
|
||||
<https://topkekker.rip/>
|
||||
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwwkCkQA/AH4A/AAcosd2m9jw04AQlyC5WL1e63YCG3lUC5WPj/x/8f+H/h4CBj/3jYXLv/3/4CCt4FC/IXM/4AI/YXk/WZzOfCgWfAoIXN/F3u9/C4V/AoIvUI6H3F4p3oC6/73e734XTR4wXQ/vd7vfC6f85gAG55HQAAppBC5n5xAAGz4vmzIAGF/33F49/C5v6F4+vC5rrFd6JHCv4XTI4WfF6lms1vF6mq1WvC6Z3WxfdABHVugXKlFUogAHoVCC5QA/AH4A6A"))
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
function showFileSelector() {
|
||||
let files = require("Storage").list().filter(f => f.endsWith('.txt'));
|
||||
|
||||
let menuItems = {};
|
||||
files.forEach(file => {
|
||||
menuItems[file] = () => {
|
||||
E.showPrompt(`Select ${file}?`).then(confirm => {
|
||||
if (confirm) {
|
||||
onFileSelected(file);
|
||||
} else {
|
||||
showFileSelector();
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
menuItems['< Back'] = () => { load(); };
|
||||
E.showMenu(menuItems);
|
||||
}
|
||||
|
||||
function onFileSelected(file) {
|
||||
const chunkSize = 1024;
|
||||
let currentOffset = 0;
|
||||
let currentPage = 1;
|
||||
let history = [];
|
||||
|
||||
function displayText(offset, pageNumber) {
|
||||
g.clear();
|
||||
g.setFont("6x8", 1);
|
||||
g.setColor(g.theme.fg);
|
||||
g.drawString("Page " + pageNumber, 10, 2);
|
||||
//g.drawString("Offset " + offset, 60, 2);
|
||||
g.drawString(file, g.getWidth() - file.length * 6, 2);
|
||||
|
||||
var text = require("Storage").read(file, offset, chunkSize);
|
||||
var lines = text.split("\n");
|
||||
var y = 15; // Text start, top row reserved for page number
|
||||
var linesDisplayed = 0; // Lines per page
|
||||
var totalCharsDisplayed = 0; // Total characters per page
|
||||
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
var wrappedLines = g.wrapString(lines[i], g.getWidth() - 20);
|
||||
for (var j = 0; j < wrappedLines.length; j++) {
|
||||
g.drawString(wrappedLines[j], 10, y);
|
||||
y += 10; // Move down for the next line
|
||||
linesDisplayed++;
|
||||
totalCharsDisplayed += wrappedLines[j].length + (j < wrappedLines.length - 1 ? 0 : 1); // Add newline character for the last wrapped line
|
||||
if (y >= g.getHeight() - 10) {
|
||||
// If we run out of space, stop drawing
|
||||
return { nextOffset: offset + totalCharsDisplayed, linesDisplayed: linesDisplayed };
|
||||
}
|
||||
}
|
||||
}
|
||||
return null; // No more lines to display
|
||||
}
|
||||
|
||||
// Initial display
|
||||
var result = displayText(currentOffset, currentPage);
|
||||
history.push({ offset: currentOffset, linesDisplayed: result.linesDisplayed });
|
||||
|
||||
// Handle touch events
|
||||
Bangle.on('touch', function(button) {
|
||||
if (button === 2) { // Right side of the screen (next page)
|
||||
var nextOffset = displayText(currentOffset, currentPage + 1);
|
||||
if (nextOffset !== null) {
|
||||
currentOffset = nextOffset.nextOffset;
|
||||
currentPage++;
|
||||
history.push({ offset: currentOffset, linesDisplayed: nextOffset.linesDisplayed });
|
||||
displayText(currentOffset, currentPage);
|
||||
} else {
|
||||
currentOffset = 0;
|
||||
currentPage = 1;
|
||||
history = [{ offset: currentOffset, linesDisplayed: result.linesDisplayed }];
|
||||
displayText(currentOffset, currentPage);
|
||||
}
|
||||
} else if (button === 1) { // Left side of the screen (previous page)
|
||||
if (currentPage > 1) {
|
||||
history.pop(); // Remove current page from history
|
||||
var previousPage = history[history.length - 1];
|
||||
currentOffset = previousPage.offset;
|
||||
currentPage--;
|
||||
displayText(currentOffset, currentPage);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
showFileSelector();
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"id": "txtreader",
|
||||
"name": "txtreader",
|
||||
"shortName": "txtreader",
|
||||
"version": "0.01",
|
||||
"description": "Basic text reader with pages and a file selector.",
|
||||
"icon": "txtreader.png",
|
||||
"screenshots": [{"url":"screenshot_txtreader.png"}],
|
||||
"tags": "app,tool",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"txtreader.app.js","url":"app.js"},
|
||||
{"name":"txtreader.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
|
@ -8,7 +8,7 @@
|
|||
"dependencies": {"weather":"app"},
|
||||
"screenshots": [{"url":"screens/screen1.png"}],
|
||||
"type": "clock",
|
||||
"tags": "clock, weather",
|
||||
"tags": "clock,weather",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"allow_emulator": true,
|
||||
"readme": "README.md",
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
"description": "Lock a Bangle 2 screen by tapping a widget.",
|
||||
"icon": "widget.png",
|
||||
"type": "widget",
|
||||
"tags": "widget, screenlock",
|
||||
"tags": "widget,screenlock",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
|
|
|
|||
|
|
@ -2,6 +2,31 @@
|
|||
/* Checks for any obvious problems in apps.json
|
||||
*/
|
||||
|
||||
var BASEDIR = __dirname+"/../";
|
||||
var APPSDIR_RELATIVE = "apps/";
|
||||
var APPSDIR = BASEDIR + APPSDIR_RELATIVE;
|
||||
var showAllErrors = process.argv.includes("--show-all");
|
||||
|
||||
if (process.argv.includes("--help")) {
|
||||
console.log(`BangleApps Sanity Check
|
||||
------------------------
|
||||
|
||||
Checks apps in this repository for common issues that might
|
||||
cause problems.
|
||||
|
||||
USAGE:
|
||||
|
||||
bin/sanitycheck.js
|
||||
- default, runs all tests (hides known errors)
|
||||
bin/sanitycheck.js --show-all
|
||||
- show all warnings/errors (including known ones)
|
||||
bin/sanitycheck.js --help
|
||||
- show this message
|
||||
`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
|
||||
var fs = require("fs");
|
||||
var vm = require("vm");
|
||||
var heatshrink = require("../webtools/heatshrink");
|
||||
|
|
@ -27,40 +52,42 @@ var jsparse = (() => {
|
|||
return str => acorn.parse(str, { ecmaVersion: 2020 });
|
||||
})();
|
||||
|
||||
var BASEDIR = __dirname+"/../";
|
||||
var APPSDIR_RELATIVE = "apps/";
|
||||
var APPSDIR = BASEDIR + APPSDIR_RELATIVE;
|
||||
|
||||
var knownWarningCount = 0;
|
||||
var knownErrorCount = 0;
|
||||
var warningCount = 0;
|
||||
var errorCount = 0;
|
||||
var warningList = [];
|
||||
var errorList = [];
|
||||
|
||||
function ERROR(msg, opt) {
|
||||
// file=app.js,line=1,col=5,endColumn=7
|
||||
opt = opt||{};
|
||||
errorList.push(msg);
|
||||
if (KNOWN_ERRORS.includes(msg)) {
|
||||
console.log(`Known error : ${msg}`);
|
||||
knownErrorCount++;
|
||||
} else {
|
||||
if (!showAllErrors) return;
|
||||
msg += " (KNOWN)"
|
||||
}
|
||||
console.log(`::error${Object.keys(opt).length?" ":""}${Object.keys(opt).map(k=>k+"="+opt[k]).join(",")}::${msg}`);
|
||||
errorCount++;
|
||||
}
|
||||
}
|
||||
function WARN(msg, opt) {
|
||||
// file=app.js,line=1,col=5,endColumn=7
|
||||
opt = opt||{};
|
||||
warningList.push(msg);
|
||||
if (KNOWN_WARNINGS.includes(msg)) {
|
||||
console.log(`Known warning : ${msg}`);
|
||||
knownWarningCount++;
|
||||
} else {
|
||||
if (!showAllErrors) return;
|
||||
msg += " (KNOWN)"
|
||||
}
|
||||
console.log(`::warning${Object.keys(opt).length?" ":""}${Object.keys(opt).map(k=>k+"="+opt[k]).join(",")}::${msg}`);
|
||||
warningCount++;
|
||||
}
|
||||
}
|
||||
/* These are errors that we temporarily allow */
|
||||
var KNOWN_ERRORS = [
|
||||
"In locale en_CA, long date output must be shorter than 15 characters (Wednesday, September 10, 2024 -> 29)",
|
||||
"In locale fr_FR, long date output must be shorter than 15 characters (10 septembre 2024 -> 17)",
|
||||
"In locale fr_FR, short month must be shorter than 5 characters",
|
||||
"In locale sv_SE, speed must be shorter than 5 characters",
|
||||
"In locale en_SE, long date output must be shorter than 15 characters (September 10 2024 -> 17)",
|
||||
"In locale en_NZ, long date output must be shorter than 15 characters (Wednesday, September 10, 2024 -> 29)",
|
||||
|
|
@ -69,51 +96,23 @@ var KNOWN_ERRORS = [
|
|||
"In locale en_IL, long date output must be shorter than 15 characters (Wednesday, September 10, 2024 -> 29)",
|
||||
"In locale es_ES, long date output must be shorter than 15 characters (miércoles, 10 de septiembre de 2024 -> 35)",
|
||||
"In locale fr_BE, long date output must be shorter than 15 characters (dimanche septembre 10 2024 -> 26)",
|
||||
"In locale fr_BE, short month must be shorter than 5 characters",
|
||||
"In locale fr_BE, short month must be shorter than 5 characters",
|
||||
"In locale fr_BE, short month must be shorter than 5 characters",
|
||||
"In locale fr_BE, short month must be shorter than 5 characters",
|
||||
"In locale fr_BE, short month must be shorter than 5 characters",
|
||||
"In locale fi_FI, long date output must be shorter than 15 characters (keskiviikkona 10. maaliskuuta 2024 -> 34)",
|
||||
"In locale fi_FI, short month must be shorter than 5 characters",
|
||||
"In locale fi_FI, short month must be shorter than 5 characters",
|
||||
"In locale fi_FI, short month must be shorter than 5 characters",
|
||||
"In locale fi_FI, short month must be shorter than 5 characters",
|
||||
"In locale fi_FI, short month must be shorter than 5 characters",
|
||||
"In locale fi_FI, short month must be shorter than 5 characters",
|
||||
"In locale fi_FI, short month must be shorter than 5 characters",
|
||||
"In locale fi_FI, short month must be shorter than 5 characters",
|
||||
"In locale fi_FI, short month must be shorter than 5 characters",
|
||||
"In locale fi_FI, short month must be shorter than 5 characters",
|
||||
"In locale fi_FI, short month must be shorter than 5 characters",
|
||||
"In locale de_CH, meridian must be shorter than 4 characters",
|
||||
"In locale de_CH, meridian must be shorter than 4 characters",
|
||||
"In locale de_CH, long date output must be shorter than 15 characters (Donnerstag, 10. September 2024 -> 30)",
|
||||
"In locale fr_CH, long date output must be shorter than 15 characters (dimanche 10 septembre 2024 -> 26)",
|
||||
"In locale fr_CH, short month must be shorter than 5 characters",
|
||||
"In locale fr_CH, short month must be shorter than 5 characters",
|
||||
"In locale fr_CH, short month must be shorter than 5 characters",
|
||||
"In locale fr_CH, short month must be shorter than 5 characters",
|
||||
"In locale fr_CH, short month must be shorter than 5 characters",
|
||||
"In locale wae_CH, long date output must be shorter than 15 characters (Sunntag, 10. Herbštmánet 2024 -> 29)",
|
||||
"In locale tr_TR, long date output must be shorter than 15 characters (10 Haziran 2024 Pazartesi -> 25)",
|
||||
"In locale hu_HU, long date output must be shorter than 15 characters (2024 Szep 10, Csütörtök -> 23)",
|
||||
"In locale oc_FR, long date output must be shorter than 15 characters (divendres 10 setembre de 2024 -> 29)",
|
||||
"In locale oc_FR, short month must be shorter than 5 characters",
|
||||
"In locale oc_FR, short month must be shorter than 5 characters",
|
||||
"In locale hr_HR, meridian must be shorter than 4 characters",
|
||||
"In locale hr_HR, meridian must be shorter than 4 characters",
|
||||
"In locale hr_HR, short month must be shorter than 5 characters",
|
||||
"In locale sl_SI, meridian must be shorter than 4 characters",
|
||||
"In locale sl_SI, meridian must be shorter than 4 characters",
|
||||
"In locale ca_ES, long date output must be shorter than 15 characters (10 setembre 2024 -> 16)",
|
||||
"In locale ca_ES, short month must be shorter than 5 characters",
|
||||
];
|
||||
/* These are warnings we know about but don't want in our output */
|
||||
var KNOWN_WARNINGS = [
|
||||
"App gpsrec data file wildcard .gpsrc? does not include app ID",
|
||||
"App owmweather data file weather.json is also listed as data file for app weather",
|
||||
"App messagegui storage file messagegui is also listed as storage file for app messagelist",
|
||||
"App carcrazy has a setting file but no corresponding data entry (add `\"data\":[{\"name\":\"carcrazy.settings.json\"}]`)",
|
||||
"App loadingscreen has a setting file but no corresponding data entry (add `\"data\":[{\"name\":\"loadingscreen.settings.json\"}]`)",
|
||||
"App trex has a setting file but no corresponding data entry (add `\"data\":[{\"name\":\"trex.settings.json\"}]`)",
|
||||
|
|
@ -169,7 +168,7 @@ const APP_KEYS = [
|
|||
const STORAGE_KEYS = ['name', 'url', 'content', 'evaluate', 'noOverwite', 'supports', 'noOverwrite'];
|
||||
const DATA_KEYS = ['name', 'wildcard', 'storageFile', 'url', 'content', 'evaluate'];
|
||||
const SUPPORTS_DEVICES = ["BANGLEJS","BANGLEJS2"]; // device IDs allowed for 'supports'
|
||||
const METADATA_TYPES = ["app","clock","widget","bootloader","RAM","launch","scheduler","notify","locale","settings","textinput","module","clkinfo"]; // values allowed for "type" field
|
||||
const METADATA_TYPES = ["app","clock","widget","bootloader","RAM","launch","scheduler","notify","locale","settings","textinput","module","clkinfo","defaultconfig"]; // values allowed for "type" field - listed in README.md
|
||||
const FORBIDDEN_FILE_NAME_CHARS = /[,;]/; // used as separators in appid.info
|
||||
const VALID_DUPLICATES = [ '.tfmodel', '.tfnames' ];
|
||||
const GRANDFATHERED_ICONS = ["s7clk", "snek", "astral", "alpinenav", "slomoclock", "arrow", "pebble", "rebble"];
|
||||
|
|
@ -207,6 +206,10 @@ apps.forEach((app,appIdx) => {
|
|||
if (!app.name) ERROR(`App ${app.id} has no name`, {file:metadataFile});
|
||||
var isApp = !app.type || app.type=="app";
|
||||
var appTags = app.tags ? app.tags.split(",") : [];
|
||||
if (appTags.some(tag => tag!=tag.trim()))
|
||||
WARN(`App ${app.id} 'tag' list contains whitespace ("${app.tags}")`, {file:metadataFile});
|
||||
if (appTags.some(tag => tag!=tag.toLowerCase()))
|
||||
WARN(`App ${app.id} 'tag' list contains uppercase ("${app.tags}")`, {file:metadataFile});
|
||||
if (app.name.length>20 && !app.shortName && isApp) ERROR(`App ${app.id} has a long name, but no shortName`, {file:metadataFile});
|
||||
if (app.type && !METADATA_TYPES.includes(app.type))
|
||||
ERROR(`App ${app.id} 'type' is one one of `+METADATA_TYPES, {file:metadataFile});
|
||||
|
|
@ -296,6 +299,7 @@ apps.forEach((app,appIdx) => {
|
|||
if (INTERNAL_FILES_IN_APP_TYPE[app.type].includes(file.name))
|
||||
fileInternal = true;
|
||||
}
|
||||
if (!app.type=="defaultconfig")
|
||||
allFiles.push({app: app.id, file: file.name, internal:fileInternal});
|
||||
if (file.url) if (!fs.existsSync(appDir+file.url)) ERROR(`App ${app.id} file ${file.url} doesn't exist`, {file:metadataFile});
|
||||
if (!file.url && !file.content && !app.custom) ERROR(`App ${app.id} file ${file.name} has no contents`, {file:metadataFile});
|
||||
|
|
@ -494,7 +498,7 @@ while(fileA=allFiles.pop()) {
|
|||
if (isGlob(nameA)||isGlob(nameB))
|
||||
ERROR(`App ${fileB.app} ${typeB} file ${nameB} matches app ${fileA.app} ${typeB} file ${nameA}`);
|
||||
else if (fileA.app != fileB.app && (!fileA.internal) && (!fileB.internal))
|
||||
WARN(`App ${fileB.app} ${typeB} file ${nameB} is also listed as ${typeA} file for app ${fileA.app}`);
|
||||
WARN(`App ${fileB.app} ${typeB} file ${nameB} is also listed as ${typeA} file for app ${fileA.app}`, {file:APPSDIR_RELATIVE+fileB.app+"/metadata.json"});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -520,8 +524,17 @@ function sanityCheckLocales(){
|
|||
}
|
||||
|
||||
promise.then(function() {
|
||||
KNOWN_ERRORS.forEach(msg => {
|
||||
if (!errorList.includes(msg))
|
||||
WARN(`Known error '${msg}' no longer occurs`);
|
||||
});
|
||||
KNOWN_WARNINGS.forEach(msg => {
|
||||
if (!warningList.includes(msg))
|
||||
WARN(`Known warning '${msg}' no longer occurs`);
|
||||
});
|
||||
console.log("==================================");
|
||||
console.log(`${errorCount} errors, ${warningCount} warnings (and ${knownErrorCount} known errors, ${knownWarningCount} known warnings)`);
|
||||
console.log(`${errorCount} errors, ${warningCount} warnings`);
|
||||
console.log(`${knownErrorCount} known errors, ${knownWarningCount} known warnings${(knownErrorCount||knownWarningCount)?", run with --show-all to see them":""}`);
|
||||
console.log("==================================");
|
||||
if (errorCount) {
|
||||
process.exit(1);
|
||||
|
|
|
|||
2
core
|
|
@ -1 +1 @@
|
|||
Subproject commit bf08b484830ef4e811faf67ec663ebf839b5d09b
|
||||
Subproject commit 3ec8e289a26a545d0d0c50f6945978584fb3d7f8
|
||||
|
|
@ -14,4 +14,4 @@ type AppInfo = {
|
|||
|
||||
type AppType = "app" | "clock" | "widget" | "module" | "bootloader" |
|
||||
"settings" | "clkinfo" | "RAM" | "launch" | "textinput" | "scheduler" |
|
||||
"notify" | "locale";
|
||||
"notify" | "locale" | "defaultconfig";
|
||||
|
|
|
|||