diff --git a/.changeset/gold-dogs-fly.md b/.changeset/gold-dogs-fly.md new file mode 100644 index 000000000..5d4418dfa --- /dev/null +++ b/.changeset/gold-dogs-fly.md @@ -0,0 +1,5 @@ +--- +'renterd': minor +--- + +Fixed an issue where file and directory names could not contain the # symbol. diff --git a/apps/hostd/components/OnboardingBar.tsx b/apps/hostd/components/OnboardingBar.tsx index 3f66c9dc7..2d4ee6395 100644 --- a/apps/hostd/components/OnboardingBar.tsx +++ b/apps/hostd/components/OnboardingBar.tsx @@ -14,7 +14,6 @@ import { PendingFilled16, Subtract24, } from '@siafoundation/react-icons' -import { useState } from 'react' import { useSyncStatus } from '../hooks/useSyncStatus' import { routes } from '../config/routes' import { useDialog } from '../contexts/dialog' @@ -23,6 +22,7 @@ import BigNumber from 'bignumber.js' import { humanSiacoin, toHastings } from '@siafoundation/sia-js' import { useAppSettings } from '@siafoundation/react-core' import { useVolumes } from '../contexts/volumes' +import useLocalStorageState from 'use-local-storage-state' export function OnboardingBar() { const { isUnlocked } = useAppSettings() @@ -30,7 +30,12 @@ export function OnboardingBar() { const { dataset: volumes } = useVolumes() const settings = useSettings() const wallet = useWallet() - const [maximized, setMaximized] = useState(true) + const [maximized, setMaximized] = useLocalStorageState( + 'v0/hostd/onboarding/maximized', + { + defaultValue: true, + } + ) const syncStatus = useSyncStatus() if (!isUnlocked) { diff --git a/apps/renterd/components/OnboardingBar.tsx b/apps/renterd/components/OnboardingBar.tsx index f1eb1c9eb..8624e8b09 100644 --- a/apps/renterd/components/OnboardingBar.tsx +++ b/apps/renterd/components/OnboardingBar.tsx @@ -14,7 +14,6 @@ import { PendingFilled16, Subtract24, } from '@siafoundation/react-icons' -import { useState } from 'react' import { useApp } from '../contexts/app' import { useSyncStatus } from '../hooks/useSyncStatus' import { routes } from '../config/routes' @@ -24,6 +23,7 @@ import { useAutopilotConfig, useWallet } from '@siafoundation/react-renterd' import BigNumber from 'bignumber.js' import { humanSiacoin } from '@siafoundation/sia-js' import { useAppSettings } from '@siafoundation/react-core' +import useLocalStorageState from 'use-local-storage-state' export function OnboardingBar() { const { isUnlocked } = useAppSettings() @@ -37,7 +37,12 @@ export function OnboardingBar() { }, }, }) - const [maximized, setMaximized] = useState(true) + const [maximized, setMaximized] = useLocalStorageState( + 'v0/renterd/onboarding/maximized', + { + defaultValue: true, + } + ) const syncStatus = useSyncStatus() const notEnoughContracts = useNotEnoughContracts() diff --git a/apps/renterd/contexts/files/index.tsx b/apps/renterd/contexts/files/index.tsx index 83047bb92..797139a5a 100644 --- a/apps/renterd/contexts/files/index.tsx +++ b/apps/renterd/contexts/files/index.tsx @@ -25,7 +25,7 @@ function useFilesMain() { // [bucket, key, directory] const activeDirectory = useMemo( - () => (router.query.path as FullPathSegments) || [], + () => (router.query.path as FullPathSegments).map(decodeURIComponent) || [], [router.query.path] ) @@ -42,7 +42,9 @@ function useFilesMain() { const setActiveDirectory = useCallback( (fn: (activeDirectory: FullPathSegments) => FullPathSegments) => { const nextActiveDirectory = fn(activeDirectory) - router.push('/files/' + nextActiveDirectory.join('/')) + router.push( + '/files/' + nextActiveDirectory.map(encodeURIComponent).join('/') + ) }, [router, activeDirectory] ) diff --git a/apps/renterd/contexts/files/paths.spec.ts b/apps/renterd/contexts/files/paths.spec.ts index 40203fa43..299295b52 100644 --- a/apps/renterd/contexts/files/paths.spec.ts +++ b/apps/renterd/contexts/files/paths.spec.ts @@ -36,6 +36,15 @@ describe('bucketAndKeyParamsFromPath', () => { }) }) + it('works for file with hash in path', () => { + expect( + bucketAndKeyParamsFromPath('bucket/path#/to#hash/file#hash.txt') + ).toEqual({ + bucket: 'bucket', + key: 'path%23/to%23hash/file%23hash.txt', + }) + }) + it('works for directory', () => { expect(bucketAndKeyParamsFromPath('bucket/path/to/directory/')).toEqual({ bucket: 'bucket', diff --git a/apps/renterd/contexts/files/paths.ts b/apps/renterd/contexts/files/paths.ts index f3aecd754..05472bb90 100644 --- a/apps/renterd/contexts/files/paths.ts +++ b/apps/renterd/contexts/files/paths.ts @@ -35,7 +35,11 @@ export function bucketAndKeyParamsFromPath(path: FullPath): { } { return { bucket: getBucketFromPath(path), - key: getKeyFromPath(path).slice(1), + key: getKeyFromPath(path) + .slice(1) + .split('/') + .map(encodeURIComponent) + .join('/'), } }