From 6bfed3e779b5c32fd545d8303581963d556de958 Mon Sep 17 00:00:00 2001 From: Egor Savkin Date: Mon, 18 Mar 2024 14:48:16 +0800 Subject: [PATCH] Show at max only one options notification Closes #124 Signed-off-by: Egor Savkin --- static/js/shop/OptionsWrapper.jsx | 9 ++++++ static/js/shop/options/DialogPopup.jsx | 8 ++++-- static/js/shop/options/Notification.jsx | 38 +++++++++---------------- static/js/shop/shop_store.js | 25 ++++++++++++++++ 4 files changed, 53 insertions(+), 27 deletions(-) diff --git a/static/js/shop/OptionsWrapper.jsx b/static/js/shop/OptionsWrapper.jsx index d5b1e556..72b49e0e 100644 --- a/static/js/shop/OptionsWrapper.jsx +++ b/static/js/shop/OptionsWrapper.jsx @@ -11,6 +11,13 @@ export function OptionsDialogWrapper({crate_index, card_index, first, last}) { const card_id = useShopStore((state) => state.crates[crate_index].items[card_index].id); const options_class = useShopStore((state) => state.crates[crate_index].items[card_index].options_class); const sideMenuIsOpen = useShopStore((state) => state.sideMenuIsOpen); + const _notificationTimer = useShopStore((state) => state.notificationTimer); + const hideNotification = useShopStore((state) => state.hideNotification); + //const notificationCardIndex = useShopStore((state) => state.notificationCardIndex); + //const displayNotification = notificationCrateId === crate_id && notificationCardIndex === card_index; + const displayNotification = useShopStore((state) => + state.notificationCrateId === crate_id && + (state.notificationCardIndex === card_index || (state.crates[crate_index].items.length + (state.notificationCardIndex || -1)) === card_index)); const onOptionsUpdate = useShopStore((state) => state.updateOptions); @@ -25,6 +32,8 @@ export function OptionsDialogWrapper({crate_index, card_index, first, last}) { first={first} last={last} sideMenuIsOpen={sideMenuIsOpen} + onHideNotification={hideNotification} + displayNotification={displayNotification} target={{ construct: ((outvar, value) => { // #!options_log diff --git a/static/js/shop/options/DialogPopup.jsx b/static/js/shop/options/DialogPopup.jsx index 58a730d0..f5efa3a7 100644 --- a/static/js/shop/options/DialogPopup.jsx +++ b/static/js/shop/options/DialogPopup.jsx @@ -3,7 +3,8 @@ import {useClickAway} from "./useClickAway"; import {ProcessOptions} from "./Options"; import {Notification} from "./Notification"; -export function DialogPopup({options, data, target, id, big, first, last, options_class, sideMenuIsOpen}) { +export function DialogPopup({options, data, target, id, big, first, last, options_class, + sideMenuIsOpen, displayNotification, onHideNotification}) { const [show, setShow] = useState(false); const ref = useClickAway((e) => { if (e.type === "mousedown") // ignore touchstart @@ -22,8 +23,11 @@ export function DialogPopup({options, data, target, id, big, first, last, option id={"processed_options_notification" + id} tip="Customization options available" sideMenuIsOpen={sideMenuIsOpen} + show={displayNotification} + onHide={onHideNotification} content={ - } /> diff --git a/static/js/shop/options/Notification.jsx b/static/js/shop/options/Notification.jsx index 5fece088..2087a710 100644 --- a/static/js/shop/options/Notification.jsx +++ b/static/js/shop/options/Notification.jsx @@ -1,30 +1,18 @@ import {OverlayTrigger, Tooltip} from "react-bootstrap"; -import React, {useEffect, useState} from "react"; - -export function Notification({id, tip, content, sideMenuIsOpen}) { - const [show, setShow] = useState(false); - - useEffect(() => { - setTimeout(() => { - setShow(true) - }, 100); - - setTimeout(() => { - setShow(false) - }, 5000); - }, []); +import React from "react"; +export function Notification({id, tip, content, sideMenuIsOpen, show, onHide}) { return ( - setShow(false)} - overlay={props => {tip}} - rootClose={!sideMenuIsOpen} - > - {content} - + {tip}} + rootClose={!sideMenuIsOpen} + onToggle={onHide} + > + {content} + ) } \ No newline at end of file diff --git a/static/js/shop/shop_store.js b/static/js/shop/shop_store.js index 7bb29d49..f7a04c80 100644 --- a/static/js/shop/shop_store.js +++ b/static/js/shop/shop_store.js @@ -29,6 +29,28 @@ const useCatalog = ((set, get) => ({ cardIndexById: card_id => get().cards_list.findIndex((element) => (card_id === element)) })); +const useOptionsNotification = ((set, get) => ({ + notificationCrateId: null, + notificationCardIndex: null, + notificationTimer: null, + _showNotification: (crate_id, card_index) => set(state => ({ + notificationCrateId: crate_id, + notificationCardIndex: card_index, + notificationTimer: setTimeout(() => { + state.hideNotification() + }, 5000) + })), + showNotification: (crate_id, card_index) => { + get().hideNotification() + setTimeout(() => get()._showNotification(crate_id, card_index), 100); + }, + hideNotification: () => set(state => ({ + notificationCrateId: null, + notificationCardIndex: null, + notificationTimer: (state.notificationTimer && clearTimeout(state.notificationTimer)) || null, + })) +})); + const useSearch = ((set, get) => ({ search_index: Array.from(Object.values(shared_data.items) .map((card, _) => ( @@ -182,6 +204,7 @@ const useImportJSON = ((set, get) => ({ get().fillExtCrateData(crate.id); }); get()._updateTotalOrderPrice(); + get().showNotification(get().active_crate, null); }, updateImportDescription: (new_description) => set(state => ({ importValue: { @@ -532,6 +555,7 @@ const useCart = ((set, get) => ({ get().noDestinationWarning(); return {}; } + get().showNotification(dest, index_to); get()._addCardFromCatalog(dest, index_from, index_to) get().fillExtData(dest); get().fillWarnings(dest); @@ -583,6 +607,7 @@ const useCart = ((set, get) => ({ export const useShopStore = createWithEqualityFn((...params) => ({ + ...useOptionsNotification(...params), ...useCatalog(...params), ...useSearch(...params), ...useCrateModes(...params),