Improve local comics page

This commit is contained in:
2024-12-22 18:07:13 +08:00
parent 6023e462d7
commit 0b96d01afb
2 changed files with 193 additions and 153 deletions

View File

@@ -342,21 +342,39 @@ class ComicTile extends StatelessWidget {
} }
List<String> _splitText(String text) { List<String> _splitText(String text) {
// split text by space, comma. text in brackets will be kept together. // split text by comma, brackets
var words = <String>[]; var words = <String>[];
var buffer = StringBuffer(); var buffer = StringBuffer();
var inBracket = false; var inBracket = false;
String? prevBracket;
for (var i = 0; i < text.length; i++) { for (var i = 0; i < text.length; i++) {
var c = text[i]; var c = text[i];
if (c == '[' || c == '(') { if (c == '[' || c == '(') {
inBracket = true;
} else if (c == ']' || c == ')') {
inBracket = false;
} else if (c == ' ' || c == ',') {
if (inBracket) { if (inBracket) {
buffer.write(c); buffer.write(c);
} else { } else {
words.add(buffer.toString()); if (buffer.isNotEmpty) {
words.add(buffer.toString().trim());
buffer.clear();
}
inBracket = true;
prevBracket = c;
}
} else if (c == ']' || c == ')') {
if (prevBracket == '[' && c == ']' || prevBracket == '(' && c == ')') {
if (buffer.isNotEmpty) {
words.add(buffer.toString().trim());
buffer.clear();
}
inBracket = false;
} else {
buffer.write(c);
}
} else if (c == ',') {
if (inBracket) {
buffer.write(c);
} else {
words.add(buffer.toString().trim());
buffer.clear(); buffer.clear();
} }
} else { } else {
@@ -364,8 +382,10 @@ class ComicTile extends StatelessWidget {
} }
} }
if (buffer.isNotEmpty) { if (buffer.isNotEmpty) {
words.add(buffer.toString()); words.add(buffer.toString().trim());
} }
words.removeWhere((element) => element == "");
words = words.toSet().toList();
return words; return words;
} }
@@ -383,7 +403,12 @@ class ComicTile extends StatelessWidget {
return StatefulBuilder(builder: (context, setState) { return StatefulBuilder(builder: (context, setState) {
return ContentDialog( return ContentDialog(
title: 'Block'.tl, title: 'Block'.tl,
content: Wrap( content: ConstrainedBox(
constraints: BoxConstraints(
maxHeight: math.min(400, context.height - 136),
),
child: SingleChildScrollView(
child: Wrap(
runSpacing: 8, runSpacing: 8,
spacing: 8, spacing: 8,
children: [ children: [
@@ -402,7 +427,9 @@ class ComicTile extends StatelessWidget {
}, },
), ),
], ],
),
).paddingHorizontal(16), ).paddingHorizontal(16),
),
actions: [ actions: [
Button.filled( Button.filled(
onPressed: () { onPressed: () {

View File

@@ -140,6 +140,8 @@ class _LocalComicsPageState extends State<LocalComicsPage> {
addFavorite(selectedComics.keys.toList()); addFavorite(selectedComics.keys.toList());
}, },
), ),
if (selectedComics.length == 1)
...exportActions(selectedComics.keys.first),
]); ]);
} }
@@ -182,13 +184,7 @@ class _LocalComicsPageState extends State<LocalComicsPage> {
buildMultiSelectMenu(), buildMultiSelectMenu(),
]; ];
var body = Scaffold( List<Widget> normalActions = [
body: SmoothCustomScrollView(
slivers: [
if (!searchMode && !multiSelectMode)
SliverAppbar(
title: Text("Local".tl),
actions: [
Tooltip( Tooltip(
message: "Search".tl, message: "Search".tl,
child: IconButton( child: IconButton(
@@ -216,25 +212,35 @@ class _LocalComicsPageState extends State<LocalComicsPage> {
}, },
), ),
), ),
], ];
)
else if (multiSelectMode) var body = Scaffold(
body: SmoothCustomScrollView(
slivers: [
if (!searchMode)
SliverAppbar( SliverAppbar(
leading: Tooltip( leading: Tooltip(
message: "Cancel".tl, message: multiSelectMode ? "Cancel".tl : "Back".tl,
child: IconButton( child: IconButton(
icon: const Icon(Icons.close),
onPressed: () { onPressed: () {
if (multiSelectMode) {
setState(() { setState(() {
multiSelectMode = false; multiSelectMode = false;
selectedComics.clear(); selectedComics.clear();
}); });
} else {
context.pop();
}
}, },
icon: multiSelectMode
? const Icon(Icons.close)
: const Icon(Icons.arrow_back),
), ),
), ),
title: Text( title: multiSelectMode
"Selected @c comics".tlParams({"c": selectedComics.length})), ? Text(selectedComics.length.toString())
actions: selectActions, : Text("Local".tl),
actions: multiSelectMode ? selectActions : normalActions,
) )
else if (searchMode) else if (searchMode)
SliverAppbar( SliverAppbar(
@@ -302,77 +308,9 @@ class _LocalComicsPageState extends State<LocalComicsPage> {
}); });
} }
}); });
}),
MenuEntry(
icon: Icons.outbox_outlined,
text: "Export as cbz".tl,
onClick: () async {
var controller = showLoadingDialog(
context,
allowCancel: false,
);
try {
var file = await CBZ.export(c as LocalComic);
await saveFile(filename: file.name, file: file);
await file.delete();
} catch (e) {
context.showMessage(message: e.toString());
}
controller.close();
}),
MenuEntry(
icon: Icons.picture_as_pdf_outlined,
text: "Export as pdf".tl,
onClick: () async {
var cache = FilePath.join(App.cachePath, 'temp.pdf');
var controller = showLoadingDialog(
context,
allowCancel: false,
);
try {
await createPdfFromComicIsolate(
comic: c as LocalComic,
savePath: cache,
);
await saveFile(
file: File(cache),
filename: "${c.title}.pdf",
);
} catch (e, s) {
Log.error("PDF Export", e, s);
context.showMessage(message: e.toString());
} finally {
controller.close();
File(cache).deleteIgnoreError();
}
}, },
), ),
MenuEntry( ...exportActions(c as LocalComic),
icon: Icons.import_contacts_outlined,
text: "Export as epub".tl,
onClick: () async {
var controller = showLoadingDialog(
context,
allowCancel: false,
);
File? file;
try {
file = await createEpubWithLocalComic(
c as LocalComic,
);
await saveFile(
file: file,
filename: "${c.title}.epub",
);
} catch (e, s) {
Log.error("EPUB Export", e, s);
context.showMessage(message: e.toString());
} finally {
controller.close();
file?.deleteIgnoreError();
}
},
)
]; ];
}, },
), ),
@@ -439,4 +377,79 @@ class _LocalComicsPageState extends State<LocalComicsPage> {
); );
return isDeleted; return isDeleted;
} }
List<MenuEntry> exportActions(LocalComic c) {
return [
MenuEntry(
icon: Icons.outbox_outlined,
text: "Export as cbz".tl,
onClick: () async {
var controller = showLoadingDialog(
context,
allowCancel: false,
);
try {
var file = await CBZ.export(c);
await saveFile(filename: file.name, file: file);
await file.delete();
} catch (e) {
context.showMessage(message: e.toString());
}
controller.close();
}),
MenuEntry(
icon: Icons.picture_as_pdf_outlined,
text: "Export as pdf".tl,
onClick: () async {
var cache = FilePath.join(App.cachePath, 'temp.pdf');
var controller = showLoadingDialog(
context,
allowCancel: false,
);
try {
await createPdfFromComicIsolate(
comic: c,
savePath: cache,
);
await saveFile(
file: File(cache),
filename: "${c.title}.pdf",
);
} catch (e, s) {
Log.error("PDF Export", e, s);
context.showMessage(message: e.toString());
} finally {
controller.close();
File(cache).deleteIgnoreError();
}
},
),
MenuEntry(
icon: Icons.import_contacts_outlined,
text: "Export as epub".tl,
onClick: () async {
var controller = showLoadingDialog(
context,
allowCancel: false,
);
File? file;
try {
file = await createEpubWithLocalComic(
c,
);
await saveFile(
file: file,
filename: "${c.title}.epub",
);
} catch (e, s) {
Log.error("EPUB Export", e, s);
context.showMessage(message: e.toString());
} finally {
controller.close();
file?.deleteIgnoreError();
}
},
)
];
}
} }