Skip to content

Commit ca3a162

Browse files
committed
feat: add logging
1 parent 1b0e500 commit ca3a162

File tree

8 files changed

+72
-20
lines changed

8 files changed

+72
-20
lines changed

analysis_options.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
analyzer:
2+
exclude:
3+
- example/**
4+
- lib/src/generated/**
5+
16
linter:
27
rules:
38
package_api_docs: true

lib/flutter_single_instance.dart

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import 'package:flutter_single_instance/src/focus.dart';
3838
import 'package:flutter_single_instance/src/generated/focus.pbgrpc.dart';
3939
import 'package:flutter_single_instance/src/instance.dart';
4040
import 'package:grpc/grpc.dart';
41+
import 'package:logging/logging.dart';
4142
import 'package:path_provider/path_provider.dart';
4243
import 'src/linux.dart';
4344
import 'src/macos.dart';
@@ -56,16 +57,20 @@ abstract class FlutterSingleInstance {
5657
Server? _server;
5758
Instance? _instance;
5859

60+
/// Logger for this class.
61+
@protected
62+
Logger get logger => Logger('FlutterSingleInstance.$runtimeType');
63+
5964
/// Provides utilities for checking if this is the first instance of the app.
6065
/// Make sure to call `WidgetsFlutterBinding.ensureInitialized()` before using this class.
6166
factory FlutterSingleInstance() {
6267
_singelton ??= Platform.isMacOS
63-
? FlutterSingleInstanceMacOS()
68+
? MacOS()
6469
: Platform.isLinux
65-
? FlutterSingleInstanceLinux()
70+
? Linux()
6671
: Platform.isWindows
67-
? FlutterSingleInstanceWindows()
68-
: FlutterSingleInstanceUnsopported();
72+
? Windows()
73+
: Unsupported();
6974

7075
return _singelton!;
7176
}
@@ -82,6 +87,7 @@ abstract class FlutterSingleInstance {
8287
/// Automatically writes a pid file to the temp directory if this is the first instance.
8388
Future<bool> isFirstInstance() async {
8489
if (debugMode) {
90+
logger.finest("Debug mode enabled, reporting as first instance");
8591
return true;
8692
}
8793

@@ -92,6 +98,8 @@ abstract class FlutterSingleInstance {
9298
pidFile!;
9399

94100
if (!pidFile.existsSync()) {
101+
logger.finest("No pid file found, activating instance");
102+
95103
// No pid file, so this is the first instance.
96104
await activateInstance(processName);
97105
return true;
@@ -101,13 +109,19 @@ abstract class FlutterSingleInstance {
101109

102110
_instance = Instance.fromJson(jsonDecode(data));
103111

112+
logger.finest("Pid file found, verifying instance: $_instance");
113+
104114
final pidName = await getProcessName(_instance!.pid);
105115

106116
if (processName == pidName) {
117+
logger.finest("Process name matches, reporting as second instance");
118+
107119
// Process exists, so this is not the first instance.
108120
return false;
109121
}
110122

123+
logger.finest("Process name does not match, activating instance");
124+
111125
// Process does not exist, so we can activate this instance.
112126
await activateInstance(processName);
113127

@@ -127,6 +141,8 @@ abstract class FlutterSingleInstance {
127141
);
128142

129143
await pidFile?.writeAsString(jsonEncode(instance.toJson()));
144+
145+
logger.finest("Instance activated: $instance at ${pidFile?.path}");
130146
}
131147

132148
/// Returns the pid file.
@@ -140,6 +156,8 @@ abstract class FlutterSingleInstance {
140156
/// Starts an RPC server that listens for focus requests.
141157
@protected
142158
Future<int> startRpcServer() async {
159+
logger.finest("Starting RPC server");
160+
143161
_server = Server.create(
144162
services: [FocusService()],
145163
codecRegistry: CodecRegistry(
@@ -152,6 +170,8 @@ abstract class FlutterSingleInstance {
152170

153171
await _server!.serve(port: 0);
154172

173+
logger.finest("RPC server started on port ${_server!.port}");
174+
155175
return _server!.port!;
156176
}
157177

@@ -161,6 +181,8 @@ abstract class FlutterSingleInstance {
161181
if (_instance == null) return "No instance to focus";
162182
if (_server != null) return "This is the first instance";
163183

184+
logger.finest("Focusing instance: $_instance");
185+
164186
try {
165187
final channel = ClientChannel(
166188
'localhost',
@@ -180,8 +202,17 @@ abstract class FlutterSingleInstance {
180202

181203
final response = await client.focus(FocusRequest());
182204

183-
return response.success ? null : response.error;
205+
if (response.success) {
206+
logger.finest("Instance focused");
207+
208+
return null;
209+
} else {
210+
logger.finest('Failed to focus instance', response.error);
211+
212+
return response.error;
213+
}
184214
} catch (e) {
215+
logger.finest('Failed to focus instance', e);
185216
return e.toString();
186217
}
187218
}

lib/src/focus.dart

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,25 @@
1+
import 'package:flutter_single_instance/flutter_single_instance.dart';
12
import 'package:flutter_single_instance/src/generated/focus.pbgrpc.dart';
23
import 'package:grpc/grpc.dart';
3-
import 'package:window_manager/window_manager.dart';
44

5+
/// Handles focus requests from other instances.
56
class FocusService extends FocusServiceBase {
67
@override
78
Future<FocusResponse> focus(ServiceCall call, FocusRequest request) async {
9+
// ignore: invalid_use_of_protected_member
10+
final logger = FlutterSingleInstance().logger;
11+
12+
logger.finest('Received focus request from ${call.remoteAddress?.address}');
13+
814
try {
915
await windowManager.focus();
1016

17+
logger.finest('Window focused');
18+
1119
return FocusResponse(success: true);
1220
} catch (e) {
21+
logger.finest('Failed to focus window', e);
22+
1323
return FocusResponse(success: false, error: e.toString());
1424
}
1525
}

lib/src/linux.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import 'dart:io';
22
import 'package:flutter_single_instance/flutter_single_instance.dart';
33

44
/// Implementation of [FlutterSingleInstance] for Linux.
5-
class FlutterSingleInstanceLinux extends FlutterSingleInstance {
5+
class Linux extends FlutterSingleInstance {
66
/// Implementation of [FlutterSingleInstance] for Linux.
7-
FlutterSingleInstanceLinux() : super.internal();
7+
Linux() : super.internal();
88

99
@override
1010
Future<String?> getProcessName(pid) async {
@@ -28,4 +28,9 @@ class FlutterSingleInstanceLinux extends FlutterSingleInstance {
2828
return parts.last;
2929
}
3030
}
31+
32+
@override
33+
Future<File?> getPidFile(String processName) async {
34+
return File('/tmp/$processName.pid');
35+
}
3136
}

lib/src/macos.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import 'dart:io';
22
import 'package:flutter_single_instance/flutter_single_instance.dart';
33

44
/// Implementation of [FlutterSingleInstance] for MacOS.
5-
class FlutterSingleInstanceMacOS extends FlutterSingleInstance {
5+
class MacOS extends FlutterSingleInstance {
66
/// Implementation of [FlutterSingleInstance] for MacOS.
7-
FlutterSingleInstanceMacOS() : super.internal();
7+
MacOS() : super.internal();
88
@override
99
Future<String?> getProcessName(pid) async {
1010
var result = await Process.run("ps", ["-p", "$pid"]);

lib/src/unsupported.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import 'dart:io';
33
import 'package:flutter_single_instance/flutter_single_instance.dart';
44

55
/// Implementation of [FlutterSingleInstance] for unsupported platforms.
6-
class FlutterSingleInstanceUnsopported extends FlutterSingleInstance {
6+
class Unsupported extends FlutterSingleInstance {
77
/// Implementation of [FlutterSingleInstance] for unsupported platforms.
8-
FlutterSingleInstanceUnsopported() : super.internal();
8+
Unsupported() : super.internal();
99

1010
@override
1111
Future<String?> getProcessName(int pid) async => null;

lib/src/windows.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import 'dart:io';
22
import 'package:flutter_single_instance/flutter_single_instance.dart';
33

44
/// Implementation of [FlutterSingleInstance] for Windows.
5-
class FlutterSingleInstanceWindows extends FlutterSingleInstance {
5+
class Windows extends FlutterSingleInstance {
66
/// Implementation of [FlutterSingleInstance] for Windows.
7-
FlutterSingleInstanceWindows() : super.internal();
7+
Windows() : super.internal();
88

99
@override
1010
Future<String?> getProcessName(pid) async {

pubspec.yaml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ description: A simple way to check if your application is already running.
44
version: 1.1.2
55
repository: https://github.com/necodeIT/flutter_single_instance
66
platforms:
7-
linux:
8-
macos:
9-
windows:
10-
ios:
11-
android:
12-
web:
7+
? linux
8+
? macos
9+
? windows
10+
? ios
11+
? android
12+
? web
1313

1414
environment:
1515
sdk: ">=2.16.2 <4.0.0"
@@ -21,6 +21,7 @@ dependencies:
2121
freezed_annotation: ^2.4.4
2222
grpc: ^4.0.1
2323
json_annotation: ^4.9.0
24+
logging: ^1.3.0
2425
path_provider: ^2.0.13
2526
window_manager: ^0.4.3
2627

0 commit comments

Comments
 (0)