mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-24 01:03:50 +02:00
Backup/restore VRC registry
This commit is contained in:
300
html/src/app.js
300
html/src/app.js
@@ -5267,6 +5267,7 @@ speechSynthesis.getVoices();
|
||||
this.refreshCustomCss();
|
||||
this.refreshCustomScript();
|
||||
this.checkVRChatDebugLogging();
|
||||
this.checkAutoBackupRestoreVrcRegistry();
|
||||
this.migrateStoredUsers();
|
||||
this.$nextTick(function () {
|
||||
this.$el.style.display = '';
|
||||
@@ -14553,6 +14554,16 @@ speechSynthesis.getVoices();
|
||||
this.autoStateChange
|
||||
);
|
||||
};
|
||||
$app.data.vrcRegistryAutoBackup = configRepository.getBool(
|
||||
'VRCX_vrcRegistryAutoBackup',
|
||||
true
|
||||
);
|
||||
$app.methods.saveVrcRegistryAutoBackup = function () {
|
||||
configRepository.setBool(
|
||||
'VRCX_vrcRegistryAutoBackup',
|
||||
this.vrcRegistryAutoBackup
|
||||
);
|
||||
};
|
||||
$app.data.orderFriendsGroup0 = configRepository.getBool(
|
||||
'orderFriendGroup0',
|
||||
true
|
||||
@@ -23850,11 +23861,14 @@ speechSynthesis.getVoices();
|
||||
var D = this.VRCXUpdateDialog;
|
||||
var url = this.branches[this.branch].urlReleases;
|
||||
this.checkingForVRCXUpdate = true;
|
||||
var response = await webApiService.execute({
|
||||
url,
|
||||
method: 'GET'
|
||||
});
|
||||
this.checkingForVRCXUpdate = false;
|
||||
try {
|
||||
var response = await webApiService.execute({
|
||||
url,
|
||||
method: 'GET'
|
||||
});
|
||||
} finally {
|
||||
this.checkingForVRCXUpdate = false;
|
||||
}
|
||||
var json = JSON.parse(response.data);
|
||||
if (this.debugWebRequests) {
|
||||
console.log(json, response);
|
||||
@@ -23919,12 +23933,15 @@ speechSynthesis.getVoices();
|
||||
}
|
||||
var url = this.branches[this.branch].urlLatest;
|
||||
this.checkingForVRCXUpdate = true;
|
||||
var response = await webApiService.execute({
|
||||
url,
|
||||
method: 'GET'
|
||||
});
|
||||
try {
|
||||
var response = await webApiService.execute({
|
||||
url,
|
||||
method: 'GET'
|
||||
});
|
||||
} finally {
|
||||
this.checkingForVRCXUpdate = false;
|
||||
}
|
||||
this.pendingVRCXUpdate = false;
|
||||
this.checkingForVRCXUpdate = false;
|
||||
var json = JSON.parse(response.data);
|
||||
if (this.debugWebRequests) {
|
||||
console.log(json, response);
|
||||
@@ -27667,7 +27684,6 @@ speechSynthesis.getVoices();
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// group members
|
||||
|
||||
@@ -28441,6 +28457,268 @@ speechSynthesis.getVoices();
|
||||
});
|
||||
};
|
||||
|
||||
// #endregion
|
||||
// #region | Dialog: registry backup dialog
|
||||
|
||||
$app.data.registryBackupDialog = {
|
||||
visible: false
|
||||
};
|
||||
|
||||
$app.data.registryBackupTable = {
|
||||
data: [],
|
||||
tableProps: {
|
||||
stripe: true,
|
||||
size: 'mini',
|
||||
defaultSort: {
|
||||
prop: 'date',
|
||||
order: 'descending'
|
||||
}
|
||||
},
|
||||
layout: 'table'
|
||||
};
|
||||
|
||||
$app.methods.showRegistryBackupDialog = function () {
|
||||
this.$nextTick(() =>
|
||||
adjustDialogZ(this.$refs.registryBackupDialog.$el)
|
||||
);
|
||||
var D = this.registryBackupDialog;
|
||||
D.visible = true;
|
||||
this.updateRegistryBackupDialog();
|
||||
};
|
||||
|
||||
$app.methods.updateRegistryBackupDialog = function () {
|
||||
var D = this.registryBackupDialog;
|
||||
this.registryBackupTable.data = [];
|
||||
if (!D.visible) {
|
||||
return;
|
||||
}
|
||||
var backupsJson = configRepository.getString(
|
||||
'VRCX_VRChatRegistryBackups'
|
||||
);
|
||||
if (!backupsJson) {
|
||||
backupsJson = JSON.stringify([]);
|
||||
}
|
||||
this.registryBackupTable.data = JSON.parse(backupsJson);
|
||||
};
|
||||
|
||||
$app.methods.promptVrcRegistryBackupName = async function () {
|
||||
var name = await this.$prompt(
|
||||
'Enter a name for the backup',
|
||||
'Backup Name',
|
||||
{
|
||||
confirmButtonText: 'Confirm',
|
||||
cancelButtonText: 'Cancel',
|
||||
inputPattern: /\S+/,
|
||||
inputErrorMessage: 'Name is required',
|
||||
inputValue: 'Backup'
|
||||
}
|
||||
);
|
||||
if (name.action === 'confirm') {
|
||||
this.backupVrcRegistry(name.value);
|
||||
}
|
||||
};
|
||||
|
||||
$app.methods.backupVrcRegistry = async function (name) {
|
||||
var regJson = await AppApi.GetVRChatRegistry();
|
||||
var newBackup = {
|
||||
name,
|
||||
date: new Date().toJSON(),
|
||||
data: regJson
|
||||
};
|
||||
var backupsJson = configRepository.getString(
|
||||
'VRCX_VRChatRegistryBackups'
|
||||
);
|
||||
if (!backupsJson) {
|
||||
backupsJson = JSON.stringify([]);
|
||||
}
|
||||
var backups = JSON.parse(backupsJson);
|
||||
backups.push(newBackup);
|
||||
configRepository.setString(
|
||||
'VRCX_VRChatRegistryBackups',
|
||||
JSON.stringify(backups)
|
||||
);
|
||||
this.updateRegistryBackupDialog();
|
||||
};
|
||||
|
||||
$app.methods.deleteVrcRegistryBackup = function (row) {
|
||||
var backups = this.registryBackupTable.data;
|
||||
removeFromArray(backups, row);
|
||||
configRepository.setString(
|
||||
'VRCX_VRChatRegistryBackups',
|
||||
JSON.stringify(backups)
|
||||
);
|
||||
this.updateRegistryBackupDialog();
|
||||
};
|
||||
|
||||
$app.methods.restoreVrcRegistryBackup = function (row) {
|
||||
this.$confirm('Continue? Restore Backup', 'Confirm', {
|
||||
confirmButtonText: 'Confirm',
|
||||
cancelButtonText: 'Cancel',
|
||||
type: 'warning',
|
||||
callback: (action) => {
|
||||
if (action !== 'confirm') {
|
||||
return;
|
||||
}
|
||||
var data = JSON.stringify(row.data);
|
||||
AppApi.SetVRChatRegistry(data)
|
||||
.then(() => {
|
||||
this.$message({
|
||||
message: 'VRC registry settings restored',
|
||||
type: 'success'
|
||||
});
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
this.$message({
|
||||
message: `Failed to restore VRC registry settings, check console for full error: ${e}`,
|
||||
type: 'error'
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$app.methods.saveVrcRegistryBackupToFile = function (row) {
|
||||
this.downloadAndSaveJson(row.name, row.data);
|
||||
};
|
||||
|
||||
$app.methods.restoreVrcRegistryFromFile = function (json) {
|
||||
try {
|
||||
var data = JSON.parse(json);
|
||||
if (!data || typeof data !== 'object') {
|
||||
throw new Error('Invalid JSON');
|
||||
}
|
||||
// quick check to make sure it's a valid registry backup
|
||||
for (var key in data) {
|
||||
var value = data[key];
|
||||
if (
|
||||
typeof value !== 'object' ||
|
||||
typeof value.type !== 'number' ||
|
||||
typeof value.data === 'undefined'
|
||||
) {
|
||||
throw new Error('Invalid JSON');
|
||||
}
|
||||
}
|
||||
AppApi.SetVRChatRegistry(json)
|
||||
.then(() => {
|
||||
this.$message({
|
||||
message: 'VRC registry settings restored',
|
||||
type: 'success'
|
||||
});
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
this.$message({
|
||||
message: `Failed to restore VRC registry settings, check console for full error: ${e}`,
|
||||
type: 'error'
|
||||
});
|
||||
});
|
||||
} catch {
|
||||
this.$message({
|
||||
message: 'Invalid JSON',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$app.methods.deleteVrcRegistry = function () {
|
||||
this.$confirm('Continue? Delete VRC Registry Settings', 'Confirm', {
|
||||
confirmButtonText: 'Confirm',
|
||||
cancelButtonText: 'Cancel',
|
||||
type: 'warning',
|
||||
callback: (action) => {
|
||||
if (action !== 'confirm') {
|
||||
return;
|
||||
}
|
||||
AppApi.DeleteVRChatRegistryFolder().then(() => {
|
||||
this.$message({
|
||||
message: 'VRC registry settings deleted',
|
||||
type: 'success'
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$app.methods.clearVrcRegistryDialog = function () {
|
||||
this.registryBackupTable.data = [];
|
||||
};
|
||||
|
||||
$app.methods.checkAutoBackupRestoreVrcRegistry = async function () {
|
||||
if (!this.vrcRegistryAutoBackup) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check for auto restore
|
||||
var hasVRChatRegistryFolder = await AppApi.HasVRChatRegistryFolder();
|
||||
if (!hasVRChatRegistryFolder) {
|
||||
var lastBackupDate = configRepository.getString(
|
||||
'VRCX_VRChatRegistryLastBackupDate'
|
||||
);
|
||||
var lastRestoreCheck = configRepository.getString(
|
||||
'VRCX_VRChatRegistryLastRestoreCheck'
|
||||
);
|
||||
if (
|
||||
lastRestoreCheck &&
|
||||
lastBackupDate &&
|
||||
lastRestoreCheck === lastBackupDate
|
||||
) {
|
||||
// only ask to restore once
|
||||
return;
|
||||
}
|
||||
// popup message about auto restore
|
||||
this.$alert(
|
||||
$t('dialog.registry_backup.restore_prompt'),
|
||||
$t('dialog.registry_backup.header')
|
||||
);
|
||||
this.showRegistryBackupDialog();
|
||||
AppApi.FocusWindow();
|
||||
configRepository.setString(
|
||||
'VRCX_VRChatRegistryLastRestoreCheck',
|
||||
lastBackupDate
|
||||
);
|
||||
} else {
|
||||
this.autoBackupVrcRegistry();
|
||||
}
|
||||
};
|
||||
|
||||
$app.methods.autoBackupVrcRegistry = function () {
|
||||
var date = new Date();
|
||||
var lastBackupDate = configRepository.getString(
|
||||
'VRCX_VRChatRegistryLastBackupDate'
|
||||
);
|
||||
if (lastBackupDate) {
|
||||
var lastBackup = new Date(lastBackupDate);
|
||||
var diff = date.getTime() - lastBackup.getTime();
|
||||
var diffDays = Math.floor(diff / (1000 * 60 * 60 * 24));
|
||||
if (diffDays < 7) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
var backupsJson = configRepository.getString(
|
||||
'VRCX_VRChatRegistryBackups'
|
||||
);
|
||||
if (!backupsJson) {
|
||||
backupsJson = JSON.stringify([]);
|
||||
}
|
||||
var backups = JSON.parse(backupsJson);
|
||||
backups.forEach((backup) => {
|
||||
if (backup.name === 'Auto Backup') {
|
||||
// remove old auto backup
|
||||
removeFromArray(backups, backup);
|
||||
}
|
||||
});
|
||||
configRepository.setString(
|
||||
'VRCX_VRChatRegistryBackups',
|
||||
JSON.stringify(backups)
|
||||
);
|
||||
this.backupVrcRegistry('Auto Backup');
|
||||
configRepository.setString(
|
||||
'VRCX_VRChatRegistryLastBackupDate',
|
||||
date.toJSON()
|
||||
);
|
||||
};
|
||||
|
||||
// #endregion
|
||||
|
||||
$app = new Vue($app);
|
||||
|
||||
@@ -2761,6 +2761,29 @@ html
|
||||
el-button(type="default" size="mini" icon="el-icon-download" circle @click="downloadAndSaveImage(fullscreenImageDialog.imageUrl)" style="margin-left:5px")
|
||||
img(v-lazy="fullscreenImageDialog.imageUrl" style="width:100%;height:100vh;object-fit:contain")
|
||||
|
||||
el-dialog.x-dialog(:before-close="beforeDialogClose" @closed="clearVrcRegistryDialog" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" ref="registryBackupDialog" :visible.sync="registryBackupDialog.visible" :title="$t('dialog.registry_backup.header')" width="600px")
|
||||
div(v-if="registryBackupDialog.visible" style="margin-top:10px")
|
||||
div.options-container
|
||||
div.options-container-item
|
||||
span.name {{ $t('dialog.registry_backup.auto_backup') }}
|
||||
el-switch(v-model="vrcRegistryAutoBackup" @change="saveVrcRegistryAutoBackup")
|
||||
el-button(@click="promptVrcRegistryBackupName" size="small") {{ $t('dialog.registry_backup.backup') }}
|
||||
el-button(@click="AppApi.OpenVrcRegJsonFileDialog()" size="small") {{ $t('dialog.registry_backup.restore_from_file') }}
|
||||
el-button(@click="deleteVrcRegistry" size="small") {{ $t('dialog.registry_backup.reset') }}
|
||||
data-tables(v-bind="registryBackupTable" style="margin-top:10px")
|
||||
el-table-column(:label="$t('dialog.registry_backup.name')" prop="name")
|
||||
el-table-column(:label="$t('dialog.registry_backup.date')" prop="date")
|
||||
template(v-once #default="scope")
|
||||
span {{ scope.row.date | formatDate('long') }}
|
||||
el-table-column(:label="$t('dialog.registry_backup.action')" width="90" align="right")
|
||||
template(v-once #default="scope")
|
||||
el-tooltip(placement="top" :content="$t('dialog.registry_backup.restore')" :disabled="hideTooltips")
|
||||
el-button(type="text" icon="el-icon-upload2" size="mini" @click="restoreVrcRegistryBackup(scope.row)")
|
||||
el-tooltip(placement="top" :content="$t('dialog.registry_backup.save_to_file')" :disabled="hideTooltips")
|
||||
el-button(type="text" icon="el-icon-download" size="mini" @click="saveVrcRegistryBackupToFile(scope.row)")
|
||||
el-tooltip(placement="top" :content="$t('dialog.registry_backup.delete')" :disabled="hideTooltips")
|
||||
el-button(type="text" icon="el-icon-delete" size="mini" @click="deleteVrcRegistryBackup(scope.row)")
|
||||
|
||||
//- dialog: open source software notice
|
||||
el-dialog.x-dialog(:before-close="beforeDialogClose" @mousedown.native="dialogMouseDown" @mouseup.native="dialogMouseUp" :visible.sync="ossDialog" :title="$t('dialog.open_source.header')" width="650px")
|
||||
div(v-if="ossDialog" style="height:350px;overflow:hidden scroll;word-break:break-all")
|
||||
|
||||
@@ -379,6 +379,7 @@
|
||||
"header": "Advanced",
|
||||
"launch_options": "Launch Options",
|
||||
"screenshot_metadata": "Screenshot Metadata",
|
||||
"vrc_registry_backup": "VRC Registry Backup",
|
||||
"common_folders": "Common Folders",
|
||||
"pending_offline": {
|
||||
"header": "Pending Offline",
|
||||
@@ -1230,6 +1231,20 @@
|
||||
"copy_image": "Copy Image",
|
||||
"open_folder": "Open Folder",
|
||||
"upload": "Upload"
|
||||
},
|
||||
"registry_backup": {
|
||||
"header": "VRC Registry Settings Backup",
|
||||
"backup": "Backup",
|
||||
"restore": "Restore",
|
||||
"save_to_file": "Save to file",
|
||||
"delete": "Delete",
|
||||
"restore_from_file": "Restore from file",
|
||||
"reset": "Reset",
|
||||
"name": "Name",
|
||||
"date": "Date",
|
||||
"action": "Action",
|
||||
"auto_backup": "Weekly Auto Backup",
|
||||
"restore_prompt": "VRCX has noticed auto backup of VRC registry settings is enabled but this computer dosn't have any, if you'd like to restore from backup you can do so from here."
|
||||
}
|
||||
},
|
||||
"prompt": {
|
||||
|
||||
@@ -379,6 +379,7 @@ mixin settingsTab()
|
||||
el-button(size="small" icon="el-icon-s-operation" @click="showVRChatConfig()") VRChat config.json
|
||||
el-button(size="small" icon="el-icon-s-operation" @click="showLaunchOptions()") {{ $t('view.settings.advanced.advanced.launch_options') }}
|
||||
el-button(size="small" icon="el-icon-picture" @click="showScreenshotMetadataDialog()") {{ $t('view.settings.advanced.advanced.screenshot_metadata') }}
|
||||
el-button(size="small" icon="el-icon-goods" @click="showRegistryBackupDialog()") {{ $t('view.settings.advanced.advanced.vrc_registry_backup') }}
|
||||
//- Advanced | Common Folders
|
||||
div.options-container
|
||||
span.header {{ $t('view.settings.advanced.advanced.common_folders') }}
|
||||
|
||||
Reference in New Issue
Block a user