diff --git a/lib/core/features/game_button.dart b/lib/core/features/game_button.dart index 9484e82..0f52d16 100644 --- a/lib/core/features/game_button.dart +++ b/lib/core/features/game_button.dart @@ -396,6 +396,7 @@ class _GameButtonState extends State with GameStoreStateMixin { _callAction(data.longPressAction); setState(() { isClicking = false; + isHovering = false; }); } @@ -408,6 +409,7 @@ class _GameButtonState extends State with GameStoreStateMixin { void _onTapUp(TapUpDetails details) { setState(() { isClicking = false; + isHovering = false; }); } @@ -433,6 +435,8 @@ class _GameButtonState extends State with GameStoreStateMixin { _callCurrentDirection(); setState(() { _direction = GameButtonInteraction.press; + isHovering = false; + isClicking = false; }); } @@ -461,6 +465,7 @@ class _GameButtonState extends State with GameStoreStateMixin { setState(() { isClicking = false; + isHovering = false; _direction = GameButtonInteraction.press; _startDragTime = null; }); diff --git a/lib/core/store.dart b/lib/core/store.dart index f45bead..23ae74c 100644 --- a/lib/core/store.dart +++ b/lib/core/store.dart @@ -47,7 +47,7 @@ class GameStore extends ChangeNotifier { RegExp("(? _currentProfile!; - List get aliases => currentProfile.aliases; + List get aliases => builtInAliases + (_currentProfile?.aliases ?? []); List get triggers => currentProfile.triggers; get connected => _clientReady && _client.connected; @@ -93,7 +93,7 @@ class GameStore extends ChangeNotifier { onError: onError, ); await currentProfile.load(); - echoSystem('Connecting...'); + echoSystem('Profile loaded. Connecting...'); _client.connect(); notifyListeners(); } @@ -114,12 +114,6 @@ class GameStore extends ChangeNotifier { } } - void requestMCCP() { - debugPrint('requestMCCP'); - _client.doo(86); - sendBytes([Symbols.iac, Symbols.doo, 86]); - } - Future disconnect() { return _client.disconnect(); } @@ -129,7 +123,7 @@ class GameStore extends ChangeNotifier { } void onRawData(List bytes) { - debugPrint('onRawData'); + debugPrint('Received Raw Data'); try { final data = Message(bytes); handleSpecialMessages(data); @@ -148,14 +142,16 @@ class GameStore extends ChangeNotifier { } void onData(Message data) { - debugPrint('onData'); try { if (currentProfile.mccpEnabled && isCompressed) { _rawStreamController.add(data.bytes); return; } - debugPrint('onData: ${data.text}'); + debugPrint('Received data'); handleSpecialMessages(data); + if (isCompressed) { + return; + } if (data.text.isEmpty) { return; } @@ -170,56 +166,83 @@ class GameStore extends ChangeNotifier { } void handleSpecialMessages(Message data) { + final terminalSub = data.subnegotiation(24); if (data.isCommand) { - debugPrint('Received command: ${data.bytes}'); + debugPrint('Received command: ${data.commands}'); } + final bytes = []; if (data.doo(24)) { - debugPrint('Received terminal type WILL request'); - sendBytes([Symbols.iac, Symbols.will, 24, Symbols.iac, Symbols.se]); - } else if (data.sb(24) && data.bytes[3] == 1) { + debugPrint('Received terminal type DO request'); + debugPrint('Sending terminal type WILL response'); + bytes.addAll([Symbols.iac, Symbols.will, 24]); + } + if (terminalSub != null && + terminalSub.isNotEmpty && + terminalSub.single == 1) { + // } else if (terminalSub.isNotEmpty && terminalSub[0] == 1) { debugPrint('Received terminal type SEND request'); - final bytes = [ + final tt = const AsciiEncoder().convert('Mublock'); + final ttBytes = [ Symbols.iac, Symbols.sb, 24, 0, - ...const AsciiEncoder().convert('Mublock'), + ...tt, Symbols.iac, Symbols.se ]; - debugPrint('Sending terminal type: $bytes'); - sendBytes(bytes); - } else if (!currentProfile.mccpEnabled) { - return; + bytes.addAll(ttBytes); + debugPrint('Sending terminal type response: $ttBytes'); } + // MCCP - else { - if (isCompressed) { - if (data.se()) { - disableMCCP(); - } - } else { + if (currentProfile.mccpEnabled) { + if (!isCompressed) { if (data.sb(86)) { - enableMCCP(); + debugPrint('Received compression start'); + if (bytes.isNotEmpty) { + sendBytes(bytes); + } + enableCompression(); + // _rawStreamController.add(data.bytes); + debugPrint( + 'bytes after mccp: ${data.bytes.sublist(data.bytes.indexOf(86) + 3)}'); + _rawStreamController + .add(data.bytes.sublist(data.bytes.indexOf(86) + 3)); + echoSystem('Compression started'); + debugPrint("Done handling command (early)"); + return; } else if (data.will(86)) { - requestMCCP(); - echo('Compression requested'); + debugPrint('Received compression request'); + bytes.addAll([Symbols.iac, Symbols.doo, 86]); + debugPrint('Sending compression request'); } + } else { // isCompressed + // if (data.se()) { + // final seIndex = data.bytes.indexOf(Symbols.se); + // if (data.bytes[seIndex - 1] == Symbols.iac) { + // debugPrint('Received compression end'); + // disableCompression(); + // } + // } } } + sendBytes(bytes); + debugPrint("Done handling command"); + // } } - void disableMCCP() { - echo('Compression disabled'); + void disableCompression() { isCompressed = false; _decodedSub.cancel(); + echoSystem('Compression disabled'); } - void enableMCCP() { + void enableCompression() { isCompressed = true; _decodedStream = _decoder.decoder.bind(_rawStreamController.stream); _decodedSub = _decodedStream.listen(onRawData); - echo('Compression enabled'); + echoSystem('Compression enabled'); } void onError(Object error) { @@ -462,8 +485,7 @@ class GameStore extends ChangeNotifier { } mixin GameStoreMixin { - GameStore storeOf(BuildContext context) => - GameStore.of(context); + GameStore storeOf(BuildContext context) => GameStore.of(context); } mixin GameStoreStateMixin on State { diff --git a/lib/main.dart b/lib/main.dart index 3f9ef45..7409b15 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -17,6 +17,8 @@ void main() async { final w = prefs.getInt('windowWidth') ?? 1000; final h = prefs.getInt('windowHeight') ?? 900; + // final x = prefs.getInt('windowX') ?? 0; + // final y = prefs.getInt('windowY') ?? 0; final size = Size(w.toDouble(), h.toDouble()); WindowOptions windowOptions = WindowOptions( diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart index 33f48ad..5eec4f5 100644 --- a/lib/pages/home_page.dart +++ b/lib/pages/home_page.dart @@ -168,6 +168,20 @@ class HomePageState extends State store.selectInput(); } + @override + void onWindowMove() { + EasyDebounce.debounce( + 'windowMove', + const Duration(milliseconds: 500), + () async { + final position = await windowManager.getPosition(); + debugPrint("Window moved to $position"); + prefs.setInt('windowX', position.dx.toInt()); + prefs.setInt('windowY', position.dy.toInt()); + }, + ); + } + @override void onWindowResize() async { EasyDebounce.debounce( diff --git a/pubspec.lock b/pubspec.lock index c1e8e98..dadca11 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -100,11 +100,10 @@ packages: ctelnet: dependency: "direct main" description: - name: ctelnet - sha256: "06cba141577de338adc9436ad733f33668224b0cfcf046f8edd58fcde09aeed2" - url: "https://pub.dev" - source: hosted - version: "0.1.4" + path: "../ctelnet" + relative: true + source: path + version: "0.1.5" cupertino_icons: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 67c2b89..6835c17 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -28,7 +28,9 @@ environment: # the latest version available on pub.dev. To see which dependencies have newer # versions available, run `flutter pub outdated`. dependencies: - ctelnet: ^0.1.4 + # ctelnet: ^0.1.4 + ctelnet: + path: ../ctelnet flutter: sdk: flutter