2023-08-12 03:22:50 +00:00
|
|
|
import { NavigationProp, useNavigation } from "@react-navigation/native";
|
|
|
|
import { format } from "date-fns";
|
|
|
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
|
|
import { useForm } from "react-hook-form";
|
2023-11-12 06:07:58 +00:00
|
|
|
import { FlatList, NativeModules } from "react-native";
|
2023-08-12 03:22:50 +00:00
|
|
|
import DocumentPicker from "react-native-document-picker";
|
|
|
|
import { Dirs, FileSystem } from "react-native-file-access";
|
2023-11-12 03:56:07 +00:00
|
|
|
import { Button } from "react-native-paper";
|
|
|
|
import AppInput from "./AppInput";
|
2023-08-12 03:22:50 +00:00
|
|
|
import ConfirmDialog from "./ConfirmDialog";
|
2023-11-12 06:07:58 +00:00
|
|
|
import { PADDING } from "./constants";
|
2023-08-12 03:22:50 +00:00
|
|
|
import { AppDataSource } from "./data-source";
|
|
|
|
import { setRepo, settingsRepo } from "./db";
|
2023-11-14 22:08:00 +00:00
|
|
|
import { DrawerParams } from "./drawer-params";
|
2023-11-14 22:21:49 +00:00
|
|
|
import DrawerHeader from "./DrawerHeader";
|
2023-08-12 03:22:50 +00:00
|
|
|
import { darkOptions, lightOptions, themeOptions } from "./options";
|
2023-11-14 22:21:49 +00:00
|
|
|
import Page from "./Page";
|
|
|
|
import Select from "./Select";
|
2023-11-12 03:56:07 +00:00
|
|
|
import Settings from "./settings";
|
2023-11-14 22:21:49 +00:00
|
|
|
import Switch from "./Switch";
|
2023-08-12 03:22:50 +00:00
|
|
|
import { toast } from "./toast";
|
2023-11-14 01:45:15 +00:00
|
|
|
import { useAppTheme } from "./use-theme";
|
2022-07-08 03:45:24 +00:00
|
|
|
|
2023-06-17 23:30:28 +00:00
|
|
|
const twelveHours = [
|
2023-08-12 03:22:50 +00:00
|
|
|
"dd/LL/yyyy",
|
|
|
|
"dd/LL/yyyy, p",
|
|
|
|
"ccc p",
|
|
|
|
"p",
|
2024-02-05 01:24:53 +00:00
|
|
|
"yyyy-MM-dd",
|
|
|
|
"yyyy-MM-dd, p",
|
|
|
|
"yyyy.MM.dd",
|
2023-08-12 03:22:50 +00:00
|
|
|
];
|
2023-11-20 21:16:31 +00:00
|
|
|
|
2023-06-17 23:30:28 +00:00
|
|
|
const twentyFours = [
|
2023-08-12 03:22:50 +00:00
|
|
|
"dd/LL/yyyy",
|
2024-01-16 11:13:23 +00:00
|
|
|
"dd/LL/yyyy, k:mm",
|
|
|
|
"ccc k:mm",
|
|
|
|
"k:mm",
|
|
|
|
"yyyy-MM-dd",
|
|
|
|
"yyyy-MM-dd, k:mm",
|
|
|
|
"yyyy.MM.dd",
|
2023-08-12 03:22:50 +00:00
|
|
|
];
|
2022-11-21 05:15:43 +00:00
|
|
|
|
2023-11-12 06:07:58 +00:00
|
|
|
interface Item {
|
|
|
|
name: string;
|
|
|
|
renderItem: (name: string) => React.JSX.Element;
|
|
|
|
}
|
|
|
|
|
2022-07-08 03:20:03 +00:00
|
|
|
export default function SettingsPage() {
|
2023-08-12 03:22:50 +00:00
|
|
|
const [ignoring, setIgnoring] = useState(false);
|
|
|
|
const [term, setTerm] = useState("");
|
|
|
|
const [formatOptions, setFormatOptions] = useState<string[]>(twelveHours);
|
|
|
|
const [importing, setImporting] = useState(false);
|
|
|
|
const [deleting, setDeleting] = useState(false);
|
2023-11-14 23:14:47 +00:00
|
|
|
const [error, setError] = useState("");
|
2023-10-28 02:59:03 +00:00
|
|
|
const { reset } = useNavigation<NavigationProp<DrawerParams>>();
|
2022-10-18 08:43:46 +00:00
|
|
|
|
2023-06-27 03:16:59 +00:00
|
|
|
const { watch, setValue } = useForm<Settings>({
|
|
|
|
defaultValues: () => settingsRepo.findOne({ where: {} }),
|
2023-08-12 03:22:50 +00:00
|
|
|
});
|
|
|
|
const settings = watch();
|
2022-12-30 02:45:18 +00:00
|
|
|
|
2023-06-27 03:16:59 +00:00
|
|
|
const {
|
|
|
|
theme,
|
|
|
|
setTheme,
|
|
|
|
lightColor,
|
|
|
|
setLightColor,
|
|
|
|
darkColor,
|
|
|
|
setDarkColor,
|
2023-11-14 01:45:15 +00:00
|
|
|
} = useAppTheme();
|
2022-12-29 04:27:43 +00:00
|
|
|
|
2022-12-29 00:52:38 +00:00
|
|
|
useEffect(() => {
|
2024-02-13 22:14:43 +00:00
|
|
|
NativeModules.SettingsModule.ignoringBattery().then(setIgnoring);
|
2022-12-29 00:52:38 +00:00
|
|
|
NativeModules.SettingsModule.is24().then((is24: boolean) => {
|
2023-08-12 03:22:50 +00:00
|
|
|
console.log(`${SettingsPage.name}.focus:`, { is24 });
|
|
|
|
if (is24) setFormatOptions(twentyFours);
|
|
|
|
else setFormatOptions(twelveHours);
|
|
|
|
});
|
|
|
|
}, []);
|
2022-07-03 01:50:01 +00:00
|
|
|
|
2023-11-13 02:15:18 +00:00
|
|
|
const backupString = useMemo(() => {
|
|
|
|
if (!settings.backupDir) return null;
|
|
|
|
const split = decodeURIComponent(settings.backupDir).split(":");
|
|
|
|
return split.pop();
|
|
|
|
}, [settings.backupDir]);
|
|
|
|
|
2022-12-28 01:15:02 +00:00
|
|
|
const soundString = useMemo(() => {
|
2023-08-12 03:22:50 +00:00
|
|
|
if (!settings.sound) return null;
|
|
|
|
const split = settings.sound.split("/");
|
|
|
|
return split.pop();
|
|
|
|
}, [settings.sound]);
|
2022-12-28 01:15:02 +00:00
|
|
|
|
2023-07-20 02:55:19 +00:00
|
|
|
const confirmDelete = useCallback(async () => {
|
2023-08-12 03:22:50 +00:00
|
|
|
setDeleting(false);
|
|
|
|
await AppDataSource.dropDatabase();
|
|
|
|
await AppDataSource.destroy();
|
|
|
|
await AppDataSource.initialize();
|
|
|
|
toast("Database deleted.");
|
|
|
|
}, []);
|
2023-06-29 03:31:24 +00:00
|
|
|
|
2022-12-08 00:18:41 +00:00
|
|
|
const confirmImport = useCallback(async () => {
|
2023-08-12 03:22:50 +00:00
|
|
|
setImporting(false);
|
2023-11-14 23:14:47 +00:00
|
|
|
await FileSystem.cp(
|
|
|
|
Dirs.DatabaseDir + "/massive.db",
|
|
|
|
Dirs.DatabaseDir + "/massive-backup.db"
|
|
|
|
);
|
2023-08-12 03:22:50 +00:00
|
|
|
await AppDataSource.destroy();
|
|
|
|
const file = await DocumentPicker.pickSingle();
|
2024-02-12 05:48:02 +00:00
|
|
|
if (!file.uri.endsWith('.db'))
|
|
|
|
return toast("File name must end with .db")
|
2023-08-12 03:22:50 +00:00
|
|
|
await FileSystem.cp(file.uri, Dirs.DatabaseDir + "/massive.db");
|
2023-11-14 23:14:47 +00:00
|
|
|
|
|
|
|
try {
|
|
|
|
await AppDataSource.initialize();
|
|
|
|
} catch (e) {
|
|
|
|
setError(e.toString());
|
|
|
|
await FileSystem.cp(
|
|
|
|
Dirs.DatabaseDir + "/massive-backup.db",
|
|
|
|
Dirs.DatabaseDir + "/massive.db"
|
|
|
|
);
|
|
|
|
await AppDataSource.initialize();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-11-20 07:06:45 +00:00
|
|
|
await setRepo.update({}, { image: null });
|
|
|
|
await settingsRepo.update({}, { sound: null, backup: false });
|
2023-11-13 02:15:18 +00:00
|
|
|
reset({ index: 0, routes: [{ name: "Settings" }] });
|
2024-02-17 11:54:51 +00:00
|
|
|
toast("Imported database successfully.")
|
2023-11-20 07:06:45 +00:00
|
|
|
}, [reset]);
|
2022-12-08 00:18:41 +00:00
|
|
|
|
2023-11-12 06:07:58 +00:00
|
|
|
const today = new Date();
|
2022-12-30 07:29:16 +00:00
|
|
|
|
2023-11-12 06:07:58 +00:00
|
|
|
const data: Item[] = [
|
2023-11-12 10:27:28 +00:00
|
|
|
{
|
|
|
|
name: "Start up page",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<Select
|
|
|
|
label={name}
|
|
|
|
items={[
|
2024-02-12 04:31:49 +00:00
|
|
|
{ label: "History", value: "History", icon: 'history' },
|
|
|
|
{ label: "Exercises", value: "Exercises", icon: 'dumbbell' },
|
2024-02-17 12:52:21 +00:00
|
|
|
{ label: "Daily", value: "Daily", icon: 'calendar-outline' },
|
|
|
|
{ label: "Plans", value: "Plans", icon: 'checkbox-multiple-marked-outline' },
|
2024-02-12 04:31:49 +00:00
|
|
|
{ label: "Graphs", value: "Graphs", icon: 'chart-bell-curve-cumulative' },
|
|
|
|
{ label: "Timer", value: "Timer", icon: 'timer-outline' },
|
|
|
|
{ label: "Weight", value: "Weight", icon: 'scale-bathroom' },
|
|
|
|
{ label: "Insights", value: "Insights", icon: 'lightbulb-on-outline' },
|
|
|
|
{ label: "Settings", value: "Settings", icon: 'cog-outline' },
|
2023-11-12 10:27:28 +00:00
|
|
|
]}
|
|
|
|
value={settings.startup}
|
|
|
|
onChange={async (value) => {
|
|
|
|
setValue("startup", value);
|
2023-11-20 07:06:45 +00:00
|
|
|
await settingsRepo.update({}, { startup: value });
|
2023-11-12 10:27:28 +00:00
|
|
|
toast(`App will always start on ${value}`);
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
},
|
2023-11-12 06:07:58 +00:00
|
|
|
{
|
|
|
|
name: "Theme",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<Select
|
|
|
|
label={name}
|
|
|
|
items={themeOptions}
|
|
|
|
value={theme}
|
|
|
|
onChange={async (value) => {
|
|
|
|
setValue("theme", value);
|
|
|
|
setTheme(value);
|
2023-11-20 07:06:45 +00:00
|
|
|
await settingsRepo.update({}, { theme: value });
|
2023-11-12 06:07:58 +00:00
|
|
|
if (value === "dark") toast("Theme will always be dark.");
|
|
|
|
else if (value === "light") toast("Theme will always be light.");
|
|
|
|
else if (value === "system") toast("Theme will follow system.");
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Date format",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<Select
|
|
|
|
label={name}
|
|
|
|
items={formatOptions.map((option) => ({
|
|
|
|
label: format(today, option),
|
|
|
|
value: option,
|
|
|
|
}))}
|
|
|
|
value={settings.date}
|
|
|
|
onChange={async (value) => {
|
|
|
|
setValue("date", value);
|
2023-11-20 07:06:45 +00:00
|
|
|
await settingsRepo.update({}, { date: value });
|
2023-11-12 06:07:58 +00:00
|
|
|
toast("Changed date format.");
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
},
|
2023-11-14 22:00:51 +00:00
|
|
|
{
|
|
|
|
name: "Auto convert",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<Select
|
|
|
|
label={name}
|
|
|
|
items={[
|
2024-02-12 04:31:49 +00:00
|
|
|
{ label: "Off", value: "", icon: 'scale-off' },
|
|
|
|
{ label: "Kilograms", value: "kg", icon: 'weight-kilogram' },
|
|
|
|
{ label: "Pounds", value: "lb", icon: 'weight-pound' },
|
|
|
|
{ label: "Stone", value: "stone", icon: 'weight' },
|
2023-11-14 22:00:51 +00:00
|
|
|
]}
|
|
|
|
value={settings.autoConvert}
|
|
|
|
onChange={async (value) => {
|
|
|
|
setValue("autoConvert", value);
|
2023-11-20 07:06:45 +00:00
|
|
|
await settingsRepo.update({}, { autoConvert: value });
|
2023-11-14 22:00:51 +00:00
|
|
|
if (value) toast(`Sets now automatically convert to ${value}`);
|
|
|
|
else toast("Stopped automatically converting sets.");
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
},
|
2023-11-12 06:07:58 +00:00
|
|
|
{
|
|
|
|
name: "Vibration duration (ms)",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<AppInput
|
|
|
|
value={settings.duration?.toString() ?? "300"}
|
|
|
|
label={name}
|
|
|
|
onChangeText={(value) => setValue("duration", Number(value))}
|
|
|
|
onSubmitEditing={async (e) => {
|
2023-11-20 07:06:45 +00:00
|
|
|
const value = Number(e.nativeEvent.text);
|
|
|
|
setValue("duration", value);
|
|
|
|
await settingsRepo.update({}, { duration: value });
|
2023-11-12 06:07:58 +00:00
|
|
|
toast("Changed duration of alarm vibrations.");
|
|
|
|
}}
|
|
|
|
keyboardType="numeric"
|
|
|
|
blurOnSubmit
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
},
|
2023-11-15 01:03:43 +00:00
|
|
|
{
|
|
|
|
name: "Default sets",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<AppInput
|
|
|
|
value={settings.defaultSets?.toString() ?? "3"}
|
|
|
|
label={name}
|
|
|
|
onChangeText={(value) => setValue("defaultSets", Number(value))}
|
|
|
|
onSubmitEditing={async (e) => {
|
2023-11-20 07:06:45 +00:00
|
|
|
const value = Number(e.nativeEvent.text);
|
|
|
|
setValue("defaultSets", value);
|
|
|
|
await settingsRepo.update({}, { defaultSets: value });
|
2023-11-15 01:03:43 +00:00
|
|
|
toast(`New exercises now have ${value} sets by default.`);
|
|
|
|
}}
|
|
|
|
keyboardType="numeric"
|
|
|
|
blurOnSubmit
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Default minutes",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<AppInput
|
|
|
|
value={settings.defaultMinutes?.toString() ?? "3"}
|
|
|
|
label={name}
|
|
|
|
onChangeText={(value) => setValue("defaultMinutes", Number(value))}
|
|
|
|
onSubmitEditing={async (e) => {
|
2023-11-20 07:06:45 +00:00
|
|
|
const value = Number(e.nativeEvent.text);
|
|
|
|
setValue("defaultMinutes", value);
|
|
|
|
await settingsRepo.update({}, { defaultMinutes: value });
|
2023-11-15 01:03:43 +00:00
|
|
|
toast(`New exercises now wait ${value} minutes by default.`);
|
|
|
|
}}
|
|
|
|
keyboardType="numeric"
|
|
|
|
blurOnSubmit
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Default seconds",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<AppInput
|
|
|
|
value={settings.defaultSeconds?.toString() ?? "30"}
|
|
|
|
label={name}
|
|
|
|
onChangeText={(value) => setValue("defaultSeconds", Number(value))}
|
|
|
|
onSubmitEditing={async (e) => {
|
2023-11-20 07:06:45 +00:00
|
|
|
const value = Number(e.nativeEvent.text);
|
|
|
|
setValue("defaultSeconds", value);
|
|
|
|
await settingsRepo.update({}, { defaultSeconds: value });
|
2023-11-15 01:03:43 +00:00
|
|
|
toast(`New exercises now wait ${value} seconds by default.`);
|
|
|
|
}}
|
|
|
|
keyboardType="numeric"
|
|
|
|
blurOnSubmit
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
},
|
2024-02-07 02:49:05 +00:00
|
|
|
{
|
|
|
|
name: "Dark color",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<Select
|
|
|
|
label={name}
|
|
|
|
items={lightOptions}
|
|
|
|
value={darkColor}
|
|
|
|
onChange={async (value) => {
|
|
|
|
setValue("darkColor", value);
|
|
|
|
setDarkColor(value);
|
|
|
|
await settingsRepo.update({}, { darkColor: value });
|
|
|
|
toast("Set primary color for dark mode.");
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Light color",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<Select
|
|
|
|
label={name}
|
|
|
|
items={darkOptions}
|
|
|
|
value={lightColor}
|
|
|
|
onChange={async (value) => {
|
|
|
|
setValue("lightColor", value);
|
|
|
|
setLightColor(value);
|
|
|
|
await settingsRepo.update({}, { lightColor: value });
|
|
|
|
toast("Set primary color for light mode.");
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
},
|
2023-11-12 06:07:58 +00:00
|
|
|
{
|
|
|
|
name: "Rest timers",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<Switch
|
|
|
|
value={settings.alarm}
|
|
|
|
onChange={async (value) => {
|
|
|
|
setValue("alarm", value);
|
2023-11-20 07:06:45 +00:00
|
|
|
if (value && !ignoring) {
|
2023-11-12 06:07:58 +00:00
|
|
|
NativeModules.SettingsModule.ignoreBattery();
|
2023-11-20 07:06:45 +00:00
|
|
|
}
|
|
|
|
await settingsRepo.update({}, { alarm: value });
|
2023-11-12 06:07:58 +00:00
|
|
|
if (value) toast("Timers will now run after each set.");
|
|
|
|
else toast("Stopped timers running after each set.");
|
|
|
|
}}
|
|
|
|
title={name}
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Vibrate",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<Switch
|
|
|
|
value={settings.vibrate}
|
|
|
|
onChange={async (value) => {
|
|
|
|
setValue("vibrate", value);
|
2023-11-20 07:06:45 +00:00
|
|
|
await settingsRepo.update({}, { vibrate: value });
|
2024-02-17 11:46:21 +00:00
|
|
|
if (value) toast("Alarms will vibrate.");
|
|
|
|
else toast("Stopped alarms from vibrating.");
|
2023-11-12 06:07:58 +00:00
|
|
|
}}
|
|
|
|
title={name}
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
2024-02-17 07:57:29 +00:00
|
|
|
name: "Sound",
|
2023-11-12 06:07:58 +00:00
|
|
|
renderItem: (name: string) => (
|
|
|
|
<Switch
|
2024-02-17 07:57:29 +00:00
|
|
|
value={!settings.noSound}
|
2023-11-12 06:07:58 +00:00
|
|
|
onChange={async (value) => {
|
2024-02-17 07:57:29 +00:00
|
|
|
setValue("noSound", !value);
|
|
|
|
await settingsRepo.update({}, { noSound: !value });
|
|
|
|
if (!value) toast("Alarms will no longer make a sound.");
|
2023-11-12 06:07:58 +00:00
|
|
|
else toast("Enabled sound for alarms.");
|
|
|
|
}}
|
|
|
|
title={name}
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Notifications",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<Switch
|
|
|
|
value={settings.notify}
|
|
|
|
onChange={async (value) => {
|
|
|
|
setValue("notify", value);
|
2023-11-20 07:06:45 +00:00
|
|
|
await settingsRepo.update({}, { notify: value });
|
2023-11-12 06:07:58 +00:00
|
|
|
if (value) toast("Show notifications for new records.");
|
|
|
|
else toast("Stopped notifications for new records.");
|
|
|
|
}}
|
|
|
|
title={name}
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Show images",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<Switch
|
|
|
|
value={settings.images}
|
|
|
|
onChange={async (value) => {
|
|
|
|
setValue("images", value);
|
2023-11-20 07:06:45 +00:00
|
|
|
await settingsRepo.update({}, { images: value });
|
2023-11-12 06:07:58 +00:00
|
|
|
if (value) toast("Show images for sets.");
|
|
|
|
else toast("Hid images for sets.");
|
|
|
|
}}
|
|
|
|
title={name}
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Show unit",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<Switch
|
|
|
|
value={settings.showUnit}
|
|
|
|
onChange={async (value) => {
|
|
|
|
setValue("showUnit", value);
|
2023-11-20 07:06:45 +00:00
|
|
|
await settingsRepo.update({}, { showUnit: value });
|
2023-11-12 06:07:58 +00:00
|
|
|
if (value) toast("Show option to select unit for sets.");
|
|
|
|
else toast("Hid unit option for sets.");
|
|
|
|
}}
|
|
|
|
title={name}
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Show date",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<Switch
|
|
|
|
value={settings.showDate}
|
|
|
|
onChange={async (value) => {
|
|
|
|
setValue("showDate", value);
|
2023-11-20 07:06:45 +00:00
|
|
|
await settingsRepo.update({}, { showDate: value });
|
2023-11-12 06:07:58 +00:00
|
|
|
if (value) toast("Show date for sets.");
|
|
|
|
else toast("Hid date on sets.");
|
|
|
|
}}
|
|
|
|
title={name}
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Automatic backup",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<Switch
|
|
|
|
value={settings.backup}
|
|
|
|
onChange={async (value) => {
|
|
|
|
setValue("backup", value);
|
2023-11-20 07:06:45 +00:00
|
|
|
await settingsRepo.update({}, { backup: value });
|
2023-11-12 06:07:58 +00:00
|
|
|
if (value) {
|
|
|
|
const result = await DocumentPicker.pickDirectory();
|
2023-11-13 02:15:18 +00:00
|
|
|
setValue("backupDir", result.uri);
|
2023-11-20 07:06:45 +00:00
|
|
|
await settingsRepo.update({}, { backupDir: result.uri });
|
2023-11-13 02:15:18 +00:00
|
|
|
console.log(`${SettingsPage.name}.backup:`, { result });
|
2023-11-12 06:07:58 +00:00
|
|
|
toast("Backup database daily.");
|
|
|
|
NativeModules.BackupModule.start(result.uri);
|
|
|
|
} else {
|
|
|
|
toast("Stopped backing up daily");
|
|
|
|
NativeModules.BackupModule.stop();
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
title={name}
|
|
|
|
/>
|
|
|
|
),
|
|
|
|
},
|
2023-11-13 02:15:18 +00:00
|
|
|
{
|
2024-02-12 02:15:34 +00:00
|
|
|
name: `Backup directory: ${backupString || "Not set yet!"}`,
|
2023-11-13 02:15:18 +00:00
|
|
|
renderItem: (name: string) => (
|
|
|
|
<Button
|
|
|
|
style={{ alignSelf: "flex-start" }}
|
|
|
|
onPress={async () => {
|
|
|
|
const result = await DocumentPicker.pickDirectory();
|
|
|
|
setValue("backupDir", result.uri);
|
2023-11-20 07:06:45 +00:00
|
|
|
await settingsRepo.update({}, { backupDir: result.uri });
|
2023-11-13 02:15:18 +00:00
|
|
|
toast("Changed backup directory.");
|
|
|
|
if (!settings.backup) return;
|
|
|
|
NativeModules.BackupModule.stop();
|
|
|
|
NativeModules.BackupModule.start(result.uri);
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{name}
|
|
|
|
</Button>
|
|
|
|
),
|
|
|
|
},
|
2023-11-12 06:07:58 +00:00
|
|
|
{
|
|
|
|
name: `Alarm sound: ${soundString || "Default"}`,
|
|
|
|
renderItem: (name: string) => (
|
2023-11-09 00:14:11 +00:00
|
|
|
<Button
|
|
|
|
style={{ alignSelf: "flex-start" }}
|
2023-11-12 06:07:58 +00:00
|
|
|
onPress={async () => {
|
|
|
|
const { fileCopyUri } = await DocumentPicker.pickSingle({
|
|
|
|
type: DocumentPicker.types.audio,
|
|
|
|
copyTo: "documentDirectory",
|
|
|
|
});
|
|
|
|
if (!fileCopyUri) return;
|
|
|
|
setValue("sound", fileCopyUri);
|
2023-11-20 07:06:45 +00:00
|
|
|
await settingsRepo.update({}, { sound: fileCopyUri });
|
2023-11-12 06:07:58 +00:00
|
|
|
toast("Sound will play after rest timers.");
|
|
|
|
}}
|
2023-11-09 00:14:11 +00:00
|
|
|
>
|
2023-11-12 06:07:58 +00:00
|
|
|
{name}
|
2023-11-09 00:14:11 +00:00
|
|
|
</Button>
|
2023-11-12 06:07:58 +00:00
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Export database",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<Button
|
|
|
|
style={{ alignSelf: "flex-start" }}
|
|
|
|
onPress={async () => {
|
2024-02-12 05:27:20 +00:00
|
|
|
const result = await DocumentPicker.pickDirectory();
|
|
|
|
const error = await NativeModules.BackupModule.once(result.uri);
|
2024-02-12 02:15:34 +00:00
|
|
|
if (error) toast(error);
|
|
|
|
else toast("Database exported.");
|
2023-11-12 06:07:58 +00:00
|
|
|
}}
|
|
|
|
>
|
|
|
|
{name}
|
|
|
|
</Button>
|
|
|
|
),
|
|
|
|
},
|
2023-11-20 21:23:11 +00:00
|
|
|
{
|
|
|
|
name: "Export sets as CSV",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<Button
|
|
|
|
style={{ alignSelf: "flex-start" }}
|
|
|
|
onPress={async () => {
|
2024-02-12 05:27:20 +00:00
|
|
|
const result = await DocumentPicker.pickDirectory();
|
|
|
|
await NativeModules.BackupModule.exportToCSV(result.uri);
|
2023-11-20 21:23:11 +00:00
|
|
|
toast("Exported sets as CSV.");
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
{name}
|
|
|
|
</Button>
|
|
|
|
),
|
|
|
|
},
|
2023-11-12 06:07:58 +00:00
|
|
|
{
|
|
|
|
name: "Import database",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<Button
|
|
|
|
style={{ alignSelf: "flex-start" }}
|
|
|
|
onPress={() => setImporting(true)}
|
|
|
|
>
|
|
|
|
{name}
|
|
|
|
</Button>
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Delete database",
|
|
|
|
renderItem: (name: string) => (
|
|
|
|
<Button
|
|
|
|
style={{ alignSelf: "flex-start" }}
|
|
|
|
onPress={() => setDeleting(true)}
|
|
|
|
>
|
|
|
|
{name}
|
|
|
|
</Button>
|
|
|
|
),
|
|
|
|
},
|
|
|
|
];
|
2022-12-24 00:36:11 +00:00
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
2023-08-12 03:22:50 +00:00
|
|
|
<DrawerHeader name="Settings" />
|
2022-12-24 00:36:11 +00:00
|
|
|
|
2023-11-12 06:07:58 +00:00
|
|
|
<Page term={term} search={setTerm}>
|
|
|
|
<FlatList
|
|
|
|
data={data.filter((item) =>
|
|
|
|
item.name.toLowerCase().includes(term.toLowerCase())
|
|
|
|
)}
|
|
|
|
renderItem={({ item }) => item.renderItem(item.name)}
|
|
|
|
style={{ flex: 1, paddingTop: PADDING }}
|
|
|
|
/>
|
2022-10-22 23:35:58 +00:00
|
|
|
</Page>
|
2022-12-08 00:18:41 +00:00
|
|
|
|
2023-11-14 23:14:47 +00:00
|
|
|
<ConfirmDialog
|
|
|
|
title="Failed to import database"
|
|
|
|
onOk={() => setError("")}
|
|
|
|
setShow={() => setError("")}
|
|
|
|
show={!!error}
|
|
|
|
>
|
|
|
|
{error}
|
|
|
|
</ConfirmDialog>
|
|
|
|
|
2022-12-08 00:18:41 +00:00
|
|
|
<ConfirmDialog
|
2023-08-12 03:22:50 +00:00
|
|
|
title="Are you sure?"
|
2022-12-08 00:18:41 +00:00
|
|
|
onOk={confirmImport}
|
|
|
|
setShow={setImporting}
|
2023-06-27 03:16:59 +00:00
|
|
|
show={importing}
|
|
|
|
>
|
2022-12-08 00:18:41 +00:00
|
|
|
Importing a database overwrites your current data. This action cannot be
|
|
|
|
reversed!
|
|
|
|
</ConfirmDialog>
|
2023-06-29 03:31:24 +00:00
|
|
|
|
|
|
|
<ConfirmDialog
|
2023-08-12 03:22:50 +00:00
|
|
|
title="Are you sure?"
|
2023-06-29 03:31:24 +00:00
|
|
|
onOk={confirmDelete}
|
|
|
|
setShow={setDeleting}
|
|
|
|
show={deleting}
|
|
|
|
>
|
|
|
|
Deleting your database wipes your current data. This action cannot be
|
|
|
|
reversed!
|
|
|
|
</ConfirmDialog>
|
2022-10-22 23:35:58 +00:00
|
|
|
</>
|
2023-08-12 03:22:50 +00:00
|
|
|
);
|
2022-07-03 01:50:01 +00:00
|
|
|
}
|