Fix Viewer not working with shared files in NcAlbum

This commit is contained in:
Ming Ming 2024-12-12 01:32:28 +08:00
parent 0ded662de5
commit 71201dab74
9 changed files with 152 additions and 159 deletions

View file

@ -7,7 +7,6 @@ import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart'; import 'package:nc_photos/account.dart';
import 'package:nc_photos/bloc_util.dart'; import 'package:nc_photos/bloc_util.dart';
import 'package:nc_photos/controller/account_controller.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_descriptor.dart';
import 'package:nc_photos/entity/file_util.dart' as file_util; import 'package:nc_photos/entity/file_util.dart' as file_util;
import 'package:nc_photos/exception_event.dart'; import 'package:nc_photos/exception_event.dart';
@ -29,7 +28,7 @@ part 'file_content_view/view.dart';
class FileContentView extends StatefulWidget { class FileContentView extends StatefulWidget {
const FileContentView({ const FileContentView({
super.key, super.key,
required this.fileId, required this.file,
required this.shouldPlayLivePhoto, required this.shouldPlayLivePhoto,
required this.canZoom, required this.canZoom,
required this.canPlay, required this.canPlay,
@ -43,7 +42,7 @@ class FileContentView extends StatefulWidget {
@override @override
State<StatefulWidget> createState() => _FileContentViewState(); State<StatefulWidget> createState() => _FileContentViewState();
final int fileId; final FileDescriptor file;
final bool shouldPlayLivePhoto; final bool shouldPlayLivePhoto;
final bool canZoom; final bool canZoom;
final bool canPlay; final bool canPlay;
@ -60,8 +59,7 @@ class _FileContentViewState extends State<FileContentView> {
super.initState(); super.initState();
_bloc = _Bloc( _bloc = _Bloc(
account: context.read<AccountController>().account, account: context.read<AccountController>().account,
filesController: context.read<AccountController>().filesController, file: widget.file,
fileId: widget.fileId,
shouldPlayLivePhoto: widget.shouldPlayLivePhoto, shouldPlayLivePhoto: widget.shouldPlayLivePhoto,
canZoom: widget.canZoom, canZoom: widget.canZoom,
canPlay: widget.canPlay, canPlay: widget.canPlay,
@ -135,40 +133,33 @@ class _WrappedFileContentView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return _BlocSelector( final file = context.bloc.file;
selector: (state) => state.file, if (file_util.isSupportedImageFormat(file)) {
builder: (context, file) { return _BlocSelector(
if (file == null) { selector: (state) => state.shouldPlayLivePhoto,
_log.severe("[build] File is null"); builder: (context, shouldPlayLivePhoto) {
return Container(); if (shouldPlayLivePhoto) {
} else if (file_util.isSupportedImageFormat(file)) { final livePhotoType = getLivePhotoTypeFromFile(file);
return _BlocSelector( if (livePhotoType != null) {
selector: (state) => state.shouldPlayLivePhoto, return _LivePhotoPageContentView(
builder: (context, shouldPlayLivePhoto) { livePhotoType: livePhotoType,
if (shouldPlayLivePhoto) { );
final livePhotoType = getLivePhotoTypeFromFile(file); } else {
if (livePhotoType != null) { _log.warning("[build] Not a live photo");
return _LivePhotoPageContentView( return const _PhotoPageContentView();
livePhotoType: livePhotoType, }
); } else {
} else { return const _PhotoPageContentView();
_log.warning("[build] Not a live photo"); }
return const _PhotoPageContentView(); },
} );
} else { } else if (file_util.isSupportedVideoFormat(file)) {
return const _PhotoPageContentView(); return const _VideoPageContentView();
} } else {
}, _log.shout("[build] Unknown file format: ${file.fdMime}");
); // _pageStates[index]!.itemHeight = 0;
} else if (file_util.isSupportedVideoFormat(file)) { return Container();
return const _VideoPageContentView(); }
} else {
_log.shout("[build] Unknown file format: ${file.fdMime}");
// _pageStates[index]!.itemHeight = 0;
return Container();
}
},
);
} }
} }

View file

@ -14,8 +14,7 @@ part of 'file_content_view.dart';
abstract class $_StateCopyWithWorker { abstract class $_StateCopyWithWorker {
_State call( _State call(
{FileDescriptor? file, {bool? shouldPlayLivePhoto,
bool? shouldPlayLivePhoto,
bool? canZoom, bool? canZoom,
bool? canPlay, bool? canPlay,
bool? isPlayControlVisible, bool? isPlayControlVisible,
@ -32,8 +31,7 @@ class _$_StateCopyWithWorkerImpl implements $_StateCopyWithWorker {
@override @override
_State call( _State call(
{dynamic file = copyWithNull, {dynamic shouldPlayLivePhoto,
dynamic shouldPlayLivePhoto,
dynamic canZoom, dynamic canZoom,
dynamic canPlay, dynamic canPlay,
dynamic isPlayControlVisible, dynamic isPlayControlVisible,
@ -44,7 +42,6 @@ class _$_StateCopyWithWorkerImpl implements $_StateCopyWithWorker {
dynamic contentHeight = copyWithNull, dynamic contentHeight = copyWithNull,
dynamic error = copyWithNull}) { dynamic error = copyWithNull}) {
return _State( return _State(
file: file == copyWithNull ? that.file : file as FileDescriptor?,
shouldPlayLivePhoto: shouldPlayLivePhoto:
shouldPlayLivePhoto as bool? ?? that.shouldPlayLivePhoto, shouldPlayLivePhoto as bool? ?? that.shouldPlayLivePhoto,
canZoom: canZoom as bool? ?? that.canZoom, canZoom: canZoom as bool? ?? that.canZoom,
@ -102,14 +99,7 @@ extension _$_BlocNpLog on _Bloc {
extension _$_StateToString on _State { extension _$_StateToString on _State {
String _$toString() { String _$toString() {
// ignore: unnecessary_string_interpolations // ignore: unnecessary_string_interpolations
return "_State {file: ${file == null ? null : "${file!.fdPath}"}, shouldPlayLivePhoto: $shouldPlayLivePhoto, canZoom: $canZoom, canPlay: $canPlay, isPlayControlVisible: $isPlayControlVisible, isLoaded: $isLoaded, isZoomed: $isZoomed, isPlaying: $isPlaying, isLivePhotoLoadFailed: $isLivePhotoLoadFailed, contentHeight: ${contentHeight == null ? null : "${contentHeight!.toStringAsFixed(3)}"}, error: $error}"; return "_State {shouldPlayLivePhoto: $shouldPlayLivePhoto, canZoom: $canZoom, canPlay: $canPlay, isPlayControlVisible: $isPlayControlVisible, isLoaded: $isLoaded, isZoomed: $isZoomed, isPlaying: $isPlaying, isLivePhotoLoadFailed: $isLivePhotoLoadFailed, contentHeight: ${contentHeight == null ? null : "${contentHeight!.toStringAsFixed(3)}"}, error: $error}";
}
}
extension _$_SetFileToString on _SetFile {
String _$toString() {
// ignore: unnecessary_string_interpolations
return "_SetFile {value: ${value == null ? null : "${value!.fdPath}"}}";
} }
} }

View file

@ -4,20 +4,17 @@ part of '../file_content_view.dart';
class _Bloc extends Bloc<_Event, _State> with BlocLogger { class _Bloc extends Bloc<_Event, _State> with BlocLogger {
_Bloc({ _Bloc({
required this.account, required this.account,
required this.filesController, required this.file,
required this.fileId,
required bool shouldPlayLivePhoto, required bool shouldPlayLivePhoto,
required bool canZoom, required bool canZoom,
required bool canPlay, required bool canPlay,
required bool isPlayControlVisible, required bool isPlayControlVisible,
}) : super(_State.init( }) : super(_State.init(
file: filesController.stream.value.dataMap[fileId],
shouldPlayLivePhoto: shouldPlayLivePhoto, shouldPlayLivePhoto: shouldPlayLivePhoto,
canZoom: canZoom, canZoom: canZoom,
canPlay: canPlay, canPlay: canPlay,
isPlayControlVisible: isPlayControlVisible, isPlayControlVisible: isPlayControlVisible,
)) { )) {
on<_SetFile>(_onSetFile);
on<_SetShouldPlayLivePhoto>(_onSetShouldPlayLivePhoto); on<_SetShouldPlayLivePhoto>(_onSetShouldPlayLivePhoto);
on<_SetCanZoom>(_onSetCanZoom); on<_SetCanZoom>(_onSetCanZoom);
on<_SetCanPlay>(_onSetCanPlay); on<_SetCanPlay>(_onSetCanPlay);
@ -30,13 +27,6 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
on<_SetLivePhotoLoadFailed>(_onSetLivePhotoLoadFailed); on<_SetLivePhotoLoadFailed>(_onSetLivePhotoLoadFailed);
on<_SetError>(_onSetError); on<_SetError>(_onSetError);
_subscriptions.add(filesController.stream.listen((ev) {
add(_SetFile(ev.dataMap[fileId]));
}));
_subscriptions.add(filesController.errorStream.listen((ev) {
add(_SetError(ev.error, ev.stackTrace));
}));
} }
@override @override
@ -63,11 +53,6 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
super.onError(error, stackTrace); super.onError(error, stackTrace);
} }
void _onSetFile(_SetFile ev, _Emitter emit) {
_log.info(ev);
emit(state.copyWith(file: ev.value));
}
void _onSetShouldPlayLivePhoto(_SetShouldPlayLivePhoto ev, _Emitter emit) { void _onSetShouldPlayLivePhoto(_SetShouldPlayLivePhoto ev, _Emitter emit) {
_log.info(ev); _log.info(ev);
emit(state.copyWith(shouldPlayLivePhoto: ev.value)); emit(state.copyWith(shouldPlayLivePhoto: ev.value));
@ -127,8 +112,7 @@ class _Bloc extends Bloc<_Event, _State> with BlocLogger {
} }
final Account account; final Account account;
final FilesController filesController; final FileDescriptor file;
final int fileId;
final _subscriptions = <StreamSubscription>[]; final _subscriptions = <StreamSubscription>[];
var _isHandlingError = false; var _isHandlingError = false;

View file

@ -4,7 +4,6 @@ part of '../file_content_view.dart';
@toString @toString
class _State { class _State {
const _State({ const _State({
required this.file,
required this.shouldPlayLivePhoto, required this.shouldPlayLivePhoto,
required this.canZoom, required this.canZoom,
required this.canPlay, required this.canPlay,
@ -18,14 +17,12 @@ class _State {
}); });
factory _State.init({ factory _State.init({
required FileDescriptor? file,
required bool shouldPlayLivePhoto, required bool shouldPlayLivePhoto,
required bool canZoom, required bool canZoom,
required bool canPlay, required bool canPlay,
required bool isPlayControlVisible, required bool isPlayControlVisible,
}) => }) =>
_State( _State(
file: file,
shouldPlayLivePhoto: shouldPlayLivePhoto, shouldPlayLivePhoto: shouldPlayLivePhoto,
canZoom: canZoom, canZoom: canZoom,
canPlay: canPlay, canPlay: canPlay,
@ -39,7 +36,6 @@ class _State {
@override @override
String toString() => _$toString(); String toString() => _$toString();
final FileDescriptor? file;
final bool shouldPlayLivePhoto; final bool shouldPlayLivePhoto;
final bool canZoom; final bool canZoom;
final bool canPlay; final bool canPlay;
@ -55,16 +51,6 @@ class _State {
abstract class _Event {} abstract class _Event {}
@toString
class _SetFile implements _Event {
const _SetFile(this.value);
@override
String toString() => _$toString();
final FileDescriptor? value;
}
@toString @toString
class _SetShouldPlayLivePhoto implements _Event { class _SetShouldPlayLivePhoto implements _Event {
const _SetShouldPlayLivePhoto(this.value); const _SetShouldPlayLivePhoto(this.value);

View file

@ -8,25 +8,22 @@ class _LivePhotoPageContentView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return _BlocBuilder( return _BlocBuilder(
buildWhen: (previous, current) => buildWhen: (previous, current) => previous.canPlay != current.canPlay,
previous.file != current.file || previous.canPlay != current.canPlay, builder: (context, state) => LivePhotoViewer(
builder: (context, state) => state.file == null account: context.bloc.account,
? Container() file: context.bloc.file,
: LivePhotoViewer( livePhotoType: livePhotoType,
account: context.bloc.account, canPlay: state.canPlay,
file: state.file!, onLoaded: () {
livePhotoType: livePhotoType, context.addEvent(const _SetLoaded());
canPlay: state.canPlay, },
onLoaded: () { onHeightChanged: (height) {
context.addEvent(const _SetLoaded()); context.addEvent(_SetContentHeight(height));
}, },
onHeightChanged: (height) { onLoadFailure: () {
context.addEvent(_SetContentHeight(height)); context.addEvent(const _SetLivePhotoLoadFailed());
}, },
onLoadFailure: () { ),
context.addEvent(const _SetLivePhotoLoadFailed());
},
),
); );
} }
@ -39,27 +36,24 @@ class _PhotoPageContentView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return _BlocBuilder( return _BlocBuilder(
buildWhen: (previous, current) => buildWhen: (previous, current) => previous.canZoom != current.canZoom,
previous.file != current.file || previous.canZoom != current.canZoom, builder: (context, state) => RemoteImageViewer(
builder: (context, state) => state.file == null account: context.bloc.account,
? Container() file: context.bloc.file,
: RemoteImageViewer( canZoom: state.canZoom,
account: context.bloc.account, onLoaded: () {
file: state.file!, context.addEvent(const _SetLoaded());
canZoom: state.canZoom, },
onLoaded: () { onHeightChanged: (height) {
context.addEvent(const _SetLoaded()); context.addEvent(_SetContentHeight(height));
}, },
onHeightChanged: (height) { onZoomStarted: () {
context.addEvent(_SetContentHeight(height)); context.addEvent(const _SetIsZoomed(true));
}, },
onZoomStarted: () { onZoomEnded: () {
context.addEvent(const _SetIsZoomed(true)); context.addEvent(const _SetIsZoomed(false));
}, },
onZoomEnded: () { ),
context.addEvent(const _SetIsZoomed(false));
},
),
); );
} }
} }
@ -71,37 +65,34 @@ class _VideoPageContentView extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return _BlocBuilder( return _BlocBuilder(
buildWhen: (previous, current) => buildWhen: (previous, current) =>
previous.file != current.file ||
previous.canZoom != current.canZoom || previous.canZoom != current.canZoom ||
previous.isPlayControlVisible != current.isPlayControlVisible || previous.isPlayControlVisible != current.isPlayControlVisible ||
previous.canPlay != current.canPlay, previous.canPlay != current.canPlay,
builder: (context, state) => state.file == null builder: (context, state) => VideoViewer(
? Container() account: context.bloc.account,
: VideoViewer( file: context.bloc.file,
account: context.bloc.account, canZoom: state.canZoom,
file: state.file!, canPlay: state.canPlay,
canZoom: state.canZoom, isControlVisible: state.isPlayControlVisible,
canPlay: state.canPlay, onLoaded: () {
isControlVisible: state.isPlayControlVisible, context.addEvent(const _SetLoaded());
onLoaded: () { },
context.addEvent(const _SetLoaded()); onHeightChanged: (height) {
}, context.addEvent(_SetContentHeight(height));
onHeightChanged: (height) { },
context.addEvent(_SetContentHeight(height)); onZoomStarted: () {
}, context.addEvent(const _SetIsZoomed(true));
onZoomStarted: () { },
context.addEvent(const _SetIsZoomed(true)); onZoomEnded: () {
}, context.addEvent(const _SetIsZoomed(false));
onZoomEnded: () { },
context.addEvent(const _SetIsZoomed(false)); onPlay: () {
}, context.addEvent(const _SetPlaying());
onPlay: () { },
context.addEvent(const _SetPlaying()); onPause: () {
}, context.addEvent(const _SetPause());
onPause: () { },
context.addEvent(const _SetPause()); ),
},
),
); );
} }
} }

View file

@ -15,6 +15,7 @@ part of 'viewer.dart';
abstract class $_StateCopyWithWorker { abstract class $_StateCopyWithWorker {
_State call( _State call(
{List<int>? fileIdOrders, {List<int>? fileIdOrders,
Map<int, FileDescriptor>? rawFiles,
Map<int, FileDescriptor>? files, Map<int, FileDescriptor>? files,
Map<int, _PageState>? fileStates, Map<int, _PageState>? fileStates,
int? index, int? index,
@ -22,7 +23,7 @@ abstract class $_StateCopyWithWorker {
_PageState? currentFileState, _PageState? currentFileState,
Collection? collection, Collection? collection,
CollectionItemsController? collectionItemsController, CollectionItemsController? collectionItemsController,
Map<int, CollectionItem>? collectionItems, Map<int, CollectionFileItem>? collectionItems,
bool? isShowDetailPane, bool? isShowDetailPane,
bool? isClosingDetailPane, bool? isClosingDetailPane,
bool? isDetailPaneActive, bool? isDetailPaneActive,
@ -48,6 +49,7 @@ class _$_StateCopyWithWorkerImpl implements $_StateCopyWithWorker {
@override @override
_State call( _State call(
{dynamic fileIdOrders, {dynamic fileIdOrders,
dynamic rawFiles,
dynamic files, dynamic files,
dynamic fileStates, dynamic fileStates,
dynamic index, dynamic index,
@ -75,6 +77,7 @@ class _$_StateCopyWithWorkerImpl implements $_StateCopyWithWorker {
dynamic error = copyWithNull}) { dynamic error = copyWithNull}) {
return _State( return _State(
fileIdOrders: fileIdOrders as List<int>? ?? that.fileIdOrders, fileIdOrders: fileIdOrders as List<int>? ?? that.fileIdOrders,
rawFiles: rawFiles as Map<int, FileDescriptor>? ?? that.rawFiles,
files: files as Map<int, FileDescriptor>? ?? that.files, files: files as Map<int, FileDescriptor>? ?? that.files,
fileStates: fileStates as Map<int, _PageState>? ?? that.fileStates, fileStates: fileStates as Map<int, _PageState>? ?? that.fileStates,
index: index as int? ?? that.index, index: index as int? ?? that.index,
@ -92,7 +95,7 @@ class _$_StateCopyWithWorkerImpl implements $_StateCopyWithWorker {
: collectionItemsController as CollectionItemsController?, : collectionItemsController as CollectionItemsController?,
collectionItems: collectionItems == copyWithNull collectionItems: collectionItems == copyWithNull
? that.collectionItems ? that.collectionItems
: collectionItems as Map<int, CollectionItem>?, : collectionItems as Map<int, CollectionFileItem>?,
isShowDetailPane: isShowDetailPane as bool? ?? that.isShowDetailPane, isShowDetailPane: isShowDetailPane as bool? ?? that.isShowDetailPane,
isClosingDetailPane: isClosingDetailPane:
isClosingDetailPane as bool? ?? that.isClosingDetailPane, isClosingDetailPane as bool? ?? that.isClosingDetailPane,
@ -206,7 +209,7 @@ extension _$_PageViewStateNpLog on _PageViewState {
extension _$_StateToString on _State { extension _$_StateToString on _State {
String _$toString() { String _$toString() {
// ignore: unnecessary_string_interpolations // ignore: unnecessary_string_interpolations
return "_State {fileIdOrders: $fileIdOrders, files: {length: ${files.length}}, fileStates: {length: ${fileStates.length}}, index: $index, currentFile: ${currentFile == null ? null : "${currentFile!.fdPath}"}, currentFileState: $currentFileState, collection: $collection, collectionItemsController: $collectionItemsController, collectionItems: ${collectionItems == null ? null : "{length: ${collectionItems!.length}}"}, isShowDetailPane: $isShowDetailPane, isClosingDetailPane: $isClosingDetailPane, isDetailPaneActive: $isDetailPaneActive, openDetailPaneRequest: $openDetailPaneRequest, closeDetailPane: $closeDetailPane, isZoomed: $isZoomed, isInitialLoad: $isInitialLoad, isShowAppBar: $isShowAppBar, appBarButtons: [length: ${appBarButtons.length}], bottomAppBarButtons: [length: ${bottomAppBarButtons.length}], pendingRemovePage: $pendingRemovePage, imageEditorRequest: $imageEditorRequest, imageEnhancerRequest: $imageEnhancerRequest, shareRequest: $shareRequest, slideshowRequest: $slideshowRequest, setAsRequest: $setAsRequest, error: $error}"; return "_State {fileIdOrders: $fileIdOrders, rawFiles: {length: ${rawFiles.length}}, files: {length: ${files.length}}, fileStates: {length: ${fileStates.length}}, index: $index, currentFile: ${currentFile == null ? null : "${currentFile!.fdPath}"}, currentFileState: $currentFileState, collection: $collection, collectionItemsController: $collectionItemsController, collectionItems: ${collectionItems == null ? null : "{length: ${collectionItems!.length}}"}, isShowDetailPane: $isShowDetailPane, isClosingDetailPane: $isClosingDetailPane, isDetailPaneActive: $isDetailPaneActive, openDetailPaneRequest: $openDetailPaneRequest, closeDetailPane: $closeDetailPane, isZoomed: $isZoomed, isInitialLoad: $isInitialLoad, isShowAppBar: $isShowAppBar, appBarButtons: [length: ${appBarButtons.length}], bottomAppBarButtons: [length: ${bottomAppBarButtons.length}], pendingRemovePage: $pendingRemovePage, imageEditorRequest: $imageEditorRequest, imageEnhancerRequest: $imageEnhancerRequest, shareRequest: $shareRequest, slideshowRequest: $slideshowRequest, setAsRequest: $setAsRequest, error: $error}";
} }
} }
@ -252,6 +255,13 @@ extension _$_SetCollectionItemsToString on _SetCollectionItems {
} }
} }
extension _$_MergeFilesToString on _MergeFiles {
String _$toString() {
// ignore: unnecessary_string_interpolations
return "_MergeFiles {}";
}
}
extension _$_ToggleAppBarToString on _ToggleAppBar { extension _$_ToggleAppBarToString on _ToggleAppBar {
String _$toString() { String _$toString() {
// ignore: unnecessary_string_interpolations // ignore: unnecessary_string_interpolations

View file

@ -26,6 +26,7 @@ class _Bloc extends Bloc<_Event, _State>
on<_RequestPage>(_onRequestPage); on<_RequestPage>(_onRequestPage);
on<_SetCollection>(_onSetCollection); on<_SetCollection>(_onSetCollection);
on<_SetCollectionItems>(_onSetCollectionItems); on<_SetCollectionItems>(_onSetCollectionItems);
on<_MergeFiles>(_onMergeFiles);
on<_ToggleAppBar>(_onToggleAppBar); on<_ToggleAppBar>(_onToggleAppBar);
on<_ShowAppBar>(_onShowAppBar); on<_ShowAppBar>(_onShowAppBar);
@ -86,6 +87,13 @@ class _Bloc extends Bloc<_Event, _State>
.add(prefController.viewerBottomAppBarButtonsChange.listen((event) { .add(prefController.viewerBottomAppBarButtonsChange.listen((event) {
add(_SetBottomAppBarButtons(event)); add(_SetBottomAppBarButtons(event));
})); }));
_subscriptions.add(stream
.distinct((a, b) =>
identical(a.rawFiles, b.rawFiles) &&
identical(a.collectionItems, b.collectionItems))
.listen((event) {
add(const _MergeFiles());
}));
add(_SetIndex(startIndex)); add(_SetIndex(startIndex));
} }
@ -121,8 +129,7 @@ class _Bloc extends Bloc<_Event, _State>
emit, emit,
filesController.stream, filesController.stream,
onData: (data) => state.copyWith( onData: (data) => state.copyWith(
files: data.dataMap, rawFiles: data.dataMap,
currentFile: data.dataMap[state.fileIdOrders[state.index]],
), ),
), ),
forEach( forEach(
@ -176,6 +183,26 @@ class _Bloc extends Bloc<_Event, _State>
emit(state.copyWith(collectionItems: itemMap)); emit(state.copyWith(collectionItems: itemMap));
} }
void _onMergeFiles(_MergeFiles ev, _Emitter emit) {
_log.info(ev);
final Map<int, FileDescriptor> files;
if (collectionId == null) {
// not collection, nothing to merge
files = state.rawFiles;
} else {
if (state.collectionItems == null) {
// collection not ready
return;
}
files = state.rawFiles.addedAll(state.collectionItems!
.map((key, value) => MapEntry(key, value.file)));
}
emit(state.copyWith(
files: files,
currentFile: files[state.fileIdOrders[state.index]],
));
}
void _onToggleAppBar(_ToggleAppBar ev, _Emitter emit) { void _onToggleAppBar(_ToggleAppBar ev, _Emitter emit) {
_log.info(ev); _log.info(ev);
final to = !state.isShowAppBar; final to = !state.isShowAppBar;

View file

@ -5,6 +5,7 @@ part of '../viewer.dart';
class _State { class _State {
const _State({ const _State({
required this.fileIdOrders, required this.fileIdOrders,
required this.rawFiles,
required this.files, required this.files,
required this.fileStates, required this.fileStates,
required this.index, required this.index,
@ -41,6 +42,7 @@ class _State {
}) => }) =>
_State( _State(
fileIdOrders: fileIds, fileIdOrders: fileIds,
rawFiles: const {},
files: const {}, files: const {},
fileStates: const {}, fileStates: const {},
index: index, index: index,
@ -70,6 +72,7 @@ class _State {
@Format(r"$$?") @Format(r"$$?")
final List<int> fileIdOrders; final List<int> fileIdOrders;
final Map<int, FileDescriptor> rawFiles;
final Map<int, FileDescriptor> files; final Map<int, FileDescriptor> files;
final Map<int, _PageState> fileStates; final Map<int, _PageState> fileStates;
final int index; final int index;
@ -77,7 +80,7 @@ class _State {
final _PageState? currentFileState; final _PageState? currentFileState;
final Collection? collection; final Collection? collection;
final CollectionItemsController? collectionItemsController; final CollectionItemsController? collectionItemsController;
final Map<int, CollectionItem>? collectionItems; final Map<int, CollectionFileItem>? collectionItems;
final bool isShowDetailPane; final bool isShowDetailPane;
final bool isClosingDetailPane; final bool isClosingDetailPane;
final bool isDetailPaneActive; final bool isDetailPaneActive;
@ -177,6 +180,17 @@ class _SetCollectionItems implements _Event {
final List<CollectionItem>? value; final List<CollectionItem>? value;
} }
@toString
/// Merge regular files with collection items. The point of doing this is to
/// support shared files in an server side shared album, as these files do not
/// have a record in filesController
class _MergeFiles implements _Event {
const _MergeFiles();
@override
String toString() => _$toString();
}
@toString @toString
class _ToggleAppBar implements _Event { class _ToggleAppBar implements _Event {
const _ToggleAppBar(); const _ToggleAppBar();

View file

@ -257,7 +257,7 @@ class _PageViewState extends State<_PageView> {
previous.isDetailPaneActive != previous.isDetailPaneActive !=
current.isDetailPaneActive, current.isDetailPaneActive,
builder: (context, state) => FileContentView( builder: (context, state) => FileContentView(
fileId: file.fdId, file: file,
shouldPlayLivePhoto: state shouldPlayLivePhoto: state
.fileStates[widget.fileId] .fileStates[widget.fileId]
?.shouldPlayLivePhoto ?? ?.shouldPlayLivePhoto ??