Reduce nesting of code within SettingsPage - 1.178 🚀
The code before needlessly factored out functions in functions and made it impossible to read and change. Also it wasn't using a FlatList which is a performance problem.
This commit is contained in:
parent
52f04ad11c
commit
afed5f1d54
577
SettingsPage.tsx
577
SettingsPage.tsx
|
@ -2,24 +2,23 @@ import { NavigationProp, useNavigation } from "@react-navigation/native";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
import { NativeModules, ScrollView } from "react-native";
|
import { FlatList, NativeModules } 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 } from "react-native-paper";
|
import { Button } from "react-native-paper";
|
||||||
import { check, PERMISSIONS, request, RESULTS } from "react-native-permissions";
|
import { PERMISSIONS, RESULTS, check, request } from "react-native-permissions";
|
||||||
import AppInput from "./AppInput";
|
import AppInput from "./AppInput";
|
||||||
import ConfirmDialog from "./ConfirmDialog";
|
import ConfirmDialog from "./ConfirmDialog";
|
||||||
import { MARGIN } from "./constants";
|
import DrawerHeader from "./DrawerHeader";
|
||||||
|
import Page from "./Page";
|
||||||
|
import Select from "./Select";
|
||||||
|
import Switch from "./Switch";
|
||||||
|
import { PADDING } from "./constants";
|
||||||
import { AppDataSource } from "./data-source";
|
import { AppDataSource } from "./data-source";
|
||||||
import { setRepo, settingsRepo } from "./db";
|
import { setRepo, settingsRepo } from "./db";
|
||||||
import { DrawerParams } from "./drawer-param-list";
|
import { DrawerParams } from "./drawer-param-list";
|
||||||
import DrawerHeader from "./DrawerHeader";
|
|
||||||
import Input from "./input";
|
|
||||||
import { darkOptions, lightOptions, themeOptions } from "./options";
|
import { darkOptions, lightOptions, themeOptions } from "./options";
|
||||||
import Page from "./Page";
|
|
||||||
import Select from "./Select";
|
|
||||||
import Settings from "./settings";
|
import Settings from "./settings";
|
||||||
import Switch from "./Switch";
|
|
||||||
import { toast } from "./toast";
|
import { toast } from "./toast";
|
||||||
import { useTheme } from "./use-theme";
|
import { useTheme } from "./use-theme";
|
||||||
|
|
||||||
|
@ -42,6 +41,11 @@ const twentyFours = [
|
||||||
"yyyy.MM.d",
|
"yyyy.MM.d",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
interface Item {
|
||||||
|
name: string;
|
||||||
|
renderItem: (name: string) => React.JSX.Element;
|
||||||
|
}
|
||||||
|
|
||||||
export default function SettingsPage() {
|
export default function SettingsPage() {
|
||||||
const [ignoring, setIgnoring] = useState(false);
|
const [ignoring, setIgnoring] = useState(false);
|
||||||
const [term, setTerm] = useState("");
|
const [term, setTerm] = useState("");
|
||||||
|
@ -88,229 +92,6 @@ export default function SettingsPage() {
|
||||||
return split.pop();
|
return split.pop();
|
||||||
}, [settings.sound]);
|
}, [settings.sound]);
|
||||||
|
|
||||||
const changeSound = useCallback(async () => {
|
|
||||||
const { fileCopyUri } = await DocumentPicker.pickSingle({
|
|
||||||
type: DocumentPicker.types.audio,
|
|
||||||
copyTo: "documentDirectory",
|
|
||||||
});
|
|
||||||
if (!fileCopyUri) return;
|
|
||||||
setValue("sound", fileCopyUri);
|
|
||||||
await update("sound", fileCopyUri);
|
|
||||||
toast("Sound will play after rest timers.");
|
|
||||||
}, [setValue, update]);
|
|
||||||
|
|
||||||
const switches: Input<boolean>[] = useMemo(
|
|
||||||
() => [
|
|
||||||
{ name: "Rest timers", value: settings.alarm, key: "alarm" },
|
|
||||||
{ name: "Vibrate", value: settings.vibrate, key: "vibrate" },
|
|
||||||
{ name: "Disable sound", value: settings.noSound, key: "noSound" },
|
|
||||||
{ name: "Notifications", value: settings.notify, key: "notify" },
|
|
||||||
{ name: "Show images", value: settings.images, key: "images" },
|
|
||||||
{ name: "Show unit", value: settings.showUnit, key: "showUnit" },
|
|
||||||
{ name: "Show steps", value: settings.steps, key: "steps" },
|
|
||||||
{ name: "Show date", value: settings.showDate, key: "showDate" },
|
|
||||||
{ name: "Automatic backup", value: settings.backup, key: "backup" },
|
|
||||||
],
|
|
||||||
[settings]
|
|
||||||
);
|
|
||||||
|
|
||||||
const filter = useCallback(
|
|
||||||
({ name }) => name.toLowerCase().includes(term.toLowerCase()),
|
|
||||||
[term]
|
|
||||||
);
|
|
||||||
|
|
||||||
const changeBoolean = useCallback(
|
|
||||||
async (key: keyof Settings, value: boolean) => {
|
|
||||||
setValue(key, value);
|
|
||||||
await update(key, value);
|
|
||||||
switch (key) {
|
|
||||||
case "alarm":
|
|
||||||
if (value) toast("Timers will now run after each set.");
|
|
||||||
else toast("Stopped timers running after each set.");
|
|
||||||
const canNotify = await check(PERMISSIONS.ANDROID.POST_NOTIFICATIONS);
|
|
||||||
if (canNotify === RESULTS.DENIED || canNotify === RESULTS.BLOCKED)
|
|
||||||
await request(PERMISSIONS.ANDROID.POST_NOTIFICATIONS);
|
|
||||||
if (value && !ignoring) NativeModules.SettingsModule.ignoreBattery();
|
|
||||||
return;
|
|
||||||
case "vibrate":
|
|
||||||
if (value) toast("Alarms will now vibrate.");
|
|
||||||
else toast("Alarms will no longer vibrate.");
|
|
||||||
return;
|
|
||||||
case "notify":
|
|
||||||
if (value) toast("Show notifications for new records.");
|
|
||||||
else toast("Stopped notifications for new records.");
|
|
||||||
return;
|
|
||||||
case "images":
|
|
||||||
if (value) toast("Show images for sets.");
|
|
||||||
else toast("Hid images for sets.");
|
|
||||||
return;
|
|
||||||
case "showUnit":
|
|
||||||
if (value) toast("Show option to select unit for sets.");
|
|
||||||
else toast("Hid unit option for sets.");
|
|
||||||
return;
|
|
||||||
case "steps":
|
|
||||||
if (value) toast("Show steps for exercises.");
|
|
||||||
else toast("Hid steps for exercises.");
|
|
||||||
return;
|
|
||||||
case "showDate":
|
|
||||||
if (value) toast("Show date for sets.");
|
|
||||||
else toast("Hid date on sets.");
|
|
||||||
return;
|
|
||||||
case "noSound":
|
|
||||||
if (value) toast("Alarms will no longer make a sound.");
|
|
||||||
else toast("Enabled sound for alarms.");
|
|
||||||
return;
|
|
||||||
case "backup":
|
|
||||||
if (value) {
|
|
||||||
const result = await DocumentPicker.pickDirectory();
|
|
||||||
toast("Backup database daily.");
|
|
||||||
NativeModules.BackupModule.start(result.uri);
|
|
||||||
} else {
|
|
||||||
toast("Stopped backing up daily");
|
|
||||||
NativeModules.BackupModule.stop();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[ignoring, setValue, update]
|
|
||||||
);
|
|
||||||
|
|
||||||
const renderSwitch = useCallback(
|
|
||||||
(item: Input<boolean>) => (
|
|
||||||
<Switch
|
|
||||||
key={item.name}
|
|
||||||
value={item.value}
|
|
||||||
onChange={(value) => changeBoolean(item.key, value)}
|
|
||||||
title={item.name}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
[changeBoolean]
|
|
||||||
);
|
|
||||||
|
|
||||||
const switchesMarkup = useMemo(
|
|
||||||
() => switches.filter(filter).map((s) => renderSwitch(s)),
|
|
||||||
[filter, switches, renderSwitch]
|
|
||||||
);
|
|
||||||
|
|
||||||
const changeString = useCallback(
|
|
||||||
async (key: keyof Settings, value: string) => {
|
|
||||||
setValue(key, value);
|
|
||||||
await update(key, value);
|
|
||||||
switch (key) {
|
|
||||||
case "date":
|
|
||||||
return toast("Changed date format");
|
|
||||||
case "darkColor":
|
|
||||||
setDarkColor(value);
|
|
||||||
return toast("Set primary color for dark mode.");
|
|
||||||
case "lightColor":
|
|
||||||
setLightColor(value);
|
|
||||||
return toast("Set primary color for light mode.");
|
|
||||||
case "vibrate":
|
|
||||||
return toast("Set primary color for light mode.");
|
|
||||||
case "sound":
|
|
||||||
return toast("Sound will play after rest timers.");
|
|
||||||
case "theme":
|
|
||||||
setTheme(value as string);
|
|
||||||
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.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[update, setTheme, setDarkColor, setLightColor, setValue]
|
|
||||||
);
|
|
||||||
|
|
||||||
const changeNumber = useCallback(
|
|
||||||
async (key: keyof Settings, value: number) => {
|
|
||||||
setValue(key, value);
|
|
||||||
await update(key, value);
|
|
||||||
switch (key) {
|
|
||||||
case "duration":
|
|
||||||
return toast("Changed duration of alarm vibrations.");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[update, setValue]
|
|
||||||
);
|
|
||||||
|
|
||||||
const numberInputs: Input<number>[] = useMemo(
|
|
||||||
() => [
|
|
||||||
{
|
|
||||||
name: "Vibration duration (ms)",
|
|
||||||
value: settings.duration,
|
|
||||||
key: "duration",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[settings]
|
|
||||||
);
|
|
||||||
|
|
||||||
const renderNumber = useCallback(
|
|
||||||
(item: Input<number>) => (
|
|
||||||
<AppInput
|
|
||||||
value={item.value?.toString() ?? "300"}
|
|
||||||
key={item.key}
|
|
||||||
label={item.name}
|
|
||||||
onChangeText={(value) => changeString(item.key, value)}
|
|
||||||
onSubmitEditing={(e) =>
|
|
||||||
changeNumber(item.key, Number(e.nativeEvent.text))
|
|
||||||
}
|
|
||||||
keyboardType="numeric"
|
|
||||||
blurOnSubmit
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
[changeString, changeNumber]
|
|
||||||
);
|
|
||||||
|
|
||||||
const numbersMarkup = useMemo(
|
|
||||||
() => numberInputs.filter(filter).map((s) => renderNumber(s)),
|
|
||||||
[numberInputs, filter, renderNumber]
|
|
||||||
);
|
|
||||||
|
|
||||||
const selects: Input<string>[] = useMemo(() => {
|
|
||||||
const today = new Date();
|
|
||||||
return [
|
|
||||||
{ name: "Theme", value: theme, items: themeOptions, key: "theme" },
|
|
||||||
{
|
|
||||||
name: "Dark color",
|
|
||||||
value: darkColor,
|
|
||||||
items: lightOptions,
|
|
||||||
key: "darkColor",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Light color",
|
|
||||||
value: lightColor,
|
|
||||||
items: darkOptions,
|
|
||||||
key: "lightColor",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Date format",
|
|
||||||
value: settings.date,
|
|
||||||
items: formatOptions.map((option) => ({
|
|
||||||
label: format(today, option),
|
|
||||||
value: option,
|
|
||||||
})),
|
|
||||||
key: "date",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}, [settings, darkColor, formatOptions, theme, lightColor]);
|
|
||||||
|
|
||||||
const renderSelect = useCallback(
|
|
||||||
(input: Input<string>) => (
|
|
||||||
<Select
|
|
||||||
key={input.name}
|
|
||||||
value={input.value}
|
|
||||||
onChange={(value) => changeString(input.key, value)}
|
|
||||||
label={input.name}
|
|
||||||
items={input.items}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
[changeString]
|
|
||||||
);
|
|
||||||
|
|
||||||
const selectsMarkup = useMemo(
|
|
||||||
() => selects.filter(filter).map(renderSelect),
|
|
||||||
[filter, selects, renderSelect]
|
|
||||||
);
|
|
||||||
|
|
||||||
const confirmDelete = useCallback(async () => {
|
const confirmDelete = useCallback(async () => {
|
||||||
setDeleting(false);
|
setDeleting(false);
|
||||||
await AppDataSource.dropDatabase();
|
await AppDataSource.dropDatabase();
|
||||||
|
@ -338,53 +119,313 @@ export default function SettingsPage() {
|
||||||
});
|
});
|
||||||
}, [reset, update]);
|
}, [reset, update]);
|
||||||
|
|
||||||
const exportDatabase = useCallback(async () => {
|
const today = new Date();
|
||||||
const result = await check(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE);
|
|
||||||
if (result === RESULTS.DENIED || result === RESULTS.BLOCKED)
|
|
||||||
await request(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE);
|
|
||||||
const path = Dirs.DatabaseDir + "/massive.db";
|
|
||||||
await FileSystem.cpExternal(path, "massive.db", "downloads");
|
|
||||||
toast("Database exported. Check downloads.");
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const buttons = useMemo(
|
const data: Item[] = [
|
||||||
() => [
|
{
|
||||||
{
|
name: "Theme",
|
||||||
name: `Alarm sound: ${soundString || "Default"}`,
|
renderItem: (name: string) => (
|
||||||
onPress: changeSound,
|
<Select
|
||||||
},
|
label={name}
|
||||||
{ name: "Export database", onPress: exportDatabase },
|
items={themeOptions}
|
||||||
{ name: "Import database", onPress: () => setImporting(true) },
|
value={theme}
|
||||||
{ name: "Delete database", onPress: () => setDeleting(true) },
|
onChange={async (value) => {
|
||||||
],
|
setValue("theme", value);
|
||||||
[changeSound, exportDatabase, soundString]
|
setTheme(value);
|
||||||
);
|
await update("theme", value);
|
||||||
|
if (value === "dark") toast("Theme will always be dark.");
|
||||||
const buttonsMarkup = useMemo(
|
else if (value === "light") toast("Theme will always be light.");
|
||||||
() =>
|
else if (value === "system") toast("Theme will follow system.");
|
||||||
buttons.filter(filter).map((button) => (
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Dark color",
|
||||||
|
renderItem: (name: string) => (
|
||||||
|
<Select
|
||||||
|
label={name}
|
||||||
|
items={lightOptions}
|
||||||
|
value={darkColor}
|
||||||
|
onChange={async (value) => {
|
||||||
|
setValue("darkColor", value);
|
||||||
|
setDarkColor(value);
|
||||||
|
await 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 update("lightColor", value);
|
||||||
|
toast("Set primary color for light mode.");
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
await update("date", value);
|
||||||
|
toast("Changed date format.");
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Vibration duration (ms)",
|
||||||
|
renderItem: (name: string) => (
|
||||||
|
<AppInput
|
||||||
|
value={settings.duration?.toString() ?? "300"}
|
||||||
|
label={name}
|
||||||
|
onChangeText={(value) => setValue("duration", Number(value))}
|
||||||
|
onSubmitEditing={async (e) => {
|
||||||
|
setValue("duration", Number(e.nativeEvent.text));
|
||||||
|
await update("duration", e.nativeEvent.text);
|
||||||
|
toast("Changed duration of alarm vibrations.");
|
||||||
|
}}
|
||||||
|
keyboardType="numeric"
|
||||||
|
blurOnSubmit
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Rest timers",
|
||||||
|
renderItem: (name: string) => (
|
||||||
|
<Switch
|
||||||
|
value={settings.alarm}
|
||||||
|
onChange={async (value) => {
|
||||||
|
setValue("alarm", value);
|
||||||
|
if (value && !ignoring)
|
||||||
|
NativeModules.SettingsModule.ignoreBattery();
|
||||||
|
await update("alarm", value);
|
||||||
|
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);
|
||||||
|
await update("vibrate", value);
|
||||||
|
if (value) toast("Timers will now run after each set.");
|
||||||
|
else toast("Stopped timers running after each set.");
|
||||||
|
}}
|
||||||
|
title={name}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Disable sound",
|
||||||
|
renderItem: (name: string) => (
|
||||||
|
<Switch
|
||||||
|
value={settings.noSound}
|
||||||
|
onChange={async (value) => {
|
||||||
|
setValue("noSound", value);
|
||||||
|
await update("noSound", value);
|
||||||
|
if (value) toast("Alarms will no longer make a sound.");
|
||||||
|
else toast("Enabled sound for alarms.");
|
||||||
|
}}
|
||||||
|
title={name}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Notifications",
|
||||||
|
renderItem: (name: string) => (
|
||||||
|
<Switch
|
||||||
|
value={settings.notify}
|
||||||
|
onChange={async (value) => {
|
||||||
|
setValue("notify", value);
|
||||||
|
await update("notify", value);
|
||||||
|
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);
|
||||||
|
await update("images", value);
|
||||||
|
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);
|
||||||
|
await update("showUnit", value);
|
||||||
|
if (value) toast("Show option to select unit for sets.");
|
||||||
|
else toast("Hid unit option for sets.");
|
||||||
|
}}
|
||||||
|
title={name}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Show steps",
|
||||||
|
renderItem: (name: string) => (
|
||||||
|
<Switch
|
||||||
|
value={settings.steps}
|
||||||
|
onChange={async (value) => {
|
||||||
|
setValue("steps", value);
|
||||||
|
await update("steps", value);
|
||||||
|
if (value) toast("Show steps for exercises.");
|
||||||
|
else toast("Hid steps for exercises.");
|
||||||
|
}}
|
||||||
|
title={name}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Show date",
|
||||||
|
renderItem: (name: string) => (
|
||||||
|
<Switch
|
||||||
|
value={settings.showDate}
|
||||||
|
onChange={async (value) => {
|
||||||
|
setValue("showDate", value);
|
||||||
|
await update("showDate", value);
|
||||||
|
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);
|
||||||
|
await update("backup", value);
|
||||||
|
if (value) {
|
||||||
|
const result = await DocumentPicker.pickDirectory();
|
||||||
|
toast("Backup database daily.");
|
||||||
|
NativeModules.BackupModule.start(result.uri);
|
||||||
|
} else {
|
||||||
|
toast("Stopped backing up daily");
|
||||||
|
NativeModules.BackupModule.stop();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
title={name}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `Alarm sound: ${soundString || "Default"}`,
|
||||||
|
renderItem: (name: string) => (
|
||||||
<Button
|
<Button
|
||||||
key={button.name}
|
|
||||||
style={{ alignSelf: "flex-start" }}
|
style={{ alignSelf: "flex-start" }}
|
||||||
onPress={button.onPress}
|
onPress={async () => {
|
||||||
|
const { fileCopyUri } = await DocumentPicker.pickSingle({
|
||||||
|
type: DocumentPicker.types.audio,
|
||||||
|
copyTo: "documentDirectory",
|
||||||
|
});
|
||||||
|
if (!fileCopyUri) return;
|
||||||
|
setValue("sound", fileCopyUri);
|
||||||
|
await update("sound", fileCopyUri);
|
||||||
|
toast("Sound will play after rest timers.");
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{button.name}
|
{name}
|
||||||
</Button>
|
</Button>
|
||||||
)),
|
),
|
||||||
[buttons, filter]
|
},
|
||||||
);
|
{
|
||||||
|
name: "Export database",
|
||||||
|
renderItem: (name: string) => (
|
||||||
|
<Button
|
||||||
|
style={{ alignSelf: "flex-start" }}
|
||||||
|
onPress={async () => {
|
||||||
|
const result = await check(
|
||||||
|
PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE
|
||||||
|
);
|
||||||
|
if (result === RESULTS.DENIED || result === RESULTS.BLOCKED)
|
||||||
|
await request(PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE);
|
||||||
|
const path = Dirs.DatabaseDir + "/massive.db";
|
||||||
|
await FileSystem.cpExternal(path, "massive.db", "downloads");
|
||||||
|
toast("Database exported. Check downloads.");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{name}
|
||||||
|
</Button>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
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>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DrawerHeader name="Settings" />
|
<DrawerHeader name="Settings" />
|
||||||
|
|
||||||
<Page term={term} search={setTerm} style={{ flexGrow: 1 }}>
|
<Page term={term} search={setTerm}>
|
||||||
<ScrollView style={{ marginTop: MARGIN, flex: 1 }}>
|
<FlatList
|
||||||
{selectsMarkup}
|
data={data.filter((item) =>
|
||||||
{numbersMarkup}
|
item.name.toLowerCase().includes(term.toLowerCase())
|
||||||
{switchesMarkup}
|
)}
|
||||||
{buttonsMarkup}
|
renderItem={({ item }) => item.renderItem(item.name)}
|
||||||
</ScrollView>
|
style={{ flex: 1, paddingTop: PADDING }}
|
||||||
|
/>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
||||||
<ConfirmDialog
|
<ConfirmDialog
|
||||||
|
|
|
@ -85,8 +85,8 @@ android {
|
||||||
applicationId "com.massive"
|
applicationId "com.massive"
|
||||||
minSdkVersion rootProject.ext.minSdkVersion
|
minSdkVersion rootProject.ext.minSdkVersion
|
||||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||||
versionCode 36203
|
versionCode 36204
|
||||||
versionName "1.177"
|
versionName "1.178"
|
||||||
}
|
}
|
||||||
signingConfigs {
|
signingConfigs {
|
||||||
release {
|
release {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "massive",
|
"name": "massive",
|
||||||
"version": "1.177",
|
"version": "1.178",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "GPL-3.0-only",
|
"license": "GPL-3.0-only",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user