mirror of https://github.com/espruino/BangleApps
Merge branch 'master' of github.com:espruino/BangleApps
commit
0dcc0ec789
|
@ -1,2 +1,3 @@
|
|||
0.01: New app!
|
||||
0.02: Fix bug with regenerating index, fix bug in word lookups
|
||||
0.03: Improve word search performance
|
||||
|
|
|
@ -27,10 +27,7 @@ least once and yields an additional 7 points. Each game contains at least one pa
|
|||
The game uses an internal dictionary consisting of a newline separated list of English words ('bee.words', using the '2of12inf' word list).
|
||||
The dictionary is fairly large (~700kB of flash space) and thus requires appropriate space on the watch and will make installing the app somewhat
|
||||
slow. Because of its size it cannot be compressed (heatshrink needs to hold the compressed/uncompressed data in memory).
|
||||
In order to make checking the validity of a guessed word faster an index file ('bee_lindex.json') is installed with
|
||||
the app that facilitates faster word lookups. This index file is specific to the dictionary file used. If one were to
|
||||
replace the dictionary file with a different version (e.g. a different language) the index file has to be regenerated. The easiest
|
||||
way to do so is to delete (via the Web IDE or the fileman app on the watch) the file 'bee_lindex.json' - it will be regenerated (and saved,
|
||||
i.e. it only happens once) on app startup automatically, a process that takes roughly 30 seconds.
|
||||
This file can be replaced with a custom dictionary, an ASCII file containing a newline-separated (single "\n", not DOS-style "\r\n") alphabetically
|
||||
sorted (sorting is important for the word lookup algorithm) list of words.
|
||||
|
||||

