BangleApps/apps/flashcards/app.js

188 lines
4.6 KiB
JavaScript
Raw Normal View History

2023-07-07 16:51:40 +00:00
/**
2023-07-07 20:18:01 +00:00
* Copyright 2023 Crisp Advice
2023-07-07 16:51:40 +00:00
* We believe in Finnish
*/
2023-07-07 17:43:16 +00:00
// Modules
var Layout = require("Layout");
var locale = require("locale");
var storage = require("Storage");
2023-07-07 16:51:40 +00:00
2023-07-07 17:43:16 +00:00
// Global variables
2023-07-08 12:05:10 +00:00
let SWAP_SIDE_BUZZ_MILLISECONDS = 50;
let CARD_DATA_FILE = "flashcards.data.json";
let CARD_SETTINGS_FILE = "flashcards.settings.json";
let CARD_EMPTY = "no cards found";
let cards = [];
let cardIndex = 0;
let backSide = false;
2023-07-09 18:15:09 +00:00
let drawTimeout;
let fontSizes = ["15%","20%","25%"];
let lastDragX = 0;
let lastDragY = 0;
2023-07-08 12:05:10 +00:00
let settings = Object.assign({
listId: "",
fontSize: 1,
cardWidth: 9,
swipeGesture: 0
}, storage.readJSON(CARD_SETTINGS_FILE, true) || {});
2023-07-07 16:51:40 +00:00
// Cards data
2023-07-09 18:15:09 +00:00
function wordWrap(textStr, maxLength) {
2023-07-07 16:51:40 +00:00
if (maxLength == undefined) {
maxLength = settings.cardWidth;
2023-07-07 16:51:40 +00:00
}
let res = '';
2023-07-09 18:15:09 +00:00
let str = textStr.trim();
2023-07-07 16:51:40 +00:00
while (str.length > maxLength) {
let found = false;
// Inserts new line at first whitespace of the line
2023-07-09 18:15:09 +00:00
for (i = maxLength - 1; i > 0; i--) {
2023-07-07 16:51:40 +00:00
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() {
2023-07-07 17:43:16 +00:00
var cardsJSON = "";
2023-07-07 16:51:40 +00:00
if (storage.read(CARD_DATA_FILE))
{
2023-07-07 17:43:16 +00:00
cardsJSON = storage.readJSON(CARD_DATA_FILE, 1) || {};
2023-07-07 16:51:40 +00:00
}
2023-07-07 17:43:16 +00:00
refreshCards(cardsJSON,false);
2023-07-07 16:51:40 +00:00
}
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 queueDraw = function() {
let timeout = 60000;
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = setTimeout(function() {
drawTimeout = undefined;
draw();
}, timeout - (Date.now() % timeout));
};
2023-07-08 12:05:10 +00:00
let cardLayout = new Layout( {
2023-07-07 16:51:40 +00:00
type:"v", c: [
{type:"txt", font:"6x8:3", label:"", id:"widgets", fillx:1 },
{type:"txt", font:fontSizes[settings.fontSize], label:"ABCDEFGHIJ KLMNOPQRST UVWXYZÅÖÄ", filly:1, fillx:1, id:"card" },
2023-07-07 16:51:40 +00:00
{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();
}
function swipeCard(forward)
{
if(forward) {
cardIndex = (cardIndex + 1) % cards.length;
}
else if(--cardIndex < 0) {
cardIndex = cards.length - 1;
}
drawCard();
}
2023-07-07 16:51:40 +00:00
// Handle a touch: swap card side
function handleTouch(zone, event) {
backSide = !backSide;
drawCard();
Bangle.buzz(SWAP_SIDE_BUZZ_MILLISECONDS);
}
// Handle a stroke event: cycle cards
function handleStroke(event) {
2023-07-07 16:51:40 +00:00
let first_x = event.xy[0];
let last_x = event.xy[event.xy.length - 2];
swipeCard((last_x - first_x) > 0);
}
// Handle a drag event: cycle cards
function handleDrag(event) {
let isFingerReleased = (event.b === 0);
if(isFingerReleased) {
let isHorizontalDrag = (Math.abs(lastDragX) >= Math.abs(lastDragY)) &&
(lastDragX !== 0);
if(isHorizontalDrag) {
swipeCard(lastDragX > 0);
}
2023-07-07 16:51:40 +00:00
}
else {
lastDragX = event.dx;
lastDragY = event.dy;
2023-07-07 16:51:40 +00:00
}
}
2023-07-12 13:36:24 +00:00
// Ensure pressing the button goes to the launcher (by making this seem like a clock?)
Bangle.setUI({mode:"clock"/*, remove:function() {
// Code to enable fast load. NOTE: this doesn't work on this app because all
// functions and vars are declared global: https://www.espruino.com/Bangle.js+Fast+Load
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = undefined;
Bangle.removeListener("touch", handleTouch);
if (settings.swipeGesture) { Bangle.removeListener("drag", handleDrag);} else { Bangle.removeListener("stroke", handleStroke); }
}*/});
2023-07-07 16:51:40 +00:00
// initialize
cardLayout.update();
Bangle.loadWidgets();
2023-07-07 20:12:49 +00:00
loadLocalCards();
2023-07-07 16:51:40 +00:00
Bangle.on("touch", handleTouch);
if (settings.swipeGesture) { Bangle.on("drag", handleDrag); } else { Bangle.on("stroke", handleStroke); }
2023-07-07 16:51:40 +00:00
// On start: display the first card
g.clear();
draw();
2023-07-12 13:36:24 +00:00