fix: require long press to open swipe picker on phones (#5382) * fix: require long press to open swipe picker on phones * fix: clarify parameter description in assignLorebookToChat function * fix: update event parameter type in onSwipeCounterClick to include TouchEvent * fix: update event parameter types in onSwipeCounterClick and addLongPressEvent
Signed| @@ -1171,9 +1171,9 @@ function onPersonaDescriptionDepthRoleInput() { | |||
| 1171 | 1171 | ||
| 1172 | /** | 1172 | /** |
| 1173 | * Opens a popup to set the lorebook for the current persona. | 1173 | * Opens a popup to set the lorebook for the current persona. |
| 1174 | * @param {JQuery.ClickEvent} event Click event | 1174 | * @param {Pick<JQuery.ClickEvent, 'shiftKey' | 'altKey'>} event Click event |
| 1175 | */ | 1175 | */ |
| 1176 | async function onPersonaLoreButtonClick(event) { | 1176 | async function onPersonaLoreButtonClick({ shiftKey, altKey }) { |
| 1177 | const personaName = power_user.personas[user_avatar]; | 1177 | const personaName = power_user.personas[user_avatar]; |
| 1178 | const selectedLorebook = power_user.persona_description_lorebook; | 1178 | const selectedLorebook = power_user.persona_description_lorebook; |
| 1179 | 1179 | ||
| @@ -1182,7 +1182,7 @@ async function onPersonaLoreButtonClick(event) { | |||
| 1182 | return; | 1182 | return; |
| 1183 | } | 1183 | } |
| 1184 | 1184 | ||
| 1185 | if (selectedLorebook && !event.shiftKey && !event.altKey) { | 1185 | if (selectedLorebook && !shiftKey && !altKey) { |
| 1186 | openWorldInfoEditor(selectedLorebook); | 1186 | openWorldInfoEditor(selectedLorebook); |
| 1187 | return; | 1187 | return; |
| 1188 | } | 1188 | } |
| @@ -3,8 +3,9 @@ import { SWIPE_DIRECTION, SWIPE_SOURCE } from './constants.js'; | |||
| 3 | import { t } from './i18n.js'; | 3 | import { t } from './i18n.js'; |
| 4 | import { callGenericPopup, Popup, POPUP_RESULT, POPUP_TYPE } from './popup.js'; | 4 | import { callGenericPopup, Popup, POPUP_RESULT, POPUP_TYPE } from './popup.js'; |
| 5 | import { power_user } from './power-user.js'; | 5 | import { power_user } from './power-user.js'; |
| 6 | import { isMobile } from './RossAscends-mods.js'; | ||
| 6 | import { getTokenCountAsync } from './tokenizers.js'; | 7 | import { getTokenCountAsync } from './tokenizers.js'; |
| 7 | import { clamp, copyText, timestampToMoment } from './utils.js'; | 8 | import { addLongPressEvent, clamp, copyText, timestampToMoment } from './utils.js'; |
| 8 | import { chat, deleteSwipe, ensureSwipes, isMessageSwipeable, isSwipingAllowed, swipe, syncMesToSwipe } from '/script.js'; | 9 | import { chat, deleteSwipe, ensureSwipes, isMessageSwipeable, isSwipingAllowed, swipe, syncMesToSwipe } from '/script.js'; |
| 9 | 10 | ||
| 10 | /** | 11 | /** |
| @@ -409,22 +410,29 @@ async function openSwipePicker(messageId) { | |||
| 409 | } | 410 | } |
| 410 | 411 | ||
| 411 | export function initSwipePicker() { | 412 | export function initSwipePicker() { |
| 412 | $(document).on('click', '.swipes-counter.swipe-picker-enabled', async function (e) { | 413 | /** |
| 414 | * Click handler for opening the swipe picker when clicking on the swipe counter. | ||
| 415 | * @param {JQuery.Event | Event} e Event object | ||
| 416 | */ | ||
| 417 | async function onSwipeCounterClick(e) { | ||
| 413 | e.preventDefault(); | 418 | e.preventDefault(); |
| 414 | e.stopPropagation(); | 419 | e.stopPropagation(); |
| 415 | 420 | ||
| 416 | const mesId = Number($(this).closest('.mes').attr('mesid')); | 421 | const mesId = Number($(this).closest('.mes').attr('mesid')); |
| 417 | await openSwipePicker(mesId); | 422 | await openSwipePicker(mesId); |
| 418 | }); | 423 | } |
| 424 | |||
| 425 | if (isMobile()) { | ||
| 426 | addLongPressEvent('.swipes-counter.swipe-picker-enabled', onSwipeCounterClick); | ||
| 427 | } else { | ||
| 428 | $(document).on('click', '.swipes-counter.swipe-picker-enabled', onSwipeCounterClick); | ||
| 429 | } | ||
| 419 | $(document).on('keydown', '.swipes-counter.swipe-picker-enabled', async function (e) { | 430 | $(document).on('keydown', '.swipes-counter.swipe-picker-enabled', async function (e) { |
| 420 | if (e.key !== ' ') { | 431 | if (e.key !== ' ') { |
| 421 | return; | 432 | return; |
| 422 | } | 433 | } |
| 423 | 434 | ||
| 424 | e.preventDefault(); | 435 | onSwipeCounterClick.call(this, e); |
| 425 | e.stopPropagation(); | ||
| 426 | const mesId = Number($(this).closest('.mes').attr('mesid')); | ||
| 427 | await openSwipePicker(mesId); | ||
| 428 | }); | 436 | }); |
| 429 | $(document).on('click', '.mes_swipe_picker', async function (e) { | 437 | $(document).on('click', '.mes_swipe_picker', async function (e) { |
| 430 | e.preventDefault(); | 438 | e.preventDefault(); |
| @@ -2955,7 +2955,7 @@ export function createTimeout(ms, errorMessage = '') { | |||
| 2955 | * Registers a long-press (touch hold) event as an alternative to modifier+click. | 2955 | * Registers a long-press (touch hold) event as an alternative to modifier+click. |
| 2956 | * Supports event delegation for dynamically created elements. | 2956 | * Supports event delegation for dynamically created elements. |
| 2957 | * @param {string} selector CSS selector for target elements | 2957 | * @param {string} selector CSS selector for target elements |
| 2958 | * @param {function} callback Callback to invoke on long-press, `this` is the matched element | 2958 | * @param {(e: TouchEvent) => void} callback Callback to invoke on long-press, `this` is the matched element |
| 2959 | * @param {number} [delay=500] Long-press duration in ms | 2959 | * @param {number} [delay=500] Long-press duration in ms |
| 2960 | */ | 2960 | */ |
| 2961 | export function addLongPressEvent(selector, callback, delay = 500) { | 2961 | export function addLongPressEvent(selector, callback, delay = 500) { |
| @@ -2964,6 +2964,7 @@ export function addLongPressEvent(selector, callback, delay = 500) { | |||
| 2964 | let target = null; | 2964 | let target = null; |
| 2965 | 2965 | ||
| 2966 | document.addEventListener('touchstart', function (event) { | 2966 | document.addEventListener('touchstart', function (event) { |
| 2967 | if (!(event.target instanceof Element)) return; | ||
| 2967 | const el = event.target.closest(selector); | 2968 | const el = event.target.closest(selector); |
| 2968 | if (!el) return; | 2969 | if (!el) return; |
| 2969 | target = el; | 2970 | target = el; |
| @@ -5808,9 +5808,7 @@ export function openWorldInfoEditor(worldName) { | |||
| 5808 | 5808 | ||
| 5809 | /** | 5809 | /** |
| 5810 | * Assigns a lorebook to the current chat. | 5810 | * Assigns a lorebook to the current chat. |
| 5811 | * @param {Object} options - The options for assigning the lorebook. | 5811 | * @param {Pick<JQuery.ClickEvent, 'shiftKey' | 'altKey'>} event Click event |
| 5812 | * @param {boolean} options.shiftKey - Whether the Shift key is pressed. | ||
| 5813 | * @param {boolean} options.altKey - Whether the Alt key is pressed. | ||
| 5814 | * @returns {Promise<void>} | 5812 | * @returns {Promise<void>} |
| 5815 | */ | 5813 | */ |
| 5816 | export async function assignLorebookToChat({ shiftKey, altKey }) { | 5814 | export async function assignLorebookToChat({ shiftKey, altKey }) { |