Overview
Exercise storage functions manage the user’s exercise library. Each exercise has a unique ID, a name, and optional notes. On first load, exercises are initialized from the default Rippler program.
Storage Key
Stores the JSON-serialized array of Exercise objects
Functions
getExercises
Retrieves all exercises from storage. If no exercises exist, initializes with default exercises from the Rippler program.
async function getExercises () : Promise < Exercise []>
Array of all exercises, or empty array if an error occurs
This function automatically initializes exercises from ripplerProgram.exercises on first run, creating IDs and saving them to storage.
Example
import { getExercises } from '@/lib/storage' ;
const exercises = await getExercises ();
console . log ( exercises );
// [
// { id: 'ex_0', name: 'Squat' },
// { id: 'ex_1', name: 'Bench Press' },
// { id: 'ex_2', name: 'Deadlift', notes: 'Focus on form' }
// ]
Source Code Reference
See implementation at lib/storage.ts:13-31
saveExercises
Saves the complete array of exercises to storage, overwriting existing data.
async function saveExercises ( exercises : Exercise []) : Promise < void >
Complete array of exercises to save
This function overwrites all existing exercises. Ensure you’ve loaded current exercises with getExercises() before modifying and saving.
Example
import { getExercises , saveExercises } from '@/lib/storage' ;
// Load current exercises
const exercises = await getExercises ();
// Modify array
exercises [ 0 ]. notes = 'Updated notes' ;
// Save back to storage
await saveExercises ( exercises );
Source Code Reference
See implementation at lib/storage.ts:33-39
addExercise
Creates a new exercise and adds it to storage. Generates a unique timestamp-based ID.
async function addExercise ( name : string , notes ?: string ) : Promise < Exercise >
The name of the exercise (e.g., “Squat”, “Bench Press”)
Optional notes about the exercise (form cues, variations, etc.)
The newly created exercise object with generated ID
Example
import { addExercise } from '@/lib/storage' ;
const newExercise = await addExercise (
'Romanian Deadlift' ,
'Keep knees slightly bent'
);
console . log ( newExercise );
// {
// id: 'ex_1234567890',
// name: 'Romanian Deadlift',
// notes: 'Keep knees slightly bent'
// }
ID Generation
Exercise IDs are generated using the pattern ex_${Date.now()}, ensuring uniqueness based on creation timestamp.
Source Code Reference
See implementation at lib/storage.ts:41-51
updateExercise
Updates specific fields of an existing exercise by ID. Uses partial updates to modify only the fields you specify.
async function updateExercise (
id : string ,
updates : Partial < Exercise >
) : Promise < void >
The unique ID of the exercise to update
updates
Partial<Exercise>
required
Object containing the fields to update (name, notes, etc.)
If the exercise ID is not found, the function completes silently without throwing an error.
Example
import { updateExercise } from '@/lib/storage' ;
// Update just the name
await updateExercise ( 'ex_1234567890' , {
name: 'Front Squat'
});
// Update multiple fields
await updateExercise ( 'ex_1234567890' , {
name: 'Front Squat' ,
notes: 'Elbows high, core tight'
});
Source Code Reference
See implementation at lib/storage.ts:53-63
deleteExercise
Removes an exercise from storage by ID.
async function deleteExercise ( id : string ) : Promise < void >
The unique ID of the exercise to delete
This operation cannot be undone. Consider warning users before deletion, especially if the exercise is referenced in logged workouts or goal weights.
Example
import { deleteExercise } from '@/lib/storage' ;
await deleteExercise ( 'ex_1234567890' );
Source Code Reference
See implementation at lib/storage.ts:65-69
Data Type
export interface Exercise {
id : string ; // Unique identifier (e.g., 'ex_1234567890')
name : string ; // Exercise name (e.g., 'Squat')
notes ?: string ; // Optional notes about form, variations, etc.
}
Common Patterns
Loading and Displaying Exercises
import { getExercises } from '@/lib/storage' ;
import { FlatList , Text } from 'react-native' ;
function ExerciseList () {
const [ exercises , setExercises ] = useState < Exercise []>([]);
useEffect (() => {
loadExercises ();
}, []);
async function loadExercises () {
const data = await getExercises ();
setExercises ( data );
}
return (
< FlatList
data = { exercises }
keyExtractor = {(item) => item. id }
renderItem = {({ item }) => <Text>{ item . name }</Text>}
/>
);
}
import { addExercise } from '@/lib/storage' ;
import { useState } from 'react' ;
function AddExerciseForm ({ onComplete } : { onComplete : () => void }) {
const [ name , setName ] = useState ( '' );
const [ notes , setNotes ] = useState ( '' );
async function handleSubmit () {
if ( ! name . trim ()) return ;
await addExercise ( name , notes || undefined );
setName ( '' );
setNotes ( '' );
onComplete ();
}
return (
< View >
< TextInput
placeholder = "Exercise name"
value = { name }
onChangeText = { setName }
/>
< TextInput
placeholder = "Notes (optional)"
value = { notes }
onChangeText = { setNotes }
/>
< Button title = "Add Exercise" onPress = { handleSubmit } />
</ View >
);
}
Batch Updating Multiple Exercises
import { getExercises , saveExercises } from '@/lib/storage' ;
async function addNotesToAllSquats () {
// Load all exercises
const exercises = await getExercises ();
// Modify in memory
const updated = exercises . map ( ex => {
if ( ex . name . toLowerCase (). includes ( 'squat' )) {
return { ... ex , notes: 'Drive through heels' };
}
return ex ;
});
// Single save operation
await saveExercises ( updated );
}
getGoalWeight Get goal weight for an exercise by name
getLoggedWorkouts View exercises logged in workouts