/** * history.js - プロンプト生成履歴の管理 * * 主な機能: * - 履歴の保存と読み込み * - 履歴の検索 * - 履歴項目の編集と削除 * - ストレージ使用量の表示 * * 重要な関数: * - saveToHistory(): 新しい履歴項目を保存 * - updateHistoryList(): 履歴リストを更新 * - filterHistory(): 履歴の検索機能 * - loadHistoryItem(): 履歴項目を読み込み * * 注意事項: * - 履歴の最大サイズは3MB * - 容量超過時は古い履歴から自動削除 */ function saveToHistory(title) { if(!title) { title = document.getElementById('query').value.slice(0, 10); } const historyItem = { query: document.getElementById('query').value, promptEn: document.getElementById('promptEn').value, promptMyLanguage: document.getElementById('promptMyLanguage').value, danbooruTags: document.getElementById('danbooruTags').value, timestamp: new Date().toISOString(), title: title }; let history = JSON.parse(localStorage.getItem('gemini_prompt_history') || '[]'); history.unshift(historyItem); // 履歴の合計サイズが3MB以下になるまで古い項目を削除 while (JSON.stringify(history).length > 3 * 1024 * 1024) { history.pop(); } localStorage.setItem('gemini_prompt_history', JSON.stringify(history)); updateHistoryList(); } function updateHistoryList() { const historyList = document.getElementById('historyList'); const noHistoryMessage = document.getElementById('noHistoryMessage'); historyList.innerHTML = ''; const history = JSON.parse(localStorage.getItem('gemini_prompt_history') || '[]'); if (history.length === 0) { noHistoryMessage.classList.remove('d-none'); historyList.classList.add('d-none'); } else { noHistoryMessage.classList.add('d-none'); historyList.classList.remove('d-none'); // 容量プログレスバーを追加 const storageUsage = JSON.stringify(history).length; const storageLimit = 3 * 1024 * 1024; // 3MB const usagePercentage = (storageUsage / storageLimit) * 100; const progressBarContainer = document.createElement('div'); progressBarContainer.className = 'mb-3'; progressBarContainer.innerHTML = `
${(storageUsage / 1024 / 1024).toFixed(2)}MB / ${storageLimit / 1024 / 1024}MB
`; historyList.appendChild(progressBarContainer); // 検索フォームを追加 const searchForm = document.createElement('div'); searchForm.className = 'mb-3'; searchForm.innerHTML = ` `; historyList.appendChild(searchForm); history.forEach((item, index) => { const li = document.createElement('li'); li.className = 'list-group-item list-group-item-action d-flex justify-content-between align-items-start'; li.dataset.item = JSON.stringify(item); const contentDiv = document.createElement('div'); contentDiv.className = 'ms-2 me-auto'; contentDiv.style.cursor = 'pointer'; contentDiv.onclick = () => loadHistoryItem(index); const titleDiv = document.createElement('div'); titleDiv.className = 'fw-bold text-truncate'; titleDiv.textContent = item.title || item.query.slice(0, 10); const dateDiv = document.createElement('div'); dateDiv.className = 'small text-muted'; dateDiv.textContent = new Date(item.timestamp).toLocaleString(); contentDiv.appendChild(titleDiv); contentDiv.appendChild(dateDiv); const buttonsContainer = document.createElement('div'); buttonsContainer.className = 'd-flex'; const editButton = document.createElement('button'); editButton.className = 'btn btn-secondary btn-sm me-2'; editButton.innerHTML = ''; editButton.onclick = (e) => { e.stopPropagation(); editHistoryItemTitle(index, titleDiv); }; const deleteButton = document.createElement('button'); deleteButton.className = 'btn btn-danger btn-sm'; deleteButton.innerHTML = ''; deleteButton.onclick = (e) => { e.stopPropagation(); deleteHistoryItem(index); }; buttonsContainer.appendChild(editButton); buttonsContainer.appendChild(deleteButton); li.appendChild(contentDiv); li.appendChild(buttonsContainer); historyList.appendChild(li); contentDiv.style.width = `calc(100% - ${buttonsContainer.offsetWidth}px)`; }); // 検索機能を追加 const searchInput = document.getElementById('historySearchInput'); searchInput.addEventListener('input', filterHistory); } } function deleteHistoryItem(index) { if (confirm('Are you sure you want to delete this history item?')) { let history = JSON.parse(localStorage.getItem('gemini_prompt_history') || '[]'); history.splice(index, 1); localStorage.setItem('gemini_prompt_history', JSON.stringify(history)); updateHistoryList(); } } function loadHistoryItem(index) { const history = JSON.parse(localStorage.getItem('gemini_prompt_history') || '[]'); const item = history[index]; document.getElementById('query').value = item.query; document.getElementById('promptEn').value = item.promptEn; document.getElementById('promptMyLanguage').value = item.promptMyLanguage; document.getElementById('danbooruTags').value = item.danbooruTags; saveToUserStorage(true); } function clearHistory() { if (confirm('Are you sure you want to delete all history items?')) { localStorage.removeItem('gemini_prompt_history'); updateHistoryList(); } } function createHistoryItem(item, index) { const li = document.createElement('li'); li.className = 'list-group-item d-flex justify-content-between align-items-center'; const titleSpan = document.createElement('span'); titleSpan.textContent = item.title || item.query.slice(0, 10); titleSpan.className = 'me-2'; li.appendChild(titleSpan); const buttonsContainer = document.createElement('div'); const editButton = document.createElement('button'); editButton.className = 'btn btn-sm btn-secondary me-2'; editButton.innerHTML = ''; editButton.onclick = () => editHistoryItemTitle(index, titleSpan); const useButton = document.createElement('button'); useButton.className = 'btn btn-sm btn-primary me-2'; useButton.innerHTML = ''; useButton.onclick = () => useHistoryItem(index); const deleteButton = document.createElement('button'); deleteButton.className = 'btn btn-sm btn-danger'; deleteButton.innerHTML = ''; deleteButton.onclick = () => { if (confirm('Are you sure you want to delete this history item?')) { deleteHistoryItem(index); } }; buttonsContainer.appendChild(editButton); buttonsContainer.appendChild(useButton); buttonsContainer.appendChild(deleteButton); li.appendChild(buttonsContainer); return li; } function editHistoryItemTitle(index, titleDiv) { const history = JSON.parse(localStorage.getItem('gemini_prompt_history') || '[]'); const item = history[index]; const currentTitle = item.title || item.query.slice(0, 10); const newTitle = prompt('New title:', currentTitle); if (newTitle !== null && newTitle.trim() !== '') { item.title = newTitle.trim(); history[index] = item; localStorage.setItem('gemini_prompt_history', JSON.stringify(history)); titleDiv.textContent = newTitle.trim(); } } function filterHistory() { const searchInput = document.getElementById('historySearchInput'); const searchTerm = searchInput.value.toLowerCase(); const historyItems = document.querySelectorAll('#historyList li[data-item]'); historyItems.forEach(item => { const itemData = JSON.parse(item.dataset.item); const searchableText = `${itemData.title} ${itemData.query} ${itemData.promptEn} ${itemData.promptMyLanguage} ${itemData.danbooruTags}`.toLowerCase(); if (searchableText.includes(searchTerm)) { item.classList.remove('d-none'); } else { item.classList.add('d-none'); } }); }