1
0
mirror of https://github.com/immich-app/immich.git synced 2024-12-26 10:50:29 +02: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:
Matthias Rupp 2023-01-26 15:40:19 +01:00 committed by GitHub
parent b1311547b2
commit bcb0056b55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 87 additions and 44 deletions

31
.github/workflows/static_analysis.yml vendored Normal file
View 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

View File

@ -2,7 +2,6 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import '../test_utils/general_helper.dart'; import '../test_utils/general_helper.dart';
import '../test_utils/login_helper.dart';
void main() async { void main() async {
await ImmichTestHelper.initialize(); await ImmichTestHelper.initialize();
@ -13,7 +12,7 @@ void main() async {
await helper.loginHelper.acknowledgeNewServerVersion(); await helper.loginHelper.acknowledgeNewServerVersion();
await helper.loginHelper.enterCredentials( await helper.loginHelper.enterCredentials(
email: " demo@immich.app" email: " demo@immich.app",
); );
await tester.pump(const Duration(milliseconds: 300)); await tester.pump(const Duration(milliseconds: 300));
@ -21,7 +20,7 @@ void main() async {
expect(find.text("login_form_err_leading_whitespace".tr()), findsOneWidget); expect(find.text("login_form_err_leading_whitespace".tr()), findsOneWidget);
await helper.loginHelper.enterCredentials( await helper.loginHelper.enterCredentials(
email: "demo@immich.app " email: "demo@immich.app ",
); );
await tester.pump(const Duration(milliseconds: 300)); await tester.pump(const Duration(milliseconds: 300));
@ -34,7 +33,7 @@ void main() async {
await helper.loginHelper.acknowledgeNewServerVersion(); await helper.loginHelper.acknowledgeNewServerVersion();
await helper.loginHelper.enterCredentials( await helper.loginHelper.enterCredentials(
email: "demo.immich.app" email: "demo.immich.app",
); );
await tester.pump(const Duration(milliseconds: 300)); await tester.pump(const Duration(milliseconds: 300));

View File

@ -1,5 +1,3 @@
import 'dart:io';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import '../test_utils/general_helper.dart'; import '../test_utils/general_helper.dart';
@ -12,8 +10,9 @@ void main() async {
immichWidgetTest("Test correct credentials", (tester, helper) async { immichWidgetTest("Test correct credentials", (tester, helper) async {
await helper.loginHelper.waitForLoginScreen(); await helper.loginHelper.waitForLoginScreen();
await helper.loginHelper.acknowledgeNewServerVersion(); await helper.loginHelper.acknowledgeNewServerVersion();
await helper.loginHelper await helper.loginHelper.enterCredentialsOf(
.enterCredentialsOf(LoginCredentials.testInstance); LoginCredentials.testInstance,
);
await helper.loginHelper.pressLoginButton(); await helper.loginHelper.pressLoginButton();
await helper.loginHelper.assertLoginSuccess(); await helper.loginHelper.assertLoginSuccess();
}); });
@ -22,16 +21,19 @@ void main() async {
await helper.loginHelper.waitForLoginScreen(); await helper.loginHelper.waitForLoginScreen();
await helper.loginHelper.acknowledgeNewServerVersion(); await helper.loginHelper.acknowledgeNewServerVersion();
await helper.loginHelper.enterCredentialsOf( await helper.loginHelper.enterCredentialsOf(
LoginCredentials.testInstanceButWithWrongPassword); LoginCredentials.testInstanceButWithWrongPassword,
);
await helper.loginHelper.pressLoginButton(); await helper.loginHelper.pressLoginButton();
await helper.loginHelper.assertLoginFailed(); 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.waitForLoginScreen();
await helper.loginHelper.acknowledgeNewServerVersion(); await helper.loginHelper.acknowledgeNewServerVersion();
await helper.loginHelper.enterCredentialsOf( await helper.loginHelper.enterCredentialsOf(
LoginCredentials.wrongInstanceUrl); LoginCredentials.wrongInstanceUrl,
);
await helper.loginHelper.pressLoginButton(); await helper.loginHelper.pressLoginButton();
await helper.loginHelper.assertLoginFailed(); await helper.loginHelper.assertLoginFailed();
}); });

View File

@ -1,17 +1,14 @@
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:hive/hive.dart'; import 'package:hive/hive.dart';
import 'package:immich_mobile/main.dart';
import 'package:integration_test/integration_test.dart'; import 'package:integration_test/integration_test.dart';
// ignore: depend_on_referenced_packages
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:immich_mobile/main.dart' as app; import 'package:immich_mobile/main.dart' as app;
import 'login_helper.dart'; import 'login_helper.dart';
class ImmichTestHelper { class ImmichTestHelper {
final WidgetTester tester; final WidgetTester tester;
ImmichTestHelper(this.tester); ImmichTestHelper(this.tester);
@ -43,15 +40,19 @@ class ImmichTestHelper {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
await EasyLocalization.ensureInitialized(); await EasyLocalization.ensureInitialized();
} }
} }
@isTest @isTest
void immichWidgetTest(String description, Future<void> Function(WidgetTester, ImmichTestHelper) test) { void immichWidgetTest(
String description,
testWidgets(description, (widgetTester) async { Future<void> Function(WidgetTester, ImmichTestHelper) test,
) {
testWidgets(
description,
(widgetTester) async {
await ImmichTestHelper.loadApp(widgetTester); await ImmichTestHelper.loadApp(widgetTester);
await test(widgetTester, ImmichTestHelper(widgetTester)); await test(widgetTester, ImmichTestHelper(widgetTester));
}, semanticsEnabled: false); },
semanticsEnabled: false,
);
} }

View File

@ -1,8 +1,6 @@
import 'dart:async';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:immich_mobile/modules/home/ui/asset_grid/immich_asset_grid.dart';
class ImmichTestLoginHelper { class ImmichTestLoginHelper {
final WidgetTester tester; final WidgetTester tester;

View File

@ -96,7 +96,7 @@ class AlbumViewerAppbar extends HookConsumerWidget with PreferredSizeWidget {
if (isSuccess) { if (isSuccess) {
Navigator.pop(context); Navigator.pop(context);
ref.watch(assetSelectionProvider.notifier).disableMultiselection(); ref.watch(assetSelectionProvider.notifier).disableMultiselection();
ref.refresh(sharedAlbumDetailProvider(albumId)); ref.invalidate(sharedAlbumDetailProvider(albumId));
} else { } else {
Navigator.pop(context); Navigator.pop(context);
ImmichToast.show( ImmichToast.show(

View File

@ -62,7 +62,7 @@ class AlbumViewerPage extends HookConsumerWidget {
if (addAssetsResult != null && if (addAssetsResult != null &&
addAssetsResult.successfullyAdded > 0) { addAssetsResult.successfullyAdded > 0) {
ref.refresh(sharedAlbumDetailProvider(albumId)); ref.invalidate(sharedAlbumDetailProvider(albumId));
} }
ImmichLoadingOverlayController.appLoader.hide(); ImmichLoadingOverlayController.appLoader.hide();
@ -88,7 +88,7 @@ class AlbumViewerPage extends HookConsumerWidget {
.addAdditionalUserToAlbum(sharedUserIds, albumId); .addAdditionalUserToAlbum(sharedUserIds, albumId);
if (isSuccess) { if (isSuccess) {
ref.refresh(sharedAlbumDetailProvider(albumId)); ref.invalidate(sharedAlbumDetailProvider(albumId));
} }
ImmichLoadingOverlayController.appLoader.hide(); ImmichLoadingOverlayController.appLoader.hide();

View File

@ -22,7 +22,7 @@ class LibraryPage extends HookConsumerWidget {
[], [],
); );
Widget _buildAppBar() { Widget buildAppBar() {
return const SliverAppBar( return const SliverAppBar(
centerTitle: true, centerTitle: true,
floating: true, floating: true,
@ -40,7 +40,7 @@ class LibraryPage extends HookConsumerWidget {
); );
} }
Widget _buildCreateAlbumButton() { Widget buildCreateAlbumButton() {
return GestureDetector( return GestureDetector(
onTap: () { onTap: () {
AutoRouter.of(context).push(CreateAlbumRoute(isSharedAlbum: false)); AutoRouter.of(context).push(CreateAlbumRoute(isSharedAlbum: false));
@ -83,7 +83,7 @@ class LibraryPage extends HookConsumerWidget {
return Scaffold( return Scaffold(
body: CustomScrollView( body: CustomScrollView(
slivers: [ slivers: [
_buildAppBar(), buildAppBar(),
SliverToBoxAdapter( SliverToBoxAdapter(
child: Padding( child: Padding(
padding: const EdgeInsets.all(12.0), padding: const EdgeInsets.all(12.0),
@ -99,7 +99,7 @@ class LibraryPage extends HookConsumerWidget {
child: Wrap( child: Wrap(
spacing: 12, spacing: 12,
children: [ children: [
_buildCreateAlbumButton(), buildCreateAlbumButton(),
for (var album in albums) for (var album in albums)
AlbumThumbnailCard( AlbumThumbnailCard(
album: album, album: album,

View File

@ -8,7 +8,8 @@ class AssetCacheService extends JsonCache<List<Asset>> {
AssetCacheService() : super("asset_cache"); AssetCacheService() : super("asset_cache");
static Future<List<Map<String, dynamic>>> _computeSerialize( static Future<List<Map<String, dynamic>>> _computeSerialize(
List<Asset> assets) async { List<Asset> assets,
) async {
return assets.map((e) => e.toJson()).toList(); return assets.map((e) => e.toJson()).toList();
} }

View File

@ -42,8 +42,13 @@ class _AssetGroupsToRenderListComputeParameters {
final Map<String, List<Asset>> groups; final Map<String, List<Asset>> groups;
final int perRow; final int perRow;
_AssetGroupsToRenderListComputeParameters(this.monthFormat, this.dayFormat, _AssetGroupsToRenderListComputeParameters(
this.dayFormatYear, this.groups, this.perRow); this.monthFormat,
this.dayFormat,
this.dayFormatYear,
this.groups,
this.perRow,
);
} }
class RenderList { class RenderList {
@ -52,7 +57,8 @@ class RenderList {
RenderList(this.elements); RenderList(this.elements);
static Future<RenderList> _processAssetGroupData( static Future<RenderList> _processAssetGroupData(
_AssetGroupsToRenderListComputeParameters data) async { _AssetGroupsToRenderListComputeParameters data,
) async {
final monthFormat = DateFormat(data.monthFormat); final monthFormat = DateFormat(data.monthFormat);
final dayFormatSameYear = DateFormat(data.dayFormat); final dayFormatSameYear = DateFormat(data.dayFormat);
final dayFormatOtherYear = DateFormat(data.dayFormatYear); final dayFormatOtherYear = DateFormat(data.dayFormatYear);

View File

@ -1,4 +1,3 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';

View File

@ -235,7 +235,7 @@ class ServerEndpointInput extends StatelessWidget {
labelText: 'login_form_endpoint_url'.tr(), labelText: 'login_form_endpoint_url'.tr(),
border: const OutlineInputBorder(), border: const OutlineInputBorder(),
hintText: 'login_form_endpoint_hint'.tr(), hintText: 'login_form_endpoint_hint'.tr(),
errorMaxLines: 4 errorMaxLines: 4,
), ),
validator: _validateInput, validator: _validateInput,
autovalidateMode: AutovalidateMode.always, autovalidateMode: AutovalidateMode.always,

View File

@ -30,8 +30,8 @@ class TabNavigationObserver extends AutoRouterObserver {
// Perform tasks on re-visit to SearchRoute // Perform tasks on re-visit to SearchRoute
if (route.name == 'SearchRoute') { if (route.name == 'SearchRoute') {
// Refresh Location State // Refresh Location State
ref.refresh(getCuratedLocationProvider); ref.invalidate(getCuratedLocationProvider);
ref.refresh(getCuratedObjectProvider); ref.invalidate(getCuratedObjectProvider);
} }
if (route.name == 'SharingRoute') { if (route.name == 'SharingRoute') {

View File

@ -83,6 +83,7 @@ class ImmichLogger {
} }
// Share file // Share file
// ignore: deprecated_member_use
await Share.shareFiles( await Share.shareFiles(
[filePath], [filePath],
subject: "Immich logs $dateTime", subject: "Immich logs $dateTime",

View File

@ -40,6 +40,7 @@ class ShareService {
} }
}); });
// ignore: deprecated_member_use
Share.shareFiles( Share.shareFiles(
await Future.wait(downloadedFilePaths), await Future.wait(downloadedFilePaths),
sharePositionOrigin: Rect.zero, sharePositionOrigin: Rect.zero,

View File

@ -10,8 +10,10 @@ String getThumbnailUrl(
return _getThumbnailUrl(asset.id, type: type); return _getThumbnailUrl(asset.id, type: type);
} }
String getThumbnailCacheKey(final AssetResponseDto asset, String getThumbnailCacheKey(
{ThumbnailFormat type = ThumbnailFormat.WEBP}) { final AssetResponseDto asset, {
ThumbnailFormat type = ThumbnailFormat.WEBP,
}) {
return _getThumbnailCacheKey(asset.id, type); return _getThumbnailCacheKey(asset.id, type);
} }

View File

@ -31,7 +31,9 @@ extension WithETag on AssetApi {
final responseBody = await _decodeBodyBytes(response); final responseBody = await _decodeBodyBytes(response);
final etag = response.headers[HttpHeaders.etagHeader]; final etag = response.headers[HttpHeaders.etagHeader];
final data = (await apiClient.deserializeAsync( final data = (await apiClient.deserializeAsync(
responseBody, 'List<AssetResponseDto>') as List) responseBody,
'List<AssetResponseDto>',
) as List)
.cast<AssetResponseDto>() .cast<AssetResponseDto>()
.toList(); .toList();
return Pair(data, etag); return Pair(data, etag);