mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-01-22 08:46:18 +01:00
Refactor slideshow to work with file ids
This also fixed files missing when starting slideshow from search result
This commit is contained in:
parent
94cb4e7d92
commit
58e6b6c238
11 changed files with 199 additions and 93 deletions
|
@ -1530,6 +1530,7 @@
|
|||
"@albumAddMapTooltip": {
|
||||
"description": "Add a map that display between photos to an album"
|
||||
},
|
||||
"fileNotFound": "File not found",
|
||||
|
||||
"errorUnauthenticated": "Unauthenticated access. Please sign-in again if the problem continues",
|
||||
"@errorUnauthenticated": {
|
||||
|
|
|
@ -272,6 +272,7 @@
|
|||
"customizeButtonsUnsupportedWarning",
|
||||
"placePickerTitle",
|
||||
"albumAddMapTooltip",
|
||||
"fileNotFound",
|
||||
"errorUnauthenticated",
|
||||
"errorDisconnected",
|
||||
"errorLocked",
|
||||
|
@ -295,7 +296,8 @@
|
|||
"customizeCollectionsNavBarDescription",
|
||||
"customizeButtonsUnsupportedWarning",
|
||||
"placePickerTitle",
|
||||
"albumAddMapTooltip"
|
||||
"albumAddMapTooltip",
|
||||
"fileNotFound"
|
||||
],
|
||||
|
||||
"de": [
|
||||
|
@ -311,7 +313,8 @@
|
|||
"customizeCollectionsNavBarDescription",
|
||||
"customizeButtonsUnsupportedWarning",
|
||||
"placePickerTitle",
|
||||
"albumAddMapTooltip"
|
||||
"albumAddMapTooltip",
|
||||
"fileNotFound"
|
||||
],
|
||||
|
||||
"el": [
|
||||
|
@ -472,7 +475,8 @@
|
|||
"customizeCollectionsNavBarDescription",
|
||||
"customizeButtonsUnsupportedWarning",
|
||||
"placePickerTitle",
|
||||
"albumAddMapTooltip"
|
||||
"albumAddMapTooltip",
|
||||
"fileNotFound"
|
||||
],
|
||||
|
||||
"es": [
|
||||
|
@ -488,7 +492,8 @@
|
|||
"customizeCollectionsNavBarDescription",
|
||||
"customizeButtonsUnsupportedWarning",
|
||||
"placePickerTitle",
|
||||
"albumAddMapTooltip"
|
||||
"albumAddMapTooltip",
|
||||
"fileNotFound"
|
||||
],
|
||||
|
||||
"fi": [
|
||||
|
@ -540,7 +545,8 @@
|
|||
"customizeCollectionsNavBarDescription",
|
||||
"customizeButtonsUnsupportedWarning",
|
||||
"placePickerTitle",
|
||||
"albumAddMapTooltip"
|
||||
"albumAddMapTooltip",
|
||||
"fileNotFound"
|
||||
],
|
||||
|
||||
"fr": [
|
||||
|
@ -592,7 +598,8 @@
|
|||
"customizeCollectionsNavBarDescription",
|
||||
"customizeButtonsUnsupportedWarning",
|
||||
"placePickerTitle",
|
||||
"albumAddMapTooltip"
|
||||
"albumAddMapTooltip",
|
||||
"fileNotFound"
|
||||
],
|
||||
|
||||
"it": [
|
||||
|
@ -649,7 +656,8 @@
|
|||
"customizeCollectionsNavBarDescription",
|
||||
"customizeButtonsUnsupportedWarning",
|
||||
"placePickerTitle",
|
||||
"albumAddMapTooltip"
|
||||
"albumAddMapTooltip",
|
||||
"fileNotFound"
|
||||
],
|
||||
|
||||
"nl": [
|
||||
|
@ -1041,6 +1049,7 @@
|
|||
"customizeButtonsUnsupportedWarning",
|
||||
"placePickerTitle",
|
||||
"albumAddMapTooltip",
|
||||
"fileNotFound",
|
||||
"errorUnauthenticated",
|
||||
"errorDisconnected",
|
||||
"errorLocked",
|
||||
|
@ -1104,7 +1113,8 @@
|
|||
"customizeCollectionsNavBarDescription",
|
||||
"customizeButtonsUnsupportedWarning",
|
||||
"placePickerTitle",
|
||||
"albumAddMapTooltip"
|
||||
"albumAddMapTooltip",
|
||||
"fileNotFound"
|
||||
],
|
||||
|
||||
"pt": [
|
||||
|
@ -1176,7 +1186,8 @@
|
|||
"customizeCollectionsNavBarDescription",
|
||||
"customizeButtonsUnsupportedWarning",
|
||||
"placePickerTitle",
|
||||
"albumAddMapTooltip"
|
||||
"albumAddMapTooltip",
|
||||
"fileNotFound"
|
||||
],
|
||||
|
||||
"ru": [
|
||||
|
@ -1228,7 +1239,8 @@
|
|||
"customizeCollectionsNavBarDescription",
|
||||
"customizeButtonsUnsupportedWarning",
|
||||
"placePickerTitle",
|
||||
"albumAddMapTooltip"
|
||||
"albumAddMapTooltip",
|
||||
"fileNotFound"
|
||||
],
|
||||
|
||||
"tr": [
|
||||
|
@ -1244,7 +1256,8 @@
|
|||
"customizeCollectionsNavBarDescription",
|
||||
"customizeButtonsUnsupportedWarning",
|
||||
"placePickerTitle",
|
||||
"albumAddMapTooltip"
|
||||
"albumAddMapTooltip",
|
||||
"fileNotFound"
|
||||
],
|
||||
|
||||
"zh": [
|
||||
|
@ -1327,7 +1340,8 @@
|
|||
"customizeCollectionsNavBarDescription",
|
||||
"customizeButtonsUnsupportedWarning",
|
||||
"placePickerTitle",
|
||||
"albumAddMapTooltip"
|
||||
"albumAddMapTooltip",
|
||||
"fileNotFound"
|
||||
],
|
||||
|
||||
"zh_Hant": [
|
||||
|
@ -1504,6 +1518,7 @@
|
|||
"customizeCollectionsNavBarDescription",
|
||||
"customizeButtonsUnsupportedWarning",
|
||||
"placePickerTitle",
|
||||
"albumAddMapTooltip"
|
||||
"albumAddMapTooltip",
|
||||
"fileNotFound"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -7,8 +7,10 @@ import 'package:flutter/services.dart';
|
|||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos/account.dart';
|
||||
import 'package:nc_photos/app_localizations.dart';
|
||||
import 'package:nc_photos/bloc_util.dart';
|
||||
import 'package:nc_photos/controller/account_controller.dart';
|
||||
import 'package:nc_photos/controller/files_controller.dart';
|
||||
import 'package:nc_photos/entity/file_descriptor.dart';
|
||||
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
|
@ -23,6 +25,7 @@ import 'package:nc_photos/widget/video_viewer.dart';
|
|||
import 'package:nc_photos/widget/viewer_mixin.dart';
|
||||
import 'package:nc_photos/widget/wakelock_util.dart';
|
||||
import 'package:np_codegen/np_codegen.dart';
|
||||
import 'package:np_common/object_util.dart';
|
||||
import 'package:np_ui/np_ui.dart';
|
||||
import 'package:to_string/to_string.dart';
|
||||
|
||||
|
@ -35,13 +38,13 @@ part 'slideshow_viewer/view.dart';
|
|||
class SlideshowViewerArguments {
|
||||
const SlideshowViewerArguments(
|
||||
this.account,
|
||||
this.files,
|
||||
this.fileIds,
|
||||
this.startIndex,
|
||||
this.config,
|
||||
);
|
||||
|
||||
final Account account;
|
||||
final List<FileDescriptor> files;
|
||||
final List<int> fileIds;
|
||||
final int startIndex;
|
||||
final SlideshowConfig config;
|
||||
}
|
||||
|
@ -59,7 +62,7 @@ class SlideshowViewer extends StatelessWidget {
|
|||
const SlideshowViewer({
|
||||
super.key,
|
||||
required this.account,
|
||||
required this.files,
|
||||
required this.fileIds,
|
||||
required this.startIndex,
|
||||
required this.config,
|
||||
});
|
||||
|
@ -68,7 +71,7 @@ class SlideshowViewer extends StatelessWidget {
|
|||
: this(
|
||||
key: key,
|
||||
account: args.account,
|
||||
files: args.files,
|
||||
fileIds: args.fileIds,
|
||||
startIndex: args.startIndex,
|
||||
config: args.config,
|
||||
);
|
||||
|
@ -77,8 +80,9 @@ class SlideshowViewer extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => _Bloc(
|
||||
filesController: context.read<AccountController>().filesController,
|
||||
account: context.read<AccountController>().account,
|
||||
files: files,
|
||||
fileIds: fileIds,
|
||||
startIndex: startIndex,
|
||||
config: config,
|
||||
)..add(const _Init()),
|
||||
|
@ -87,7 +91,7 @@ class SlideshowViewer extends StatelessWidget {
|
|||
}
|
||||
|
||||
final Account account;
|
||||
final List<FileDescriptor> files;
|
||||
final List<int> fileIds;
|
||||
final int startIndex;
|
||||
final SlideshowConfig config;
|
||||
}
|
||||
|
@ -145,7 +149,11 @@ class _WrappedSlideshowViewerState extends State<_WrappedSlideshowViewer>
|
|||
onPopInvoked: (_) {
|
||||
context.addEvent(const _RequestExit());
|
||||
},
|
||||
child: const _Body(),
|
||||
child: _BlocSelector<bool>(
|
||||
selector: (state) => state.hasInit,
|
||||
builder: (context, hasInit) =>
|
||||
hasInit ? const _Body() : const _InitBody(),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -18,6 +18,7 @@ abstract class $_StateCopyWithWorker {
|
|||
int? page,
|
||||
int? nextPage,
|
||||
bool? shouldAnimateNextPage,
|
||||
List<FileDescriptor?>? files,
|
||||
FileDescriptor? currentFile,
|
||||
bool? isShowUi,
|
||||
bool? isPlay,
|
||||
|
@ -38,7 +39,8 @@ class _$_StateCopyWithWorkerImpl implements $_StateCopyWithWorker {
|
|||
dynamic page,
|
||||
dynamic nextPage,
|
||||
dynamic shouldAnimateNextPage,
|
||||
dynamic currentFile,
|
||||
dynamic files,
|
||||
dynamic currentFile = copyWithNull,
|
||||
dynamic isShowUi,
|
||||
dynamic isPlay,
|
||||
dynamic isVideoCompleted,
|
||||
|
@ -53,7 +55,10 @@ class _$_StateCopyWithWorkerImpl implements $_StateCopyWithWorker {
|
|||
nextPage: nextPage as int? ?? that.nextPage,
|
||||
shouldAnimateNextPage:
|
||||
shouldAnimateNextPage as bool? ?? that.shouldAnimateNextPage,
|
||||
currentFile: currentFile as FileDescriptor? ?? that.currentFile,
|
||||
files: files as List<FileDescriptor?>? ?? that.files,
|
||||
currentFile: currentFile == copyWithNull
|
||||
? that.currentFile
|
||||
: currentFile as FileDescriptor?,
|
||||
isShowUi: isShowUi as bool? ?? that.isShowUi,
|
||||
isPlay: isPlay as bool? ?? that.isPlay,
|
||||
isVideoCompleted: isVideoCompleted as bool? ?? that.isVideoCompleted,
|
||||
|
@ -104,7 +109,7 @@ extension _$_PageViewNpLog on _PageView {
|
|||
extension _$_StateToString on _State {
|
||||
String _$toString() {
|
||||
// ignore: unnecessary_string_interpolations
|
||||
return "_State {hasInit: $hasInit, page: $page, nextPage: $nextPage, shouldAnimateNextPage: $shouldAnimateNextPage, currentFile: ${currentFile.fdPath}, isShowUi: $isShowUi, isPlay: $isPlay, isVideoCompleted: $isVideoCompleted, hasPrev: $hasPrev, hasNext: $hasNext, isShowTimeline: $isShowTimeline, hasShownTimeline: $hasShownTimeline, hasRequestExit: $hasRequestExit}";
|
||||
return "_State {hasInit: $hasInit, page: $page, nextPage: $nextPage, shouldAnimateNextPage: $shouldAnimateNextPage, files: [length: ${files.length}], currentFile: ${currentFile == null ? null : "${currentFile!.fdPath}"}, isShowUi: $isShowUi, isPlay: $isPlay, isVideoCompleted: $isVideoCompleted, hasPrev: $hasPrev, hasNext: $hasNext, isShowTimeline: $isShowTimeline, hasShownTimeline: $hasShownTimeline, hasRequestExit: $hasRequestExit}";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,6 +120,13 @@ extension _$_InitToString on _Init {
|
|||
}
|
||||
}
|
||||
|
||||
extension _$_SetFilesToString on _SetFiles {
|
||||
String _$toString() {
|
||||
// ignore: unnecessary_string_interpolations
|
||||
return "_SetFiles {dataMap: {length: ${dataMap.length}}}";
|
||||
}
|
||||
}
|
||||
|
||||
extension _$_ToggleShowUiToString on _ToggleShowUi {
|
||||
String _$toString() {
|
||||
// ignore: unnecessary_string_interpolations
|
||||
|
|
|
@ -3,14 +3,14 @@ part of '../slideshow_viewer.dart';
|
|||
@npLog
|
||||
class _Bloc extends Bloc<_Event, _State> with BlocLogger {
|
||||
_Bloc({
|
||||
required this.filesController,
|
||||
required this.account,
|
||||
required this.files,
|
||||
required this.fileIds,
|
||||
required this.startIndex,
|
||||
required this.config,
|
||||
}) : super(_State.init(
|
||||
initialFile: files[startIndex],
|
||||
)) {
|
||||
}) : super(_State.init()) {
|
||||
on<_Init>(_onInit);
|
||||
on<_SetFiles>(_onSetFiles);
|
||||
on<_ToggleShowUi>(_onToggleShowUi);
|
||||
on<_PreloadSidePages>(_onPreloadSidePages);
|
||||
on<_VideoCompleted>(_onVideoCompleted);
|
||||
|
@ -23,6 +23,10 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
|
|||
on<_ToggleTimeline>(_onToggleTimeline);
|
||||
on<_RequestPage>(_onRequestPage);
|
||||
on<_RequestExit>(_onRequestExit);
|
||||
|
||||
_subscriptions.add(filesController.stream.listen((event) {
|
||||
add(_SetFiles(event.dataMap));
|
||||
}));
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -40,24 +44,27 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
|
|||
/// Convert the page index to the corresponding item index
|
||||
int convertPageToFileIndex(int pageIndex) {
|
||||
if (config.isShuffle) {
|
||||
final i = pageIndex ~/ files.length;
|
||||
final i = pageIndex ~/ fileIds.length;
|
||||
if (!_shuffledIndex.containsKey(i)) {
|
||||
final index = [for (var i = 0; i < files.length; ++i) i];
|
||||
final index = [for (var i = 0; i < fileIds.length; ++i) i];
|
||||
_shuffledIndex[i] = index..shuffle();
|
||||
}
|
||||
return _shuffledIndex[i]![pageIndex % files.length];
|
||||
return _shuffledIndex[i]![pageIndex % fileIds.length];
|
||||
} else {
|
||||
return _shuffledIndex[0]![pageIndex % files.length];
|
||||
return _shuffledIndex[0]![pageIndex % fileIds.length];
|
||||
}
|
||||
}
|
||||
|
||||
FileDescriptor getFileByPageIndex(int pageIndex) =>
|
||||
files[convertPageToFileIndex(pageIndex)];
|
||||
FileDescriptor? getFileByPageIndex(int pageIndex) =>
|
||||
state.files[convertPageToFileIndex(pageIndex)];
|
||||
|
||||
void _onInit(_Init ev, Emitter<_State> emit) {
|
||||
Future<void> _onInit(_Init ev, Emitter<_State> emit) async {
|
||||
_log.info(ev);
|
||||
// needed for now because some pages (e.g., search) haven't yet migrated
|
||||
await filesController.queryByFileId(fileIds);
|
||||
|
||||
final parsedConfig = _parseConfig(
|
||||
files: files,
|
||||
fileIds: fileIds,
|
||||
startIndex: startIndex,
|
||||
config: config,
|
||||
);
|
||||
|
@ -71,7 +78,16 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
|
|||
hasPrev: initialPage > 0,
|
||||
hasNext: pageCount == null || initialPage < (pageCount! - 1),
|
||||
));
|
||||
_prepareNextPage();
|
||||
unawaited(_prepareNextPage());
|
||||
}
|
||||
|
||||
void _onSetFiles(_SetFiles ev, Emitter<_State> emit) {
|
||||
_log.info(ev);
|
||||
final files = fileIds.map((e) => ev.dataMap[e]).toList();
|
||||
emit(state.copyWith(
|
||||
files: files,
|
||||
currentFile: files[convertPageToFileIndex(state.page)],
|
||||
));
|
||||
}
|
||||
|
||||
void _onToggleShowUi(_ToggleShowUi ev, Emitter<_State> emit) {
|
||||
|
@ -96,16 +112,14 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
|
|||
}
|
||||
_log.info("[_onPreloadSidePages] Pre-loading nearby images");
|
||||
if (ev.center > 0) {
|
||||
final fileIndex = convertPageToFileIndex(ev.center - 1);
|
||||
final prevFile = files[fileIndex];
|
||||
if (file_util.isSupportedImageFormat(prevFile)) {
|
||||
final prevFile = getFileByPageIndex(ev.center - 1);
|
||||
if (prevFile != null && file_util.isSupportedImageFormat(prevFile)) {
|
||||
RemoteImageViewer.preloadImage(account, prevFile);
|
||||
}
|
||||
}
|
||||
if (pageCount == null || ev.center + 1 < pageCount!) {
|
||||
final fileIndex = convertPageToFileIndex(ev.center + 1);
|
||||
final nextFile = files[fileIndex];
|
||||
if (file_util.isSupportedImageFormat(nextFile)) {
|
||||
final nextFile = getFileByPageIndex(ev.center + 1);
|
||||
if (nextFile != null && file_util.isSupportedImageFormat(nextFile)) {
|
||||
RemoteImageViewer.preloadImage(account, nextFile);
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +142,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
|
|||
|
||||
void _onSetPlay(_SetPlay ev, Emitter<_State> emit) {
|
||||
_log.info(ev);
|
||||
if (file_util.isSupportedVideoFormat(state.currentFile)) {
|
||||
if (state.currentFile?.let(file_util.isSupportedVideoFormat) == true) {
|
||||
// only start the countdown if the video completed
|
||||
if (state.isVideoCompleted) {
|
||||
_pageChangeTimer?.cancel();
|
||||
|
@ -196,12 +210,12 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
|
|||
}
|
||||
|
||||
static ({List<int> shuffled, int initial, int? count}) _parseConfig({
|
||||
required List<FileDescriptor> files,
|
||||
required List<int> fileIds,
|
||||
required int startIndex,
|
||||
required SlideshowConfig config,
|
||||
}) {
|
||||
final index = [for (var i = 0; i < files.length; ++i) i];
|
||||
final count = config.isRepeat ? null : files.length;
|
||||
final index = [for (var i = 0; i < fileIds.length; ++i) i];
|
||||
final count = config.isRepeat ? null : fileIds.length;
|
||||
if (config.isShuffle) {
|
||||
return (
|
||||
shuffled: index..shuffle(),
|
||||
|
@ -211,7 +225,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
|
|||
} else if (config.isReverse) {
|
||||
return (
|
||||
shuffled: index.reversed.toList(),
|
||||
initial: files.length - 1 - startIndex,
|
||||
initial: fileIds.length - 1 - startIndex,
|
||||
count: count,
|
||||
);
|
||||
} else {
|
||||
|
@ -224,8 +238,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
|
|||
}
|
||||
|
||||
Future<void> _prepareNextPage() async {
|
||||
final file = state.currentFile;
|
||||
if (file_util.isSupportedVideoFormat(file)) {
|
||||
if (state.currentFile?.let(file_util.isSupportedVideoFormat) == true) {
|
||||
// for videos, we need to wait until it's ended
|
||||
return;
|
||||
}
|
||||
|
@ -264,8 +277,9 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
|
|||
add(_NextPage(nextPage));
|
||||
}
|
||||
|
||||
final FilesController filesController;
|
||||
final Account account;
|
||||
final List<FileDescriptor> files;
|
||||
final List<int> fileIds;
|
||||
final int startIndex;
|
||||
final SlideshowConfig config;
|
||||
|
||||
|
|
|
@ -8,7 +8,8 @@ class _State {
|
|||
required this.page,
|
||||
required this.nextPage,
|
||||
required this.shouldAnimateNextPage,
|
||||
required this.currentFile,
|
||||
required this.files,
|
||||
this.currentFile,
|
||||
required this.isShowUi,
|
||||
required this.isPlay,
|
||||
required this.isVideoCompleted,
|
||||
|
@ -19,15 +20,12 @@ class _State {
|
|||
required this.hasRequestExit,
|
||||
});
|
||||
|
||||
factory _State.init({
|
||||
required FileDescriptor initialFile,
|
||||
}) =>
|
||||
_State(
|
||||
factory _State.init() => const _State(
|
||||
hasInit: false,
|
||||
page: 0,
|
||||
nextPage: 0,
|
||||
shouldAnimateNextPage: true,
|
||||
currentFile: initialFile,
|
||||
files: [],
|
||||
isShowUi: false,
|
||||
isPlay: true,
|
||||
isVideoCompleted: false,
|
||||
|
@ -45,7 +43,8 @@ class _State {
|
|||
final int page;
|
||||
final int nextPage;
|
||||
final bool shouldAnimateNextPage;
|
||||
final FileDescriptor currentFile;
|
||||
final List<FileDescriptor?> files;
|
||||
final FileDescriptor? currentFile;
|
||||
final bool isShowUi;
|
||||
final bool isPlay;
|
||||
final bool isVideoCompleted;
|
||||
|
@ -66,6 +65,16 @@ class _Init implements _Event {
|
|||
String toString() => _$toString();
|
||||
}
|
||||
|
||||
@toString
|
||||
class _SetFiles implements _Event {
|
||||
const _SetFiles(this.dataMap);
|
||||
|
||||
@override
|
||||
String toString() => _$toString();
|
||||
|
||||
final Map<int, FileDescriptor> dataMap;
|
||||
}
|
||||
|
||||
@toString
|
||||
class _ToggleShowUi implements _Event {
|
||||
const _ToggleShowUi();
|
||||
|
|
|
@ -87,11 +87,24 @@ class _TimelineItem extends StatelessWidget {
|
|||
color: isSelected
|
||||
? Theme.of(context).colorScheme.secondaryContainer
|
||||
: Colors.transparent,
|
||||
child: PhotoListImage(
|
||||
child: file != null
|
||||
? PhotoListImage(
|
||||
account: context.bloc.account,
|
||||
previewUrl: NetworkRectThumbnail.imageUrlForFile(
|
||||
context.bloc.account,
|
||||
file,
|
||||
file!,
|
||||
),
|
||||
)
|
||||
: AspectRatio(
|
||||
aspectRatio: 1,
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: Text(
|
||||
L10n.global().fileNotFound,
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -111,6 +124,6 @@ class _TimelineItem extends StatelessWidget {
|
|||
}
|
||||
|
||||
final int index;
|
||||
final FileDescriptor file;
|
||||
final FileDescriptor? file;
|
||||
final bool isSelected;
|
||||
}
|
||||
|
|
|
@ -129,6 +129,31 @@ class _ControlBar extends StatelessWidget {
|
|||
}
|
||||
}
|
||||
|
||||
class _InitBody extends StatelessWidget {
|
||||
const _InitBody();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
children: [
|
||||
const Center(child: CircularProgressIndicator()),
|
||||
Positioned.directional(
|
||||
textDirection: Directionality.of(context),
|
||||
top: 0,
|
||||
start: 0,
|
||||
child: IconButton(
|
||||
icon: const Icon(Icons.close),
|
||||
tooltip: MaterialLocalizations.of(context).closeButtonTooltip,
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@npLog
|
||||
class _Body extends StatelessWidget {
|
||||
const _Body();
|
||||
|
@ -259,7 +284,17 @@ class _PageView extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final file = context.bloc.files[itemIndex];
|
||||
return _BlocSelector<FileDescriptor?>(
|
||||
selector: (state) => state.files[itemIndex],
|
||||
builder: (context, file) {
|
||||
if (file == null) {
|
||||
return Center(
|
||||
child: Text(
|
||||
L10n.global().fileNotFound,
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
);
|
||||
}
|
||||
if (file_util.isSupportedImageFormat(file)) {
|
||||
return _ImagePageView(
|
||||
file: file,
|
||||
|
@ -278,6 +313,8 @@ class _PageView extends StatelessWidget {
|
|||
_log.shout("[build] Unknown file format: ${file.fdMime}");
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
final int page;
|
||||
|
|
|
@ -254,7 +254,7 @@ class _WrappedViewerState extends State<_WrappedViewer>
|
|||
SlideshowViewer.routeName,
|
||||
arguments: SlideshowViewerArguments(
|
||||
slideshowRequest.value!.account,
|
||||
slideshowRequest.value!.files,
|
||||
slideshowRequest.value!.fileIds,
|
||||
slideshowRequest.value!.startIndex,
|
||||
result,
|
||||
),
|
||||
|
|
|
@ -343,14 +343,11 @@ class _Bloc extends Bloc<_Event, _State>
|
|||
|
||||
void _onStartSlideshow(_StartSlideshow ev, _Emitter emit) {
|
||||
_log.info(ev);
|
||||
final files =
|
||||
state.fileIdOrders.map((id) => state.files[id]).nonNulls.toList();
|
||||
final req = _SlideshowRequest(
|
||||
account: account,
|
||||
files: files,
|
||||
startIndex: files
|
||||
.indexWhere((e) => e.fdId == ev.fileId)
|
||||
.let((i) => i == -1 ? 0 : i),
|
||||
fileIds: state.fileIdOrders,
|
||||
startIndex:
|
||||
state.fileIdOrders.indexOf(ev.fileId).let((i) => i == -1 ? 0 : i),
|
||||
);
|
||||
emit(state.copyWith(slideshowRequest: Unique(req)));
|
||||
}
|
||||
|
|
|
@ -15,12 +15,12 @@ class _ShareRequest {
|
|||
class _SlideshowRequest {
|
||||
const _SlideshowRequest({
|
||||
required this.account,
|
||||
required this.files,
|
||||
required this.fileIds,
|
||||
required this.startIndex,
|
||||
});
|
||||
|
||||
final Account account;
|
||||
final List<FileDescriptor> files;
|
||||
final List<int> fileIds;
|
||||
final int startIndex;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue