UNPKG

@oxyhq/services

Version:

Reusable OxyHQ module to handle authentication, user management, karma system, device-based session management and more 🚀

145 lines (141 loc) • 3.74 kB
"use strict"; import { create } from 'zustand'; // Shallow compare two file metadata objects by keys/values function shallowEqualFile(a, b) { if (a === b) return true; if (!a || !b) return false; const aKeys = Object.keys(a); const bKeys = Object.keys(b); if (aKeys.length !== bKeys.length) return false; for (const k of aKeys) { // treat metadata/variants shallowly by reference if (a[k] !== b[k]) return false; } return true; } // Basic upload progress type for aggregate tracking const initialState = { files: {}, order: [], uploading: false, deleting: null, uploadProgress: null }; export const useFileStore = create((set, get) => ({ ...initialState, setFiles: (files, opts) => set(state => { const merge = opts?.merge !== false; // default true if (!merge) { const map = {}; const order = []; files.forEach(f => { map[f.id] = f; order.push(f.id); }); // detect if identical to avoid redundant updates const sameOrder = order.length === state.order.length && order.every((id, i) => id === state.order[i]); let sameFiles = sameOrder; if (sameOrder) { sameFiles = order.every(id => state.files[id] && shallowEqualFile(state.files[id], map[id])); } if (sameOrder && sameFiles) return {}; return { files: map, order }; } const newFiles = { ...state.files }; const newOrder = [...state.order]; let changed = false; files.forEach(f => { const prev = state.files[f.id]; const merged = { ...(prev || {}), ...f }; if (!prev || !shallowEqualFile(prev, merged)) { newFiles[f.id] = merged; changed = true; } if (!newOrder.includes(f.id)) { newOrder.unshift(f.id); changed = true; } }); if (!changed) return {}; return { files: newFiles, order: newOrder }; }), addFile: (file, opts) => set(state => { const prepend = opts?.prepend !== false; // default true if (state.files[file.id]) { if (shallowEqualFile(state.files[file.id], file)) return {}; return { files: { ...state.files, [file.id]: file } }; } return { files: { ...state.files, [file.id]: file }, order: prepend ? [file.id, ...state.order] : [...state.order, file.id] }; }), updateFile: (id, patch) => set(state => { const existing = state.files[id]; if (!existing) return {}; const updated = { ...existing, ...patch }; if (shallowEqualFile(existing, updated)) return {}; return { files: { ...state.files, [id]: updated } }; }), removeFile: id => set(state => { if (!state.files[id]) return {}; const { [id]: _removed, ...rest } = state.files; const newOrder = state.order.filter(fid => fid !== id); return { files: rest, order: newOrder }; }), setUploading: val => set({ uploading: val }), setDeleting: id => set({ deleting: id }), setUploadProgress: p => set({ uploadProgress: p }), reset: () => set(initialState) })); // selectors export const useFiles = () => { const files = useFileStore(s => s.files); const order = useFileStore(s => s.order); // Return stable array when contents unchanged const out = order.map(id => files[id]); return out; }; export const useUploading = () => useFileStore(s => s.uploading); export const useUploadAggregateProgress = () => useFileStore(s => s.uploadProgress); export const useDeleting = () => useFileStore(s => s.deleting); //# sourceMappingURL=fileStore.js.map