mirror of
https://github.com/obsqrbtz/goose-highlighter.git
synced 2026-04-08 20:19:06 +03:00
added move-to dropdown to word items
This commit is contained in:
@@ -185,6 +185,18 @@
|
|||||||
"copy": {
|
"copy": {
|
||||||
"message": "Kopieren"
|
"message": "Kopieren"
|
||||||
},
|
},
|
||||||
|
"move_to_list": {
|
||||||
|
"message": "Zur Liste verschieben"
|
||||||
|
},
|
||||||
|
"copy_to_list": {
|
||||||
|
"message": "In Liste kopieren"
|
||||||
|
},
|
||||||
|
"no_other_lists": {
|
||||||
|
"message": "Keine anderen Listen"
|
||||||
|
},
|
||||||
|
"word_actions": {
|
||||||
|
"message": "In eine andere Liste verschieben oder kopieren"
|
||||||
|
},
|
||||||
"merge_lists_min_two": {
|
"merge_lists_min_two": {
|
||||||
"message": "Wählen Sie mindestens zwei Listen zum Zusammenführen aus."
|
"message": "Wählen Sie mindestens zwei Listen zum Zusammenführen aus."
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -191,6 +191,18 @@
|
|||||||
"copy": {
|
"copy": {
|
||||||
"message": "Copy"
|
"message": "Copy"
|
||||||
},
|
},
|
||||||
|
"move_to_list": {
|
||||||
|
"message": "Move to list"
|
||||||
|
},
|
||||||
|
"copy_to_list": {
|
||||||
|
"message": "Copy to list"
|
||||||
|
},
|
||||||
|
"no_other_lists": {
|
||||||
|
"message": "No other lists"
|
||||||
|
},
|
||||||
|
"word_actions": {
|
||||||
|
"message": "Move or copy to another list"
|
||||||
|
},
|
||||||
"merge_lists_min_two": {
|
"merge_lists_min_two": {
|
||||||
"message": "Select at least two lists to merge."
|
"message": "Select at least two lists to merge."
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -191,6 +191,18 @@
|
|||||||
"copy": {
|
"copy": {
|
||||||
"message": "Copiar"
|
"message": "Copiar"
|
||||||
},
|
},
|
||||||
|
"move_to_list": {
|
||||||
|
"message": "Mover a lista"
|
||||||
|
},
|
||||||
|
"copy_to_list": {
|
||||||
|
"message": "Copiar a lista"
|
||||||
|
},
|
||||||
|
"no_other_lists": {
|
||||||
|
"message": "No hay otras listas"
|
||||||
|
},
|
||||||
|
"word_actions": {
|
||||||
|
"message": "Mover o copiar a otra lista"
|
||||||
|
},
|
||||||
"merge_lists_min_two": {
|
"merge_lists_min_two": {
|
||||||
"message": "Seleccione al menos dos listas para combinar."
|
"message": "Seleccione al menos dos listas para combinar."
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -191,6 +191,18 @@
|
|||||||
"copy": {
|
"copy": {
|
||||||
"message": "Copier"
|
"message": "Copier"
|
||||||
},
|
},
|
||||||
|
"move_to_list": {
|
||||||
|
"message": "Déplacer vers la liste"
|
||||||
|
},
|
||||||
|
"copy_to_list": {
|
||||||
|
"message": "Copier vers la liste"
|
||||||
|
},
|
||||||
|
"no_other_lists": {
|
||||||
|
"message": "Aucune autre liste"
|
||||||
|
},
|
||||||
|
"word_actions": {
|
||||||
|
"message": "Déplacer ou copier vers une autre liste"
|
||||||
|
},
|
||||||
"merge_lists_min_two": {
|
"merge_lists_min_two": {
|
||||||
"message": "Sélectionnez au moins deux listes à fusionner."
|
"message": "Sélectionnez au moins deux listes à fusionner."
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -191,6 +191,18 @@
|
|||||||
"copy": {
|
"copy": {
|
||||||
"message": "कॉपी करें"
|
"message": "कॉपी करें"
|
||||||
},
|
},
|
||||||
|
"move_to_list": {
|
||||||
|
"message": "सूची में ले जाएं"
|
||||||
|
},
|
||||||
|
"copy_to_list": {
|
||||||
|
"message": "सूची में कॉपी करें"
|
||||||
|
},
|
||||||
|
"no_other_lists": {
|
||||||
|
"message": "कोई अन्य सूची नहीं"
|
||||||
|
},
|
||||||
|
"word_actions": {
|
||||||
|
"message": "किसी अन्य सूची में ले जाएं या कॉपी करें"
|
||||||
|
},
|
||||||
"merge_lists_min_two": {
|
"merge_lists_min_two": {
|
||||||
"message": "मर्ज करने के लिए कम से कम दो सूचियाँ चुनें।"
|
"message": "मर्ज करने के लिए कम से कम दो सूचियाँ चुनें।"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -191,6 +191,18 @@
|
|||||||
"copy": {
|
"copy": {
|
||||||
"message": "Copia"
|
"message": "Copia"
|
||||||
},
|
},
|
||||||
|
"move_to_list": {
|
||||||
|
"message": "Sposta in elenco"
|
||||||
|
},
|
||||||
|
"copy_to_list": {
|
||||||
|
"message": "Copia in elenco"
|
||||||
|
},
|
||||||
|
"no_other_lists": {
|
||||||
|
"message": "Nessun altro elenco"
|
||||||
|
},
|
||||||
|
"word_actions": {
|
||||||
|
"message": "Sposta o copia in un altro elenco"
|
||||||
|
},
|
||||||
"merge_lists_min_two": {
|
"merge_lists_min_two": {
|
||||||
"message": "Seleziona almeno due elenchi da unire."
|
"message": "Seleziona almeno due elenchi da unire."
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -191,6 +191,18 @@
|
|||||||
"copy": {
|
"copy": {
|
||||||
"message": "コピー"
|
"message": "コピー"
|
||||||
},
|
},
|
||||||
|
"move_to_list": {
|
||||||
|
"message": "リストに移動"
|
||||||
|
},
|
||||||
|
"copy_to_list": {
|
||||||
|
"message": "リストにコピー"
|
||||||
|
},
|
||||||
|
"no_other_lists": {
|
||||||
|
"message": "他のリストはありません"
|
||||||
|
},
|
||||||
|
"word_actions": {
|
||||||
|
"message": "別のリストに移動またはコピー"
|
||||||
|
},
|
||||||
"merge_lists_min_two": {
|
"merge_lists_min_two": {
|
||||||
"message": "統合するには少なくとも2つのリストを選択してください。"
|
"message": "統合するには少なくとも2つのリストを選択してください。"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -191,6 +191,18 @@
|
|||||||
"copy": {
|
"copy": {
|
||||||
"message": "복사"
|
"message": "복사"
|
||||||
},
|
},
|
||||||
|
"move_to_list": {
|
||||||
|
"message": "목록으로 이동"
|
||||||
|
},
|
||||||
|
"copy_to_list": {
|
||||||
|
"message": "목록에 복사"
|
||||||
|
},
|
||||||
|
"no_other_lists": {
|
||||||
|
"message": "다른 목록 없음"
|
||||||
|
},
|
||||||
|
"word_actions": {
|
||||||
|
"message": "다른 목록으로 이동 또는 복사"
|
||||||
|
},
|
||||||
"merge_lists_min_two": {
|
"merge_lists_min_two": {
|
||||||
"message": "병합하려면 최소 두 개의 리스트를 선택하세요."
|
"message": "병합하려면 최소 두 개의 리스트를 선택하세요."
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -191,6 +191,18 @@
|
|||||||
"copy": {
|
"copy": {
|
||||||
"message": "Kopiëren"
|
"message": "Kopiëren"
|
||||||
},
|
},
|
||||||
|
"move_to_list": {
|
||||||
|
"message": "Verplaats naar lijst"
|
||||||
|
},
|
||||||
|
"copy_to_list": {
|
||||||
|
"message": "Kopieer naar lijst"
|
||||||
|
},
|
||||||
|
"no_other_lists": {
|
||||||
|
"message": "Geen andere lijsten"
|
||||||
|
},
|
||||||
|
"word_actions": {
|
||||||
|
"message": "Verplaats of kopieer naar een andere lijst"
|
||||||
|
},
|
||||||
"merge_lists_min_two": {
|
"merge_lists_min_two": {
|
||||||
"message": "Selecteer minimaal twee lijsten om samen te voegen."
|
"message": "Selecteer minimaal twee lijsten om samen te voegen."
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -191,6 +191,18 @@
|
|||||||
"copy": {
|
"copy": {
|
||||||
"message": "Kopiuj"
|
"message": "Kopiuj"
|
||||||
},
|
},
|
||||||
|
"move_to_list": {
|
||||||
|
"message": "Przenieś do listy"
|
||||||
|
},
|
||||||
|
"copy_to_list": {
|
||||||
|
"message": "Kopiuj do listy"
|
||||||
|
},
|
||||||
|
"no_other_lists": {
|
||||||
|
"message": "Brak innych list"
|
||||||
|
},
|
||||||
|
"word_actions": {
|
||||||
|
"message": "Przenieś lub skopiuj do innej listy"
|
||||||
|
},
|
||||||
"merge_lists_min_two": {
|
"merge_lists_min_two": {
|
||||||
"message": "Wybierz co najmniej dwie listy do scalenia."
|
"message": "Wybierz co najmniej dwie listy do scalenia."
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -191,6 +191,18 @@
|
|||||||
"copy": {
|
"copy": {
|
||||||
"message": "Copiar"
|
"message": "Copiar"
|
||||||
},
|
},
|
||||||
|
"move_to_list": {
|
||||||
|
"message": "Mover para lista"
|
||||||
|
},
|
||||||
|
"copy_to_list": {
|
||||||
|
"message": "Copiar para lista"
|
||||||
|
},
|
||||||
|
"no_other_lists": {
|
||||||
|
"message": "Nenhuma outra lista"
|
||||||
|
},
|
||||||
|
"word_actions": {
|
||||||
|
"message": "Mover ou copiar para outra lista"
|
||||||
|
},
|
||||||
"merge_lists_min_two": {
|
"merge_lists_min_two": {
|
||||||
"message": "Selecione pelo menos duas listas para mesclar."
|
"message": "Selecione pelo menos duas listas para mesclar."
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -191,6 +191,18 @@
|
|||||||
"copy": {
|
"copy": {
|
||||||
"message": "Копировать"
|
"message": "Копировать"
|
||||||
},
|
},
|
||||||
|
"move_to_list": {
|
||||||
|
"message": "Переместить в список"
|
||||||
|
},
|
||||||
|
"copy_to_list": {
|
||||||
|
"message": "Копировать в список"
|
||||||
|
},
|
||||||
|
"no_other_lists": {
|
||||||
|
"message": "Нет других списков"
|
||||||
|
},
|
||||||
|
"word_actions": {
|
||||||
|
"message": "Переместить или скопировать в другой список"
|
||||||
|
},
|
||||||
"merge_lists_min_two": {
|
"merge_lists_min_two": {
|
||||||
"message": "Выберите как минимум два списка для объединения."
|
"message": "Выберите как минимум два списка для объединения."
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -191,6 +191,18 @@
|
|||||||
"copy": {
|
"copy": {
|
||||||
"message": "Kopyala"
|
"message": "Kopyala"
|
||||||
},
|
},
|
||||||
|
"move_to_list": {
|
||||||
|
"message": "Listeye taşı"
|
||||||
|
},
|
||||||
|
"copy_to_list": {
|
||||||
|
"message": "Listeye kopyala"
|
||||||
|
},
|
||||||
|
"no_other_lists": {
|
||||||
|
"message": "Başka liste yok"
|
||||||
|
},
|
||||||
|
"word_actions": {
|
||||||
|
"message": "Başka bir listeye taşı veya kopyala"
|
||||||
|
},
|
||||||
"merge_lists_min_two": {
|
"merge_lists_min_two": {
|
||||||
"message": "Birleştirmek için en az iki liste seçin."
|
"message": "Birleştirmek için en az iki liste seçin."
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -191,6 +191,18 @@
|
|||||||
"copy": {
|
"copy": {
|
||||||
"message": "复制"
|
"message": "复制"
|
||||||
},
|
},
|
||||||
|
"move_to_list": {
|
||||||
|
"message": "移动到列表"
|
||||||
|
},
|
||||||
|
"copy_to_list": {
|
||||||
|
"message": "复制到列表"
|
||||||
|
},
|
||||||
|
"no_other_lists": {
|
||||||
|
"message": "没有其他列表"
|
||||||
|
},
|
||||||
|
"word_actions": {
|
||||||
|
"message": "移动或复制到另一个列表"
|
||||||
|
},
|
||||||
"merge_lists_min_two": {
|
"merge_lists_min_two": {
|
||||||
"message": "选择至少两个列表进行合并。"
|
"message": "选择至少两个列表进行合并。"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -645,6 +645,60 @@ body {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Word item 3-dot menu dropdown */
|
||||||
|
.word-item-menu-dropdown {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
min-width: 160px;
|
||||||
|
background: var(--input-bg);
|
||||||
|
border: 1px solid var(--input-border);
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.15);
|
||||||
|
z-index: 200;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.word-item-menu-dropdown.open {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.word-item-menu-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--text-color);
|
||||||
|
cursor: pointer;
|
||||||
|
text-align: left;
|
||||||
|
transition: background 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.word-item-menu-item:hover:not(.disabled) {
|
||||||
|
background: var(--section-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.word-item-menu-item.disabled {
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.word-item-menu-item i {
|
||||||
|
font-size: 12px;
|
||||||
|
opacity: 0.8;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.word-item-menu-item .list-color-indicator {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 50%;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Empty State */
|
/* Empty State */
|
||||||
.empty-state {
|
.empty-state {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|||||||
@@ -196,6 +196,9 @@
|
|||||||
<!-- Word List -->
|
<!-- Word List -->
|
||||||
<div id="wordList" class="word-list-container"></div>
|
<div id="wordList" class="word-list-container"></div>
|
||||||
|
|
||||||
|
<!-- Word item 3-dot menu dropdown (positioned by JS) -->
|
||||||
|
<div id="wordItemMenuDropdown" class="word-item-menu-dropdown" role="menu" aria-hidden="true"></div>
|
||||||
|
|
||||||
<!-- Help text -->
|
<!-- Help text -->
|
||||||
<p class="word-list-hint" data-i18n="multi_select_hint">Click to select • Ctrl/Cmd+Click for multi-select</p>
|
<p class="word-list-hint" data-i18n="multi_select_hint">Click to select • Ctrl/Cmd+Click for multi-select</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ export class PopupController {
|
|||||||
private activeTab = 'lists';
|
private activeTab = 'lists';
|
||||||
private pageHighlights: Array<{ word: string; count: number; background: string; foreground: string }> = [];
|
private pageHighlights: Array<{ word: string; count: number; background: string; foreground: string }> = [];
|
||||||
private highlightIndices = new Map<string, number>();
|
private highlightIndices = new Map<string, number>();
|
||||||
|
private wordMenuOpenForIndex: number | null = null;
|
||||||
|
private wordMenuCopyOnly = false;
|
||||||
|
private wordMenuCloseListener: (() => void) | null = null;
|
||||||
|
|
||||||
async initialize(): Promise<void> {
|
async initialize(): Promise<void> {
|
||||||
await this.loadData();
|
await this.loadData();
|
||||||
@@ -278,6 +281,17 @@ export class PopupController {
|
|||||||
const list = this.lists[this.currentListIndex];
|
const list = this.lists[this.currentListIndex];
|
||||||
if (!list) return;
|
if (!list) return;
|
||||||
|
|
||||||
|
// Handle 3-dot menu button click
|
||||||
|
const menuBtn = target.closest('.word-item-menu-btn') as HTMLElement | null;
|
||||||
|
if (menuBtn) {
|
||||||
|
e.stopPropagation();
|
||||||
|
const index = Number(menuBtn.dataset.index);
|
||||||
|
if (!Number.isNaN(index)) {
|
||||||
|
this.openWordItemMenu(index, menuBtn);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle edit button click
|
// Handle edit button click
|
||||||
const editBtn = target.closest('.word-item-icon-btn.edit-word-btn') as HTMLElement | null;
|
const editBtn = target.closest('.word-item-icon-btn.edit-word-btn') as HTMLElement | null;
|
||||||
if (editBtn) {
|
if (editBtn) {
|
||||||
@@ -428,6 +442,155 @@ export class PopupController {
|
|||||||
input.select();
|
input.select();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private openWordItemMenu(wordIndex: number, buttonEl: HTMLElement): void {
|
||||||
|
const dropdown = document.getElementById('wordItemMenuDropdown');
|
||||||
|
if (!dropdown) return;
|
||||||
|
|
||||||
|
this.closeWordItemMenu();
|
||||||
|
|
||||||
|
const rect = buttonEl.getBoundingClientRect();
|
||||||
|
const padding = 8;
|
||||||
|
dropdown.style.left = `${rect.left}px`;
|
||||||
|
dropdown.style.top = `${rect.bottom + 4}px`;
|
||||||
|
dropdown.style.right = '';
|
||||||
|
|
||||||
|
const moveLabel = chrome.i18n.getMessage('move_to_list') || 'Move to list';
|
||||||
|
const copyLabel = chrome.i18n.getMessage('copy_to_list') || 'Copy to list';
|
||||||
|
|
||||||
|
dropdown.innerHTML = `
|
||||||
|
<button type="button" class="word-item-menu-item" data-action="move">
|
||||||
|
<i class="fa-solid fa-arrow-right"></i>
|
||||||
|
<span>${DOMUtils.escapeHtml(moveLabel)}</span>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="word-item-menu-item" data-action="copy">
|
||||||
|
<i class="fa-solid fa-copy"></i>
|
||||||
|
<span>${DOMUtils.escapeHtml(copyLabel)}</span>
|
||||||
|
</button>
|
||||||
|
`;
|
||||||
|
|
||||||
|
dropdown.querySelectorAll('.word-item-menu-item').forEach(item => {
|
||||||
|
item.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
const action = (item as HTMLElement).dataset.action;
|
||||||
|
if (action === 'move') {
|
||||||
|
this.showWordMenuListPicker(wordIndex, false);
|
||||||
|
} else if (action === 'copy') {
|
||||||
|
this.showWordMenuListPicker(wordIndex, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.wordMenuOpenForIndex = wordIndex;
|
||||||
|
dropdown.classList.add('open');
|
||||||
|
dropdown.setAttribute('aria-hidden', 'false');
|
||||||
|
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
const dr = dropdown.getBoundingClientRect();
|
||||||
|
const vw = window.innerWidth;
|
||||||
|
const vh = window.innerHeight;
|
||||||
|
if (dr.right > vw - padding) {
|
||||||
|
dropdown.style.left = `${vw - dr.width - padding}px`;
|
||||||
|
}
|
||||||
|
if (dr.left < padding) {
|
||||||
|
dropdown.style.left = `${padding}px`;
|
||||||
|
}
|
||||||
|
if (dr.bottom > vh - padding) {
|
||||||
|
dropdown.style.top = `${vh - dr.height - padding}px`;
|
||||||
|
}
|
||||||
|
if (dr.top < padding) {
|
||||||
|
dropdown.style.top = `${padding}px`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const closeHandler = (e: MouseEvent) => {
|
||||||
|
const target = e.target as Node;
|
||||||
|
if (dropdown.contains(target) || buttonEl.contains(target)) return;
|
||||||
|
this.closeWordItemMenu();
|
||||||
|
document.removeEventListener('click', closeHandler);
|
||||||
|
this.wordMenuCloseListener = null;
|
||||||
|
};
|
||||||
|
this.wordMenuCloseListener = () => {
|
||||||
|
document.removeEventListener('click', closeHandler);
|
||||||
|
this.wordMenuCloseListener = null;
|
||||||
|
};
|
||||||
|
setTimeout(() => document.addEventListener('click', closeHandler), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private showWordMenuListPicker(wordIndex: number, copyOnly: boolean): void {
|
||||||
|
const dropdown = document.getElementById('wordItemMenuDropdown');
|
||||||
|
if (!dropdown || this.wordMenuOpenForIndex === null) return;
|
||||||
|
|
||||||
|
this.wordMenuCopyOnly = copyOnly;
|
||||||
|
const currentList = this.lists[this.currentListIndex];
|
||||||
|
const otherLists = this.lists
|
||||||
|
.map((list, index) => ({ list, index }))
|
||||||
|
.filter(({ index }) => index !== this.currentListIndex);
|
||||||
|
|
||||||
|
if (otherLists.length === 0) {
|
||||||
|
const noOtherLabel = chrome.i18n.getMessage('no_other_lists') || 'No other lists';
|
||||||
|
dropdown.innerHTML = `
|
||||||
|
<div class="word-item-menu-item disabled">
|
||||||
|
<span>${DOMUtils.escapeHtml(noOtherLabel)}</span>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dropdown.innerHTML = otherLists.map(({ list, index }) => `
|
||||||
|
<button type="button" class="word-item-menu-item" data-target-index="${index}">
|
||||||
|
<span class="list-color-indicator" style="background-color: ${DOMUtils.escapeHtml(list.background)}"></span>
|
||||||
|
<span>${DOMUtils.escapeHtml(list.name)}</span>
|
||||||
|
</button>
|
||||||
|
`).join('');
|
||||||
|
|
||||||
|
dropdown.querySelectorAll('.word-item-menu-item[data-target-index]').forEach(item => {
|
||||||
|
item.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
const targetIndex = Number((item as HTMLElement).dataset.targetIndex);
|
||||||
|
if (Number.isNaN(targetIndex)) return;
|
||||||
|
if (this.wordMenuCopyOnly) {
|
||||||
|
this.copyWordToOtherList(wordIndex, targetIndex);
|
||||||
|
} else {
|
||||||
|
this.moveWordToOtherList(wordIndex, targetIndex);
|
||||||
|
}
|
||||||
|
this.closeWordItemMenu();
|
||||||
|
this.save();
|
||||||
|
this.renderWords();
|
||||||
|
this.renderLists();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private closeWordItemMenu(): void {
|
||||||
|
const dropdown = document.getElementById('wordItemMenuDropdown');
|
||||||
|
if (dropdown) {
|
||||||
|
dropdown.classList.remove('open');
|
||||||
|
dropdown.setAttribute('aria-hidden', 'true');
|
||||||
|
dropdown.innerHTML = '';
|
||||||
|
}
|
||||||
|
this.wordMenuOpenForIndex = null;
|
||||||
|
if (this.wordMenuCloseListener) {
|
||||||
|
this.wordMenuCloseListener();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private moveWordToOtherList(wordIndex: number, targetListIndex: number): void {
|
||||||
|
const list = this.lists[this.currentListIndex];
|
||||||
|
const targetList = this.lists[targetListIndex];
|
||||||
|
const word = list.words[wordIndex];
|
||||||
|
if (!word || !targetList) return;
|
||||||
|
targetList.words.push({ ...word });
|
||||||
|
list.words.splice(wordIndex, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private copyWordToOtherList(wordIndex: number, targetListIndex: number): void {
|
||||||
|
const list = this.lists[this.currentListIndex];
|
||||||
|
const targetList = this.lists[targetListIndex];
|
||||||
|
const word = list.words[wordIndex];
|
||||||
|
if (!word || !targetList) return;
|
||||||
|
targetList.words.push({ ...word });
|
||||||
|
}
|
||||||
|
|
||||||
private setupWordSelection(): void {
|
private setupWordSelection(): void {
|
||||||
document.getElementById('selectAllBtn')?.addEventListener('click', () => {
|
document.getElementById('selectAllBtn')?.addEventListener('click', () => {
|
||||||
const list = this.lists[this.currentListIndex];
|
const list = this.lists[this.currentListIndex];
|
||||||
@@ -890,6 +1053,7 @@ export class PopupController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private renderWords(): void {
|
private renderWords(): void {
|
||||||
|
this.closeWordItemMenu();
|
||||||
const list = this.lists[this.currentListIndex];
|
const list = this.lists[this.currentListIndex];
|
||||||
const wordList = document.getElementById('wordList') as HTMLDivElement;
|
const wordList = document.getElementById('wordList') as HTMLDivElement;
|
||||||
|
|
||||||
@@ -922,6 +1086,7 @@ export class PopupController {
|
|||||||
const list = this.lists[this.currentListIndex];
|
const list = this.lists[this.currentListIndex];
|
||||||
const bgColor = word.background || list.background;
|
const bgColor = word.background || list.background;
|
||||||
const fgColor = word.foreground || list.foreground;
|
const fgColor = word.foreground || list.foreground;
|
||||||
|
const menuTitle = chrome.i18n.getMessage('word_actions') || 'Actions';
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="word-item ${isSelected ? 'selected' : ''}" data-index="${realIndex}">
|
<div class="word-item ${isSelected ? 'selected' : ''}" data-index="${realIndex}">
|
||||||
@@ -940,6 +1105,9 @@ export class PopupController {
|
|||||||
<i class="fa-solid fa-eye-slash eye-disabled"></i>
|
<i class="fa-solid fa-eye-slash eye-disabled"></i>
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
|
<button type="button" class="word-item-icon-btn word-item-menu-btn" data-index="${realIndex}" title="${DOMUtils.escapeHtml(menuTitle)}" aria-label="${DOMUtils.escapeHtml(menuTitle)}">
|
||||||
|
<i class="fa-solid fa-ellipsis-v"></i>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|||||||
Reference in New Issue
Block a user