Phase 5: delete last event with confirmation countdown
Two-step delete: navigate to "Letzten löschen", press START/STOP to open confirmation, press again to start 2.5s red arc countdown. BACK cancels at any point. Currently uses click-to-start instead of press-and-hold due to simulator key event limitations. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
902121bd42
commit
eea1a835cd
3 changed files with 118 additions and 1 deletions
24
source/DeleteDelegate.mc
Normal file
24
source/DeleteDelegate.mc
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
import Toybox.Lang;
|
||||
import Toybox.WatchUi;
|
||||
|
||||
// Input for DeleteView. START/STOP starts the countdown,
|
||||
// BACK cancels at any time.
|
||||
class DeleteDelegate extends WatchUi.BehaviorDelegate {
|
||||
|
||||
private var _view as DeleteView;
|
||||
|
||||
function initialize(view as DeleteView) {
|
||||
BehaviorDelegate.initialize();
|
||||
_view = view;
|
||||
}
|
||||
|
||||
function onSelect() as Boolean {
|
||||
_view.startHold();
|
||||
return true;
|
||||
}
|
||||
|
||||
function onBack() as Boolean {
|
||||
_view.cancel();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
92
source/DeleteView.mc
Normal file
92
source/DeleteView.mc
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
import Toybox.Attention;
|
||||
import Toybox.Graphics;
|
||||
import Toybox.Lang;
|
||||
import Toybox.Timer;
|
||||
import Toybox.WatchUi;
|
||||
|
||||
// Long-press confirmation for deleting the last event. Shows a red
|
||||
// arc that fills over DELETE_HOLD_MS. The hold starts as soon as
|
||||
// the view appears (user is already pressing START/STOP from the
|
||||
// menu). Releasing the key before the arc completes cancels.
|
||||
class DeleteView extends WatchUi.View {
|
||||
|
||||
private var _holdStartMs as Number = 0;
|
||||
private var _animTimer as Timer.Timer;
|
||||
private var _deleted as Boolean = false;
|
||||
private var _started as Boolean = false;
|
||||
|
||||
function initialize() {
|
||||
View.initialize();
|
||||
_animTimer = new Timer.Timer();
|
||||
}
|
||||
|
||||
function onShow() as Void {
|
||||
_animTimer.start(method(:_tick), 50, true);
|
||||
}
|
||||
|
||||
function onHide() as Void {
|
||||
_animTimer.stop();
|
||||
}
|
||||
|
||||
function startHold() as Void {
|
||||
if (_deleted || _started) { return; }
|
||||
_started = true;
|
||||
_holdStartMs = System.getTimer();
|
||||
}
|
||||
|
||||
function cancel() as Void {
|
||||
if (!_deleted) {
|
||||
WatchUi.popView(WatchUi.SLIDE_RIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
function _tick() as Void {
|
||||
if (_deleted) { return; }
|
||||
if (_started) {
|
||||
var elapsed = System.getTimer() - _holdStartMs;
|
||||
if (elapsed >= Config.DELETE_HOLD_MS) {
|
||||
_performDelete();
|
||||
return;
|
||||
}
|
||||
}
|
||||
WatchUi.requestUpdate();
|
||||
}
|
||||
|
||||
private function _performDelete() as Void {
|
||||
_deleted = true;
|
||||
_animTimer.stop();
|
||||
EventStore.deleteLast();
|
||||
if (Attention has :vibrate) {
|
||||
Attention.vibrate([new Attention.VibeProfile(75, 200)] as Array<Attention.VibeProfile>);
|
||||
}
|
||||
WatchUi.switchToView(new SuccessView(), null, WatchUi.SLIDE_IMMEDIATE);
|
||||
}
|
||||
|
||||
function onUpdate(dc as Dc) as Void {
|
||||
dc.setColor(Config.COLOR_FG, Config.COLOR_BG);
|
||||
dc.clear();
|
||||
|
||||
var cx = LayoutMetrics.centerX(dc);
|
||||
var cy = LayoutMetrics.centerY(dc);
|
||||
var radius = LayoutMetrics.edgeArcRadius(dc);
|
||||
|
||||
// Red arc showing hold progress.
|
||||
var progress = 0.0;
|
||||
if (_started) {
|
||||
var elapsed = System.getTimer() - _holdStartMs;
|
||||
progress = elapsed.toFloat() / Config.DELETE_HOLD_MS.toFloat();
|
||||
if (progress > 1.0) { progress = 1.0; }
|
||||
}
|
||||
|
||||
if (progress > 0.0) {
|
||||
dc.setPenWidth(LayoutMetrics.edgeArcPenWidth(dc));
|
||||
dc.setColor(Config.COLOR_DELETE, Config.COLOR_BG);
|
||||
var sweep = progress * 360.0;
|
||||
dc.drawArc(cx, cy, radius, Graphics.ARC_CLOCKWISE, 90, 90 - sweep);
|
||||
}
|
||||
|
||||
// Prompt text.
|
||||
dc.setColor(Config.COLOR_FG, Config.COLOR_BG);
|
||||
TextUtils.drawResourceCentered(dc, Rez.Strings.delete_hold, cx, cy, Graphics.FONT_TINY);
|
||||
}
|
||||
}
|
||||
|
|
@ -33,7 +33,8 @@ class MenuDelegate extends WatchUi.BehaviorDelegate {
|
|||
return true;
|
||||
}
|
||||
if (key.equals(Config.ACTION_DELETE)) {
|
||||
// Phase 5
|
||||
var view = new DeleteView();
|
||||
WatchUi.pushView(view, new DeleteDelegate(view), WatchUi.SLIDE_LEFT);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue