Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/images/icon/macos/status_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icon/macos/status_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/icon/macos/status_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 54 additions & 8 deletions lib/common/tray.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,58 @@ class Tray {
await trayManager.destroy();
}

String getTryIcon({required bool isStart, required bool tunEnable}) {
if (system.isMacOS || !isStart) {
return 'assets/images/icon/status_1.$trayIconSuffix';
String get _macosIconDir => 'assets/images/icon/macos';

String getTryIcon({
required bool isStart,
required bool tunEnable,
required bool systemProxy,
String? customStopped,
String? customProxy,
String? customTun,
}) {
final defaultSuffix =
system.isMacOS ? 'png' : trayIconSuffix;
final defaultDir =
system.isMacOS ? _macosIconDir : 'assets/images/icon';
if (!isStart || (!tunEnable && !systemProxy)) {
final p = customStopped;
if (p != null && File(p).existsSync()) return p;
return '$defaultDir/status_1.$defaultSuffix';
}
if (!tunEnable) {
return 'assets/images/icon/status_2.$trayIconSuffix';
if (tunEnable) {
final p = customTun;
if (p != null && File(p).existsSync()) return p;
return '$defaultDir/status_3.$defaultSuffix';
}
return 'assets/images/icon/status_3.$trayIconSuffix';
final p = customProxy;
if (p != null && File(p).existsSync()) return p;
return '$defaultDir/status_2.$defaultSuffix';
}

Future _updateSystemTray({
required bool isStart,
required bool tunEnable,
required bool systemProxy,
String? customStopped,
String? customProxy,
String? customTun,
required bool trayIconUseTemplate,
}) async {
if (Platform.isLinux) {
await trayManager.destroy();
}
final iconPath = getTryIcon(
isStart: isStart,
tunEnable: tunEnable,
systemProxy: systemProxy,
customStopped: customStopped,
customProxy: customProxy,
customTun: customTun,
);
await trayManager.setIcon(
getTryIcon(isStart: isStart, tunEnable: tunEnable),
isTemplate: true,
iconPath,
isTemplate: iconPath.startsWith('/') ? trayIconUseTemplate : true,
);
if (!Platform.isLinux) {
await trayManager.setToolTip(appName);
Expand All @@ -59,6 +91,10 @@ class Tray {
Future<void> update({
required TrayState trayState,
required Traffic traffic,
String? trayIconStoppedPath,
String? trayIconProxyPath,
String? trayIconTunPath,
required bool trayIconUseTemplate,
}) async {
if (system.isAndroid) {
return;
Expand All @@ -67,6 +103,11 @@ class Tray {
await _updateSystemTray(
isStart: trayState.isStart,
tunEnable: trayState.tunEnable,
systemProxy: trayState.systemProxy,
customStopped: trayIconStoppedPath,
customProxy: trayIconProxyPath,
customTun: trayIconTunPath,
trayIconUseTemplate: trayIconUseTemplate,
);
}
List<MenuItem> menuItems = [];
Expand Down Expand Up @@ -188,6 +229,11 @@ class Tray {
await _updateSystemTray(
isStart: trayState.isStart,
tunEnable: trayState.tunEnable,
systemProxy: trayState.systemProxy,
customStopped: trayIconStoppedPath,
customProxy: trayIconProxyPath,
customTun: trayIconTunPath,
trayIconUseTemplate: trayIconUseTemplate,
);
}
updateTrayTitle(showTrayTitle: trayState.showTrayTitle, traffic: traffic);
Expand Down
5 changes: 5 additions & 0 deletions lib/controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -956,11 +956,16 @@ extension SystemControllerExt on AppController {
}

Future<void> updateTray() async {
final setting = _ref.read(appSettingProvider);
tray?.update(
trayState: _ref.read(trayStateProvider),
traffic: _ref.read(
trafficsProvider.select((state) => state.list.safeLast(Traffic())),
),
trayIconStoppedPath: setting.trayIconStoppedPath,
trayIconProxyPath: setting.trayIconProxyPath,
trayIconTunPath: setting.trayIconTunPath,
trayIconUseTemplate: setting.trayIconUseTemplate,
);
}

Expand Down
10 changes: 10 additions & 0 deletions lib/l10n/intl/messages_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,16 @@ class MessageLookup extends MessageLookupByLibrary {
"specialProxy": MessageLookupByLibrary.simpleMessage("Special proxy"),
"specialRules": MessageLookupByLibrary.simpleMessage("special rules"),
"speedStatistics": MessageLookupByLibrary.simpleMessage("Speed statistics"),
"trayIcon": MessageLookupByLibrary.simpleMessage("Tray icon"),
"trayIconDesc": MessageLookupByLibrary.simpleMessage(
"Customize tray icon for each state",
),
"trayIconUseTemplate": MessageLookupByLibrary.simpleMessage(
"Use template image",
),
"trayIconUseTemplateDesc": MessageLookupByLibrary.simpleMessage(
"Render custom icons as monochrome template (follows system appearance)",
),
"stackMode": MessageLookupByLibrary.simpleMessage("Stack mode"),
"standard": MessageLookupByLibrary.simpleMessage("Standard"),
"standardModeDesc": MessageLookupByLibrary.simpleMessage(
Expand Down
4 changes: 4 additions & 0 deletions lib/l10n/intl/messages_ja.dart
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,10 @@ class MessageLookup extends MessageLookupByLibrary {
"specialProxy": MessageLookupByLibrary.simpleMessage("特殊プロキシ"),
"specialRules": MessageLookupByLibrary.simpleMessage("特殊ルール"),
"speedStatistics": MessageLookupByLibrary.simpleMessage("速度統計"),
"trayIcon": MessageLookupByLibrary.simpleMessage("トレイアイコン"),
"trayIconDesc": MessageLookupByLibrary.simpleMessage("各状態のトレイアイコンをカスタマイズ"),
"trayIconUseTemplate": MessageLookupByLibrary.simpleMessage("テンプレート画像を使用"),
"trayIconUseTemplateDesc": MessageLookupByLibrary.simpleMessage("カスタムアイコンをモノクロテンプレートとして描画(システム外観に従う)"),
"stackMode": MessageLookupByLibrary.simpleMessage("スタックモード"),
"standard": MessageLookupByLibrary.simpleMessage("標準"),
"standardModeDesc": MessageLookupByLibrary.simpleMessage(
Expand Down
10 changes: 10 additions & 0 deletions lib/l10n/intl/messages_ru.dart
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,16 @@ class MessageLookup extends MessageLookupByLibrary {
"speedStatistics": MessageLookupByLibrary.simpleMessage(
"Статистика скорости",
),
"trayIcon": MessageLookupByLibrary.simpleMessage("Значок трея"),
"trayIconDesc": MessageLookupByLibrary.simpleMessage(
"Настройка значка трея для каждого состояния",
),
"trayIconUseTemplate": MessageLookupByLibrary.simpleMessage(
"Использовать шаблон изображения",
),
"trayIconUseTemplateDesc": MessageLookupByLibrary.simpleMessage(
"Отображать пользовательские значки как монохромный шаблон (следует оформлению системы)",
),
"stackMode": MessageLookupByLibrary.simpleMessage("Режим стека"),
"standard": MessageLookupByLibrary.simpleMessage("Стандартный"),
"standardModeDesc": MessageLookupByLibrary.simpleMessage(
Expand Down
4 changes: 4 additions & 0 deletions lib/l10n/intl/messages_zh_CN.dart
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,10 @@ class MessageLookup extends MessageLookupByLibrary {
"specialProxy": MessageLookupByLibrary.simpleMessage("特殊代理"),
"specialRules": MessageLookupByLibrary.simpleMessage("特殊规则"),
"speedStatistics": MessageLookupByLibrary.simpleMessage("网速统计"),
"trayIcon": MessageLookupByLibrary.simpleMessage("托盘图标"),
"trayIconDesc": MessageLookupByLibrary.simpleMessage("自定义各状态下的托盘图标"),
"trayIconUseTemplate": MessageLookupByLibrary.simpleMessage("使用模板图像"),
"trayIconUseTemplateDesc": MessageLookupByLibrary.simpleMessage("将自定义图标渲染为单色模板(跟随系统外观)"),
"stackMode": MessageLookupByLibrary.simpleMessage("栈模式"),
"standard": MessageLookupByLibrary.simpleMessage("标准"),
"standardModeDesc": MessageLookupByLibrary.simpleMessage(
Expand Down
35 changes: 35 additions & 0 deletions lib/l10n/l10n.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions lib/manager/tray_manager.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:fl_clash/common/common.dart';
import 'package:fl_clash/controller.dart';
import 'package:fl_clash/providers/config.dart';
import 'package:fl_clash/providers/state.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
Expand All @@ -24,6 +25,14 @@ class _TrayContainerState extends ConsumerState<TrayManager> with TrayListener {
appController.updateTray();
}
});
ref.listenManual(
appSettingProvider.select(
(s) => (s.trayIconStoppedPath, s.trayIconProxyPath, s.trayIconTunPath, s.trayIconUseTemplate),
),
(prev, next) {
if (prev != next) appController.updateTray();
},
);
if (system.isMacOS) {
ref.listenManual(trayTitleStateProvider, (prev, next) {
if (prev != next) {
Expand Down
4 changes: 4 additions & 0 deletions lib/models/config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ abstract class AppSettingProps with _$AppSettingProps {
@Default(false) bool developerMode,
@Default(RestoreStrategy.compatible) RestoreStrategy restoreStrategy,
@Default(true) bool showTrayTitle,
@Default(null) String? trayIconStoppedPath,
@Default(null) String? trayIconProxyPath,
@Default(null) String? trayIconTunPath,
@Default(false) bool trayIconUseTemplate,
}) = _AppSettingProps;

factory AppSettingProps.fromJson(Map<String, Object?> json) =>
Expand Down
Loading