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 {
|
||||
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(`
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,11 +29,15 @@ 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);
|
||||
if (name) {
|
||||
await db.executeSql(`UPDATE sets SET name = ? WHERE name = ?`, [
|
||||
name,
|
||||
params.value.name,
|
||||
|
@ -42,8 +47,14 @@ export default function EditWorkout() {
|
|||
WHERE workouts LIKE ?`,
|
||||
[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}>
|
||||
|
|
14
SetForm.tsx
14
SetForm.tsx
|
@ -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}
|
||||
|
|
34
SetItem.tsx
34
SetItem.tsx
|
@ -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={() => (
|
||||
<>
|
||||
{dates && (
|
||||
<Text
|
||||
style={{
|
||||
alignSelf: 'center',
|
||||
}}>
|
||||
{dates ? item.created?.replace('T', ' ') : null}
|
||||
{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>
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
|
|
|
@ -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
4
db.ts
|
@ -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;
|
||||
`;
|
||||
|
|
Loading…
Reference in New Issue
Block a user