Skip to content

Commit dce500a

Browse files
committed
使用flatpak添加Linux的基本支持
1 parent 96159cd commit dce500a

31 files changed

Lines changed: 1497 additions & 267 deletions

.gitignore

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,11 @@ app.*.map.json
5353
# .env.proxy
5454

5555
script/bin/
56-
windows-installer/src-tauri/resources
56+
windows-installer/src-tauri/resources
57+
58+
# Flatpak related
59+
build-flatpak/
60+
repo-flatpak/
61+
*.flatpak
62+
.flatpak-builder/
63+
GPUCache/
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[Desktop Entry]
2+
Type=Application
3+
Name=Breeze
4+
Name[zh_CN]=Breeze
5+
Description=Third-party client for Bika and JM
6+
Description[zh_CN]=哔咔和禁漫的第三方客户端
7+
Exec=breeze
8+
Icon=io.github.windy.breeze
9+
Terminal=false
10+
Categories=Utility;Network;
11+
keywords=cartoon;comic;bika;jm;
12+
StartupNotify=true

flatpak/io.github.windy.breeze.yml

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
app-id: io.github.windy.breeze
2+
runtime: org.freedesktop.Platform
3+
runtime-version: "24.08"
4+
sdk: org.freedesktop.Sdk
5+
command: breeze
6+
finish-args:
7+
- --share=ipc
8+
- --socket=fallback-x11
9+
- --socket=wayland
10+
- --device=dri
11+
- --share=network
12+
- --filesystem=home
13+
- --talk-name=org.kde.StatusNotifierWatcher
14+
- --env=LD_LIBRARY_PATH=/app/lib
15+
modules:
16+
- name: intltool
17+
buildsystem: autotools
18+
sources:
19+
- type: archive
20+
url: https://launchpad.net/intltool/trunk/0.51.0/+download/intltool-0.51.0.tar.gz
21+
sha256: 67c74d94196b153b774ab9f89b2fa6c6ba79352407037c8c14d5aeb334e959cd
22+
23+
- name: libdbusmenu
24+
buildsystem: simple
25+
build-commands:
26+
- sed -i '/AC_OUTPUT/i AM_CONDITIONAL([HAVE_VALGRIND], [test "x1" = "x0"])' configure.ac
27+
- autoreconf -vfi
28+
- ./configure --prefix=/app --disable-dumper --disable-tests --with-gtk=3 --disable-nls --disable-introspection --disable-vala CFLAGS="-Wno-error"
29+
- make
30+
- make install
31+
sources:
32+
- type: archive
33+
url: https://launchpad.net/libdbusmenu/16.04/16.04.0/+download/libdbusmenu-16.04.0.tar.gz
34+
sha256: b9cc4a2acd74509435892823607d966d424bd9ad5d0b00938f27240a1bfa878a
35+
36+
- name: ayatana-ido
37+
buildsystem: simple
38+
build-commands:
39+
- sed -i '/find_package.*Vala/s/^/#/' src/CMakeLists.txt
40+
- sed -i '/find_package.*GObjectIntrospection/s/^/#/' src/CMakeLists.txt
41+
- sed -i '/install.*gir/s/^/#/' src/CMakeLists.txt
42+
- sed -i '/install.*typelib/s/^/#/' src/CMakeLists.txt
43+
- cmake . -DCMAKE_INSTALL_PREFIX=/app -DCMAKE_INSTALL_LIBDIR=lib -DENABLE_TESTS=OFF -DCMAKE_BUILD_TYPE=Release
44+
- make
45+
- make install
46+
sources:
47+
- type: archive
48+
url: https://github.com/AyatanaIndicators/ayatana-ido/archive/0.10.4.tar.gz
49+
sha256: bd59abd5f1314e411d0d55ce3643e91cef633271f58126be529de5fb71c5ab38
50+
51+
- name: libayatana-indicator
52+
buildsystem: simple
53+
build-commands:
54+
- sed -i '/find_package.*Vala/s/^/#/' src/CMakeLists.txt
55+
- sed -i '/find_package.*GObjectIntrospection/s/^/#/' src/CMakeLists.txt
56+
- sed -i '/install.*gir/s/^/#/' src/CMakeLists.txt
57+
- sed -i '/install.*typelib/s/^/#/' src/CMakeLists.txt
58+
- cmake . -DCMAKE_INSTALL_PREFIX=/app -DCMAKE_INSTALL_LIBDIR=lib -DENABLE_TESTS=OFF -DCMAKE_BUILD_TYPE=Release -DENABLE_BINDINGS_MONO=OFF
59+
- make
60+
- make install
61+
sources:
62+
- type: archive
63+
url: https://github.com/AyatanaIndicators/libayatana-indicator/archive/0.9.4.tar.gz
64+
sha256: a18d3c682e29afd77db24366f8475b26bda22b0e16ff569a2ec71cd6eb4eac95
65+
66+
- name: libayatana-appindicator
67+
buildsystem: simple
68+
build-commands:
69+
- sed -i '/find_package.*Vala/s/^/#/' src/CMakeLists.txt
70+
- sed -i '/find_package.*GObjectIntrospection/s/^/#/' src/CMakeLists.txt
71+
- sed -i '/install.*gir/s/^/#/' src/CMakeLists.txt
72+
- sed -i '/install.*typelib/s/^/#/' src/CMakeLists.txt
73+
- sed -i '/add_custom_target(src ALL DEPENDS/s/^/#/' src/CMakeLists.txt
74+
- cmake . -DCMAKE_INSTALL_PREFIX=/app -DCMAKE_INSTALL_LIBDIR=lib -DENABLE_TESTS=OFF -DCMAKE_BUILD_TYPE=Release -DENABLE_BINDINGS_MONO=OFF -DENABLE_BINDINGS_PYTHON=OFF -DENABLE_BINDINGS_VALA=OFF -DENABLE_GTKDOC=OFF
75+
- make
76+
- make install
77+
sources:
78+
- type: archive
79+
url: https://github.com/AyatanaIndicators/libayatana-appindicator/archive/0.5.93.tar.gz
80+
sha256: cbefed7a918a227bf71286246e237fcd3a9c8499b3eaac4897811a869409edf0
81+
82+
- name: breeze
83+
buildsystem: simple
84+
build-commands:
85+
# Create a directory for the app content
86+
- install -d /app/breeze
87+
# Copy all files from the source (the build bundle) to /app/breeze
88+
- cp -r * /app/breeze/
89+
# Create the bin directory and symlink the executable
90+
- install -d /app/bin
91+
- install -d /app/bin
92+
- ln -s /app/breeze/breeze /app/bin/breeze
93+
# Fix missing libbz2.so.1.0 symlink
94+
- install -d /app/lib
95+
- ln -s /usr/lib/x86_64-linux-gnu/libbz2.so.1.0.8 /app/lib/libbz2.so.1.0
96+
# Create it in /app/breeze/lib where the rust lib resides, to be safe
97+
- ln -s /usr/lib/x86_64-linux-gnu/libbz2.so.1.0.8 /app/breeze/lib/libbz2.so.1.0
98+
# Install the icon
99+
- install -D io.github.windy.breeze.png /app/share/icons/hicolor/128x128/apps/io.github.windy.breeze.png
100+
# Install the desktop file
101+
- install -D io.github.windy.breeze.desktop /app/share/applications/io.github.windy.breeze.desktop
102+
sources:
103+
- type: dir
104+
path: ../build/linux/x64/release/bundle
105+
- type: file
106+
path: ../asset/image/app-icon.png
107+
dest-filename: io.github.windy.breeze.png
108+
- type: file
109+
path: io.github.windy.breeze.desktop

