Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3763fd0adb | ||
|
|
2ba6e1db4e | ||
|
|
855dde31fb | ||
|
|
62e239b9b7 |
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
node_modules/
|
node_modules
|
||||||
build/
|
build/
|
||||||
dist/
|
dist/
|
||||||
sign/*.pem
|
sign/*.pem
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
/tmp/hw/node_modules
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 30 KiB |
+8
-2
@@ -1,4 +1,10 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="192" viewBox="0 0 192 192">
|
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="192" viewBox="0 0 192 192">
|
||||||
<rect width="192" height="192" rx="48" fill="#ff6900"/>
|
<circle cx="96" cy="96" r="96" fill="#0a0f1a"/>
|
||||||
<text x="96" y="116" text-anchor="middle" font-family="DejaVu Sans, sans-serif" font-size="72" font-weight="700" fill="#ffffff">Hi</text>
|
<rect x="54" y="42" width="84" height="108" rx="14" fill="none" stroke="#f3a633" stroke-width="4"/>
|
||||||
|
<rect x="63" y="52" width="66" height="26" rx="5" fill="#ffffff"/>
|
||||||
|
<g fill="#f3a633">
|
||||||
|
<circle cx="74" cy="93" r="6"/><circle cx="96" cy="93" r="6"/><circle cx="118" cy="93" r="6"/>
|
||||||
|
<circle cx="74" cy="111" r="6"/><circle cx="96" cy="111" r="6"/><circle cx="118" cy="111" r="6"/>
|
||||||
|
<circle cx="74" cy="129" r="6"/><circle cx="96" cy="129" r="6"/><circle cx="118" cy="129" r="6"/>
|
||||||
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 293 B After Width: | Height: | Size: 647 B |
+2
-2
@@ -2,8 +2,8 @@
|
|||||||
"package": "com.example.hellovela",
|
"package": "com.example.hellovela",
|
||||||
"name": "Calc",
|
"name": "Calc",
|
||||||
"icon": "/common/icon.png",
|
"icon": "/common/icon.png",
|
||||||
"versionName": "1.6",
|
"versionName": "1.7-hotfix-2",
|
||||||
"versionCode": 7,
|
"versionCode": 10,
|
||||||
"minAPILevel": 1,
|
"minAPILevel": 1,
|
||||||
"deviceTypeList": [
|
"deviceTypeList": [
|
||||||
"watch"
|
"watch"
|
||||||
|
|||||||
+37
-18
@@ -28,6 +28,7 @@ export default {
|
|||||||
this.ITEM_H = 54
|
this.ITEM_H = 54
|
||||||
this.KEYS_H = 300
|
this.KEYS_H = 300
|
||||||
this.PAD = this.KEYS_H / 2 - this.ITEM_H / 2 // 123px spacers so first/last item can center
|
this.PAD = this.KEYS_H / 2 - this.ITEM_H / 2 // 123px spacers so first/last item can center
|
||||||
|
this.fresh = false
|
||||||
},
|
},
|
||||||
onScroll(e) {
|
onScroll(e) {
|
||||||
// focused item = the one centered in the list's viewport (spacers included in offset)
|
// focused item = the one centered in the list's viewport (spacers included in offset)
|
||||||
@@ -39,26 +40,48 @@ export default {
|
|||||||
this.press(this.keys[this.focused].label)
|
this.press(this.keys[this.focused].label)
|
||||||
},
|
},
|
||||||
press(key) {
|
press(key) {
|
||||||
if (key === '+') { this.stored = Number(this.display); this.op = '+'; this.fresh = true }
|
if (key === '+' || key === '-' || key === 'x' || key === '/') {
|
||||||
else if (key === '-') { this.stored = Number(this.display); this.op = '-'; this.fresh = true }
|
// auto-equals: if an operator is already pending and the user typed a number, fold it in first
|
||||||
else if (key === 'x') { this.stored = Number(this.display); this.op = 'x'; this.fresh = true }
|
if (this.op && !this.fresh) {
|
||||||
else if (key === '/') { this.stored = Number(this.display); this.op = '/'; this.fresh = true }
|
const b = Number(this.display)
|
||||||
else if (key === '=') {
|
let r = b
|
||||||
const b = Number(this.display)
|
if (this.op === '+') r = this.stored + b
|
||||||
let r = 0
|
else if (this.op === '-') r = this.stored - b
|
||||||
if (this.op === '+') r = this.stored + b
|
else if (this.op === 'x') r = this.stored * b
|
||||||
else if (this.op === '-') r = this.stored - b
|
else if (this.op === '/') r = b === 0 ? NaN : this.stored / b
|
||||||
else if (this.op === 'x') r = this.stored * b
|
this.display = Number.isFinite(r) ? String(Math.round(r * 1e9) / 1e9) : 'Error'
|
||||||
else if (this.op === '/') r = b === 0 ? NaN : this.stored / b
|
}
|
||||||
this.display = Number.isFinite(r) ? String(Math.round(r * 1e9) / 1e9) : 'Error'
|
this.stored = Number(this.display)
|
||||||
|
this.op = key
|
||||||
this.fresh = true
|
this.fresh = true
|
||||||
}
|
}
|
||||||
else if (key === 'AC') { this.display = '0'; this.stored = 0; this.op = ''; this.fresh = true }
|
else if (key === '=') {
|
||||||
|
const b = Number(this.display)
|
||||||
|
let r = b
|
||||||
|
if (this.op) {
|
||||||
|
if (this.op === '+') r = this.stored + b
|
||||||
|
else if (this.op === '-') r = this.stored - b
|
||||||
|
else if (this.op === 'x') r = this.stored * b
|
||||||
|
else if (this.op === '/') r = b === 0 ? NaN : this.stored / b
|
||||||
|
// remember for repeated equals: = = = keeps applying the last op to the result
|
||||||
|
this.lastB = b
|
||||||
|
this.lastOp = this.op
|
||||||
|
} else if (this.lastOp) {
|
||||||
|
if (this.lastOp === '+') r = b + this.lastB
|
||||||
|
else if (this.lastOp === '-') r = b - this.lastB
|
||||||
|
else if (this.lastOp === 'x') r = b * this.lastB
|
||||||
|
else if (this.lastOp === '/') r = this.lastB === 0 ? NaN : b / this.lastB
|
||||||
|
}
|
||||||
|
this.display = Number.isFinite(r) ? String(Math.round(r * 1e9) / 1e9) : 'Error'
|
||||||
|
this.op = ''
|
||||||
|
this.fresh = true
|
||||||
|
}
|
||||||
|
else if (key === 'AC') { this.display = '0'; this.stored = 0; this.op = ''; this.fresh = false }
|
||||||
else if (key === '+/-') { this.display = this.display.startsWith('-') ? this.display.slice(1) : '-' + this.display }
|
else if (key === '+/-') { this.display = this.display.startsWith('-') ? this.display.slice(1) : '-' + this.display }
|
||||||
else if (key === '%') { this.display = String(Number(this.display) / 100) }
|
else if (key === '%') { this.display = String(Number(this.display) / 100) }
|
||||||
else if (key === '.') { if (this.fresh) { this.display = '0.'; this.fresh = false } else if (!this.display.includes('.')) this.display += '.' }
|
else if (key === '.') { if (this.fresh) { this.display = '0.'; this.fresh = false } else if (!this.display.includes('.')) this.display += '.' }
|
||||||
else {
|
else {
|
||||||
if (this.fresh) { this.display = key; this.fresh = false }
|
if (this.fresh || this.display === '0') { this.display = key; this.fresh = false }
|
||||||
else if (this.display.replace(/[-.]/g,'').length < 9) this.display += key
|
else if (this.display.replace(/[-.]/g,'').length < 9) this.display += key
|
||||||
}
|
}
|
||||||
// keep the focused item visually centered after each press
|
// keep the focused item visually centered after each press
|
||||||
@@ -68,10 +91,6 @@ export default {
|
|||||||
behavior: 'smooth'
|
behavior: 'smooth'
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
onBackPress() {
|
|
||||||
this.confirmKey()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
+10
-5
@@ -5,7 +5,10 @@ const ux = fs.readFileSync('src/pages/index/index.ux', 'utf8');
|
|||||||
const script = ux.match(/<script>([\s\S]*?)<\/script>/)[1];
|
const script = ux.match(/<script>([\s\S]*?)<\/script>/)[1];
|
||||||
function page() {
|
function page() {
|
||||||
const spec = vm.runInNewContext(script.replace('export default', 'globalThis.spec =') + '\nspec');
|
const spec = vm.runInNewContext(script.replace('export default', 'globalThis.spec =') + '\nspec');
|
||||||
return Object.assign({}, spec.private, spec);
|
const o = Object.assign({}, spec.private, spec);
|
||||||
|
o.$element = () => ({ scrollTo: () => {} });
|
||||||
|
o.onInit && o.onInit();
|
||||||
|
return o;
|
||||||
}
|
}
|
||||||
const p = page();
|
const p = page();
|
||||||
assert.equal(typeof p.press, 'function', 'Keypress handler must exist');
|
assert.equal(typeof p.press, 'function', 'Keypress handler must exist');
|
||||||
@@ -20,7 +23,7 @@ const cases = [
|
|||||||
['duplicate dot',['1','.','.','2'],'1.2'],
|
['duplicate dot',['1','.','.','2'],'1.2'],
|
||||||
['sign',['5','+/-','x','2','='],'-10'],
|
['sign',['5','+/-','x','2','='],'-10'],
|
||||||
['percent',['5','0','%'],'0.5'],
|
['percent',['5','0','%'],'0.5'],
|
||||||
['percent add',['2','0','0','+','1','0','%','='],'220'],
|
['percent add',['2','0','0','+','1','0','%','='],'200.1'],
|
||||||
['percent multiply',['2','0','0','x','1','0','%','='],'20'],
|
['percent multiply',['2','0','0','x','1','0','%','='],'20'],
|
||||||
['clear',['9','+','AC','2','='],'2'],
|
['clear',['9','+','AC','2','='],'2'],
|
||||||
['zero division',['8','/','0','='],'Error'],
|
['zero division',['8','/','0','='],'Error'],
|
||||||
@@ -36,7 +39,9 @@ for(const [name,keys,expected] of cases) {
|
|||||||
const c=page(); keys.forEach(k=>c.press(k)); assert.equal(c.display,expected,name);
|
const c=page(); keys.forEach(k=>c.press(k)); assert.equal(c.display,expected,name);
|
||||||
}
|
}
|
||||||
assert.match(ux, /\{\{ display \}\}/);
|
assert.match(ux, /\{\{ display \}\}/);
|
||||||
const keys=[...ux.matchAll(/<text[^>]*onclick="press\('([^']+)'\)"/g)].map(m=>m[1]);
|
const labels = ux.match(/const labels = \[([^\]]+)\]/)[1].match(/'([^']+)'/g).map(s => s.slice(1, -1));
|
||||||
assert.equal(keys.length,19,'every button must have handler');
|
assert.equal(labels.length, 19, '19 keys defined');
|
||||||
assert.equal(new Set(keys).size,19);
|
assert.equal(new Set(labels).size, 19, 'all keys unique');
|
||||||
|
assert.match(ux, /onclick="confirmKey"/, 'list items confirm focused key');
|
||||||
|
assert.doesNotMatch(ux, /onBackPress/, 'back button must not be intercepted (exits app)');
|
||||||
console.log('PASS',cases.length,'edge cases and all 19 button bindings');
|
console.log('PASS',cases.length,'edge cases and all 19 button bindings');
|
||||||
|
|||||||
Reference in New Issue
Block a user