fix: link_randomuuid_cache (#718)
* fix: [SPDV-828] use react router link instead of href * fix: auto import issue * fix: replace randomuuid with getRandomValues= * fix: reset FM states if state is invalid * fix: use no-cache for stamp fetch * fix: clear cache and reload message * fix: shallReset flag * fix: identify browser platform and set help url accordingly * fix: edge browser detection * fix: use fallback chrome and verify for safari --------- Co-authored-by: Nandor Komlodi <nandor.komlodi@gmail.com> Co-authored-by: Balint Ujvari <balint.ujvari@solarpunk.buzz>
This commit is contained in:
@@ -12,6 +12,7 @@ import { UpgradeDriveModal } from '../UpgradeDriveModal/UpgradeDriveModal'
|
|||||||
import { UpgradeTimeoutModal } from '../UpgradeTimeoutModal/UpgradeTimeoutModal'
|
import { UpgradeTimeoutModal } from '../UpgradeTimeoutModal/UpgradeTimeoutModal'
|
||||||
import { FILE_MANAGER_EVENTS, POLLING_TIMEOUT_MS } from '../../constants/common'
|
import { FILE_MANAGER_EVENTS, POLLING_TIMEOUT_MS } from '../../constants/common'
|
||||||
import { useStampPolling } from '../../hooks/useStampPolling'
|
import { useStampPolling } from '../../hooks/useStampPolling'
|
||||||
|
import { TOOLTIPS } from '../../constants/tooltips'
|
||||||
|
|
||||||
interface AdminStatusBarProps {
|
interface AdminStatusBarProps {
|
||||||
adminStamp: PostageBatch | null
|
adminStamp: PostageBatch | null
|
||||||
@@ -226,10 +227,7 @@ export function AdminStatusBar({
|
|||||||
|
|
||||||
<div>File Manager Available: Until: {expiresAt}</div>
|
<div>File Manager Available: Until: {expiresAt}</div>
|
||||||
|
|
||||||
<Tooltip
|
<Tooltip label={TOOLTIPS.ADMIN_STATUS_WARNING} />
|
||||||
label="The File Manager works only while your storage remains valid. If it expires, all catalogue metadata is
|
|
||||||
permanently lost."
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{renderModalsAndOverlays()}
|
{renderModalsAndOverlays()}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { useState, ReactElement, useEffect } from 'react'
|
|||||||
import './PrivateKeyModal.scss'
|
import './PrivateKeyModal.scss'
|
||||||
import { Button } from '../Button/Button'
|
import { Button } from '../Button/Button'
|
||||||
import { setSignerPk, getSigner } from '../../utils/common'
|
import { setSignerPk, getSigner } from '../../utils/common'
|
||||||
|
import { uuidV4 } from '../../../../utils'
|
||||||
import { PrivateKey } from '@ethersphere/bee-js'
|
import { PrivateKey } from '@ethersphere/bee-js'
|
||||||
import ClipboardIcon from 'remixicon-react/FileCopyLineIcon'
|
import ClipboardIcon from 'remixicon-react/FileCopyLineIcon'
|
||||||
import CheckDoubleLineIcon from 'remixicon-react/CheckDoubleLineIcon'
|
import CheckDoubleLineIcon from 'remixicon-react/CheckDoubleLineIcon'
|
||||||
@@ -31,7 +32,7 @@ export function PrivateKeyModal({ onSaved }: Props): ReactElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleGenerateNew = () => {
|
const handleGenerateNew = () => {
|
||||||
const id = crypto.randomUUID()
|
const id = uuidV4()
|
||||||
const signer = getSigner(id)
|
const signer = getSigner(id)
|
||||||
const privKey = signer.toHex()
|
const privKey = signer.toHex()
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ This action will do two things:
|
|||||||
ADMIN_PURCHASE_BUTTON_ALREADY_EXISTED_ADMIN_DRIVE: `${getTitleWithStyle('Create Admin Drive')}
|
ADMIN_PURCHASE_BUTTON_ALREADY_EXISTED_ADMIN_DRIVE: `${getTitleWithStyle('Create Admin Drive')}
|
||||||
|
|
||||||
It will create the Admin Drive.`,
|
It will create the Admin Drive.`,
|
||||||
|
ADMIN_STATUS_WARNING:
|
||||||
|
'The File Manager works only while your storage remains valid. If it expires, all catalogue metadata is permanently lost.',
|
||||||
|
|
||||||
// Drive Creation
|
// Drive Creation
|
||||||
DRIVE_NAME: `${getTitleWithStyle('About Drive Name')}
|
DRIVE_NAME: `${getTitleWithStyle('About Drive Name')}
|
||||||
|
|||||||
@@ -172,6 +172,7 @@ export const handleCreateDrive = async (options: CreateDriveOptions): Promise<vo
|
|||||||
|
|
||||||
batchId = await beeApi.buyStorage(size, duration, { label }, undefined, encryption, redundancyLevel)
|
batchId = await beeApi.buyStorage(size, duration, { label }, undefined, encryption, redundancyLevel)
|
||||||
} else {
|
} else {
|
||||||
|
// TODO: redundant, fm checks for stamp validtiy
|
||||||
const isValid = await validateStampStillExists(beeApi, existingBatch.batchID)
|
const isValid = await validateStampStillExists(beeApi, existingBatch.batchID)
|
||||||
|
|
||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { AdminStatusBar } from '../../modules/filemanager/components/AdminStatus
|
|||||||
import { FileBrowser } from '../../modules/filemanager/components/FileBrowser/FileBrowser'
|
import { FileBrowser } from '../../modules/filemanager/components/FileBrowser/FileBrowser'
|
||||||
import { InitialModal } from '../../modules/filemanager/components/InitialModal/InitialModal'
|
import { InitialModal } from '../../modules/filemanager/components/InitialModal/InitialModal'
|
||||||
import { Context as FMContext } from '../../providers/FileManager'
|
import { Context as FMContext } from '../../providers/FileManager'
|
||||||
|
import { BrowserPlatform, cacheClearUrls, detectBrowser } from '../../providers/Platform'
|
||||||
import { Context as SettingsContext } from '../../providers/Settings'
|
import { Context as SettingsContext } from '../../providers/Settings'
|
||||||
import { Context as BeeContext, CheckState } from '../../providers/Bee'
|
import { Context as BeeContext, CheckState } from '../../providers/Bee'
|
||||||
import { PrivateKeyModal } from '../../modules/filemanager/components/PrivateKeyModal/PrivateKeyModal'
|
import { PrivateKeyModal } from '../../modules/filemanager/components/PrivateKeyModal/PrivateKeyModal'
|
||||||
@@ -28,6 +29,7 @@ export function FileManagerPage(): ReactElement {
|
|||||||
const [showResetModal, setShowResetModal] = useState<boolean>(false)
|
const [showResetModal, setShowResetModal] = useState<boolean>(false)
|
||||||
const [isCreationInProgress, setIsCreationInProgress] = useState<boolean>(false)
|
const [isCreationInProgress, setIsCreationInProgress] = useState<boolean>(false)
|
||||||
const [showConnectionError, setShowConnectionError] = useState<boolean>(false)
|
const [showConnectionError, setShowConnectionError] = useState<boolean>(false)
|
||||||
|
const [cacheHelpUrl, setCacheHelpUrl] = useState<string>(cacheClearUrls[BrowserPlatform.Chrome])
|
||||||
|
|
||||||
const { status } = useContext(BeeContext)
|
const { status } = useContext(BeeContext)
|
||||||
const { beeApi } = useContext(SettingsContext)
|
const { beeApi } = useContext(SettingsContext)
|
||||||
@@ -36,6 +38,13 @@ export function FileManagerPage(): ReactElement {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
isMountedRef.current = true
|
isMountedRef.current = true
|
||||||
|
|
||||||
|
const getBrowserPlatform = async () => {
|
||||||
|
const browserPlatform = await detectBrowser()
|
||||||
|
setCacheHelpUrl(cacheClearUrls[browserPlatform])
|
||||||
|
}
|
||||||
|
|
||||||
|
getBrowserPlatform()
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
isMountedRef.current = false
|
isMountedRef.current = false
|
||||||
}
|
}
|
||||||
@@ -162,8 +171,21 @@ export function FileManagerPage(): ReactElement {
|
|||||||
<div className="fm-main">
|
<div className="fm-main">
|
||||||
<ConfirmModal
|
<ConfirmModal
|
||||||
title="Reset File Manager State"
|
title="Reset File Manager State"
|
||||||
message="Your File Manager state appears invalid. Please reset it to continue."
|
message={
|
||||||
confirmLabel="Proceed"
|
<span>
|
||||||
|
Your File Manager state appears invalid. Please{' '}
|
||||||
|
<a
|
||||||
|
href={cacheHelpUrl}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
style={{ display: 'inline', textDecoration: 'underline' }}
|
||||||
|
>
|
||||||
|
clear the browser cache
|
||||||
|
</a>{' '}
|
||||||
|
and reload the page. Then you can reset the File Manager to continue.
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
confirmLabel="Continue"
|
||||||
onConfirm={() => {
|
onConfirm={() => {
|
||||||
setShowResetModal(false)
|
setShowResetModal(false)
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
import { ReactElement } from 'react'
|
import { ReactElement } from 'react'
|
||||||
import { HistoryHeader } from '../../components/HistoryHeader'
|
import { HistoryHeader } from '../../components/HistoryHeader'
|
||||||
import { Typography } from '@material-ui/core'
|
import { Typography } from '@material-ui/core'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
|
import { ROUTES } from '../../routes'
|
||||||
|
|
||||||
export default function PageNotFound(): ReactElement {
|
export default function PageNotFound(): ReactElement {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<HistoryHeader>Page not found</HistoryHeader>
|
<HistoryHeader>Page not found</HistoryHeader>
|
||||||
<Typography>
|
<Typography>
|
||||||
The given url is invalid. Please go back or <a href="/">navigate to Home screen.</a>
|
The given url is invalid. Please go back or <Link to={ROUTES.INFO}>navigate to Home screen.</Link>
|
||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ import { FileManagerBase, FileManagerEvents } from '@solarpunkltd/file-manager-l
|
|||||||
import { Context as SettingsContext } from './Settings'
|
import { Context as SettingsContext } from './Settings'
|
||||||
import { DriveInfo } from '@solarpunkltd/file-manager-lib'
|
import { DriveInfo } from '@solarpunkltd/file-manager-lib'
|
||||||
import { getSignerPk } from '../modules/filemanager/utils/common'
|
import { getSignerPk } from '../modules/filemanager/utils/common'
|
||||||
import { getUsableStamps } from '../../src/modules/filemanager/utils/bee'
|
|
||||||
import { FILE_MANAGER_EVENTS } from '../modules/filemanager/constants/common'
|
import { FILE_MANAGER_EVENTS } from '../modules/filemanager/constants/common'
|
||||||
|
import { getUsableStamps } from '../modules/filemanager/utils/bee'
|
||||||
|
|
||||||
interface ContextInterface {
|
interface ContextInterface {
|
||||||
fm: FileManagerBase | null
|
fm: FileManagerBase | null
|
||||||
@@ -256,6 +256,12 @@ export function Provider({ children }: Props) {
|
|||||||
|
|
||||||
const handleResetState = (isInvalid: boolean) => {
|
const handleResetState = (isInvalid: boolean) => {
|
||||||
setShallReset(isInvalid)
|
setShallReset(isInvalid)
|
||||||
|
setFiles([])
|
||||||
|
setDrives([])
|
||||||
|
setExpiredDrives([])
|
||||||
|
setAdminDrive(null)
|
||||||
|
setCurrentDrive(undefined)
|
||||||
|
setCurrentStamp(undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
manager.emitter.on(FileManagerEvents.STATE_INVALID, handleResetState)
|
manager.emitter.on(FileManagerEvents.STATE_INVALID, handleResetState)
|
||||||
|
|||||||
@@ -55,6 +55,42 @@ function getOS(): Platforms | null {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum BrowserPlatform {
|
||||||
|
Chrome = 'chrome',
|
||||||
|
Firefox = 'firefox',
|
||||||
|
Safari = 'safari',
|
||||||
|
Brave = 'brave',
|
||||||
|
Edge = 'edge',
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function isBraveBrowser(): Promise<boolean> {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
return (window.navigator.brave && (await window.navigator.brave.isBrave())) === true
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function detectBrowser(): Promise<BrowserPlatform> {
|
||||||
|
const ua = window.navigator.userAgent.toLowerCase()
|
||||||
|
|
||||||
|
if (ua.includes('edge') || ua.includes('edg/')) return BrowserPlatform.Edge
|
||||||
|
|
||||||
|
if (ua.includes('chrome') && (await isBraveBrowser())) return BrowserPlatform.Brave
|
||||||
|
|
||||||
|
if (ua.includes('firefox')) return BrowserPlatform.Firefox
|
||||||
|
|
||||||
|
if (ua.includes('safari') && !ua.includes('chrome')) return BrowserPlatform.Safari
|
||||||
|
|
||||||
|
return BrowserPlatform.Chrome
|
||||||
|
}
|
||||||
|
|
||||||
|
export const cacheClearUrls = {
|
||||||
|
chrome: 'https://support.google.com/accounts/answer/32050?hl=en&co=GENIE.Platform%3DDesktop',
|
||||||
|
brave: 'https://support.brave.app/hc/en-us/articles/360048833872-How-Do-I-Clear-Cookies-And-Site-Data-In-Brave',
|
||||||
|
firefox: 'https://support.mozilla.org/en-US/kb/how-clear-firefox-cache',
|
||||||
|
safari: 'https://support.apple.com/en-il/guide/safari/sfri47acf5d6/mac',
|
||||||
|
edge: 'https://support.microsoft.com/en-us/microsoft-edge/view-and-delete-browser-history-in-microsoft-edge-00cf7943-a9e1-975a-a33d-ac10ce454ca4',
|
||||||
|
}
|
||||||
|
|
||||||
export function Provider({ children }: Props): ReactElement {
|
export function Provider({ children }: Props): ReactElement {
|
||||||
const [platform, setPlatform] = useState<SupportedPlatforms>(SupportedPlatforms.Linux)
|
const [platform, setPlatform] = useState<SupportedPlatforms>(SupportedPlatforms.Linux)
|
||||||
|
|
||||||
|
|||||||
@@ -211,6 +211,7 @@ interface Options {
|
|||||||
timeout?: number
|
timeout?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: merge this with FM component getUsableStamps()
|
||||||
export function waitUntilStampUsable(batchId: BatchId | string, bee: Bee, options?: Options): Promise<PostageBatch> {
|
export function waitUntilStampUsable(batchId: BatchId | string, bee: Bee, options?: Options): Promise<PostageBatch> {
|
||||||
return waitForStamp(batchId, bee, options)
|
return waitForStamp(batchId, bee, options)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user