mirror of
https://github.com/immich-app/immich.git
synced 2024-12-25 10:43:13 +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:
parent
b1311547b2
commit
bcb0056b55
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 {
|
||||
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);
|
||||
|
||||
},
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user