Add images to sets
This commit is contained in:
parent
9b8fb95559
commit
f6dec0c3b2
2
App.tsx
2
App.tsx
|
@ -16,6 +16,7 @@ import {SQLiteDatabase} from 'react-native-sqlite-storage';
|
||||||
import Ionicon from 'react-native-vector-icons/Ionicons';
|
import Ionicon from 'react-native-vector-icons/Ionicons';
|
||||||
import {
|
import {
|
||||||
addHidden,
|
addHidden,
|
||||||
|
addImage,
|
||||||
addNotify,
|
addNotify,
|
||||||
addSound,
|
addSound,
|
||||||
createPlans,
|
createPlans,
|
||||||
|
@ -75,6 +76,7 @@ const App = () => {
|
||||||
await _db.executeSql(createWorkouts);
|
await _db.executeSql(createWorkouts);
|
||||||
await _db.executeSql(addHidden).catch(() => null);
|
await _db.executeSql(addHidden).catch(() => null);
|
||||||
await _db.executeSql(addNotify).catch(() => null);
|
await _db.executeSql(addNotify).catch(() => null);
|
||||||
|
await _db.executeSql(addImage).catch(() => null);
|
||||||
const [result] = await _db.executeSql(`SELECT * FROM settings LIMIT 1`);
|
const [result] = await _db.executeSql(`SELECT * FROM settings LIMIT 1`);
|
||||||
if (result.rows.length === 0)
|
if (result.rows.length === 0)
|
||||||
return _db.executeSql(`
|
return _db.executeSql(`
|
||||||
|
|
|
@ -57,13 +57,13 @@ export default function EditSet() {
|
||||||
|
|
||||||
const add = useCallback(
|
const add = useCallback(
|
||||||
async (set: Set) => {
|
async (set: Set) => {
|
||||||
const {name, reps, weight, unit} = set;
|
const {name, reps, weight, unit, image} = set;
|
||||||
const insert = `
|
const insert = `
|
||||||
INSERT INTO sets(name, reps, weight, created, unit)
|
INSERT INTO sets(name, reps, weight, created, unit, image)
|
||||||
VALUES (?,?,?,strftime('%Y-%m-%dT%H:%M:%S', 'now', 'localtime'),?)
|
VALUES (?,?,?,strftime('%Y-%m-%dT%H:%M:%S', 'now', 'localtime'),?, ?)
|
||||||
`;
|
`;
|
||||||
startTimer();
|
startTimer();
|
||||||
await db.executeSql(insert, [name, reps, weight, unit]);
|
await db.executeSql(insert, [name, reps, weight, unit, image]);
|
||||||
const [result] = await db.executeSql(`SELECT * FROM settings LIMIT 1`);
|
const [result] = await db.executeSql(`SELECT * FROM settings LIMIT 1`);
|
||||||
const settings: Settings = result.rows.item(0);
|
const settings: Settings = result.rows.item(0);
|
||||||
if (settings.notify === 0) return navigation.goBack();
|
if (settings.notify === 0) return navigation.goBack();
|
||||||
|
|
|
@ -15,6 +15,7 @@ import {WorkoutsPageParams} from './WorkoutsPage';
|
||||||
|
|
||||||
export default function EditWorkout() {
|
export default function EditWorkout() {
|
||||||
const [name, setName] = useState('');
|
const [name, setName] = useState('');
|
||||||
|
const [uri, setUri] = useState('');
|
||||||
const {params} = useRoute<RouteProp<WorkoutsPageParams, 'EditWorkout'>>();
|
const {params} = useRoute<RouteProp<WorkoutsPageParams, 'EditWorkout'>>();
|
||||||
const db = useContext(DatabaseContext);
|
const db = useContext(DatabaseContext);
|
||||||
const navigation = useNavigation();
|
const navigation = useNavigation();
|
||||||
|
@ -28,22 +29,32 @@ export default function EditWorkout() {
|
||||||
headerRight: null,
|
headerRight: null,
|
||||||
title: params.value.name ? 'Edit workout' : 'New workout',
|
title: params.value.name ? 'Edit workout' : 'New workout',
|
||||||
});
|
});
|
||||||
}, [navigation, params.value.name]),
|
db.executeSql(`SELECT image FROM sets WHERE name = ? LIMIT 1`, [
|
||||||
|
params.value.name,
|
||||||
|
]).then(([result]) => setUri(result.rows.item(0)?.image));
|
||||||
|
}, [navigation, params.value.name, db]),
|
||||||
);
|
);
|
||||||
|
|
||||||
const update = useCallback(async () => {
|
const update = useCallback(async () => {
|
||||||
console.log(`${EditWorkout.name}.update`, set);
|
console.log(`${EditWorkout.name}.update`, set);
|
||||||
await db.executeSql(`UPDATE sets SET name = ? WHERE name = ?`, [
|
if (name) {
|
||||||
name,
|
await db.executeSql(`UPDATE sets SET name = ? WHERE name = ?`, [
|
||||||
params.value.name,
|
name,
|
||||||
]);
|
params.value.name,
|
||||||
await db.executeSql(
|
]);
|
||||||
`UPDATE plans SET workouts = REPLACE(workouts, ?, ?)
|
await db.executeSql(
|
||||||
|
`UPDATE plans SET workouts = REPLACE(workouts, ?, ?)
|
||||||
WHERE workouts LIKE ?`,
|
WHERE workouts LIKE ?`,
|
||||||
[params.value.name, name, `%${params.value.name}%`],
|
[params.value.name, name, `%${params.value.name}%`],
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
if (uri)
|
||||||
|
await db.executeSql(`UPDATE sets SET image = ? WHERE name = ?`, [
|
||||||
|
uri,
|
||||||
|
params.value.name,
|
||||||
|
]);
|
||||||
navigation.goBack();
|
navigation.goBack();
|
||||||
}, [db, navigation, params.value.name, name]);
|
}, [db, navigation, params.value.name, name, uri]);
|
||||||
|
|
||||||
const add = useCallback(async () => {
|
const add = useCallback(async () => {
|
||||||
const insert = `
|
const insert = `
|
||||||
|
@ -59,18 +70,32 @@ export default function EditWorkout() {
|
||||||
return add();
|
return add();
|
||||||
}, [update, add, params.value.name]);
|
}, [update, add, params.value.name]);
|
||||||
|
|
||||||
|
const changeImage = useCallback(async () => {
|
||||||
|
const {fileCopyUri} = await DocumentPicker.pickSingle({
|
||||||
|
type: 'image/*',
|
||||||
|
copyTo: 'documentDirectory',
|
||||||
|
});
|
||||||
|
if (fileCopyUri) setUri(fileCopyUri);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollView style={{padding: 10, height: '90%'}}>
|
<ScrollView style={{padding: 10, height: '90%'}}>
|
||||||
{params.value.name ? (
|
{params.value.name ? (
|
||||||
<>
|
<>
|
||||||
<MassiveInput label="Old name" value={params.value.name} disabled />
|
<MassiveInput label="Old name" value={params.value.name} disabled />
|
||||||
<MassiveInput label="New name" value={name} onChangeText={setName} />
|
<MassiveInput label="New name" value={name} onChangeText={setName} />
|
||||||
|
<View style={{flexDirection: 'row', paddingBottom: 10}}>
|
||||||
|
{uri && <Image source={{uri}} style={{height: 50, width: 50}} />}
|
||||||
|
<Button onPress={changeImage} icon="image">
|
||||||
|
Image
|
||||||
|
</Button>
|
||||||
|
</View>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<MassiveInput label="Name" value={name} onChangeText={setName} />
|
<MassiveInput label="Name" value={name} onChangeText={setName} />
|
||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
disabled={!name && !!params.value.name}
|
disabled={!name && !!params.value.name && !uri}
|
||||||
mode="contained"
|
mode="contained"
|
||||||
icon="save"
|
icon="save"
|
||||||
onPress={save}>
|
onPress={save}>
|
||||||
|
|
14
SetForm.tsx
14
SetForm.tsx
|
@ -18,6 +18,7 @@ export default function SetForm({
|
||||||
const [reps, setReps] = useState(set.reps.toString());
|
const [reps, setReps] = useState(set.reps.toString());
|
||||||
const [weight, setWeight] = useState(set.weight.toString());
|
const [weight, setWeight] = useState(set.weight.toString());
|
||||||
const [unit, setUnit] = useState(set.unit);
|
const [unit, setUnit] = useState(set.unit);
|
||||||
|
const [uri, setUri] = useState(set.image);
|
||||||
const [selection, setSelection] = useState({
|
const [selection, setSelection] = useState({
|
||||||
start: 0,
|
start: 0,
|
||||||
end: set.reps.toString().length,
|
end: set.reps.toString().length,
|
||||||
|
@ -33,8 +34,18 @@ export default function SetForm({
|
||||||
weight: Number(weight),
|
weight: Number(weight),
|
||||||
id: set.id,
|
id: set.id,
|
||||||
unit,
|
unit,
|
||||||
|
image: uri,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const db = useContext(DatabaseContext);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
console.log('SetForm.useEffect:', {uri, name: set.name});
|
||||||
|
if (!uri)
|
||||||
|
db.executeSql(`SELECT image FROM sets WHERE name = ? LIMIT 1`, [
|
||||||
|
set.name,
|
||||||
|
]).then(([result]) => setUri(result.rows.item(0).image));
|
||||||
|
}, [uri, db, set.name]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -78,7 +89,7 @@ export default function SetForm({
|
||||||
{set.created.replace('T', ' ')}
|
{set.created.replace('T', ' ')}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
<Text>
|
<Text style={{marginBottom: 10}}>
|
||||||
{workouts?.map((workout, index) => (
|
{workouts?.map((workout, index) => (
|
||||||
<React.Fragment key={workout}>
|
<React.Fragment key={workout}>
|
||||||
<Text
|
<Text
|
||||||
|
@ -92,6 +103,7 @@ export default function SetForm({
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
))}
|
))}
|
||||||
</Text>
|
</Text>
|
||||||
|
{uri && <Image source={{uri}} style={{width: 250, height: 250}} />}
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
<Button
|
<Button
|
||||||
disabled={!name}
|
disabled={!name}
|
||||||
|
|
42
SetItem.tsx
42
SetItem.tsx
|
@ -1,6 +1,6 @@
|
||||||
import {NavigationProp, useNavigation} from '@react-navigation/native';
|
import {NavigationProp, useNavigation} from '@react-navigation/native';
|
||||||
import React, {useCallback, useContext, useState} from 'react';
|
import React, {useCallback, useContext, useState} from 'react';
|
||||||
import {GestureResponderEvent, Text} from 'react-native';
|
import {GestureResponderEvent, Image, Text} from 'react-native';
|
||||||
import {Divider, List, Menu} from 'react-native-paper';
|
import {Divider, List, Menu} from 'react-native-paper';
|
||||||
import {DatabaseContext} from './App';
|
import {DatabaseContext} from './App';
|
||||||
import {HomePageParams} from './HomePage';
|
import {HomePageParams} from './HomePage';
|
||||||
|
@ -11,11 +11,15 @@ export default function SetItem({
|
||||||
onRemove,
|
onRemove,
|
||||||
dates,
|
dates,
|
||||||
setDates,
|
setDates,
|
||||||
|
images,
|
||||||
|
setImages,
|
||||||
}: {
|
}: {
|
||||||
item: Set;
|
item: Set;
|
||||||
onRemove: () => void;
|
onRemove: () => void;
|
||||||
dates: boolean;
|
dates: boolean;
|
||||||
setDates: (value: boolean) => void;
|
setDates: (value: boolean) => void;
|
||||||
|
images: boolean;
|
||||||
|
setImages: (value: boolean) => void;
|
||||||
}) {
|
}) {
|
||||||
const [showMenu, setShowMenu] = useState(false);
|
const [showMenu, setShowMenu] = useState(false);
|
||||||
const [anchor, setAnchor] = useState({x: 0, y: 0});
|
const [anchor, setAnchor] = useState({x: 0, y: 0});
|
||||||
|
@ -46,7 +50,14 @@ export default function SetItem({
|
||||||
const toggleDates = useCallback(() => {
|
const toggleDates = useCallback(() => {
|
||||||
setDates(!dates);
|
setDates(!dates);
|
||||||
setShowMenu(false);
|
setShowMenu(false);
|
||||||
}, [dates, setDates]);
|
if (!dates && images) setImages(false);
|
||||||
|
}, [dates, setDates, images, setImages]);
|
||||||
|
|
||||||
|
const toggleImages = useCallback(() => {
|
||||||
|
setImages(!images);
|
||||||
|
setShowMenu(false);
|
||||||
|
if (!images && dates) setDates(false);
|
||||||
|
}, [dates, setDates, images, setImages]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -56,16 +67,31 @@ export default function SetItem({
|
||||||
description={`${item.reps} x ${item.weight}${item.unit || 'kg'}`}
|
description={`${item.reps} x ${item.weight}${item.unit || 'kg'}`}
|
||||||
onLongPress={longPress}
|
onLongPress={longPress}
|
||||||
right={() => (
|
right={() => (
|
||||||
<Text
|
<>
|
||||||
style={{
|
{dates && (
|
||||||
alignSelf: 'center',
|
<Text
|
||||||
}}>
|
style={{
|
||||||
{dates ? item.created?.replace('T', ' ') : null}
|
alignSelf: 'center',
|
||||||
|
}}>
|
||||||
|
{item.created?.replace('T', ' ')}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
{images && (
|
||||||
|
<Image
|
||||||
|
source={{uri: item.image}}
|
||||||
|
style={{height: 75, width: 75}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<Menu
|
<Menu
|
||||||
anchor={anchor}
|
anchor={anchor}
|
||||||
visible={showMenu}
|
visible={showMenu}
|
||||||
onDismiss={() => setShowMenu(false)}>
|
onDismiss={() => setShowMenu(false)}>
|
||||||
<Menu.Item icon="copy" onPress={copy} title="Copy" />
|
<Menu.Item icon="copy" onPress={copy} title="Copy" />
|
||||||
|
<Menu.Item
|
||||||
|
icon="image-outline"
|
||||||
|
onPress={toggleImages}
|
||||||
|
title="Images"
|
||||||
|
/>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
icon="calendar-outline"
|
icon="calendar-outline"
|
||||||
onPress={toggleDates}
|
onPress={toggleDates}
|
||||||
|
@ -74,7 +100,7 @@ export default function SetItem({
|
||||||
<Divider />
|
<Divider />
|
||||||
<Menu.Item icon="trash" onPress={remove} title="Delete" />
|
<Menu.Item icon="trash" onPress={remove} title="Delete" />
|
||||||
</Menu>
|
</Menu>
|
||||||
</Text>
|
</>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -34,6 +34,7 @@ export default function SetList() {
|
||||||
const [refreshing, setRefreshing] = useState(false);
|
const [refreshing, setRefreshing] = useState(false);
|
||||||
const [end, setEnd] = useState(false);
|
const [end, setEnd] = useState(false);
|
||||||
const [dates, setDates] = useState(false);
|
const [dates, setDates] = useState(false);
|
||||||
|
const [images, setImages] = useState(false);
|
||||||
const db = useContext(DatabaseContext);
|
const db = useContext(DatabaseContext);
|
||||||
const navigation = useNavigation<NavigationProp<HomePageParams>>();
|
const navigation = useNavigation<NavigationProp<HomePageParams>>();
|
||||||
|
|
||||||
|
@ -143,12 +144,14 @@ export default function SetList() {
|
||||||
<SetItem
|
<SetItem
|
||||||
dates={dates}
|
dates={dates}
|
||||||
setDates={setDates}
|
setDates={setDates}
|
||||||
|
images={images}
|
||||||
|
setImages={setImages}
|
||||||
item={item}
|
item={item}
|
||||||
key={item.id}
|
key={item.id}
|
||||||
onRemove={refresh}
|
onRemove={refresh}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
[refresh, dates, setDates],
|
[refresh, dates, setDates, images, setImages],
|
||||||
);
|
);
|
||||||
|
|
||||||
const next = useCallback(async () => {
|
const next = useCallback(async () => {
|
||||||
|
|
4
db.ts
4
db.ts
|
@ -51,3 +51,7 @@ export const addHidden = `
|
||||||
export const addNotify = `
|
export const addNotify = `
|
||||||
ALTER TABLE settings ADD COLUMN notify DEFAULT false;
|
ALTER TABLE settings ADD COLUMN notify DEFAULT false;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const addImage = `
|
||||||
|
ALTER TABLE sets ADD COLUMN image TEXT NULL;
|
||||||
|
`;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user