print: show feedback for multipage entries
This commit is contained in:
parent
10b4ce6898
commit
c7b6e17a7f
6 changed files with 37 additions and 28 deletions
|
@ -111,7 +111,9 @@ class MediaStoreSource extends CollectionSource {
|
|||
final uriByContentId = Map.fromEntries(changedUris.map((uri) {
|
||||
if (uri == null) return null;
|
||||
final idString = Uri.parse(uri).pathSegments.last;
|
||||
return MapEntry(int.tryParse(idString), uri);
|
||||
final contentId = int.tryParse(idString);
|
||||
if (contentId == null) return null;
|
||||
return MapEntry(contentId, uri);
|
||||
}).where((kv) => kv != null));
|
||||
|
||||
// clean up obsolete entries
|
||||
|
|
|
@ -79,14 +79,14 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
|
|||
if (!await checkFreeSpaceForMove(context, selection, destinationAlbum, moveType)) return;
|
||||
|
||||
final copy = moveType == MoveType.copy;
|
||||
final selectionCount = selection.length;
|
||||
showOpReport<MoveOpEvent>(
|
||||
context: context,
|
||||
selection: selection,
|
||||
opStream: ImageFileService.move(selection, copy: copy, destinationAlbum: destinationAlbum),
|
||||
itemCount: selectionCount,
|
||||
onDone: (processed) async {
|
||||
final movedOps = processed.where((e) => e.success);
|
||||
final movedCount = movedOps.length;
|
||||
final selectionCount = selection.length;
|
||||
if (movedCount < selectionCount) {
|
||||
final count = selectionCount - movedCount;
|
||||
showFeedback(context, 'Failed to ${copy ? 'copy' : 'move'} ${Intl.plural(count, one: '$count item', other: '$count items')}');
|
||||
|
@ -132,14 +132,14 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
|
|||
|
||||
if (!await checkStoragePermission(context, selection)) return;
|
||||
|
||||
final selectionCount = selection.length;
|
||||
showOpReport<ImageOpEvent>(
|
||||
context: context,
|
||||
selection: selection,
|
||||
opStream: ImageFileService.delete(selection),
|
||||
itemCount: selectionCount,
|
||||
onDone: (processed) {
|
||||
final deletedUris = processed.where((e) => e.success).map((e) => e.uri).toList();
|
||||
final deletedCount = deletedUris.length;
|
||||
final selectionCount = selection.length;
|
||||
if (deletedCount < selectionCount) {
|
||||
final count = selectionCount - deletedCount;
|
||||
showFeedback(context, 'Failed to delete ${Intl.plural(count, one: '$count item', other: '$count items')}');
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import 'package:aves/model/entry.dart';
|
||||
import 'package:aves/services/image_op_events.dart';
|
||||
import 'package:aves/theme/durations.dart';
|
||||
import 'package:flushbar/flushbar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -27,22 +25,20 @@ mixin FeedbackMixin {
|
|||
|
||||
// report overlay for multiple operations
|
||||
|
||||
OverlayEntry _opReportOverlayEntry;
|
||||
|
||||
void showOpReport<T extends ImageOpEvent>({
|
||||
void showOpReport<T>({
|
||||
@required BuildContext context,
|
||||
@required Set<AvesEntry> selection,
|
||||
@required Stream<T> opStream,
|
||||
@required void Function(Set<T> processed) onDone,
|
||||
@required int itemCount,
|
||||
void Function(Set<T> processed) onDone,
|
||||
}) {
|
||||
OverlayEntry _opReportOverlayEntry;
|
||||
_opReportOverlayEntry = OverlayEntry(
|
||||
builder: (context) => ReportOverlay<T>(
|
||||
opStream: opStream,
|
||||
itemCount: selection.length,
|
||||
itemCount: itemCount,
|
||||
onDone: (processed) {
|
||||
_opReportOverlayEntry?.remove();
|
||||
_opReportOverlayEntry = null;
|
||||
onDone(processed);
|
||||
_opReportOverlayEntry.remove();
|
||||
onDone?.call(processed);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
|
|
@ -79,14 +79,14 @@ class AlbumChipActionDelegate extends ChipActionDelegate with FeedbackMixin, Per
|
|||
|
||||
if (!await checkStoragePermission(context, selection)) return;
|
||||
|
||||
final selectionCount = selection.length;
|
||||
showOpReport<ImageOpEvent>(
|
||||
context: context,
|
||||
selection: selection,
|
||||
opStream: ImageFileService.delete(selection),
|
||||
itemCount: selectionCount,
|
||||
onDone: (processed) {
|
||||
final deletedUris = processed.where((e) => e.success).map((e) => e.uri).toList();
|
||||
final deletedCount = deletedUris.length;
|
||||
final selectionCount = selection.length;
|
||||
if (deletedCount < selectionCount) {
|
||||
final count = selectionCount - deletedCount;
|
||||
showFeedback(context, 'Failed to delete ${Intl.plural(count, one: '$count item', other: '$count items')}');
|
||||
|
@ -113,14 +113,14 @@ class AlbumChipActionDelegate extends ChipActionDelegate with FeedbackMixin, Per
|
|||
|
||||
if (!await checkFreeSpaceForMove(context, selection, destinationAlbum, MoveType.move)) return;
|
||||
|
||||
final selectionCount = selection.length;
|
||||
showOpReport<MoveOpEvent>(
|
||||
context: context,
|
||||
selection: selection,
|
||||
opStream: ImageFileService.move(selection, copy: false, destinationAlbum: destinationAlbum),
|
||||
itemCount: selectionCount,
|
||||
onDone: (processed) async {
|
||||
final movedOps = processed.where((e) => e.success);
|
||||
final movedCount = movedOps.length;
|
||||
final selectionCount = selection.length;
|
||||
if (movedCount < selectionCount) {
|
||||
final count = selectionCount - movedCount;
|
||||
showFeedback(context, 'Failed to move ${Intl.plural(count, one: '$count item', other: '$count items')}');
|
||||
|
|
|
@ -54,7 +54,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
_showRenameDialog(context, entry);
|
||||
break;
|
||||
case EntryAction.print:
|
||||
EntryPrinter(entry).print();
|
||||
EntryPrinter(entry).print(context);
|
||||
break;
|
||||
case EntryAction.rotateCCW:
|
||||
_rotate(context, entry, clockwise: false);
|
||||
|
@ -181,14 +181,14 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix
|
|||
selection.add(entry);
|
||||
}
|
||||
|
||||
final selectionCount = selection.length;
|
||||
showOpReport<ExportOpEvent>(
|
||||
context: context,
|
||||
selection: selection,
|
||||
opStream: ImageFileService.export(selection, destinationAlbum: destinationAlbum),
|
||||
itemCount: selectionCount,
|
||||
onDone: (processed) {
|
||||
final movedOps = processed.where((e) => e.success);
|
||||
final movedCount = movedOps.length;
|
||||
final selectionCount = selection.length;
|
||||
if (movedCount < selectionCount) {
|
||||
final count = selectionCount - movedCount;
|
||||
showFeedback(context, 'Failed to export ${Intl.plural(count, one: '$count page', other: '$count pages')}');
|
||||
|
|
|
@ -1,23 +1,26 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:aves/model/entry.dart';
|
||||
import 'package:aves/model/entry_images.dart';
|
||||
import 'package:aves/services/image_file_service.dart';
|
||||
import 'package:aves/services/metadata_service.dart';
|
||||
import 'package:aves/widgets/common/action_mixins/feedback.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:pdf/widgets.dart' as pdf;
|
||||
import 'package:pedantic/pedantic.dart';
|
||||
import 'package:printing/printing.dart';
|
||||
|
||||
class EntryPrinter {
|
||||
class EntryPrinter with FeedbackMixin {
|
||||
final AvesEntry entry;
|
||||
|
||||
const EntryPrinter(this.entry);
|
||||
EntryPrinter(this.entry);
|
||||
|
||||
Future<void> print() async {
|
||||
Future<void> print(BuildContext context) async {
|
||||
final documentName = entry.bestTitle ?? 'Aves';
|
||||
final doc = pdf.Document(title: documentName);
|
||||
|
||||
final pages = await _buildPages();
|
||||
final pages = await _buildPages(context);
|
||||
if (pages.isNotEmpty) {
|
||||
pages.forEach(doc.addPage); // Page
|
||||
unawaited(Printing.layoutPdf(
|
||||
|
@ -27,7 +30,7 @@ class EntryPrinter {
|
|||
}
|
||||
}
|
||||
|
||||
Future<List<pdf.Page>> _buildPages() async {
|
||||
Future<List<pdf.Page>> _buildPages(BuildContext context) async {
|
||||
final pages = <pdf.Page>[];
|
||||
|
||||
void _addPdfPage(pdf.Widget pdfChild) {
|
||||
|
@ -47,10 +50,18 @@ class EntryPrinter {
|
|||
if (entry.isMultipage) {
|
||||
final multiPageInfo = await MetadataService.getMultiPageInfo(entry);
|
||||
if (multiPageInfo.pageCount > 1) {
|
||||
final streamController = StreamController<AvesEntry>.broadcast();
|
||||
showOpReport<AvesEntry>(
|
||||
context: context,
|
||||
opStream: streamController.stream,
|
||||
itemCount: multiPageInfo.pageCount,
|
||||
);
|
||||
for (final page in multiPageInfo.pages) {
|
||||
final pageEntry = entry.getPageEntry(page);
|
||||
_addPdfPage(await _buildPageImage(pageEntry));
|
||||
streamController.sink.add(pageEntry);
|
||||
}
|
||||
await streamController.close();
|
||||
}
|
||||
}
|
||||
if (pages.isEmpty) {
|
||||
|
|
Loading…
Reference in a new issue