diff --git a/mobile/.fvmrc b/mobile/.fvmrc
index cf7449069c..971587f297 100644
--- a/mobile/.fvmrc
+++ b/mobile/.fvmrc
@@ -1,3 +1,3 @@
 {
-  "flutter": "3.22.3"
-}
\ No newline at end of file
+  "flutter": "3.24.0"
+}
diff --git a/mobile/.vscode/settings.json b/mobile/.vscode/settings.json
index c959187bb5..aa43dab3fb 100644
--- a/mobile/.vscode/settings.json
+++ b/mobile/.vscode/settings.json
@@ -1,5 +1,5 @@
 {
-  "dart.flutterSdkPath": ".fvm/versions/3.22.3",
+  "dart.flutterSdkPath": ".fvm/versions/3.24.0",
   "search.exclude": {
     "**/.fvm": true
   },
diff --git a/mobile/android/build.gradle b/mobile/android/build.gradle
index 9b5e515a68..87cc79281d 100644
--- a/mobile/android/build.gradle
+++ b/mobile/android/build.gradle
@@ -10,6 +10,18 @@ allprojects {
 rootProject.buildDir = '../build'
 
 subprojects {
+  //  fix for verifyReleaseResources
+  // ============
+  afterEvaluate { project ->
+        if (project.plugins.hasPlugin("com.android.application") ||
+                project.plugins.hasPlugin("com.android.library")) {
+            project.android {
+                compileSdkVersion 34
+                buildToolsVersion "34.0.0"
+            }
+        }
+    }
+    // ============
     project.buildDir = "${rootProject.buildDir}/${project.name}"
 }
 
@@ -23,4 +35,5 @@ tasks.register("clean", Delete) {
 
 tasks.named('wrapper') {
     distributionType = Wrapper.DistributionType.ALL
-}
\ No newline at end of file
+}
+
diff --git a/mobile/ios/Podfile.lock b/mobile/ios/Podfile.lock
index e3603eef42..3b361c4e19 100644
--- a/mobile/ios/Podfile.lock
+++ b/mobile/ios/Podfile.lock
@@ -202,7 +202,7 @@ SPEC CHECKSUMS:
   fluttertoast: e9a18c7be5413da53898f660530c56f35edfba9c
   geolocator_apple: 6cbaf322953988e009e5ecb481f07efece75c450
   image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1
-  integration_test: ce0a3ffa1de96d1a89ca0ac26fca7ea18a749ef4
+  integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573
   isar_flutter_libs: b69f437aeab9c521821c3f376198c4371fa21073
   MapLibre: 620fc933c1d6029b33738c905c1490d024e5d4ef
   maplibre_gl: a2efec727dd340e4c65e26d2b03b584f14881fd9
diff --git a/mobile/ios/Runner/AppDelegate.swift b/mobile/ios/Runner/AppDelegate.swift
index a73b6417c6..05cb061ca5 100644
--- a/mobile/ios/Runner/AppDelegate.swift
+++ b/mobile/ios/Runner/AppDelegate.swift
@@ -6,7 +6,7 @@ import path_provider_ios
 import photo_manager
 import permission_handler_apple
 
-@UIApplicationMain
+@main
 @objc class AppDelegate: FlutterAppDelegate {
     
   override func application(
diff --git a/mobile/lib/main.dart b/mobile/lib/main.dart
index 916c1ad3d3..dc1df746cb 100644
--- a/mobile/lib/main.dart
+++ b/mobile/lib/main.dart
@@ -39,7 +39,6 @@ import 'package:path_provider/path_provider.dart';
 
 void main() async {
   ImmichWidgetsBinding();
-
   final db = await loadDb();
   await initApp();
   await migrateDatabaseIfNeeded(db);
@@ -73,6 +72,7 @@ Future<void> initApp() async {
   var log = Logger("ImmichErrorLogger");
 
   FlutterError.onError = (details) {
+    debugPrint("FlutterError - Catch all: $details");
     FlutterError.presentError(details);
     log.severe(
       'FlutterError - Catch all',
diff --git a/mobile/lib/pages/common/gallery_viewer.page.dart b/mobile/lib/pages/common/gallery_viewer.page.dart
index 8c2c70d93c..cc62620dfb 100644
--- a/mobile/lib/pages/common/gallery_viewer.page.dart
+++ b/mobile/lib/pages/common/gallery_viewer.page.dart
@@ -264,7 +264,7 @@ class GalleryViewerPage extends HookConsumerWidget {
 
     return PopScope(
       // Change immersive mode back to normal "edgeToEdge" mode
-      onPopInvoked: (_) =>
+      onPopInvokedWithResult: (didPop, _) =>
           SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge),
       child: Scaffold(
         backgroundColor: Colors.black,
diff --git a/mobile/lib/pages/common/headers_settings.page.dart b/mobile/lib/pages/common/headers_settings.page.dart
index e2a816bce1..7f6ee3e4e2 100644
--- a/mobile/lib/pages/common/headers_settings.page.dart
+++ b/mobile/lib/pages/common/headers_settings.page.dart
@@ -74,7 +74,7 @@ class HeaderSettingsPage extends HookConsumerWidget {
         ],
       ),
       body: PopScope(
-        onPopInvoked: (_) => saveHeaders(headers.value),
+        onPopInvokedWithResult: (didPop, _) => saveHeaders(headers.value),
         child: ListView.separated(
           padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 16.0),
           itemCount: list.length,
diff --git a/mobile/lib/pages/common/tab_controller.page.dart b/mobile/lib/pages/common/tab_controller.page.dart
index a48e9e92be..b619e003d2 100644
--- a/mobile/lib/pages/common/tab_controller.page.dart
+++ b/mobile/lib/pages/common/tab_controller.page.dart
@@ -177,7 +177,7 @@ class TabControllerPage extends HookConsumerWidget {
         final tabsRouter = AutoTabsRouter.of(context);
         return PopScope(
           canPop: tabsRouter.activeIndex == 0,
-          onPopInvoked: (didPop) =>
+          onPopInvokedWithResult: (didPop, _) =>
               !didPop ? tabsRouter.setActiveIndex(0) : null,
           child: LayoutBuilder(
             builder: (context, constraints) {
diff --git a/mobile/lib/pages/common/video_viewer.page.dart b/mobile/lib/pages/common/video_viewer.page.dart
index 527411ec89..573f7277f2 100644
--- a/mobile/lib/pages/common/video_viewer.page.dart
+++ b/mobile/lib/pages/common/video_viewer.page.dart
@@ -123,7 +123,7 @@ class VideoViewerPage extends HookConsumerWidget {
     final size = MediaQuery.sizeOf(context);
 
     return PopScope(
-      onPopInvoked: (pop) {
+      onPopInvokedWithResult: (didPop, _) {
         ref.read(videoPlaybackValueProvider.notifier).value =
             VideoPlaybackValue.uninitialized();
       },
diff --git a/mobile/lib/widgets/asset_grid/draggable_scrollbar_custom.dart b/mobile/lib/widgets/asset_grid/draggable_scrollbar_custom.dart
index 94a01a57c5..4490da7aed 100644
--- a/mobile/lib/widgets/asset_grid/draggable_scrollbar_custom.dart
+++ b/mobile/lib/widgets/asset_grid/draggable_scrollbar_custom.dart
@@ -59,6 +59,8 @@ class DraggableScrollbar extends StatefulWidget {
 
   final Function(bool scrolling) scrollStateListener;
 
+  final double viewPortHeight;
+
   DraggableScrollbar.semicircle({
     super.key,
     Key? scrollThumbKey,
@@ -67,6 +69,7 @@ class DraggableScrollbar extends StatefulWidget {
     required this.controller,
     required this.itemPositionsListener,
     required this.scrollStateListener,
+    required this.viewPortHeight,
     this.heightScrollThumb = 48.0,
     this.backgroundColor = Colors.white,
     this.padding,
@@ -251,7 +254,7 @@ class DraggableScrollbarState extends State<DraggableScrollbar>
   }
 
   double get barMaxScrollExtent =>
-      (context.size?.height ?? 0) -
+      widget.viewPortHeight -
       widget.heightScrollThumb -
       (widget.heightOffset ?? 0);
 
@@ -316,37 +319,39 @@ class DraggableScrollbarState extends State<DraggableScrollbar>
     }
 
     setState(() {
-      int firstItemIndex =
-          widget.itemPositionsListener.itemPositions.value.first.index;
+      try {
+        int firstItemIndex =
+            widget.itemPositionsListener.itemPositions.value.first.index;
 
-      if (notification is ScrollUpdateNotification) {
-        _barOffset = (firstItemIndex / maxItemCount) * barMaxScrollExtent;
+        if (notification is ScrollUpdateNotification) {
+          _barOffset = (firstItemIndex / maxItemCount) * barMaxScrollExtent;
 
-        if (_barOffset < barMinScrollExtent) {
-          _barOffset = barMinScrollExtent;
-        }
-        if (_barOffset > barMaxScrollExtent) {
-          _barOffset = barMaxScrollExtent;
-        }
-      }
-
-      if (notification is ScrollUpdateNotification ||
-          notification is OverscrollNotification) {
-        if (_thumbAnimationController.status != AnimationStatus.forward) {
-          _thumbAnimationController.forward();
+          if (_barOffset < barMinScrollExtent) {
+            _barOffset = barMinScrollExtent;
+          }
+          if (_barOffset > barMaxScrollExtent) {
+            _barOffset = barMaxScrollExtent;
+          }
         }
 
-        if (itemPos < maxItemCount) {
-          _currentItem = itemPos;
-        }
+        if (notification is ScrollUpdateNotification ||
+            notification is OverscrollNotification) {
+          if (_thumbAnimationController.status != AnimationStatus.forward) {
+            _thumbAnimationController.forward();
+          }
 
-        _fadeoutTimer?.cancel();
-        _fadeoutTimer = Timer(widget.scrollbarTimeToFade, () {
-          _thumbAnimationController.reverse();
-          _labelAnimationController.reverse();
-          _fadeoutTimer = null;
-        });
-      }
+          if (itemPos < maxItemCount) {
+            _currentItem = itemPos;
+          }
+
+          _fadeoutTimer?.cancel();
+          _fadeoutTimer = Timer(widget.scrollbarTimeToFade, () {
+            _thumbAnimationController.reverse();
+            _labelAnimationController.reverse();
+            _fadeoutTimer = null;
+          });
+        }
+      } catch (_) {}
     });
   }
 
diff --git a/mobile/lib/widgets/asset_grid/immich_asset_grid_view.dart b/mobile/lib/widgets/asset_grid/immich_asset_grid_view.dart
index ea65031a0c..8ae74ba120 100644
--- a/mobile/lib/widgets/asset_grid/immich_asset_grid_view.dart
+++ b/mobile/lib/widgets/asset_grid/immich_asset_grid_view.dart
@@ -262,8 +262,9 @@ class ImmichAssetGridViewState extends ConsumerState<ImmichAssetGridView> {
       shrinkWrap: widget.shrinkWrap,
     );
 
-    final child = useDragScrolling
+    final child = (useDragScrolling && ModalRoute.of(context) != null)
         ? DraggableScrollbar.semicircle(
+            viewPortHeight: context.height,
             scrollStateListener: dragScrolling,
             itemPositionsListener: _itemPositionsListener,
             controller: _itemScrollController,
@@ -281,6 +282,7 @@ class ImmichAssetGridViewState extends ConsumerState<ImmichAssetGridView> {
             child: listWidget,
           )
         : listWidget;
+
     return widget.onRefresh == null
         ? child
         : appBarOffset()
@@ -528,7 +530,7 @@ class ImmichAssetGridViewState extends ConsumerState<ImmichAssetGridView> {
   Widget build(BuildContext context) {
     return PopScope(
       canPop: !(widget.selectionActive && _selectedAssets.isNotEmpty),
-      onPopInvoked: (didPop) => !didPop ? _deselectAll() : null,
+      onPopInvokedWithResult: (didPop, _) => !didPop ? _deselectAll() : null,
       child: Stack(
         children: [
           AssetDragRegion(
diff --git a/mobile/lib/widgets/common/immich_app_bar.dart b/mobile/lib/widgets/common/immich_app_bar.dart
index 455a19fcdb..8e2465fc9c 100644
--- a/mobile/lib/widgets/common/immich_app_bar.dart
+++ b/mobile/lib/widgets/common/immich_app_bar.dart
@@ -58,7 +58,7 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget {
           isLabelVisible: serverInfoState.isVersionMismatch ||
               ((user?.isAdmin ?? false) &&
                   serverInfoState.isNewReleaseAvailable),
-          offset: const Offset(2, 2),
+          offset: const Offset(-2, -12),
           child: user == null
               ? const Icon(
                   Icons.face_outlined,
@@ -132,7 +132,7 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget {
           backgroundColor: Colors.transparent,
           alignment: Alignment.bottomRight,
           isLabelVisible: indicatorIcon != null,
-          offset: const Offset(2, 2),
+          offset: const Offset(-2, -12),
           child: Icon(
             Icons.backup_rounded,
             size: widgetSize,
diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock
index 5c62b95227..14b487ce4d 100644
--- a/mobile/pubspec.lock
+++ b/mobile/pubspec.lock
@@ -5,23 +5,23 @@ packages:
     dependency: transitive
     description:
       name: _fe_analyzer_shared
-      sha256: "5aaf60d96c4cd00fe7f21594b5ad6a1b699c80a27420f8a837f4d68473ef09e3"
+      sha256: f256b0c0ba6c7577c15e2e4e114755640a875e885099367bf6e012b19314c834
       url: "https://pub.dev"
     source: hosted
-    version: "68.0.0"
+    version: "72.0.0"
   _macros:
     dependency: transitive
     description: dart
     source: sdk
-    version: "0.1.0"
+    version: "0.3.2"
   analyzer:
     dependency: "direct overridden"
     description:
       name: analyzer
-      sha256: "21f1d3720fd1c70316399d5e2bccaebb415c434592d778cce8acb967b8578808"
+      sha256: b652861553cd3990d8ed361f7979dc6d7053a9ac8843fa73820ab68ce5410139
       url: "https://pub.dev"
     source: hosted
-    version: "6.5.0"
+    version: "6.7.0"
   analyzer_plugin:
     dependency: "direct overridden"
     description:
@@ -540,10 +540,10 @@ packages:
     dependency: "direct main"
     description:
       name: flutter_local_notifications
-      sha256: "55b9b229307a10974b26296ff29f2e132256ba4bd74266939118eaefa941cb00"
+      sha256: dd6676d8c2926537eccdf9f72128bbb2a9d0814689527b17f92c248ff192eaf3
       url: "https://pub.dev"
     source: hosted
-    version: "16.3.3"
+    version: "17.2.1+2"
   flutter_local_notifications_linux:
     dependency: transitive
     description:
@@ -901,18 +901,18 @@ packages:
     dependency: transitive
     description:
       name: leak_tracker
-      sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
+      sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05"
       url: "https://pub.dev"
     source: hosted
-    version: "10.0.4"
+    version: "10.0.5"
   leak_tracker_flutter_testing:
     dependency: transitive
     description:
       name: leak_tracker_flutter_testing
-      sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
+      sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806"
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.3"
+    version: "3.0.5"
   leak_tracker_testing:
     dependency: transitive
     description:
@@ -941,10 +941,10 @@ packages:
     dependency: transitive
     description:
       name: macros
-      sha256: "12e8a9842b5a7390de7a781ec63d793527582398d16ea26c60fed58833c9ae79"
+      sha256: "0acaed5d6b7eab89f63350bccd82119e6c602df0f391260d0e32b5e23db79536"
       url: "https://pub.dev"
     source: hosted
-    version: "0.1.0-main.0"
+    version: "0.1.2-main.4"
   maplibre_gl:
     dependency: "direct main"
     description:
@@ -981,10 +981,10 @@ packages:
     dependency: transitive
     description:
       name: material_color_utilities
-      sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
+      sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
       url: "https://pub.dev"
     source: hosted
-    version: "0.8.0"
+    version: "0.11.1"
   meta:
     dependency: "direct overridden"
     description:
@@ -1212,10 +1212,10 @@ packages:
     dependency: transitive
     description:
       name: platform
-      sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
+      sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65"
       url: "https://pub.dev"
     source: hosted
-    version: "3.1.4"
+    version: "3.1.5"
   plugin_platform_interface:
     dependency: transitive
     description:
@@ -1537,10 +1537,10 @@ packages:
     dependency: transitive
     description:
       name: test_api
-      sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
+      sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb"
       url: "https://pub.dev"
     source: hosted
-    version: "0.7.0"
+    version: "0.7.2"
   thumbhash:
     dependency: "direct main"
     description:
@@ -1737,10 +1737,10 @@ packages:
     dependency: transitive
     description:
       name: vm_service
-      sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
+      sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc
       url: "https://pub.dev"
     source: hosted
-    version: "14.2.1"
+    version: "14.2.4"
   wakelock_plus:
     dependency: "direct main"
     description:
@@ -1847,4 +1847,4 @@ packages:
     version: "3.1.2"
 sdks:
   dart: ">=3.4.0 <4.0.0"
-  flutter: ">=3.22.3"
+  flutter: ">=3.24.0"
diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml
index 2551acce48..51a31a24e3 100644
--- a/mobile/pubspec.yaml
+++ b/mobile/pubspec.yaml
@@ -6,7 +6,7 @@ version: 1.112.1+154
 
 environment:
   sdk: '>=3.3.0 <4.0.0'
-  flutter: 3.22.3
+  flutter: 3.24.0
 
 dependencies:
   flutter:
@@ -50,7 +50,7 @@ dependencies:
   device_info_plus: ^9.1.1
   connectivity_plus: ^5.0.2
   wakelock_plus: ^1.1.4
-  flutter_local_notifications: ^16.3.2
+  flutter_local_notifications: ^17.2.1+2
   timezone: ^0.9.2
   octo_image: ^2.0.0
   thumbhash: 0.1.0+1