-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3654 from retcurve/scrolly
New app: scrolly
- Loading branch information
Showing
7 changed files
with
310 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
0.01: New app! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# ![Image](app.png "icon") Scrolly | ||
|
||
**Note:** This app requires a [keyboard library](https://banglejs.com/apps/?c=textinput#) | ||
|
||
Scrolly is a simple app designed to display scrolling text across your screen in a clean and dynamic way. Perfect for announcements or just for fun! | ||
|
||
![Image](screenshot.gif "screenshot") | ||
|
||
## Usage | ||
|
||
* **Edit Text:** Tap the text area or the pencil icon to modify your message. | ||
* **Access Settings:** Tap the gear icon to open the settings menu. | ||
* **Start Scrolling:** Tap the play icon to begin the scrolling text. | ||
|
||
## Features | ||
|
||
* **Customizable Scroll Speed:** Control how fast or slow the text moves. | ||
* **Multiple Scroll Directions:** Choose from 0, 90, 180, or 270 degree rotation of the screen | ||
* **No Screen Dimming:** Optionally keep your screen bright and active while the text scrolls | ||
* **Countdown:** Start your scroll with an optional countdown timer, giving your audience a brief pause before the message begins to move. | ||
* **Persistent settings:** Automatically remembers your last entered message and settings when you exit the app, so you can pick up right where you left off without having to re-enter everything. | ||
|
||
## Author | ||
|
||
Woogal [github](https://github.com/retcurve) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require("heatshrink").decompress(atob("mEwgI63nfcAp4AEgeAgPAApoXHAqpNdAAJBFApYAJNa5NZAGQA==")) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,262 @@ | ||
Bangle.loadWidgets(); | ||
|
||
Graphics.prototype.setFontDoto = function(scale) { | ||
// Actual height 40 (39 - 0) | ||
// 1 BPP | ||
return this.setFontCustom( | ||
E.toString(require('heatshrink').decompress(atob('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'))), | ||
32, | ||
atob("GAwQFBQUFAwQEBQUEBQQFBQUFBQUFBQUFBQQEBQUFBQUFBQUFBQUFBQQFBQUFBQUFBQUFBQUFBQUFBQQFBAUFBAUFBQUFBQUFBAUFBAUFBQUFBQUFBQUFBQUFBQMFBQAFgsQACcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADBQUExQGFBAUFBgXABQUEBYNDBAUFAwQCxQYHBwdFBQUFBQUFBQUFBQUFBAQEBAUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEBAQEBQUFBQUFBQUFBQUFBQUFBQ="), | ||
40+(scale<<8)+(1<<16) | ||
); | ||
}; | ||
|
||
// Load settings | ||
const SETTINGS = 'scrolly.json'; | ||
let settings = Object.assign({ | ||
maxBright: true, | ||
doNotDim: true, | ||
speed: 50, | ||
rotate: 0, | ||
countdown: true, | ||
lastText: '', | ||
rememberText: true | ||
}, require('Storage').readJSON(SETTINGS, true) || {}); | ||
|
||
let x; | ||
let scrollInterval, countdownInterval; | ||
let countdownNum; | ||
let text = settings.lastText; | ||
let originalOptions = Bangle.getOptions(); | ||
let brightness = require('Storage').readJSON('setting.json').brightness; | ||
|
||
// Main interface | ||
var Layout = require("Layout"); | ||
var layout = new Layout( { | ||
type: 'v', c: [ | ||
{ // Text area | ||
type: 'txt', | ||
font: '6x8:2', | ||
label: text ? text : 'Enter text...', // Show prompt if text not set | ||
col: text ? g.theme.fg2 : '#555', // Grey text if prompt shown | ||
id: 'text', | ||
wrap: true, | ||
height: Bangle.appRect.h - 52, // Icons are 32px, padding 10px top and bottom | ||
width: g.getWidth(), | ||
valign:0, | ||
cb: l=> editText() // Tapping the text area triggers the same editor as the pen icon | ||
}, | ||
{ | ||
type: 'h', c: [ | ||
{ // Edit icon | ||
type: 'img', | ||
pad: 10, | ||
src: require("heatshrink").decompress(atob("kEg4kA///6f8gH41VStP6gGYBYPv2dV1uyykkvOe+/LrVNteW2sA3Bc4hnM4APM5mY5geM51m3ogL5mGs1r7geK48bswgL5lxiO2EAJBIDwMRiIgC3ggHDwURilGs25B4weDiNCkgPIDwkikV7xgeLkUvrpPGDw311guFDw9aD0sMyIeMB4O2DxgPCsIeLgHNW4MSDxUA5IPBsgeKgHOB4Nmp4eJgHLB4W/DxMM522s279PDDxEM7HuxPc5kwB5Pd5nMFhAPDDZQAyA=")), | ||
cb: l=> editText() | ||
}, | ||
{ // Settings icon | ||
type: 'img', | ||
pad: 10, | ||
src: require("heatshrink").decompress(atob("kEg4UA///6ec1VSqOMEzUVqoHFqoHUisBA4NAiglDr/1qtUCofq1YZDqte1Wq2oZBDoNaA4OlA4dqA4OpqtQA4Pq1EqEANAF4Oq0EK1QvCguqwEC1VQA4wPKD4IPFF4InBF4MAH4xHCvQHB1oHDL4ofBq4HB6pvDqt//p/DisFR4QHCV64HJiolEAAw=")), | ||
cb: l=> showSettings() | ||
}, | ||
{ // Scroll icon | ||
type: 'img', | ||
pad: 10, | ||
src: require("heatshrink").decompress(atob("kEg4UB8EH/4AC+mnqoAQqAgBA4goCgoGCqgxDA4VAA4cVCwgYEA4kBDwogCGoMD+AHFgWsFAYHC1XAA4Q2BA4OwA42oA4wYCgoHEDAIHNC42rMAQHD0AvGI4ZPCCwQHDgYWCM4J3HA4qHBS5CnHYwTIFDwoQECwTJDAwoAFA")), | ||
id: 'scrollBtn', | ||
cb: l=>{ | ||
if (text) { | ||
scrollText(); | ||
} else { | ||
E.showAlert('No text to scroll').then(() => { | ||
layout.setUI(); | ||
layout.render(); | ||
}); | ||
} | ||
} | ||
}, | ||
] | ||
} | ||
] | ||
}, {back: load}); | ||
|
||
// Display scrolling text | ||
function scrollText() { | ||
require("widget_utils").hide(); | ||
|
||
Bangle.setUI({ | ||
mode:"custom", | ||
btn: () => { // Button returns to main interface | ||
if (scrollInterval) // Stop scroll | ||
clearInterval(scrollInterval); | ||
if (countdownInterval) // Stop countdown | ||
clearInterval(countdownInterval); | ||
|
||
// Reset screen to original settings | ||
g.setRotation(0); | ||
Bangle.setOptions(originalOptions); | ||
Bangle.setLCDBrightness(brightness); | ||
|
||
// Draw the main interface | ||
require("widget_utils").show(); | ||
g.clearRect(Bangle.appRect); | ||
layout.setUI(); | ||
layout.render(); | ||
} | ||
}); | ||
|
||
// Setup screen | ||
if (settings.doNotDim) { // Don't lock or turn off the backlight while scrolling | ||
Bangle.setOptions({backlightTimeout: 0, lockTimeout: 0}); | ||
Bangle.setBacklight(1); | ||
} else { // For some reason the screen locking resets the font style and alignment, so don't allow this to happen while scrolling | ||
Bangle.setOptions({lockTimeout: 0}); | ||
} | ||
if (settings.maxBright) { | ||
Bangle.setLCDBrightness(1); | ||
} | ||
g.setRotation(settings.rotate); | ||
|
||
g.setFontDoto(4); | ||
g.setColor(g.theme.fg); | ||
g.setBgColor(g.theme.bg); | ||
|
||
if (settings.countdown) { // Display a countdown timer before scrolling | ||
g.setFontAlign(0, 0); | ||
countdownNum = 3; | ||
countdown(); | ||
countdownInterval = setInterval(() => { | ||
if (countdownNum == 0) { | ||
clearInterval(countdownInterval); | ||
startScrolling(); | ||
} else { | ||
countdown(); | ||
} | ||
}, 1000); | ||
} else { // No countdown, so just scroll | ||
startScrolling(); | ||
} | ||
} | ||
|
||
// Start the scroll animation | ||
function startScrolling() { | ||
g.clear(); | ||
g.setFontAlign(-1, 0); // Vertical align text | ||
|
||
x=g.getWidth(); // Start the text just off screen | ||
|
||
scrollInterval = setInterval(() => { | ||
g.clear(); | ||
g.drawString(text, x, g.getHeight()/2); | ||
x=x-10; | ||
if (x<-g.stringWidth(text)) { // Loop the text | ||
x=g.getWidth(); | ||
} | ||
}, settings.speed); | ||
} | ||
|
||
// Show countdown timer | ||
function countdown() { | ||
g.clear(); | ||
g.drawString(countdownNum, g.getWidth()/2, g.getHeight()/2); | ||
countdownNum--; | ||
} | ||
|
||
// Load keyboard and set text | ||
function editText() { | ||
try { | ||
require("textinput").input({text:text}).then(result => { | ||
text = result; | ||
if (settings.rememberText) { | ||
setSetting('lastText', text); | ||
} | ||
layout.text.label = text ? text : 'Enter text...'; // Show prompt if text not set | ||
layout.text.col = text ? g.theme.fg2 : '#555'; // Grey text if prompt shown | ||
layout.setUI(); | ||
layout.render(); | ||
Bangle.drawWidgets(); | ||
}); | ||
} catch (error) { | ||
E.showAlert('Please install a keyboard app').then(() => { | ||
layout.setUI(); | ||
layout.render(); | ||
}); | ||
} | ||
} | ||
|
||
// Save setting key | ||
function setSetting(key,value) { | ||
settings[key] = value; | ||
require('Storage').writeJSON(SETTINGS, settings); | ||
} | ||
|
||
// Helper method which uses int-based menu item for set of string values and their labels | ||
function stringItems(key, startvalue, values, labels) { | ||
return { | ||
value: (startvalue === undefined ? 0 : values.indexOf(startvalue)), | ||
format: v => labels[v], | ||
min: 0, | ||
max: values.length - 1, | ||
wrap: true, | ||
step: 1, | ||
onchange: v => { | ||
setSetting(key,values[v]); | ||
} | ||
}; | ||
} | ||
|
||
// Helper method which breaks string set settings down to local settings object | ||
function stringInSettings(name, values, labels) { | ||
return stringItems(name,settings[name], values, labels); | ||
} | ||
|
||
// Settings menu | ||
function showSettings() { | ||
E.showMenu({ | ||
'' : { 'title' : 'Settings' }, | ||
'< Back' : () => { | ||
g.clearRect(Bangle.appRect); | ||
layout.setUI(); | ||
layout.render(); | ||
}, | ||
'Rotate': stringInSettings('rotate', [0, 1, 2, 3], [0, 90, 180, 270]), | ||
'Speed': stringInSettings('speed', [10, 50, 80], ['Fast', 'Medium', 'Slow']), | ||
'Max bright': { | ||
value: !!settings.maxBright, | ||
onchange: v => { | ||
setSetting('maxBright', v); | ||
}, | ||
}, | ||
"Don't dim": { | ||
value: !!settings.doNotDim, | ||
onchange: v => { | ||
setSetting('doNotDim', v); | ||
}, | ||
}, | ||
'Countdown': { | ||
value: !!settings.countdown, | ||
onchange: v => { | ||
setSetting('countdown', v); | ||
}, | ||
}, | ||
'Remember text': { | ||
value: !!settings.rememberText, | ||
onchange: v => { | ||
setSetting('rememberText', v); | ||
if (v) { | ||
setSetting('lastText', text); | ||
} else { | ||
setSetting('lastText', ''); | ||
} | ||
}, | ||
} | ||
}); | ||
} | ||
|
||
// Initial layout render | ||
g.clear(); | ||
Bangle.drawWidgets(); | ||
layout.render(); | ||
|
||
|
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
{ | ||
"id": "scrolly", | ||
"name": "Scrolly", | ||
"shortName":"Scrolly", | ||
"icon": "app.png", | ||
"screenshots" : [ { "url":"screenshot.gif" } ], | ||
"version":"0.01", | ||
"description": "Scrolly is a simple app designed to display scrolling text across your screen in a clean and dynamic way. Perfect for announcements or just for fun!", | ||
"readme":"README.md", | ||
"type": "app", | ||
"tags": "tool", | ||
"supports": ["BANGLEJS2"], | ||
"dependencies": {"textinput":"type"}, | ||
"storage": [ | ||
{"name":"scrolly.app.js","url":"app.js"}, | ||
{"name":"scrolly.img","url":"app-icon.js","evaluate":true} | ||
], | ||
"data": [ | ||
{"name":"scrolly.json"} | ||
] | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.