flatpak/pack.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Ensure we are in the project root (one level up from this script)
5+
cd "$(dirname "$0")/.."
6+
7+
echo "🚀 Building Flutter application (Release)..."
8+
flutter build linux --release
9+
10+
echo "📦 Building Flatpak..."
11+
# Define directories
12+
BUILD_DIR="build-flatpak"
13+
REPO_DIR="repo-flatpak"
14+
MANIFEST="flatpak/io.github.windy.breeze.yml"
15+
16+
# Build the Flatpak
17+
# --force-clean: Clean the build directory
18+
# --repo: Export to a repository (needed for bundling)
19+
flatpak-builder --force-clean --repo=$REPO_DIR $BUILD_DIR $MANIFEST
20+
21+
echo "🎁 Creating Flatpak bundle..."
22+
flatpak build-bundle $REPO_DIR breeze.flatpak io.github.windy.breeze
23+
24+
echo "✅ Done! 'breeze.flatpak' has been created in the project root."
25+
echo "To install (for testing): flatpak install --user breeze.flatpak"

lib/main.dart

Lines changed: 53 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ final appRouter = AppRouter();
5353
// 全局事件总线实例
5454
EventBus eventBus = EventBus();
5555

56-
final logger = Logger();
56+
var logger = Logger();
5757

