chore: add always_put_control_body_on_new_line lint (#28352)

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
shenlong
2026-05-12 00:47:24 +07:00
committed by GitHub
parent 7837d40f57
commit 12f7b2a005
122 changed files with 774 additions and 263 deletions
@@ -21,21 +21,27 @@ class AppearsInDetails extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
if (!asset.hasRemote) return const SizedBox.shrink();
if (!asset.hasRemote) {
return const SizedBox.shrink();
}
final remoteAssetId = switch (asset) {
RemoteAsset(:final id) => id,
LocalAsset(:final remoteAssetId) => remoteAssetId,
};
if (remoteAssetId == null) return const SizedBox.shrink();
if (remoteAssetId == null) {
return const SizedBox.shrink();
}
final userId = ref.watch(currentUserProvider)?.id;
final assetAlbums = ref.watch(albumsContainingAssetProvider(remoteAssetId));
return assetAlbums.when(
data: (albums) {
if (albums.isEmpty) return const SizedBox.shrink();
if (albums.isEmpty) {
return const SizedBox.shrink();
}
albums.sortBy((a) => a.name);
@@ -20,7 +20,9 @@ class RatingDetails extends ConsumerWidget {
.watch(userMetadataPreferencesProvider)
.maybeWhen(data: (prefs) => prefs?.ratingsEnabled ?? false, orElse: () => false);
if (!isRatingEnabled) return const SizedBox.shrink();
if (!isRatingEnabled) {
return const SizedBox.shrink();
}
return Padding(
padding: const EdgeInsets.only(left: 16.0, top: 16.0),
@@ -111,7 +111,9 @@ class TechnicalDetails extends ConsumerWidget {
}
static String? _getCameraInfoTitle(ExifInfo? exifInfo) {
if (exifInfo == null) return null;
if (exifInfo == null) {
return null;
}
return switch ((exifInfo.make, exifInfo.model)) {
(null, null) => null,
(String make, null) => make,
@@ -121,17 +123,23 @@ class TechnicalDetails extends ConsumerWidget {
}
static String? _getCameraInfoSubtitle(ExifInfo? exifInfo) {
if (exifInfo == null) return null;
if (exifInfo == null) {
return null;
}
final exposureTime = exifInfo.exposureTime.isNotEmpty ? exifInfo.exposureTime : null;
final iso = exifInfo.iso != null ? 'ISO ${exifInfo.iso}' : null;
return [exposureTime, iso].where((spec) => spec != null && spec.isNotEmpty).join(_kSeparator);
}
static String? _getLensInfoSubtitle(ExifInfo? exifInfo) {
if (exifInfo == null) return null;
if (exifInfo == null) {
return null;
}
final fNumber = exifInfo.fNumber.isNotEmpty ? 'ƒ/${exifInfo.fNumber}' : null;
final focalLength = exifInfo.focalLength.isNotEmpty ? '${exifInfo.focalLength} mm' : null;
if (fNumber == null && focalLength == null) return null;
if (fNumber == null && focalLength == null) {
return null;
}
return [fNumber, focalLength].where((spec) => spec != null && spec.isNotEmpty).join(_kSeparator);
}
}
@@ -14,14 +14,14 @@ import 'package:immich_mobile/extensions/scroll_extensions.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_details.widget.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_stack.provider.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_stack.widget.dart';
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/video_viewer.widget.dart';
import 'package:immich_mobile/presentation/widgets/images/image_provider.dart';
import 'package:immich_mobile/presentation/widgets/images/thumbnail.widget.dart';
import 'package:immich_mobile/providers/app_settings.provider.dart';
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.provider.dart';
import 'package:immich_mobile/services/app_settings.service.dart';
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
import 'package:immich_mobile/services/app_settings.service.dart';
import 'package:immich_mobile/widgets/common/immich_loading_indicator.dart';
import 'package:immich_mobile/widgets/photo_view/photo_view.dart';
@@ -62,7 +62,9 @@ class _AssetPageState extends ConsumerState<AssetPage> {
super.initState();
_eventSubscription = EventStream.shared.listen(_onEvent);
WidgetsBinding.instance.addPostFrameCallback((_) {
if (!mounted || !_scrollController.hasClients) return;
if (!mounted || !_scrollController.hasClients) {
return;
}
_scrollController.snapPosition.snapOffset = _snapOffset;
if (_showingDetails && _snapOffset > 0) {
_scrollController.jumpTo(_snapOffset);
@@ -87,7 +89,9 @@ class _AssetPageState extends ConsumerState<AssetPage> {
}
void _showDetails() {
if (!_scrollController.hasClients || _snapOffset <= 0) return;
if (!_scrollController.hasClients || _snapOffset <= 0) {
return;
}
_viewer.setShowingDetails(true);
_scrollController.animateTo(_snapOffset, duration: Durations.medium2, curve: Curves.easeOutCubic);
}
@@ -128,7 +132,9 @@ class _AssetPageState extends ConsumerState<AssetPage> {
}
void _updateDrag(DragUpdateDetails details) {
if (_dragStart == null) return;
if (_dragStart == null) {
return;
}
if (_dragIntent == _DragIntent.none) {
_dragIntent = switch ((details.globalPosition - _dragStart!.globalPosition).dy) {
@@ -141,7 +147,9 @@ class _AssetPageState extends ConsumerState<AssetPage> {
switch (_dragIntent) {
case _DragIntent.none:
case _DragIntent.scroll:
if (_drag == null) _startProxyDrag();
if (_drag == null) {
_startProxyDrag();
}
_drag?.update(details);
_syncShowingDetails();
@@ -151,7 +159,9 @@ class _AssetPageState extends ConsumerState<AssetPage> {
}
void _endDrag(DragEndDetails details) {
if (_dragStart == null) return;
if (_dragStart == null) {
return;
}
final start = _dragStart;
_dragStart = null;
@@ -188,7 +198,9 @@ class _AssetPageState extends ConsumerState<AssetPage> {
PhotoViewControllerBase controller,
PhotoViewScaleStateController scaleStateController,
) {
if (!_showingDetails && _isZoomed) return;
if (!_showingDetails && _isZoomed) {
return;
}
_beginDrag(details);
}
@@ -215,7 +227,9 @@ class _AssetPageState extends ConsumerState<AssetPage> {
}
void _onTapUp(BuildContext context, TapUpDetails details, PhotoViewControllerValue controllerValue) {
if (_showingDetails || _dragStart != null) return;
if (_showingDetails || _dragStart != null) {
return;
}
final tapToNavigate = ref.read(appSettingsServiceProvider).getSetting<bool>(AppSettingsEnum.tapToNavigate);
if (!tapToNavigate) {
@@ -247,31 +261,43 @@ class _AssetPageState extends ConsumerState<AssetPage> {
_viewer.setZoomed(_isZoomed);
if (scaleState != PhotoViewScaleState.initial) {
if (_dragStart == null) _viewer.setControls(false);
if (_dragStart == null) {
_viewer.setControls(false);
}
return;
}
if (!_showingDetails) _viewer.setControls(true);
if (!_showingDetails) {
_viewer.setControls(true);
}
}
void _listenForScaleBoundaries(PhotoViewControllerBase? controller) {
_scaleBoundarySub?.cancel();
_scaleBoundarySub = null;
if (controller == null || controller.scaleBoundaries != null) return;
if (controller == null || controller.scaleBoundaries != null) {
return;
}
_scaleBoundarySub = controller.outputStateStream.listen((_) {
if (controller.scaleBoundaries != null) {
_scaleBoundarySub?.cancel();
_scaleBoundarySub = null;
if (mounted) setState(() {});
if (mounted) {
setState(() {});
}
}
});
}
double _getImageHeight(double maxWidth, double maxHeight, BaseAsset? asset) {
final sb = _viewController?.scaleBoundaries;
if (sb != null) return sb.childSize.height * sb.initialScale;
if (sb != null) {
return sb.childSize.height * sb.initialScale;
}
if (asset == null || asset.width == null || asset.height == null) return maxHeight;
if (asset == null || asset.width == null || asset.height == null) {
return maxHeight;
}
final r = asset.width! / asset.height!;
return math.min(maxWidth / r, maxHeight);
@@ -21,12 +21,16 @@ class AssetPreloader {
unawaited(timelineService.preloadAssets(index));
_timer?.cancel();
_timer = Timer(Durations.medium4, () async {
if (!mounted()) return;
if (!mounted()) {
return;
}
final (prev, next) = await (
timelineService.getAssetAsync(index - 1),
timelineService.getAssetAsync(index + 1),
).wait;
if (!mounted()) return;
if (!mounted()) {
return;
}
_prevStream?.removeListener(_dummyListener);
_nextStream?.removeListener(_dummyListener);
_prevStream = prev != null ? _resolveImage(prev, size) : null;
@@ -17,9 +17,9 @@ import 'package:immich_mobile/presentation/widgets/action_buttons/download_statu
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_page.widget.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_preloader.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/asset_stack.provider.dart';
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/viewer_top_app_bar.widget.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/viewer_bottom_app_bar.widget.dart';
import 'package:immich_mobile/presentation/widgets/asset_viewer/viewer_top_app_bar.widget.dart';
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
import 'package:immich_mobile/providers/cast.provider.dart';
import 'package:immich_mobile/providers/infrastructure/current_album.provider.dart';
import 'package:immich_mobile/providers/infrastructure/timeline.provider.dart';
@@ -67,7 +67,9 @@ class AssetViewer extends ConsumerStatefulWidget {
ref.read(assetViewerProvider.notifier).reset();
// Hide controls by default for videos
if (asset.isVideo) ref.read(assetViewerProvider.notifier).setControls(false);
if (asset.isVideo) {
ref.read(assetViewerProvider.notifier).setControls(false);
}
_setAsset(ref, asset);
}
@@ -90,7 +92,9 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
void _onTapNavigate(int direction) {
final page = _pageController.page?.toInt();
if (page == null) return;
if (page == null) {
return;
}
final target = page + direction;
final maxPage = _totalAssets - 1;
if (target >= 0 && target <= maxPage) {
@@ -105,7 +109,9 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
final asset = ref.read(assetViewerProvider).currentAsset;
assert(asset != null, "Current asset should not be null when opening the AssetViewer");
if (asset != null) _stackChildrenKeepAlive = ref.read(stackChildrenNotifier(asset).notifier).ref.keepAlive();
if (asset != null) {
_stackChildrenKeepAlive = ref.read(stackChildrenNotifier(asset).notifier).ref.keepAlive();
}
_reloadSubscription = EventStream.shared.listen(_onEvent);
@@ -137,7 +143,9 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
// playing, and preventing the video on the next page from becoming ready
// unnecessarily.
bool _onScrollEnd(ScrollEndNotification notification) {
if (notification.depth != 0) return false;
if (notification.depth != 0) {
return false;
}
final page = _pageController.page?.round();
if (page != null && page != _currentPage) {
@@ -155,7 +163,9 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
_currentPage = index;
final asset = await ref.read(timelineServiceProvider).getAssetAsync(index);
if (asset == null) return;
if (asset == null) {
return;
}
AssetViewer._setAsset(ref, asset);
_preloader.preload(index, context.sizeData);
@@ -165,9 +175,13 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
}
void _handleCasting() {
if (!ref.read(castProvider).isCasting) return;
if (!ref.read(castProvider).isCasting) {
return;
}
final asset = ref.read(assetViewerProvider).currentAsset;
if (asset == null) return;
if (asset == null) {
return;
}
if (asset is RemoteAsset) {
context.scaffoldMessenger.hideCurrentSnackBar();
@@ -199,7 +213,9 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
}
void _onViewerReloadEvent() {
if (_totalAssets <= 1) return;
if (_totalAssets <= 1) {
return;
}
final index = _pageController.page?.round() ?? 0;
final target = index >= _totalAssets - 1 ? index - 1 : index + 1;
@@ -252,7 +268,9 @@ class _AssetViewerState extends ConsumerState<AssetViewer> {
// Listen for casting changes and send initial asset to the cast provider
ref.listen(castProvider.select((value) => value.isCasting), (_, isCasting) {
if (!isCasting) return;
if (!isCasting) {
return;
}
WidgetsBinding.instance.addPostFrameCallback((_) {
_handleCasting();
});
@@ -53,7 +53,9 @@ class _RatingBarState extends State<RatingBar> {
final totalWidth = widget.itemCount * widget.itemSize + (widget.itemCount - 1) * widget.starPadding;
double dx = localPosition.dx;
if (isRTL) dx = totalWidth - dx;
if (isRTL) {
dx = totalWidth - dx;
}
double newRating;
@@ -9,8 +9,8 @@ import 'package:immich_mobile/domain/services/setting.service.dart';
import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/extensions/platform_extensions.dart';
import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart';
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
import 'package:immich_mobile/providers/app_settings.provider.dart';
import 'package:immich_mobile/providers/asset_viewer/asset_viewer.provider.dart';
import 'package:immich_mobile/providers/asset_viewer/is_motion_video_playing.provider.dart';
import 'package:immich_mobile/providers/asset_viewer/video_player_provider.dart';
import 'package:immich_mobile/providers/cast.provider.dart';
@@ -61,7 +61,9 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> with Widg
void didUpdateWidget(NativeVideoViewer oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.isCurrent == oldWidget.isCurrent || _controller == null) return;
if (widget.isCurrent == oldWidget.isCurrent || _controller == null) {
return;
}
if (!widget.isCurrent) {
_loadTimer?.cancel();
@@ -85,25 +87,35 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> with Widg
void didChangeAppLifecycleState(AppLifecycleState state) async {
switch (state) {
case AppLifecycleState.resumed:
if (_shouldPlayOnForeground) await _notifier.play();
if (_shouldPlayOnForeground) {
await _notifier.play();
}
case AppLifecycleState.paused:
_shouldPlayOnForeground = await _controller?.isPlaying() ?? true;
if (_shouldPlayOnForeground) await _notifier.pause();
if (_shouldPlayOnForeground) {
await _notifier.pause();
}
default:
}
}
Future<VideoSource?> _createSource() async {
if (!mounted) return null;
if (!mounted) {
return null;
}
final videoAsset = await ref.read(assetServiceProvider).getAsset(widget.asset) ?? widget.asset;
if (!mounted) return null;
if (!mounted) {
return null;
}
try {
if (videoAsset.hasLocal && videoAsset.livePhotoVideoId == null) {
final id = videoAsset is LocalAsset ? videoAsset.id : (videoAsset as RemoteAsset).localId!;
final file = await StorageRepository().getFileForAsset(id);
if (!mounted) return null;
if (!mounted) {
return null;
}
if (file == null) {
throw Exception('No file found for the video');
@@ -134,25 +146,35 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> with Widg
}
void _onPlaybackReady() async {
if (!mounted || !widget.isCurrent) return;
if (!mounted || !widget.isCurrent) {
return;
}
_notifier.onNativePlaybackReady();
// onPlaybackReady may be called multiple times, usually when more data
// loads. If this is not the first time that the player has become ready, we
// should not autoplay.
if (_isVideoReady) return;
if (_isVideoReady) {
return;
}
setState(() => _isVideoReady = true);
if (ref.read(assetViewerProvider).showingDetails) return;
if (ref.read(assetViewerProvider).showingDetails) {
return;
}
final autoPlayVideo = AppSetting.get(Setting.autoPlayVideo);
if (autoPlayVideo || widget.asset.isMotionPhoto) await _notifier.play();
if (autoPlayVideo || widget.asset.isMotionPhoto) {
await _notifier.play();
}
}
void _onPlaybackEnded() {
if (!mounted) return;
if (!mounted) {
return;
}
_notifier.onNativePlaybackEnded();
@@ -162,12 +184,16 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> with Widg
}
void _onPlaybackPositionChanged() {
if (!mounted) return;
if (!mounted) {
return;
}
_notifier.onNativePositionChanged();
}
void _onPlaybackStatusChanged() {
if (!mounted) return;
if (!mounted) {
return;
}
_notifier.onNativeStatusChanged();
}
@@ -180,10 +206,14 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> with Widg
void _loadVideo() async {
final nc = _controller;
if (nc == null || nc.videoSource != null || !mounted) return;
if (nc == null || nc.videoSource != null || !mounted) {
return;
}
final source = await _videoSource;
if (source == null || !mounted) return;
if (source == null || !mounted) {
return;
}
await _notifier.load(source);
final loopVideo = ref.read(appSettingsServiceProvider).getSetting<bool>(AppSettingsEnum.loopVideo);
@@ -192,7 +222,9 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> with Widg
}
void _initController(NativeVideoPlayerController nc) {
if (_controller != null || !mounted) return;
if (_controller != null || !mounted) {
return;
}
_notifier.attachController(nc);
@@ -203,7 +235,9 @@ class _NativeVideoViewerState extends ConsumerState<NativeVideoViewer> with Widg
_controller = nc;
if (widget.isCurrent) _loadVideo();
if (widget.isCurrent) {
_loadVideo();
}
}
@override