mirror of
				https://github.com/KevinMidboe/immich.git
				synced 2025-10-29 17:40:28 +00:00 
			
		
		
		
	chore(mobile): Run dart analyze in CI (#1425)
* Run dart analyze in CI * Add pub get * Fix linter errors in mobile code
This commit is contained in:
		
							
								
								
									
										31
									
								
								.github/workflows/static_analysis.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								.github/workflows/static_analysis.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| name: Static Code Analysis | ||||
| on: | ||||
|   workflow_dispatch: | ||||
|   pull_request: | ||||
|   push: | ||||
|     branches: [main] | ||||
|  | ||||
| jobs: | ||||
|   mobile-dart-analyze: | ||||
|     name: Run Dart Code Analysis | ||||
|  | ||||
|     runs-on: ubuntu-latest | ||||
|  | ||||
|     steps: | ||||
|       - name: Checkout code | ||||
|         uses: actions/checkout@v3 | ||||
|  | ||||
|       - name: Setup Flutter SDK | ||||
|         uses: subosito/flutter-action@v2 | ||||
|         with: | ||||
|           channel: 'stable' | ||||
|           flutter-version: '3.3.10' | ||||
|  | ||||
|       - name: Install dependencies | ||||
|         run: dart pub get | ||||
|         working-directory: ./mobile | ||||
|  | ||||
|       - name: Run dart analyze | ||||
|         run: dart analyze --fatal-infos | ||||
|         working-directory: ./mobile | ||||
|  | ||||
| @@ -2,7 +2,6 @@ import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter_test/flutter_test.dart'; | ||||
|  | ||||
| import '../test_utils/general_helper.dart'; | ||||
| import '../test_utils/login_helper.dart'; | ||||
|  | ||||
| void main() async { | ||||
|   await ImmichTestHelper.initialize(); | ||||
| @@ -13,7 +12,7 @@ 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)); | ||||
| @@ -21,7 +20,7 @@ void main() async { | ||||
|       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)); | ||||
| @@ -34,7 +33,7 @@ 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)); | ||||
|   | ||||
| @@ -1,5 +1,3 @@ | ||||
| import 'dart:io'; | ||||
|  | ||||
| import 'package:flutter_test/flutter_test.dart'; | ||||
|  | ||||
| import '../test_utils/general_helper.dart'; | ||||
| @@ -12,8 +10,9 @@ void main() async { | ||||
|     immichWidgetTest("Test correct credentials", (tester, helper) async { | ||||
|       await helper.loginHelper.waitForLoginScreen(); | ||||
|       await helper.loginHelper.acknowledgeNewServerVersion(); | ||||
|       await helper.loginHelper | ||||
|           .enterCredentialsOf(LoginCredentials.testInstance); | ||||
|       await helper.loginHelper.enterCredentialsOf( | ||||
|         LoginCredentials.testInstance, | ||||
|       ); | ||||
|       await helper.loginHelper.pressLoginButton(); | ||||
|       await helper.loginHelper.assertLoginSuccess(); | ||||
|     }); | ||||
| @@ -22,16 +21,19 @@ void main() async { | ||||
|       await helper.loginHelper.waitForLoginScreen(); | ||||
|       await helper.loginHelper.acknowledgeNewServerVersion(); | ||||
|       await helper.loginHelper.enterCredentialsOf( | ||||
|           LoginCredentials.testInstanceButWithWrongPassword); | ||||
|         LoginCredentials.testInstanceButWithWrongPassword, | ||||
|       ); | ||||
|       await helper.loginHelper.pressLoginButton(); | ||||
|       await helper.loginHelper.assertLoginFailed(); | ||||
|     }); | ||||
|  | ||||
|     immichWidgetTest("Test login with wrong server URL", (tester, helper) async { | ||||
|     immichWidgetTest("Test login with wrong server URL", | ||||
|         (tester, helper) async { | ||||
|       await helper.loginHelper.waitForLoginScreen(); | ||||
|       await helper.loginHelper.acknowledgeNewServerVersion(); | ||||
|       await helper.loginHelper.enterCredentialsOf( | ||||
|           LoginCredentials.wrongInstanceUrl); | ||||
|         LoginCredentials.wrongInstanceUrl, | ||||
|       ); | ||||
|       await helper.loginHelper.pressLoginButton(); | ||||
|       await helper.loginHelper.assertLoginFailed(); | ||||
|     }); | ||||
|   | ||||
| @@ -1,17 +1,14 @@ | ||||
|  | ||||
| import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter/foundation.dart'; | ||||
| import 'package:flutter_test/flutter_test.dart'; | ||||
| import 'package:hive/hive.dart'; | ||||
| import 'package:immich_mobile/main.dart'; | ||||
| import 'package:integration_test/integration_test.dart'; | ||||
| // ignore: depend_on_referenced_packages | ||||
| import 'package:meta/meta.dart'; | ||||
| import 'package:immich_mobile/main.dart' as app; | ||||
|  | ||||
| import 'login_helper.dart'; | ||||
|  | ||||
| class ImmichTestHelper { | ||||
|  | ||||
|   final WidgetTester tester; | ||||
|  | ||||
|   ImmichTestHelper(this.tester); | ||||
| @@ -43,15 +40,19 @@ class ImmichTestHelper { | ||||
|     await tester.pumpAndSettle(); | ||||
|     await EasyLocalization.ensureInitialized(); | ||||
|   } | ||||
|  | ||||
| } | ||||
|  | ||||
| @isTest | ||||
| void immichWidgetTest(String description, Future<void> Function(WidgetTester, ImmichTestHelper) test) { | ||||
|  | ||||
|     testWidgets(description, (widgetTester) async { | ||||
|         await ImmichTestHelper.loadApp(widgetTester); | ||||
|         await test(widgetTester, ImmichTestHelper(widgetTester)); | ||||
|     }, semanticsEnabled: false); | ||||
|  | ||||
| } | ||||
| void immichWidgetTest( | ||||
|   String description, | ||||
|   Future<void> Function(WidgetTester, ImmichTestHelper) test, | ||||
| ) { | ||||
|   testWidgets( | ||||
|     description, | ||||
|     (widgetTester) async { | ||||
|       await ImmichTestHelper.loadApp(widgetTester); | ||||
|       await test(widgetTester, ImmichTestHelper(widgetTester)); | ||||
|     }, | ||||
|     semanticsEnabled: false, | ||||
|   ); | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,6 @@ | ||||
| import 'dart:async'; | ||||
| import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:flutter_test/flutter_test.dart'; | ||||
| import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart'; | ||||
|  | ||||
| class ImmichTestLoginHelper { | ||||
|   final WidgetTester tester; | ||||
|   | ||||
| @@ -96,7 +96,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget { | ||||
|       if (isSuccess) { | ||||
|         Navigator.pop(context); | ||||
|         ref.watch(assetSelectionProvider.notifier).disableMultiselection(); | ||||
|         ref.refresh(sharedAlbumDetailProvider(albumId)); | ||||
|         ref.invalidate(sharedAlbumDetailProvider(albumId)); | ||||
|       } else { | ||||
|         Navigator.pop(context); | ||||
|         ImmichToast.show( | ||||
|   | ||||
| @@ -62,7 +62,7 @@ class AlbumViewerPage extends HookConsumerWidget { | ||||
|  | ||||
|           if (addAssetsResult != null && | ||||
|               addAssetsResult.successfullyAdded > 0) { | ||||
|             ref.refresh(sharedAlbumDetailProvider(albumId)); | ||||
|             ref.invalidate(sharedAlbumDetailProvider(albumId)); | ||||
|           } | ||||
|  | ||||
|           ImmichLoadingOverlayController.appLoader.hide(); | ||||
| @@ -88,7 +88,7 @@ class AlbumViewerPage extends HookConsumerWidget { | ||||
|             .addAdditionalUserToAlbum(sharedUserIds, albumId); | ||||
|  | ||||
|         if (isSuccess) { | ||||
|           ref.refresh(sharedAlbumDetailProvider(albumId)); | ||||
|           ref.invalidate(sharedAlbumDetailProvider(albumId)); | ||||
|         } | ||||
|  | ||||
|         ImmichLoadingOverlayController.appLoader.hide(); | ||||
|   | ||||
| @@ -22,7 +22,7 @@ class LibraryPage extends HookConsumerWidget { | ||||
|       [], | ||||
|     ); | ||||
|  | ||||
|     Widget _buildAppBar() { | ||||
|     Widget buildAppBar() { | ||||
|       return const SliverAppBar( | ||||
|         centerTitle: true, | ||||
|         floating: true, | ||||
| @@ -40,7 +40,7 @@ class LibraryPage extends HookConsumerWidget { | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     Widget _buildCreateAlbumButton() { | ||||
|     Widget buildCreateAlbumButton() { | ||||
|       return GestureDetector( | ||||
|         onTap: () { | ||||
|           AutoRouter.of(context).push(CreateAlbumRoute(isSharedAlbum: false)); | ||||
| @@ -83,7 +83,7 @@ class LibraryPage extends HookConsumerWidget { | ||||
|     return Scaffold( | ||||
|       body: CustomScrollView( | ||||
|         slivers: [ | ||||
|           _buildAppBar(), | ||||
|           buildAppBar(), | ||||
|           SliverToBoxAdapter( | ||||
|             child: Padding( | ||||
|               padding: const EdgeInsets.all(12.0), | ||||
| @@ -99,7 +99,7 @@ class LibraryPage extends HookConsumerWidget { | ||||
|               child: Wrap( | ||||
|                 spacing: 12, | ||||
|                 children: [ | ||||
|                   _buildCreateAlbumButton(), | ||||
|                   buildCreateAlbumButton(), | ||||
|                   for (var album in albums) | ||||
|                     AlbumThumbnailCard( | ||||
|                       album: album, | ||||
|   | ||||
| @@ -8,7 +8,8 @@ class AssetCacheService extends JsonCache<List<Asset>> { | ||||
|   AssetCacheService() : super("asset_cache"); | ||||
|  | ||||
|   static Future<List<Map<String, dynamic>>> _computeSerialize( | ||||
|       List<Asset> assets) async { | ||||
|     List<Asset> assets, | ||||
|   ) async { | ||||
|     return assets.map((e) => e.toJson()).toList(); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -42,8 +42,13 @@ class _AssetGroupsToRenderListComputeParameters { | ||||
|   final Map<String, List<Asset>> groups; | ||||
|   final int perRow; | ||||
|  | ||||
|   _AssetGroupsToRenderListComputeParameters(this.monthFormat, this.dayFormat, | ||||
|       this.dayFormatYear, this.groups, this.perRow); | ||||
|   _AssetGroupsToRenderListComputeParameters( | ||||
|     this.monthFormat, | ||||
|     this.dayFormat, | ||||
|     this.dayFormatYear, | ||||
|     this.groups, | ||||
|     this.perRow, | ||||
|   ); | ||||
| } | ||||
|  | ||||
| class RenderList { | ||||
| @@ -52,7 +57,8 @@ class RenderList { | ||||
|   RenderList(this.elements); | ||||
|  | ||||
|   static Future<RenderList> _processAssetGroupData( | ||||
|       _AssetGroupsToRenderListComputeParameters data) async { | ||||
|     _AssetGroupsToRenderListComputeParameters data, | ||||
|   ) async { | ||||
|     final monthFormat = DateFormat(data.monthFormat); | ||||
|     final dayFormatSameYear = DateFormat(data.dayFormat); | ||||
|     final dayFormatOtherYear = DateFormat(data.dayFormatYear); | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
| import 'package:easy_localization/easy_localization.dart'; | ||||
| import 'package:flutter/material.dart'; | ||||
| import 'package:hooks_riverpod/hooks_riverpod.dart'; | ||||
|  | ||||
|   | ||||
| @@ -235,7 +235,7 @@ class ServerEndpointInput extends StatelessWidget { | ||||
|         labelText: 'login_form_endpoint_url'.tr(), | ||||
|         border: const OutlineInputBorder(), | ||||
|         hintText: 'login_form_endpoint_hint'.tr(), | ||||
|         errorMaxLines: 4 | ||||
|         errorMaxLines: 4, | ||||
|       ), | ||||
|       validator: _validateInput, | ||||
|       autovalidateMode: AutovalidateMode.always, | ||||
|   | ||||
| @@ -30,8 +30,8 @@ class TabNavigationObserver extends AutoRouterObserver { | ||||
|     // Perform tasks on re-visit to SearchRoute | ||||
|     if (route.name == 'SearchRoute') { | ||||
|       // Refresh Location State | ||||
|       ref.refresh(getCuratedLocationProvider); | ||||
|       ref.refresh(getCuratedObjectProvider); | ||||
|       ref.invalidate(getCuratedLocationProvider); | ||||
|       ref.invalidate(getCuratedObjectProvider); | ||||
|     } | ||||
|  | ||||
|     if (route.name == 'SharingRoute') { | ||||
|   | ||||
| @@ -83,6 +83,7 @@ class ImmichLogger { | ||||
|     } | ||||
|  | ||||
|     // Share file | ||||
|     // ignore: deprecated_member_use | ||||
|     await Share.shareFiles( | ||||
|       [filePath], | ||||
|       subject: "Immich logs $dateTime", | ||||
|   | ||||
| @@ -40,6 +40,7 @@ class ShareService { | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|     // ignore: deprecated_member_use | ||||
|     Share.shareFiles( | ||||
|       await Future.wait(downloadedFilePaths), | ||||
|       sharePositionOrigin: Rect.zero, | ||||
|   | ||||
| @@ -10,8 +10,10 @@ String getThumbnailUrl( | ||||
|   return _getThumbnailUrl(asset.id, type: type); | ||||
| } | ||||
|  | ||||
| String getThumbnailCacheKey(final AssetResponseDto asset, | ||||
|     {ThumbnailFormat type = ThumbnailFormat.WEBP}) { | ||||
| String getThumbnailCacheKey( | ||||
|   final AssetResponseDto asset, { | ||||
|   ThumbnailFormat type = ThumbnailFormat.WEBP, | ||||
| }) { | ||||
|   return _getThumbnailCacheKey(asset.id, type); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -31,7 +31,9 @@ extension WithETag on AssetApi { | ||||
|       final responseBody = await _decodeBodyBytes(response); | ||||
|       final etag = response.headers[HttpHeaders.etagHeader]; | ||||
|       final data = (await apiClient.deserializeAsync( | ||||
|               responseBody, 'List<AssetResponseDto>') as List) | ||||
|         responseBody, | ||||
|         'List<AssetResponseDto>', | ||||
|       ) as List) | ||||
|           .cast<AssetResponseDto>() | ||||
|           .toList(); | ||||
|       return Pair(data, etag); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user