Choose directory when backing up automatically - 1.135
Related to #146.
This commit is contained in:
parent
2fb46e1dcc
commit
76e5aeacfd
|
@ -6,6 +6,7 @@ import {NativeModules, ScrollView, View} from 'react-native'
|
||||||
import DocumentPicker from 'react-native-document-picker'
|
import DocumentPicker from 'react-native-document-picker'
|
||||||
import {Dirs, FileSystem} from 'react-native-file-access'
|
import {Dirs, FileSystem} from 'react-native-file-access'
|
||||||
import {Button, Subheading} from 'react-native-paper'
|
import {Button, Subheading} from 'react-native-paper'
|
||||||
|
import {PERMISSIONS, request} from 'react-native-permissions'
|
||||||
import ConfirmDialog from './ConfirmDialog'
|
import ConfirmDialog from './ConfirmDialog'
|
||||||
import {ITEM_PADDING, MARGIN} from './constants'
|
import {ITEM_PADDING, MARGIN} from './constants'
|
||||||
import {AppDataSource} from './data-source'
|
import {AppDataSource} from './data-source'
|
||||||
|
@ -134,8 +135,14 @@ export default function SettingsPage() {
|
||||||
return
|
return
|
||||||
case 'backup':
|
case 'backup':
|
||||||
if (value) {
|
if (value) {
|
||||||
|
const granted = await request(
|
||||||
|
PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE,
|
||||||
|
)
|
||||||
|
if (!granted) return
|
||||||
|
const result = await DocumentPicker.pickDirectory()
|
||||||
|
console.log(result.uri)
|
||||||
toast('Backup database daily.')
|
toast('Backup database daily.')
|
||||||
NativeModules.BackupModule.start()
|
NativeModules.BackupModule.start(result.uri)
|
||||||
} else {
|
} else {
|
||||||
toast('Stopped backing up daily')
|
toast('Stopped backing up daily')
|
||||||
NativeModules.BackupModule.stop()
|
NativeModules.BackupModule.stop()
|
||||||
|
|
|
@ -41,8 +41,8 @@ android {
|
||||||
missingDimensionStrategy "RNNotifications.reactNativeVersion", "reactNative60"
|
missingDimensionStrategy "RNNotifications.reactNativeVersion", "reactNative60"
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 36160
|
versionCode 36161
|
||||||
versionName "1.134"
|
versionName "1.135"
|
||||||
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
||||||
|
|
||||||
if (isNewArchitectureEnabled()) {
|
if (isNewArchitectureEnabled()) {
|
||||||
|
|
|
@ -1,75 +1,44 @@
|
||||||
package com.massive
|
package com.massive
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.app.AlarmManager
|
import android.app.AlarmManager
|
||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.BroadcastReceiver
|
import android.content.*
|
||||||
import android.content.Context
|
import android.net.Uri
|
||||||
import android.content.Intent
|
|
||||||
import android.content.IntentFilter
|
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Environment
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.documentfile.provider.DocumentFile
|
||||||
import com.facebook.react.bridge.ReactApplicationContext
|
import com.facebook.react.bridge.ReactApplicationContext
|
||||||
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
||||||
import com.facebook.react.bridge.ReactMethod
|
import com.facebook.react.bridge.ReactMethod
|
||||||
import java.io.File
|
import java.io.*
|
||||||
import java.io.FileInputStream
|
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.io.IOException
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
class BackupModule constructor(context: ReactApplicationContext?) :
|
class BackupModule constructor(context: ReactApplicationContext?) :
|
||||||
ReactContextBaseJavaModule(context) {
|
ReactContextBaseJavaModule(context) {
|
||||||
val context: ReactApplicationContext = reactApplicationContext
|
val context: ReactApplicationContext = reactApplicationContext
|
||||||
|
private var targetDir: String? = null
|
||||||
|
|
||||||
private val copyReceiver = object : BroadcastReceiver() {
|
private val copyReceiver = object : BroadcastReceiver() {
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
|
val treeUri: Uri = Uri.parse(targetDir)
|
||||||
|
val documentFile = context?.let { DocumentFile.fromTreeUri(it, treeUri) }
|
||||||
|
val file = documentFile?.createFile("application/octet-stream", "massive.db")
|
||||||
|
val output = context?.contentResolver?.openOutputStream(file!!.uri)
|
||||||
val sourceFile = File(context?.getDatabasePath("massive.db")!!.path)
|
val sourceFile = File(context?.getDatabasePath("massive.db")!!.path)
|
||||||
val targetDir =
|
|
||||||
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
|
|
||||||
val targetFile = File(targetDir, "massive.db")
|
|
||||||
|
|
||||||
try {
|
|
||||||
val input = FileInputStream(sourceFile)
|
val input = FileInputStream(sourceFile)
|
||||||
val output = FileOutputStream(targetFile)
|
if (output != null) {
|
||||||
input.copyTo(output)
|
input.copyTo(output)
|
||||||
input.close()
|
|
||||||
output.close()
|
|
||||||
} catch (e: IOException) {
|
|
||||||
Toast.makeText(
|
|
||||||
reactApplicationContext,
|
|
||||||
"Access to massive.db is denied. Try deleting it first.",
|
|
||||||
Toast.LENGTH_LONG
|
|
||||||
).show()
|
|
||||||
}
|
}
|
||||||
|
output?.flush()
|
||||||
|
output?.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.M)
|
@RequiresApi(Build.VERSION_CODES.M)
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
fun start() {
|
fun start(baseUri: String) {
|
||||||
val permission: Int =
|
targetDir = baseUri
|
||||||
ActivityCompat.checkSelfPermission(
|
|
||||||
reactApplicationContext,
|
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
|
||||||
)
|
|
||||||
if (permission != PackageManager.PERMISSION_GRANTED) {
|
|
||||||
ActivityCompat.requestPermissions(
|
|
||||||
currentActivity!!,
|
|
||||||
arrayOf<String>(
|
|
||||||
Manifest.permission.READ_EXTERNAL_STORAGE,
|
|
||||||
Manifest.permission.WRITE_EXTERNAL_STORAGE
|
|
||||||
),
|
|
||||||
1
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
val alarmMgr = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||||
val intent = Intent(COPY_BROADCAST)
|
val intent = Intent(COPY_BROADCAST)
|
||||||
val pendingIntent =
|
val pendingIntent =
|
||||||
|
|
|
@ -11,6 +11,7 @@ NativeModules.SettingsModule = NativeModules.SettingsModule || {
|
||||||
|
|
||||||
jest.mock('react-native-file-access', () => jest.fn())
|
jest.mock('react-native-file-access', () => jest.fn())
|
||||||
jest.mock('react-native-share', () => jest.fn())
|
jest.mock('react-native-share', () => jest.fn())
|
||||||
|
jest.mock('react-native-permissions', () => jest.fn())
|
||||||
jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper')
|
jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper')
|
||||||
jest.mock('react-native/Libraries/EventEmitter/NativeEventEmitter')
|
jest.mock('react-native/Libraries/EventEmitter/NativeEventEmitter')
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "massive",
|
"name": "massive",
|
||||||
"version": "1.134",
|
"version": "1.135",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "GPL-3.0-only",
|
"license": "GPL-3.0-only",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -39,6 +39,7 @@
|
||||||
"react-native-linear-gradient": "^2.6.2",
|
"react-native-linear-gradient": "^2.6.2",
|
||||||
"react-native-pager-view": "^6.0.1",
|
"react-native-pager-view": "^6.0.1",
|
||||||
"react-native-paper": "^4.12.5",
|
"react-native-paper": "^4.12.5",
|
||||||
|
"react-native-permissions": "^3.8.0",
|
||||||
"react-native-reanimated": "^2.12.0",
|
"react-native-reanimated": "^2.12.0",
|
||||||
"react-native-safe-area-context": "^4.4.1",
|
"react-native-safe-area-context": "^4.4.1",
|
||||||
"react-native-screens": "^3.18.2",
|
"react-native-screens": "^3.18.2",
|
||||||
|
|
27
yarn.lock
27
yarn.lock
|
@ -7313,6 +7313,7 @@ __metadata:
|
||||||
react-native-linear-gradient: ^2.6.2
|
react-native-linear-gradient: ^2.6.2
|
||||||
react-native-pager-view: ^6.0.1
|
react-native-pager-view: ^6.0.1
|
||||||
react-native-paper: ^4.12.5
|
react-native-paper: ^4.12.5
|
||||||
|
react-native-permissions: ^3.8.0
|
||||||
react-native-reanimated: ^2.12.0
|
react-native-reanimated: ^2.12.0
|
||||||
react-native-safe-area-context: ^4.4.1
|
react-native-safe-area-context: ^4.4.1
|
||||||
react-native-screens: ^3.18.2
|
react-native-screens: ^3.18.2
|
||||||
|
@ -8592,6 +8593,15 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"pkg-dir@npm:^5.0.0":
|
||||||
|
version: 5.0.0
|
||||||
|
resolution: "pkg-dir@npm:5.0.0"
|
||||||
|
dependencies:
|
||||||
|
find-up: ^5.0.0
|
||||||
|
checksum: b167bb8dac7bbf22b1d5e30ec223e6b064b84b63010c9d49384619a36734caf95ed23ad23d4f9bd975e8e8082b60a83395f43a89bb192df53a7c25a38ecb57d9
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"posix-character-classes@npm:^0.1.0":
|
"posix-character-classes@npm:^0.1.0":
|
||||||
version: 0.1.1
|
version: 0.1.1
|
||||||
resolution: "posix-character-classes@npm:0.1.1"
|
resolution: "posix-character-classes@npm:0.1.1"
|
||||||
|
@ -8898,6 +8908,23 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"react-native-permissions@npm:^3.8.0":
|
||||||
|
version: 3.8.0
|
||||||
|
resolution: "react-native-permissions@npm:3.8.0"
|
||||||
|
dependencies:
|
||||||
|
picocolors: ^1.0.0
|
||||||
|
pkg-dir: ^5.0.0
|
||||||
|
peerDependencies:
|
||||||
|
react: ">=16.13.1"
|
||||||
|
react-native: ">=0.63.3"
|
||||||
|
react-native-windows: ">=0.62.0"
|
||||||
|
peerDependenciesMeta:
|
||||||
|
react-native-windows:
|
||||||
|
optional: true
|
||||||
|
checksum: acbd8605adabfc48e19fbc468a3a143fb85bd34d3ed0fe6a4b52f16304591b8a4b3c561a507c11643fcc8ce1b4dc09e31f149387d1ea461098a2e40c43989f7c
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"react-native-reanimated@npm:^2.12.0":
|
"react-native-reanimated@npm:^2.12.0":
|
||||||
version: 2.12.0
|
version: 2.12.0
|
||||||
resolution: "react-native-reanimated@npm:2.12.0"
|
resolution: "react-native-reanimated@npm:2.12.0"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user