From 2ad92748ca1a9c167b1920e883b18ff2ee966bbf Mon Sep 17 00:00:00 2001 From: ArthurHeitmann <37270165+ArthurHeitmann@users.noreply.github.com> Date: Sat, 26 Oct 2024 08:26:50 +0200 Subject: [PATCH] singe instance when opening file with exe --- lib/main.dart | 19 ++++++- .../openFiles/types/xml/sync/syncServer.dart | 56 ++++++++++++++++--- lib/utils/fileOpenCommand.dart | 56 +++++++++++++++++++ lib/utils/utils.dart | 9 +++ 4 files changed, 130 insertions(+), 10 deletions(-) create mode 100644 lib/utils/fileOpenCommand.dart diff --git a/lib/main.dart b/lib/main.dart index c30b0b46..138d15ba 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -11,10 +12,12 @@ import 'background/IdLookup.dart'; import 'background/wemFilesIndexer.dart'; import 'keyboardEvents/globalShortcutsWrapper.dart'; import 'stateManagement/beforeExitCleanup.dart'; +import 'stateManagement/hierarchy/FileHierarchy.dart'; import 'stateManagement/openFiles/openFilesManager.dart'; import 'stateManagement/openFiles/types/xml/sync/syncServer.dart'; import 'stateManagement/preferencesData.dart'; import 'utils/assetDirFinder.dart'; +import 'utils/fileOpenCommand.dart'; import 'utils/loggingWrapper.dart'; import 'utils/utils.dart'; import 'widgets/EditorLayout.dart'; @@ -31,6 +34,13 @@ void main(List args) { } void init(List args) async { + if (args.isNotEmpty) { + var paths = args.where((arg) => FileSystemEntity.typeSync(arg) != FileSystemEntityType.notFound).toList(); + if (await trySendFileArgs(paths)) { + exit(0); + } + } + WidgetsFlutterBinding.ensureInitialized(); runApp(const SplashScreen()); @@ -88,9 +98,12 @@ void init(List args) async { runApp(const MyApp()); - unawaited(waitForNextFrame().then((_) { - for (var arg in args) - areasManager.openFile(arg); + unawaited(waitForNextFrame().then((_) async { + for (var arg in args) { + await openHierarchyManager.openFile(arg); + if (await canOpenAsFile(arg)) + areasManager.openFile(arg); + } })); } diff --git a/lib/stateManagement/openFiles/types/xml/sync/syncServer.dart b/lib/stateManagement/openFiles/types/xml/sync/syncServer.dart index fc899ce9..96217566 100644 --- a/lib/stateManagement/openFiles/types/xml/sync/syncServer.dart +++ b/lib/stateManagement/openFiles/types/xml/sync/syncServer.dart @@ -5,17 +5,22 @@ import 'dart:io'; import 'package:flutter/material.dart'; +import '../../../../../utils/fileOpenCommand.dart'; import '../../../../events/statusInfo.dart'; -const _wsPort = 1547; +const wsPort = 1547; WebSocket? _activeSocket; ValueNotifier canSync = ValueNotifier(false); +DateTime? serverStartTime; var _wsMessageStream = StreamController.broadcast(); var wsMessageStream = _wsMessageStream.stream; -class SyncMessage { +abstract class WsMessage { + Map toJson(); +} +class SyncMessage extends WsMessage { final String method; final String uuid; final Map args; @@ -27,6 +32,7 @@ class SyncMessage { uuid = json["uuid"], args = json["args"]; + @override Map toJson() { return { "method": method, @@ -35,6 +41,27 @@ class SyncMessage { }; } } +class CustomWsMessage extends WsMessage { + final String method; + final Map json; + + CustomWsMessage(this.method, this.json); + + CustomWsMessage.fromJson(Map json) + : method = json["method"], + json = { + for (var key in json.keys) + if (key != "method") key: json[key] + }; + + @override + Map toJson() { + return { + "method": method, + ...json, + }; + } +} void _handleWebSocket(WebSocket client) { print("New WebSocket client connected"); @@ -49,11 +76,20 @@ void _handleWebSocket(WebSocket client) { _onClientDone(); }); wsSend(SyncMessage("connected", "", {})); - messageLog.add("Connected to Blender"); + if (_startupCompleted()) + messageLog.add("Connected"); } void _onClientData(data) { - var message = SyncMessage.fromJson(jsonDecode(data)); + var jsonData = jsonDecode(data); + var method = jsonData["method"]; + if (method == "openFiles") { + var msg = CustomWsMessage.fromJson(jsonData); + var files = (msg.json["files"] as List).cast(); + onFileOpenCommand(files); + return; + } + var message = SyncMessage.fromJson(jsonData); _wsMessageStream.add(message); } @@ -61,14 +97,20 @@ void _onClientDone() { print("WebSocket client disconnected"); _activeSocket = null; canSync.value = false; - messageLog.add("Disconnected from Blender"); + if (_startupCompleted()) + messageLog.add("Disconnected"); } -void wsSend(SyncMessage data) { +void wsSend(WsMessage data) { _activeSocket?.add(jsonEncode(data.toJson())); } +bool _startupCompleted() { + return DateTime.now().difference(serverStartTime ?? DateTime.now()).inSeconds > 5; +} + void startSyncServer() async { - final server = await HttpServer.bind("localhost", _wsPort); + final server = await HttpServer.bind("localhost", wsPort); server.transform(WebSocketTransformer()).listen(_handleWebSocket); + serverStartTime = DateTime.now(); } diff --git a/lib/utils/fileOpenCommand.dart b/lib/utils/fileOpenCommand.dart new file mode 100644 index 00000000..faab6d35 --- /dev/null +++ b/lib/utils/fileOpenCommand.dart @@ -0,0 +1,56 @@ + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:window_manager/window_manager.dart'; + +import '../stateManagement/events/statusInfo.dart'; +import '../stateManagement/hierarchy/FileHierarchy.dart'; +import '../stateManagement/openFiles/openFilesManager.dart'; +import '../stateManagement/openFiles/types/xml/sync/syncServer.dart'; +import 'utils.dart'; + +void onFileOpenCommand(List paths) async { + await Future.wait(paths.map((path) async { + await openHierarchyManager.openFile(path); + if (await canOpenAsFile(path)) + areasManager.openFile(path); + })); + await windowManager.focus(); + messageLog.add(""); +} + +Future trySendFileArgs(List args) async { + if (args.isEmpty) + return false; + var completer = Completer(); + WebSocket? webSocket; + var timeout = Timer(const Duration(milliseconds: 500), () { + completer.complete(false); + webSocket?.close(); + }); + unawaited(WebSocket.connect("ws://localhost:$wsPort") + .then((ws) { + if (completer.isCompleted) { + ws.close(); + return; + } + webSocket = ws; + ws.add(jsonEncode(CustomWsMessage("openFiles", {"files": args}))); + ws.listen((data) { + var msg = SyncMessage.fromJson(jsonDecode(data)); + if (msg.method == "connected") { + completer.complete(true); + ws.close(); + timeout.cancel(); + } + }); + }) + .catchError((e) { + completer.complete(false); + }) + ); + + return completer.future; +} diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 73672db3..466c80d8 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -823,3 +823,12 @@ void debugOnly(void Function() func) { return true; }()); } + +const sideBarOnlyExtensions = [...datExtensions, ".pak", ".wai", ".bnk", ".wsp"]; + +Future canOpenAsFile(String path) async { + var ext = extension(path); + if (sideBarOnlyExtensions.contains(ext)) + return false; + return await File(path).exists(); +}