File size: 5,503 Bytes
d988ae4 3bbb98d d988ae4 3bbb98d d988ae4 3bbb98d d988ae4 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | 'use client';
import { useState, useEffect } from 'react';
import { apiUrl } from '../constants';
import { appendTokenToUrl, withAdminTokenHeader } from '../adminAuth';
interface SavedClipboard {
roomCode: string;
lastVisited: string; // ISO date string
name?: string; // Optional custom name
isExpired?: boolean; // Whether the clipboard has expired
isPasswordProtected?: boolean; // Whether the clipboard is password protected
lastChecked?: string; // When the clipboard status was last checked
}
export function useSavedClipboards() {
const [savedClipboards, setSavedClipboards] = useState<SavedClipboard[]>([]);
const [isLoaded, setIsLoaded] = useState(false);
const [isCheckingStatus, setIsCheckingStatus] = useState(false);
// Load saved clipboards from localStorage
useEffect(() => {
const loadSavedClipboards = () => {
try {
const saved = localStorage.getItem('savedClipboards');
if (saved) {
setSavedClipboards(JSON.parse(saved));
}
} catch (error) {
console.error('Failed to load saved clipboards:', error);
} finally {
setIsLoaded(true);
}
};
loadSavedClipboards();
}, []);
// Save clipboards to localStorage whenever they change
useEffect(() => {
if (isLoaded) {
localStorage.setItem('savedClipboards', JSON.stringify(savedClipboards));
}
}, [savedClipboards, isLoaded]);
// Check clipboard status (expired and password-protected)
useEffect(() => {
const checkClipboardStatus = async () => {
if (!isLoaded || savedClipboards.length === 0 || isCheckingStatus) {
return;
}
setIsCheckingStatus(true);
const now = new Date();
const ONE_HOUR = 60 * 60 * 1000; // 1 hour in milliseconds
// Create a copy of the clipboards array to update
const updatedClipboards = [...savedClipboards];
let hasChanges = false;
// Check each clipboard that hasn't been checked in the last hour
for (let i = 0; i < updatedClipboards.length; i++) {
const clipboard = updatedClipboards[i];
const lastChecked = clipboard.lastChecked ? new Date(clipboard.lastChecked) : null;
// Skip if checked within the last hour
if (lastChecked && (now.getTime() - lastChecked.getTime() < ONE_HOUR)) {
continue;
}
try {
const response = await fetch(
appendTokenToUrl(`${apiUrl}/clipboard/${clipboard.roomCode}/exists`),
{
headers: withAdminTokenHeader(),
},
);
if (response.ok) {
const data = await response.json();
// Update clipboard status
if (clipboard.isExpired !== !data.exists || clipboard.isPasswordProtected !== data.hasPassword) {
updatedClipboards[i] = {
...clipboard,
isExpired: !data.exists,
isPasswordProtected: data.hasPassword,
lastChecked: now.toISOString()
};
hasChanges = true;
} else if (!clipboard.lastChecked) {
// Just update the lastChecked timestamp if nothing else changed
updatedClipboards[i] = {
...clipboard,
lastChecked: now.toISOString()
};
hasChanges = true;
}
}
} catch (error) {
console.error(`Failed to check status for clipboard ${clipboard.roomCode}:`, error);
// If we can't reach the server, don't mark as expired
}
}
if (hasChanges) {
setSavedClipboards(updatedClipboards);
}
setIsCheckingStatus(false);
};
checkClipboardStatus();
}, [isLoaded, savedClipboards]);
// Add a clipboard to saved list
const addClipboard = (roomCode: string, name?: string) => {
setSavedClipboards(prev => {
// Check if the clipboard already exists
const existingIndex = prev.findIndex(item => item.roomCode === roomCode);
// Create a new array to avoid mutation
const newSavedClipboards = [...prev];
const now = new Date().toISOString();
if (existingIndex >= 0) {
// Update existing clipboard with new timestamp
newSavedClipboards[existingIndex] = {
...newSavedClipboards[existingIndex],
lastVisited: now,
name: name || newSavedClipboards[existingIndex].name
};
} else {
// Add new clipboard
newSavedClipboards.unshift({
roomCode,
lastVisited: now,
name
});
}
// Limit to 10 recent clipboards
return newSavedClipboards.slice(0, 10);
});
};
// Remove a clipboard from saved list
const removeClipboard = (roomCode: string) => {
setSavedClipboards(prev =>
prev.filter(item => item.roomCode !== roomCode)
);
};
// Clear all saved clipboards
const clearClipboards = () => {
setSavedClipboards([]);
};
// Rename a saved clipboard
const renameClipboard = (roomCode: string, newName: string) => {
setSavedClipboards(prev =>
prev.map(item =>
item.roomCode === roomCode
? { ...item, name: newName || undefined }
: item
)
);
};
return {
savedClipboards,
addClipboard,
removeClipboard,
clearClipboards,
renameClipboard,
isLoaded,
isCheckingStatus
};
}
|