From f757ba04e86c3c89f78b3305e4dd25e46c6118b9 Mon Sep 17 00:00:00 2001 From: broken-droid Date: Sat, 16 May 2026 17:14:16 -0500 Subject: [PATCH 1/8] add support for windows beta builds --- windows/CMakeLists.txt | 9 ++++++++- windows/runner/Runner.rc | 11 +++++++++-- windows/runner/main.cpp | 4 ++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index f2ebb31e..1dfd1ec1 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -2,7 +2,14 @@ cmake_minimum_required(VERSION 3.14) project(moonfin LANGUAGES CXX) -set(BINARY_NAME "moonfin") +# for CLI - flutter run --dart-define=MOONFIN_WINDOWS_BETA=true +# for launch configurations - add an env for "MOONFIN_WINDOWS_BETA": "true" +if(DEFINED ENV{MOONFIN_BETA_BUILD}) + set(BINARY_NAME "Moonfin-Beta") + add_definitions(-DMOONFIN_BETA_BUILD) +else() + set(BINARY_NAME "moonfin") +endif () # Explicitly opt in to modern CMake behaviors to avoid warnings with recent # versions of CMake. diff --git a/windows/runner/Runner.rc b/windows/runner/Runner.rc index baa35c31..0490ea76 100644 --- a/windows/runner/Runner.rc +++ b/windows/runner/Runner.rc @@ -90,12 +90,19 @@ BEGIN BLOCK "040904e4" BEGIN VALUE "CompanyName", "org.moonfin" "\0" +#ifdef MOONFIN_BETA_BUILD + VALUE "FileDescription", "Moonfin Beta" "\0" + VALUE "InternalName", "moonfin-beta" "\0" + VALUE "OriginalFilename", "moonfin-beta.exe" "\0" + VALUE "ProductName", "Moonfin Beta" "\0" +#else VALUE "FileDescription", "Moonfin" "\0" - VALUE "FileVersion", VERSION_AS_STRING "\0" VALUE "InternalName", "moonfin" "\0" - VALUE "LegalCopyright", "Copyright (C) 2026 org.moonfin. All rights reserved." "\0" VALUE "OriginalFilename", "moonfin.exe" "\0" VALUE "ProductName", "Moonfin" "\0" +#endif + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "LegalCopyright", "Copyright (C) 2026 org.moonfin. All rights reserved." "\0" VALUE "ProductVersion", VERSION_AS_STRING "\0" END END diff --git a/windows/runner/main.cpp b/windows/runner/main.cpp index fcbd5ef9..81ea4c63 100644 --- a/windows/runner/main.cpp +++ b/windows/runner/main.cpp @@ -27,7 +27,11 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, FlutterWindow window(project); Win32Window::Point origin(10, 10); Win32Window::Size size(1280, 720); +#ifdef MOONFIN_BETA_BUILD + if (!window.Create(L"Moonfin Beta", origin, size)) { +#else if (!window.Create(L"Moonfin", origin, size)) { +#endif return EXIT_FAILURE; } window.SetQuitOnClose(true); From 4a5ca548584fc6221a19322cda88416bc3b35050 Mon Sep 17 00:00:00 2001 From: broken-droid Date: Sat, 16 May 2026 17:54:45 -0500 Subject: [PATCH 2/8] change some hardcoded paths in storage_path_service.dart --- lib/data/services/storage_path_service.dart | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/data/services/storage_path_service.dart b/lib/data/services/storage_path_service.dart index aa532ec4..32105f2b 100644 --- a/lib/data/services/storage_path_service.dart +++ b/lib/data/services/storage_path_service.dart @@ -17,6 +17,9 @@ class StoragePathService { void clearCache() => _cachedRoot = null; + static String get appFolderName => + const bool.fromEnvironment('MOONFIN_BETA_BUILD') ? 'MoonfinBeta' : 'Moonfin'; + Future getOfflineRoot() async { if (_cachedRoot != null) return _cachedRoot!; @@ -45,10 +48,10 @@ class StoragePathService { if (PlatformDetection.isAndroid) { final extDir = await getExternalStorageDirectory(); final base = extDir ?? await getApplicationDocumentsDirectory(); - dir = Directory('${base.path}/Moonfin'); + dir = Directory('${base.path}/$appFolderName'); } else if (PlatformDetection.isIOS) { final docs = await getApplicationDocumentsDirectory(); - dir = Directory('${docs.path}/Moonfin'); + dir = Directory('${docs.path}/$appFolderName'); } else { final support = await getApplicationSupportDirectory(); dir = Directory('${support.path}/Downloads'); @@ -82,7 +85,7 @@ class StoragePathService { Future getDatabaseFile() async { final docs = await getApplicationDocumentsDirectory(); - final dbDir = Directory('${docs.path}/Moonfin/DB'); + final dbDir = Directory('${docs.path}/$appFolderName/DB'); if (!await dbDir.exists()) await dbDir.create(recursive: true); return File('${dbDir.path}/offline.db'); } @@ -90,7 +93,7 @@ class StoragePathService { Future getImageCacheDir() async { if (PlatformDetection.isAndroid && _useMediaStore) { final support = await getApplicationSupportDirectory(); - final dir = Directory('${support.path}/Moonfin/images'); + final dir = Directory('${support.path}/$appFolderName/images'); if (!await dir.exists()) await dir.create(recursive: true); return dir; } From f3ed45e1f1fdd73bfeb31fa32293e53241e75e82 Mon Sep 17 00:00:00 2001 From: broken-droid Date: Sat, 16 May 2026 18:16:13 -0500 Subject: [PATCH 3/8] Fix the appFolderName helper to read from env in addition to reading explicitly passed vars in --dart-define Updated a hardcoded path in database_connection_impl_io.dart to use the StoragePathService static helper --- lib/data/database/database_connection_impl_io.dart | 3 ++- lib/data/services/storage_path_service.dart | 10 +++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/data/database/database_connection_impl_io.dart b/lib/data/database/database_connection_impl_io.dart index 6fe00639..504d55fa 100644 --- a/lib/data/database/database_connection_impl_io.dart +++ b/lib/data/database/database_connection_impl_io.dart @@ -2,12 +2,13 @@ import 'dart:io'; import 'package:drift/drift.dart'; import 'package:drift/native.dart'; +import 'package:moonfin/data/services/storage_path_service.dart'; import 'package:path_provider/path_provider.dart'; QueryExecutor openConnection() { return LazyDatabase(() async { final docs = await getApplicationDocumentsDirectory(); - final dbDir = Directory('${docs.path}/Moonfin/DB'); + final dbDir = Directory('${docs.path}/${StoragePathService.appFolderName}/DB'); if (!dbDir.existsSync()) { await dbDir.create(recursive: true); } diff --git a/lib/data/services/storage_path_service.dart b/lib/data/services/storage_path_service.dart index 32105f2b..4e0ebbf2 100644 --- a/lib/data/services/storage_path_service.dart +++ b/lib/data/services/storage_path_service.dart @@ -17,9 +17,13 @@ class StoragePathService { void clearCache() => _cachedRoot = null; - static String get appFolderName => - const bool.fromEnvironment('MOONFIN_BETA_BUILD') ? 'MoonfinBeta' : 'Moonfin'; - + static String get appFolderName { + // Checks for the env var set either from launch configs or dart-define + final isBeta = Platform.environment['MOONFIN_BETA_BUILD'] == 'true' || + const bool.fromEnvironment('MOONFIN_BETA_BUILD'); + return isBeta ? 'MoonfinBeta' : 'Moonfin'; + } + Future getOfflineRoot() async { if (_cachedRoot != null) return _cachedRoot!; From ea52eb05c0ba627d2980c91f8323baf79f98dd9e Mon Sep 17 00:00:00 2001 From: broken-droid Date: Sat, 16 May 2026 18:19:34 -0500 Subject: [PATCH 4/8] fix comment --- windows/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index 1dfd1ec1..f0c00fdb 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.14) project(moonfin LANGUAGES CXX) -# for CLI - flutter run --dart-define=MOONFIN_WINDOWS_BETA=true -# for launch configurations - add an env for "MOONFIN_WINDOWS_BETA": "true" +# for CLI - flutter run --dart-define=MOONFIN_BETA_BUILD=true +# for launch configurations - add an env for "MOONFIN_BETA_BUILD": "true" if(DEFINED ENV{MOONFIN_BETA_BUILD}) set(BINARY_NAME "Moonfin-Beta") add_definitions(-DMOONFIN_BETA_BUILD) From 9879e487e94312ec2565efc6761013b3db6ceff3 Mon Sep 17 00:00:00 2001 From: broken-droid Date: Sat, 16 May 2026 18:22:29 -0500 Subject: [PATCH 5/8] initial linux setup - untested --- linux/CMakeLists.txt | 12 ++++++++++-- linux/runner/my_application.cc | 4 ++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index d54c29d8..707a6733 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -2,8 +2,16 @@ cmake_minimum_required(VERSION 3.13) project(runner LANGUAGES CXX) -set(BINARY_NAME "moonfin") -set(APPLICATION_ID "org.moonfin.linux") +# for CLI - flutter run --dart-define=MOONFIN_BETA_BUILD=true +# for launch configurations - add an env for "MOONFIN_BETA_BUILD": "true" +if(DEFINED ENV{MOONFIN_BETA_BUILD}) + set(BINARY_NAME "moonfin-beta") + set(APPLICATION_ID "org.moonfin.linux.beta") + add_definitions(-DMOONFIN_BETA_BUILD) +else() + set(BINARY_NAME "moonfin") + set(APPLICATION_ID "org.moonfin.linux") +endif() # Explicitly opt in to modern CMake behaviors to avoid warnings with recent # versions of CMake. diff --git a/linux/runner/my_application.cc b/linux/runner/my_application.cc index 302f7303..1c70f4ae 100644 --- a/linux/runner/my_application.cc +++ b/linux/runner/my_application.cc @@ -17,7 +17,11 @@ static void my_application_activate(GApplication* application) { GtkWindow* window = GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); +#ifdef MOONFIN_BETA_BUILD + gtk_window_set_title(window, "Moonfin Beta"); +#else gtk_window_set_title(window, "Moonfin"); +#endif gtk_window_set_default_size(window, 1280, 720); gtk_widget_show(GTK_WIDGET(window)); From 39fc56ec506854b2a167e7df962017c9aa49143c Mon Sep 17 00:00:00 2001 From: broken-droid Date: Sat, 16 May 2026 23:32:00 -0500 Subject: [PATCH 6/8] add flavor detection to appFolderName helper so flavors use separate app paths too --- lib/data/services/storage_path_service.dart | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/data/services/storage_path_service.dart b/lib/data/services/storage_path_service.dart index 4e0ebbf2..1ab64ec7 100644 --- a/lib/data/services/storage_path_service.dart +++ b/lib/data/services/storage_path_service.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'dart:math'; +import 'package:flutter/foundation.dart'; import 'package:get_it/get_it.dart'; import 'package:path_provider/path_provider.dart'; @@ -17,13 +18,21 @@ class StoragePathService { void clearCache() => _cachedRoot = null; - static String get appFolderName { - // Checks for the env var set either from launch configs or dart-define - final isBeta = Platform.environment['MOONFIN_BETA_BUILD'] == 'true' || - const bool.fromEnvironment('MOONFIN_BETA_BUILD'); + static String get appFolderName { + // get the flavor passed via --flavor + // android/androidtv/macos/ios - only android/androidtv are set up currently + const flavor = String.fromEnvironment('FLUTTER_APP_FLAVOR'); + final betaFlavor = flavor.toLowerCase().contains('beta'); + // check for --dart-define MOONFIN_BETA_BUILD=true from CLI + const betaCLI = bool.fromEnvironment('MOONFIN_BETA_BUILD'); + // check for env var MOONFIN_BETA_BUILD=true + final betaEnvVar = Platform.environment['MOONFIN_BETA_BUILD'] == 'true'; + + final isBeta = betaFlavor || betaCLI || betaEnvVar; + debugPrint('StoragePathService: isBeta=$isBeta (flavor=$flavor, betaCLI=$betaCLI, betaEnvVar=$betaEnvVar)'); return isBeta ? 'MoonfinBeta' : 'Moonfin'; } - + Future getOfflineRoot() async { if (_cachedRoot != null) return _cachedRoot!; From 91439eb3cdc5ecc818a2d5598c772535bcf71052 Mon Sep 17 00:00:00 2001 From: broken-droid Date: Tue, 19 May 2026 17:27:13 -0500 Subject: [PATCH 7/8] create window-beta-build.ps1 script to set beta env for cmake, and pass dart-define for flutter --- build-windows-beta.ps1 | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 build-windows-beta.ps1 diff --git a/build-windows-beta.ps1 b/build-windows-beta.ps1 new file mode 100644 index 00000000..0b59d0d1 --- /dev/null +++ b/build-windows-beta.ps1 @@ -0,0 +1,29 @@ +param( + [string[]]$FlutterArgs = @() +) + +# Set the build flag for this process only +$env:MOONFIN_BETA_BUILD = "true" + +# wipe out the windows build directory if you're running into build problems +#$buildDir = Join-Path $PSScriptRoot "build\windows\x64" +#if (Test-Path $buildDir) { +# Write-Host "Removing existing Windows build dir: $buildDir" +# Remove-Item -Recurse -Force $buildDir +#} + +# Ensure the dart-define is passed to the Flutter tool so `const.fromEnvironment` +# in Dart will be set at compile time. Also allow additional args to be passed. +$argsList = @("build", "windows", "--release") + $FlutterArgs +if (-not ($argsList -contains "--dart-define=MOONFIN_BETA_BUILD=true")) { + $argsList += "--dart-define=MOONFIN_BETA_BUILD=true" +} +Write-Host "Running: flutter $($argsList -join ' ')" +& flutter @argsList +$exit = $LASTEXITCODE +if ($exit -ne 0) { + Write-Error "flutter build windows failed with exit code $exit" + exit $exit +} + +Write-Host "Built Windows Beta version" From 4994bc3d5ae3188b111a766dbc341d034cdfae9b Mon Sep 17 00:00:00 2001 From: broken-droid Date: Tue, 19 May 2026 17:48:00 -0500 Subject: [PATCH 8/8] Changed concept, building beta on windows will still need dart-define so we'll just check for that. Also runtime may not have the env set anymore which wouldn't make sense. Windows can't see dart-define in the cmake process, linux might be able to. Changed getImageCacheDir path for windows, since it includes the app name already --- lib/data/services/storage_path_service.dart | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/data/services/storage_path_service.dart b/lib/data/services/storage_path_service.dart index 1ab64ec7..72c7b7cb 100644 --- a/lib/data/services/storage_path_service.dart +++ b/lib/data/services/storage_path_service.dart @@ -20,17 +20,17 @@ class StoragePathService { static String get appFolderName { // get the flavor passed via --flavor - // android/androidtv/macos/ios - only android/androidtv are set up currently + // android/androidtv/macos/ios/linux too? - only android/androidtv are set up currently const flavor = String.fromEnvironment('FLUTTER_APP_FLAVOR'); final betaFlavor = flavor.toLowerCase().contains('beta'); + // check for --dart-define MOONFIN_BETA_BUILD=true from CLI - const betaCLI = bool.fromEnvironment('MOONFIN_BETA_BUILD'); - // check for env var MOONFIN_BETA_BUILD=true - final betaEnvVar = Platform.environment['MOONFIN_BETA_BUILD'] == 'true'; + // needed for windows, and maybe linux if we don't do a flavor + const betaDartDefine = bool.fromEnvironment('MOONFIN_BETA_BUILD'); - final isBeta = betaFlavor || betaCLI || betaEnvVar; - debugPrint('StoragePathService: isBeta=$isBeta (flavor=$flavor, betaCLI=$betaCLI, betaEnvVar=$betaEnvVar)'); - return isBeta ? 'MoonfinBeta' : 'Moonfin'; + final isBeta = betaFlavor || betaDartDefine; + debugPrint('StoragePathService: isBeta=$isBeta (flavor=$flavor, betaDartDefine=$betaDartDefine)'); + return isBeta ? 'Moonfin Beta' : 'Moonfin'; } Future getOfflineRoot() async { @@ -106,7 +106,10 @@ class StoragePathService { Future getImageCacheDir() async { if (PlatformDetection.isAndroid && _useMediaStore) { final support = await getApplicationSupportDirectory(); - final dir = Directory('${support.path}/$appFolderName/images'); + final dir = (!Platform.isWindows) + ? Directory('${support.path}/$appFolderName/images') + // windows includes the app folder + : Directory('${support.path}/images'); if (!await dir.exists()) await dir.create(recursive: true); return dir; }