mirror of
https://github.com/venera-app/venera.git
synced 2025-09-27 07:47:24 +00:00
Convert network folder to local
This commit is contained in:
@@ -288,3 +288,178 @@ Future<void> sortFolders() async {
|
||||
|
||||
LocalFavoritesManager().updateOrder(folders);
|
||||
}
|
||||
|
||||
Future<void> importNetworkFolder(
|
||||
String source,
|
||||
String? folder,
|
||||
String? folderID,
|
||||
) async {
|
||||
var comicSource = ComicSource.find(source);
|
||||
if (comicSource == null) {
|
||||
return;
|
||||
}
|
||||
if(folder != null && folder.isEmpty) {
|
||||
folder = null;
|
||||
}
|
||||
var resultName = folder ?? comicSource.name;
|
||||
var exists = LocalFavoritesManager().existsFolder(resultName);
|
||||
if (exists) {
|
||||
if (!LocalFavoritesManager()
|
||||
.isLinkedToNetworkFolder(resultName, source, folderID ?? "")) {
|
||||
App.rootContext.showMessage(message: "Folder already exists".tl);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(!exists) {
|
||||
LocalFavoritesManager().createFolder(resultName);
|
||||
LocalFavoritesManager().linkFolderToNetwork(
|
||||
resultName,
|
||||
source,
|
||||
folderID ?? "",
|
||||
);
|
||||
}
|
||||
|
||||
var current = 0;
|
||||
var isFinished = false;
|
||||
String? next;
|
||||
|
||||
Future<void> fetchNext() async {
|
||||
var retry = 3;
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
if (comicSource.favoriteData?.loadComic != null) {
|
||||
next ??= '1';
|
||||
var page = int.parse(next!);
|
||||
var res = await comicSource.favoriteData!.loadComic!(page, folderID);
|
||||
var count = 0;
|
||||
for (var c in res.data) {
|
||||
var result = LocalFavoritesManager().addComic(
|
||||
resultName,
|
||||
FavoriteItem(
|
||||
id: c.id,
|
||||
name: c.title,
|
||||
coverPath: c.cover,
|
||||
type: ComicType(source.hashCode),
|
||||
author: c.subtitle ?? '',
|
||||
tags: c.tags ?? [],
|
||||
),
|
||||
);
|
||||
if (result) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
current += count;
|
||||
if (res.data.isEmpty || res.subData == page) {
|
||||
isFinished = true;
|
||||
next = null;
|
||||
} else {
|
||||
next = (page + 1).toString();
|
||||
}
|
||||
} else if (comicSource.favoriteData?.loadNext != null) {
|
||||
var res = await comicSource.favoriteData!.loadNext!(next, folderID);
|
||||
var count = 0;
|
||||
for (var c in res.data) {
|
||||
var result = LocalFavoritesManager().addComic(
|
||||
resultName,
|
||||
FavoriteItem(
|
||||
id: c.id,
|
||||
name: c.title,
|
||||
coverPath: c.cover,
|
||||
type: ComicType(source.hashCode),
|
||||
author: c.subtitle ?? '',
|
||||
tags: c.tags ?? [],
|
||||
),
|
||||
);
|
||||
if (result) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
current += count;
|
||||
if (res.data.isEmpty || res.subData == null) {
|
||||
isFinished = true;
|
||||
next = null;
|
||||
} else {
|
||||
next = res.subData;
|
||||
}
|
||||
} else {
|
||||
throw "Unsupported source";
|
||||
}
|
||||
return;
|
||||
} catch (e) {
|
||||
retry--;
|
||||
if (retry == 0) {
|
||||
rethrow;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isCanceled = false;
|
||||
String? errorMsg;
|
||||
bool isErrored() => errorMsg != null;
|
||||
|
||||
void Function()? updateDialog;
|
||||
|
||||
showDialog(
|
||||
context: App.rootContext,
|
||||
builder: (context) {
|
||||
return StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
updateDialog = () => setState(() {});
|
||||
return ContentDialog(
|
||||
title: isFinished
|
||||
? "Finished".tl
|
||||
: isErrored()
|
||||
? "Error".tl
|
||||
: "Importing".tl,
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 4),
|
||||
LinearProgressIndicator(
|
||||
value: isFinished ? 1 : null,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text("Imported @c comics".tlParams({
|
||||
"c": current,
|
||||
})),
|
||||
const SizedBox(height: 4),
|
||||
if (isErrored()) Text("Error: $errorMsg"),
|
||||
],
|
||||
).paddingHorizontal(16),
|
||||
actions: [
|
||||
Button.filled(
|
||||
color: (isFinished || isErrored())
|
||||
? null
|
||||
: context.colorScheme.error,
|
||||
onPressed: () {
|
||||
isCanceled = true;
|
||||
context.pop();
|
||||
},
|
||||
child: (isFinished || isErrored())
|
||||
? Text("OK".tl)
|
||||
: Text("Cancel".tl),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
).then((_) {
|
||||
isCanceled = true;
|
||||
});
|
||||
|
||||
while (!isFinished && !isCanceled) {
|
||||
try {
|
||||
await fetchNext();
|
||||
updateDialog?.call();
|
||||
} catch (e) {
|
||||
errorMsg = e.toString();
|
||||
updateDialog?.call();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_reorderable_grid_view/widgets/reorderable_builder.dart';
|
||||
import 'package:venera/components/components.dart';
|
||||
|
@@ -14,6 +14,9 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> {
|
||||
|
||||
late List<FavoriteItem> comics;
|
||||
|
||||
String? networkSource;
|
||||
String? networkFolder;
|
||||
|
||||
void updateComics() {
|
||||
setState(() {
|
||||
comics = LocalFavoritesManager().getAllComics(widget.folder);
|
||||
@@ -24,6 +27,9 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> {
|
||||
void initState() {
|
||||
favPage = context.findAncestorStateOfType<_FavoritesPageState>()!;
|
||||
comics = LocalFavoritesManager().getAllComics(widget.folder);
|
||||
var (a, b) = LocalFavoritesManager().findLinked(widget.folder);
|
||||
networkSource = a;
|
||||
networkFolder = b;
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@@ -49,6 +55,51 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> {
|
||||
child: Text(favPage.folder ?? "Unselected".tl),
|
||||
),
|
||||
actions: [
|
||||
if (networkSource != null)
|
||||
Tooltip(
|
||||
message: "Sync".tl,
|
||||
child: Flyout(
|
||||
flyoutBuilder: (context) {
|
||||
var sourceName = ComicSource.find(networkSource!)?.name ??
|
||||
networkSource!;
|
||||
var text = "The folder is Linked to @source".tlParams({
|
||||
"source": sourceName,
|
||||
});
|
||||
if(networkFolder != null && networkFolder!.isNotEmpty) {
|
||||
text += "\n${"Source Folder".tl}: $networkFolder";
|
||||
}
|
||||
return FlyoutContent(
|
||||
title: "Sync".tl,
|
||||
content: Text(text),
|
||||
actions: [
|
||||
Button.filled(
|
||||
child: Text("Update".tl),
|
||||
onPressed: () {
|
||||
context.pop();
|
||||
importNetworkFolder(
|
||||
networkSource!,
|
||||
widget.folder,
|
||||
networkFolder!,
|
||||
).then(
|
||||
(value) {
|
||||
updateComics();
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
child: Builder(builder: (context) {
|
||||
return IconButton(
|
||||
icon: const Icon(Icons.sync),
|
||||
onPressed: () {
|
||||
Flyout.of(context).show();
|
||||
},
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
MenuButton(
|
||||
entries: [
|
||||
MenuEntry(
|
||||
|
@@ -108,6 +108,17 @@ class _NormalFavoritePageState extends State<_NormalFavoritePage> {
|
||||
onTap: context.width < _kTwoPanelChangeWidth ? showFolders : null,
|
||||
child: Text(widget.data.title),
|
||||
),
|
||||
actions: [
|
||||
MenuButton(entries: [
|
||||
MenuEntry(
|
||||
icon: Icons.sync,
|
||||
text: "Convert to local".tl,
|
||||
onClick: () {
|
||||
importNetworkFolder(widget.data.key, null, null);
|
||||
},
|
||||
)
|
||||
]),
|
||||
],
|
||||
),
|
||||
errorLeading: Appbar(
|
||||
leading: Tooltip(
|
||||
@@ -533,6 +544,17 @@ class _FavoriteFolder extends StatelessWidget {
|
||||
key: comicListKey,
|
||||
leadingSliver: SliverAppbar(
|
||||
title: Text(title),
|
||||
actions: [
|
||||
MenuButton(entries: [
|
||||
MenuEntry(
|
||||
icon: Icons.sync,
|
||||
text: "Convert to local".tl,
|
||||
onClick: () {
|
||||
importNetworkFolder(data.key, title, folderID);
|
||||
},
|
||||
)
|
||||
]),
|
||||
],
|
||||
),
|
||||
errorLeading: Appbar(
|
||||
title: Text(title),
|
||||
|
Reference in New Issue
Block a user