feat: allow to load client without free space on device (or no write permissions)
This commit is contained in:
parent
52ae41a78d
commit
edad57a225
5 changed files with 31 additions and 7 deletions
|
|
@ -14,22 +14,41 @@ import { VALID_REPLAY_EXTENSIONS, openFile } from './packetsReplay/replayPackets
|
|||
import { getFixedFilesize } from './downloadAndOpenFile'
|
||||
import { packetsReplayState } from './react/state/packetsReplayState'
|
||||
import { createFullScreenProgressReporter } from './core/progressReporter'
|
||||
import { showNotification } from './react/NotificationProvider'
|
||||
const { GoogleDriveFileSystem } = require('google-drive-browserfs/src/backends/GoogleDrive')
|
||||
|
||||
browserfs.install(window)
|
||||
const defaultMountablePoints = {
|
||||
'/world': { fs: 'LocalStorage' }, // will be removed in future
|
||||
'/data': { fs: 'IndexedDB' },
|
||||
'/resourcepack': { fs: 'InMemory' }, // temporary storage for currently loaded resource pack
|
||||
'/temp': { fs: 'InMemory' }
|
||||
}
|
||||
const fallbackMountablePoints = {
|
||||
'/resourcepack': { fs: 'InMemory' }, // temporary storage for downloaded server resource pack
|
||||
'/temp': { fs: 'InMemory' }
|
||||
}
|
||||
browserfs.configure({
|
||||
fs: 'MountableFileSystem',
|
||||
options: defaultMountablePoints,
|
||||
}, async (e) => {
|
||||
// todo disable singleplayer button
|
||||
if (e) throw e
|
||||
if (e) {
|
||||
browserfs.configure({
|
||||
fs: 'MountableFileSystem',
|
||||
options: fallbackMountablePoints,
|
||||
}, async (e2) => {
|
||||
if (e2) {
|
||||
showNotification('Unknown FS error, cannot continue', e2.message, true)
|
||||
throw e2
|
||||
}
|
||||
showNotification('Failed to access device storage', `Check you have free space. ${e.message}`, true)
|
||||
miscUiState.appLoaded = true
|
||||
miscUiState.singleplayerAvailable = false
|
||||
})
|
||||
return
|
||||
}
|
||||
await updateTexturePackInstalledState()
|
||||
miscUiState.appLoaded = true
|
||||
miscUiState.singleplayerAvailable = true
|
||||
})
|
||||
|
||||
export const forceCachedDataPaths = {}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ async function handleDroppedFile (file: File) {
|
|||
return
|
||||
}
|
||||
if (file.name.endsWith('.mca')) {
|
||||
const tempPath = '/data/temp.mca'
|
||||
const tempPath = '/temp/temp.mca'
|
||||
try {
|
||||
await fs.promises.writeFile(tempPath, Buffer.from(await file.arrayBuffer()) as any)
|
||||
const region = new RegionFile(tempPath)
|
||||
|
|
|
|||
|
|
@ -145,6 +145,7 @@ export const miscUiState = proxy({
|
|||
/** currently trying to load or loaded mc version, after all data is loaded */
|
||||
loadedDataVersion: null as string | null,
|
||||
appLoaded: false,
|
||||
singleplayerAvailable: false,
|
||||
usingGamepadInput: false,
|
||||
appConfig: null as AppConfig | null,
|
||||
displaySearchInput: false,
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ interface Props {
|
|||
bottomRightLinks?: string
|
||||
versionText?: string
|
||||
onVersionTextClick?: () => void
|
||||
singleplayerAvailable?: boolean
|
||||
}
|
||||
|
||||
const httpsRegex = /^https?:\/\//
|
||||
|
|
@ -41,7 +42,8 @@ export default ({
|
|||
versionStatus,
|
||||
versionTitle,
|
||||
onVersionStatusClick,
|
||||
bottomRightLinks
|
||||
bottomRightLinks,
|
||||
singleplayerAvailable = true
|
||||
}: Props) => {
|
||||
if (!bottomRightLinks?.trim()) bottomRightLinks = undefined
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
|
|
@ -107,6 +109,7 @@ export default ({
|
|||
style={{ width: 150 }}
|
||||
{...singleplayerLongPress}
|
||||
data-test-id='singleplayer-button'
|
||||
disabled={!singleplayerAvailable}
|
||||
initialTooltip={{
|
||||
content: 'Create worlds and play offline',
|
||||
placement: 'left',
|
||||
|
|
@ -183,7 +186,7 @@ export default ({
|
|||
</div>
|
||||
})}
|
||||
</div>
|
||||
<span>A Minecraft client in the browser!</span>
|
||||
<span>A Minecraft client clone in the browser!</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ export const mainMenuState = proxy({
|
|||
let disableAnimation = false
|
||||
export default () => {
|
||||
const haveModals = useSnapshot(activeModalStack).length
|
||||
const { gameLoaded, appLoaded, appConfig } = useSnapshot(miscUiState)
|
||||
const { gameLoaded, appLoaded, appConfig, singleplayerAvailable } = useSnapshot(miscUiState)
|
||||
|
||||
const noDisplay = haveModals || gameLoaded || !appLoaded
|
||||
|
||||
|
|
@ -118,6 +118,7 @@ export default () => {
|
|||
return <Transition in={!noDisplay} timeout={disableAnimation ? 0 : 100} mountOnEnter unmountOnExit>
|
||||
{(state) => <div style={{ transition: state === 'exiting' || disableAnimation ? '' : '100ms opacity ease-in', ...state === 'entered' ? { opacity: 1 } : { opacity: 0 } }}>
|
||||
<MainMenu
|
||||
singleplayerAvailable={singleplayerAvailable}
|
||||
connectToServerAction={() => showModal({ reactType: 'serversList' })}
|
||||
singleplayerAction={async () => {
|
||||
const oldFormatSave = fs.existsSync('./world/level.dat')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue