Files
memefast/resources/js/stores/MediaStore.js
2025-07-16 15:49:30 +08:00

315 lines
11 KiB
JavaScript

import axiosInstance from '@/plugins/axios-plugin';
import { mountStoreDevtool } from 'simple-zustand-devtools';
import { toast } from 'sonner';
import { route } from 'ziggy-js';
import { create } from 'zustand';
import { devtools } from 'zustand/middleware';
const useMediaStore = create(
devtools((set, get) => ({
currentTab: 'memes',
memes: [],
backgrounds: [],
isFetchingMemes: false,
isFetchingBackgrounds: false,
// Selected items
selectedMeme: null,
selectedBackground: null,
currentCaption: 'I am chicken rice',
watermarked: true,
keywords: [],
isLoadingAIHints: false,
isGeneratingMeme: false,
setCurrentTab: (tab) => {
set({ currentTab: tab });
},
// Selection actions
selectMeme: async (meme) => {
set({ selectedMeme: meme });
try {
await axiosInstance.post(route('api.app.select.meme'), {
meme_ids: meme.ids,
});
} catch (error) {
console.error('Error meme selection:', error);
}
},
selectBackground: async (background) => {
set({ selectedBackground: background });
try {
await axiosInstance.post(route('api.app.select.background'), {
background_ids: background.ids,
});
} catch (error) {
console.error('Error background selection:', error);
}
},
// Update current caption when user edits text
updateCurrentCaption: (caption) => {
set({ currentCaption: caption });
},
// Clear selections
clearSelectedMeme: () => {
set({ selectedMeme: null });
},
clearSelectedBackground: () => {
set({ selectedBackground: null });
},
// Save meme action
saveMeme: async (captionTexts, isPremiumExport = false) => {
try {
const { selectedMeme, selectedBackground } = get();
await axiosInstance.post(route('api.app.save.meme'), {
meme_media_ids: selectedMeme?.ids || null,
background_media_ids: selectedBackground?.ids || null,
caption_texts: captionTexts,
is_premium_export: isPremiumExport,
});
} catch (error) {
console.error('Error saving meme:', error);
// Silently ignore save tracking errors
}
},
// Fetch AI hints
fetchAIHints: async () => {
set({ isLoadingAIHints: true });
try {
const response = await axiosInstance.post(route('api.ai_hints'));
set({
keywords: response.data.success?.data?.keywords || [],
});
return response.data;
} catch (error) {
console.error(route('api.ai_hints'));
console.error('Error fetching AI hints:', error);
toast.error('Failed to fetch AI hints');
} finally {
set({ isLoadingAIHints: false });
}
},
// Clear keywords
clearKeywords: () => {
set({ keywords: [] });
},
init: async () => {
try {
const response = await axiosInstance.post(route('api.app.init'));
if (response?.data?.success?.data?.init) {
set({
currentCaption: response.data.success.data.init.caption,
selectedMeme: response.data.success.data.init.meme,
selectedBackground: response.data.success.data.init.background,
});
} else {
throw 'Invalid API response';
}
} catch (error) {
console.error('Error fetching init:', error);
throw error;
}
},
generateMeme: async (prompt) => {
set({ isGeneratingMeme: true });
try {
const response = await axiosInstance.post(route('api.user.generate_meme'), { prompt: prompt });
if (response?.data?.success?.data?.job_id) {
return response.data;
} else {
throw 'Invalid API response';
}
} catch (error) {
console.error('Error generating meme:', error);
toast.error('Failed to generate meme');
set({ isGeneratingMeme: false });
throw error;
}
},
checkMemeJobStatus: async (jobId) => {
try {
const response = await axiosInstance.post(route('api.user.check_meme_job_status'), { job_id: jobId });
return response.data;
} catch (error) {
console.error('Error checking job status:', error);
throw error;
}
},
checkActiveJob: async () => {
try {
const response = await axiosInstance.post(route('api.user.get_active_job'));
return response.data;
} catch (error) {
console.error('Error checking active job:', error);
throw error;
}
},
getMemeHistory: async () => {
try {
const response = await axiosInstance.post(route('api.user.get_meme_history'));
return response.data;
} catch (error) {
console.error('Error getting meme history:', error);
throw error;
}
},
updateMemeResult: (result) => {
set({
currentCaption: result.generate.caption,
selectedMeme: result.generate.meme,
selectedBackground: result.generate.background,
isGeneratingMeme: false,
});
},
setGeneratingMeme: (isGenerating) => {
set({ isGeneratingMeme: isGenerating });
},
// Fetch memes (overlays)
fetchMemes: async () => {
set({ isFetchingMemes: true });
try {
const response = await axiosInstance.post(route('api.app.memes'));
if (response?.data?.success?.data?.memes) {
set({
memes: response.data.success.data.memes,
isFetchingMemes: false,
});
return response.data.success.data.memes;
} else {
throw 'Invalid API response';
}
} catch (error) {
console.error('Error fetching memes:', error);
set({ isFetchingMemes: false });
if (error?.response?.data?.error?.message?.length > 0) {
toast.error(error.response.data.error.message);
}
throw error;
}
},
// Fetch backgrounds
fetchBackgrounds: async () => {
set({ isFetchingBackgrounds: true });
try {
const response = await axiosInstance.post(route('api.app.background'));
if (response?.data?.success?.data?.backgrounds) {
set({
backgrounds: response.data.success.data.backgrounds,
isFetchingBackgrounds: false,
});
return response.data.success.data.backgrounds;
} else {
throw 'Invalid API response';
}
} catch (error) {
console.error('Error fetching backgrounds:', error);
set({ isFetchingBackgrounds: false });
if (error?.response?.data?.error?.message?.length > 0) {
toast.error(error.response.data.error.message);
}
throw error;
}
},
// Search memes
searchMemes: async (query = '') => {
set({ isFetchingMemes: true });
try {
const response = await axiosInstance.post(route('api.app.search.memes'), { query });
if (response?.data?.success?.data?.memes) {
set({
memes: response.data.success.data.memes,
isFetchingMemes: false,
});
return response.data.success.data.memes;
} else {
throw 'Invalid API response';
}
} catch (error) {
console.error('Error searching memes:', error);
set({ isFetchingMemes: false });
if (error?.response?.data?.error?.message?.length > 0) {
toast.error(error.response.data.error.message);
}
throw error;
}
},
// Search backgrounds
searchBackgrounds: async (query = '') => {
set({ isFetchingBackgrounds: true });
try {
const response = await axiosInstance.post(route('api.app.search.background'), { query });
if (response?.data?.success?.data?.backgrounds) {
set({
backgrounds: response.data.success.data.backgrounds,
isFetchingBackgrounds: false,
});
return response.data.success.data.backgrounds;
} else {
throw 'Invalid API response';
}
} catch (error) {
console.error('Error searching backgrounds:', error);
set({ isFetchingBackgrounds: false });
if (error?.response?.data?.error?.message?.length > 0) {
toast.error(error.response.data.error.message);
}
throw error;
}
},
// Reset store to default state
restoreMemeStateToDefault: () => {
console.log('restoreMemeStateToDefault');
set({
memes: [],
backgrounds: [],
isFetchingMemes: false,
isFetchingBackgrounds: false,
selectedMeme: null,
selectedBackground: null,
isGeneratingMeme: false,
});
},
})),
{
name: 'MemeStore',
store: 'MemeStore',
},
);
if (import.meta.env.APP_ENV === 'local') {
mountStoreDevtool('MediaStore', useMediaStore);
}
export default useMediaStore;