refactor(input): compile the disabled diagnostics and screenshot-blur subsystems out of normal builds
TextInputDiagnostics.enabled and kBlurArtwork were mutable/const-false flags nothing ever set, yet the diagnostics side eagerly built log strings on the gamepad and key-simulator hot paths on every event. Both flags are now const bool.fromEnvironment (PLEZY_TEXT_INPUT_DIAGNOSTICS / PLEZY_BLUR_ARTWORK) so the branches const-fold away, every eager interpolation sits behind a guard, and screenshot blurring stays one dart-define away. The vowel-rotation title obfuscation had no consumer need beyond artwork blur and is gone.
This commit is contained in:
@@ -329,15 +329,19 @@ class GamepadService with WindowListener {
|
||||
}
|
||||
|
||||
Future<void> _setNativeTextInputFocused(bool focused) async {
|
||||
_logGamepadDiag('setNativeTextInputFocused requested focused=$focused current=$_nativeTextInputFocused');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('setNativeTextInputFocused requested focused=$focused current=$_nativeTextInputFocused');
|
||||
}
|
||||
if (_nativeTextInputFocused == focused) {
|
||||
_logGamepadDiag('setNativeTextInputFocused no-op focused=$focused');
|
||||
if (TextInputDiagnostics.enabled) _logGamepadDiag('setNativeTextInputFocused no-op focused=$focused');
|
||||
return;
|
||||
}
|
||||
_nativeTextInputFocused = focused;
|
||||
|
||||
if (focused) {
|
||||
_logGamepadDiag('native text input focused; clearing repeat/buttons/duplicate guard before pause');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('native text input focused; clearing repeat/buttons/duplicate guard before pause');
|
||||
}
|
||||
_stopDirectionRepeat();
|
||||
_pressedButtons.clear();
|
||||
_suppressedButtons.clear();
|
||||
@@ -347,20 +351,22 @@ class GamepadService with WindowListener {
|
||||
|
||||
final debugHandler = debugNativeTextInputFocusHandler;
|
||||
if (debugHandler != null) {
|
||||
_logGamepadDiag('setNativeTextInputFocused using debug handler focused=$focused');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('setNativeTextInputFocused using debug handler focused=$focused');
|
||||
}
|
||||
await debugHandler(focused);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (focused) {
|
||||
_logGamepadDiag('calling Gamepad.pause for native text input');
|
||||
if (TextInputDiagnostics.enabled) _logGamepadDiag('calling Gamepad.pause for native text input');
|
||||
await Gamepad.instance.pause();
|
||||
_logGamepadDiag('Gamepad.pause completed for native text input');
|
||||
if (TextInputDiagnostics.enabled) _logGamepadDiag('Gamepad.pause completed for native text input');
|
||||
} else {
|
||||
_logGamepadDiag('calling Gamepad.resume after native text input');
|
||||
if (TextInputDiagnostics.enabled) _logGamepadDiag('calling Gamepad.resume after native text input');
|
||||
await Gamepad.instance.resume();
|
||||
_logGamepadDiag('Gamepad.resume completed after native text input');
|
||||
if (TextInputDiagnostics.enabled) _logGamepadDiag('Gamepad.resume completed after native text input');
|
||||
}
|
||||
} catch (e) {
|
||||
appLogger.e('GamepadService: Failed to ${focused ? "pause" : "resume"} for native text input', error: e);
|
||||
@@ -368,11 +374,15 @@ class GamepadService with WindowListener {
|
||||
}
|
||||
|
||||
void _handleGamepadEvent(GamepadEvent event) {
|
||||
_logGamepadDiag('event received type=${event.runtimeType} nativeTextInputFocused=$_nativeTextInputFocused');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('event received type=${event.runtimeType} nativeTextInputFocused=$_nativeTextInputFocused');
|
||||
}
|
||||
switch (event) {
|
||||
case final GamepadConnectionEvent e:
|
||||
appLogger.i('GamepadService: Gamepad ${e.connected ? "connected" : "disconnected"}: ${e.info.name}');
|
||||
_logGamepadDiag('connection connected=${e.connected} info=${e.info.name}/${e.info.id}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('connection connected=${e.connected} info=${e.info.name}/${e.info.id}');
|
||||
}
|
||||
case final GamepadButtonEvent e:
|
||||
_handleButton(e);
|
||||
case final GamepadAxisEvent e:
|
||||
@@ -381,15 +391,21 @@ class GamepadService with WindowListener {
|
||||
}
|
||||
|
||||
void _handleButton(GamepadButtonEvent event) {
|
||||
_logGamepadDiag(
|
||||
'button received ${_describeGamepadButton(event)} windowFocused=$_windowFocused nativeTextInputFocused=$_nativeTextInputFocused',
|
||||
);
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag(
|
||||
'button received ${_describeGamepadButton(event)} windowFocused=$_windowFocused nativeTextInputFocused=$_nativeTextInputFocused',
|
||||
);
|
||||
}
|
||||
if (!_windowFocused) {
|
||||
_logGamepadDiag('button ignored because window is not focused ${_describeGamepadButton(event)}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('button ignored because window is not focused ${_describeGamepadButton(event)}');
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (isTvosEngineOwnedGamepadButton(isAppleTV: PlatformDetector.isAppleTV(), button: event.button)) {
|
||||
_logGamepadDiag('button ignored because tvOS engine owns its key lifecycle ${_describeGamepadButton(event)}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('button ignored because tvOS engine owns its key lifecycle ${_describeGamepadButton(event)}');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -408,7 +424,9 @@ class GamepadService with WindowListener {
|
||||
if (event.pressed && !wasPressed) {
|
||||
_pressedButtons.add(event.button);
|
||||
if (_shouldSuppressButton(event.button)) {
|
||||
_logGamepadDiag('button suppressed by duplicate guard ${_describeGamepadButton(event)}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('button suppressed by duplicate guard ${_describeGamepadButton(event)}');
|
||||
}
|
||||
_suppressedButtons.add(event.button);
|
||||
return;
|
||||
}
|
||||
@@ -416,32 +434,46 @@ class GamepadService with WindowListener {
|
||||
// D-pad — navigate with auto-repeat while held
|
||||
switch (event.button) {
|
||||
case GamepadButton.dpadUp:
|
||||
_logGamepadDiag('button starts direction repeat up ${_describeGamepadButton(event)}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('button starts direction repeat up ${_describeGamepadButton(event)}');
|
||||
}
|
||||
_startDirectionRepeat(TraversalDirection.up);
|
||||
return;
|
||||
case GamepadButton.dpadDown:
|
||||
_logGamepadDiag('button starts direction repeat down ${_describeGamepadButton(event)}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('button starts direction repeat down ${_describeGamepadButton(event)}');
|
||||
}
|
||||
_startDirectionRepeat(TraversalDirection.down);
|
||||
return;
|
||||
case GamepadButton.dpadLeft:
|
||||
_logGamepadDiag('button starts direction repeat left ${_describeGamepadButton(event)}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('button starts direction repeat left ${_describeGamepadButton(event)}');
|
||||
}
|
||||
_startDirectionRepeat(TraversalDirection.left);
|
||||
return;
|
||||
case GamepadButton.dpadRight:
|
||||
_logGamepadDiag('button starts direction repeat right ${_describeGamepadButton(event)}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('button starts direction repeat right ${_describeGamepadButton(event)}');
|
||||
}
|
||||
_startDirectionRepeat(TraversalDirection.right);
|
||||
return;
|
||||
// Face buttons — send KeyDown on press, KeyUp on release
|
||||
// so widget-level long-press timers work naturally
|
||||
case GamepadButton.a:
|
||||
_logGamepadDiag('button simulates key down enter ${_describeGamepadButton(event)}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('button simulates key down enter ${_describeGamepadButton(event)}');
|
||||
}
|
||||
_simulateKeyDown(LogicalKeyboardKey.enter);
|
||||
case GamepadButton.x:
|
||||
_logGamepadDiag('button simulates key down context/menu ${_describeGamepadButton(event)}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('button simulates key down context/menu ${_describeGamepadButton(event)}');
|
||||
}
|
||||
_simulateKeyDown(LogicalKeyboardKey.gameButtonX);
|
||||
// Immediate actions on press
|
||||
case GamepadButton.b:
|
||||
_logGamepadDiag('button simulates key press back ${_describeGamepadButton(event)}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('button simulates key press back ${_describeGamepadButton(event)}');
|
||||
}
|
||||
_simulateKeyPress(LogicalKeyboardKey.gameButtonB);
|
||||
case GamepadButton.leftShoulder:
|
||||
_dispatchTabNavigation(previous: true);
|
||||
@@ -453,7 +485,9 @@ class GamepadService with WindowListener {
|
||||
} else if (!event.pressed && wasPressed) {
|
||||
_pressedButtons.remove(event.button);
|
||||
if (_suppressedButtons.remove(event.button)) {
|
||||
_logGamepadDiag('button release consumed by suppressed set ${_describeGamepadButton(event)}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('button release consumed by suppressed set ${_describeGamepadButton(event)}');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -463,14 +497,20 @@ class GamepadService with WindowListener {
|
||||
case GamepadButton.dpadDown:
|
||||
case GamepadButton.dpadLeft:
|
||||
case GamepadButton.dpadRight:
|
||||
_logGamepadDiag('button stops direction repeat ${_describeGamepadButton(event)}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('button stops direction repeat ${_describeGamepadButton(event)}');
|
||||
}
|
||||
_stopDirectionRepeat();
|
||||
// Face button release — send KeyUp
|
||||
case GamepadButton.a:
|
||||
_logGamepadDiag('button simulates key up enter ${_describeGamepadButton(event)}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('button simulates key up enter ${_describeGamepadButton(event)}');
|
||||
}
|
||||
_simulateKeyUp(LogicalKeyboardKey.enter);
|
||||
case GamepadButton.x:
|
||||
_logGamepadDiag('button simulates key up context/menu ${_describeGamepadButton(event)}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('button simulates key up context/menu ${_describeGamepadButton(event)}');
|
||||
}
|
||||
_simulateKeyUp(LogicalKeyboardKey.gameButtonX);
|
||||
default:
|
||||
break;
|
||||
@@ -481,16 +521,22 @@ class GamepadService with WindowListener {
|
||||
bool _shouldSuppressButton(GamepadButton button) {
|
||||
final syntheticKey = _syntheticKeyByButton[button];
|
||||
final suppressed = syntheticKey != null && _duplicateInputGuard.shouldSuppressSyntheticKey(syntheticKey);
|
||||
_logGamepadDiag('duplicate guard button=$button syntheticKey=$syntheticKey suppressed=$suppressed');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('duplicate guard button=$button syntheticKey=$syntheticKey suppressed=$suppressed');
|
||||
}
|
||||
return suppressed;
|
||||
}
|
||||
|
||||
void _handleAxis(GamepadAxisEvent event) {
|
||||
_logGamepadDiag(
|
||||
'axis received ${_describeGamepadAxis(event)} windowFocused=$_windowFocused nativeTextInputFocused=$_nativeTextInputFocused',
|
||||
);
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag(
|
||||
'axis received ${_describeGamepadAxis(event)} windowFocused=$_windowFocused nativeTextInputFocused=$_nativeTextInputFocused',
|
||||
);
|
||||
}
|
||||
if (!_windowFocused) {
|
||||
_logGamepadDiag('axis ignored because window is not focused ${_describeGamepadAxis(event)}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag('axis ignored because window is not focused ${_describeGamepadAxis(event)}');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -512,18 +558,20 @@ class GamepadService with WindowListener {
|
||||
|
||||
/// Fire [direction] immediately, then auto-repeat after an initial delay.
|
||||
void _startDirectionRepeat(TraversalDirection direction) {
|
||||
_logGamepadDiag('startDirectionRepeat direction=$direction');
|
||||
if (TextInputDiagnostics.enabled) _logGamepadDiag('startDirectionRepeat direction=$direction');
|
||||
_stopDirectionRepeat();
|
||||
final logicalKey = _directionToKey(direction);
|
||||
_logGamepadDiag(
|
||||
'moveFocus direction=$direction logicalKey=${logicalKey.keyLabel}/${logicalKey.keyId} nativeTextInputFocused=$_nativeTextInputFocused',
|
||||
);
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_logGamepadDiag(
|
||||
'moveFocus direction=$direction logicalKey=${logicalKey.keyLabel}/${logicalKey.keyId} nativeTextInputFocused=$_nativeTextInputFocused',
|
||||
);
|
||||
}
|
||||
_simulator.startKeyRepeat(logicalKey, initialDelay: _repeatInitialDelay, interval: _repeatInterval);
|
||||
}
|
||||
|
||||
void _stopDirectionRepeat() {
|
||||
if (_keyEventSimulator?.isRepeating ?? false) {
|
||||
_logGamepadDiag('stopDirectionRepeat');
|
||||
if (TextInputDiagnostics.enabled) _logGamepadDiag('stopDirectionRepeat');
|
||||
}
|
||||
_keyEventSimulator?.stopKeyRepeat();
|
||||
}
|
||||
|
||||
@@ -60,7 +60,9 @@ class KeyEventSimulatorController {
|
||||
/// Simulates a full key press (down and up) in one frame.
|
||||
void simulateKeyPress(LogicalKeyboardKey logicalKey) {
|
||||
if (_disposed) return;
|
||||
_log('simulateKeyPress scheduled logical=${logicalKey.keyLabel}/${logicalKey.keyId}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_log('simulateKeyPress scheduled logical=${logicalKey.keyLabel}/${logicalKey.keyId}');
|
||||
}
|
||||
_schedule((focusNode) {
|
||||
final physicalKey = _physicalKeyFor(logicalKey);
|
||||
_dispatchKeyEvent(focusNode, _keyDownEvent(logicalKey, physicalKey));
|
||||
@@ -71,7 +73,9 @@ class KeyEventSimulatorController {
|
||||
/// Simulates key down and remembers its focus until key up.
|
||||
void simulateKeyDown(LogicalKeyboardKey logicalKey) {
|
||||
if (_disposed) return;
|
||||
_log('simulateKeyDown scheduled logical=${logicalKey.keyLabel}/${logicalKey.keyId}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_log('simulateKeyDown scheduled logical=${logicalKey.keyLabel}/${logicalKey.keyId}');
|
||||
}
|
||||
_schedule((focusNode) {
|
||||
_heldFocusNodes[logicalKey] = focusNode;
|
||||
_dispatchKeyEvent(focusNode, _keyDownEvent(logicalKey, _physicalKeyFor(logicalKey)));
|
||||
@@ -81,7 +85,9 @@ class KeyEventSimulatorController {
|
||||
/// Simulates key up on the focus that received the matching key down.
|
||||
void simulateKeyUp(LogicalKeyboardKey logicalKey) {
|
||||
if (_disposed) return;
|
||||
_log('simulateKeyUp scheduled logical=${logicalKey.keyLabel}/${logicalKey.keyId}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_log('simulateKeyUp scheduled logical=${logicalKey.keyLabel}/${logicalKey.keyId}');
|
||||
}
|
||||
scheduleFrameIfIdle();
|
||||
SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||
if (!_disposed) _dispatchKeyUp(logicalKey);
|
||||
@@ -147,7 +153,9 @@ class KeyEventSimulatorController {
|
||||
final focusNode = heldFocusNode ?? FocusManager.instance.primaryFocus;
|
||||
if (focusNode == null) return;
|
||||
if (heldFocusNode != null && heldFocusNode.context == null) {
|
||||
_log('simulateKeyUp dropped detached held focus logical=${logicalKey.keyLabel}/${logicalKey.keyId}');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_log('simulateKeyUp dropped detached held focus logical=${logicalKey.keyLabel}/${logicalKey.keyId}');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -173,21 +181,27 @@ class KeyEventSimulatorController {
|
||||
}
|
||||
|
||||
void _dispatchKeyEvent(FocusNode focusNode, KeyEvent event) {
|
||||
_log('dispatch start focus=${focusNode.debugLabel} key=(${_describeSimulatedKey(event)})');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_log('dispatch start focus=${focusNode.debugLabel} key=(${_describeSimulatedKey(event)})');
|
||||
}
|
||||
FocusNode? node = focusNode;
|
||||
while (node != null) {
|
||||
if (node.onKeyEvent != null) {
|
||||
final result = node.onKeyEvent!(node, event);
|
||||
_log('dispatch node=${node.debugLabel} result=$result key=(${_describeSimulatedKey(event)})');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_log('dispatch node=${node.debugLabel} result=$result key=(${_describeSimulatedKey(event)})');
|
||||
}
|
||||
if (result != KeyEventResult.ignored) {
|
||||
_log('dispatch stopped node=${node.debugLabel} result=$result');
|
||||
if (TextInputDiagnostics.enabled) _log('dispatch stopped node=${node.debugLabel} result=$result');
|
||||
break;
|
||||
}
|
||||
}
|
||||
node = node.parent;
|
||||
}
|
||||
if (node == null) {
|
||||
_log('dispatch reached root ignored key=(${_describeSimulatedKey(event)})');
|
||||
if (TextInputDiagnostics.enabled) {
|
||||
_log('dispatch reached root ignored key=(${_describeSimulatedKey(event)})');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,3 @@
|
||||
/// Set to `true` to blur all artwork (for store screenshots).
|
||||
const kBlurArtwork = false;
|
||||
|
||||
/// Rotates vowels (a→e, e→i, i→o, o→u, u→a) when [kBlurArtwork] is `true`.
|
||||
String obfuscateText(String text) {
|
||||
if (!kBlurArtwork) return text;
|
||||
const from = 'aeiouAEIOU';
|
||||
const to = 'eiouaEIOUA';
|
||||
final buf = StringBuffer();
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
final idx = from.indexOf(text[i]);
|
||||
buf.write(idx >= 0 ? to[idx] : text[i]);
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
/// Blur all artwork (for store screenshots). Compile-time switch: run with
|
||||
/// `--dart-define=PLEZY_BLUR_ARTWORK=true`; const-folded out of normal builds.
|
||||
const kBlurArtwork = bool.fromEnvironment('PLEZY_BLUR_ARTWORK');
|
||||
|
||||
@@ -2,7 +2,11 @@ import 'app_logger.dart';
|
||||
import 'platform_detector.dart';
|
||||
|
||||
class TextInputDiagnostics {
|
||||
static bool enabled = false;
|
||||
/// Compile-time switch: run with
|
||||
/// `--dart-define=PLEZY_TEXT_INPUT_DIAGNOSTICS=true` to enable. Const so the
|
||||
/// guarded branches (and their log-string interpolation) compile out of
|
||||
/// every normal build.
|
||||
static const bool enabled = bool.fromEnvironment('PLEZY_TEXT_INPUT_DIAGNOSTICS');
|
||||
|
||||
static void log(String source, String message) {
|
||||
if (!enabled || !PlatformDetector.isTV()) return;
|
||||
|
||||
Reference in New Issue
Block a user