mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-01-22 08:46:18 +01:00
Add a dialog that lead user to the video preview help page
This commit is contained in:
parent
bd0e4fd342
commit
4fc6b17de1
15 changed files with 180 additions and 27 deletions
|
@ -152,6 +152,12 @@ class PrefController {
|
|||
value: value,
|
||||
);
|
||||
|
||||
Future<bool> setDontShowVideoPreviewHint(bool value) => _set<bool>(
|
||||
controller: _isDontShowVideoPreviewHintController,
|
||||
setter: (pref, value) => pref.setDontShowVideoPreviewHint(value),
|
||||
value: value,
|
||||
);
|
||||
|
||||
Future<bool> _set<T>({
|
||||
required BehaviorSubject<T> controller,
|
||||
required Future<bool> Function(Pref pref, T value) setter,
|
||||
|
@ -249,6 +255,9 @@ class PrefController {
|
|||
@NpSubjectAccessor(type: "Color?")
|
||||
late final _secondarySeedColorController = BehaviorSubject<Color?>.seeded(
|
||||
_c.pref.getSecondarySeedColor()?.run(Color.new));
|
||||
@npSubjectAccessor
|
||||
late final _isDontShowVideoPreviewHintController =
|
||||
BehaviorSubject.seeded(_c.pref.isDontShowVideoPreviewHintOr(false));
|
||||
}
|
||||
|
||||
@npSubjectAccessor
|
||||
|
|
|
@ -148,6 +148,15 @@ extension $PrefControllerNpSubjectAccessor on PrefController {
|
|||
Stream<Color?> get secondarySeedColorChange =>
|
||||
secondarySeedColor.distinct().skip(1);
|
||||
Color? get secondarySeedColorValue => _secondarySeedColorController.value;
|
||||
// _isDontShowVideoPreviewHintController
|
||||
ValueStream<bool> get isDontShowVideoPreviewHint =>
|
||||
_isDontShowVideoPreviewHintController.stream;
|
||||
Stream<bool> get isDontShowVideoPreviewHintNew =>
|
||||
isDontShowVideoPreviewHint.skip(1);
|
||||
Stream<bool> get isDontShowVideoPreviewHintChange =>
|
||||
isDontShowVideoPreviewHint.distinct().skip(1);
|
||||
bool get isDontShowVideoPreviewHintValue =>
|
||||
_isDontShowVideoPreviewHintController.value;
|
||||
}
|
||||
|
||||
extension $SecurePrefControllerNpSubjectAccessor on SecurePrefController {
|
||||
|
|
|
@ -81,4 +81,11 @@ extension on Pref {
|
|||
return provider.setString(PrefKey.protectedPageAuthPassword, value);
|
||||
}
|
||||
}
|
||||
|
||||
bool? isDontShowVideoPreviewHint() =>
|
||||
provider.getBool(PrefKey.dontShowVideoPreviewHint);
|
||||
bool isDontShowVideoPreviewHintOr(bool def) =>
|
||||
isDontShowVideoPreviewHint() ?? def;
|
||||
Future<bool> setDontShowVideoPreviewHint(bool value) =>
|
||||
provider.setBool(PrefKey.dontShowVideoPreviewHint, value);
|
||||
}
|
||||
|
|
|
@ -112,6 +112,7 @@ enum PrefKey implements PrefKeyInterface {
|
|||
protectedPageAuthType,
|
||||
protectedPageAuthPin,
|
||||
protectedPageAuthPassword,
|
||||
dontShowVideoPreviewHint,
|
||||
;
|
||||
|
||||
@override
|
||||
|
@ -196,6 +197,8 @@ enum PrefKey implements PrefKeyInterface {
|
|||
return "protectedPageAuthPin";
|
||||
case PrefKey.protectedPageAuthPassword:
|
||||
return "protectedPageAuthPassword";
|
||||
case PrefKey.dontShowVideoPreviewHint:
|
||||
return "dontShowVideoPreviewHint";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,3 +13,4 @@ const enhanceRetouchUrl = "https://bit.ly/3Ds2cea";
|
|||
const editPhotosUrl = "https://bit.ly/3v82oKA";
|
||||
const collectionTypesUrl = "https://bit.ly/3OwSiNq";
|
||||
const contributorsUrl = "https://bit.ly/3QhlQQs";
|
||||
const videoPreviewUrl = "https://bit.ly/4c7cazP";
|
||||
|
|
|
@ -1485,6 +1485,8 @@
|
|||
"description": "There's no HTTPS server in the account list"
|
||||
},
|
||||
"trustedCertManagerFailedToRemoveCertError": "Failed to remove certificate",
|
||||
"missingVideoThumbnailHelpDialogTitle": "Having trouble with video thumbnails?",
|
||||
"dontShowAgain": "Don't show again",
|
||||
|
||||
"errorUnauthenticated": "Unauthenticated access. Please sign-in again if the problem continues",
|
||||
"@errorUnauthenticated": {
|
||||
|
|
|
@ -247,6 +247,8 @@
|
|||
"trustedCertManagerSelectServer",
|
||||
"trustedCertManagerNoHttpsServerError",
|
||||
"trustedCertManagerFailedToRemoveCertError",
|
||||
"missingVideoThumbnailHelpDialogTitle",
|
||||
"dontShowAgain",
|
||||
"errorUnauthenticated",
|
||||
"errorDisconnected",
|
||||
"errorLocked",
|
||||
|
@ -280,7 +282,9 @@
|
|||
"trustedCertManagerAlreadyTrustedError",
|
||||
"trustedCertManagerSelectServer",
|
||||
"trustedCertManagerNoHttpsServerError",
|
||||
"trustedCertManagerFailedToRemoveCertError"
|
||||
"trustedCertManagerFailedToRemoveCertError",
|
||||
"missingVideoThumbnailHelpDialogTitle",
|
||||
"dontShowAgain"
|
||||
],
|
||||
|
||||
"de": [
|
||||
|
@ -332,7 +336,9 @@
|
|||
"trustedCertManagerAlreadyTrustedError",
|
||||
"trustedCertManagerSelectServer",
|
||||
"trustedCertManagerNoHttpsServerError",
|
||||
"trustedCertManagerFailedToRemoveCertError"
|
||||
"trustedCertManagerFailedToRemoveCertError",
|
||||
"missingVideoThumbnailHelpDialogTitle",
|
||||
"dontShowAgain"
|
||||
],
|
||||
|
||||
"el": [
|
||||
|
@ -467,7 +473,9 @@
|
|||
"trustedCertManagerAlreadyTrustedError",
|
||||
"trustedCertManagerSelectServer",
|
||||
"trustedCertManagerNoHttpsServerError",
|
||||
"trustedCertManagerFailedToRemoveCertError"
|
||||
"trustedCertManagerFailedToRemoveCertError",
|
||||
"missingVideoThumbnailHelpDialogTitle",
|
||||
"dontShowAgain"
|
||||
],
|
||||
|
||||
"es": [
|
||||
|
@ -493,7 +501,9 @@
|
|||
"trustedCertManagerAlreadyTrustedError",
|
||||
"trustedCertManagerSelectServer",
|
||||
"trustedCertManagerNoHttpsServerError",
|
||||
"trustedCertManagerFailedToRemoveCertError"
|
||||
"trustedCertManagerFailedToRemoveCertError",
|
||||
"missingVideoThumbnailHelpDialogTitle",
|
||||
"dontShowAgain"
|
||||
],
|
||||
|
||||
"fi": [
|
||||
|
@ -519,7 +529,9 @@
|
|||
"trustedCertManagerAlreadyTrustedError",
|
||||
"trustedCertManagerSelectServer",
|
||||
"trustedCertManagerNoHttpsServerError",
|
||||
"trustedCertManagerFailedToRemoveCertError"
|
||||
"trustedCertManagerFailedToRemoveCertError",
|
||||
"missingVideoThumbnailHelpDialogTitle",
|
||||
"dontShowAgain"
|
||||
],
|
||||
|
||||
"fr": [
|
||||
|
@ -545,7 +557,9 @@
|
|||
"trustedCertManagerAlreadyTrustedError",
|
||||
"trustedCertManagerSelectServer",
|
||||
"trustedCertManagerNoHttpsServerError",
|
||||
"trustedCertManagerFailedToRemoveCertError"
|
||||
"trustedCertManagerFailedToRemoveCertError",
|
||||
"missingVideoThumbnailHelpDialogTitle",
|
||||
"dontShowAgain"
|
||||
],
|
||||
|
||||
"it": [
|
||||
|
@ -576,7 +590,9 @@
|
|||
"trustedCertManagerAlreadyTrustedError",
|
||||
"trustedCertManagerSelectServer",
|
||||
"trustedCertManagerNoHttpsServerError",
|
||||
"trustedCertManagerFailedToRemoveCertError"
|
||||
"trustedCertManagerFailedToRemoveCertError",
|
||||
"missingVideoThumbnailHelpDialogTitle",
|
||||
"dontShowAgain"
|
||||
],
|
||||
|
||||
"nl": [
|
||||
|
@ -944,6 +960,8 @@
|
|||
"trustedCertManagerSelectServer",
|
||||
"trustedCertManagerNoHttpsServerError",
|
||||
"trustedCertManagerFailedToRemoveCertError",
|
||||
"missingVideoThumbnailHelpDialogTitle",
|
||||
"dontShowAgain",
|
||||
"errorUnauthenticated",
|
||||
"errorDisconnected",
|
||||
"errorLocked",
|
||||
|
@ -981,7 +999,9 @@
|
|||
"trustedCertManagerAlreadyTrustedError",
|
||||
"trustedCertManagerSelectServer",
|
||||
"trustedCertManagerNoHttpsServerError",
|
||||
"trustedCertManagerFailedToRemoveCertError"
|
||||
"trustedCertManagerFailedToRemoveCertError",
|
||||
"missingVideoThumbnailHelpDialogTitle",
|
||||
"dontShowAgain"
|
||||
],
|
||||
|
||||
"pt": [
|
||||
|
@ -1027,7 +1047,9 @@
|
|||
"trustedCertManagerAlreadyTrustedError",
|
||||
"trustedCertManagerSelectServer",
|
||||
"trustedCertManagerNoHttpsServerError",
|
||||
"trustedCertManagerFailedToRemoveCertError"
|
||||
"trustedCertManagerFailedToRemoveCertError",
|
||||
"missingVideoThumbnailHelpDialogTitle",
|
||||
"dontShowAgain"
|
||||
],
|
||||
|
||||
"ru": [
|
||||
|
@ -1053,7 +1075,9 @@
|
|||
"trustedCertManagerAlreadyTrustedError",
|
||||
"trustedCertManagerSelectServer",
|
||||
"trustedCertManagerNoHttpsServerError",
|
||||
"trustedCertManagerFailedToRemoveCertError"
|
||||
"trustedCertManagerFailedToRemoveCertError",
|
||||
"missingVideoThumbnailHelpDialogTitle",
|
||||
"dontShowAgain"
|
||||
],
|
||||
|
||||
"tr": [
|
||||
|
@ -1062,7 +1086,9 @@
|
|||
"trustedCertManagerAlreadyTrustedError",
|
||||
"trustedCertManagerSelectServer",
|
||||
"trustedCertManagerNoHttpsServerError",
|
||||
"trustedCertManagerFailedToRemoveCertError"
|
||||
"trustedCertManagerFailedToRemoveCertError",
|
||||
"missingVideoThumbnailHelpDialogTitle",
|
||||
"dontShowAgain"
|
||||
],
|
||||
|
||||
"zh": [
|
||||
|
@ -1119,7 +1145,9 @@
|
|||
"trustedCertManagerAlreadyTrustedError",
|
||||
"trustedCertManagerSelectServer",
|
||||
"trustedCertManagerNoHttpsServerError",
|
||||
"trustedCertManagerFailedToRemoveCertError"
|
||||
"trustedCertManagerFailedToRemoveCertError",
|
||||
"missingVideoThumbnailHelpDialogTitle",
|
||||
"dontShowAgain"
|
||||
],
|
||||
|
||||
"zh_Hant": [
|
||||
|
@ -1270,6 +1298,8 @@
|
|||
"trustedCertManagerAlreadyTrustedError",
|
||||
"trustedCertManagerSelectServer",
|
||||
"trustedCertManagerNoHttpsServerError",
|
||||
"trustedCertManagerFailedToRemoveCertError"
|
||||
"trustedCertManagerFailedToRemoveCertError",
|
||||
"missingVideoThumbnailHelpDialogTitle",
|
||||
"dontShowAgain"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -22,5 +22,7 @@ class SessionStorage {
|
|||
|
||||
DateTime lastSuspendTime = clock.now();
|
||||
|
||||
bool hasShownVideoPreviewHint = false;
|
||||
|
||||
static final _inst = SessionStorage._();
|
||||
}
|
||||
|
|
|
@ -50,6 +50,8 @@ class _Bloc extends Bloc<_Event, _State>
|
|||
on<_UpdateDateTimeGroup>(_onUpdateDateTimeGroup);
|
||||
on<_UpdateMemories>(_onUpdateMemories);
|
||||
|
||||
on<_TripMissingVideoPreview>(_onTripMissingVideoPreview);
|
||||
|
||||
on<_SetError>(_onSetError);
|
||||
|
||||
_subscriptions
|
||||
|
@ -486,6 +488,14 @@ class _Bloc extends Bloc<_Event, _State>
|
|||
));
|
||||
}
|
||||
|
||||
void _onTripMissingVideoPreview(
|
||||
_TripMissingVideoPreview ev, Emitter<_State> emit) {
|
||||
// _log.info(ev);
|
||||
if (!state.hasMissingVideoPreview) {
|
||||
emit(state.copyWith(hasMissingVideoPreview: true));
|
||||
}
|
||||
}
|
||||
|
||||
void _onSetError(_SetError ev, Emitter<_State> emit) {
|
||||
_log.info(ev);
|
||||
emit(state.copyWith(error: ExceptionEvent(ev.error, ev.stackTrace)));
|
||||
|
|
|
@ -25,6 +25,7 @@ class _State {
|
|||
this.minimapItems,
|
||||
required this.minimapYRatio,
|
||||
this.scrollDate,
|
||||
required this.hasMissingVideoPreview,
|
||||
this.error,
|
||||
});
|
||||
|
||||
|
@ -45,6 +46,7 @@ class _State {
|
|||
isScrolling: false,
|
||||
filesSummary: const DbFilesSummary(items: {}),
|
||||
minimapYRatio: 1,
|
||||
hasMissingVideoPreview: false,
|
||||
);
|
||||
|
||||
@override
|
||||
|
@ -76,6 +78,8 @@ class _State {
|
|||
final double minimapYRatio;
|
||||
final Date? scrollDate;
|
||||
|
||||
final bool hasMissingVideoPreview;
|
||||
|
||||
final ExceptionEvent? error;
|
||||
}
|
||||
|
||||
|
@ -315,6 +319,14 @@ class _UpdateMemories implements _Event {
|
|||
String toString() => _$toString();
|
||||
}
|
||||
|
||||
@toString
|
||||
class _TripMissingVideoPreview implements _Event {
|
||||
const _TripMissingVideoPreview();
|
||||
|
||||
@override
|
||||
String toString() => _$toString();
|
||||
}
|
||||
|
||||
@toString
|
||||
class _SetError implements _Event {
|
||||
const _SetError(this.error, [this.stackTrace]);
|
||||
|
|
|
@ -72,6 +72,9 @@ class _VideoItem extends _FileItem {
|
|||
account: account,
|
||||
previewUrl: _previewUrl,
|
||||
isFavorite: file.fdIsFavorite,
|
||||
onError: () {
|
||||
context.addEvent(const _TripMissingVideoPreview());
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -311,3 +311,30 @@ class _ScrollLabel extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _VideoPreviewHintDialog extends StatelessWidget {
|
||||
const _VideoPreviewHintDialog();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text(L10n.global().missingVideoThumbnailHelpDialogTitle),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
launch(help_util.videoPreviewUrl);
|
||||
},
|
||||
child: Text(L10n.global().learnMoreButtonLabel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
context.read<PrefController>().setDontShowVideoPreviewHint(true);
|
||||
},
|
||||
child: Text(L10n.global().dontShowAgain),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,13 +33,16 @@ import 'package:nc_photos/entity/file_util.dart' as file_util;
|
|||
import 'package:nc_photos/event/event.dart';
|
||||
import 'package:nc_photos/exception_event.dart';
|
||||
import 'package:nc_photos/flutter_util.dart' as flutter_util;
|
||||
import 'package:nc_photos/help_utils.dart' as help_util;
|
||||
import 'package:nc_photos/k.dart' as k;
|
||||
import 'package:nc_photos/progress_util.dart';
|
||||
import 'package:nc_photos/remote_storage_util.dart' as remote_storage_util;
|
||||
import 'package:nc_photos/session_storage.dart';
|
||||
import 'package:nc_photos/snack_bar_manager.dart';
|
||||
import 'package:nc_photos/stream_extension.dart';
|
||||
import 'package:nc_photos/theme.dart';
|
||||
import 'package:nc_photos/theme/dimension.dart';
|
||||
import 'package:nc_photos/url_launcher_util.dart';
|
||||
import 'package:nc_photos/widget/collection_browser.dart';
|
||||
import 'package:nc_photos/widget/collection_picker.dart';
|
||||
import 'package:nc_photos/widget/file_sharer_dialog.dart';
|
||||
|
@ -133,6 +136,23 @@ class _WrappedHomePhotosState extends State<_WrappedHomePhotos> {
|
|||
},
|
||||
child: MultiBlocListener(
|
||||
listeners: [
|
||||
_BlocListenerT<bool>(
|
||||
selector: (state) => state.hasMissingVideoPreview,
|
||||
listener: (context, hasMissingVideoPreview) {
|
||||
if (hasMissingVideoPreview) {
|
||||
if (!context
|
||||
.read<PrefController>()
|
||||
.isDontShowVideoPreviewHintValue &&
|
||||
!SessionStorage().hasShownVideoPreviewHint) {
|
||||
SessionStorage().hasShownVideoPreviewHint = true;
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => const _VideoPreviewHintDialog(),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
_BlocListenerT<ExceptionEvent?>(
|
||||
selector: (state) => state.error,
|
||||
listener: (context, error) {
|
||||
|
|
|
@ -35,6 +35,7 @@ abstract class $_StateCopyWithWorker {
|
|||
List<_MinimapItem>? minimapItems,
|
||||
double? minimapYRatio,
|
||||
Date? scrollDate,
|
||||
bool? hasMissingVideoPreview,
|
||||
ExceptionEvent? error});
|
||||
}
|
||||
|
||||
|
@ -64,6 +65,7 @@ class _$_StateCopyWithWorkerImpl implements $_StateCopyWithWorker {
|
|||
dynamic minimapItems = copyWithNull,
|
||||
dynamic minimapYRatio,
|
||||
dynamic scrollDate = copyWithNull,
|
||||
dynamic hasMissingVideoPreview,
|
||||
dynamic error = copyWithNull}) {
|
||||
return _State(
|
||||
files: files as List<FileDescriptor>? ?? that.files,
|
||||
|
@ -102,6 +104,8 @@ class _$_StateCopyWithWorkerImpl implements $_StateCopyWithWorker {
|
|||
minimapYRatio: minimapYRatio as double? ?? that.minimapYRatio,
|
||||
scrollDate:
|
||||
scrollDate == copyWithNull ? that.scrollDate : scrollDate as Date?,
|
||||
hasMissingVideoPreview:
|
||||
hasMissingVideoPreview as bool? ?? that.hasMissingVideoPreview,
|
||||
error: error == copyWithNull ? that.error : error as ExceptionEvent?);
|
||||
}
|
||||
|
||||
|
@ -180,7 +184,7 @@ extension _$_ContentListBodyNpLog on _ContentListBody {
|
|||
extension _$_StateToString on _State {
|
||||
String _$toString() {
|
||||
// ignore: unnecessary_string_interpolations
|
||||
return "_State {files: [length: ${files.length}], isLoading: $isLoading, transformedItems: [length: ${transformedItems.length}], selectedItems: {length: ${selectedItems.length}}, filesSummary: $filesSummary, visibleDates: {length: ${visibleDates.length}}, queriedDates: {length: ${queriedDates.length}}, isEnableMemoryCollection: $isEnableMemoryCollection, memoryCollections: [length: ${memoryCollections.length}], contentListMaxExtent: ${contentListMaxExtent == null ? null : "${contentListMaxExtent!.toStringAsFixed(3)}"}, syncProgress: $syncProgress, zoom: $zoom, scale: ${scale == null ? null : "${scale!.toStringAsFixed(3)}"}, viewWidth: ${viewWidth == null ? null : "${viewWidth!.toStringAsFixed(3)}"}, viewHeight: ${viewHeight == null ? null : "${viewHeight!.toStringAsFixed(3)}"}, itemPerRow: $itemPerRow, itemSize: ${itemSize == null ? null : "${itemSize!.toStringAsFixed(3)}"}, isScrolling: $isScrolling, minimapItems: ${minimapItems == null ? null : "[length: ${minimapItems!.length}]"}, minimapYRatio: ${minimapYRatio.toStringAsFixed(3)}, scrollDate: $scrollDate, error: $error}";
|
||||
return "_State {files: [length: ${files.length}], isLoading: $isLoading, transformedItems: [length: ${transformedItems.length}], selectedItems: {length: ${selectedItems.length}}, filesSummary: $filesSummary, visibleDates: {length: ${visibleDates.length}}, queriedDates: {length: ${queriedDates.length}}, isEnableMemoryCollection: $isEnableMemoryCollection, memoryCollections: [length: ${memoryCollections.length}], contentListMaxExtent: ${contentListMaxExtent == null ? null : "${contentListMaxExtent!.toStringAsFixed(3)}"}, syncProgress: $syncProgress, zoom: $zoom, scale: ${scale == null ? null : "${scale!.toStringAsFixed(3)}"}, viewWidth: ${viewWidth == null ? null : "${viewWidth!.toStringAsFixed(3)}"}, viewHeight: ${viewHeight == null ? null : "${viewHeight!.toStringAsFixed(3)}"}, itemPerRow: $itemPerRow, itemSize: ${itemSize == null ? null : "${itemSize!.toStringAsFixed(3)}"}, isScrolling: $isScrolling, minimapItems: ${minimapItems == null ? null : "[length: ${minimapItems!.length}]"}, minimapYRatio: ${minimapYRatio.toStringAsFixed(3)}, scrollDate: $scrollDate, hasMissingVideoPreview: $hasMissingVideoPreview, error: $error}";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -360,6 +364,13 @@ extension _$_UpdateMemoriesToString on _UpdateMemories {
|
|||
}
|
||||
}
|
||||
|
||||
extension _$_TripMissingVideoPreviewToString on _TripMissingVideoPreview {
|
||||
String _$toString() {
|
||||
// ignore: unnecessary_string_interpolations
|
||||
return "_TripMissingVideoPreview {}";
|
||||
}
|
||||
}
|
||||
|
||||
extension _$_SetErrorToString on _SetError {
|
||||
String _$toString() {
|
||||
// ignore: unnecessary_string_interpolations
|
||||
|
|
|
@ -278,6 +278,7 @@ class PhotoListVideo extends StatelessWidget {
|
|||
required this.account,
|
||||
required this.previewUrl,
|
||||
this.isFavorite = false,
|
||||
this.onError,
|
||||
});
|
||||
|
||||
@override
|
||||
|
@ -293,24 +294,29 @@ class PhotoListVideo extends StatelessWidget {
|
|||
child: NetworkRectThumbnail(
|
||||
account: account,
|
||||
imageUrl: previewUrl,
|
||||
errorBuilder: (_) => Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Icon(
|
||||
Icons.image_not_supported,
|
||||
color: Theme.of(context).listPlaceholderForegroundColor,
|
||||
),
|
||||
),
|
||||
errorBuilder: (context) {
|
||||
onError?.call();
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Icon(
|
||||
Icons.image_not_supported,
|
||||
color: Theme.of(context).listPlaceholderForegroundColor,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Container(
|
||||
alignment: AlignmentDirectional.topEnd,
|
||||
padding: const EdgeInsets.all(6),
|
||||
Positioned.directional(
|
||||
textDirection: Directionality.of(context),
|
||||
top: 6,
|
||||
end: 6,
|
||||
child: const Icon(Icons.play_circle_outlined, size: 17),
|
||||
),
|
||||
if (isFavorite)
|
||||
Container(
|
||||
alignment: AlignmentDirectional.bottomStart,
|
||||
padding: const EdgeInsets.all(6),
|
||||
Positioned.directional(
|
||||
textDirection: Directionality.of(context),
|
||||
bottom: 6,
|
||||
start: 6,
|
||||
child: const Icon(Icons.star, size: 15),
|
||||
),
|
||||
],
|
||||
|
@ -322,6 +328,7 @@ class PhotoListVideo extends StatelessWidget {
|
|||
final Account account;
|
||||
final String previewUrl;
|
||||
final bool isFavorite;
|
||||
final VoidCallback? onError;
|
||||
}
|
||||
|
||||
class PhotoListLabel extends StatelessWidget {
|
||||
|
|
Loading…
Reference in a new issue