mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-14 20:33:41 +00:00
feat(ui): support running as menubar app (#1216)
This commit is contained in:
1 parent
b0e133b554
commit
cb6331c20d
28 files changed
+214
-40
No files matched your search
@@ -115,6 +115,9 @@ class AppController extends GetxController with WindowListener, TrayListener {
|
||||
@override
|
||||
void onWindowFocus() {
|
||||
refresh();
|
||||
if (Util.isMacos() && Database.instance.getRunAsMenubarApp()) {
|
||||
windowManager.setSkipTaskbar(true);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -9,9 +9,11 @@ import 'package:gopeed/app/views/copy_button.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:launch_at_startup/launch_at_startup.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
import '../../../../api/api.dart' as api;
|
||||
import '../../../../api/model/downloader_config.dart';
|
||||
import '../../../../database/database.dart';
|
||||
import '../../../../i18n/message.dart';
|
||||
import '../../../../util/input_formatter.dart';
|
||||
import '../../../../util/locale_manager.dart';
|
||||
@@ -369,6 +371,46 @@ class SettingView extends GetView<SettingController> {
|
||||
);
|
||||
});
|
||||
|
||||
// Menubar mode only for macOS
|
||||
final buildMenubarMode = !Util.isMacos()
|
||||
? () => null
|
||||
: _buildConfigItem('runAsMenubarApp', () {
|
||||
return Database.instance.getRunAsMenubarApp() ? 'on'.tr : 'off'.tr;
|
||||
}, (Key key) {
|
||||
return Container(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Switch(
|
||||
value: Database.instance.getRunAsMenubarApp(),
|
||||
onChanged: (bool value) async {
|
||||
// Save to database (single source of truth)
|
||||
Database.instance.saveRunAsMenubarApp(value);
|
||||
// Apply dock icon visibility
|
||||
await windowManager.setSkipTaskbar(value);
|
||||
// Small delay to let macOS process the activation policy change
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
// Ensure window stays visible after toggle
|
||||
await windowManager.show();
|
||||
await windowManager.focus();
|
||||
// Force UI refresh
|
||||
controller.clearTap();
|
||||
await debounceSave();
|
||||
},
|
||||
),
|
||||
Text(
|
||||
'runAsMenubarAppDesc'.tr,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Theme.of(context).hintColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
// http config items start
|
||||
final httpConfig = downloaderCfg.value.protocolConfig.http;
|
||||
final buildHttpUa =
|
||||
@@ -1353,6 +1395,7 @@ class SettingView extends GetView<SettingController> {
|
||||
buildDefaultDirectDownload(),
|
||||
buildBrowserExtension(),
|
||||
buildAutoStartup(),
|
||||
buildMenubarMode(),
|
||||
]),
|
||||
)),
|
||||
Text('archives'.tr),
|
||||
|
||||
@@ -10,6 +10,7 @@ const String _windowState = 'windowState';
|
||||
const String _bookmark = 'bookmark';
|
||||
const String _createHistory = 'createHistory';
|
||||
const String _webToken = 'webToken';
|
||||
const String _runAsMenubarApp = 'runAsMenubarApp';
|
||||
|
||||
class Database {
|
||||
static final Database _instance = Database._internal();
|
||||
@@ -109,4 +110,12 @@ class Database {
|
||||
void clearCreateHistory() {
|
||||
clear(_createHistory);
|
||||
}
|
||||
|
||||
void saveRunAsMenubarApp(bool value) {
|
||||
box.put(_runAsMenubarApp, value);
|
||||
}
|
||||
|
||||
bool getRunAsMenubarApp() {
|
||||
return box.get(_runAsMenubarApp, defaultValue: false) as bool;
|
||||
}
|
||||
}
|
||||
@@ -106,6 +106,8 @@ const deDE = {
|
||||
'Vielen Dank an alle Mitwirkenden, die beim Aufbau und der Entwicklung der Gopeed-Community geholfen haben!',
|
||||
'browserExtension': 'Browsererweiterung',
|
||||
'launchAtStartup': 'Beim Start starten',
|
||||
'runAsMenubarApp': 'Als Menüleisten-App ausführen',
|
||||
'runAsMenubarAppDesc': 'Dock-Symbol ausblenden und nur in der Menüleiste ausführen',
|
||||
'seedConfig': 'Seed-Konfiguration',
|
||||
'seedKeep': 'Weiter-seeden bis manuell gestoppt',
|
||||
'seedRatio': 'Seed Verhältniss',
|
||||
|
||||
@@ -114,6 +114,8 @@ const enUS = {
|
||||
'Thanks to all the contributors who have helped build and develop the Gopeed community!',
|
||||
'browserExtension': 'Browser Extension',
|
||||
'launchAtStartup': 'Launch at Startup',
|
||||
'runAsMenubarApp': 'Run as menubar app',
|
||||
'runAsMenubarAppDesc': 'Hide dock icon and run in menubar only',
|
||||
'seedConfig': 'Seed Config',
|
||||
'seedKeep': 'Keep seeding until manually stopped',
|
||||
'seedRatio': 'Seed ratio',
|
||||
|
||||
@@ -99,6 +99,8 @@ const esES = {
|
||||
'¡Gracias a todos los contribuyentes que han ayudado a construir y desarrollar la comunidad Gopeed!',
|
||||
'browserExtension': 'Extensión del Navegador',
|
||||
'launchAtStartup': 'Iniciar al Arranque',
|
||||
'runAsMenubarApp': 'Ejecutar como aplicación de barra de menú',
|
||||
'runAsMenubarAppDesc': 'Ocultar icono del Dock y ejecutar solo en la barra de menú',
|
||||
'seedConfig': 'Configuración de Semilla',
|
||||
'seedKeep': 'Mantener sembrado',
|
||||
'seedRatio': 'Ratio de semilla',
|
||||
|
||||
@@ -86,5 +86,8 @@ const faIR = {
|
||||
'categoryPath': 'مسیر دستهبندی',
|
||||
'builtInCategory': 'دستهبندی داخلی قابل حذف نیست',
|
||||
'selectCategory': 'انتخاب دستهبندی',
|
||||
'launchAtStartup': 'راهاندازی در استارتآپ',
|
||||
'runAsMenubarApp': 'اجرا به عنوان برنامه نوار منو',
|
||||
'runAsMenubarAppDesc': 'پنهان کردن آیکون Dock و اجرا فقط در نوار منو',
|
||||
}
|
||||
};
|
||||
@@ -99,6 +99,8 @@ const frFR = {
|
||||
'Merci à tous les contributeurs qui ont aidé à construire et développer la communauté Gopeed !',
|
||||
'browserExtension': 'Extension du navigateur',
|
||||
'launchAtStartup': 'Lancer au démarrage',
|
||||
'runAsMenubarApp': 'Exécuter en tant qu\'application de barre de menus',
|
||||
'runAsMenubarAppDesc': 'Masquer l\'icône du Dock et exécuter uniquement dans la barre de menus',
|
||||
'skipVerifyCert': 'Ignorer la vérification du certificat',
|
||||
'archives': 'Archives',
|
||||
'autoExtract': 'Extraire automatiquement les archives',
|
||||
|
||||
@@ -106,6 +106,8 @@ const huHU = {
|
||||
'Köszönet minden hozzájárulónak, aki segített a Gopeed közösség építésében és fejlesztésében!',
|
||||
'browserExtension': 'Böngésző bővítmény',
|
||||
'launchAtStartup': 'Indítás indításkor',
|
||||
'runAsMenubarApp': 'Futtatás menüsáv alkalmazásként',
|
||||
'runAsMenubarAppDesc': 'Dock ikon elrejtése és csak a menüsávban való futtatás',
|
||||
'seedConfig': 'Seed beállítás',
|
||||
'seedKeep': 'Tartsa a seedet amíg manuálisan le nem állítják',
|
||||
'seedRatio': 'Seed arány',
|
||||
|
||||
@@ -101,6 +101,8 @@ const idID = {
|
||||
'Terima kasih kepada semua kontributor yang telah membantu membangun dan mengembangkan komunitas Gopeed!',
|
||||
'browserExtension': 'Ekstensi Perambanan',
|
||||
'launchAtStartup': 'Luncurkan saat Startup',
|
||||
'runAsMenubarApp': 'Jalankan sebagai aplikasi bilah menu',
|
||||
'runAsMenubarAppDesc': 'Sembunyikan ikon Dock dan jalankan hanya di bilah menu',
|
||||
'seedConfig': 'Konfigurasi Seed',
|
||||
'seedKeep': 'Terus seeding hingga dihentikan secara manual',
|
||||
'seedRatio': 'Rasio Seed',
|
||||
|
||||
@@ -97,6 +97,8 @@ const itIT = {
|
||||
'Grazie a tutti i contributori che hanno contribuito a costruire e sviluppare la comunità Gopeed!',
|
||||
'browserExtension': 'Estensione del browser',
|
||||
'launchAtStartup': "Lancia all'avvio",
|
||||
'runAsMenubarApp': 'Esegui come app della barra dei menu',
|
||||
'runAsMenubarAppDesc': 'Nascondi icona Dock ed esegui solo nella barra dei menu',
|
||||
'skipVerifyCert': 'Salta la verifica del certificato',
|
||||
'archives': 'Archivi',
|
||||
'autoExtract': 'Estrai automaticamente gli archivi',
|
||||
|
||||
@@ -87,5 +87,8 @@ const jaJP = {
|
||||
'categoryPath': 'カテゴリパス',
|
||||
'builtInCategory': '内蔵カテゴリは削除できません',
|
||||
'selectCategory': 'カテゴリを選択',
|
||||
'launchAtStartup': '起動時に起動',
|
||||
'runAsMenubarApp': 'メニューバーアプリとして実行',
|
||||
'runAsMenubarAppDesc': 'Dockアイコンを非表示にして、メニューバーのみで実行',
|
||||
}
|
||||
};
|
||||
@@ -95,6 +95,8 @@ const plPL = {
|
||||
'Dziękuję wszystkim za pomoc przy powstawaniu aplikacji Gopeed!',
|
||||
'browserExtension': 'Wtyczka dla przeglądarki',
|
||||
'launchAtStartup': 'Uruchom na starcie',
|
||||
'runAsMenubarApp': 'Uruchom jako aplikacja paska menu',
|
||||
'runAsMenubarAppDesc': 'Ukryj ikonę Docka i uruchom tylko w pasku menu',
|
||||
'skipVerifyCert': 'Pomiń weryfikację certyfikatu',
|
||||
'archives': 'Archiwa',
|
||||
'autoExtract': 'Automatycznie wyodrębnij archiwa',
|
||||
|
||||
@@ -103,6 +103,8 @@ const ptBR = {
|
||||
'Obrigado a todos os colaboradores que ajudaram a construir e desenvolver a comunidade Gopeed!',
|
||||
'browserExtension': 'Extensões para Navegadores',
|
||||
'launchAtStartup': 'Launch at Startup',
|
||||
'runAsMenubarApp': 'Executar como aplicativo da barra de menus',
|
||||
'runAsMenubarAppDesc': 'Ocultar ícone do Dock e executar apenas na barra de menus',
|
||||
'seedConfig': 'Seed Config',
|
||||
'seedKeep': 'Keep seeding until manually stopped',
|
||||
'seedRatio': 'Seed ratio',
|
||||
|
||||
@@ -103,6 +103,8 @@ const ruRU = {
|
||||
'Благодарим всех участников за их вклад в строительство и развитие сообщества Gopeed!',
|
||||
'browserExtension': 'Расширение браузера',
|
||||
'launchAtStartup': 'Запускать при загрузке системы',
|
||||
'runAsMenubarApp': 'Запускать как приложение в строке меню',
|
||||
'runAsMenubarAppDesc': 'Скрыть значок в Dock и запускать только в строке меню',
|
||||
'seedConfig': 'Настройка раздачи',
|
||||
'seedKeep': 'Раздавать пока не остановлю вручную',
|
||||
'seedRatio': 'Коэффициент раздачи',
|
||||
|
||||
@@ -97,6 +97,8 @@ const taTA = {
|
||||
'Gopeed சமூகத்தை உருவாக்கவும் மற்றும் மேம்படுத்த உதவிய அனைத்து பங்களிப்பாளர்களுக்கும் நன்றி!',
|
||||
'browserExtension': 'உலாவி நீட்டிப்பு',
|
||||
'launchAtStartup': 'தொடக்கத்தின் போது இயங்கு',
|
||||
'runAsMenubarApp': 'மெனுபார் பயன்பாடாக இயக்கு',
|
||||
'runAsMenubarAppDesc': 'டாக் ஐகானை மறைத்து மெனுபாரில் மட்டும் இயக்கு',
|
||||
'skipVerifyCert': 'திருத்தி சான்று சரிபார்க்கவும்',
|
||||
'archives': 'காப்பகங்கள்',
|
||||
'autoExtract': 'காப்பகங்களை தானாக பிரித்தெடு',
|
||||
|
||||
@@ -104,6 +104,8 @@ const trTR = {
|
||||
'Gopeed topluluğunun inşasında ve geliştirilmesinde katkıda bulunan herkese teşekkürler!',
|
||||
'browserExtension': 'Tarayıcı Eklentisi',
|
||||
'launchAtStartup': 'Başlangıçta Çalıştır',
|
||||
'runAsMenubarApp': 'Menü çubuğu uygulaması olarak çalıştır',
|
||||
'runAsMenubarAppDesc': 'Dock simgesini gizle ve yalnızca menü çubuğunda çalıştır',
|
||||
'seedConfig': 'Seed Ayarları',
|
||||
'seedKeep': 'Manuel olarak durdurulana kadar seed etmeye devam et',
|
||||
'seedRatio': 'Seed oranı',
|
||||
|
||||
@@ -103,6 +103,8 @@ const ukUA = {
|
||||
'Дякуємо всім учасникам, які допомогли створити та розвивати спільноту Gopeed!',
|
||||
'browserExtension': 'Розширення для браузера',
|
||||
'launchAtStartup': 'Запускати під час завантаження системи',
|
||||
'runAsMenubarApp': 'Запускати як додаток у рядку меню',
|
||||
'runAsMenubarAppDesc': 'Приховати значок у Dock і запускати лише в рядку меню',
|
||||
'seedConfig': 'Налаштування роздачі',
|
||||
'seedKeep': 'Роздавати доки не зупиню вручну',
|
||||
'seedRatio': 'Коефіцієнт роздачі',
|
||||
|
||||
@@ -114,5 +114,8 @@ const viVN = {
|
||||
'categoryPath': 'Đường dẫn danh mục',
|
||||
'builtInCategory': 'Không thể xóa danh mục tích hợp',
|
||||
'selectCategory': 'Chọn danh mục',
|
||||
'launchAtStartup': 'Khởi động cùng hệ thống',
|
||||
'runAsMenubarApp': 'Chạy như ứng dụng thanh menu',
|
||||
'runAsMenubarAppDesc': 'Ẩn biểu tượng Dock và chỉ chạy trong thanh menu',
|
||||
},
|
||||
};
|
||||
@@ -112,6 +112,8 @@ const zhCN = {
|
||||
'thanksDesc': '感谢所有为 Gopeed 社区建设添砖加瓦的贡献者们!',
|
||||
'browserExtension': '浏览器扩展',
|
||||
'launchAtStartup': '开机自动运行',
|
||||
'runAsMenubarApp': '以菜单栏应用运行',
|
||||
'runAsMenubarAppDesc': '隐藏程序坞图标,仅在菜单栏运行',
|
||||
'seedConfig': '做种设置',
|
||||
'seedKeep': '持续做种直到手动停止',
|
||||
'seedRatio': '做种分享率',
|
||||
|
||||
@@ -100,6 +100,8 @@ const zhTW = {
|
||||
'thanksDesc': '感謝所有幫助建立和發展 Gopeed 社群的貢獻者!',
|
||||
'browserExtension': '瀏覽器擴充功能',
|
||||
'launchAtStartup': '開機自動執行',
|
||||
'runAsMenubarApp': '以選單列應用程式執行',
|
||||
'runAsMenubarAppDesc': '隱藏 Dock 圖示,僅在選單列執行',
|
||||
'seedConfig': '做種設定',
|
||||
'seedKeep': '持續做種直到手動停止',
|
||||
'seedRatio': '做種分享率',
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import 'package:args/args.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_foreground_task/flutter_foreground_task.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:hotkey_manager/hotkey_manager.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
import 'api/api.dart' as api;
|
||||
@@ -67,10 +69,14 @@ Future<void> init(Args args) async {
|
||||
if (Util.isDesktop()) {
|
||||
await windowManager.ensureInitialized();
|
||||
final windowState = Database.instance.getWindowState();
|
||||
|
||||
// Check if menubar mode is enabled (only for macOS)
|
||||
final runAsMenubarApp = Util.isMacos() && Database.instance.getRunAsMenubarApp();
|
||||
|
||||
final windowOptions = WindowOptions(
|
||||
size: Size(windowState?.width ?? 800, windowState?.height ?? 600),
|
||||
center: true,
|
||||
skipTaskbar: false,
|
||||
skipTaskbar: runAsMenubarApp,
|
||||
);
|
||||
await windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||
if (!args.hidden) {
|
||||
@@ -84,6 +90,22 @@ Future<void> init(Args args) async {
|
||||
// await windowManager.maximize();
|
||||
// }
|
||||
});
|
||||
|
||||
// Register Cmd+W hotkey on macOS to close window
|
||||
if (Util.isMacos()) {
|
||||
await hotKeyManager.unregisterAll();
|
||||
HotKey hotKey = HotKey(
|
||||
key: PhysicalKeyboardKey.keyW,
|
||||
modifiers: [HotKeyModifier.meta],
|
||||
scope: HotKeyScope.inapp,
|
||||
);
|
||||
await hotKeyManager.register(
|
||||
hotKey,
|
||||
keyDownHandler: (hotKey) {
|
||||
windowManager.hide();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
initLogger();
|
||||
|
||||
Reference in new issue
Block a user