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