5858
List<String> cfIpList = [];
5959

@@ -162,18 +162,22 @@ Future<void> main() async {
162162
return true; // 表示错误已处理
163163
};
164164
} else {
165-
await Firebase.initializeApp(
166-
options: DefaultFirebaseOptions.currentPlatform,
167-
);
165+
if (!Platform.isLinux) {
166+
await Firebase.initializeApp(
167+
options: DefaultFirebaseOptions.currentPlatform,
168+
);
168169

169-
FlutterError.onError = (FlutterErrorDetails errorDetails) {
170-
FirebaseCrashlytics.instance.recordFlutterFatalError(errorDetails);
171-
};
170+
FlutterError.onError = (FlutterErrorDetails errorDetails) {
171+
FirebaseCrashlytics.instance.recordFlutterFatalError(errorDetails);
172+
};
172173

173-
PlatformDispatcher.instance.onError = (error, stack) {
174-
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
175-
return true; // 表示错误已处理
176-
};
174+
PlatformDispatcher.instance.onError = (error, stack) {
175+
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
176+
return true; // 表示错误已处理
177+
};
178+
} else {
179+
logger = Logger(filter: ProductionFilter(), output: ConsoleOutput());
180+
}
177181
}
178182

179183
runApp(
@@ -191,6 +195,10 @@ Future<void> main() async {
191195
if (kDebugMode) {
192196
logger.e(error, error: error, stackTrace: stackTrace);
193197
} else {
198+
if (Platform.isLinux) {
199+
return;
200+
}
201+
194202
FirebaseCrashlytics.instance.recordError(
195203
error,
196204
stackTrace,
@@ -213,6 +221,7 @@ class _MyAppState extends State<MyApp> with WindowListener, TrayListener {
213221
void initState() {
214222
super.initState();
215223
windowManager.addListener(this);
224+
_init();
216225
WindowLogic.initWindow(context).then((_) {
217226
// 窗口初始化完成后,拦截关闭按钮
218227
windowManager.setPreventClose(true);
@@ -251,22 +260,37 @@ class _MyAppState extends State<MyApp> with WindowListener, TrayListener {
251260

252261
@override
253262
void onWindowClose() async {
254-
// 如果窗口可见,点 X 只是隐藏到托盘
255-
bool isVisible = await windowManager.isVisible();
256-
if (isVisible) {
257-
windowManager.hide();
258-
} else {
259-
// 窗口已隐藏却收到 WM_CLOSE,说明是系统关机或安装器在关闭
260-
_performGracefulExit();
263+
bool isPreventClose = await windowManager.isPreventClose();
264+
if (isPreventClose) {
265+
final dialogContext = appRouter.navigatorKey.currentContext;
266+
if (dialogContext == null || !dialogContext.mounted) return;
267+
showDialog(
268+
context: dialogContext,
269+
builder: (context) {
270+
return AlertDialog(
271+
title: Text('您确定要关闭此窗口吗?'),
272+
actions: [
273+
TextButton(
274+
child: Text('否'),
275+
onPressed: () {
276+
Navigator.of(context).pop();
277+
},
278+
),
279+
TextButton(
280+
child: Text('是'),
281+
onPressed: () async {
282+
Navigator.of(context).pop();
283+
await windowManager.destroy();
284+
},
285+
),
286+
],
287+
);
288+
},
289+
);
261290
}
262291
}
263292

264-
/// 优雅退出:关闭数据库、释放资源后退出
265293
Future<void> _performGracefulExit() async {
266-
logger.i("收到退出指令,正在清理资源...");
267-
await windowManager.setPreventClose(false);
268-
objectbox.store.close();
269-
await Hive.close();
270294
exit(0);
271295
}
272296

@@ -296,6 +320,12 @@ class _MyAppState extends State<MyApp> with WindowListener, TrayListener {
296320
}
297321
}
298322

323+
void _init() async {
324+
// 添加此行以覆盖默认的关闭处理程序
325+
await windowManager.setPreventClose(true);
326+
setState(() {});
327+
}
328+
299329
@override
300330
Widget build(BuildContext context) {
301331
final globalSettingState = context.watch<GlobalSettingCubit>().state;

0 commit comments

Comments
 (0)