Compare commits
11 Commits
617fca0094
...
5b066bccaf
Author | SHA1 | Date |
---|---|---|
Brandon Presley | 5b066bccaf | |
Brandon Presley | d5fab6d6d2 | |
Brandon Presley | c6ac2cae86 | |
Brandon Presley | 8162724328 | |
Brandon Presley | d89e307950 | |
Brandon Presley | a9367cd53b | |
Brandon Presley | f5f96035a0 | |
Brandon Presley | 974d2207db | |
Brandon Presley | cc5089d4b4 | |
Brandon Presley | 2d9c69a3dd | |
Brandon Presley | 495d6b35b7 |
|
@ -3,12 +3,13 @@ import { StackScreenProps } from "@react-navigation/stack";
|
|||
import { IconButton, useTheme, Banner } from "react-native-paper";
|
||||
import { DrawerParams } from "./drawer-params";
|
||||
import ExerciseList from "./ExerciseList";
|
||||
import GraphsList from "./GraphsList";
|
||||
import GraphsList from "./GraphList";
|
||||
import InsightsPage from "./InsightsPage";
|
||||
import PlanList from "./PlanList";
|
||||
import SetList from "./SetList";
|
||||
import SettingsPage from "./SettingsPage";
|
||||
import WeightList from "./WeightList";
|
||||
import Daily from "./Daily";
|
||||
|
||||
const Drawer = createDrawerNavigator<DrawerParams>();
|
||||
|
||||
|
@ -42,10 +43,15 @@ export default function AppDrawer({
|
|||
component={ExerciseList}
|
||||
options={{ drawerIcon: () => <IconButton icon="dumbbell" /> }}
|
||||
/>
|
||||
<Drawer.Screen
|
||||
name="Daily"
|
||||
component={Daily}
|
||||
options={{ drawerIcon: () => <IconButton icon="calendar-outline" /> }}
|
||||
/>
|
||||
<Drawer.Screen
|
||||
name="Plans"
|
||||
component={PlanList}
|
||||
options={{ drawerIcon: () => <IconButton icon="calendar-outline" /> }}
|
||||
options={{ drawerIcon: () => <IconButton icon="checkbox-multiple-marked-outline" /> }}
|
||||
/>
|
||||
<Drawer.Screen
|
||||
name="Graphs"
|
||||
|
|
|
@ -17,6 +17,7 @@ function AppInput(
|
|||
selectTextOnFocus
|
||||
ref={props.innerRef}
|
||||
blurOnSubmit={false}
|
||||
mode="outlined"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
import { useCallback, useEffect, useState } from "react";
|
||||
import { FlatList, Pressable, View } from "react-native";
|
||||
import { Button, IconButton, List, Text } from "react-native-paper";
|
||||
import AppFab from "./AppFab";
|
||||
import DrawerHeader from "./DrawerHeader";
|
||||
import { LIMIT, PADDING } from "./constants";
|
||||
import GymSet, { defaultSet } from "./gym-set";
|
||||
import { getNow, setRepo, settingsRepo } from "./db";
|
||||
import { NavigationProp, useFocusEffect, useNavigation } from "@react-navigation/native";
|
||||
import { Like } from "typeorm";
|
||||
import Settings from "./settings";
|
||||
import { format } from "date-fns";
|
||||
import { DateTimePickerAndroid } from "@react-native-community/datetimepicker";
|
||||
import SetItem from "./SetItem";
|
||||
import { StackParams } from "./AppStack";
|
||||
|
||||
export default function Daily() {
|
||||
const [sets, setSets] = useState<GymSet[]>();
|
||||
const [day, setDay] = useState<Date>()
|
||||
const [settings, setSettings] = useState<Settings>();
|
||||
const navigation = useNavigation<NavigationProp<StackParams>>();
|
||||
|
||||
const onFocus = async () => {
|
||||
const now = await getNow();
|
||||
let created = now.split('T')[0];
|
||||
setDay(new Date(created));
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
if (!day) return
|
||||
const created = day.toISOString().split('T')[0]
|
||||
const newSets = await setRepo.find({
|
||||
where: { hidden: 0 as any, created: Like(`${created}%`) },
|
||||
take: LIMIT,
|
||||
skip: 0,
|
||||
order: { created: "DESC" },
|
||||
});
|
||||
setSets(newSets);
|
||||
console.log(`${Daily.name}.useEffect:`, { day });
|
||||
settingsRepo.findOne({ where: {} }).then(setSettings)
|
||||
})()
|
||||
}, [day])
|
||||
|
||||
useFocusEffect(useCallback(() => {
|
||||
onFocus();
|
||||
}, []))
|
||||
|
||||
const onAdd = async () => {
|
||||
const now = await getNow();
|
||||
let set: Partial<GymSet> = { ...sets[0] };
|
||||
if (!set) set = { ...defaultSet };
|
||||
set.created = now;
|
||||
delete set.id;
|
||||
navigation.navigate("EditSet", { set });
|
||||
|
||||
}
|
||||
|
||||
const onRight = () => {
|
||||
const newDay = new Date(day)
|
||||
newDay.setDate(newDay.getDate() + 1)
|
||||
setDay(newDay)
|
||||
}
|
||||
|
||||
const onLeft = () => {
|
||||
const newDay = new Date(day)
|
||||
newDay.setDate(newDay.getDate() - 1)
|
||||
setDay(newDay)
|
||||
}
|
||||
|
||||
const onDate = () => {
|
||||
DateTimePickerAndroid.open({
|
||||
value: new Date(day),
|
||||
onChange: (event, date) => {
|
||||
if (event.type === 'dismissed') return;
|
||||
setDay(date)
|
||||
},
|
||||
mode: 'date',
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<DrawerHeader name="Daily" />
|
||||
|
||||
|
||||
<View style={{ padding: PADDING, flexGrow: 1 }}>
|
||||
<View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center' }}>
|
||||
<IconButton style={{ marginRight: 'auto' }} icon="chevron-double-left" onPress={onLeft} />
|
||||
<Button onPress={onDate}>{format(day ? new Date(day) : new Date(), "PPPP")}</Button>
|
||||
<IconButton style={{ marginLeft: 'auto' }} icon="chevron-double-right" onPress={onRight} />
|
||||
</View>
|
||||
|
||||
{settings && (
|
||||
<FlatList ListEmptyComponent={<List.Item title="No sets yet" />} style={{ flex: 1 }} data={sets} renderItem={({ item }) => <SetItem ids={[]} setIds={() => { }} item={item} settings={settings} />} />
|
||||
)}
|
||||
|
||||
<AppFab onPress={onAdd} />
|
||||
</View>
|
||||
|
||||
|
||||
</>
|
||||
)
|
||||
}
|
|
@ -138,17 +138,15 @@ export default function EditExercise() {
|
|||
onChangeText={setName}
|
||||
onSubmitEditing={submitName}
|
||||
/>
|
||||
{settings?.steps && (
|
||||
<AppInput
|
||||
innerRef={stepsRef}
|
||||
selectTextOnFocus={false}
|
||||
value={steps}
|
||||
onChangeText={setSteps}
|
||||
label="Steps"
|
||||
multiline
|
||||
onSubmitEditing={() => setsRef.current?.focus()}
|
||||
/>
|
||||
)}
|
||||
<AppInput
|
||||
innerRef={stepsRef}
|
||||
selectTextOnFocus={false}
|
||||
value={steps}
|
||||
onChangeText={setSteps}
|
||||
label="Steps"
|
||||
multiline
|
||||
onSubmitEditing={() => setsRef.current?.focus()}
|
||||
/>
|
||||
<AppInput
|
||||
innerRef={setsRef}
|
||||
value={sets}
|
||||
|
|
|
@ -120,17 +120,15 @@ export default function EditExercises() {
|
|||
onChangeText={setName}
|
||||
onSubmitEditing={submitName}
|
||||
/>
|
||||
{settings?.steps && (
|
||||
<AppInput
|
||||
innerRef={stepsRef}
|
||||
selectTextOnFocus={false}
|
||||
value={steps}
|
||||
onChangeText={setSteps}
|
||||
label={`Steps: ${oldSteps}`}
|
||||
multiline
|
||||
onSubmitEditing={() => setsRef.current?.focus()}
|
||||
/>
|
||||
)}
|
||||
<AppInput
|
||||
innerRef={stepsRef}
|
||||
selectTextOnFocus={false}
|
||||
value={steps}
|
||||
onChangeText={setSteps}
|
||||
label={`Steps: ${oldSteps}`}
|
||||
multiline
|
||||
onSubmitEditing={() => setsRef.current?.focus()}
|
||||
/>
|
||||
<AppInput
|
||||
innerRef={setsRef}
|
||||
value={sets}
|
||||
|
|
|
@ -62,7 +62,10 @@ export default function EditSet() {
|
|||
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
settingsRepo.findOne({ where: {} }).then(setSettings);
|
||||
settingsRepo.findOne({ where: {} }).then(gotSettings => {
|
||||
setSettings(gotSettings);
|
||||
console.log(`${EditSet.name}.focus:`, { gotSettings })
|
||||
});
|
||||
}, [])
|
||||
);
|
||||
|
||||
|
|
|
@ -125,6 +125,7 @@ export default function SettingsPage() {
|
|||
await setRepo.update({}, { image: null });
|
||||
await settingsRepo.update({}, { sound: null, backup: false });
|
||||
reset({ index: 0, routes: [{ name: "Settings" }] });
|
||||
toast("Imported database successfully.")
|
||||
}, [reset]);
|
||||
|
||||
const today = new Date();
|
||||
|
@ -138,7 +139,8 @@ export default function SettingsPage() {
|
|||
items={[
|
||||
{ label: "History", value: "History", icon: 'history' },
|
||||
{ label: "Exercises", value: "Exercises", icon: 'dumbbell' },
|
||||
{ label: "Plans", value: "Plans", icon: 'calendar-outline' },
|
||||
{ label: "Daily", value: "Daily", icon: 'calendar-outline' },
|
||||
{ label: "Plans", value: "Plans", icon: 'checkbox-multiple-marked-outline' },
|
||||
{ label: "Graphs", value: "Graphs", icon: 'chart-bell-curve-cumulative' },
|
||||
{ label: "Timer", value: "Timer", icon: 'timer-outline' },
|
||||
{ label: "Weight", value: "Weight", icon: 'scale-bathroom' },
|
||||
|
@ -341,38 +343,22 @@ export default function SettingsPage() {
|
|||
onChange={async (value) => {
|
||||
setValue("vibrate", value);
|
||||
await settingsRepo.update({}, { vibrate: value });
|
||||
if (value) toast("Timers will now run after each set.");
|
||||
else toast("Stopped timers running after each set.");
|
||||
if (value) toast("Alarms will vibrate.");
|
||||
else toast("Stopped alarms from vibrating.");
|
||||
}}
|
||||
title={name}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Disable sound",
|
||||
name: "Sound",
|
||||
renderItem: (name: string) => (
|
||||
<Switch
|
||||
value={settings.noSound}
|
||||
value={!settings.noSound}
|
||||
onChange={async (value) => {
|
||||
setValue("noSound", value);
|
||||
const silentPath = Dirs.DocumentDir + "/silent.mp3";
|
||||
|
||||
if (value) {
|
||||
await FileSystem.writeFile(silentPath, "");
|
||||
setValue("sound", silentPath);
|
||||
await settingsRepo.update(
|
||||
{},
|
||||
{
|
||||
sound: silentPath,
|
||||
noSound: value,
|
||||
}
|
||||
);
|
||||
} else if (!value && settings.sound === silentPath) {
|
||||
setValue("sound", null);
|
||||
await settingsRepo.update({}, { sound: null, noSound: value });
|
||||
}
|
||||
|
||||
if (value) toast("Alarms will no longer make a sound.");
|
||||
setValue("noSound", !value);
|
||||
await settingsRepo.update({}, { noSound: !value });
|
||||
if (!value) toast("Alarms will no longer make a sound.");
|
||||
else toast("Enabled sound for alarms.");
|
||||
}}
|
||||
title={name}
|
||||
|
@ -424,21 +410,6 @@ export default function SettingsPage() {
|
|||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Show steps",
|
||||
renderItem: (name: string) => (
|
||||
<Switch
|
||||
value={settings.steps}
|
||||
onChange={async (value) => {
|
||||
setValue("steps", value);
|
||||
await settingsRepo.update({}, { steps: value });
|
||||
if (value) toast("Show steps for exercises.");
|
||||
else toast("Hid steps for exercises.");
|
||||
}}
|
||||
title={name}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "Show date",
|
||||
renderItem: (name: string) => (
|
||||
|
|
|
@ -31,7 +31,7 @@ export default function StartPlan() {
|
|||
const [reps, setReps] = useState(params.first?.reps.toString() || "0");
|
||||
const [weight, setWeight] = useState(params.first?.weight.toString() || "0");
|
||||
const [unit, setUnit] = useState<string>(params.first?.unit || "kg");
|
||||
const [selected, setSelected] = useState<number | null>(null);
|
||||
const [selected, setSelected] = useState<number>(0);
|
||||
const [settings, setSettings] = useState<Settings>();
|
||||
const [counts, setCounts] = useState<CountMany[]>();
|
||||
const weightRef = useRef<TextInput>(null);
|
||||
|
@ -88,10 +88,6 @@ export default function StartPlan() {
|
|||
useCallback(() => {
|
||||
settingsRepo.findOne({ where: {} }).then(setSettings);
|
||||
refresh();
|
||||
setRepo.find({ order: { created: "DESC" }, take: 1 }).then(sets => {
|
||||
const index = exercises.findIndex(exercise => exercise === sets[0].name);
|
||||
setSelected(index === -1 ? 0 : index);
|
||||
});
|
||||
// eslint-disable-next-line
|
||||
}, [])
|
||||
);
|
||||
|
@ -132,6 +128,8 @@ export default function StartPlan() {
|
|||
const canNotify = await check(PERMISSIONS.ANDROID.POST_NOTIFICATIONS);
|
||||
if (canNotify === RESULTS.DENIED)
|
||||
await request(PERMISSIONS.ANDROID.POST_NOTIFICATIONS);
|
||||
if (isNaN(exercise.total) ? 0 : exercise.total === best.sets - 1 && selected === exercises.length - 1)
|
||||
return
|
||||
NativeModules.AlarmModule.timer(milliseconds, `${exercise.name} (${exercise.total + 1}/${best.sets})`);
|
||||
};
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@ export default function StartPlanItem(props: Props) {
|
|||
setShowMenu(false);
|
||||
if (!first) return toast("Nothing to undo.");
|
||||
await setRepo.delete(first.id);
|
||||
NativeModules.AlarmModule.stop();
|
||||
onUndo();
|
||||
}, [setShowMenu, onUndo, item.name]);
|
||||
|
||||
|
|
|
@ -87,8 +87,8 @@ android {
|
|||
applicationId "com.massive"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 36240
|
||||
versionName "2.25"
|
||||
versionCode 36241
|
||||
versionName "2.26"
|
||||
}
|
||||
signingConfigs {
|
||||
release {
|
||||
|
|
|
@ -71,6 +71,7 @@ class TimerService : Service() {
|
|||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
timerRunnable?.let { timerHandler.removeCallbacks(it) }
|
||||
secondsLeft = (intent?.getIntExtra("milliseconds", 0) ?: 0) / 1000
|
||||
currentDescription = intent?.getStringExtra("description").toString()
|
||||
secondsTotal = secondsLeft
|
||||
|
|
|
@ -6,7 +6,7 @@ export const LIGHT_COLORS = [
|
|||
{ hex: "#FA8072", name: "Salmon" },
|
||||
{ hex: "#FFC0CB", name: "Pink" },
|
||||
{ hex: "#E9DCC9", name: "Linen" },
|
||||
{ hex: "#9ACD32", name: "Yellow Green" },
|
||||
{ hex: "#9ACD32", name: "Green" },
|
||||
{ hex: "#FFD700", name: "Gold" },
|
||||
{ hex: "#00CED1", name: "Turquoise" },
|
||||
];
|
||||
|
|
|
@ -7,4 +7,5 @@ export type DrawerParams = {
|
|||
Weight: {};
|
||||
Insights: {};
|
||||
Settings: {};
|
||||
Daily: {};
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "massive",
|
||||
"version": "2.25",
|
||||
"version": "2.26",
|
||||
"private": true,
|
||||
"license": "GPL-3.0-only",
|
||||
"scripts": {
|
||||
|
|
Loading…
Reference in New Issue