diff --git a/package.json b/package.json index d7098c29a..cca82ae30 100644 --- a/package.json +++ b/package.json @@ -137,7 +137,6 @@ "react-redux": "^9.0.4", "react-router-dom": "^5.3.0", "react-router-dom-v5-compat": "^6.6.2", - "react-router-scroll-4": "^1.0.0-beta.2", "react-simple-pull-to-refresh": "^1.3.3", "react-sparklines": "^1.7.0", "react-sticky-box": "^2.0.0", diff --git a/src/components/scroll-context.tsx b/src/components/scroll-context.tsx new file mode 100644 index 000000000..ad427659f --- /dev/null +++ b/src/components/scroll-context.tsx @@ -0,0 +1,24 @@ +import React, { useEffect } from 'react'; +import { useLocation } from 'react-router-dom'; + +import { usePrevious } from 'soapbox/hooks'; + +export type Location = ReturnType>; + +interface IScrollContext { + shouldUpdateScroll(prevLocation: Location | undefined, location: Location): boolean; + children: React.ReactNode; +} + +export const ScrollContext: React.FC = ({ shouldUpdateScroll, children }) => { + const location = useLocation(); + const prevLocation = usePrevious(location); + + useEffect(() => { + if (prevLocation && shouldUpdateScroll(prevLocation, location)) { + window.scrollTo(0, 0); + } + }, [location, shouldUpdateScroll]); + + return children; +}; \ No newline at end of file diff --git a/src/components/sidebar-navigation-link.tsx b/src/components/sidebar-navigation-link.tsx index 336aac5ae..e5aca128e 100644 --- a/src/components/sidebar-navigation-link.tsx +++ b/src/components/sidebar-navigation-link.tsx @@ -1,6 +1,6 @@ import clsx from 'clsx'; import React from 'react'; -import { NavLink } from 'react-router-dom'; +import { NavLink, useLocation } from 'react-router-dom'; import { Icon, Text } from './ui'; @@ -24,7 +24,9 @@ interface ISidebarNavigationLink { /** Desktop sidebar navigation link. */ const SidebarNavigationLink = React.forwardRef((props: ISidebarNavigationLink, ref: React.ForwardedRef): JSX.Element => { const { icon, activeIcon, text, to = '', count, countMax, onClick } = props; - const isActive = location.pathname === to; + const { pathname } = useLocation(); + + const isActive = pathname === to; const handleClick: React.EventHandler = (e) => { if (onClick) { diff --git a/src/features/audio/index.tsx b/src/features/audio/index.tsx index 366a6a076..61a43d89b 100644 --- a/src/features/audio/index.tsx +++ b/src/features/audio/index.tsx @@ -4,7 +4,7 @@ import throttle from 'lodash/throttle'; import React, { useEffect, useLayoutEffect, useRef, useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; -import Icon from 'soapbox/components/icon'; +import SvgIcon from 'soapbox/components/ui/icon/svg-icon'; import { formatTime, getPointerPosition } from 'soapbox/features/video'; import Visualizer from './visualizer'; @@ -64,10 +64,11 @@ const Audio: React.FC = (props) => { const [duration, setDuration] = useState(undefined); const [paused, setPaused] = useState(true); const [muted, setMuted] = useState(false); + const [preVolume, setPreVolume] = useState(0); const [volume, setVolume] = useState(0.5); const [dragging, setDragging] = useState(false); const [hovered, setHovered] = useState(false); - + const [seekHovered, setSeekHovered] = useState(false); const visualizer = useRef(new Visualizer(TICK_SIZE)); const audioContext = useRef(null); @@ -150,12 +151,20 @@ const Audio: React.FC = (props) => { }; const toggleMute = () => { - const nextMuted = !muted; - - setMuted(nextMuted); - if (audio.current) { - audio.current.muted = nextMuted; + const muted = !audio.current.muted; + setMuted(muted); + audio.current.muted = muted; + + if (muted) { + setPreVolume(audio.current.volume); + audio.current.volume = 0; + setVolume(0); + } else { + audio.current.volume = preVolume; + setVolume(preVolume); + } + } }; @@ -259,6 +268,14 @@ const Audio: React.FC = (props) => { setHovered(false); }; + const handleSeekEnter = () => { + setSeekHovered(true); + }; + + const handleSeekLeave = () => { + setSeekHovered(false); + }; + const handleLoadedData = () => { if (audio.current) { setDuration(audio.current.duration); @@ -438,7 +455,8 @@ const Audio: React.FC = (props) => { return (
= (props) => { width: '100%', height: fullscreen ? '100%' : (height || props.height), }} - onMouseEnter={handleMouseEnter} - onMouseLeave={handleMouseLeave} tabIndex={0} onKeyDown={handleKeyDown} onClick={e => e.stopPropagation()} @@ -466,7 +482,7 @@ const Audio: React.FC = (props) => { = (props) => { /> )} -
+
-
+
-
-
-
+
+
+
- +
- - {formatTime(Math.floor(currentTime))} + + {formatTime(Math.floor(currentTime))} {getDuration() && (<> - / {/* eslint-disable-line formatjs/no-literal-string-in-jsx */} - {formatTime(Math.floor(getDuration()))} + /{/* eslint-disable-line formatjs/no-literal-string-in-jsx */} + {formatTime(Math.floor(getDuration()))} )}
- diff --git a/src/features/ui/components/modals/nostr-login-modal/components/nostr-extension-indicator.tsx b/src/features/ui/components/modals/nostr-login-modal/components/nostr-extension-indicator.tsx index 33cbccc3c..3e24808f7 100644 --- a/src/features/ui/components/modals/nostr-login-modal/components/nostr-extension-indicator.tsx +++ b/src/features/ui/components/modals/nostr-login-modal/components/nostr-extension-indicator.tsx @@ -15,20 +15,38 @@ const NostrExtensionIndicator: React.FC = () => { dispatch(closeModal()); }; + function renderBody(): React.ReactNode { + if (window.nostr && window.nostr.nip44) { + return ( + , + }} + /> + ); + } else if (window.nostr) { + return ( + + ); + } else { + return ( + + ); + } + } + return ( - {window.nostr ? ( - , - }} - /> - ) : ( - - )} + {renderBody()} ); diff --git a/src/features/video/index.tsx b/src/features/video/index.tsx index 028c1188a..438e84378 100644 --- a/src/features/video/index.tsx +++ b/src/features/video/index.tsx @@ -400,7 +400,7 @@ const Video: React.FC = ({ const toggleMute = () => { if (video.current) { const muted = !video.current.muted; - setMuted(!muted); + setMuted(muted); video.current.muted = muted; if (muted) { diff --git a/src/init/soapbox-mount.tsx b/src/init/soapbox-mount.tsx index 71942395c..ea365031f 100644 --- a/src/init/soapbox-mount.tsx +++ b/src/init/soapbox-mount.tsx @@ -2,12 +2,11 @@ import React, { Suspense, useEffect } from 'react'; import { Toaster } from 'react-hot-toast'; import { BrowserRouter, Switch, Redirect, Route } from 'react-router-dom'; import { CompatRouter } from 'react-router-dom-v5-compat'; -// @ts-ignore: it doesn't have types -import { ScrollContext } from 'react-router-scroll-4'; import { openModal } from 'soapbox/actions/modals'; import * as BuildConfig from 'soapbox/build-config'; import LoadingScreen from 'soapbox/components/loading-screen'; +import { Location, ScrollContext } from 'soapbox/components/scroll-context'; import SiteErrorBoundary from 'soapbox/components/site-error-boundary'; import { ModalContainer, @@ -25,6 +24,10 @@ const GdprBanner = React.lazy(() => import('soapbox/components/gdpr-banner')); const EmbeddedStatus = React.lazy(() => import('soapbox/features/embedded-status')); const UI = React.lazy(() => import('soapbox/features/ui')); +interface LocationState { + soapboxModalKey?: string; +} + /** Highest level node with the Redux store. */ const SoapboxMount = () => { useCachedLocationHandler(); @@ -51,10 +54,9 @@ const SoapboxMount = () => { const { redirectRootNoLogin, gdpr } = soapboxConfig; - // @ts-ignore: I don't actually know what these should be, lol - const shouldUpdateScroll = (prevRouterProps, { location }) => { - return !(location.state?.soapboxModalKey && location.state?.soapboxModalKey !== prevRouterProps?.location?.state?.soapboxModalKey); - }; + function shouldUpdateScroll(prev: Location | undefined, location: Location): boolean { + return !(location.state?.soapboxModalKey && location.state?.soapboxModalKey !== prev?.state?.soapboxModalKey); + } return ( diff --git a/src/locales/en.json b/src/locales/en.json index 541cddd3f..d75c5c114 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1167,6 +1167,7 @@ "new_group_panel.title": "Create Group", "nostr_extension.found": "Sign in with browser extension.", "nostr_extension.not_found": "Browser extension not found.", + "nostr_extension.not_supported": "Browser extension not supported. Please upgrade to the latest version.", "nostr_login.siwe.action": "Log in with extension", "nostr_login.siwe.alt": "Log in with key", "nostr_login.siwe.sign_up": "Sign Up", diff --git a/src/utils/features.ts b/src/utils/features.ts index d30905225..8a9b2b8dd 100644 --- a/src/utils/features.ts +++ b/src/utils/features.ts @@ -988,6 +988,7 @@ const getInstanceFeatures = (instance: InstanceV1 | InstanceV2) => { v.software === ICESHRIMP, v.software === MASTODON && gte(v.version, '2.8.0'), v.software === PLEROMA && gte(v.version, '1.0.0'), + v.software === DITTO, ]), /** diff --git a/yarn.lock b/yarn.lock index f44a44aae..52938252f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5516,13 +5516,6 @@ intl-pluralrules@^2.0.0: resolved "https://registry.yarnpkg.com/intl-pluralrules/-/intl-pluralrules-2.0.1.tgz#de16c3df1e09437635829725e88ea70c9ad79569" integrity sha512-astxTLzIdXPeN0K9Rumi6LfMpm3rvNO0iJE+h/k8Kr/is+wPbRe4ikyDjlLr6VTh/mEfNv8RjN+gu3KwDiuhqg== -invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" @@ -7363,14 +7356,6 @@ react-router-dom@^5.3.0: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-router-scroll-4@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.yarnpkg.com/react-router-scroll-4/-/react-router-scroll-4-1.0.0-beta.2.tgz#d887063ec0f66124aaf450158dd158ff7d3dc279" - integrity sha512-K67Dnm75naSBs/WYc2CDNxqU+eE8iA3I0wSCArgGSHb0xR/7AUcgUEXtCxrQYVTogXvjVK60gmwYvOyRQ6fuBA== - dependencies: - scroll-behavior "^0.9.1" - warning "^3.0.0" - react-router@5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.1.tgz#4d2e4e9d5ae9425091845b8dbc6d9d276239774d" @@ -7817,14 +7802,6 @@ schema-utils@^4.0.0: ajv-formats "^2.1.1" ajv-keywords "^5.0.0" -scroll-behavior@^0.9.1: - version "0.9.12" - resolved "https://registry.yarnpkg.com/scroll-behavior/-/scroll-behavior-0.9.12.tgz#1c22d273ec4ce6cd4714a443fead50227da9424c" - integrity sha512-18sirtyq1P/VsBX6O/vgw20Np+ngduFXEMO4/NDFXabdOKBL2kjPVUpz1y0+jm99EWwFJafxf5/tCyMeXt9Xyg== - dependencies: - dom-helpers "^3.4.0" - invariant "^2.2.4" - semver-compare@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"