From 48a415931386783fe8a789290b25ba2ec43bbc4b Mon Sep 17 00:00:00 2001 From: Noah Onyejese <129368606+noahonyejese@users.noreply.github.com> Date: Tue, 11 Feb 2025 11:27:49 +0100 Subject: [PATCH 1/9] feat: created a keyboard command handler --- app/utils/use-keyboard-shortcuts.ts | 62 +++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 app/utils/use-keyboard-shortcuts.ts diff --git a/app/utils/use-keyboard-shortcuts.ts b/app/utils/use-keyboard-shortcuts.ts new file mode 100644 index 0000000000..73117ed8d0 --- /dev/null +++ b/app/utils/use-keyboard-shortcuts.ts @@ -0,0 +1,62 @@ +import { useCallback, useEffect, useState } from "react"; + +type KeyCombo = { + keys: string[]; + ctrlKey?: boolean; + metaKey?: boolean; +}; + +type KeyHandler = (event: KeyboardEvent) => void; + +export const useKeyboardShortcut = ( + keyCombo: KeyCombo, + handler: KeyHandler, + options: { preventDefault?: boolean } = {} +) => { + const [pressedKeys, setPressedKeys] = useState([]); + + const handleKeyDown = useCallback( + (event: KeyboardEvent) => { + setPressedKeys((prev) => { + const key = event.key.toLowerCase(); + if (!prev.includes(key)) { + return [...prev, key]; + } + return prev; + }); + + const targetKeys = keyCombo.keys.map((k) => k.toLowerCase()); + const currentKeys = [...pressedKeys, event.key.toLowerCase()]; + + const hasAllKeys = targetKeys.every((k) => currentKeys.includes(k)); + const matchesCtrl = + keyCombo.ctrlKey === undefined || event.ctrlKey === keyCombo.ctrlKey; + const matchesMeta = + keyCombo.metaKey === undefined || event.metaKey === keyCombo.metaKey; + + if (hasAllKeys && matchesCtrl && matchesMeta) { + if (options.preventDefault) { + event.preventDefault(); + } + handler(event); + } + }, + [keyCombo, handler, options.preventDefault, pressedKeys] + ); + + const handleKeyUp = useCallback((event: KeyboardEvent) => { + setPressedKeys((prev) => { + const key = event.key.toLowerCase(); + return prev.filter((k) => k !== key); + }); + }, []); + + useEffect(() => { + window.addEventListener("keydown", handleKeyDown); + window.addEventListener("keyup", handleKeyUp); + return () => { + window.removeEventListener("keydown", handleKeyDown); + window.removeEventListener("keyup", handleKeyUp); + }; + }, [handleKeyDown, handleKeyUp]); +}; From b55241e59d25f1a344e9842ff21ae8f99cdd56d0 Mon Sep 17 00:00:00 2001 From: Noah Onyejese <129368606+noahonyejese@users.noreply.github.com> Date: Tue, 11 Feb 2025 11:28:15 +0100 Subject: [PATCH 2/9] feat: extended flags to toggle debug w/ keyboard commands --- app/flags/useFlag.ts | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/app/flags/useFlag.ts b/app/flags/useFlag.ts index 8d829f5475..43513a918b 100644 --- a/app/flags/useFlag.ts +++ b/app/flags/useFlag.ts @@ -1,6 +1,9 @@ +import qs from "qs"; import { useEffect, useState } from "react"; -import { flag } from "./flag"; +import { useKeyboardShortcut } from "@/utils/use-keyboard-shortcuts"; + +import { flag, FLAG_PREFIX } from "./flag"; import { FlagName } from "./types"; export default function useFlagValue(name: FlagName) { @@ -40,3 +43,37 @@ export function useFlags() { return flags; } + +export const useDebugShortcut = (enable?: boolean) => { + useKeyboardShortcut( + { + keys: ["t", "d"], + ctrlKey: true, + }, + (event) => { + event.preventDefault(); + enable && addDebugFlag(); + } + ); +}; + +const addDebugFlag = () => { + const currentUrl = new URL(window.location.href); + const currentParams = qs.parse(currentUrl.search.substring(1)); + + const debugFlagKey = `${FLAG_PREFIX}debug`; + const hasDebugFlag = currentParams[debugFlagKey] === "true"; + + if (hasDebugFlag) { + delete currentParams[debugFlagKey]; + } else { + currentParams[debugFlagKey] = "true"; + } + + const newSearch = qs.stringify(currentParams); + const newUrl = `${window.location.pathname}${newSearch ? `?${newSearch}` : ""}`; + window.history.pushState({}, "", newUrl); + + const event = new Event("popstate"); + window.dispatchEvent(event); +}; From 1f8a4cf164c6effdafcf1f80be8caf38a55a3b83 Mon Sep 17 00:00:00 2001 From: Noah Onyejese <129368606+noahonyejese@users.noreply.github.com> Date: Tue, 11 Feb 2025 11:29:02 +0100 Subject: [PATCH 3/9] feat: added Debug hook to root --- app/pages/_app.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/pages/_app.tsx b/app/pages/_app.tsx index 5687cadaff..5304940622 100644 --- a/app/pages/_app.tsx +++ b/app/pages/_app.tsx @@ -11,8 +11,10 @@ import { useRouter } from "next/router"; import { useEffect } from "react"; import { SnackbarProvider } from "@/components/snackbar"; +import "@/configurator/components/color-picker.css"; import { PUBLIC_URL } from "@/domain/env"; import { flag } from "@/flags/flag"; +import { useDebugShortcut } from "@/flags/useFlag"; import { GraphqlProvider } from "@/graphql/GraphqlProvider"; import { i18n, parseLocaleString } from "@/locales/locales"; import { LocaleProvider } from "@/locales/use-locale"; @@ -24,8 +26,6 @@ import AsyncLocalizationProvider from "@/utils/l10n-provider"; import "@/utils/nprogress.css"; import { useNProgress } from "@/utils/use-nprogress"; -import "@/configurator/components/color-picker.css"; - const GQLDebugPanel = dynamic(() => import("@/gql-flamegraph/devtool"), { ssr: false, }); @@ -68,6 +68,8 @@ export default function App({ const shouldShowGQLDebug = process.env.NODE_ENV === "development" || flag("debug"); + useDebugShortcut(shouldShowGQLDebug); + return ( <> From a02f70639297b81ef786965d1566d203935dd67e Mon Sep 17 00:00:00 2001 From: Noah Onyejese <129368606+noahonyejese@users.noreply.github.com> Date: Tue, 11 Feb 2025 11:29:09 +0100 Subject: [PATCH 4/9] chore: Added CHANGELOG --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71d63c11ea..6cfb8f8cae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ You can also check the # Unreleased +- Feature + - flags can now be toggle by clicking "ctrl + t + d" on the keyboard (t,d => + toggle debug) - Fixes - Weekly-based temporal dimensions now work correctly when used in dashboard filters From 04d0bcbb4eb35a9745490c6d0234c9df8f8169e1 Mon Sep 17 00:00:00 2001 From: Noah Onyejese <129368606+noahonyejese@users.noreply.github.com> Date: Thu, 13 Feb 2025 09:44:13 +0100 Subject: [PATCH 5/9] chore: changed CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e76348512..bc6e066111 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ You can also check the # Unreleased -- Feature +- Maintenance - flags can now be toggle by clicking "ctrl + t + d" on the keyboard (t,d => toggle debug) From d5c2b81d0b7ca287927aa5b3388ddc8405cc04d6 Mon Sep 17 00:00:00 2001 From: Noah Onyejese <129368606+noahonyejese@users.noreply.github.com> Date: Mon, 17 Feb 2025 09:27:12 +0100 Subject: [PATCH 6/9] chore: added use konami --- app/package.json | 1 + yarn.lock | 121 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 108 insertions(+), 14 deletions(-) diff --git a/app/package.json b/app/package.json index 3171816565..38cb66f919 100644 --- a/app/package.json +++ b/app/package.json @@ -151,6 +151,7 @@ "urql": "^2.0.5", "use-debounce": "^7.0.0", "use-immer": "^0.5.1", + "use-konami": "^1.0.1", "use-sync-external-store": "^1.2.0", "wellknown": "^0.5.0", "wonka": "4.0.15", diff --git a/yarn.lock b/yarn.lock index 0065a15043..b15bd05d88 100644 --- a/yarn.lock +++ b/yarn.lock @@ -257,7 +257,7 @@ "@babel/highlight" "^7.24.2" picocolors "^1.0.0" -"@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.0": +"@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.0", "@babel/code-frame@^7.26.2": version "7.26.2" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== @@ -286,7 +286,29 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.2.tgz#278b6b13664557de95b8f35b90d96785850bb56e" integrity sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg== -"@babel/core@7.12.9", "@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.10.5", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.12.9", "@babel/core@^7.14.6", "@babel/core@^7.18.9", "@babel/core@^7.23.0", "@babel/core@^7.23.2", "@babel/core@^7.24.4", "@babel/core@^7.7.2", "@babel/core@^7.7.5", "@babel/core@^7.7.7": +"@babel/core@7.12.9": + version "7.12.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.9.tgz#fd450c4ec10cdbb980e2928b7aa7a28484593fc8" + integrity sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.12.5" + "@babel/helper-module-transforms" "^7.12.1" + "@babel/helpers" "^7.12.5" + "@babel/parser" "^7.12.7" + "@babel/template" "^7.12.7" + "@babel/traverse" "^7.12.9" + "@babel/types" "^7.12.7" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.19" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/core@^7.0.0", "@babel/core@^7.1.0", "@babel/core@^7.10.5", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.12.9", "@babel/core@^7.18.9", "@babel/core@^7.23.0", "@babel/core@^7.23.2", "@babel/core@^7.24.4", "@babel/core@^7.7.2", "@babel/core@^7.7.5", "@babel/core@^7.7.7": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.0.tgz#d78b6023cc8f3114ccf049eb219613f74a747b40" integrity sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg== @@ -316,6 +338,17 @@ jsesc "^2.5.1" source-map "^0.5.0" +"@babel/generator@^7.12.5", "@babel/generator@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.9.tgz#75a9482ad3d0cc7188a537aa4910bc59db67cbca" + integrity sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg== + dependencies: + "@babel/parser" "^7.26.9" + "@babel/types" "^7.26.9" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^3.0.2" + "@babel/generator@^7.20.14": version "7.23.0" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.0.tgz#df5c386e2218be505b34837acbcb874d7a983420" @@ -594,6 +627,15 @@ "@babel/traverse" "^7.25.9" "@babel/types" "^7.25.9" +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" + integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== + dependencies: + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@babel/traverse" "^7.25.9" + "@babel/helper-module-transforms@^7.14.5": version "7.15.8" resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz" @@ -619,15 +661,6 @@ "@babel/helper-split-export-declaration" "^7.22.6" "@babel/helper-validator-identifier" "^7.22.20" -"@babel/helper-module-transforms@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" - integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== - dependencies: - "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - "@babel/traverse" "^7.25.9" - "@babel/helper-optimise-call-expression@^7.14.5", "@babel/helper-optimise-call-expression@^7.15.4": version "7.15.4" resolved "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz" @@ -837,6 +870,14 @@ "@babel/template" "^7.22.15" "@babel/types" "^7.22.19" +"@babel/helpers@^7.12.5": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.9.tgz#28f3fb45252fc88ef2dc547c8a911c255fc9fef6" + integrity sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA== + dependencies: + "@babel/template" "^7.26.9" + "@babel/types" "^7.26.9" + "@babel/helpers@^7.26.0": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.0.tgz#30e621f1eba5aa45fe6f4868d2e9154d884119a4" @@ -882,13 +923,25 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/parser@7.12.16", "@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.14.6", "@babel/parser@^7.14.7", "@babel/parser@^7.15.4", "@babel/parser@^7.20.15", "@babel/parser@^7.20.7", "@babel/parser@^7.21.4", "@babel/parser@^7.22.15", "@babel/parser@^7.23.0", "@babel/parser@^7.24.0", "@babel/parser@^7.24.4", "@babel/parser@^7.24.5", "@babel/parser@^7.25.9", "@babel/parser@^7.26.0", "@babel/parser@^7.26.2", "@babel/parser@^7.7.2": +"@babel/parser@7.12.16": + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.16.tgz#cc31257419d2c3189d394081635703f549fc1ed4" + integrity sha512-c/+u9cqV6F0+4Hpq01jnJO+GLp2DdT63ppz9Xa+6cHaajM9VFzK/iDXiKK65YtpeVwu+ctfS6iqlMqRgQRzeCw== + +"@babel/parser@^7.0.0", "@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.14.7", "@babel/parser@^7.15.4", "@babel/parser@^7.20.15", "@babel/parser@^7.20.7", "@babel/parser@^7.21.4", "@babel/parser@^7.22.15", "@babel/parser@^7.23.0", "@babel/parser@^7.24.0", "@babel/parser@^7.24.4", "@babel/parser@^7.24.5", "@babel/parser@^7.25.9", "@babel/parser@^7.26.0", "@babel/parser@^7.26.2", "@babel/parser@^7.7.2": version "7.26.5" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.5.tgz#6fec9aebddef25ca57a935c86dbb915ae2da3e1f" integrity sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw== dependencies: "@babel/types" "^7.26.5" +"@babel/parser@^7.12.7", "@babel/parser@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.9.tgz#d9e78bee6dc80f9efd8f2349dcfbbcdace280fd5" + integrity sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A== + dependencies: + "@babel/types" "^7.26.9" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.5": version "7.24.5" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.5.tgz#4c3685eb9cd790bcad2843900fe0250c91ccf895" @@ -2542,6 +2595,15 @@ resolved "https://registry.npmjs.org/@babel/standalone/-/standalone-7.14.6.tgz" integrity sha512-oAoSp82jhJFnXKybKTOj5QF04XxiDRyiiqrFToiU1udlBXuZoADlPmmnOcuqBrZxSNNUjzJIVK8vt838Qoqjxg== +"@babel/template@^7.12.7", "@babel/template@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.26.9.tgz#4577ad3ddf43d194528cff4e1fa6b232fa609bb2" + integrity sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA== + dependencies: + "@babel/code-frame" "^7.26.2" + "@babel/parser" "^7.26.9" + "@babel/types" "^7.26.9" + "@babel/template@^7.15.4", "@babel/template@^7.3.3": version "7.15.4" resolved "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz" @@ -2608,6 +2670,19 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/traverse@^7.12.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.9.tgz#4398f2394ba66d05d988b2ad13c219a2c857461a" + integrity sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg== + dependencies: + "@babel/code-frame" "^7.26.2" + "@babel/generator" "^7.26.9" + "@babel/parser" "^7.26.9" + "@babel/template" "^7.26.9" + "@babel/types" "^7.26.9" + debug "^4.3.1" + globals "^11.1.0" + "@babel/traverse@^7.18.9", "@babel/traverse@^7.23.2": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.0.tgz#4a408fbf364ff73135c714a2ab46a5eab2831b1e" @@ -2670,6 +2745,14 @@ "@babel/helper-validator-identifier" "^7.14.9" to-fast-properties "^2.0.0" +"@babel/types@^7.12.7", "@babel/types@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.9.tgz#08b43dec79ee8e682c2ac631c010bdcac54a21ce" + integrity sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw== + dependencies: + "@babel/helper-string-parser" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@babel/types@^7.16.7": version "7.17.0" resolved "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz" @@ -16741,7 +16824,7 @@ fwd-stream@^1.0.4: dependencies: readable-stream "~1.0.26-4" -gensync@^1.0.0-beta.2: +gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== @@ -24613,7 +24696,7 @@ resolve@^1.21.0, resolve@^1.22.1: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^1.22.4: +resolve@^1.22.4, resolve@^1.3.2: version "1.22.10" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== @@ -24930,6 +25013,11 @@ semver-compare@^1.0.0: resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== +semver@^5.4.1: + version "5.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" + integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== + semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" @@ -27295,6 +27383,11 @@ use-immer@^0.5.1: resolved "https://registry.npmjs.org/use-immer/-/use-immer-0.5.2.tgz" integrity sha512-aHnLa85kftWo05lqJVOy3GLXrydqu6kl0MXvo5k5OW8IoLJixa9NY/48Xdy0LlcqdakBTFLbSDZaYVPMVhYy8Q== +use-konami@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/use-konami/-/use-konami-1.0.1.tgz#7bdca59e37bba347b21f1bafca1eca59e6596531" + integrity sha512-oqLN0zMKnzCc2eHoPlTq63eZrigCTGPSizUHiqB0tmZE1FDD8ieP0U670YmEIodsUvt2eT0JHLzs603uj30+TA== + use-memo-one@^1.1.1: version "1.1.2" resolved "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.2.tgz" From 7a13d8dada29e971c32ec63b29116cbfe09ffd67 Mon Sep 17 00:00:00 2001 From: Noah Onyejese <129368606+noahonyejese@users.noreply.github.com> Date: Mon, 17 Feb 2025 09:27:30 +0100 Subject: [PATCH 7/9] refactor: changed keyboard shortcut to konami --- app/flags/{useFlag.ts => use-flags.ts} | 29 +++++++----- app/utils/use-keyboard-shortcuts.ts | 62 -------------------------- 2 files changed, 17 insertions(+), 74 deletions(-) rename app/flags/{useFlag.ts => use-flags.ts} (79%) delete mode 100644 app/utils/use-keyboard-shortcuts.ts diff --git a/app/flags/useFlag.ts b/app/flags/use-flags.ts similarity index 79% rename from app/flags/useFlag.ts rename to app/flags/use-flags.ts index 43513a918b..b48c862c8f 100644 --- a/app/flags/useFlag.ts +++ b/app/flags/use-flags.ts @@ -1,7 +1,6 @@ import qs from "qs"; import { useEffect, useState } from "react"; - -import { useKeyboardShortcut } from "@/utils/use-keyboard-shortcuts"; +import useKonami, { UseKonamiArgs } from "use-konami"; import { flag, FLAG_PREFIX } from "./flag"; import { FlagName } from "./types"; @@ -44,17 +43,23 @@ export function useFlags() { return flags; } -export const useDebugShortcut = (enable?: boolean) => { - useKeyboardShortcut( - { - keys: ["t", "d"], - ctrlKey: true, +type UseDebugShortcutProps = { + enable?: boolean; +}; + +export const useDebugShortcut = ({ + enable, +}: UseDebugShortcutProps = {}): void => { + const konamiConfig: UseKonamiArgs = { + sequence: ["t", "o", "g", "g", "l", "e", "d", "e", "b", "u", "g"], + onUnlock: () => { + if (enable) { + addDebugFlag(); + } }, - (event) => { - event.preventDefault(); - enable && addDebugFlag(); - } - ); + }; + + useKonami(konamiConfig); }; const addDebugFlag = () => { diff --git a/app/utils/use-keyboard-shortcuts.ts b/app/utils/use-keyboard-shortcuts.ts deleted file mode 100644 index 73117ed8d0..0000000000 --- a/app/utils/use-keyboard-shortcuts.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { useCallback, useEffect, useState } from "react"; - -type KeyCombo = { - keys: string[]; - ctrlKey?: boolean; - metaKey?: boolean; -}; - -type KeyHandler = (event: KeyboardEvent) => void; - -export const useKeyboardShortcut = ( - keyCombo: KeyCombo, - handler: KeyHandler, - options: { preventDefault?: boolean } = {} -) => { - const [pressedKeys, setPressedKeys] = useState([]); - - const handleKeyDown = useCallback( - (event: KeyboardEvent) => { - setPressedKeys((prev) => { - const key = event.key.toLowerCase(); - if (!prev.includes(key)) { - return [...prev, key]; - } - return prev; - }); - - const targetKeys = keyCombo.keys.map((k) => k.toLowerCase()); - const currentKeys = [...pressedKeys, event.key.toLowerCase()]; - - const hasAllKeys = targetKeys.every((k) => currentKeys.includes(k)); - const matchesCtrl = - keyCombo.ctrlKey === undefined || event.ctrlKey === keyCombo.ctrlKey; - const matchesMeta = - keyCombo.metaKey === undefined || event.metaKey === keyCombo.metaKey; - - if (hasAllKeys && matchesCtrl && matchesMeta) { - if (options.preventDefault) { - event.preventDefault(); - } - handler(event); - } - }, - [keyCombo, handler, options.preventDefault, pressedKeys] - ); - - const handleKeyUp = useCallback((event: KeyboardEvent) => { - setPressedKeys((prev) => { - const key = event.key.toLowerCase(); - return prev.filter((k) => k !== key); - }); - }, []); - - useEffect(() => { - window.addEventListener("keydown", handleKeyDown); - window.addEventListener("keyup", handleKeyUp); - return () => { - window.removeEventListener("keydown", handleKeyDown); - window.removeEventListener("keyup", handleKeyUp); - }; - }, [handleKeyDown, handleKeyUp]); -}; From f2517f301912718b994f5f6a677b5a6b3bfee4f7 Mon Sep 17 00:00:00 2001 From: Noah Onyejese <129368606+noahonyejese@users.noreply.github.com> Date: Mon, 17 Feb 2025 09:27:42 +0100 Subject: [PATCH 8/9] fix: fixed enable logic --- app/flags/index.tsx | 2 +- app/pages/_app.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/flags/index.tsx b/app/flags/index.tsx index 49a62d67ad..8c35267a2c 100644 --- a/app/flags/index.tsx +++ b/app/flags/index.tsx @@ -1,2 +1,2 @@ export { flag } from "./flag"; -export { default as useFlag, useFlags } from "./useFlag"; +export { default as useFlag, useFlags } from "./use-flags"; diff --git a/app/pages/_app.tsx b/app/pages/_app.tsx index 5304940622..500ac74a2a 100644 --- a/app/pages/_app.tsx +++ b/app/pages/_app.tsx @@ -14,7 +14,7 @@ import { SnackbarProvider } from "@/components/snackbar"; import "@/configurator/components/color-picker.css"; import { PUBLIC_URL } from "@/domain/env"; import { flag } from "@/flags/flag"; -import { useDebugShortcut } from "@/flags/useFlag"; +import { useDebugShortcut } from "@/flags/use-flags"; import { GraphqlProvider } from "@/graphql/GraphqlProvider"; import { i18n, parseLocaleString } from "@/locales/locales"; import { LocaleProvider } from "@/locales/use-locale"; @@ -68,7 +68,7 @@ export default function App({ const shouldShowGQLDebug = process.env.NODE_ENV === "development" || flag("debug"); - useDebugShortcut(shouldShowGQLDebug); + useDebugShortcut({ enable: shouldShowGQLDebug }); return ( <> From 624b90bfc9af27953e940d24dd0cbd799fa939a2 Mon Sep 17 00:00:00 2001 From: Noah Onyejese <129368606+noahonyejese@users.noreply.github.com> Date: Mon, 17 Feb 2025 09:54:41 +0100 Subject: [PATCH 9/9] fix: always enable --- app/pages/_app.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/pages/_app.tsx b/app/pages/_app.tsx index 500ac74a2a..f770b4449e 100644 --- a/app/pages/_app.tsx +++ b/app/pages/_app.tsx @@ -68,7 +68,7 @@ export default function App({ const shouldShowGQLDebug = process.env.NODE_ENV === "development" || flag("debug"); - useDebugShortcut({ enable: shouldShowGQLDebug }); + useDebugShortcut({ enable: true }); return ( <>