feat(touch): add press/release detection with touch-down tracking
This commit is contained in:
@@ -143,6 +143,68 @@ public:
|
||||
_drv->updateHint(x, y, active);
|
||||
}
|
||||
|
||||
/// Show touch feedback - highlights the tile at given coordinates
|
||||
/// Returns true if a valid tile is being touched
|
||||
bool showTouchFeedback(int x, int y) {
|
||||
if(!_drv || _gridCols <= 0) return false;
|
||||
|
||||
// Transform touch coordinates
|
||||
_drv->transformTouch(&x, &y);
|
||||
|
||||
int headerH = 30;
|
||||
if(y < headerH) return false;
|
||||
|
||||
// Calculate which cell
|
||||
int cellW = _drv->width() / _gridCols;
|
||||
int cellH = (_drv->height() - headerH) / _gridRows;
|
||||
|
||||
int col = x / cellW;
|
||||
int row = (y - headerH) / cellH;
|
||||
|
||||
if(col < 0 || col >= _gridCols || row < 0 || row >= _gridRows)
|
||||
return false;
|
||||
|
||||
// Find which tile is at this position
|
||||
for(int i = 0; i < _tileCount; i++) {
|
||||
const TileLayout& lay = _layouts[i];
|
||||
if(lay.col <= col && col < lay.col + lay.cols &&
|
||||
lay.row <= row && lay.row + lay.rows > row) {
|
||||
// Found the tile - draw highlight via driver
|
||||
_drv->updateHint(lay.x, lay.y, true); // active=true means show feedback
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Clear touch feedback
|
||||
void clearTouchFeedback() {
|
||||
if(_drv)
|
||||
_drv->updateHint(0, 0, false); // active=false means clear
|
||||
}
|
||||
|
||||
/// Check if current position is still in same tile as touch-down
|
||||
bool isSameTile(int downX, int downY, int currentX, int currentY) const {
|
||||
if(!_drv || _gridCols <= 0 || downX < 0) return false;
|
||||
|
||||
int dx = downX, dy = downY;
|
||||
int cx = currentX, cy = currentY;
|
||||
|
||||
_drv->transformTouch(&dx, &dy);
|
||||
_drv->transformTouch(&cx, &cy);
|
||||
|
||||
int headerH = 30;
|
||||
int cellW = _drv->width() / _gridCols;
|
||||
int cellH = (_drv->height() - headerH) / _gridRows;
|
||||
|
||||
int downCol = dx / cellW;
|
||||
int downRow = (dy - headerH) / cellH;
|
||||
int curCol = cx / cellW;
|
||||
int curRow = (cy - headerH) / cellH;
|
||||
|
||||
return downCol == curCol && downRow == curRow;
|
||||
}
|
||||
|
||||
int width() { return _drv ? _drv->width() : 0; }
|
||||
int height() { return _drv ? _drv->height() : 0; }
|
||||
|
||||
|
||||
@@ -310,48 +310,62 @@ void DoorbellLogic::setScreen(ScreenID s) {
|
||||
}
|
||||
|
||||
int DoorbellLogic::handleTouch(const TouchEvent& evt) {
|
||||
if(!evt.pressed)
|
||||
return -1;
|
||||
// Handle press - show visual feedback
|
||||
if(evt.pressed) {
|
||||
// Reset inactivity timer on any touch
|
||||
_lastActivityMs = millis();
|
||||
|
||||
// Reset inactivity timer on any touch
|
||||
_lastActivityMs = millis();
|
||||
if(_state.screen == ScreenID::OFF) {
|
||||
Serial.printf("[%lu] [TOUCH] OFF → DASHBOARD\n", millis());
|
||||
setScreen(ScreenID::DASHBOARD);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(_state.screen == ScreenID::OFF) {
|
||||
Serial.printf("[%lu] [TOUCH] OFF → DASHBOARD\n", millis());
|
||||
setScreen(ScreenID::DASHBOARD);
|
||||
// Show touch feedback on press
|
||||
if(_state.screen == ScreenID::DASHBOARD) {
|
||||
_display->showTouchFeedback(evt.x, evt.y);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(_state.screen == ScreenID::DASHBOARD) {
|
||||
TileAction action = _display->handleDashboardTouch(evt.x, evt.y);
|
||||
if(action != TileAction::NONE) {
|
||||
Serial.printf("[DASH] Action: %d\n", (int)action);
|
||||
switch(action) {
|
||||
case TileAction::ALERT:
|
||||
onAlert("Manual Alert", "Tile tap");
|
||||
break;
|
||||
case TileAction::SILENCE:
|
||||
if(_state.deviceState == DeviceState::ALERTING)
|
||||
silenceAlert();
|
||||
break;
|
||||
case TileAction::STATUS:
|
||||
heartbeat();
|
||||
break;
|
||||
case TileAction::REBOOT:
|
||||
flushStatus("REBOOT (tile)");
|
||||
delay(500);
|
||||
ESP.restart();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
// Handle release - fire action if same tile
|
||||
if(evt.released) {
|
||||
// Clear feedback
|
||||
_display->clearTouchFeedback();
|
||||
|
||||
if(_state.screen == ScreenID::DASHBOARD) {
|
||||
// Only fire action if finger stayed on same tile
|
||||
if(evt.downX >= 0 && _display->isSameTile(evt.downX, evt.downY, evt.x, evt.y)) {
|
||||
TileAction action = _display->handleDashboardTouch(evt.downX, evt.downY);
|
||||
if(action != TileAction::NONE) {
|
||||
Serial.printf("[DASH] Action: %d\n", (int)action);
|
||||
switch(action) {
|
||||
case TileAction::ALERT:
|
||||
onAlert("Manual Alert", "Tile tap");
|
||||
break;
|
||||
case TileAction::SILENCE:
|
||||
if(_state.deviceState == DeviceState::ALERTING)
|
||||
silenceAlert();
|
||||
break;
|
||||
case TileAction::STATUS:
|
||||
heartbeat();
|
||||
break;
|
||||
case TileAction::REBOOT:
|
||||
flushStatus("REBOOT (tile)");
|
||||
delay(500);
|
||||
ESP.restart();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (int)action;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (int)action;
|
||||
}
|
||||
|
||||
if(_state.screen == ScreenID::ALERT) {
|
||||
Serial.println("[TOUCH] ALERT tap");
|
||||
return -1;
|
||||
if(_state.screen == ScreenID::ALERT) {
|
||||
Serial.println("[TOUCH] ALERT tap");
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
#include "ScreenState.h"
|
||||
|
||||
struct TouchEvent {
|
||||
bool pressed = false;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
bool pressed = false; // finger just touched down
|
||||
bool released = false; // finger just lifted (after being pressed)
|
||||
int x = 0; // current x position
|
||||
int y = 0; // current y position
|
||||
int downX = -1; // x position where touch started
|
||||
int downY = -1; // y position where touch started
|
||||
};
|
||||
|
||||
struct HoldState {
|
||||
|
||||
Reference in New Issue
Block a user