From cf2c45687af49f01e16d4afb7a4e58afb3d20132 Mon Sep 17 00:00:00 2001 From: Luke Date: Thu, 4 Aug 2022 13:12:58 +0200 Subject: [PATCH] refactor(menu): split side and vertical scroll change handlers Resolves an issue where changing to the next button while scrolling a horizontal list would not trigger the onChange function for the previous button --- resource/interface/client/menu.lua | 40 ++++++++++++++++------------ web/src/features/menu/list/index.tsx | 35 +++++++++++------------- 2 files changed, 39 insertions(+), 36 deletions(-) diff --git a/resource/interface/client/menu.lua b/resource/interface/client/menu.lua index def62e6..a631259 100644 --- a/resource/interface/client/menu.lua +++ b/resource/interface/client/menu.lua @@ -36,28 +36,27 @@ function lib.getOpenMenu() return openMenu end RegisterNUICallback('confirmSelected', function(data, cb) cb(1) - local selected = type(data) == 'number' and data+1 or data[1] + local selected = {data[1] + 1, data[2] and data[2] + 1} -- data = [selected, scrollIndex] local menu = registeredMenus[openMenu] - if menu.options[selected].close ~= false then SetNuiFocus(false, false) end - local args = menu.options[selected].args - if type(data) == 'number' then - registeredMenus[openMenu].cb(data, nil, args) - else - registeredMenus[openMenu].cb(data[1], data[2], args) - end + if menu.options[selected[1]].close ~= false then SetNuiFocus(false, false) end + local args = menu.options[selected[1]].args + registeredMenus[openMenu].cb(selected[1], selected[2], args) +end) + +RegisterNUICallback('changeIndex', function(data, cb) + cb(1) + if not registeredMenus[openMenu].onSideScroll then return end + local selected = {data[1] + 1, data[2] and data[2] + 1} -- data = [selected, scrollIndex] + local args = registeredMenus[openMenu].options[selected[1]].args + registeredMenus[openMenu].onSideScroll(selected[1], selected[2], args) end) RegisterNUICallback('changeSelected', function(data, cb) cb(1) - if not registeredMenus[openMenu].onChange then return end - local selected = data - if type(selected) == 'number' then - local args = registeredMenus[openMenu].options[selected+1].args - registeredMenus[openMenu].onChange(selected, nil, args) - else - local args = registeredMenus[openMenu].options[selected[1]+1].args - registeredMenus[openMenu].onChange(selected[1], selected[2], args) - end + if not registeredMenus[openMenu].onSelected then return end + local selected = {data[1] + 1, data[2] and data[2] + 1} -- data = [selected, scrollIndex] + local args = registeredMenus[openMenu].options[selected[1]].args + registeredMenus[openMenu].onSelected(selected[1], selected[2], args) end) RegisterNUICallback('closeMenu', function(data, cb) @@ -88,10 +87,17 @@ RegisterCommand('testMenu', function() --lib.setMenuOptions('epic_menu', {label = 'Not nice'}, 1) --lib.showMenu('epic_menu') end, + onSelected = function(selected, scrollIndex, args) + print('selected: ', selected, scrollIndex) + end, + onSideScroll = function(selected, scrollIndex, args) + print('sideScroll: ', selected, scrollIndex) + end, options = { {label = 'Extra nice option', args = 'Hello there', close = false}, {label = 'Giga nice option'}, {label = 'Omega nice option'}, + {label = 'Values', values={'hello', 'there', 'general', 'kenobi'}} } }, function(selected, scrollIndex, args) print(selected, scrollIndex, args) diff --git a/web/src/features/menu/list/index.tsx b/web/src/features/menu/list/index.tsx index b230fd1..b4329ff 100644 --- a/web/src/features/menu/list/index.tsx +++ b/web/src/features/menu/list/index.tsx @@ -8,6 +8,7 @@ import FocusTrap from "focus-trap-react"; import { IconProp } from "@fortawesome/fontawesome-svg-core"; import { fetchNui } from "../../../utils/fetchNui"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import React from "react"; export interface MenuItem { label: string; @@ -106,15 +107,20 @@ const ListMenu: React.FC = () => { break; case "Enter": if (!menu.items[selected]) return; - fetchNui( - "confirmSelected", - Array.isArray(menu.items[selected].values) ? [selected, indexStates[selected]] : selected - ); + fetchNui("confirmSelected", [selected, indexStates[selected]]).catch(); if (menu.items[selected].close === undefined || menu.items[selected].close) setVisible(false); break; } }; + useEffect(() => { + if (!menu.items[selected]?.values) return; + const timer = setTimeout(() => { + fetchNui("changeIndex", [selected, indexStates[selected]]).catch(); + }, 100); + return () => clearTimeout(timer); + }, [indexStates]); + useEffect(() => { if (!menu.items[selected]) return; listRefs.current[selected]?.scrollIntoView({ @@ -124,13 +130,10 @@ const ListMenu: React.FC = () => { listRefs.current[selected]?.focus({ preventScroll: true }); // debounces the callback to avoid spam const timer = setTimeout(() => { - fetchNui( - "changeSelected", - Array.isArray(menu.items[selected].values) ? [selected, indexStates[selected]] : selected - ); - }, 500); + fetchNui("changeSelected", [selected, indexStates[selected]]).catch(); + }, 100); return () => clearTimeout(timer); - }, [selected, menu, indexStates]); + }, [selected, menu]); useEffect(() => { if (!visible) return; @@ -197,17 +200,11 @@ const ListMenu: React.FC = () => { {menu.items.map((item, index) => ( - <> + {item.label && ( - + )} - + ))}