Skip to content

Commit 5706852

Browse files
wip
1 parent 42adc36 commit 5706852

File tree

2 files changed

+89
-40
lines changed

2 files changed

+89
-40
lines changed

ext/css/settings.css

-3
Original file line numberDiff line numberDiff line change
@@ -2312,9 +2312,6 @@ button.hotkey-list-item-enabled-button[data-scope-count='0'] {
23122312
--dictionary-item-index-margin: 0.5em;
23132313
--dictionary-item-index-width: 1.2em;
23142314
}
2315-
.dictionary-item.dragging {
2316-
opacity: 0.5;
2317-
}
23182315
.dictionary-list-index {
23192316
margin-right: var(--dictionary-item-index-margin);
23202317
}

ext/js/pages/settings/dictionary-controller.js

+89-37
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,15 @@ class DictionaryEntry {
9999
return this._dictionaryInfo;
100100
}
101101

102+
/** @type {number} */
103+
get index() {
104+
return this._index;
105+
}
106+
107+
set index(value) {
108+
this._index = value;
109+
}
110+
102111
/** */
103112
prepare() {
104113
//
@@ -236,12 +245,12 @@ class DictionaryEntry {
236245

237246
/** */
238247
_onDragStart() {
239-
this._dictionaryItem.classList.add('dragging');
248+
this._dictionaryItem.dispatchEvent(new CustomEvent('entryDragStart', {detail: {index: this._index}}));
240249
}
241250

242251
/** */
243252
_onDragEnd() {
244-
this._dictionaryItem.classList.remove('dragging');
253+
this._dictionaryItem.dispatchEvent(new CustomEvent('entryDragEnd', {detail: {index: this._index}}));
245254
}
246255

247256
/** */
@@ -532,7 +541,9 @@ export class DictionaryController {
532541
/** @type {boolean} */
533542
this._isDeleting = false;
534543
/** @type {number|null} */
535-
this._dragging = null;
544+
this._draggingIndex = null;
545+
/** @type {EventListenerCollection} */
546+
this._eventListeners = new EventListenerCollection();
536547
}
537548

538549
/** @type {import('./modal-controller.js').ModalController} */
@@ -566,23 +577,23 @@ export class DictionaryController {
566577

567578
this._settingsController.application.on('databaseUpdated', this._onDatabaseUpdated.bind(this));
568579
this._settingsController.on('optionsChanged', this._onOptionsChanged.bind(this));
569-
this._allCheckbox.addEventListener('change', this._onAllCheckboxChange.bind(this), false);
570-
dictionaryDeleteButton.addEventListener('click', this._onDictionaryConfirmDelete.bind(this), false);
571-
dictionaryUpdateButton.addEventListener('click', this._onDictionaryConfirmUpdate.bind(this), false);
580+
this._eventListeners.addEventListener(this._allCheckbox, 'change', this._onAllCheckboxChange.bind(this), false);
581+
this._eventListeners.addEventListener(dictionaryDeleteButton, 'click', this._onDictionaryConfirmDelete.bind(this), false);
582+
this._eventListeners.addEventListener(dictionaryUpdateButton, 'click', this._onDictionaryConfirmUpdate.bind(this), false);
572583

573-
dictionaryMoveButton.addEventListener('click', this._onDictionaryMoveButtonClick.bind(this), false);
584+
this._eventListeners.addEventListener(dictionaryMoveButton, 'click', this._onDictionaryMoveButtonClick.bind(this), false);
574585

575-
dictionarySetAliasButton.addEventListener('click', this._onDictionarySetAliasButtonClick.bind(this), false);
576-
dictionaryResetAliasButton.addEventListener('click', this._onDictionaryResetAliasButtonClick.bind(this), false);
577586

578-
const onDragOverThrottled = throttle(this._onDragOver.bind(this), 100, this);
579-
this._dictionaryEntryContainer.addEventListener('dragover', onDragOverThrottled.bind(this), false);
587+
this._eventListeners.addEventListener(dictionarySetAliasButton, 'click', this._onDictionarySetAliasButtonClick.bind(this), false);
588+
this._eventListeners.addEventListener(dictionaryResetAliasButton, 'click', this._onDictionaryResetAliasButtonClick.bind(this), false);
580589

590+
const onDragOverThrottled = throttle(this._onDragOver.bind(this), 1, this);
591+
this._eventListeners.addEventListener(this._dictionaryEntryContainer, 'dragover', onDragOverThrottled, false);
581592
if (this._checkUpdatesButton !== null) {
582-
this._checkUpdatesButton.addEventListener('click', this._onCheckUpdatesButtonClick.bind(this), false);
593+
this._eventListeners.addEventListener(this._checkUpdatesButton, 'click', this._onCheckUpdatesButtonClick.bind(this), false);
583594
}
584595
if (this._checkIntegrityButton !== null) {
585-
this._checkIntegrityButton.addEventListener('click', this._onCheckIntegrityButtonClick.bind(this), false);
596+
this._eventListeners.addEventListener(this._checkIntegrityButton, 'click', this._onCheckIntegrityButtonClick.bind(this), false);
586597
}
587598

588599
this._updateDictionaryEntryCount();
@@ -646,18 +657,20 @@ export class DictionaryController {
646657
const event = {source: this};
647658
this._settingsController.trigger('dictionarySettingsReordered', event);
648659

649-
const movedEntry = this._dictionaryEntries.splice(currentIndex, 1)[0];
660+
const nextNeighborIndex = targetIndex + 1;
661+
662+
/** @type {(fragment: DocumentFragment) => void} */
663+
const insertFunction = (nextNeighborIndex < this._dictionaryEntries.length) ?
664+
(fragment) => this._dictionaryEntryContainer.insertBefore(fragment, this._dictionaryEntries[nextNeighborIndex].dictionaryItem) :
665+
(fragment) => this._dictionaryEntryContainer.appendChild(fragment);
666+
667+
const removedEntry = this._removeDictionaryEntry(currentIndex);
668+
const {entry: movedEntry, fragment} = this._createDictionaryEntry(targetIndex, removedEntry.dictionaryInfo);
650669
this._dictionaryEntries.splice(targetIndex, 0, movedEntry);
670+
insertFunction(fragment);
651671

652-
const nextNeighborIndex = targetIndex + 1;
653-
if (nextNeighborIndex < this._dictionaryEntries.length) {
654-
this._dictionaryEntryContainer.removeChild(movedEntry.dictionaryItem);
655-
const fragment = this._createDictionaryEntry(targetIndex, movedEntry.dictionaryInfo);
656-
this._dictionaryEntryContainer.insertBefore(fragment, this._dictionaryEntries[nextNeighborIndex].dictionaryItem);
657-
} else {
658-
this._dictionaryEntryContainer.removeChild(movedEntry.dictionaryItem);
659-
const fragment = this._createDictionaryEntry(targetIndex, movedEntry.dictionaryInfo);
660-
this._dictionaryEntryContainer.appendChild(fragment);
672+
for (const [i, entry] of this._dictionaryEntries.entries()) {
673+
entry.index = i;
661674
}
662675
}
663676

@@ -831,7 +844,8 @@ export class DictionaryController {
831844
const {name} = dictionaryOptionsArray[i];
832845
const dictionaryInfo = dictionaryInfoMap.get(name);
833846
if (typeof dictionaryInfo === 'undefined') { continue; }
834-
const fragment = this._createDictionaryEntry(i, dictionaryInfo);
847+
const {entry, fragment} = this._createDictionaryEntry(i, dictionaryInfo);
848+
this._dictionaryEntries.push(entry);
835849
this._appendDictionaryEntryFragment(fragment);
836850
}
837851
}
@@ -948,27 +962,36 @@ export class DictionaryController {
948962

949963
/**
950964
* @param {DragEvent} e
965+
* @throws {Error}
951966
*/
952967
_onDragOver(e) {
953-
// get dragged item from event
954-
console.log('dragover', e);
955-
const draggingIndex = this._dictionaryEntries.findIndex((entry) => entry.dictionaryItem.classList.contains('dragging'));
956-
if (draggingIndex === -1) { return; }
957-
let nextDictionaryIndex = this._getDragOverDictionaryItem(draggingIndex, e.clientY);
968+
const draggingIndex = this._draggingIndex;
969+
const cursorY = e.clientY;
970+
if (draggingIndex === null) { throw new Error('No dragging index'); }
971+
972+
const nextDictionaryIndex = this._getDragOverDictionaryItem(draggingIndex, cursorY);
958973
if (nextDictionaryIndex === draggingIndex) { return; }
959-
if (nextDictionaryIndex === null) {
960-
nextDictionaryIndex = this._dictionaryEntries.length - 1;
961-
}
962974
void this.moveDictionaryOptions(draggingIndex, nextDictionaryIndex);
975+
this._draggingIndex = nextDictionaryIndex;
976+
977+
const containerRect = this._dictionaryEntryContainer.getBoundingClientRect();
978+
const topZone = [containerRect.top - 30, containerRect.top + 60];
979+
const bottomZone = [containerRect.bottom - 60, containerRect.bottom + 30];
980+
981+
if (cursorY > topZone[0] && cursorY < topZone[1]) {
982+
this._dictionaryEntryContainer.scrollBy(0, -5); // Scroll up
983+
} else if (cursorY > bottomZone[0] && cursorY < bottomZone[1]) {
984+
this._dictionaryEntryContainer.scrollBy(0, 5); // Scroll down
985+
}
963986
}
964987

965988
/**
966989
* @param {number} draggingIndex
967990
* @param {number} y
968-
* @returns {number|null}
991+
* @returns {number}
969992
*/
970993
_getDragOverDictionaryItem(draggingIndex, y) {
971-
const neighbors = [draggingIndex - 1, draggingIndex + 1]
994+
const neighbors = [draggingIndex - 1, draggingIndex, draggingIndex + 1]
972995
.filter((index) => index >= 0 && index < this._dictionaryEntries.length);
973996

974997
/** @type {{index: number|null, offset: number}} */
@@ -982,6 +1005,11 @@ export class DictionaryController {
9821005
currentBest.offset = offset;
9831006
}
9841007
}
1008+
1009+
if (currentBest.index === null) {
1010+
return this._dictionaryEntries.length - 1;
1011+
}
1012+
9851013
return currentBest.index;
9861014
}
9871015

@@ -1114,16 +1142,26 @@ export class DictionaryController {
11141142
/**
11151143
* @param {number} index
11161144
* @param {import('dictionary-importer').Summary} dictionaryInfo
1117-
* @returns {DocumentFragment}
1145+
* @returns {{entry: DictionaryEntry, fragment: DocumentFragment}}
11181146
*/
11191147
_createDictionaryEntry(index, dictionaryInfo) {
11201148
const fragment = this.instantiateTemplateFragment('dictionary');
11211149

11221150
const entry = new DictionaryEntry(this, fragment, index, dictionaryInfo);
1123-
this._dictionaryEntries.push(entry);
11241151
entry.prepare();
1152+
this._eventListeners.addEventListener(entry.dictionaryItem, 'entryDragStart', this._onEntryDragStart.bind(this), false);
1153+
this._eventListeners.addEventListener(entry.dictionaryItem, 'entryDragEnd', this._onEntryDragEnd.bind(this), false);
1154+
return {entry, fragment};
1155+
}
11251156

1126-
return fragment;
1157+
/**
1158+
* @param {number} index
1159+
* @returns {DictionaryEntry}
1160+
*/
1161+
_removeDictionaryEntry(index) {
1162+
const entry = this._dictionaryEntries.splice(index, 1)[0];
1163+
entry.cleanup();
1164+
return entry;
11271165
}
11281166

11291167
/**
@@ -1137,6 +1175,20 @@ export class DictionaryController {
11371175
this._updateDictionaryEntryCount();
11381176
}
11391177

1178+
/**
1179+
* @param {CustomEvent<{index: number}>} e
1180+
*/
1181+
_onEntryDragStart(e) {
1182+
const index = e?.detail?.index;
1183+
if (typeof index !== 'number') { return; }
1184+
this._draggingIndex = index;
1185+
}
1186+
1187+
/** */
1188+
_onEntryDragEnd() {
1189+
this._draggingIndex = null;
1190+
}
1191+
11401192
/**
11411193
* @param {string} dictionaryTitle
11421194
*/

0 commit comments

Comments
 (0)