parent
8ae8de9612
commit
537a1b960d
|
@ -5,9 +5,9 @@ import {FileSystem} from 'react-native-file-access';
|
||||||
import {Divider, IconButton, Menu} from 'react-native-paper';
|
import {Divider, IconButton, Menu} from 'react-native-paper';
|
||||||
import {DatabaseContext, DrawerParamList, SnackbarContext} from './App';
|
import {DatabaseContext, DrawerParamList, SnackbarContext} from './App';
|
||||||
import ConfirmDialog from './ConfirmDialog';
|
import ConfirmDialog from './ConfirmDialog';
|
||||||
import {useWrite} from './file';
|
|
||||||
import {Plan} from './plan';
|
import {Plan} from './plan';
|
||||||
import Set from './set';
|
import Set from './set';
|
||||||
|
import {write} from './write';
|
||||||
|
|
||||||
const setFields = 'id,name,reps,weight,created,unit';
|
const setFields = 'id,name,reps,weight,created,unit';
|
||||||
const planFields = 'id,days,workouts';
|
const planFields = 'id,days,workouts';
|
||||||
|
@ -18,7 +18,6 @@ export default function DrawerMenu({name}: {name: keyof DrawerParamList}) {
|
||||||
const db = useContext(DatabaseContext);
|
const db = useContext(DatabaseContext);
|
||||||
const {toast} = useContext(SnackbarContext);
|
const {toast} = useContext(SnackbarContext);
|
||||||
const {reset} = useNavigation<NavigationProp<DrawerParamList>>();
|
const {reset} = useNavigation<NavigationProp<DrawerParamList>>();
|
||||||
const {write} = useWrite();
|
|
||||||
|
|
||||||
const exportSets = useCallback(async () => {
|
const exportSets = useCallback(async () => {
|
||||||
const [result] = await db.executeSql('SELECT * FROM sets');
|
const [result] = await db.executeSql('SELECT * FROM sets');
|
||||||
|
@ -34,7 +33,7 @@ export default function DrawerMenu({name}: {name: keyof DrawerParamList}) {
|
||||||
.join('\n');
|
.join('\n');
|
||||||
console.log(`${DrawerMenu.name}.exportSets`, {length: sets.length});
|
console.log(`${DrawerMenu.name}.exportSets`, {length: sets.length});
|
||||||
await write('sets.csv', data);
|
await write('sets.csv', data);
|
||||||
}, [db, write]);
|
}, [db]);
|
||||||
|
|
||||||
const exportPlans = useCallback(async () => {
|
const exportPlans = useCallback(async () => {
|
||||||
const [result] = await db.executeSql('SELECT * FROM plans');
|
const [result] = await db.executeSql('SELECT * FROM plans');
|
||||||
|
@ -45,7 +44,7 @@ export default function DrawerMenu({name}: {name: keyof DrawerParamList}) {
|
||||||
.join('\n');
|
.join('\n');
|
||||||
console.log(`${DrawerMenu.name}.exportPlans`, {length: sets.length});
|
console.log(`${DrawerMenu.name}.exportPlans`, {length: sets.length});
|
||||||
await write('plans.csv', data);
|
await write('plans.csv', data);
|
||||||
}, [db, write]);
|
}, [db]);
|
||||||
|
|
||||||
const download = useCallback(async () => {
|
const download = useCallback(async () => {
|
||||||
setShowMenu(false);
|
setShowMenu(false);
|
||||||
|
|
51
android/app/src/main/java/com/massive/DownloadModule.kt
Normal file
51
android/app/src/main/java/com/massive/DownloadModule.kt
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
package com.massive
|
||||||
|
|
||||||
|
import android.app.DownloadManager
|
||||||
|
import android.app.NotificationChannel
|
||||||
|
import android.app.NotificationManager
|
||||||
|
import android.app.NotificationManager.IMPORTANCE_DEFAULT
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.app.PendingIntent.FLAG_IMMUTABLE
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Environment
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
import androidx.core.app.NotificationCompat
|
||||||
|
import androidx.core.net.toUri
|
||||||
|
import com.facebook.react.bridge.ReactApplicationContext
|
||||||
|
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
||||||
|
import com.facebook.react.bridge.ReactMethod
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class DownloadModule internal constructor(context: ReactApplicationContext) :
|
||||||
|
ReactContextBaseJavaModule(context) {
|
||||||
|
override fun getName(): String {
|
||||||
|
return "DownloadModule"
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
|
@ReactMethod
|
||||||
|
fun show(name: String) {
|
||||||
|
val channel = NotificationChannel(CHANNEL_ID, CHANNEL_ID, IMPORTANCE_DEFAULT)
|
||||||
|
channel.description = "Notifications for downloaded files."
|
||||||
|
val manager =
|
||||||
|
reactApplicationContext.getSystemService(NotificationManager::class.java)
|
||||||
|
manager.createNotificationChannel(channel)
|
||||||
|
val intent = Intent(DownloadManager.ACTION_VIEW_DOWNLOADS)
|
||||||
|
val pendingIntent =
|
||||||
|
PendingIntent.getActivity(reactApplicationContext, 0, intent, FLAG_IMMUTABLE)
|
||||||
|
val builder = NotificationCompat.Builder(reactApplicationContext, CHANNEL_ID)
|
||||||
|
.setSmallIcon(R.drawable.ic_baseline_arrow_downward_24)
|
||||||
|
.setContentTitle("Downloaded $name")
|
||||||
|
.setContentIntent(pendingIntent)
|
||||||
|
.setAutoCancel(true)
|
||||||
|
manager.notify(NOTIFICATION_ID, builder.build())
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val CHANNEL_ID = "MassiveDownloads"
|
||||||
|
private const val NOTIFICATION_ID = 3
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ class MassivePackage : ReactPackage {
|
||||||
): List<NativeModule> {
|
): List<NativeModule> {
|
||||||
val modules: MutableList<NativeModule> = ArrayList()
|
val modules: MutableList<NativeModule> = ArrayList()
|
||||||
modules.add(AlarmModule(reactContext))
|
modules.add(AlarmModule(reactContext))
|
||||||
|
modules.add(DownloadModule(reactContext))
|
||||||
return modules
|
return modules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
26
file.ts
26
file.ts
|
@ -1,26 +0,0 @@
|
||||||
import {useContext} from 'react';
|
|
||||||
import {PermissionsAndroid} from 'react-native';
|
|
||||||
import {Dirs, FileSystem} from 'react-native-file-access';
|
|
||||||
import {SnackbarContext} from './App';
|
|
||||||
|
|
||||||
export const useWrite = () => {
|
|
||||||
const {toast} = useContext(SnackbarContext);
|
|
||||||
|
|
||||||
return {
|
|
||||||
write: async (name: string, data: string) => {
|
|
||||||
const filePath = `${Dirs.DocumentDir}/${name}`;
|
|
||||||
const permission = async () => {
|
|
||||||
const granted = await PermissionsAndroid.request(
|
|
||||||
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
|
|
||||||
);
|
|
||||||
return granted === PermissionsAndroid.RESULTS.GRANTED;
|
|
||||||
};
|
|
||||||
const granted = await permission();
|
|
||||||
if (!granted) return;
|
|
||||||
await FileSystem.writeFile(filePath, data);
|
|
||||||
if (!FileSystem.exists(filePath)) return;
|
|
||||||
await FileSystem.cpExternal(filePath, name, 'downloads');
|
|
||||||
toast(`Saved "${name}" in your downloads folder.`, 6000);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
18
write.ts
Normal file
18
write.ts
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import {NativeModules, PermissionsAndroid} from 'react-native';
|
||||||
|
import {Dirs, FileSystem} from 'react-native-file-access';
|
||||||
|
|
||||||
|
export const write = async (name: string, data: string) => {
|
||||||
|
const filePath = `${Dirs.DocumentDir}/${name}`;
|
||||||
|
const permission = async () => {
|
||||||
|
const granted = await PermissionsAndroid.request(
|
||||||
|
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
|
||||||
|
);
|
||||||
|
return granted === PermissionsAndroid.RESULTS.GRANTED;
|
||||||
|
};
|
||||||
|
const granted = await permission();
|
||||||
|
if (!granted) return;
|
||||||
|
await FileSystem.writeFile(filePath, data);
|
||||||
|
if (!FileSystem.exists(filePath)) return;
|
||||||
|
await FileSystem.cpExternal(filePath, name, 'downloads');
|
||||||
|
NativeModules.DownloadModule.show(name);
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user