fix: long-press support for topicSelect, #14045

This commit is contained in:
Julian Lam
2026-03-13 14:42:48 -04:00
parent 58da90361f
commit d1e1a0082d
2 changed files with 51 additions and 4 deletions

View File

@@ -9,11 +9,16 @@ define('forum/category/tools', [
'api', 'api',
'bootbox', 'bootbox',
'alerts', 'alerts',
], function (topicSelect, threadTools, components, api, bootbox, alerts) { 'bootstrap',
], function (topicSelect, threadTools, components, api, bootbox, alerts, bootstrap) {
const CategoryTools = {}; const CategoryTools = {};
CategoryTools.init = function (containerEl) { CategoryTools.init = function (containerEl) {
topicSelect.init(updateDropdownOptions, containerEl); topicSelect.init(updateDropdownOptions, () => {
const toggleEl = document.querySelector('.thread-tools button');
const dropdown = new bootstrap.Dropdown(toggleEl);
dropdown.show();
}, containerEl);
handlePinnedTopicSort(); handlePinnedTopicSort();

View File

@@ -7,13 +7,14 @@ define('topicSelect', ['components'], function (components) {
let topicsContainer; let topicsContainer;
TopicSelect.init = function (onSelect, containerEl) { TopicSelect.init = function (onSelect, onLongPress, containerEl) {
topicsContainer = containerEl || $('[component="category"]'); topicsContainer = containerEl || $('[component="category"]');
topicsContainer.on('selectstart', '[component="topic/select"]', function (ev) { topicsContainer.on('selectstart', '[component="topic/select"]', function (ev) {
ev.preventDefault(); ev.preventDefault();
}); });
topicsContainer.on('click', '[component="topic/select"]', function (ev) { let isLongPress = false;
const click = function (ev) {
const select = $(this); const select = $(this);
const topicEl = select.parents('[component="category/topic"]'); const topicEl = select.parents('[component="category/topic"]');
if (ev.shiftKey) { if (ev.shiftKey) {
@@ -28,6 +29,47 @@ define('topicSelect', ['components'], function (components) {
if (typeof onSelect === 'function') { if (typeof onSelect === 'function') {
onSelect(); onSelect();
} }
};
topicsContainer.on('click', '[component="topic/select"]', function (ev) {
if (isLongPress) {
ev.preventDefault();
ev.stopImmediatePropagation();
return false;
}
click.call(this, ev);
});
// Long press
let longPressTimeout;
const start = function (ev) {
if (ev.type === 'touchstart') {
ev.preventDefault();
}
isLongPress = false;
longPressTimeout = setTimeout(() => {
isLongPress = true;
click.call(this, ev);
if (navigator.vibrate) {
navigator.vibrate(50);
}
const topicEl = this.closest('[component="category/topic"]');
if (topicEl.classList.contains('selected')) {
onLongPress();
}
}, 500);
};
const cancel = () => {
clearTimeout(longPressTimeout);
};
topicsContainer.on('mousedown', '[component="topic/select"]', start);
topicsContainer.on('touchstart', '[component="topic/select"]', start);
topicsContainer.on('mouseup', '[component="topic/select"]', cancel);
topicsContainer.on('mouseleave', '[component="topic/select"]', cancel);
topicsContainer.on('touchend', '[component="topic/select"]', cancel);
topicsContainer.on('touchcancel', '[component="topic/select"]', cancel);
topicsContainer.on('contextmenu', (e) => {
e.preventDefault();
}); });
}; };