mirror of https://github.com/espruino/BangleApps
Add manual download from settings
parent
edfb9000e8
commit
597703cda9
|
@ -0,0 +1,3 @@
|
||||||
|
A simple flash cards application based on Trello public board.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwwhC/AH0iABQWKgQXLkAXhCxZIKFxgwKC68zABwWGgYXPmAX/C/4X/C/4X/C9ndACQX/C6dEAAQXS6gXDpovpR/4X/C8ENCyPQC4YA/AGo"))
|
|
@ -0,0 +1,158 @@
|
||||||
|
/**
|
||||||
|
* Copyright 2023 SHOGEL
|
||||||
|
* We believe in Finnish
|
||||||
|
*/
|
||||||
|
var Layout = require("Layout");
|
||||||
|
var locale = require("locale");
|
||||||
|
var storage = require("Storage");
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
let SWAP_SIDE_BUZZ_MILLISECONDS = 50;
|
||||||
|
let CARD_DATA_FILE = "flashcards.data.json";
|
||||||
|
let CARD_EMPTY = "empty card";
|
||||||
|
let CARD_LINE_LENGTH = 9;
|
||||||
|
let CARD_LINE_FONT = "20%";
|
||||||
|
|
||||||
|
// Global variables
|
||||||
|
let cards = [];
|
||||||
|
|
||||||
|
let cardIndex = 0;
|
||||||
|
let backSide = false;
|
||||||
|
let lastDragX = 0;
|
||||||
|
let lastDragY = 0;
|
||||||
|
|
||||||
|
// Cards data
|
||||||
|
function wordWrap(str, maxLength) {
|
||||||
|
if (maxLength == undefined) {
|
||||||
|
maxLength = CARD_LINE_LENGTH;
|
||||||
|
}
|
||||||
|
let res = '';
|
||||||
|
while (str.length > maxLength) {
|
||||||
|
let found = false;
|
||||||
|
// Inserts new line at first whitespace of the line
|
||||||
|
for (i = maxLength - 1; i >= 0; i--) {
|
||||||
|
if (str.charAt(i)==' ') {
|
||||||
|
res = res + [str.slice(0, i), "\n"].join('');
|
||||||
|
str = str.slice(i + 1);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Inserts new line at MAX_LENGTH position, the word is too long to wrap
|
||||||
|
if (!found) {
|
||||||
|
res += [str.slice(0, maxLength), "\n"].join('');
|
||||||
|
str = str.slice(maxLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res + str;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadLocalCards() {
|
||||||
|
if (storage.read(CARD_DATA_FILE))
|
||||||
|
{
|
||||||
|
refreshCards(storage.readJSON(CARD_DATA_FILE, 1) || {},false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function refreshCards(cardsJSON,showMsg)
|
||||||
|
{
|
||||||
|
cardIndex = 0;
|
||||||
|
backSide = false;
|
||||||
|
cards = [];
|
||||||
|
|
||||||
|
if (cardsJSON && cardsJSON.length) {
|
||||||
|
cardsJSON.forEach(card => {
|
||||||
|
cards.push([ wordWrap(card.name), wordWrap(card.desc) ]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cards.length) {
|
||||||
|
cards.push([ wordWrap(CARD_EMPTY), wordWrap(CARD_EMPTY) ]);
|
||||||
|
drawMessage("e: cards not found");
|
||||||
|
} else if (showMsg) {
|
||||||
|
drawMessage("i: cards refreshed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drawing a card
|
||||||
|
let drawTimeout;
|
||||||
|
let queueDraw = function() {
|
||||||
|
let timeout = 60000;
|
||||||
|
if (drawTimeout) clearTimeout(drawTimeout);
|
||||||
|
drawTimeout = setTimeout(function() {
|
||||||
|
drawTimeout = undefined;
|
||||||
|
draw();
|
||||||
|
}, timeout - (Date.now() % timeout));
|
||||||
|
};
|
||||||
|
|
||||||
|
var cardLayout = new Layout( {
|
||||||
|
type:"v", c: [
|
||||||
|
{type:"txt", font:"6x8:3", label:"", id:"widgets", fillx:1 },
|
||||||
|
{type:"txt", font:CARD_LINE_FONT, label:"ABCDEFGHIJ KLMNOPQRST UVWXYZÅÄÖ", filly:1, id:"card" },
|
||||||
|
{type:"txt", font:"6x8:2", label:"00:00", id:"clock", fillx:1, bgCol:g.theme.fg, col:g.theme.bg }
|
||||||
|
]
|
||||||
|
}, {lazy:true});
|
||||||
|
|
||||||
|
function drawCard() {
|
||||||
|
cardLayout.card.label = cards[cardIndex][backSide ? 1 : 0];
|
||||||
|
cardLayout.clock.label = locale.time(new Date(),1);
|
||||||
|
cardLayout.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawMessage(msg) {
|
||||||
|
cardLayout.card.label = wordWrap(msg);
|
||||||
|
cardLayout.render();
|
||||||
|
console.log(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function draw() {
|
||||||
|
drawCard();
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
queueDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle a touch: swap card side
|
||||||
|
function handleTouch(zone, event) {
|
||||||
|
backSide = !backSide;
|
||||||
|
drawCard();
|
||||||
|
Bangle.buzz(SWAP_SIDE_BUZZ_MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle a drag event: cycle cards
|
||||||
|
function handleDrag(event) {
|
||||||
|
let first_x = event.xy[0];
|
||||||
|
let last_x = event.xy[event.xy.length - 2];
|
||||||
|
let xdiff = last_x - first_x;
|
||||||
|
/*
|
||||||
|
let first_y = event.xy[1];
|
||||||
|
let last_y = event.xy[event.xy.length - 1];
|
||||||
|
let ydiff = last_y - first_y;
|
||||||
|
*/
|
||||||
|
if(xdiff > 0) {
|
||||||
|
cardIndex = (cardIndex + 1) % cards.length;
|
||||||
|
}
|
||||||
|
else if(--cardIndex < 0) {
|
||||||
|
cardIndex = cards.length - 1;
|
||||||
|
}
|
||||||
|
drawCard();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// initialize
|
||||||
|
loadLocalCards();
|
||||||
|
cardLayout.update();
|
||||||
|
Bangle.loadWidgets();
|
||||||
|
Bangle.on("touch", handleTouch);
|
||||||
|
Bangle.on("stroke", handleDrag);
|
||||||
|
|
||||||
|
// On start: display the first card
|
||||||
|
g.clear();
|
||||||
|
draw();
|
||||||
|
|
||||||
|
// cleanup
|
||||||
|
Bangle.setUI({mode:"clock", remove:function() {
|
||||||
|
if (drawTimeout) clearTimeout(drawTimeout);
|
||||||
|
drawTimeout = undefined;
|
||||||
|
Bangle.removeListener("touch", handleTouch);
|
||||||
|
Bangle.removeListener("stroke", handleDrag);
|
||||||
|
}});
|
Binary file not shown.
After Width: | Height: | Size: 640 B |
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"id": "flashcards",
|
||||||
|
"name": "Flash Cards",
|
||||||
|
"shortName": "Flash Cards",
|
||||||
|
"version": "1.1",
|
||||||
|
"description": "Flash cards based on public Trello board",
|
||||||
|
"screenshots" : [ { "url":"screenshot.png" }],
|
||||||
|
"icon": "app.png",
|
||||||
|
"tags": "flash cards",
|
||||||
|
"type": "clock",
|
||||||
|
"supports": ["BANGLEJS2"],
|
||||||
|
"storage": [
|
||||||
|
{"name":"flashcards.app.js","url":"app.js"},
|
||||||
|
{"name":"flashcards.settings.js","url":"settings.js"},
|
||||||
|
{"name":"flashcards.img","url":"app-icon.js","evaluate":true}
|
||||||
|
],
|
||||||
|
"data": [
|
||||||
|
{"name":"flashcards.data.json"},
|
||||||
|
{"name":"flashcards.settings.json"}
|
||||||
|
]
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
|
@ -0,0 +1,56 @@
|
||||||
|
(function(back) {
|
||||||
|
var storage = require("Storage");
|
||||||
|
|
||||||
|
var settingsFILE = "flashcards.settings.json";
|
||||||
|
var dataFile = "flashcards.data.json";
|
||||||
|
var trelloTimeout = 3000;
|
||||||
|
var trelloURL = "https://api.trello.com/1/lists/$cardsListId/cards/?fields=name%2Cdesc%2Clist";
|
||||||
|
|
||||||
|
var settings = Object.assign({
|
||||||
|
listId: ""
|
||||||
|
}, storage.readJSON(settingsFILE, true) || {});
|
||||||
|
|
||||||
|
function writeSettings() {
|
||||||
|
storage.writeJSON(FILE, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
var settingsMenu = {
|
||||||
|
"" : { "title" : "Flash Cards" },
|
||||||
|
"< Back" : () => back(),
|
||||||
|
"Get from Trello": () => {
|
||||||
|
E.showPrompt("Download cards?").then((v) => {
|
||||||
|
let delay = 500;
|
||||||
|
if (v) {
|
||||||
|
if (Bangle.http)
|
||||||
|
{
|
||||||
|
if (settings.listId.length)
|
||||||
|
{
|
||||||
|
delay = delay + trelloTimeout;
|
||||||
|
E.showMessage('i: downloading');
|
||||||
|
Bangle.http(trelloURL.replace("$cardsListId", settings.listId),
|
||||||
|
{
|
||||||
|
timeout : trelloTimeout,
|
||||||
|
method: "GET",
|
||||||
|
headers: { "Content-Type": "application/json" }
|
||||||
|
}).then(data=>{
|
||||||
|
var cardsJSON = JSON.parse(data.resp);
|
||||||
|
storage.write(dataFile, JSON.stringify(result));
|
||||||
|
E.showMessage('i: downloaded');
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
E.showMessage("e: " + e);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
E.showMessage("e: list Id not found");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
E.showMessage("e: Gadgetbridge not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setTimeout(() => E.showMenu(settingsMenu), delay);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Show the menu
|
||||||
|
E.showMenu(settingsMenu);
|
||||||
|
})(load)
|
Loading…
Reference in New Issue