Skip to content

Commit 38e58ba

Browse files
authoredMar 31, 2024
fix(linux): ensure icon works in sandboxed environments (#43)
* refactor: only pass icon as base64 for macOS Only macOS requires the icon to be passed as a base64 string. No need to do this for other platforms. * fix(linux): ensure icon works in sandboxed environments When running in a sandboxed environment, such as a Flatpak or Snap, the icon should be passed as the icon name, not a path. This is required because when running in a sandbox, paths are not the same as seen by the app and the host system.
1 parent 1c0e963 commit 38e58ba

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed
 

‎lib/src/helpers/sandbox.dart

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import 'dart:io';
2+
3+
/// Returns `true` if the app is running in a sandbox, eg. Flatpak or Snap.
4+
bool runningInSandbox() {
5+
return Platform.environment.containsKey('FLATPAK_ID') ||
6+
Platform.environment.containsKey('SNAP');
7+
}

‎lib/src/tray_manager.dart

+30-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:flutter/foundation.dart';
99
import 'package:flutter/services.dart';
1010
import 'package:shortid/shortid.dart';
1111

12+
import 'helpers/sandbox.dart';
1213
import 'tray_listener.dart';
1314

1415
const kEventOnTrayIconMouseDown = 'onTrayIconMouseDown';
@@ -90,25 +91,50 @@ class TrayManager {
9091
}
9192

9293
/// Sets the image associated with this tray icon.
94+
///
95+
/// [iconPath] is the path to the image file.
96+
///
97+
/// However, if the app is running in a sandbox like Flatpak or Snap,
98+
/// [iconPath] should be the name of the icon as specified in the app's
99+
/// manifest file, without the path or file extension. For example, if the
100+
/// icon is specified as `org.example.app` in the Flatpak manifest file, then
101+
/// the icon should be passed as `org.example.app`.
93102
Future<void> setIcon(
94103
String iconPath, {
95104
bool isTemplate = false, // macOS only
96105
TrayIconPositon iconPosition = TrayIconPositon.left, // macOS only
97106
}) async {
98-
ByteData imageData = await rootBundle.load(iconPath);
99-
String base64Icon = base64Encode(imageData.buffer.asUint8List());
100-
101107
final Map<String, dynamic> arguments = {
102108
"id": shortid.generate(),
103109
'iconPath': path.joinAll([
104110
path.dirname(Platform.resolvedExecutable),
105111
'data/flutter_assets',
106112
iconPath,
107113
]),
108-
'base64Icon': base64Icon,
109114
'isTemplate': isTemplate,
110115
'iconPosition': iconPosition.name,
111116
};
117+
118+
switch (defaultTargetPlatform) {
119+
case TargetPlatform.linux:
120+
if (runningInSandbox()) {
121+
// Pass the icon name as specified if running in a sandbox.
122+
//
123+
// This is required because when running in a sandbox, paths are not
124+
// the same as seen by the app and the host system.
125+
arguments['iconPath'] = iconPath;
126+
}
127+
break;
128+
case TargetPlatform.macOS:
129+
// Add the icon as base64 string
130+
ByteData imageData = await rootBundle.load(iconPath);
131+
String base64Icon = base64Encode(imageData.buffer.asUint8List());
132+
arguments['base64Icon'] = base64Icon;
133+
break;
134+
default:
135+
break;
136+
}
137+
112138
await _channel.invokeMethod('setIcon', arguments);
113139
}
114140

0 commit comments

Comments
 (0)