-
Notifications
You must be signed in to change notification settings - Fork 110
/
Copy pathMacrosMenu.jsx
132 lines (116 loc) · 4.07 KB
/
MacrosMenu.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import { memo, useState, useEffect, useContext, useRef, useCallback } from 'react'
import useRedirect from '../../hooks/useRedirect'
import useIsKeyPressed from '../../hooks/useIsKeyPressed'
import { useStateSelector , useUpdate} from '../../contexts/Store'
import { SettingsContext } from '../../contexts/Settings'
import { Splide, SplideSlide } from '@splidejs/react-splide'
import { Grid } from '@splidejs/splide-extension-grid'
import Card from '../Card/Card'
import { allowedModes } from '../../rules'
import classes from './MacrosMenu.module.css'
import '@splidejs/react-splide/css'
const pinnedMacros = window.CONFIG.macros.filter(m => m.pinned)
function MacrosMenu({ visibility, fullVisibility }) {
// settings
const settings = useContext(SettingsContext)
const pagination = settings.menu.pagination
const arrows = settings.menu.arrows
const drag = settings.menu.drag
const rows = settings.menu.rows
const cols = settings.menu.columns
const gap = settings.menu.gap
const slideCapacity = cols * rows
const isSliderHasMultipleSlides = pinnedMacros.length > slideCapacity
/* store */
const mode = useStateSelector(store => store.mode)
// ---
// selected macro
const [selected, setSelected] = useState(null)
const isShiftPressed = useIsKeyPressed('Shift')
// if the slider is on the slide with the selected card
const [isCardInFocus, setIsCardInFocus] = useState(false)
const sliderRef = useRef(null)
const updateValue = useUpdate()
const redirect = useRedirect()
const activateCard = useCallback(macro => {
const cardIndex = pinnedMacros.indexOf(macro)
// select the card
setSelected(macro)
// block the store
updateValue({ redirected: true })
// go to the selected card
sliderRef.current.splide.Components.Controller.go(
Math.floor(cardIndex / slideCapacity),
// allow going to the current slide
true,
() => setIsCardInFocus(true)
)
// !visibility - ignore animations if the menu isn't visible
redirect(macro.url, 'card', !visibility)
}, [redirect, visibility, slideCapacity, updateValue])
// hotkeys listener
useEffect(() => {
const handleKeypress = e => {
if (!allowedModes.get('Chevron').has(mode)) return
// If the shift key is pressed
if (e.shiftKey) {
// For every macro if not null
for (const macro of pinnedMacros.filter(m => m.key)) {
// Support of all keyboards by using the key instead of the code
// Supporting "keyX" or "X" in the config + case insensitive
if (e.key.toUpperCase() === macro.key.toUpperCase() || ("key" + e.key).toUpperCase() === macro.key.toUpperCase()) {
activateCard(macro)
break
}
}
}
}
document.addEventListener('keypress', handleKeypress)
return () => document.removeEventListener('keypress', handleKeypress)
}, [mode, activateCard])
const splideOptions = {
ref: sliderRef,
tag: 'section',
extensions: { Grid },
options: {
pagination,
arrows: arrows && isSliderHasMultipleSlides,
drag: drag && isSliderHasMultipleSlides,
perPage: 1,
wheel: true,
keyboard: allowedModes.get('Slider').has(mode) ? 'global' : false,
grid: {
cols,
rows,
gap: {
col: gap + 'px',
row: gap + 'px'
}
}
}
}
return (
<div className={classes['container']}>
<Splide {...splideOptions}>
{
pinnedMacros.map(pm => {
return (
<SplideSlide key={pm.name}>
<Card
active={pm === selected && visibility && fullVisibility && isCardInFocus}
title={pm.name}
icon={pm.icon}
bgColor={pm.bgColor}
textColor={pm.textColor}
hotKey={pm.key && pm.key.slice(-1)}
isHintActive={isShiftPressed}
onClick={() => activateCard(pm)}/>
</SplideSlide>
)
})
}
</Splide>
</div>
)
}
export default memo(MacrosMenu)