@@ -3,19 +3,21 @@ import { useSnapshot } from 'valtio'
33import { openURL } from 'renderer/viewer/lib/simpleUtils'
44import { noCase } from 'change-case'
55import { gameAdditionalState , miscUiState , openOptionsMenu , showModal } from './globalState'
6- import { AppOptions , options } from './optionsStorage'
6+ import { AppOptions , getChangedSettings , options , resetOptions } from './optionsStorage'
77import Button from './react/Button'
88import { OptionMeta , OptionSlider } from './react/OptionsItems'
99import Slider from './react/Slider'
1010import { getScreenRefreshRate } from './utils'
1111import { setLoadingScreenStatus } from './appStatus'
12- import { openFilePicker , resetLocalStorageWithoutWorld } from './browserfs'
12+ import { openFilePicker , resetLocalStorage } from './browserfs'
1313import { completeResourcepackPackInstall , getResourcePackNames , resourcePackState , uninstallResourcePack } from './resourcePack'
1414import { downloadPacketsReplay , packetsRecordingState } from './packetsReplay/packetsReplayLegacy'
15- import { showOptionsModal } from './react/SelectOption'
15+ import { showInputsModal , showOptionsModal } from './react/SelectOption'
1616import supportedVersions from './supportedVersions.mjs'
1717import { getVersionAutoSelect } from './connect'
1818import { createNotificationProgressReporter } from './core/progressReporter'
19+ import { customKeymaps } from './controls'
20+ import { appStorage } from './react/appStorageProvider'
1921
2022export const guiOptionsScheme : {
2123 [ t in OptionsGroupType ] : Array < { [ K in keyof AppOptions ] ?: Partial < OptionMeta < AppOptions [ K ] > > } & { custom ? } >
@@ -450,16 +452,31 @@ export const guiOptionsScheme: {
450452 return < Button
451453 inScreen
452454 onClick = { ( ) => {
453- if ( confirm ( 'Are you sure you want to reset all settings?' ) ) resetLocalStorageWithoutWorld ( )
455+ if ( confirm ( 'Are you sure you want to reset all settings?' ) ) resetOptions ( )
454456 } }
455- > Reset all settings</ Button >
457+ > Reset settings</ Button >
458+ } ,
459+ } ,
460+ {
461+ custom ( ) {
462+ return < Button
463+ inScreen
464+ onClick = { ( ) => {
465+ if ( confirm ( 'Are you sure you want to remove all data (settings, keybindings, servers, username, auth, proxies)?' ) ) resetLocalStorage ( )
466+ } }
467+ > Remove all data</ Button >
456468 } ,
457469 } ,
458470 {
459471 custom ( ) {
460472 return < Category > Developer</ Category >
461473 } ,
462474 } ,
475+ {
476+ custom ( ) {
477+ return < Button label = 'Export/Import...' onClick = { ( ) => openOptionsMenu ( 'export-import' ) } inScreen />
478+ }
479+ } ,
463480 {
464481 custom ( ) {
465482 const { active } = useSnapshot ( packetsRecordingState )
@@ -521,8 +538,91 @@ export const guiOptionsScheme: {
521538 } ,
522539 } ,
523540 ] ,
541+ 'export-import' : [
542+ {
543+ custom ( ) {
544+ return < Category > Export/Import Data</ Category >
545+ }
546+ } ,
547+ {
548+ custom ( ) {
549+ return < Button
550+ inScreen
551+ disabled = { true }
552+ onClick = { ( ) => { } }
553+ > Import Data</ Button >
554+ }
555+ } ,
556+ {
557+ custom ( ) {
558+ return < Button
559+ inScreen
560+ onClick = { async ( ) => {
561+ const data = await showInputsModal ( 'Export Profile' , {
562+ profileName : {
563+ type : 'text' ,
564+ } ,
565+ exportSettings : {
566+ type : 'checkbox' ,
567+ defaultValue : true ,
568+ } ,
569+ exportKeybindings : {
570+ type : 'checkbox' ,
571+ defaultValue : true ,
572+ } ,
573+ exportServers : {
574+ type : 'checkbox' ,
575+ defaultValue : true ,
576+ } ,
577+ saveUsernameAndProxy : {
578+ type : 'checkbox' ,
579+ defaultValue : true ,
580+ } ,
581+ } )
582+ const fileName = `${ data . profileName ? `${ data . profileName } -` : '' } web-client-profile.json`
583+ const json = {
584+ _about : 'Minecraft Web Client (mcraft.fun) Profile' ,
585+ ...data . exportSettings ? {
586+ options : getChangedSettings ( ) ,
587+ } : { } ,
588+ ...data . exportKeybindings ? {
589+ keybindings : customKeymaps ,
590+ } : { } ,
591+ ...data . saveUsernameAndProxy ? {
592+ username : appStorage . username ,
593+ proxy : appStorage . proxiesData ?. selected ,
594+ } : { } ,
595+ }
596+ const blob = new Blob ( [ JSON . stringify ( json , null , 2 ) ] , { type : 'application/json' } )
597+ const url = URL . createObjectURL ( blob )
598+ const a = document . createElement ( 'a' )
599+ a . href = url
600+ a . download = fileName
601+ a . click ( )
602+ URL . revokeObjectURL ( url )
603+ } }
604+ > Export Data</ Button >
605+ }
606+ } ,
607+ {
608+ custom ( ) {
609+ return < Button
610+ inScreen
611+ disabled
612+ > Export Worlds</ Button >
613+ }
614+ } ,
615+ {
616+ custom ( ) {
617+ return < Button
618+ inScreen
619+ disabled
620+ > Export Resource Pack</ Button >
621+ }
622+ }
623+ ] ,
524624}
525- export type OptionsGroupType = 'main' | 'render' | 'interface' | 'controls' | 'sound' | 'advanced' | 'VR'
625+ export type OptionsGroupType = 'main' | 'render' | 'interface' | 'controls' | 'sound' | 'advanced' | 'VR' | 'export-import'
526626
527627const Category = ( { children } ) => < div style = { {
528628 fontSize : 9 ,
0 commit comments