Add images to sets

This commit is contained in:
Brandon Presley 2022-08-28 20:55:12 +12:00
parent 9b8fb95559
commit f6dec0c3b2
8 changed files with 98 additions and 25 deletions

View File

@ -16,6 +16,7 @@ import {SQLiteDatabase} from 'react-native-sqlite-storage';
import Ionicon from 'react-native-vector-icons/Ionicons';
import {
addHidden,
addImage,
addNotify,
addSound,
createPlans,
@ -75,6 +76,7 @@ const App = () => {
await _db.executeSql(createWorkouts);
await _db.executeSql(addHidden).catch(() => null);
await _db.executeSql(addNotify).catch(() => null);
await _db.executeSql(addImage).catch(() => null);
const [result] = await _db.executeSql(`SELECT * FROM settings LIMIT 1`);
if (result.rows.length === 0)
return _db.executeSql(`

View File

@ -57,13 +57,13 @@ export default function EditSet() {
const add = useCallback(
async (set: Set) => {
const {name, reps, weight, unit} = set;
const {name, reps, weight, unit, image} = set;
const insert = `
INSERT INTO sets(name, reps, weight, created, unit)
VALUES (?,?,?,strftime('%Y-%m-%dT%H:%M:%S', 'now', 'localtime'),?)
INSERT INTO sets(name, reps, weight, created, unit, image)
VALUES (?,?,?,strftime('%Y-%m-%dT%H:%M:%S', 'now', 'localtime'),?, ?)
`;
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 settings: Settings = result.rows.item(0);
if (settings.notify === 0) return navigation.goBack();

View File

@ -15,6 +15,7 @@ import {WorkoutsPageParams} from './WorkoutsPage';
export default function EditWorkout() {
const [name, setName] = useState('');
const [uri, setUri] = useState('');
const {params} = useRoute<RouteProp<WorkoutsPageParams, 'EditWorkout'>>();
const db = useContext(DatabaseContext);
const navigation = useNavigation();
@ -28,22 +29,32 @@ export default function EditWorkout() {
headerRight: null,
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 () => {
console.log(`${EditWorkout.name}.update`, set);
await db.executeSql(`UPDATE sets SET name = ? WHERE name = ?`, [
name,
params.value.name,
]);
await db.executeSql(
`UPDATE plans SET workouts = REPLACE(workouts, ?, ?)
if (name) {
await db.executeSql(`UPDATE sets SET name = ? WHERE name = ?`, [
name,
params.value.name,
]);
await db.executeSql(
`UPDATE plans SET workouts = REPLACE(workouts, ?, ?)
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();
}, [db, navigation, params.value.name, name]);
}, [db, navigation, params.value.name, name, uri]);
const add = useCallback(async () => {
const insert = `
@ -59,18 +70,32 @@ export default function EditWorkout() {
return add();
}, [update, add, params.value.name]);
const changeImage = useCallback(async () => {
const {fileCopyUri} = await DocumentPicker.pickSingle({
type: 'image/*',
copyTo: 'documentDirectory',
});
if (fileCopyUri) setUri(fileCopyUri);
}, []);
return (
<ScrollView style={{padding: 10, height: '90%'}}>
{params.value.name ? (
<>
<MassiveInput label="Old name" value={params.value.name} disabled />
<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} />
)}
<Button
disabled={!name && !!params.value.name}
disabled={!name && !!params.value.name && !uri}
mode="contained"
icon="save"
onPress={save}>

View File

@ -18,6 +18,7 @@ export default function SetForm({
const [reps, setReps] = useState(set.reps.toString());
const [weight, setWeight] = useState(set.weight.toString());
const [unit, setUnit] = useState(set.unit);
const [uri, setUri] = useState(set.image);
const [selection, setSelection] = useState({
start: 0,
end: set.reps.toString().length,
@ -33,8 +34,18 @@ export default function SetForm({
weight: Number(weight),
id: set.id,
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 (
<>
@ -78,7 +89,7 @@ export default function SetForm({
{set.created.replace('T', ' ')}
</Text>
)}
<Text>
<Text style={{marginBottom: 10}}>
{workouts?.map((workout, index) => (
<React.Fragment key={workout}>
<Text
@ -92,6 +103,7 @@ export default function SetForm({
</React.Fragment>
))}
</Text>
{uri && <Image source={{uri}} style={{width: 250, height: 250}} />}
</ScrollView>
<Button
disabled={!name}

View File

@ -1,6 +1,6 @@
import {NavigationProp, useNavigation} from '@react-navigation/native';
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 {DatabaseContext} from './App';
import {HomePageParams} from './HomePage';
@ -11,11 +11,15 @@ export default function SetItem({
onRemove,
dates,
setDates,
images,
setImages,
}: {
item: Set;
onRemove: () => void;
dates: boolean;
setDates: (value: boolean) => void;
images: boolean;
setImages: (value: boolean) => void;
}) {
const [showMenu, setShowMenu] = useState(false);
const [anchor, setAnchor] = useState({x: 0, y: 0});
@ -46,7 +50,14 @@ export default function SetItem({
const toggleDates = useCallback(() => {
setDates(!dates);
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 (
<>
@ -56,16 +67,31 @@ export default function SetItem({
description={`${item.reps} x ${item.weight}${item.unit || 'kg'}`}
onLongPress={longPress}
right={() => (
<Text
style={{
alignSelf: 'center',
}}>
{dates ? item.created?.replace('T', ' ') : null}
<>
{dates && (
<Text
style={{
alignSelf: 'center',
}}>
{item.created?.replace('T', ' ')}
</Text>
)}
{images && (
<Image
source={{uri: item.image}}
style={{height: 75, width: 75}}
/>
)}
<Menu
anchor={anchor}
visible={showMenu}
onDismiss={() => setShowMenu(false)}>
<Menu.Item icon="copy" onPress={copy} title="Copy" />
<Menu.Item
icon="image-outline"
onPress={toggleImages}
title="Images"
/>
<Menu.Item
icon="calendar-outline"
onPress={toggleDates}
@ -74,7 +100,7 @@ export default function SetItem({
<Divider />
<Menu.Item icon="trash" onPress={remove} title="Delete" />
</Menu>
</Text>
</>
)}
/>
</>

View File

@ -34,6 +34,7 @@ export default function SetList() {
const [refreshing, setRefreshing] = useState(false);
const [end, setEnd] = useState(false);
const [dates, setDates] = useState(false);
const [images, setImages] = useState(false);
const db = useContext(DatabaseContext);
const navigation = useNavigation<NavigationProp<HomePageParams>>();
@ -143,12 +144,14 @@ export default function SetList() {
<SetItem
dates={dates}
setDates={setDates}
images={images}
setImages={setImages}
item={item}
key={item.id}
onRemove={refresh}
/>
),
[refresh, dates, setDates],
[refresh, dates, setDates, images, setImages],
);
const next = useCallback(async () => {

4
db.ts
View File

@ -51,3 +51,7 @@ export const addHidden = `
export const addNotify = `
ALTER TABLE settings ADD COLUMN notify DEFAULT false;
`;
export const addImage = `
ALTER TABLE sets ADD COLUMN image TEXT NULL;
`;

1
set.ts
View File

@ -6,4 +6,5 @@ export default interface Set {
created?: string;
unit?: string;
hidden?: boolean;
image?: string;
}