From d087f7c870392d41a3e5b4f477a9b7e489f148e1 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 10 Jul 2025 21:42:29 -0500 Subject: [PATCH] chore: beta flavor build (#19862) * chore: beta flavor build * make file * beta flavor * add build flavor to GHA * add build flavor to GHA --- .github/workflows/build-mobile.yml | 8 ++-- mobile/android/app/build.gradle | 14 ++++++ .../android/app/src/beta/AndroidManifest.xml | 5 ++ .../android/app/src/main/AndroidManifest.xml | 32 ++++++------- .../domain/services/sync_stream.service.dart | 8 +++- mobile/lib/pages/common/tab_shell.page.dart | 6 +++ .../pages/dev/feat_in_development.page.dart | 46 +++++++++++-------- mobile/lib/widgets/common/immich_app_bar.dart | 3 +- .../widgets/common/immich_sliver_app_bar.dart | 5 ++ mobile/makefile | 5 +- 10 files changed, 91 insertions(+), 41 deletions(-) create mode 100644 mobile/android/app/src/beta/AndroidManifest.xml diff --git a/.github/workflows/build-mobile.yml b/.github/workflows/build-mobile.yml index a048536b2f..ca24e33b52 100644 --- a/.github/workflows/build-mobile.yml +++ b/.github/workflows/build-mobile.yml @@ -122,17 +122,17 @@ jobs: IS_MAIN: ${{ github.ref == 'refs/heads/main' }} run: | if [[ $IS_MAIN == 'true' ]]; then - flutter build apk --release - flutter build apk --release --split-per-abi --target-platform android-arm,android-arm64,android-x64 + flutter build apk --release --flavor production + flutter build apk --release --flavor production --split-per-abi --target-platform android-arm,android-arm64,android-x64 else - flutter build apk --debug --split-per-abi --target-platform android-arm64 + flutter build apk --debug --flavor production --split-per-abi --target-platform android-arm64 fi - name: Publish Android Artifact uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: release-apk-signed - path: mobile/build/app/outputs/flutter-apk/*.apk + path: mobile/build/app/outputs/flutter-apk/**/*.apk - name: Save Gradle Cache id: cache-gradle-save diff --git a/mobile/android/app/build.gradle b/mobile/android/app/build.gradle index 0d07228252..870e424461 100644 --- a/mobile/android/app/build.gradle +++ b/mobile/android/app/build.gradle @@ -66,6 +66,20 @@ android { } } + flavorDimensions "default" + productFlavors { + production { + dimension "default" + applicationId "app.alextran.immich" + } + + beta { + dimension "default" + applicationId "app.alextran.immich.beta" + versionNameSuffix "-BETA" + } + } + buildTypes { debug { applicationIdSuffix '.debug' diff --git a/mobile/android/app/src/beta/AndroidManifest.xml b/mobile/android/app/src/beta/AndroidManifest.xml new file mode 100644 index 0000000000..d4f7b5bc80 --- /dev/null +++ b/mobile/android/app/src/beta/AndroidManifest.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/mobile/android/app/src/main/AndroidManifest.xml b/mobile/android/app/src/main/AndroidManifest.xml index 6a96aa68e4..cf3b7ee719 100644 --- a/mobile/android/app/src/main/AndroidManifest.xml +++ b/mobile/android/app/src/main/AndroidManifest.xml @@ -100,24 +100,24 @@ - - - + + + - + - - - - + + + + diff --git a/mobile/lib/domain/services/sync_stream.service.dart b/mobile/lib/domain/services/sync_stream.service.dart index ee0ec6c44f..29066195f2 100644 --- a/mobile/lib/domain/services/sync_stream.service.dart +++ b/mobile/lib/domain/services/sync_stream.service.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:immich_mobile/domain/models/sync_event.model.dart'; import 'package:immich_mobile/infrastructure/repositories/sync_api.repository.dart'; import 'package:immich_mobile/infrastructure/repositories/sync_stream.repository.dart'; +import 'package:immich_mobile/presentation/pages/dev/dev_logger.dart'; import 'package:logging/logging.dart'; import 'package:openapi/api.dart'; @@ -23,7 +24,12 @@ class SyncStreamService { bool get isCancelled => _cancelChecker?.call() ?? false; - Future sync() => _syncApiRepository.streamChanges(_handleEvents); + Future sync() { + _logger.info("Remote sync request for userr"); + DLog.log("Remote sync request for user"); + // Start the sync stream and handle events + return _syncApiRepository.streamChanges(_handleEvents); + } Future _handleEvents(List events, Function() abort) async { List items = []; diff --git a/mobile/lib/pages/common/tab_shell.page.dart b/mobile/lib/pages/common/tab_shell.page.dart index 4eab0e32cf..edaec6d336 100644 --- a/mobile/lib/pages/common/tab_shell.page.dart +++ b/mobile/lib/pages/common/tab_shell.page.dart @@ -5,6 +5,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/providers/asset_viewer/scroll_notifier.provider.dart'; import 'package:immich_mobile/providers/haptic_feedback.provider.dart'; +import 'package:immich_mobile/providers/infrastructure/album.provider.dart'; import 'package:immich_mobile/providers/search/search_input_focus.provider.dart'; import 'package:immich_mobile/providers/tab.provider.dart'; import 'package:immich_mobile/providers/timeline/multiselect.provider.dart'; @@ -164,6 +165,11 @@ void _onNavigationSelected(TabsRouter router, int index, WidgetRef ref) { ref.read(searchInputFocusProvider).requestFocus(); } + // Album page + if (index == 2) { + ref.read(remoteAlbumProvider.notifier).getAll(); + } + ref.read(hapticFeedbackProvider.notifier).selectionClick(); router.setActiveIndex(index); ref.read(tabProvider.notifier).state = TabEnum.values[index]; diff --git a/mobile/lib/presentation/pages/dev/feat_in_development.page.dart b/mobile/lib/presentation/pages/dev/feat_in_development.page.dart index 566c10c70a..bdb426fe22 100644 --- a/mobile/lib/presentation/pages/dev/feat_in_development.page.dart +++ b/mobile/lib/presentation/pages/dev/feat_in_development.page.dart @@ -17,6 +17,21 @@ import 'package:immich_mobile/providers/user.provider.dart'; import 'package:immich_mobile/routing/router.dart'; final _features = [ + _Feature( + name: 'Main Timeline', + icon: Icons.timeline_rounded, + onTap: (ctx, _) => ctx.pushRoute(const TabShellRoute()), + ), + _Feature( + name: 'Video', + icon: Icons.video_collection_outlined, + onTap: (ctx, _) => ctx.pushRoute(const DriftVideoRoute()), + ), + _Feature( + name: 'Recently Taken', + icon: Icons.schedule_outlined, + onTap: (ctx, _) => ctx.pushRoute(const DriftRecentlyTakenRoute()), + ), _Feature( name: 'Selection Mode Timeline', icon: Icons.developer_mode_rounded, @@ -42,23 +57,28 @@ final _features = [ return Future.value(); }, ), + _Feature( + name: '', + icon: Icons.vertical_align_center_sharp, + onTap: (_, __) => Future.value(), + ), _Feature( name: 'Sync Local', icon: Icons.photo_album_rounded, onTap: (_, ref) => ref.read(backgroundSyncProvider).syncLocal(), ), _Feature( - name: 'Sync Local Full', + name: 'Sync Local Full (1)', icon: Icons.photo_library_rounded, onTap: (_, ref) => ref.read(backgroundSyncProvider).syncLocal(full: true), ), _Feature( - name: 'Hash Local Assets', + name: 'Hash Local Assets (2)', icon: Icons.numbers_outlined, onTap: (_, ref) => ref.read(backgroundSyncProvider).hashAssets(), ), _Feature( - name: 'Sync Remote', + name: 'Sync Remote (3)', icon: Icons.refresh_rounded, onTap: (_, ref) => ref.read(backgroundSyncProvider).syncRemote(), ), @@ -69,6 +89,11 @@ final _features = [ .read(driftProvider) .customStatement("pragma wal_checkpoint(truncate)"), ), + _Feature( + name: '', + icon: Icons.vertical_align_center_sharp, + onTap: (_, __) => Future.value(), + ), _Feature( name: 'Clear Delta Checkpoint', icon: Icons.delete_rounded, @@ -122,21 +147,6 @@ final _features = [ } }, ), - _Feature( - name: 'Main Timeline', - icon: Icons.timeline_rounded, - onTap: (ctx, _) => ctx.pushRoute(const TabShellRoute()), - ), - _Feature( - name: 'Video', - icon: Icons.video_collection_outlined, - onTap: (ctx, _) => ctx.pushRoute(const DriftVideoRoute()), - ), - _Feature( - name: 'Recently Taken', - icon: Icons.schedule_outlined, - onTap: (ctx, _) => ctx.pushRoute(const DriftRecentlyTakenRoute()), - ), ]; @RoutePage() diff --git a/mobile/lib/widgets/common/immich_app_bar.dart b/mobile/lib/widgets/common/immich_app_bar.dart index dbf088c112..799cf17f3f 100644 --- a/mobile/lib/widgets/common/immich_app_bar.dart +++ b/mobile/lib/widgets/common/immich_app_bar.dart @@ -2,6 +2,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_svg/svg.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; @@ -185,7 +186,7 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget { child: action, ), ), - if (kDebugMode || kProfileMode) + if (kDebugMode || kProfileMode || appFlavor == 'beta') IconButton( icon: const Icon(Icons.science_rounded), onPressed: () => context.pushRoute(const FeatInDevRoute()), diff --git a/mobile/lib/widgets/common/immich_sliver_app_bar.dart b/mobile/lib/widgets/common/immich_sliver_app_bar.dart index bff1ab4bb1..c2c5b79753 100644 --- a/mobile/lib/widgets/common/immich_sliver_app_bar.dart +++ b/mobile/lib/widgets/common/immich_sliver_app_bar.dart @@ -76,6 +76,11 @@ class ImmichSliverAppBar extends ConsumerWidget { onPressed: () { ref.read(backgroundSyncProvider).syncLocal(full: true); ref.read(backgroundSyncProvider).syncRemote(); + + Future.delayed( + const Duration(seconds: 10), + () => ref.read(backgroundSyncProvider).hashAssets(), + ); }, icon: const Icon( Icons.sync, diff --git a/mobile/makefile b/mobile/makefile index 64992ec946..37d33fa817 100644 --- a/mobile/makefile +++ b/mobile/makefile @@ -28,4 +28,7 @@ translation: dart run easy_localization:generate -S ../i18n dart run bin/generate_keys.dart dart format lib/generated/codegen_loader.g.dart - dart format lib/generated/intl_keys.g.dart \ No newline at end of file + dart format lib/generated/intl_keys.g.dart + +build-beta: + flutter build apk --flavor beta --release