feat(mobile): slideshow view (#28421)

* feat(mobile): slideshow view

* move slideshow settings to metadata store

* remove watch in initState

* wrap progress bar in safearea

* show slideshow button on remote albums

* fix crash on unknown assets

* always show slideshow option

* add zoom effect

* add padding to slideshow settings

* chore: styling tweak

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
Ben Beckford
2026-05-15 16:12:04 -07:00
committed by GitHub
parent df016f9228
commit 0ef04d9baa
15 changed files with 657 additions and 7 deletions
@@ -4,6 +4,7 @@ import 'package:immich_mobile/domain/models/config/map_config.dart';
import 'package:immich_mobile/domain/models/config/theme_config.dart';
import 'package:immich_mobile/domain/models/config/timeline_config.dart';
import 'package:immich_mobile/domain/models/config/viewer_config.dart';
import 'package:immich_mobile/domain/models/config/slideshow_config.dart';
class AppConfig {
final ThemeConfig theme;
@@ -12,6 +13,7 @@ class AppConfig {
final TimelineConfig timeline;
final ImageConfig image;
final ViewerConfig viewer;
final SlideshowConfig slideshow;
const AppConfig({
this.theme = const .new(),
@@ -20,6 +22,7 @@ class AppConfig {
this.timeline = const .new(),
this.image = const .new(),
this.viewer = const .new(),
this.slideshow = const .new(),
});
AppConfig copyWith({
@@ -29,6 +32,7 @@ class AppConfig {
TimelineConfig? timeline,
ImageConfig? image,
ViewerConfig? viewer,
SlideshowConfig? slideshow,
}) => .new(
theme: theme ?? this.theme,
cleanup: cleanup ?? this.cleanup,
@@ -36,6 +40,7 @@ class AppConfig {
timeline: timeline ?? this.timeline,
image: image ?? this.image,
viewer: viewer ?? this.viewer,
slideshow: slideshow ?? this.slideshow,
);
@override
@@ -47,12 +52,13 @@ class AppConfig {
other.map == map &&
other.timeline == timeline &&
other.image == image &&
other.viewer == viewer);
other.viewer == viewer &&
other.slideshow == slideshow);
@override
int get hashCode => Object.hash(theme, cleanup, map, timeline, image, viewer);
int get hashCode => Object.hash(theme, cleanup, map, timeline, image, viewer, slideshow);
@override
String toString() =>
'AppConfig(theme: $theme, cleanup: $cleanup, map: $map, timeline: $timeline, image: $image, viewer: $viewer)';
'AppConfig(theme: $theme, cleanup: $cleanup, map: $map, timeline: $timeline, image: $image, viewer: $viewer, slideshow: $slideshow)';
}
@@ -0,0 +1,48 @@
import 'package:immich_mobile/constants/enums.dart';
class SlideshowConfig {
final bool transition;
final bool repeat;
final int duration;
final SlideshowLook look;
final SlideshowDirection direction;
const SlideshowConfig({
this.transition = true,
this.repeat = true,
this.duration = 5,
this.look = SlideshowLook.contain,
this.direction = SlideshowDirection.forward,
});
SlideshowConfig copyWith({
bool? transition,
bool? repeat,
int? duration,
SlideshowLook? look,
SlideshowDirection? direction,
}) => SlideshowConfig(
transition: transition ?? this.transition,
repeat: repeat ?? this.repeat,
duration: duration ?? this.duration,
look: look ?? this.look,
direction: direction ?? this.direction,
);
@override
bool operator ==(Object other) =>
identical(this, other) ||
(other is SlideshowConfig &&
other.transition == transition &&
other.repeat == repeat &&
other.duration == duration &&
other.look == look &&
other.direction == direction);
@override
int get hashCode => Object.hash(transition, repeat, duration, look, direction);
@override
String toString() =>
'SlideshowConfig(transition: $transition, repeat: $repeat, duration: $duration, look: $look, direction: $direction)';
}