Skip to content

Commit

Permalink
bookmark: use Storage Access Framework to export bookmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
sliverappbar committed Oct 15, 2023
1 parent 921fa12 commit b3b4243
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 24 deletions.
69 changes: 69 additions & 0 deletions android/app/src/main/kotlin/xyz/project/violet/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package xyz.project.violet

import android.app.Activity
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.Environment
Expand All @@ -13,6 +15,8 @@ import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugins.GeneratedPluginRegistrant
import java.io.FileInputStream
import java.io.FileOutputStream

class MainActivity : FlutterFragmentActivity() {
private val VOLUME_CHANNEL = "xyz.project.violet/volume"
Expand Down Expand Up @@ -82,6 +86,7 @@ class MainActivity : FlutterFragmentActivity() {
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, MISC_CHANNEL).setMethodCallHandler { call, result ->
when (call.method) {
"finishMainActivity" -> finishMainActivity(call, result)
"exportFile" -> exportFile(call, result)
else -> result.notImplemented()
}
}
Expand All @@ -100,4 +105,68 @@ class MainActivity : FlutterFragmentActivity() {
finish()
result.success(null)
}

private class ExportFileRequest(
val filePath: String,
val call: MethodCall,
val result: MethodChannel.Result,
)

private var nextExportFileRequestCode = 1000001;
private val exportFileRequestMap = hashMapOf<Int, ExportFileRequest>()

private fun exportFile(call: MethodCall, result: MethodChannel.Result) {
val filePath = call.argument<String>("filePath")

if (filePath == null) {
result.error("noArgument", "filePath", null)
return
}

try {
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "application/vnd.sqlite3"
putExtra(Intent.EXTRA_TITLE, "violet-bookmarks.db")
}

exportFileRequestMap[nextExportFileRequestCode] =
ExportFileRequest(filePath, call, result)
startActivityForResult(intent, nextExportFileRequestCode++);
} catch (e: Throwable) {
result.error("exception", e.toString(), e);
}
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)

val request = exportFileRequestMap[requestCode] ?: return

try {
if (resultCode != Activity.RESULT_OK) {
request.result.error("intentResultFail", "resultCode=$resultCode", null)
return
}

try {
val uri = data!!.data!!
val targetFileDescriptor = contentResolver.openFileDescriptor(uri, "w")

val input = FileInputStream(request.filePath)
val output = FileOutputStream(targetFileDescriptor!!.fileDescriptor)

input.copyTo(output)

input.close()
output.close()

request.result.success(null)
} catch (e: Throwable) {
request.result.error("exception", e.toString(), e);
}
} finally {
exportFileRequestMap.remove(requestCode)
}
}
}
56 changes: 32 additions & 24 deletions lib/pages/settings/settings_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import 'package:violet/pages/settings/tag_rebuild_page.dart';
import 'package:violet/pages/settings/tag_selector.dart';
import 'package:violet/pages/settings/version_page.dart';
import 'package:violet/pages/splash/splash_page.dart';
import 'package:violet/platform/misc.dart';
import 'package:violet/server/violet.dart';
import 'package:violet/settings/settings.dart';
import 'package:violet/style/palette.dart';
Expand Down Expand Up @@ -1994,36 +1995,43 @@ class _SettingsPageState extends State<SettingsPage>
title: Text(Translations.of(context).trans('exportingbookmark')),
trailing: const Icon(Icons.keyboard_arrow_right),
onTap: () async {
if (!await Permission.storage.isGranted) {
if (await Permission.storage.request() ==
PermissionStatus.denied) {
flutterToast.showToast(
child: ToastWrapper(
isCheck: false,
msg: Translations.of(context).trans('noauth'),
),
gravity: ToastGravity.BOTTOM,
toastDuration: const Duration(seconds: 4),
);
final dir = Platform.isIOS
? await getApplicationSupportDirectory()
: (await getApplicationDocumentsDirectory());
final bookmarkDatabaseFile = File('${dir.path}/user.db');

return;
}
}
if (Platform.isAndroid) {
await PlatformMiscMethods.instance.exportFile(
bookmarkDatabaseFile.path,
);
} else {
if (!await Permission.storage.isGranted) {
if (await Permission.storage.request() ==
PermissionStatus.denied) {
flutterToast.showToast(
child: ToastWrapper(
isCheck: false,
msg: Translations.of(context).trans('noauth'),
),
gravity: ToastGravity.BOTTOM,
toastDuration: const Duration(seconds: 4),
);

final selectedPath = await FilePicker.platform.getDirectoryPath();
return;
}
}

if (selectedPath == null) {
return;
}
final selectedPath =
await FilePicker.platform.getDirectoryPath();

final db = Platform.isIOS
? await getApplicationSupportDirectory()
: (await getApplicationDocumentsDirectory());
final dbfile = File('${db.path}/user.db');
if (selectedPath == null) {
return;
}

final extpath = '$selectedPath/bookmark.db';
final extpath = '$selectedPath/bookmark.db';

await dbfile.copy(extpath);
await bookmarkDatabaseFile.copy(extpath);
}

flutterToast.showToast(
child: ToastWrapper(
Expand Down
13 changes: 13 additions & 0 deletions lib/platform/misc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,17 @@ class PlatformMiscMethods {

await _methodChannel.invokeMethod('finishMainActivity');
}

Future<void> exportFile(String filePath) async {
if (!Platform.isAndroid) {
throw UnsupportedError('Android only');
}

await _methodChannel.invokeMethod<String>(
'exportFile',
<String, dynamic>{
'filePath': filePath,
},
);
}
}

0 comments on commit b3b4243

Please sign in to comment.