diff --git a/package.json b/package.json index 6f8af99..cf5b66d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "wow-best-places", "description": "This app is supposed to make you feel nostalgic", - "version": "1.2.0", + "version": "1.3.0", "author": { "name": "obergodmar", "email": "obergodmar@gmail.com", diff --git a/src/app/index.tsx b/src/app/index.tsx index e7be3cb..df29eda 100644 --- a/src/app/index.tsx +++ b/src/app/index.tsx @@ -69,9 +69,13 @@ export default function App() { }) }, [isLoading]) - const handleLeftPreviewClick = (value: number) => delayedChange(setActivePlace, value) + const handleLeftPreviewClick = useCallback((value: number) => + delayedChange(setActivePlace, value), + [delayedChange]) - const handleBottomPreviewClick = (value: number) => delayedChange(setActiveView, value) + const handleBottomPreviewClick = useCallback((value: number) => + delayedChange(setActiveView, value), + [delayedChange]) useEffect(() => { if (app && app.current) { @@ -89,11 +93,12 @@ export default function App() { return } currentPlaying.setVolume(musicVolume) + currentPlaying.playMusic() }, [currentPlaying, musicVolume]) - const appClick = () => currentPlaying && currentPlaying.playMusic() + const appClick = useCallback(() => currentPlaying && currentPlaying.playMusic(), [currentPlaying]) - const openCloseSettings = () => { + const openCloseSettings = useCallback(() => { setSettingsShown(!isSettingsShown) if (app && app.current) { app.current.focus() @@ -106,9 +111,9 @@ export default function App() { } else { settingsOpenSound.playSound() } - } + }, [app, isSettingsShown, uiSound, settingsCloseSound, settingsOpenSound]) - const handleOpenSettings = (e: KeyboardEvent) => { + const handleOpenSettings = useCallback((e: KeyboardEvent) => { switch (e.keyCode) { case 27: if (isLeftPanelShown || isBottomPanelShown) { @@ -129,7 +134,7 @@ export default function App() { currentPlaying.playMusic() } } - } + }, [isLeftPanelShown, isBottomPanelShown, isPlaying, currentPlaying, openCloseSettings]) return (
- +
obergodmar - v1.2.0 + v1.3.0
{ - const handleKeyDown = (e: KeyboardEvent, option: any) => { + const handleKeyDown = useCallback((e: KeyboardEvent, option: any) => { if (e.keyCode !== 13 && e.keyCode !== 32) { return } handleClick(option) - } + }, [handleClick]) + return (
{ - const handleKeyDown = (e: KeyboardEvent) => { + const handleKeyDown = useCallback((e: KeyboardEvent) => { if (e.keyCode !== 13 && e.keyCode !== 32) { return } handleClick() - } + }, [handleClick]) return (
{ const {settings: {language, uiSound}} = useSettings() const [isDrag, setDrag] = useState(false) - const [trackMouse, setTrackMouse] = useState(0) + const [trackPosition, setTrackPosition] = useState(0) const [position, setPosition] = useState(0) const [lastPosition, setLastPosition] = useState(0) @@ -65,7 +65,7 @@ export const PanelComponent = ({ panel.current.style.transition = `transform 0.5s` } panel.current.style.transform = `unset` - setTrackMouse(0) + setTrackPosition(0) setPosition(0) setLastPosition(0) }, [panel]) @@ -123,9 +123,9 @@ export const PanelComponent = ({ } const limiter = (value: number, overflow: number, isWheel: boolean = false) => { - let diff = (!isWheel ? trackMouse : 0) - value + lastPosition - if (Math.abs(diff) > overflow + 40) { - diff = overflow + 40 + let diff = (!isWheel ? trackPosition : 0) - value + lastPosition + if (Math.abs(diff) > overflow + SPACE) { + diff = overflow + SPACE } else if (diff < 0) { diff = 0 } @@ -142,14 +142,14 @@ export const PanelComponent = ({ const handleMouseDown = (e: MouseEvent) => { const {clientX, clientY} = e e.nativeEvent.stopImmediatePropagation() - setTrackMouse(isBottom ? clientX : clientY) + setTrackPosition(isBottom ? clientX : clientY) setDrag(true) } const handleTouchstart = (e: TouchEvent) => { const {touches} = e e.nativeEvent.stopImmediatePropagation() - setTrackMouse(isBottom ? touches[0].clientX : touches[0].clientY) + setTrackPosition(isBottom ? touches[0].clientX : touches[0].clientY) setDrag(true) } @@ -180,7 +180,7 @@ export const PanelComponent = ({ return } - const value = deltaY > 0 ? 80 : -80 + const value = deltaY > 0 ? -80 : 80 const diff = limiter(value, overflow, true) setPosition(diff) changePosition() diff --git a/src/components/preview-component/preview-component.tsx b/src/components/preview-component/preview-component.tsx index fec7a57..9b9aa08 100644 --- a/src/components/preview-component/preview-component.tsx +++ b/src/components/preview-component/preview-component.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import { useEffect, useMemo, useState } from 'react' +import { useCallback, useEffect, useMemo, useState } from 'react' import { useSettings } from '../../hooks' import { Plug } from '../../assets' @@ -33,10 +33,10 @@ export const PreviewComponent = ({name = '', src, value, handleChange, isLoading } }, [image]) - const handleClick = (e: React.MouseEvent) => { + const handleClick = useCallback((e: React.MouseEvent) => { e.preventDefault() handleChange(value) - } + }, [handleChange, value]) return (
{ const stick = useRef(null) + const handleFocus = useCallback(() => setPressed(true), []) + const handleFree = useCallback(() => setPressed(false), []) + const handleKeyDown = (e: KeyboardEvent) => { if (!stick || !stick.current || !stick.current.parentNode) { return @@ -23,43 +26,57 @@ export const RangeComponent = ({handleChange, defaultValue}: Props) => { const {width} = (stick.current.parentNode as HTMLDivElement).getBoundingClientRect() switch (e.keyCode) { case 37: - if (position - 5 < 0) { - return - } - setPosition(position - 5) - handleChange(position / MAX) + const minusValue = position - 5 + const minusDiff = limiter(minusValue, width) + + setPosition(minusDiff) + handleChange(minusDiff / MAX) break case 39: - if (position + 5 > width - 35) { - return - } - setPosition(position + 5) - handleChange(position / MAX) + const plusValue = position + 5 + const plusDiff = limiter(plusValue, width) + + setPosition(plusDiff) + handleChange(plusDiff / MAX) break } } - const handleMouseDown = useCallback(() => { - setPressed(true) - }, []) - - const handleMouseUp = useCallback(() => { - setPressed(false) - }, []) - - const handleMouseMove = useCallback((e: MouseEvent) => { - if (!isPressed) { - return - } + const handlePoint = useCallback((e: React.MouseEvent | MouseEvent) => { if (!stick || !stick.current || !stick.current.parentNode) { return } const {width, left} = (stick.current.parentNode as HTMLDivElement).getBoundingClientRect() const {clientX} = e - const diff = clientX - left - 20 - if (diff > width - 35 || diff < 0) { + const value = clientX - left - 20 + const diff = limiter(value, width) + + setPosition(diff) + handleChange(diff / MAX) + }, [stick, handleChange]) + + const handleMouseMove = useCallback((e: MouseEvent) => { + if (!isPressed) { return } + handlePoint(e) + }, [isPressed, handlePoint]) + + const handleTouchMove = useCallback((e: TouchEvent) => { + if (!isPressed) { + return + } + const {touches} = e + const {clientX} = touches[0] + + if (!stick || !stick.current || !stick.current.parentNode) { + return + } + const {width, left} = (stick.current.parentNode as HTMLDivElement).getBoundingClientRect() + + const value = clientX - left - 20 + const diff = limiter(value, width) + setPosition(diff) handleChange(diff / MAX) }, [isPressed, stick, handleChange]) @@ -73,27 +90,42 @@ export const RangeComponent = ({handleChange, defaultValue}: Props) => { range.focus() const {deltaY} = e const value = position + (deltaY > 0 ? -5 : 5) - if (value > width - 35 || value < 0) { - return + const diff = limiter(value, width) + + setPosition(diff) + handleChange(diff / MAX) + } + + const limiter = (value: number, width: number) => { + let diff = value + if (diff > width - 35) { + diff = MAX + } else if (diff < 0) { + diff = 0 } - setPosition(value) - handleChange(value / MAX) + return diff } useEffect(() => { window.addEventListener('mousemove', handleMouseMove) - window.addEventListener('mouseup', handleMouseUp) + window.addEventListener('mouseup', handleFree) + window.addEventListener('touchmove', handleTouchMove) + window.addEventListener('touchend', handleFree) return () => { window.removeEventListener('mousemove', handleMouseMove) - window.removeEventListener('mouseup', handleMouseUp) + window.removeEventListener('mouseup', handleFree) + window.removeEventListener('touchmove', handleTouchMove) + window.removeEventListener('touchend', handleFree) } - }, [handleMouseMove, handleMouseUp]) + }, [handleMouseMove, handleTouchMove, handleFree]) return (
diff --git a/src/components/select-component/select-component.tsx b/src/components/select-component/select-component.tsx index 69e1f42..a8d90b4 100644 --- a/src/components/select-component/select-component.tsx +++ b/src/components/select-component/select-component.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import { FocusEvent, KeyboardEvent, useRef, useState } from 'react' +import { FocusEvent, KeyboardEvent, useCallback, useRef, useState } from 'react' import './select-component.scss' @@ -14,7 +14,7 @@ export const SelectComponent = ({children, options, current, handleChange}: Prop const [isSelectShown, setSelectShown] = useState(false) const dropDownRef = useRef(null) - const handleSelectClick = () => setSelectShown(!isSelectShown) + const handleSelectClick = useCallback(() => setSelectShown(!isSelectShown), [isSelectShown]) const handleBlur = (e: FocusEvent) => { if (!dropDownRef || !dropDownRef.current) { @@ -52,7 +52,7 @@ export const SelectComponent = ({children, options, current, handleChange}: Prop className={`select ${isSelectShown ? 'select--opened' : ''}`} > {children} -
+
{isSelectShown && (
{ const [imageSrc, setImageSrc] = useState(Background) const [isLoaded, setLoaded] = useState(false) + const [isDrag, setDrag] = useState(false) + const [trackPosition, setTrackPosition] = useState(initialPosition) + const [position, setPosition] = useState(initialPosition) + const [lastPosition, setLastPosition] = useState(initialPosition) + + const handleResize = useCallback(() => { + const {innerWidth, innerHeight} = window + + let width = (innerWidth - DEFAULT_WIDTH) / 2 + let height = (innerHeight - DEFAULT_HEIGHT) / 2 + + if (innerWidth >= DEFAULT_WIDTH) { + width = 0 + } + if (innerHeight >= DEFAULT_HEIGHT) { + height = 0 + } + setPosition({x: width, y: height}) + setLastPosition({x: width, y: height}) + }, []) useEffect(() => { + handleResize() setLoaded(false) const timer = setTimeout(() => { const image = new Image() @@ -27,16 +58,99 @@ export const ViewComponent = ({src}: Props) => { return () => { clearTimeout(timer) } - }, [src]) + }, [src, handleResize]) + + useEffect(() => { + window.addEventListener('resize', handleResize) + return () => { + window.removeEventListener('resize', handleResize) + } + }, [handleResize]) + + const handleTouchMove = (e: TouchEvent) => { + const {touches} = e + const {innerWidth, innerHeight} = window + const width = DEFAULT_WIDTH - innerWidth + const height = DEFAULT_HEIGHT - innerHeight + const {clientX: x, clientY: y} = touches[0] + + const diff = limiter({x, y}, width, height) + + setPosition(diff) + } + + const limiter = (value: Position, width: number, height: number) => { + const {x: xValue, y: yValue} = value + + let x = trackPosition.x - xValue + lastPosition.x + let y = trackPosition.y - yValue + lastPosition.y + + if (x > 0) { + x = 0 + } else if (x < -width) { + x = -width + } + + if (y > 0) { + y = 0 + } else if (y < -height) { + y = -height + } + + return ({x, y}) + } + + const handleTouchstart = (e: TouchEvent) => { + const {touches} = e + e.nativeEvent.stopImmediatePropagation() + const {clientX: x, clientY: y} = touches[0] + setTrackPosition({x, y}) + setDrag(true) + } + + const handleMouseDown = (e: MouseEvent) => { + const {clientX, clientY} = e + e.nativeEvent.stopImmediatePropagation() + setTrackPosition({x: clientX, y: clientY}) + setDrag(true) + } + + const handleFree = (e: MouseEvent | FocusEvent | TouchEvent) => { + e.nativeEvent.stopImmediatePropagation() + setDrag(false) + setLastPosition(position) + } + + const handleDragScroll = (e: MouseEvent) => { + if (!isDrag) { + return + } + const {innerWidth, innerHeight} = window + const width = DEFAULT_WIDTH - innerWidth + const height = DEFAULT_HEIGHT - innerHeight + + const {clientX: x, clientY: y} = e + const diff = limiter({x, y}, width, height) + setPosition(diff) + } return (
-
+
) } diff --git a/src/index.tsx b/src/index.tsx index 9f6ae81..c8a3bbf 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -17,7 +17,7 @@ const defaultSettings: Settings = { ReactDom.render( - + , document.getElementById('root') ) diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 3a416d8..72f6200 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -4,3 +4,6 @@ export const PREVIEW_WIDTH = 320 export const PREVIEW_HEIGHT = 180 export const UI_SOUND_VOLUME = 0.2 export const UI_MUSIC_VOLUME = 1 +export const SPACE = 200 +export const DEFAULT_WIDTH = 1920 +export const DEFAULT_HEIGHT = 1080 diff --git a/src/utils/index.ts b/src/utils/index.ts index b4d713a..c5126f8 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -7,7 +7,10 @@ export { UI_MUSIC_VOLUME, UI_SOUND_VOLUME, LOADING_DURATION, - ANIMATION_DURATION + ANIMATION_DURATION, + DEFAULT_HEIGHT, + DEFAULT_WIDTH, + SPACE } from './constants' export const delay = () => new Promise(resolve => setTimeout(resolve, LOADING_DURATION))