Skip to content

Commit bb9b6fb

Browse files
author
thyttan
committed
Merge branch 'slidertest' into app-loader
2 parents 4d8ff49 + 9a570b9 commit bb9b6fb

File tree

12 files changed

+257
-0
lines changed

12 files changed

+257
-0
lines changed

apps/slidertest/ChangeLog

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0.01: New App!

apps/slidertest/README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Slider Test app
2+
3+
- 1: A volume slider that hides when not interacted with. It uses the incrementing mode.
4+
- 2: A hidden slider that increments a preview of a change to the
5+
backdrop color. When the user stops interacting with it the backdrop
6+
is updated.
7+
- 3: An always visible slider that controls the brightness level.
8+
- 4: A non-interactable progressbar that follows the position in a media
9+
track playing on a connected android device.
10+
11+
A square will blink when messages with music state arrives.
12+
13+
The app is started:
14+
15+
![s](screenshot-0.png)
16+
17+
The hidden volume slider on the left is draged:
18+
19+
![s](screenshot-1.png)
20+
21+
The colour slider in the middle is draged:
22+
23+
![s](screenshot-2.png)
24+
25+
The colour slider is released, redrawing with a new backgdrop:
26+
27+
![s](screenshot-3.png)
28+
29+
The rounded brightness slider on the right is draged:
30+
31+
![s](screenshot-4.png)
32+
33+
The progress bar at the bottom tracks a song on an android device.
34+
35+
![s](screenshot-5.png)
36+
37+
## Usage
38+
39+
## Features
40+
41+
Name the function
42+
43+
## Controls
44+
45+
Name the buttons and what they are used for
46+
47+
## Requests
48+
49+
Name who should be contacted for support/update requests
50+
51+
## Creator
52+
53+
[thyttan](https://github.com/thyttan)

apps/slidertest/app-icon.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
require("heatshrink").decompress(atob("mEwwJC/AH4A/AH4AgA=="))

apps/slidertest/app.js

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
{
2+
/*
3+
let setDevMode = ()=>{
4+
Bangle.setLCDTimeout(0); // Easier to read the screen while developing.
5+
Bangle.setLocked(false);
6+
Bangle.setLCDBrightness(0.6);
7+
Bangle.setLCDPower(true);
8+
};
9+
setDevMode();
10+
*/
11+
12+
//// Drawing operations
13+
14+
Bangle.loadWidgets(); // So appRect takes widgets into account.
15+
let R = Bangle.appRect;
16+
17+
let backDropColor = [1,0,0];
18+
19+
let draw = (rect)=>{
20+
g.reset();
21+
if (rect) g.setClipRect(rect.x1, rect.y1, rect.x2, rect.y2);
22+
g.setColor(backDropColor[0],backDropColor[1],backDropColor[2]).fillRect(0,0,176,176);
23+
g.setColor(1,1,1).drawLine(xA, R.y, xA, yA).drawLine(xB, R.y, xB, yA);
24+
g.reset();
25+
Bangle.drawWidgets();
26+
};
27+
28+
let blink = ()=>{setTimeout(()=>{
29+
g.reset().setColor(backDropColor[1],backDropColor[0],backDropColor[2]).fillRect(R.x2/2-15,R.y2-29,R.x2/2-5,R.y2-19);
30+
setTimeout(()=>{g.reset().setColor(backDropColor[0],backDropColor[1],backDropColor[2]).fillRect(R.x2/2-15,R.y2-29,R.x2/2-5,R.y2-19);},100);
31+
},0);
32+
};
33+
34+
//// Functional logic
35+
36+
// Get audio levels from Android device
37+
let audioLevels = {u:30, c:15}; // Init with values to avoid "Uncaught Error: Cannot read property 'u' of undefined" if values were not gathered from Gadgetbridge.
38+
let audioHandler = (e)=>{audioLevels = e;print(audioLevels);};
39+
Bangle.on('audio', audioHandler);
40+
Bangle.musicControl("vg"); // vg = Volume Get level
41+
42+
// Handle music messages
43+
// Bangle.emit("message", type, msg);
44+
let trackPosition = 0;
45+
let trackDur = 30;
46+
let trackState = "pause";
47+
let messageHandler = (type, msg)=>{
48+
print("\n","type:"+type, "t:"+msg.t, "src:"+msg.src, "mode:"+msg.state, "pos:"+msg.position, "dur:"+msg.dur);
49+
if (type==='music' && msg.src=="musicstate") {
50+
trackState = msg.state;
51+
trackPosition = msg.position + (trackState==="play"?1:0); // +1 when playing to account for latency.
52+
trackDur = msg.dur;
53+
if (progressBar) {
54+
progressBar.f.stopAutoUpdate();
55+
initProgressBar();
56+
}
57+
blink(); // Indicate when a `musicstate` message arrived.
58+
}
59+
};
60+
Bangle.on('message', messageHandler);
61+
62+
// cbVolumeSlider is used with volumeSlider
63+
let cbVolumeSlider = (mode,fb)=>{
64+
if (mode =="incr") Bangle.musicControl(fb>0?"volumedown":"volumeup");
65+
if (mode =="remove") {
66+
audioLevels.c = fb;
67+
ebLast = 0;
68+
draw(volumeSlider.c.r);
69+
//progressBar.f.draw(progressBar.v.level);
70+
print(process.memory().usage);
71+
print("#drag handlers: " + Bangle["#ondrag"].length);
72+
}
73+
};
74+
75+
// cbColorSlider is used with progressBar
76+
let cbColorSlider = (mode,fb)=>{
77+
if (mode =="incr") {
78+
let l = colorSlider.v.level;
79+
print("color mode: " + l);
80+
if (l===0) backDropColor = [1,0,0];
81+
if (l===1) backDropColor = [0.75,0.25,0];
82+
if (l===2) backDropColor = [0.5,0.5,0];
83+
if (l===3) backDropColor = [0.25,0.75,0];
84+
if (l===4) backDropColor = [0,1,0];
85+
if (l===5) backDropColor = [0,0.75,0.25];
86+
if (l===6) backDropColor = [0,0.5,0.5];
87+
if (l===7) backDropColor = [0,0.25,0.75];
88+
if (l===8) backDropColor = [0,0,1];
89+
g.setColor(backDropColor[0],backDropColor[1],backDropColor[2]).fillRect(xA+1,R.y,xB-1,yA);
90+
}
91+
if (mode =="remove") {
92+
init();
93+
}
94+
};
95+
96+
// cbBrightnessSlider is used with progressBar
97+
let cbBrightnessSlider = (mode,fb)=>{
98+
if (mode =="map") Bangle.setLCDBrightness(fb/100);
99+
if (mode =="remove") print("remove handling triggered")
100+
};
101+
102+
// cbProgressbar is used with progressBar
103+
let cbProgressbar = (mode,fb)=>{
104+
print("progressbar callback");
105+
//let currentLevel = fb;
106+
//print(process.memory().usage);
107+
//print("#drag handlers: " + Bangle["#ondrag"].length)
108+
};
109+
110+
// For use when dividing the parts of the screen for different sliders.
111+
let xA = R.x+4*R.w/8;
112+
let xB = R.x+11*R.w/16;
113+
let yA = R.x2-Math.round(R.w/20)-5;
114+
115+
// volumeSlider controls volume level on the android device.
116+
let volumeSlider=require("Slider").create(
117+
cbVolumeSlider,
118+
{mode:"incr", steps:audioLevels.u, initLevel:audioLevels.c, horizontal:false, rounded:false, height:R.h-21, timeout:0.5, propagateDrag:true, xStart:R.x+4, dragRect:{x:R.x, y:0, x2:xA-1, y2: R.y2}}
119+
);
120+
121+
// colorSlider controls the background color of this app. It uses custom graphics defined in its callback function.
122+
let colorSlider = require("Slider").create(
123+
cbColorSlider,
124+
{mode:"incr", steps:8, drawableSlider:false, xStart: R.x2-2*R.w/4, height:R.h-21, initLevel:0, propagateDrag:true, timeout:0, dragRect:{x:xA, y:0, x2:xB-1, y2: R.y2}}
125+
);
126+
127+
// brightnessSlider controls the brightness of the Bangle.js
128+
let brightnessSlider = require("Slider").create(
129+
cbBrightnessSlider,
130+
{mode:"map", steps:100, height:R.h-21, timeout:0, initLevel:100*0.0, propagateDrag:true, dragRect:{x:xB, y:0, x2:R.x2, y2: R.y2}, rounded:true}
131+
);
132+
133+
// progressBar follows the media track playing on the android device.
134+
let progressBar;
135+
let initProgressBar = ()=>{
136+
progressBar = require("Slider").create(
137+
cbProgressbar,
138+
{dragableSlider:false, steps:trackDur, initLevel:trackPosition, horizontal:true, rounded:false, timeout:0, immediateDraw:false, propagateDrag:true, width:Math.round(R.w/20), xStart:R.x2-R.w/20-4, oversizeR:10, oversizeL:10, autoProgress:true, yStart: R.x+4, height: R.w-8}
139+
);
140+
progressBar.f.draw(progressBar.v.level);
141+
if (trackState==="play") progressBar.f.startAutoUpdate();
142+
};
143+
144+
let init = ()=> {
145+
draw();
146+
if (progressBar) {
147+
progressBar.f.draw(progressBar.v.level);
148+
} else {initProgressBar();}
149+
brightnessSlider.f.draw(brightnessSlider.v.level);
150+
};
151+
152+
// let isAnySliderDragActive = ()=>{
153+
// return (volumeSlider.v.dragActive || brightnessSlider.v.dragActive || colorSlider.v.dragActive || progressBar.v.dragActive);
154+
// };
155+
156+
let ebLast = 0; // Used for fix/Hack needed because there is a timeout before the slider is called upon.
157+
Bangle.on('drag', (e)=>{
158+
if (ebLast==0) {
159+
// if (!isAnySliderDragActive()) {
160+
if (e.y<yA) {
161+
if (e.x<xA && !volumeSlider.v.dragActive) {
162+
Bangle.musicControl("vg"); // vg = Volume Get level
163+
setTimeout(()=>{ // Timeout so gadgetbridge has time to send back volume levels.
164+
volumeSlider.c.steps=audioLevels.u;
165+
volumeSlider.v.level=audioLevels.c;
166+
},200);
167+
Bangle.prependListener('drag', volumeSlider.f.dragSlider);
168+
}
169+
if (e.x>=xA && e.x<xB && !colorSlider.v.dragActive) {
170+
Bangle.prependListener('drag', colorSlider.f.dragSlider);
171+
}
172+
if (e.x>=xB && !brightnessSlider.v.dragActive) {
173+
Bangle.prependListener('drag', brightnessSlider.f.dragSlider);
174+
}
175+
}
176+
if (e.y>=yA) {
177+
progressBar.f.dragSlider&&Bangle.prependListener('drag',progressBar.f.dragSlider);
178+
}
179+
// }
180+
}
181+
ebLast = e.b;
182+
});
183+
184+
init();
185+
186+
//print("#drag handlers: " + Bangle["#ondrag"].length)
187+
}

apps/slidertest/app.png

1.58 KB
Loading

apps/slidertest/metadata.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{ "id": "slidertest",
2+
"name": "Slider test app",
3+
"shortName":"Slider test",
4+
"version":"0.01",
5+
"description": "A detailed description of my great app",
6+
"icon": "app.png",
7+
"tags": "ui",
8+
"supports": ["BANGLEJS2"],
9+
"readme": "README.md",
10+
"storage": [
11+
{"name":"slidertest.img","url":"app-icon.js","evaluate":"true"},
12+
{"name":"slidertest.app.js","url":"app.js"}
13+
]
14+
}
15+

apps/slidertest/screenshot-0.png

2.8 KB
Loading

apps/slidertest/screenshot-1.png

3.19 KB
Loading

apps/slidertest/screenshot-2.png

2.77 KB
Loading

apps/slidertest/screenshot-3.png

2.75 KB
Loading

0 commit comments

Comments
 (0)