|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
const S = require("Storage");
|
||||
const words = S.read("bee.words");
|
||||
var letters = [];
|
||||
var letterIdx = [];
|
||||
|
||||
var centers = [];
|
||||
|
||||
|
@ -12,29 +12,17 @@ var score = 0;
|
|||
|
||||
var intervalID = -1;
|
||||
|
||||
function prepareLetterIdx () {
|
||||
function biSearch(w, ws, start, end, count) {
|
||||
"compile"
|
||||
var li = [0];
|
||||
if (S.read("bee_lindex.json")!==undefined) li = S.readJSON("bee_lindex.json"); // check for cached index
|
||||
else {
|
||||
for (var i=1; i<26; ++i) {
|
||||
var prefix = String.fromCharCode(97+i%26);
|
||||
console.log(prefix);
|
||||
li.push(S.read('bee.words').indexOf("\n"+prefix, li[i-1])+1);
|
||||
}
|
||||
li.push(S.read('bee.words').length);
|
||||
S.writeJSON("bee_lindex.json", li);
|
||||
}
|
||||
for (var i=0; i<26; ++i) letterIdx[i] = S.read("bee.words", li[i], li[i+1]-li[i]);
|
||||
}
|
||||
|
||||
function findWord (w) {
|
||||
"compile"
|
||||
var ci = w.charCodeAt(0)-97;
|
||||
var f = letterIdx[ci].indexOf("\n"+w+"\n");
|
||||
if (f>=0) return true;
|
||||
if (letterIdx[ci].substr(0, w.length)==w) return true;
|
||||
return false;
|
||||
if (start>end-w.legnth || count--<=0) return ws.substr(start, end-start).indexOf("\n"+w+"\n");
|
||||
var mid = (end+start)>>1;
|
||||
if (ws[mid-1]==="\n") --mid;
|
||||
else while (mid<end && ws[mid]!=="\n") mid++;
|
||||
var i = 0;
|
||||
while (i<w.length && ws[mid+i+1]==w[i]) ++i;
|
||||
if (i==w.length && ws[mid+i+1]==="\n") return mid+1;
|
||||
if (i==w.length || w[i]<ws[mid+i+1]) return biSearch(w, ws, start, mid+1, count);
|
||||
if (w[i]>ws[mid+i+1]) return biSearch(w, ws, mid+1, end, count);
|
||||
}
|
||||
|
||||
function isPangram(w) {
|
||||
|
@ -46,7 +34,7 @@ function isPangram(w) {
|
|||
function checkWord (w) {
|
||||
if (w.indexOf(String.fromCharCode(97+letters[0]))==-1) return false; // does it contain central letter?
|
||||
if (foundWords.indexOf(w)>=0) return false; // already found
|
||||
if (findWord(w)) {
|
||||
if (biSearch(w, words, 0, words.length, 20)>-1) {
|
||||
foundWords.push(w);
|
||||
foundWords.sort();
|
||||
if (w.length==4) score++;
|
||||
|
@ -93,13 +81,12 @@ function pickLetters() {
|
|||
var ltrs = "";
|
||||
while (ltrs.length!==7) {
|
||||
ltrs = [];
|
||||
var j = Math.floor(26*Math.random());
|
||||
var i = Math.floor((letterIdx[j].length-10)*Math.random());
|
||||
while (letterIdx[j][i]!="\n" && i<letterIdx[j].length) ++i;
|
||||
if (i<letterIdx[j].length-1) {
|
||||
var i = Math.floor((words.length-10)*Math.random());
|
||||
while (words[i]!="\n" && i<words.length) ++i;
|
||||
if (i<words.length-1) {
|
||||
++i;
|
||||
while (letterIdx[j][i]!=="\n") {
|
||||
var c = letterIdx[j][i];
|
||||
while (words[i]!=="\n") {
|
||||
var c = words[i];
|
||||
if (ltrs.indexOf(c)===-1) ltrs += c;
|
||||
++i;
|
||||
}
|
||||
|
@ -187,7 +174,6 @@ function showWordList() {
|
|||
});
|
||||
}
|
||||
|
||||
prepareLetterIdx();
|
||||
pickLetters();
|
||||
drawHive();
|
||||
drawScore();
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
[0,41048,80445,152390,198606,228714,257919,279071,303726,337982,343582,348026,367246,404452,419780,438696,496250,499697,544600,624304,659085,680996,691270,708186,708341,709916,710883]
|
|
@ -2,7 +2,7 @@
|
|||
"name": "Bee",
|
||||
"shortName":"Bee",
|
||||
"icon": "app.png",
|
||||
"version":"0.02",
|
||||
"version":"0.03",
|
||||
"description": "Spelling bee",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
|
@ -10,7 +10,6 @@
|
|||
"storage": [
|
||||
{"name":"bee.app.js","url":"bee.app.js"},
|
||||
{"name":"bee.words","url":"bee_words_2of12"},
|
||||
{"name":"bee_lindex.json","url":"bee_lindex.json"},
|
||||
{"name":"bee.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
0.01: New App!
|
||||
0.02: Add the option to enable touching the widget only on clock and settings.
|
||||
0.03: Settings page now uses built-in min/max/wrap (fix #1607)
|
||||
0.04: Add masking widget input to other apps (using espruino/Espruino#2151), add a oversize option to increase the touch area.
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
# Light Switch Widget
|
||||
|
||||
Whis this widget I wanted to create a solution to quickly en-/disable the LCD backlight and even change the brightness.
|
||||
With this widget I wanted to create a solution to quickly en-/disable the LCD backlight and even change the brightness.
|
||||
In addition it shows the lock status with the option to personalize the lock icon with a tiny image.
|
||||
|
||||
All touch and drag inputs related to this widget are cached/masked to prevent actions in the active app.
|
||||
(See [espruino/Espruino#2151](https://github.com/espruino/Espruino/issues/2151) for more information.)
|
||||
|
||||
---
|
||||
### Control
|
||||
---
|
||||
|
@ -39,6 +42,9 @@ In addition it shows the lock status with the option to personalize the lock ico
|
|||
* _clk+launch_ -> on all apps of the types _clock_ and _launch_
|
||||
* _except apps_ -> on all apps of the types _clock_ and _launch_ and in the settings
|
||||
* _always on_ -> always enabled when the widget is displayed
|
||||
* __Oversize__
|
||||
_0px_ / _1px_ / _..._ / __20px__ / _..._ / _50px_
|
||||
To make it easier to hit the widget, this value extends the touch area of the widget in all directions.
|
||||
* __Drag Delay__
|
||||
_off_ / _50ms_ / _100ms_ / _..._ / __500ms__ / _..._ / _1000ms_
|
||||
Change the maximum delay between first touch and re-touch/drag to change the brightness or disable changing the brightness completely.
|
||||
|
@ -85,8 +91,6 @@ This images are stored in a seperate file _(lightswitch.images.json)_.
|
|||
### Worth Mentioning
|
||||
---
|
||||
#### To do list
|
||||
* Catch the touch and draw input related to this widget to prevent actions in the active app.
|
||||
_(For now I have no idea how to achieve this, help is appreciated)_
|
||||
* Manage images for the lock icon through a _Customize and Upload App_ page.
|
||||
|
||||
#### Requests, Bugs and Feedback
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"id": "lightswitch",
|
||||
"name": "Light Switch Widget",
|
||||
"shortName": "Light Switch",
|
||||
"version": "0.03",
|
||||
"version": "0.04",
|
||||
"description": "A fast way to switch LCD backlight on/off, change the brightness and show the lock status. All in one widget.",
|
||||
"icon": "images/app.png",
|
||||
"screenshots": [
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
var settings = Object.assign({
|
||||
colors: "011",
|
||||
image: "default",
|
||||
touchOn: "clock,launch",
|
||||
touchOn: "always",
|
||||
oversize: 20,
|
||||
dragDelay: 500,
|
||||
minValue: 0.1,
|
||||
unlockSide: "",
|
||||
|
@ -45,7 +46,7 @@
|
|||
return {
|
||||
value: entry.value.indexOf(settings[key]),
|
||||
min : 0,
|
||||
max : entry.value.length-1,
|
||||
max : entry.value.length - 1,
|
||||
wrap : true,
|
||||
format: v => entry.title ? entry.title[v] : entry.value[v],
|
||||
onchange: function(v) {
|
||||
|
@ -57,11 +58,11 @@
|
|||
// return entry for numerical value
|
||||
return {
|
||||
value: settings[key] * entry.factor,
|
||||
step: entry.step,
|
||||
format: v => v > 0 ? v + entry.unit : "off",
|
||||
min : entry.min,
|
||||
max : entry.max,
|
||||
step: entry.step,
|
||||
wrap : true,
|
||||
format: v => v > 0 ? v + entry.unit : "off",
|
||||
onchange: function(v) {
|
||||
writeSetting(key, v / entry.factor, entry.drawWidgets);
|
||||
},
|
||||
|
@ -96,6 +97,14 @@
|
|||
value: ["", "clock", "clock,setting.app.js", "clock,launch", "clock,setting.app.js,launch", "always"],
|
||||
drawWidgets: true
|
||||
},
|
||||
oversize: {
|
||||
factor: 1,
|
||||
unit: "px",
|
||||
min: 0,
|
||||
max: 50,
|
||||
step: 1,
|
||||
drawWidgets: true
|
||||
},
|
||||
dragDelay: {
|
||||
factor: 1,
|
||||
unit: "ms",
|
||||
|
@ -142,6 +151,7 @@
|
|||
"Image": getEntry("image"),
|
||||
"-- Control": 0,
|
||||
"Touch": getEntry("touchOn"),
|
||||
"Oversize": getEntry("oversize"),
|
||||
"Drag Delay": getEntry("dragDelay"),
|
||||
"Min Value": getEntry("minValue"),
|
||||
"-- Unlock": 0,
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
"101" -> magenta
|
||||
|
||||
* image: string //
|
||||
"default" ->
|
||||
"random" ->
|
||||
"default" -> image nearest to the default lock
|
||||
"random" -> a random image from all available
|
||||
|
||||
* touchOn: string // select when widget touch is active
|
||||
"" -> only on default clock
|
||||
|
@ -19,6 +19,9 @@
|
|||
"clock,launch" -> on all clocks and lanchers (default)
|
||||
"always" -> always
|
||||
|
||||
* oversize: int // extends the touch area of the widget in px in all directions
|
||||
0 to 50, 20 as default
|
||||
|
||||
* dragDelay: int // drag listener reset time in ms
|
||||
// time until a drag is needed to activate backlight changing mode
|
||||
0 -> disabled
|
||||
|
@ -59,6 +62,7 @@
|
|||
"colors": "011",
|
||||
"image": "default",
|
||||
"touchOn": "clock,launch",
|
||||
"oversize": 20,
|
||||
"dragDelay": 500,
|
||||
"minValue": 0.1,
|
||||
"unlockSide": "",
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
var settings = Object.assign({
|
||||
colors: "011",
|
||||
image: "default",
|
||||
touchOn: "clock,launch",
|
||||
touchOn: "always",
|
||||
oversize: 20,
|
||||
dragDelay: 500,
|
||||
minValue: 0.1,
|
||||
unlockSide: "",
|
||||
|
@ -162,6 +163,11 @@
|
|||
// change brigthness value, skip write to storage while still touching
|
||||
w.changeValue(value, event.b);
|
||||
|
||||
// masks this drag event by messing up the event handler
|
||||
// see https://github.com/espruino/Espruino/issues/2151
|
||||
Bangle.removeListener("drag", w.dragListener);
|
||||
Bangle["#ondrag"] = [w.dragListener].concat(Bangle["#ondrag"]);
|
||||
|
||||
// on touch release remove drag listener and reset drag status to indicate stopped drag action
|
||||
if (!event.b) {
|
||||
Bangle.removeListener("drag", w.dragListener);
|
||||
|
@ -184,14 +190,14 @@
|
|||
if (w.dragStatus === "off") {
|
||||
|
||||
// check if inside widget area
|
||||
if (!(!w || cursor.x < w.x || cursor.x > w.x + w.width ||
|
||||
cursor.y < w.y || cursor.y > w.y + 23)) {
|
||||
if (!(!w || cursor.x < w.x - w.oversize || cursor.x > w.x + w.width + w.oversize ||
|
||||
cursor.y < w.y - w.oversize || cursor.y > w.y + 23 + w.oversize)) {
|
||||
// first touch feedback
|
||||
Bangle.buzz(25);
|
||||
// check if drag is disabled
|
||||
if (w.dragDelay) {
|
||||
// add drag listener
|
||||
Bangle.on("drag", w.dragListener);
|
||||
// add drag listener at first position
|
||||
Bangle["#ondrag"] = [w.dragListener].concat(Bangle["#ondrag"]);
|
||||
// set drag timeout
|
||||
w.dragStatus = setTimeout((w) => {
|
||||
// remove drag listener
|
||||
|
@ -204,6 +210,10 @@
|
|||
}
|
||||
// switch backlight
|
||||
w.changeValue();
|
||||
// masks this touch event by messing up the event handler
|
||||
// see https://github.com/espruino/Espruino/issues/2151
|
||||
Bangle.removeListener("touch", w.touchListener);
|
||||
Bangle["#ontouch"] = [w.touchListener].concat(Bangle["#ontouch"]);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -236,11 +246,11 @@
|
|||
// add lock listener
|
||||
Bangle.on("lock", w.draw);
|
||||
|
||||
// add touch listener to control the light depending on settings
|
||||
// add touch listener to control the light depending on settings at first position
|
||||
if (w.touchOn === "always" || !global.__FILE__ ||
|
||||
w.touchOn.includes(__FILE__) ||
|
||||
w.touchOn.includes(require("Storage").readJSON(__FILE__.replace("app.js", "info")).type))
|
||||
Bangle.on("touch", w.touchListener);
|
||||
Bangle["#ontouch"] = [w.touchListener].concat(Bangle["#ontouch"]);
|
||||
|
||||
// add tap listener to unlock and/or flash backlight
|
||||
if (w.unlockSide || w.tapSide) Bangle.on("tap", require("lightswitch.js").tapListener);
|
||||
|
|
|
@ -688,8 +688,8 @@ var locales = {
|
|||
datePattern: { 0: "%d. %b %Y", "1": "%d.%m.%Y" }, // 1. Mar 2020 // 01.03.20
|
||||
abmonth: "Jan,Feb,Mar,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Des",
|
||||
month: "Januar,Februar,Mars,April,Mai,Juni,Juli,August,September,Oktober,November,Desember",
|
||||
abday: "Ma,Ti,On,To,Fr,Lø,Sø",
|
||||
day: "Mandag,Tirsdag,Onsdag,Torsdag,Fredag,Lørdag,Søndag",
|
||||
abday: "Sø,Ma,Ti,On,To,Fr,Lø",
|
||||
day: "Søndag,Mandag,Tirsdag,Onsdag,Torsdag,Fredag,Lørdag",
|
||||
trans: { yes: "ja", Yes: "Ja", no: "nei", No: "Nei", ok: "ok", on: "på", off: "av", "< Back": "< Tilbake", "Delete": "Slett", "Mark Unread": "Merk som ulest" }
|
||||
},
|
||||
/*,
|
||||
|
|
|
@ -43,3 +43,4 @@
|
|||
0.28: Option to auto-unlock the watch when a new message arrives
|
||||
0.29: Fix message list overwrites on Bangle.js 1 (fix #1642)
|
||||
0.30: Add new Icons (Youtube, Twitch, MS TODO, Teams, Snapchat, Signal, Post & DHL, Nina, Lieferando, Kalender, Discord, Corona Warn, Bibel)
|
||||
0.31: Option to disable icon flashing
|
||||
|
|
|
@ -21,6 +21,7 @@ is chosen if there isn't much message text, but this specifies the smallest the
|
|||
it starts getting clipped.
|
||||
* `Auto-Open Music` - Should the app automatically open when the phone starts playing music?
|
||||
* `Unlock Watch` - Should the app unlock the watch when a new message arrives, so you can touch the buttons at the bottom of the app?
|
||||
* `Flash Icon` - Toggle flashing of the widget icon.
|
||||
|
||||
## New Messages
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "messages",
|
||||
"name": "Messages",
|
||||
"version": "0.30",
|
||||
"version": "0.31",
|
||||
"description": "App to display notifications from iOS and Gadgetbridge/Android",
|
||||
"icon": "app.png",
|
||||
"type": "app",
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
settings.unlockWatch=!!settings.unlockWatch;
|
||||
settings.openMusic=!!settings.openMusic;
|
||||
settings.maxUnreadTimeout=240;
|
||||
if (settings.flash===undefined) settings.flash=true;
|
||||
return settings;
|
||||
}
|
||||
function updateSetting(setting, value) {
|
||||
|
@ -47,6 +48,11 @@
|
|||
format: v => v?/*LANG*/'Yes':/*LANG*/'No',
|
||||
onchange: v => updateSetting("unlockWatch", v)
|
||||
},
|
||||
/*LANG*/'Flash Icon': {
|
||||
value: !!settings().flash,
|
||||
format: v => v?/*LANG*/'Yes':/*LANG*/'No',
|
||||
onchange: v => updateSetting("flash", v)
|
||||
},
|
||||
};
|
||||
E.showMenu(mainmenu);
|
||||
})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
WIDGETS["messages"]={area:"tl", width:0, iconwidth:24,
|
||||
draw:function() {
|
||||
draw:function(recall) {
|
||||
// If we had a setTimeout queued from the last time we were called, remove it
|
||||
if (WIDGETS["messages"].i) {
|
||||
clearTimeout(WIDGETS["messages"].i);
|
||||
|
@ -8,15 +8,18 @@ draw:function() {
|
|||
Bangle.removeListener('touch', this.touch);
|
||||
if (!this.width) return;
|
||||
var c = (Date.now()-this.t)/1000;
|
||||
g.reset().clearRect(this.x, this.y, this.x+this.width, this.y+this.iconwidth);
|
||||
g.drawImage((c&1) ? atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+DAADDAADDAADDwAPD8A/DOBzDDn/DA//DAHvDAPvjAPvjAPvjAPvh///gf/vAAD+AAB8AAAAA==") : atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+D///D///A//8CP/xDj/HD48DD+B8D/D+D/3vD/vvj/vvj/vvj/vvh/v/gfnvAAD+AAB8AAAAA=="), this.x, this.y);
|
||||
let settings = require('Storage').readJSON("messages.settings.json", true) || {};
|
||||
if (settings.flash===undefined) settings.flash = true;
|
||||
if (recall !== true || settings.flash) {
|
||||
g.reset().clearRect(this.x, this.y, this.x+this.width, this.y+23);
|
||||
g.drawImage(settings.flash && (c&1) ? atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+DAADDAADDAADDwAPD8A/DOBzDDn/DA//DAHvDAPvjAPvjAPvjAPvh///gf/vAAD+AAB8AAAAA==") : atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+D///D///A//8CP/xDj/HD48DD+B8D/D+D/3vD/vvj/vvj/vvj/vvh/v/gfnvAAD+AAB8AAAAA=="), this.x, this.y-1);
|
||||
}
|
||||
if (settings.repeat===undefined) settings.repeat = 4;
|
||||
if (c<120 && (Date.now()-this.l)>settings.repeat*1000) {
|
||||
this.l = Date.now();
|
||||
WIDGETS["messages"].buzz(); // buzz every 4 seconds
|
||||
}
|
||||
WIDGETS["messages"].i=setTimeout(()=>WIDGETS["messages"].draw(), 1000);
|
||||
WIDGETS["messages"].i=setTimeout(()=>WIDGETS["messages"].draw(true), 1000);
|
||||
if (process.env.HWVERSION>1) Bangle.on('touch', this.touch);
|
||||
},show:function(quiet) {
|
||||
WIDGETS["messages"].t=Date.now(); // first time
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
0.01: First release
|
||||
0.02: Enhanced icon, make it bolder
|
||||
0.03: Fixed issue with defaulting back to London
|
||||
0.04: Fixed issue selecting Frankfurt not saved
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"icon": "mylocation.png",
|
||||
"type": "app",
|
||||
"screenshots": [{"url":"screenshot_1.png"}],
|
||||
"version":"0.03",
|
||||
"version":"0.04",
|
||||
"description": "Sets and stores the lat and long of your preferred City or it can be set from the GPS. mylocation.json can be used by other apps that need your main location lat and lon. See README",
|
||||
"readme": "README.md",
|
||||
"tags": "tool,utility",
|
||||
|
|
|
@ -61,7 +61,7 @@ function showMainMenu() {
|
|||
min: 0, max: locations.length - 1,
|
||||
format: v => locations[v],
|
||||
onchange: v => {
|
||||
if (v != 6) {
|
||||
if (locations[v] !== "???") {
|
||||
s.location = locations[v];
|
||||
s.lat = lats[v];
|
||||
s.lon = lons[v];
|
||||
|
|
Loading…
Reference in New Issue