From 4c632e164eb15235e5254b042259b870e4fd7857 Mon Sep 17 00:00:00 2001 From: AG Date: Fri, 28 Nov 2025 18:20:22 +0200 Subject: [PATCH] UUID generation fixed --- App.tsx | 3 ++- components/AICoach.tsx | 7 ++++--- components/ExerciseModal.tsx | 3 ++- components/Plans.tsx | 7 ++++--- components/Tracker.tsx | 3 ++- services/geminiService.ts | 3 ++- utils/uuid.ts | 10 ++++++++++ 7 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 utils/uuid.ts diff --git a/App.tsx b/App.tsx index 1edbeda..04b50ff 100644 --- a/App.tsx +++ b/App.tsx @@ -12,6 +12,7 @@ import { TabView, WorkoutSession, WorkoutSet, WorkoutPlan, User, Language } from import { getSessions, saveSession, deleteSession, getPlans } from './services/storage'; import { getCurrentUserProfile, getMe } from './services/auth'; import { getSystemLanguage } from './services/i18n'; +import { generateId } from './utils/uuid'; function App() { const [currentUser, setCurrentUser] = useState(null); @@ -86,7 +87,7 @@ function App() { const currentWeight = startWeight || profile?.weight || 70; const newSession: WorkoutSession = { - id: crypto.randomUUID(), + id: generateId(), startTime: Date.now(), userBodyWeight: currentWeight, sets: [], diff --git a/components/AICoach.tsx b/components/AICoach.tsx index 57fd1b9..08b2f80 100644 --- a/components/AICoach.tsx +++ b/components/AICoach.tsx @@ -5,6 +5,7 @@ import { createFitnessChat } from '../services/geminiService'; import { WorkoutSession, Language, UserProfile, WorkoutPlan } from '../types'; import { Chat, GenerateContentResponse } from '@google/genai'; import { t } from '../services/i18n'; +import { generateId } from '../utils/uuid'; interface AICoachProps { history: WorkoutSession[]; @@ -53,7 +54,7 @@ const AICoach: React.FC = ({ history, userProfile, plans, lang }) const handleSend = async () => { if (!input.trim() || !chatSessionRef.current || loading) return; - const userMsg: Message = { id: crypto.randomUUID(), role: 'user', text: input }; + const userMsg: Message = { id: generateId(), role: 'user', text: input }; setMessages(prev => [...prev, userMsg]); setInput(''); setLoading(true); @@ -63,7 +64,7 @@ const AICoach: React.FC = ({ history, userProfile, plans, lang }) const text = result.text; const aiMsg: Message = { - id: crypto.randomUUID(), + id: generateId(), role: 'model', text: text || "Error generating response." }; @@ -80,7 +81,7 @@ const AICoach: React.FC = ({ history, userProfile, plans, lang }) errorText = err.message; } } - setMessages(prev => [...prev, { id: crypto.randomUUID(), role: 'model', text: errorText }]); + setMessages(prev => [...prev, { id: generateId(), role: 'model', text: errorText }]); } finally { setLoading(false); } diff --git a/components/ExerciseModal.tsx b/components/ExerciseModal.tsx index c2e4bc0..ff32c26 100644 --- a/components/ExerciseModal.tsx +++ b/components/ExerciseModal.tsx @@ -2,6 +2,7 @@ import React, { useState } from 'react'; import { X, Dumbbell, User, Flame, Timer as TimerIcon, ArrowUp, ArrowRight, Footprints, Ruler, Percent } from 'lucide-react'; import { ExerciseDef, ExerciseType, Language } from '../types'; import { t } from '../services/i18n'; +import { generateId } from '../utils/uuid'; import FilledInput from './FilledInput'; interface ExerciseModalProps { @@ -43,7 +44,7 @@ const ExerciseModal: React.FC = ({ isOpen, onClose, onSave, } const newEx: ExerciseDef = { - id: crypto.randomUUID(), + id: generateId(), name: trimmedName, type: newType, ...(newType === ExerciseType.BODYWEIGHT && { bodyWeightPercentage: parseFloat(newBwPercentage) || 100 }) diff --git a/components/Plans.tsx b/components/Plans.tsx index b06edc0..31a5b04 100644 --- a/components/Plans.tsx +++ b/components/Plans.tsx @@ -4,6 +4,7 @@ import { Plus, Trash2, PlayCircle, Dumbbell, Save, X, ChevronRight, List, ArrowU import { WorkoutPlan, ExerciseDef, PlannedSet, Language, ExerciseType } from '../types'; import { getPlans, savePlan, deletePlan, getExercises, saveExercise } from '../services/storage'; import { t } from '../services/i18n'; +import { generateId } from '../utils/uuid'; interface PlansProps { userId: string; @@ -68,7 +69,7 @@ const Plans: React.FC = ({ userId, onStartPlan, lang }) => { }, [userId]); const handleCreateNew = () => { - setEditId(crypto.randomUUID()); + setEditId(generateId()); setName(''); setDescription(''); setSteps([]); @@ -103,7 +104,7 @@ const Plans: React.FC = ({ userId, onStartPlan, lang }) => { const addStep = (ex: ExerciseDef) => { const newStep: PlannedSet = { - id: crypto.randomUUID(), + id: generateId(), exerciseId: ex.id, exerciseName: ex.name, exerciseType: ex.type, @@ -116,7 +117,7 @@ const Plans: React.FC = ({ userId, onStartPlan, lang }) => { const handleCreateExercise = async () => { if (!newExName.trim()) return; const newEx: ExerciseDef = { - id: crypto.randomUUID(), + id: generateId(), name: newExName.trim(), type: newExType, ...(newExType === ExerciseType.BODYWEIGHT && { bodyWeightPercentage: parseFloat(newExBwPercentage) || 100 }) diff --git a/components/Tracker.tsx b/components/Tracker.tsx index b142e18..aca4f5c 100644 --- a/components/Tracker.tsx +++ b/components/Tracker.tsx @@ -5,6 +5,7 @@ import { WorkoutSession, WorkoutSet, ExerciseDef, ExerciseType, WorkoutPlan, Lan import { getExercises, getLastSetForExercise, saveExercise, getPlans } from '../services/storage'; import { getCurrentUserProfile } from '../services/auth'; import { t } from '../services/i18n'; +import { generateId } from '../utils/uuid'; interface TrackerProps { userId: string; @@ -151,7 +152,7 @@ const Tracker: React.FC = ({ userId, userWeight, activeSession, ac if (!activeSession || !selectedExercise) return; const newSet: WorkoutSet = { - id: crypto.randomUUID(), + id: generateId(), exerciseId: selectedExercise.id, exerciseName: selectedExercise.name, type: selectedExercise.type, diff --git a/services/geminiService.ts b/services/geminiService.ts index 124e56b..ec1f7d9 100644 --- a/services/geminiService.ts +++ b/services/geminiService.ts @@ -1,5 +1,6 @@ import { WorkoutSession, UserProfile, WorkoutPlan } from '../types'; import { api } from './api'; +import { generateId } from '../utils/uuid'; interface FitnessChatOptions { history: WorkoutSession[]; @@ -16,7 +17,7 @@ export const createFitnessChat = ( plans?: WorkoutPlan[] ): any => { // Generate a unique session ID for this chat instance - const sessionId = crypto.randomUUID(); + const sessionId = generateId(); // Summarize workout history const workoutSummary = history.slice(0, 20).map(s => ({ diff --git a/utils/uuid.ts b/utils/uuid.ts new file mode 100644 index 0000000..65d6a1e --- /dev/null +++ b/utils/uuid.ts @@ -0,0 +1,10 @@ +export const generateId = (): string => { + if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') { + return crypto.randomUUID(); + } + // Fallback for non-secure contexts + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); +};