You've already forked immich
							
							
				mirror of
				https://github.com/immich-app/immich.git
				synced 2025-10-31 00:18:28 +02:00 
			
		
		
		
	chore(mobile): Upgrade to Flutter 3.7 (#1416)
This commit is contained in:
		
							
								
								
									
										2
									
								
								.github/workflows/build-mobile.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/build-mobile.yml
									
									
									
									
										vendored
									
									
								
							| @@ -39,7 +39,7 @@ jobs: | ||||
|         uses: subosito/flutter-action@v2 | ||||
|         with: | ||||
|           channel: "stable" | ||||
|           flutter-version: "3.3.10" | ||||
|           flutter-version: "3.7.3" | ||||
|           cache: true | ||||
|  | ||||
|       - name: Create the Keystore | ||||
|   | ||||
							
								
								
									
										2
									
								
								.github/workflows/static_analysis.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/static_analysis.yml
									
									
									
									
										vendored
									
									
								
							| @@ -19,7 +19,7 @@ jobs: | ||||
|         uses: subosito/flutter-action@v2 | ||||
|         with: | ||||
|           channel: 'stable' | ||||
|           flutter-version: '3.3.10' | ||||
|           flutter-version: '3.7.3' | ||||
|  | ||||
|       - name: Install dependencies | ||||
|         run: dart pub get | ||||
|   | ||||
							
								
								
									
										4
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/test.yml
									
									
									
									
										vendored
									
									
								
							| @@ -49,7 +49,7 @@ jobs: | ||||
|         uses: subosito/flutter-action@v2 | ||||
|         with: | ||||
|           channel: 'stable' | ||||
|           flutter-version: '3.3.10' | ||||
|           flutter-version: '3.7.3' | ||||
|       - name: Run tests | ||||
|         working-directory: ./mobile | ||||
|         run: flutter test | ||||
| @@ -78,7 +78,7 @@ jobs: | ||||
|         uses: subosito/flutter-action@v2 | ||||
|         with: | ||||
|           channel: 'stable' | ||||
|           flutter-version: '3.3.10' | ||||
|           flutter-version: '3.7.3' | ||||
|       - name: Run integration tests | ||||
|         uses: reactivecircus/android-emulator-runner@v2.27.0 | ||||
|         with: | ||||
|   | ||||
| @@ -2,6 +2,11 @@ | ||||
|   xmlns:tools="http://schemas.android.com/tools"> | ||||
|   <application android:label="Immich" android:name=".ImmichApp" android:usesCleartextTraffic="true" | ||||
|     android:icon="@mipmap/ic_launcher" android:requestLegacyExternalStorage="true"> | ||||
|  | ||||
|     <meta-data | ||||
|       android:name="io.flutter.embedding.android.EnableImpeller" | ||||
|       android:value="false" /> | ||||
|  | ||||
|     <activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop" | ||||
|       android:theme="@style/LaunchTheme" | ||||
|       android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" | ||||
|   | ||||
| @@ -7,7 +7,8 @@ void main() async { | ||||
|   await ImmichTestHelper.initialize(); | ||||
|  | ||||
|   group("Login input validation test", () { | ||||
|     immichWidgetTest("Test leading/trailing whitespace", (tester, helper) async { | ||||
|     immichWidgetTest("Test leading/trailing whitespace", | ||||
|         (tester, helper) async { | ||||
|       await helper.loginHelper.waitForLoginScreen(); | ||||
|       await helper.loginHelper.acknowledgeNewServerVersion(); | ||||
|  | ||||
| @@ -17,15 +18,21 @@ void main() async { | ||||
|  | ||||
|       await tester.pump(const Duration(milliseconds: 300)); | ||||
|  | ||||
|       expect(find.text("login_form_err_leading_whitespace".tr()), findsOneWidget); | ||||
|       expect( | ||||
|         find.text("login_form_err_leading_whitespace".tr()), | ||||
|         findsOneWidget, | ||||
|       ); | ||||
|  | ||||
|       await helper.loginHelper.enterCredentials( | ||||
|           email: "demo@immich.app ", | ||||
|         email: "demo@immich.app ", | ||||
|       ); | ||||
|  | ||||
|       await tester.pump(const Duration(milliseconds: 300)); | ||||
|  | ||||
|       expect(find.text("login_form_err_trailing_whitespace".tr()), findsOneWidget); | ||||
|       expect( | ||||
|         find.text("login_form_err_trailing_whitespace".tr()), | ||||
|         findsOneWidget, | ||||
|       ); | ||||
|     }); | ||||
|  | ||||
|     immichWidgetTest("Test invalid email", (tester, helper) async { | ||||
| @@ -33,13 +40,12 @@ void main() async { | ||||
|       await helper.loginHelper.acknowledgeNewServerVersion(); | ||||
|  | ||||
|       await helper.loginHelper.enterCredentials( | ||||
|           email: "demo.immich.app", | ||||
|         email: "demo.immich.app", | ||||
|       ); | ||||
|  | ||||
|       await tester.pump(const Duration(milliseconds: 300)); | ||||
|  | ||||
|       expect(find.text("login_form_err_invalid_email".tr()), findsOneWidget); | ||||
|     }); | ||||
|  | ||||
|   }); | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| # Uncomment this line to define a global platform for your project | ||||
| platform :ios, '11.0' | ||||
| # platform :ios, '11.0' | ||||
|  | ||||
| # CocoaPods analytics sends network stats synchronously affecting flutter build latency. | ||||
| ENV['COCOAPODS_DISABLE_STATS'] = 'true' | ||||
| @@ -34,19 +34,8 @@ target 'Runner' do | ||||
|   flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) | ||||
| end | ||||
|  | ||||
| # post_install do |installer| | ||||
| #   installer.pods_project.targets.each do |target| | ||||
| #     flutter_additional_ios_build_settings(target) | ||||
| #   end | ||||
| # end | ||||
|  | ||||
| post_install do |installer|  | ||||
|   installer.pods_project.targets.each do |target|  | ||||
|     flutter_additional_ios_build_settings(target)  | ||||
|     target.build_configurations.each do |config|  | ||||
|       config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"  | ||||
|       config.build_settings['ENABLE_BITCODE'] = 'YES'  | ||||
|       config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0'  | ||||
|     end  | ||||
|   end  | ||||
| end | ||||
| post_install do |installer| | ||||
|   installer.pods_project.targets.each do |target| | ||||
|     flutter_additional_ios_build_settings(target) | ||||
|   end | ||||
| end | ||||
| @@ -21,16 +21,18 @@ PODS: | ||||
|     - Flutter | ||||
|   - package_info_plus (0.4.5): | ||||
|     - Flutter | ||||
|   - path_provider_ios (0.0.1): | ||||
|   - path_provider_foundation (0.0.1): | ||||
|     - Flutter | ||||
|     - FlutterMacOS | ||||
|   - photo_manager (2.0.0): | ||||
|     - Flutter | ||||
|     - FlutterMacOS | ||||
|   - SAMKeychain (1.5.3) | ||||
|   - share_plus (0.0.1): | ||||
|     - Flutter | ||||
|   - shared_preferences_ios (0.0.1): | ||||
|   - shared_preferences_foundation (0.0.1): | ||||
|     - Flutter | ||||
|     - FlutterMacOS | ||||
|   - sqflite (0.0.2): | ||||
|     - Flutter | ||||
|     - FMDB (>= 2.7.5) | ||||
| @@ -52,10 +54,10 @@ DEPENDENCIES: | ||||
|   - integration_test (from `.symlinks/plugins/integration_test/ios`) | ||||
|   - isar_flutter_libs (from `.symlinks/plugins/isar_flutter_libs/ios`) | ||||
|   - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) | ||||
|   - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`) | ||||
|   - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`) | ||||
|   - photo_manager (from `.symlinks/plugins/photo_manager/ios`) | ||||
|   - share_plus (from `.symlinks/plugins/share_plus/ios`) | ||||
|   - shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`) | ||||
|   - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`) | ||||
|   - sqflite (from `.symlinks/plugins/sqflite/ios`) | ||||
|   - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) | ||||
|   - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`) | ||||
| @@ -86,14 +88,14 @@ EXTERNAL SOURCES: | ||||
|     :path: ".symlinks/plugins/isar_flutter_libs/ios" | ||||
|   package_info_plus: | ||||
|     :path: ".symlinks/plugins/package_info_plus/ios" | ||||
|   path_provider_ios: | ||||
|     :path: ".symlinks/plugins/path_provider_ios/ios" | ||||
|   path_provider_foundation: | ||||
|     :path: ".symlinks/plugins/path_provider_foundation/ios" | ||||
|   photo_manager: | ||||
|     :path: ".symlinks/plugins/photo_manager/ios" | ||||
|   share_plus: | ||||
|     :path: ".symlinks/plugins/share_plus/ios" | ||||
|   shared_preferences_ios: | ||||
|     :path: ".symlinks/plugins/shared_preferences_ios/ios" | ||||
|   shared_preferences_foundation: | ||||
|     :path: ".symlinks/plugins/shared_preferences_foundation/ios" | ||||
|   sqflite: | ||||
|     :path: ".symlinks/plugins/sqflite/ios" | ||||
|   url_launcher_ios: | ||||
| @@ -108,23 +110,23 @@ SPEC CHECKSUMS: | ||||
|   flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef | ||||
|   flutter_udid: 0848809dbed4c055175747ae6a45a8b4f6771e1c | ||||
|   flutter_web_auth: c25208760459cec375a3c39f6a8759165ca0fa4d | ||||
|   fluttertoast: 16fbe6039d06a763f3533670197d01fc73459037 | ||||
|   fluttertoast: eb263d302cc92e04176c053d2385237e9f43fad0 | ||||
|   FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a | ||||
|   image_picker_ios: b786a5dcf033a8336a657191401bfdf12017dabb | ||||
|   integration_test: a1e7d09bd98eca2fc37aefd79d4f41ad37bdbbe5 | ||||
|   isar_flutter_libs: b69f437aeab9c521821c3f376198c4371fa21073 | ||||
|   package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e | ||||
|   path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02 | ||||
|   path_provider_foundation: 37748e03f12783f9de2cb2c4eadfaa25fe6d4852 | ||||
|   photo_manager: 4f6810b7dfc4feb03b461ac1a70dacf91fba7604 | ||||
|   SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c | ||||
|   share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68 | ||||
|   shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad | ||||
|   shared_preferences_foundation: 297b3ebca31b34ec92be11acd7fb0ba932c822ca | ||||
|   sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 | ||||
|   Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 | ||||
|   url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de | ||||
|   url_launcher_ios: ae1517e5e344f5544fb090b079e11f399dfbe4d2 | ||||
|   video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff | ||||
|   wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f | ||||
|  | ||||
| PODFILE CHECKSUM: 05c3056158482c567a3e0cdab1351ceeee238a07 | ||||
| PODFILE CHECKSUM: c798208781ca5116c4a3d5927d689946791f0189 | ||||
|  | ||||
| COCOAPODS: 1.11.3 | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
| 	archiveVersion = 1; | ||||
| 	classes = { | ||||
| 	}; | ||||
| 	objectVersion = 51; | ||||
| 	objectVersion = 54; | ||||
| 	objects = { | ||||
|  | ||||
| /* Begin PBXBuildFile section */ | ||||
| @@ -201,6 +201,7 @@ | ||||
| /* Begin PBXShellScriptBuildPhase section */ | ||||
| 		3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { | ||||
| 			isa = PBXShellScriptBuildPhase; | ||||
| 			alwaysOutOfDate = 1; | ||||
| 			buildActionMask = 2147483647; | ||||
| 			files = ( | ||||
| 			); | ||||
| @@ -237,6 +238,7 @@ | ||||
| 		}; | ||||
| 		9740EEB61CF901F6004384FC /* Run Script */ = { | ||||
| 			isa = PBXShellScriptBuildPhase; | ||||
| 			alwaysOutOfDate = 1; | ||||
| 			buildActionMask = 2147483647; | ||||
| 			files = ( | ||||
| 			); | ||||
| @@ -341,7 +343,7 @@ | ||||
| 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | ||||
| 				GCC_WARN_UNUSED_FUNCTION = YES; | ||||
| 				GCC_WARN_UNUSED_VARIABLE = YES; | ||||
| 				IPHONEOS_DEPLOYMENT_TARGET = 11.0; | ||||
| 				IPHONEOS_DEPLOYMENT_TARGET = 13.0; | ||||
| 				MTL_ENABLE_DEBUG_INFO = NO; | ||||
| 				NEW_SETTING = ""; | ||||
| 				SDKROOT = iphoneos; | ||||
| @@ -425,7 +427,7 @@ | ||||
| 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | ||||
| 				GCC_WARN_UNUSED_FUNCTION = YES; | ||||
| 				GCC_WARN_UNUSED_VARIABLE = YES; | ||||
| 				IPHONEOS_DEPLOYMENT_TARGET = 11.0; | ||||
| 				IPHONEOS_DEPLOYMENT_TARGET = 13.0; | ||||
| 				MTL_ENABLE_DEBUG_INFO = YES; | ||||
| 				NEW_SETTING = ""; | ||||
| 				ONLY_ACTIVE_ARCH = YES; | ||||
| @@ -475,7 +477,7 @@ | ||||
| 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | ||||
| 				GCC_WARN_UNUSED_FUNCTION = YES; | ||||
| 				GCC_WARN_UNUSED_VARIABLE = YES; | ||||
| 				IPHONEOS_DEPLOYMENT_TARGET = 11.0; | ||||
| 				IPHONEOS_DEPLOYMENT_TARGET = 13.0; | ||||
| 				MTL_ENABLE_DEBUG_INFO = NO; | ||||
| 				NEW_SETTING = ""; | ||||
| 				SDKROOT = iphoneos; | ||||
|   | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -1,97 +1,101 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||
| <plist version="1.0"> | ||||
| 	<dict> | ||||
| 		<key>CFBundleDevelopmentRegion</key> | ||||
| 		<string>$(DEVELOPMENT_LANGUAGE)</string> | ||||
| 		<key>CFBundleDisplayName</key> | ||||
| 		<string>Immich</string> | ||||
| 		<key>CFBundleExecutable</key> | ||||
| 		<string>$(EXECUTABLE_NAME)</string> | ||||
| 		<key>CFBundleIdentifier</key> | ||||
| 		<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||||
| 		<key>CFBundleInfoDictionaryVersion</key> | ||||
| 		<string>6.0</string> | ||||
| 		<key>CFBundleName</key> | ||||
| 		<string>immich_mobile</string> | ||||
| 		<key>CFBundlePackageType</key> | ||||
| 		<string>APPL</string> | ||||
| 		<key>CFBundleShortVersionString</key> | ||||
| 		<string>1.46.0</string> | ||||
| 		<key>CFBundleSignature</key> | ||||
| 		<string>????</string> | ||||
| 		<key>CFBundleVersion</key> | ||||
| 		<string>85</string> | ||||
| 		<key>LSRequiresIPhoneOS</key> | ||||
| 		<true/> | ||||
| 		<key>MGLMapboxMetricsEnabledSettingShownInApp</key> | ||||
| 		<true/> | ||||
| 		<key>NSAppTransportSecurity</key> | ||||
| 		<dict> | ||||
| 			<key>NSAllowsArbitraryLoads</key> | ||||
| 			<true/> | ||||
| 		</dict> | ||||
| 		<key>NSLocationAlwaysUsageDescription</key> | ||||
| 		<string>Enable location setting to show position of assets on map</string> | ||||
| 		<key>NSLocationWhenInUseUsageDescription</key> | ||||
| 		<string>Enable location setting to show position of assets on map</string> | ||||
| 		<key>NSPhotoLibraryUsageDescription</key> | ||||
| 		<string>We need to manage backup your photos album</string> | ||||
| 		<key>NSPhotoLibraryAddUsageDescription</key> | ||||
| 		<string>We need to manage backup your photos album</string> | ||||
| 		<key>NSCameraUsageDescription</key> | ||||
| 		<string>We need to access the camera to let you take beautiful video using this app</string> | ||||
| 		<key>NSMicrophoneUsageDescription</key> | ||||
| 		<string>We need to access the microphone to let you take beautiful video using this app</string> | ||||
| 		<key>UILaunchStoryboardName</key> | ||||
| 		<string>LaunchScreen</string> | ||||
| 		<key>UIMainStoryboardFile</key> | ||||
| 		<string>Main</string> | ||||
| 		<key>UISupportedInterfaceOrientations</key> | ||||
| 		<array> | ||||
| 			<string>UIInterfaceOrientationPortrait</string> | ||||
| 			<string>UIInterfaceOrientationLandscapeLeft</string> | ||||
| 			<string>UIInterfaceOrientationLandscapeRight</string> | ||||
| 		</array> | ||||
| 		<key>UISupportedInterfaceOrientations~ipad</key> | ||||
| 		<array> | ||||
| 			<string>UIInterfaceOrientationPortrait</string> | ||||
| 			<string>UIInterfaceOrientationPortraitUpsideDown</string> | ||||
| 			<string>UIInterfaceOrientationLandscapeLeft</string> | ||||
| 			<string>UIInterfaceOrientationLandscapeRight</string> | ||||
| 		</array> | ||||
| 		<key>UIViewControllerBasedStatusBarAppearance</key> | ||||
| 		<true/> | ||||
| 		<key>io.flutter.embedded_views_preview</key> | ||||
| 		<true/> | ||||
| 		<key>ITSAppUsesNonExemptEncryption</key> | ||||
| 		<false/> | ||||
| 		<key>CADisableMinimumFrameDurationOnPhone</key> | ||||
| 		<true/> | ||||
| 		<key>LSApplicationQueriesSchemes</key> | ||||
| 		<array> | ||||
| 			<string>https</string> | ||||
| 		</array> | ||||
| 		<key>CFBundleLocalizations</key> | ||||
| 		<array> | ||||
| 			<string>cs</string> | ||||
| 			<string>da</string> | ||||
| 			<string>de</string> | ||||
| 			<string>en</string> | ||||
| 			<string>es</string> | ||||
| 			<string>fi</string> | ||||
| 			<string>fr</string> | ||||
| 			<string>it</string> | ||||
| 			<string>ja</string> | ||||
| 			<string>ko</string> | ||||
| 			<string>nl</string> | ||||
| 			<string>pl</string> | ||||
| 			<string>pt</string> | ||||
| 			<string>ru</string> | ||||
| 			<string>sk</string> | ||||
| 			<string>zh</string> | ||||
| 		</array> | ||||
| 		<key>UIStatusBarHidden</key> | ||||
| 		<false/> | ||||
| 	</dict> | ||||
| </plist> | ||||
|   <dict> | ||||
|     <key>CFBundleDevelopmentRegion</key> | ||||
|     <string>$(DEVELOPMENT_LANGUAGE)</string> | ||||
|     <key>CFBundleDisplayName</key> | ||||
|     <string>Immich</string> | ||||
|     <key>CFBundleExecutable</key> | ||||
|     <string>$(EXECUTABLE_NAME)</string> | ||||
|     <key>CFBundleIdentifier</key> | ||||
|     <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||||
|     <key>CFBundleInfoDictionaryVersion</key> | ||||
|     <string>6.0</string> | ||||
|     <key>CFBundleName</key> | ||||
|     <string>immich_mobile</string> | ||||
|     <key>CFBundlePackageType</key> | ||||
|     <string>APPL</string> | ||||
|     <key>CFBundleShortVersionString</key> | ||||
|     <string>1.46.0</string> | ||||
|     <key>CFBundleSignature</key> | ||||
|     <string>????</string> | ||||
|     <key>CFBundleVersion</key> | ||||
|     <string>85</string> | ||||
|     <key>LSRequiresIPhoneOS</key> | ||||
|     <true /> | ||||
|     <key>MGLMapboxMetricsEnabledSettingShownInApp</key> | ||||
|     <true /> | ||||
|     <key>NSAppTransportSecurity</key> | ||||
|     <dict> | ||||
|       <key>NSAllowsArbitraryLoads</key> | ||||
|       <true /> | ||||
|     </dict> | ||||
|     <key>NSLocationAlwaysUsageDescription</key> | ||||
|     <string>Enable location setting to show position of assets on map</string> | ||||
|     <key>NSLocationWhenInUseUsageDescription</key> | ||||
|     <string>Enable location setting to show position of assets on map</string> | ||||
|     <key>NSPhotoLibraryUsageDescription</key> | ||||
|     <string>We need to manage backup your photos album</string> | ||||
|     <key>NSPhotoLibraryAddUsageDescription</key> | ||||
|     <string>We need to manage backup your photos album</string> | ||||
|     <key>NSCameraUsageDescription</key> | ||||
|     <string>We need to access the camera to let you take beautiful video using this app</string> | ||||
|     <key>NSMicrophoneUsageDescription</key> | ||||
|     <string>We need to access the microphone to let you take beautiful video using this app</string> | ||||
|     <key>UILaunchStoryboardName</key> | ||||
|     <string>LaunchScreen</string> | ||||
|     <key>UIMainStoryboardFile</key> | ||||
|     <string>Main</string> | ||||
|     <key>UISupportedInterfaceOrientations</key> | ||||
|     <array> | ||||
|       <string>UIInterfaceOrientationPortrait</string> | ||||
|       <string>UIInterfaceOrientationLandscapeLeft</string> | ||||
|       <string>UIInterfaceOrientationLandscapeRight</string> | ||||
|     </array> | ||||
|     <key>UISupportedInterfaceOrientations~ipad</key> | ||||
|     <array> | ||||
|       <string>UIInterfaceOrientationPortrait</string> | ||||
|       <string>UIInterfaceOrientationPortraitUpsideDown</string> | ||||
|       <string>UIInterfaceOrientationLandscapeLeft</string> | ||||
|       <string>UIInterfaceOrientationLandscapeRight</string> | ||||
|     </array> | ||||
|     <key>UIViewControllerBasedStatusBarAppearance</key> | ||||
|     <true /> | ||||
|     <key>io.flutter.embedded_views_preview</key> | ||||
|     <true /> | ||||
|     <key>ITSAppUsesNonExemptEncryption</key> | ||||
|     <false /> | ||||
|     <key>CADisableMinimumFrameDurationOnPhone</key> | ||||
|     <true /> | ||||
|     <key>LSApplicationQueriesSchemes</key> | ||||
|     <array> | ||||
|       <string>https</string> | ||||
|     </array> | ||||
|     <key>CFBundleLocalizations</key> | ||||
|     <array> | ||||
|       <string>cs</string> | ||||
|       <string>da</string> | ||||
|       <string>de</string> | ||||
|       <string>en</string> | ||||
|       <string>es</string> | ||||
|       <string>fi</string> | ||||
|       <string>fr</string> | ||||
|       <string>it</string> | ||||
|       <string>ja</string> | ||||
|       <string>ko</string> | ||||
|       <string>nl</string> | ||||
|       <string>pl</string> | ||||
|       <string>pt</string> | ||||
|       <string>ru</string> | ||||
|       <string>sk</string> | ||||
|       <string>zh</string> | ||||
|     </array> | ||||
|     <key>UIStatusBarHidden</key> | ||||
|     <false /> | ||||
|     <key>UIApplicationSupportsIndirectInputEvents</key> | ||||
|     <true /> | ||||
|     <key>FLTEnableImpeller</key> | ||||
|     <true /> | ||||
|   </dict> | ||||
| </plist> | ||||
| @@ -91,7 +91,7 @@ class AddToAlbumBottomSheet extends HookConsumerWidget { | ||||
|                     children: [ | ||||
|                       Text( | ||||
|                         'Add to album', | ||||
|                         style: Theme.of(context).textTheme.headline2, | ||||
|                         style: Theme.of(context).textTheme.displayMedium, | ||||
|                       ), | ||||
|                       TextButton.icon( | ||||
|                         icon: const Icon(Icons.add), | ||||
|   | ||||
| @@ -24,90 +24,97 @@ class AlbumThumbnailCard extends StatelessWidget { | ||||
|     var isDarkMode = Theme.of(context).brightness == Brightness.dark; | ||||
|     return LayoutBuilder( | ||||
|       builder: (context, constraints) { | ||||
|       var cardSize = constraints.maxWidth; | ||||
|         var cardSize = constraints.maxWidth; | ||||
|  | ||||
|       buildEmptyThumbnail() { | ||||
|         return Container( | ||||
|           height: cardSize, | ||||
|           width: cardSize, | ||||
|           decoration: BoxDecoration( | ||||
|             color: isDarkMode ? Colors.grey[800] : Colors.grey[200], | ||||
|           ), | ||||
|           child: Center( | ||||
|             child: Icon( | ||||
|               Icons.no_photography, | ||||
|               size: cardSize * .15, | ||||
|         buildEmptyThumbnail() { | ||||
|           return Container( | ||||
|             height: cardSize, | ||||
|             width: cardSize, | ||||
|             decoration: BoxDecoration( | ||||
|               color: isDarkMode ? Colors.grey[800] : Colors.grey[200], | ||||
|             ), | ||||
|           ), | ||||
|         ); | ||||
|       } | ||||
|             child: Center( | ||||
|               child: Icon( | ||||
|                 Icons.no_photography, | ||||
|                 size: cardSize * .15, | ||||
|               ), | ||||
|             ), | ||||
|           ); | ||||
|         } | ||||
|  | ||||
|       buildAlbumThumbnail() { | ||||
|         return CachedNetworkImage( | ||||
|           width: cardSize, | ||||
|           height: cardSize, | ||||
|           fit: BoxFit.cover, | ||||
|           fadeInDuration: const Duration(milliseconds: 200), | ||||
|           imageUrl: getAlbumThumbnailUrl( | ||||
|             album, | ||||
|             type: ThumbnailFormat.JPEG, | ||||
|           ), | ||||
|           httpHeaders: {"Authorization": "Bearer ${box.get(accessTokenKey)}"}, | ||||
|           cacheKey: getAlbumThumbNailCacheKey(album, type: ThumbnailFormat.JPEG), | ||||
|         ); | ||||
|       } | ||||
|         buildAlbumThumbnail() { | ||||
|           return CachedNetworkImage( | ||||
|             width: cardSize, | ||||
|             height: cardSize, | ||||
|             fit: BoxFit.cover, | ||||
|             fadeInDuration: const Duration(milliseconds: 200), | ||||
|             imageUrl: getAlbumThumbnailUrl( | ||||
|               album, | ||||
|               type: ThumbnailFormat.JPEG, | ||||
|             ), | ||||
|             httpHeaders: {"Authorization": "Bearer ${box.get(accessTokenKey)}"}, | ||||
|             cacheKey: | ||||
|                 getAlbumThumbNailCacheKey(album, type: ThumbnailFormat.JPEG), | ||||
|           ); | ||||
|         } | ||||
|  | ||||
|       return GestureDetector( | ||||
|         onTap: onTap, | ||||
|         child: Padding( | ||||
|           padding: const EdgeInsets.only(bottom: 32.0), | ||||
|           child: Column( | ||||
|             crossAxisAlignment: CrossAxisAlignment.start, | ||||
|         return GestureDetector( | ||||
|           onTap: onTap, | ||||
|           child: Flex( | ||||
|             direction: Axis.vertical, | ||||
|             children: [ | ||||
|               Expanded( | ||||
|                 child: ClipRRect( | ||||
|                   borderRadius: BorderRadius.circular(8), | ||||
|                   child: album.albumThumbnailAssetId == null | ||||
|                     ? buildEmptyThumbnail() | ||||
|                     : buildAlbumThumbnail(), | ||||
|                 ), | ||||
|               ), | ||||
|               Padding( | ||||
|                 padding: const EdgeInsets.only(top: 8.0), | ||||
|                 child: SizedBox( | ||||
|                   width: cardSize, | ||||
|                   child: Text( | ||||
|                     album.name, | ||||
|                     style: const TextStyle( | ||||
|                       fontWeight: FontWeight.bold, | ||||
|                     ), | ||||
|                   ), | ||||
|                 ), | ||||
|               ), | ||||
|               Row( | ||||
|                 mainAxisSize: MainAxisSize.min, | ||||
|                 children: [ | ||||
|                   Text( | ||||
|                     album.assetCount == 1 | ||||
|                         ? 'album_thumbnail_card_item' | ||||
|                         : 'album_thumbnail_card_items', | ||||
|                     style: const TextStyle( | ||||
|                       fontSize: 12, | ||||
|                     ), | ||||
|                   ).tr(args: ['${album.assetCount}']), | ||||
|                   if (album.shared) | ||||
|                     const Text( | ||||
|                       'album_thumbnail_card_shared', | ||||
|                       style: TextStyle( | ||||
|                         fontSize: 12, | ||||
|               Flexible( | ||||
|                 child: Column( | ||||
|                   crossAxisAlignment: CrossAxisAlignment.start, | ||||
|                   children: [ | ||||
|                     SizedBox( | ||||
|                       width: cardSize, | ||||
|                       height: cardSize, | ||||
|                       child: ClipRRect( | ||||
|                         borderRadius: BorderRadius.circular(20), | ||||
|                         child: album.albumThumbnailAssetId == null | ||||
|                             ? buildEmptyThumbnail() | ||||
|                             : buildAlbumThumbnail(), | ||||
|                       ), | ||||
|                     ).tr() | ||||
|                 ], | ||||
|               ) | ||||
|                     ), | ||||
|                     Padding( | ||||
|                       padding: const EdgeInsets.only(top: 8.0), | ||||
|                       child: SizedBox( | ||||
|                         width: cardSize, | ||||
|                         child: Text( | ||||
|                           album.name, | ||||
|                           style: const TextStyle( | ||||
|                             fontWeight: FontWeight.bold, | ||||
|                           ), | ||||
|                         ), | ||||
|                       ), | ||||
|                     ), | ||||
|                     Row( | ||||
|                       mainAxisSize: MainAxisSize.min, | ||||
|                       children: [ | ||||
|                         Text( | ||||
|                           album.assetCount == 1 | ||||
|                               ? 'album_thumbnail_card_item' | ||||
|                               : 'album_thumbnail_card_items', | ||||
|                           style: const TextStyle( | ||||
|                             fontSize: 12, | ||||
|                           ), | ||||
|                         ).tr(args: ['${album.assetCount}']), | ||||
|                         if (album.shared) | ||||
|                           const Text( | ||||
|                             'album_thumbnail_card_shared', | ||||
|                             style: TextStyle( | ||||
|                               fontSize: 12, | ||||
|                             ), | ||||
|                           ).tr() | ||||
|                       ], | ||||
|                     ) | ||||
|                   ], | ||||
|                 ), | ||||
|               ), | ||||
|             ], | ||||
|           ), | ||||
|         ), | ||||
|       ); | ||||
|         ); | ||||
|       }, | ||||
|     ); | ||||
|   } | ||||
|   | ||||
| @@ -34,7 +34,7 @@ class AlbumTitleTextField extends ConsumerWidget { | ||||
|       focusNode: albumTitleTextFieldFocusNode, | ||||
|       style: TextStyle( | ||||
|         fontSize: 28, | ||||
|         color: Colors.grey[700], | ||||
|         color: isDarkTheme ? Colors.grey[300] : Colors.grey[700], | ||||
|         fontWeight: FontWeight.bold, | ||||
|       ), | ||||
|       controller: albumTitleController, | ||||
|   | ||||
| @@ -19,7 +19,7 @@ class CreateAlbumPage extends HookConsumerWidget { | ||||
|   final List<Asset>? initialAssets; | ||||
|  | ||||
|   const CreateAlbumPage({ | ||||
|     Key? key,  | ||||
|     Key? key, | ||||
|     required this.isSharedAlbum, | ||||
|     this.initialAssets, | ||||
|   }) : super(key: key); | ||||
| @@ -84,7 +84,7 @@ class CreateAlbumPage extends HookConsumerWidget { | ||||
|             padding: const EdgeInsets.only(top: 200, left: 18), | ||||
|             child: Text( | ||||
|               'create_shared_album_page_share_add_assets', | ||||
|               style: Theme.of(context).textTheme.headline2?.copyWith( | ||||
|               style: Theme.of(context).textTheme.displayMedium?.copyWith( | ||||
|                     fontSize: 12, | ||||
|                     fontWeight: FontWeight.normal, | ||||
|                   ), | ||||
| @@ -214,7 +214,7 @@ class CreateAlbumPage extends HookConsumerWidget { | ||||
|         ), | ||||
|         title: Text( | ||||
|           'share_create_album', | ||||
|           style: Theme.of(context).textTheme.headline2?.copyWith( | ||||
|           style: Theme.of(context).textTheme.displayMedium?.copyWith( | ||||
|                 color: Theme.of(context).primaryColor, | ||||
|               ), | ||||
|         ).tr(), | ||||
| @@ -228,7 +228,9 @@ class CreateAlbumPage extends HookConsumerWidget { | ||||
|                 'create_shared_album_page_share'.tr(), | ||||
|                 style: TextStyle( | ||||
|                   fontWeight: FontWeight.bold, | ||||
|                   color: Theme.of(context).primaryColor, | ||||
|                   color: albumTitleController.text.isEmpty | ||||
|                       ? Theme.of(context).disabledColor | ||||
|                       : Theme.of(context).primaryColor, | ||||
|                 ), | ||||
|               ), | ||||
|             ), | ||||
|   | ||||
| @@ -15,6 +15,7 @@ class LibraryPage extends HookConsumerWidget { | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     final albums = ref.watch(albumProvider); | ||||
|     var isDarkMode = Theme.of(context).brightness == Brightness.dark; | ||||
|  | ||||
|     useEffect( | ||||
|       () { | ||||
| @@ -122,9 +123,12 @@ class LibraryPage extends HookConsumerWidget { | ||||
|                 child: Container( | ||||
|                   decoration: BoxDecoration( | ||||
|                     border: Border.all( | ||||
|                       color: Colors.grey, | ||||
|                       color: isDarkMode | ||||
|                           ? const Color.fromARGB(255, 53, 53, 53) | ||||
|                           : const Color.fromARGB(255, 203, 203, 203), | ||||
|                     ), | ||||
|                     borderRadius: BorderRadius.circular(8), | ||||
|                     color: isDarkMode ? Colors.grey[900] : Colors.grey[50], | ||||
|                     borderRadius: BorderRadius.circular(20), | ||||
|                   ), | ||||
|                   child: Center( | ||||
|                     child: Icon( | ||||
| @@ -168,25 +172,22 @@ class LibraryPage extends HookConsumerWidget { | ||||
|               style: TextStyle( | ||||
|                 fontWeight: FontWeight.bold, | ||||
|                 fontSize: 12.0, | ||||
|                 color: Theme.of(context).brightness == Brightness.dark | ||||
|                     ? Colors.white | ||||
|                     : Colors.black, | ||||
|                 color: isDarkMode ? Colors.white : Colors.black, | ||||
|               ), | ||||
|             ), | ||||
|           ), | ||||
|           style: OutlinedButton.styleFrom( | ||||
|             padding: const EdgeInsets.all(12), | ||||
|             backgroundColor: isDarkMode ? Colors.grey[900] : Colors.grey[50], | ||||
|             side: BorderSide( | ||||
|               color: Theme.of(context).brightness == Brightness.dark | ||||
|                   ? Colors.grey[600]! | ||||
|                   : Colors.grey[300]!, | ||||
|               color: isDarkMode ? Colors.grey[800]! : Colors.grey[300]!, | ||||
|             ), | ||||
|             alignment: Alignment.centerLeft, | ||||
|             shape: RoundedRectangleBorder( | ||||
|               borderRadius: BorderRadius.circular(6.0), | ||||
|             ), | ||||
|           ), | ||||
|           icon: Icon(icon, color: Theme.of(context).primaryColor), | ||||
|           icon: Icon( | ||||
|             icon, | ||||
|             color: Theme.of(context).primaryColor, | ||||
|           ), | ||||
|         ), | ||||
|       ); | ||||
|     } | ||||
| @@ -253,7 +254,7 @@ class LibraryPage extends HookConsumerWidget { | ||||
|               delegate: SliverChildBuilderDelegate( | ||||
|                 childCount: sorted.length + 1, | ||||
|                 (context, index) { | ||||
|                   if (index  == 0) { | ||||
|                   if (index == 0) { | ||||
|                     return buildCreateAlbumButton(); | ||||
|                   } | ||||
|  | ||||
|   | ||||
| @@ -77,13 +77,13 @@ class SharingPage extends HookConsumerWidget { | ||||
|           child: Card( | ||||
|             elevation: 0, | ||||
|             shape: RoundedRectangleBorder( | ||||
|               borderRadius: BorderRadius.circular(10), // if you need this | ||||
|               borderRadius: BorderRadius.circular(20), | ||||
|               side: const BorderSide( | ||||
|                 color: Colors.grey, | ||||
|                 width: 1, | ||||
|                 width: 0.5, | ||||
|               ), | ||||
|             ), | ||||
|             color: Colors.transparent, | ||||
|             // color: Colors.transparent, | ||||
|             child: Padding( | ||||
|               padding: const EdgeInsets.all(18.0), | ||||
|               child: Column( | ||||
| @@ -92,7 +92,7 @@ class SharingPage extends HookConsumerWidget { | ||||
|                   Padding( | ||||
|                     padding: const EdgeInsets.only(left: 5.0, bottom: 5), | ||||
|                     child: Icon( | ||||
|                       Icons.offline_share_outlined, | ||||
|                       Icons.insert_photo_rounded, | ||||
|                       size: 50, | ||||
|                       color: Theme.of(context).primaryColor, | ||||
|                     ), | ||||
| @@ -101,7 +101,7 @@ class SharingPage extends HookConsumerWidget { | ||||
|                     padding: const EdgeInsets.all(8.0), | ||||
|                     child: Text( | ||||
|                       'sharing_page_empty_list', | ||||
|                       style: Theme.of(context).textTheme.headline3, | ||||
|                       style: Theme.of(context).textTheme.displaySmall, | ||||
|                     ).tr(), | ||||
|                   ), | ||||
|                   Padding( | ||||
|   | ||||
| @@ -15,7 +15,7 @@ import 'package:immich_mobile/modules/asset_viewer/ui/top_control_app_bar.dart'; | ||||
| import 'package:immich_mobile/modules/asset_viewer/views/video_viewer_page.dart'; | ||||
| import 'package:immich_mobile/modules/favorite/providers/favorite_provider.dart'; | ||||
| import 'package:immich_mobile/shared/services/asset.service.dart'; | ||||
| import 'package:immich_mobile/modules/home/ui/delete_diaglog.dart'; | ||||
| import 'package:immich_mobile/modules/home/ui/delete_dialog.dart'; | ||||
| import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart'; | ||||
| import 'package:immich_mobile/modules/settings/services/app_settings.service.dart'; | ||||
| import 'package:immich_mobile/shared/ui/photo_view/photo_view_gallery.dart'; | ||||
| @@ -213,7 +213,7 @@ class GalleryViewerPage extends HookConsumerWidget { | ||||
|  | ||||
|     void handleSwipeUpDown(DragUpdateDetails details) { | ||||
|       int sensitivity = 15; | ||||
|       int dxThreshhold = 50; | ||||
|       int dxThreshold = 50; | ||||
|  | ||||
|       if (isZoomed.value) { | ||||
|         return; | ||||
| @@ -222,7 +222,7 @@ class GalleryViewerPage extends HookConsumerWidget { | ||||
|       // Check for delta from initial down point | ||||
|       final d = details.localPosition - localPosition; | ||||
|       // If the magnitude of the dx swipe is large, we probably didn't mean to go down | ||||
|       if (d.dx.abs() > dxThreshhold) { | ||||
|       if (d.dx.abs() > dxThreshold) { | ||||
|         return; | ||||
|       } | ||||
|  | ||||
| @@ -247,8 +247,8 @@ class GalleryViewerPage extends HookConsumerWidget { | ||||
|             isPlayingMotionVideo: isPlayingMotionVideo.value, | ||||
|             asset: assetList[indexOfAsset.value], | ||||
|             isFavorite: ref.watch(favoriteProvider).contains( | ||||
|               assetList[indexOfAsset.value].id, | ||||
|             ), | ||||
|                   assetList[indexOfAsset.value].id, | ||||
|                 ), | ||||
|             onMoreInfoPressed: () { | ||||
|               showInfo(); | ||||
|             }, | ||||
| @@ -314,7 +314,7 @@ class GalleryViewerPage extends HookConsumerWidget { | ||||
|                 ? (context, event) { | ||||
|                     final asset = assetList[indexOfAsset.value]; | ||||
|                     if (!asset.isLocal) { | ||||
|                       // Use the WEBP Thumbnail as a placeholder for the JPEG thumbnail to acheive | ||||
|                       // Use the WEBP Thumbnail as a placeholder for the JPEG thumbnail to achieve | ||||
|                       // Three-Stage Loading (WEBP -> JPEG -> Original) | ||||
|                       final webPThumbnail = CachedNetworkImage( | ||||
|                         imageUrl: getThumbnailUrl( | ||||
|   | ||||
| @@ -81,10 +81,6 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { | ||||
|           child: GestureDetector( | ||||
|             onTap: removeSelection, | ||||
|             child: Chip( | ||||
|               visualDensity: VisualDensity.compact, | ||||
|               shape: RoundedRectangleBorder( | ||||
|                 borderRadius: BorderRadius.circular(10), | ||||
|               ), | ||||
|               label: Text( | ||||
|                 album.name, | ||||
|                 style: TextStyle( | ||||
| @@ -119,10 +115,6 @@ class BackupAlbumSelectionPage extends HookConsumerWidget { | ||||
|           child: Padding( | ||||
|             padding: const EdgeInsets.only(right: 8.0), | ||||
|             child: Chip( | ||||
|               visualDensity: VisualDensity.compact, | ||||
|               shape: RoundedRectangleBorder( | ||||
|                 borderRadius: BorderRadius.circular(10), | ||||
|               ), | ||||
|               label: Text( | ||||
|                 album.name, | ||||
|                 style: TextStyle( | ||||
|   | ||||
| @@ -92,11 +92,10 @@ class ImmichAssetGridState extends State<ImmichAssetGrid> { | ||||
|     RenderAssetGridRow row, | ||||
|     bool scrolling, | ||||
|   ) { | ||||
|  | ||||
|     return LayoutBuilder( | ||||
|       builder: (context, constraints) { | ||||
|         final size = constraints.maxWidth / widget.assetsPerRow - | ||||
|           widget.margin * (widget.assetsPerRow - 1) / widget.assetsPerRow; | ||||
|             widget.margin * (widget.assetsPerRow - 1) / widget.assetsPerRow; | ||||
|         return Row( | ||||
|           key: Key("asset-row-${row.assets.first.id}"), | ||||
|           children: row.assets.mapIndexed((int index, Asset asset) { | ||||
| @@ -141,7 +140,7 @@ class ImmichAssetGridState extends State<ImmichAssetGrid> { | ||||
|         style: TextStyle( | ||||
|           fontSize: 26, | ||||
|           fontWeight: FontWeight.bold, | ||||
|           color: Theme.of(context).textTheme.headline1?.color, | ||||
|           color: Theme.of(context).textTheme.displayLarge?.color, | ||||
|         ), | ||||
|       ), | ||||
|     ); | ||||
|   | ||||
| @@ -22,7 +22,7 @@ class MonthlyTitleText extends StatelessWidget { | ||||
|           style: TextStyle( | ||||
|             fontSize: 26, | ||||
|             fontWeight: FontWeight.bold, | ||||
|             color: Theme.of(context).textTheme.headline1?.color, | ||||
|             color: Theme.of(context).textTheme.displayLarge?.color, | ||||
|           ), | ||||
|         ), | ||||
|       ), | ||||
|   | ||||
| @@ -2,7 +2,7 @@ import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:immich_mobile/modules/album/ui/add_to_album_sliverlist.dart'; | ||||
| import 'package:immich_mobile/modules/home/ui/delete_diaglog.dart'; | ||||
| import 'package:immich_mobile/modules/home/ui/delete_dialog.dart'; | ||||
| import 'package:immich_mobile/shared/ui/drag_sheet.dart'; | ||||
| import 'package:immich_mobile/shared/models/album.dart'; | ||||
|  | ||||
| @@ -29,6 +29,8 @@ class ControlBottomAppBar extends ConsumerWidget { | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     var isDarkMode = Theme.of(context).brightness == Brightness.dark; | ||||
|  | ||||
|     Widget renderActionButtons() { | ||||
|       return Row( | ||||
|         children: [ | ||||
| @@ -60,7 +62,6 @@ class ControlBottomAppBar extends ConsumerWidget { | ||||
|               ); | ||||
|             }, | ||||
|           ), | ||||
|  | ||||
|         ], | ||||
|       ); | ||||
|     } | ||||
| @@ -75,7 +76,9 @@ class ControlBottomAppBar extends ConsumerWidget { | ||||
|         ScrollController scrollController, | ||||
|       ) { | ||||
|         return Card( | ||||
|           elevation: 12.0, | ||||
|           color: isDarkMode ? Colors.grey[900] : Colors.grey[100], | ||||
|           surfaceTintColor: Colors.transparent, | ||||
|           elevation: 18.0, | ||||
|           shape: const RoundedRectangleBorder( | ||||
|             borderRadius: BorderRadius.only( | ||||
|               topLeft: Radius.circular(12), | ||||
| @@ -83,45 +86,37 @@ class ControlBottomAppBar extends ConsumerWidget { | ||||
|             ), | ||||
|           ), | ||||
|           margin: const EdgeInsets.all(0), | ||||
|           child: Container( | ||||
|             decoration: const BoxDecoration( | ||||
|               borderRadius: BorderRadius.only( | ||||
|                 topLeft: Radius.circular(12), | ||||
|                 topRight: Radius.circular(12), | ||||
|           child: CustomScrollView( | ||||
|             controller: scrollController, | ||||
|             slivers: [ | ||||
|               SliverToBoxAdapter( | ||||
|                 child: Column( | ||||
|                   children: <Widget>[ | ||||
|                     const SizedBox(height: 12), | ||||
|                     const CustomDraggingHandle(), | ||||
|                     const SizedBox(height: 12), | ||||
|                     renderActionButtons(), | ||||
|                     const Divider( | ||||
|                       indent: 16, | ||||
|                       endIndent: 16, | ||||
|                       thickness: 1, | ||||
|                     ), | ||||
|                     AddToAlbumTitleRow(onCreateNewAlbum: onCreateNewAlbum), | ||||
|                   ], | ||||
|                 ), | ||||
|               ), | ||||
|             ), | ||||
|             child: CustomScrollView( | ||||
|               controller: scrollController, | ||||
|               slivers: [ | ||||
|                 SliverToBoxAdapter( | ||||
|                   child: Column( | ||||
|                     children: <Widget>[ | ||||
|                       const SizedBox(height: 12), | ||||
|                       const CustomDraggingHandle(), | ||||
|                       const SizedBox(height: 12), | ||||
|                       renderActionButtons(), | ||||
|                       const Divider( | ||||
|                         indent: 16, | ||||
|                         endIndent: 16, | ||||
|                         thickness: 1, | ||||
|                       ), | ||||
|                       AddToAlbumTitleRow(onCreateNewAlbum: onCreateNewAlbum), | ||||
|                     ], | ||||
|                   ), | ||||
|               SliverPadding( | ||||
|                 padding: const EdgeInsets.symmetric(horizontal: 16), | ||||
|                 sliver: AddToAlbumSliverList( | ||||
|                   albums: albums, | ||||
|                   sharedAlbums: sharedAlbums, | ||||
|                   onAddToAlbum: onAddToAlbum, | ||||
|                 ), | ||||
|                 SliverPadding( | ||||
|                   padding: const EdgeInsets.symmetric(horizontal: 16), | ||||
|                   sliver: AddToAlbumSliverList( | ||||
|                     albums: albums, | ||||
|                     sharedAlbums: sharedAlbums, | ||||
|                     onAddToAlbum: onAddToAlbum, | ||||
|                   ), | ||||
|                 ), | ||||
|                 const SliverToBoxAdapter( | ||||
|                   child: SizedBox(height: 200), | ||||
|                 ) | ||||
|               ], | ||||
|             ), | ||||
|               ), | ||||
|               const SliverToBoxAdapter( | ||||
|                 child: SizedBox(height: 200), | ||||
|               ) | ||||
|             ], | ||||
|           ), | ||||
|         ); | ||||
|       }, | ||||
|   | ||||
| @@ -1,5 +1,4 @@ | ||||
| import 'package:auto_route/auto_route.dart'; | ||||
| import 'package:badges/badges.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
| import 'package:immich_mobile/modules/login/providers/authentication.provider.dart'; | ||||
| @@ -29,7 +28,6 @@ class HomePageAppBar extends ConsumerWidget with PreferredSizeWidget { | ||||
|     final ServerInfoState serverInfoState = ref.watch(serverInfoProvider); | ||||
|  | ||||
|     return AppBar( | ||||
|       centerTitle: true, | ||||
|       backgroundColor: Theme.of(context).appBarTheme.backgroundColor, | ||||
|       shape: const RoundedRectangleBorder( | ||||
|         borderRadius: BorderRadius.all( | ||||
| @@ -44,10 +42,9 @@ class HomePageAppBar extends ConsumerWidget with PreferredSizeWidget { | ||||
|                 top: 5, | ||||
|                 child: IconButton( | ||||
|                   splashRadius: 25, | ||||
|                   icon: Icon( | ||||
|                   icon: const Icon( | ||||
|                     Icons.face_outlined, | ||||
|                     size: 30, | ||||
|                     color: Theme.of(context).primaryColor, | ||||
|                   ), | ||||
|                   onPressed: () { | ||||
|                     Scaffold.of(context).openDrawer(); | ||||
| @@ -112,16 +109,13 @@ class HomePageAppBar extends ConsumerWidget with PreferredSizeWidget { | ||||
|               splashRadius: 25, | ||||
|               iconSize: 30, | ||||
|               icon: isEnableAutoBackup | ||||
|                   ? Icon( | ||||
|                   ? const Icon( | ||||
|                       Icons.backup_rounded, | ||||
|                       color: Theme.of(context).primaryColor, | ||||
|                     ) | ||||
|                   : Badge( | ||||
|                       padding: const EdgeInsets.all(4), | ||||
|                       elevation: 3, | ||||
|                       position: BadgePosition.bottomEnd(bottom: -4, end: -4), | ||||
|                       badgeColor: Colors.white, | ||||
|                       badgeContent: const Icon( | ||||
|                       backgroundColor: Colors.white, | ||||
|                       label: const Icon( | ||||
|                         Icons.cloud_off_rounded, | ||||
|                         size: 8, | ||||
|                         color: Colors.indigo, | ||||
|   | ||||
| @@ -15,7 +15,7 @@ class ProfileDrawer extends HookConsumerWidget { | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|     buildSignoutButton() { | ||||
|     buildSignOutButton() { | ||||
|       return ListTile( | ||||
|         horizontalTitleGap: 0, | ||||
|         leading: SizedBox( | ||||
| @@ -95,6 +95,9 @@ class ProfileDrawer extends HookConsumerWidget { | ||||
|     } | ||||
|  | ||||
|     return Drawer( | ||||
|       shape: const RoundedRectangleBorder( | ||||
|         borderRadius: BorderRadius.zero, | ||||
|       ), | ||||
|       child: Column( | ||||
|         mainAxisAlignment: MainAxisAlignment.spaceBetween, | ||||
|         children: [ | ||||
| @@ -105,7 +108,7 @@ class ProfileDrawer extends HookConsumerWidget { | ||||
|               const ProfileDrawerHeader(), | ||||
|               buildSettingButton(), | ||||
|               buildAppLogButton(), | ||||
|               buildSignoutButton(), | ||||
|               buildSignOutButton(), | ||||
|             ], | ||||
|           ), | ||||
|           const ServerInfoBox() | ||||
|   | ||||
| @@ -22,7 +22,7 @@ class ProfileDrawerHeader extends HookConsumerWidget { | ||||
|     AuthenticationState authState = ref.watch(authenticationProvider); | ||||
|     final uploadProfileImageStatus = | ||||
|         ref.watch(uploadProfileImageProvider).status; | ||||
|     var dummmy = Random().nextInt(1024); | ||||
|     var dummy = Random().nextInt(1024); | ||||
|     final isDarkMode = Theme.of(context).brightness == Brightness.dark; | ||||
|  | ||||
|     buildUserProfileImage() { | ||||
| @@ -39,7 +39,7 @@ class ProfileDrawerHeader extends HookConsumerWidget { | ||||
|           return CircleAvatar( | ||||
|             radius: 35, | ||||
|             backgroundImage: NetworkImage( | ||||
|               '$endpoint/user/profile-image/${authState.userId}?d=${dummmy++}', | ||||
|               '$endpoint/user/profile-image/${authState.userId}?d=${dummy++}', | ||||
|             ), | ||||
|             backgroundColor: Colors.transparent, | ||||
|           ); | ||||
| @@ -56,7 +56,7 @@ class ProfileDrawerHeader extends HookConsumerWidget { | ||||
|         return CircleAvatar( | ||||
|           radius: 35, | ||||
|           backgroundImage: NetworkImage( | ||||
|             '$endpoint/user/profile-image/${authState.userId}?d=${dummmy++}', | ||||
|             '$endpoint/user/profile-image/${authState.userId}?d=${dummy++}', | ||||
|           ), | ||||
|           backgroundColor: Colors.transparent, | ||||
|         ); | ||||
|   | ||||
| @@ -53,6 +53,9 @@ class SearchBar extends HookConsumerWidget with PreferredSizeWidget { | ||||
|         }, | ||||
|         decoration: InputDecoration( | ||||
|           hintText: 'search_bar_hint'.tr(), | ||||
|           hintStyle: Theme.of(context).textTheme.titleSmall?.copyWith( | ||||
|                 color: Theme.of(context).colorScheme.onSurface.withOpacity(0.5), | ||||
|               ), | ||||
|           enabledBorder: const UnderlineInputBorder( | ||||
|             borderSide: BorderSide(color: Colors.transparent), | ||||
|           ), | ||||
|   | ||||
| @@ -11,7 +11,6 @@ class TabControllerPage extends ConsumerWidget { | ||||
|  | ||||
|   @override | ||||
|   Widget build(BuildContext context, WidgetRef ref) { | ||||
|  | ||||
|     navigationRail(TabsRouter tabsRouter) { | ||||
|       return NavigationRail( | ||||
|         labelType: NavigationRailLabelType.all, | ||||
| @@ -35,32 +34,33 @@ class TabControllerPage extends ConsumerWidget { | ||||
|               right: 4, | ||||
|               bottom: 4, | ||||
|             ), | ||||
|             icon: const Icon(Icons.photo_outlined),  | ||||
|             icon: const Icon(Icons.photo_outlined), | ||||
|             selectedIcon: const Icon(Icons.photo), | ||||
|             label: const Text('tab_controller_nav_photos').tr(), | ||||
|           ), | ||||
|           NavigationRailDestination( | ||||
|             padding: const EdgeInsets.all(4), | ||||
|             icon: const Icon(Icons.search_rounded),  | ||||
|             selectedIcon: const Icon(Icons.search),  | ||||
|             icon: const Icon(Icons.search_rounded), | ||||
|             selectedIcon: const Icon(Icons.search), | ||||
|             label: const Text('tab_controller_nav_search').tr(), | ||||
|           ), | ||||
|           NavigationRailDestination( | ||||
|             padding: const EdgeInsets.all(4), | ||||
|             icon: const Icon(Icons.share_rounded),  | ||||
|             selectedIcon: const Icon(Icons.share),  | ||||
|             icon: const Icon(Icons.share_rounded), | ||||
|             selectedIcon: const Icon(Icons.share), | ||||
|             label: const Text('tab_controller_nav_sharing').tr(), | ||||
|           ), | ||||
|           NavigationRailDestination( | ||||
|             padding: const EdgeInsets.all(4), | ||||
|             icon: const Icon(Icons.photo_album_outlined),  | ||||
|             selectedIcon: const Icon(Icons.photo_album),  | ||||
|             icon: const Icon(Icons.photo_album_outlined), | ||||
|             selectedIcon: const Icon(Icons.photo_album), | ||||
|             label: const Text('tab_controller_nav_library').tr(), | ||||
|           ), | ||||
|         ], | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     // ignore: unused_element | ||||
|     bottomNavigationBar(TabsRouter tabsRouter) { | ||||
|       return BottomNavigationBar( | ||||
|         selectedLabelStyle: const TextStyle( | ||||
| @@ -101,6 +101,58 @@ class TabControllerPage extends ConsumerWidget { | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     experimentalNavigationBar(TabsRouter tabsRouter) { | ||||
|       return NavigationBar( | ||||
|         selectedIndex: tabsRouter.activeIndex, | ||||
|         onDestinationSelected: (index) { | ||||
|           HapticFeedback.selectionClick(); | ||||
|           tabsRouter.setActiveIndex(index); | ||||
|         }, | ||||
|         destinations: [ | ||||
|           NavigationDestination( | ||||
|             label: 'tab_controller_nav_photos'.tr(), | ||||
|             icon: const Icon( | ||||
|               Icons.photo_outlined, | ||||
|             ), | ||||
|             selectedIcon: Icon( | ||||
|               Icons.photo, | ||||
|               color: Theme.of(context).primaryColor, | ||||
|             ), | ||||
|           ), | ||||
|           NavigationDestination( | ||||
|             label: 'tab_controller_nav_search'.tr(), | ||||
|             icon: const Icon( | ||||
|               Icons.search_rounded, | ||||
|             ), | ||||
|             selectedIcon: Icon( | ||||
|               Icons.search, | ||||
|               color: Theme.of(context).primaryColor, | ||||
|             ), | ||||
|           ), | ||||
|           NavigationDestination( | ||||
|             label: 'tab_controller_nav_sharing'.tr(), | ||||
|             icon: const Icon( | ||||
|               Icons.group_outlined, | ||||
|             ), | ||||
|             selectedIcon: Icon( | ||||
|               Icons.group, | ||||
|               color: Theme.of(context).primaryColor, | ||||
|             ), | ||||
|           ), | ||||
|           NavigationDestination( | ||||
|             label: 'tab_controller_nav_library'.tr(), | ||||
|             icon: const Icon( | ||||
|               Icons.photo_album_outlined, | ||||
|             ), | ||||
|             selectedIcon: Icon( | ||||
|               Icons.photo_album_rounded, | ||||
|               color: Theme.of(context).primaryColor, | ||||
|             ), | ||||
|           ) | ||||
|         ], | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     final multiselectEnabled = ref.watch(multiselectProvider); | ||||
|     return AutoTabsRouter( | ||||
|       routes: [ | ||||
| @@ -116,7 +168,7 @@ class TabControllerPage extends ConsumerWidget { | ||||
|             bool atHomeTab = tabsRouter.activeIndex == 0; | ||||
|             if (!atHomeTab) { | ||||
|               tabsRouter.setActiveIndex(0); | ||||
|             }  | ||||
|             } | ||||
|  | ||||
|             return atHomeTab; | ||||
|           }, | ||||
| @@ -127,7 +179,7 @@ class TabControllerPage extends ConsumerWidget { | ||||
|               final Widget body; | ||||
|               if (constraints.maxWidth < medium) { | ||||
|                 // Normal phone width | ||||
|                 bottom = bottomNavigationBar(tabsRouter); | ||||
|                 bottom = experimentalNavigationBar(tabsRouter); | ||||
|                 body = FadeTransition( | ||||
|                   opacity: animation, | ||||
|                   child: child, | ||||
| @@ -146,13 +198,13 @@ class TabControllerPage extends ConsumerWidget { | ||||
|                     ), | ||||
|                   ], | ||||
|                 ); | ||||
|               }              return Scaffold( | ||||
|                body: body, | ||||
|                bottomNavigationBar: multiselectEnabled | ||||
|                   ? null | ||||
|                   : bottom, | ||||
|             ); | ||||
|           },), | ||||
|               } | ||||
|               return Scaffold( | ||||
|                 body: body, | ||||
|                 bottomNavigationBar: multiselectEnabled ? null : bottom, | ||||
|               ); | ||||
|             }, | ||||
|           ), | ||||
|         ); | ||||
|       }, | ||||
|     ); | ||||
|   | ||||
| @@ -20,6 +20,83 @@ final immichThemeProvider = StateProvider<ThemeMode>((ref) { | ||||
|   } | ||||
| }); | ||||
|  | ||||
| ThemeData base = ThemeData( | ||||
|   chipTheme: const ChipThemeData( | ||||
|     side: BorderSide.none, | ||||
|   ), | ||||
| ); | ||||
|  | ||||
| ThemeData immichLightTheme = ThemeData( | ||||
|   useMaterial3: true, | ||||
|   brightness: Brightness.light, | ||||
|   primarySwatch: Colors.indigo, | ||||
|   primaryColor: Colors.indigo, | ||||
|   hintColor: Colors.indigo, | ||||
|   fontFamily: 'WorkSans', | ||||
|   scaffoldBackgroundColor: immichBackgroundColor, | ||||
|   snackBarTheme: const SnackBarThemeData( | ||||
|     contentTextStyle: TextStyle(fontFamily: 'WorkSans'), | ||||
|   ), | ||||
|   appBarTheme: AppBarTheme( | ||||
|     titleTextStyle: const TextStyle( | ||||
|       fontFamily: 'WorkSans', | ||||
|       color: Colors.indigo, | ||||
|     ), | ||||
|     backgroundColor: immichBackgroundColor, | ||||
|     foregroundColor: Colors.indigo, | ||||
|     elevation: 0, | ||||
|     scrolledUnderElevation: 0, | ||||
|     centerTitle: true, | ||||
|   ), | ||||
|   bottomNavigationBarTheme: BottomNavigationBarThemeData( | ||||
|     type: BottomNavigationBarType.fixed, | ||||
|     backgroundColor: immichBackgroundColor, | ||||
|     selectedItemColor: Colors.indigo, | ||||
|   ), | ||||
|   cardTheme: const CardTheme( | ||||
|     surfaceTintColor: Colors.transparent, | ||||
|   ), | ||||
|   drawerTheme: DrawerThemeData( | ||||
|     backgroundColor: immichBackgroundColor, | ||||
|   ), | ||||
|   textTheme: const TextTheme( | ||||
|     displayLarge: TextStyle( | ||||
|       fontSize: 26, | ||||
|       fontWeight: FontWeight.bold, | ||||
|       color: Colors.indigo, | ||||
|     ), | ||||
|     displayMedium: TextStyle( | ||||
|       fontSize: 14, | ||||
|       fontWeight: FontWeight.bold, | ||||
|       color: Colors.black87, | ||||
|     ), | ||||
|     displaySmall: TextStyle( | ||||
|       fontSize: 12, | ||||
|       fontWeight: FontWeight.bold, | ||||
|       color: Colors.indigo, | ||||
|     ), | ||||
|   ), | ||||
|   elevatedButtonTheme: ElevatedButtonThemeData( | ||||
|     style: ElevatedButton.styleFrom( | ||||
|       backgroundColor: Colors.indigo, | ||||
|       foregroundColor: Colors.white, | ||||
|     ), | ||||
|   ), | ||||
|   chipTheme: base.chipTheme, | ||||
|   popupMenuTheme: const PopupMenuThemeData( | ||||
|     shape: RoundedRectangleBorder( | ||||
|       borderRadius: BorderRadius.all(Radius.circular(10)), | ||||
|     ), | ||||
|     surfaceTintColor: Colors.transparent, | ||||
|     color: Colors.white, | ||||
|   ), | ||||
|   navigationBarTheme: NavigationBarThemeData( | ||||
|     indicatorColor: Colors.indigo.withOpacity(0.15), | ||||
|     backgroundColor: immichBackgroundColor, | ||||
|     surfaceTintColor: Colors.transparent, | ||||
|   ), | ||||
| ); | ||||
|  | ||||
| ThemeData immichDarkTheme = ThemeData( | ||||
|   useMaterial3: true, | ||||
|   brightness: Brightness.dark, | ||||
| @@ -43,7 +120,8 @@ ThemeData immichDarkTheme = ThemeData( | ||||
|     ), | ||||
|     backgroundColor: const Color.fromARGB(255, 32, 33, 35), | ||||
|     foregroundColor: immichDarkThemePrimaryColor, | ||||
|     elevation: 1, | ||||
|     elevation: 0, | ||||
|     scrolledUnderElevation: 0, | ||||
|     centerTitle: true, | ||||
|   ), | ||||
|   bottomNavigationBarTheme: BottomNavigationBarThemeData( | ||||
| @@ -56,17 +134,17 @@ ThemeData immichDarkTheme = ThemeData( | ||||
|     scrimColor: Colors.white.withOpacity(0.1), | ||||
|   ), | ||||
|   textTheme: TextTheme( | ||||
|     headline1: const TextStyle( | ||||
|     displayLarge: const TextStyle( | ||||
|       fontSize: 26, | ||||
|       fontWeight: FontWeight.bold, | ||||
|       color: Color.fromARGB(255, 255, 255, 255), | ||||
|     ), | ||||
|     headline2: const TextStyle( | ||||
|     displayMedium: const TextStyle( | ||||
|       fontSize: 14, | ||||
|       fontWeight: FontWeight.bold, | ||||
|       color: Color.fromARGB(255, 255, 255, 255), | ||||
|     ), | ||||
|     headline3: TextStyle( | ||||
|     displaySmall: TextStyle( | ||||
|       fontSize: 12, | ||||
|       fontWeight: FontWeight.bold, | ||||
|       color: immichDarkThemePrimaryColor, | ||||
| @@ -79,57 +157,19 @@ ThemeData immichDarkTheme = ThemeData( | ||||
|       backgroundColor: immichDarkThemePrimaryColor, | ||||
|     ), | ||||
|   ), | ||||
| ); | ||||
|  | ||||
| ThemeData immichLightTheme = ThemeData( | ||||
|   useMaterial3: true, | ||||
|   brightness: Brightness.light, | ||||
|   primarySwatch: Colors.indigo, | ||||
|   hintColor: Colors.indigo, | ||||
|   fontFamily: 'WorkSans', | ||||
|   scaffoldBackgroundColor: immichBackgroundColor, | ||||
|   snackBarTheme: const SnackBarThemeData( | ||||
|     contentTextStyle: TextStyle(fontFamily: 'WorkSans'), | ||||
|   ), | ||||
|   appBarTheme: AppBarTheme( | ||||
|     titleTextStyle: const TextStyle( | ||||
|       fontFamily: 'WorkSans', | ||||
|       color: Colors.indigo, | ||||
|   chipTheme: base.chipTheme, | ||||
|   popupMenuTheme: const PopupMenuThemeData( | ||||
|     shape: RoundedRectangleBorder( | ||||
|       borderRadius: BorderRadius.all(Radius.circular(10)), | ||||
|     ), | ||||
|     backgroundColor: immichBackgroundColor, | ||||
|     foregroundColor: Colors.indigo, | ||||
|     elevation: 1, | ||||
|     centerTitle: true, | ||||
|     surfaceTintColor: Colors.transparent, | ||||
|   ), | ||||
|   bottomNavigationBarTheme: BottomNavigationBarThemeData( | ||||
|     type: BottomNavigationBarType.fixed, | ||||
|     backgroundColor: immichBackgroundColor, | ||||
|     selectedItemColor: Colors.indigo, | ||||
|   ), | ||||
|   drawerTheme: DrawerThemeData( | ||||
|     backgroundColor: immichBackgroundColor, | ||||
|   ), | ||||
|   textTheme: const TextTheme( | ||||
|     headline1: TextStyle( | ||||
|       fontSize: 26, | ||||
|       fontWeight: FontWeight.bold, | ||||
|       color: Colors.indigo, | ||||
|     ), | ||||
|     headline2: TextStyle( | ||||
|       fontSize: 14, | ||||
|       fontWeight: FontWeight.bold, | ||||
|       color: Colors.black87, | ||||
|     ), | ||||
|     headline3: TextStyle( | ||||
|       fontSize: 12, | ||||
|       fontWeight: FontWeight.bold, | ||||
|       color: Colors.indigo, | ||||
|     ), | ||||
|   ), | ||||
|   elevatedButtonTheme: ElevatedButtonThemeData( | ||||
|     style: ElevatedButton.styleFrom( | ||||
|       backgroundColor: Colors.indigo, | ||||
|       foregroundColor: Colors.white, | ||||
|   navigationBarTheme: NavigationBarThemeData( | ||||
|     indicatorColor: immichDarkThemePrimaryColor.withOpacity(0.4), | ||||
|     iconTheme: const MaterialStatePropertyAll( | ||||
|       IconThemeData(color: Colors.white), | ||||
|     ), | ||||
|     backgroundColor: Colors.grey[900], | ||||
|     surfaceTintColor: Colors.transparent, | ||||
|   ), | ||||
| ); | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user