mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-05-02 21:16:07 +02:00
f4f78bb5ec
* refactor: frontend * Fix avatar gallery sort * Update .NET dependencies * Update npm dependencies electron v37.1.0 * bulkRefreshFriends * fix dark theme * Remove crowdin * Fix config.json dialog not updating * VRCX log file fixes & add Cef log * Remove SharedVariable, fix startup * Revert init theme change * Logging date not working? Fix WinformThemer designer error * Add Cef request hander, no more escaping main page * clean * fix * fix * clean * uh * Apply thememode at startup, fixes random user colours * Split database into files * Instance info remove empty lines * Open external VRC links with VRCX * Electron fixes * fix userdialog style * ohhhh * fix store * fix store * fix: load all group members after kicking a user * fix: world dialog favorite button style * fix: Clear VRCX Cache Timer input value * clean * Fix VR overlay * Fix VR overlay 2 * Fix Discord discord rich presence for RPC worlds * Clean up age verified user tags * Fix playerList being occupied after program reload * no `this` * Fix login stuck loading * writable: false * Hide dialogs on logout * add flush sync option * rm LOGIN event * rm LOGOUT event * remove duplicate event listeners * remove duplicate event listeners * clean * remove duplicate event listeners * clean * fix theme style * fix t * clearable * clean * fix ipcEvent * Small changes * Popcorn Palace support * Remove checkActiveFriends * Clean up * Fix dragEnterCef * Block API requests when not logged in * Clear state on login & logout * Fix worldDialog instances not updating * use <script setup> * Fix avatar change event, CheckGameRunning at startup * Fix image dragging * fix * Remove PWI * fix updateLoop * add webpack-dev-server to dev environment * rm unnecessary chunks * use <script setup> * webpack-dev-server changes * use <script setup> * use <script setup> * Fix UGC text size * Split login event * t * use <script setup> * fix * Update .gitignore and enable checkJs in jsconfig * fix i18n t * use <script setup> * use <script setup> * clean * global types * fix * use checkJs for debugging * Add watchState for login watchers * fix .vue template * type fixes * rm Vue.filter * Cef v138.0.170, VC++ 2022 * Settings fixes * Remove 'USER:CURRENT' * clean up 2FA callbacks * remove userApply * rm i18n import * notification handling to use notification store methods * refactor favorite handling to use favorite store methods and clean up event emissions * refactor moderation handling to use dedicated functions for player moderation events * refactor friend handling to use dedicated functions for friend events * Fix program startup, move lang init * Fix friend state * Fix status change error * Fix user notes diff * fix * rm group event * rm auth event * rm avatar event * clean * clean * getUser * getFriends * getFavoriteWorlds, getFavoriteAvatars * AvatarGalleryUpload btn style & package.json update * Fix friend requests * Apply user * Apply world * Fix note diff * Fix VR overlay * Fixes * Update build scripts * Apply avatar * Apply instance * Apply group * update hidden VRC+ badge * Fix sameInstance "private" * fix 502/504 API errors * fix 502/504 API errors * clean * Fix friend in same instance on orange showing twice in friends list * Add back in broken friend state repair methods * add types --------- Co-authored-by: Natsumi <cmcooper123@hotmail.com>
498 lines
16 KiB
JavaScript
498 lines
16 KiB
JavaScript
import { defineStore } from 'pinia';
|
|
import { computed, reactive } from 'vue';
|
|
import * as workerTimers from 'worker-timers';
|
|
import { $app } from '../app';
|
|
import configRepository from '../service/config';
|
|
import { watchState } from '../service/watchState';
|
|
import { branches } from '../shared/constants';
|
|
import { changeLogRemoveLinks } from '../shared/utils';
|
|
import { useAuthStore } from './auth';
|
|
import { useUiStore } from './ui';
|
|
import { useI18n } from 'vue-i18n-bridge';
|
|
import { AppGlobal } from '../service/appConfig';
|
|
|
|
export const useVRCXUpdaterStore = defineStore('VRCXUpdater', () => {
|
|
const uiStore = useUiStore();
|
|
const { t } = useI18n();
|
|
|
|
const state = reactive({
|
|
appVersion: '',
|
|
autoUpdateVRCX: 'Auto Download',
|
|
latestAppVersion: '',
|
|
branch: 'Stable',
|
|
vrcxId: '',
|
|
checkingForVRCXUpdate: false,
|
|
VRCXUpdateDialog: {
|
|
visible: false,
|
|
updatePending: false,
|
|
updatePendingIsLatest: false,
|
|
release: '',
|
|
releases: [],
|
|
json: {}
|
|
},
|
|
changeLogDialog: {
|
|
visible: false,
|
|
buildName: '',
|
|
changeLog: ''
|
|
},
|
|
pendingVRCXUpdate: false,
|
|
pendingVRCXInstall: false,
|
|
|
|
updateInProgress: false,
|
|
updateProgress: 0
|
|
});
|
|
|
|
async function initVRCXUpdaterSettings() {
|
|
const [autoUpdateVRCX, vrcxId] = await Promise.all([
|
|
configRepository.getString('VRCX_autoUpdateVRCX', 'Auto Download'),
|
|
configRepository.getString('VRCX_id', '')
|
|
]);
|
|
|
|
if (autoUpdateVRCX === 'Auto Install') {
|
|
state.autoUpdateVRCX = 'Auto Download';
|
|
} else {
|
|
state.autoUpdateVRCX = autoUpdateVRCX;
|
|
}
|
|
|
|
state.appVersion = await AppApi.GetVersion();
|
|
state.vrcxId = vrcxId;
|
|
|
|
await initBranch();
|
|
await loadVrcxId();
|
|
|
|
if (await compareAppVersion()) {
|
|
showChangeLogDialog();
|
|
}
|
|
if (state.autoUpdateVRCX !== 'Off') {
|
|
await checkForVRCXUpdate();
|
|
}
|
|
}
|
|
|
|
const appVersion = computed(() => state.appVersion);
|
|
const autoUpdateVRCX = computed(() => state.autoUpdateVRCX);
|
|
const latestAppVersion = computed(() => state.latestAppVersion);
|
|
const branch = computed({
|
|
get: () => state.branch,
|
|
set: (value) => {
|
|
state.branch = value;
|
|
}
|
|
});
|
|
const currentVersion = computed(() =>
|
|
state.appVersion.replace(' (Linux)', '')
|
|
);
|
|
const vrcxId = computed(() => state.vrcxId);
|
|
const checkingForVRCXUpdate = computed({
|
|
get: () => state.checkingForVRCXUpdate,
|
|
set: (value) => {
|
|
state.checkingForVRCXUpdate = value;
|
|
}
|
|
});
|
|
const VRCXUpdateDialog = computed({
|
|
get: () => state.VRCXUpdateDialog,
|
|
set: (value) => {
|
|
state.VRCXUpdateDialog = { ...state.VRCXUpdateDialog, ...value };
|
|
}
|
|
});
|
|
const changeLogDialog = computed({
|
|
get: () => state.changeLogDialog,
|
|
set: (value) => {
|
|
state.changeLogDialog = value;
|
|
}
|
|
});
|
|
const pendingVRCXUpdate = computed({
|
|
get: () => state.pendingVRCXUpdate,
|
|
set: (value) => {
|
|
state.pendingVRCXUpdate = value;
|
|
}
|
|
});
|
|
const pendingVRCXInstall = computed({
|
|
get: () => state.pendingVRCXInstall,
|
|
set: (value) => {
|
|
state.pendingVRCXInstall = value;
|
|
}
|
|
});
|
|
const updateInProgress = computed({
|
|
get: () => state.updateInProgress,
|
|
set: (value) => {
|
|
state.updateInProgress = value;
|
|
}
|
|
});
|
|
const updateProgress = computed({
|
|
get: () => state.updateProgress,
|
|
set: (value) => {
|
|
state.updateProgress = value;
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @param {string} value
|
|
*/
|
|
async function setAutoUpdateVRCX(value) {
|
|
if (value === 'Off') {
|
|
state.pendingVRCXUpdate = false;
|
|
}
|
|
state.autoUpdateVRCX = value;
|
|
await configRepository.setString('VRCX_autoUpdateVRCX', value);
|
|
}
|
|
/**
|
|
* @param {string} value
|
|
*/
|
|
function setLatestAppVersion(value) {
|
|
state.latestAppVersion = value;
|
|
}
|
|
/**
|
|
* @param {string} value
|
|
*/
|
|
function setBranch(value) {
|
|
state.branch = value;
|
|
configRepository.setString('VRCX_branch', value);
|
|
}
|
|
|
|
async function initBranch() {
|
|
if (!state.appVersion) {
|
|
return;
|
|
}
|
|
if (currentVersion.value.includes('VRCX Nightly')) {
|
|
state.branch = 'Nightly';
|
|
} else {
|
|
state.branch = 'Stable';
|
|
}
|
|
await configRepository.setString('VRCX_branch', state.branch);
|
|
}
|
|
|
|
async function compareAppVersion() {
|
|
const lastVersion = await configRepository.getString(
|
|
'VRCX_lastVRCXVersion',
|
|
''
|
|
);
|
|
if (lastVersion !== currentVersion.value) {
|
|
await configRepository.setString(
|
|
'VRCX_lastVRCXVersion',
|
|
currentVersion.value
|
|
);
|
|
return state.branch === 'Stable' && !!lastVersion;
|
|
}
|
|
return false;
|
|
}
|
|
async function loadVrcxId() {
|
|
if (!state.vrcxId) {
|
|
state.vrcxId = crypto.randomUUID();
|
|
await configRepository.setString('VRCX_id', state.vrcxId);
|
|
}
|
|
}
|
|
async function checkForVRCXUpdate() {
|
|
const authStore = useAuthStore();
|
|
if (
|
|
!currentVersion.value ||
|
|
currentVersion.value === 'VRCX Nightly Build' ||
|
|
currentVersion.value === 'VRCX Build'
|
|
) {
|
|
// ignore custom builds
|
|
return;
|
|
}
|
|
if (state.branch === 'Beta') {
|
|
// move Beta users to stable
|
|
setBranch('Stable');
|
|
}
|
|
if (typeof branches[state.branch] === 'undefined') {
|
|
// handle invalid branch
|
|
setBranch('Stable');
|
|
}
|
|
const url = branches[state.branch].urlLatest;
|
|
state.checkingForVRCXUpdate = true;
|
|
let response;
|
|
try {
|
|
response = await webApiService.execute({
|
|
url,
|
|
method: 'GET',
|
|
headers: {
|
|
'VRCX-ID': state.vrcxId
|
|
}
|
|
});
|
|
} finally {
|
|
state.checkingForVRCXUpdate = false;
|
|
}
|
|
state.pendingVRCXUpdate = false;
|
|
const json = JSON.parse(response.data);
|
|
if (AppGlobal.debugWebRequests) {
|
|
console.log(json, response);
|
|
}
|
|
if (json === Object(json) && json.name && json.published_at) {
|
|
state.VRCXUpdateDialog.updateJson = json;
|
|
state.changeLogDialog.buildName = json.name;
|
|
state.changeLogDialog.changeLog = changeLogRemoveLinks(json.body);
|
|
const releaseName = json.name;
|
|
setLatestAppVersion(releaseName);
|
|
state.VRCXUpdateDialog.updatePendingIsLatest = false;
|
|
if (releaseName === state.pendingVRCXInstall) {
|
|
// update already downloaded
|
|
state.VRCXUpdateDialog.updatePendingIsLatest = true;
|
|
} else if (releaseName > state.currentVersion) {
|
|
let downloadUrl = '';
|
|
let downloadName = '';
|
|
let hashUrl = '';
|
|
let size = 0;
|
|
for (const asset of json.assets) {
|
|
if (asset.state !== 'uploaded') {
|
|
continue;
|
|
}
|
|
if (
|
|
!LINUX &&
|
|
(asset.content_type === 'application/x-msdownload' ||
|
|
asset.content_type ===
|
|
'application/x-msdos-program')
|
|
) {
|
|
downloadUrl = asset.browser_download_url;
|
|
downloadName = asset.name;
|
|
size = asset.size;
|
|
continue;
|
|
}
|
|
if (
|
|
LINUX &&
|
|
asset.content_type === 'application/octet-stream'
|
|
) {
|
|
downloadUrl = asset.browser_download_url;
|
|
downloadName = asset.name;
|
|
size = asset.size;
|
|
continue;
|
|
}
|
|
if (
|
|
asset.name === 'SHA256SUMS.txt' &&
|
|
asset.content_type === 'text/plain'
|
|
) {
|
|
hashUrl = asset.browser_download_url;
|
|
continue;
|
|
}
|
|
}
|
|
if (!downloadUrl) {
|
|
return;
|
|
}
|
|
state.pendingVRCXUpdate = true;
|
|
uiStore.notifyMenu('settings');
|
|
const type = 'Auto';
|
|
if (!watchState.isLoggedIn) {
|
|
showVRCXUpdateDialog();
|
|
} else if (state.autoUpdateVRCX === 'Notify') {
|
|
// this.showVRCXUpdateDialog();
|
|
} else if (state.autoUpdateVRCX === 'Auto Download') {
|
|
await downloadVRCXUpdate(
|
|
downloadUrl,
|
|
downloadName,
|
|
hashUrl,
|
|
size,
|
|
releaseName,
|
|
type
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
async function showVRCXUpdateDialog() {
|
|
const D = state.VRCXUpdateDialog;
|
|
D.visible = true;
|
|
D.updatePendingIsLatest = false;
|
|
D.updatePending = await AppApi.CheckForUpdateExe();
|
|
await loadBranchVersions();
|
|
}
|
|
|
|
async function loadBranchVersions() {
|
|
const D = state.VRCXUpdateDialog;
|
|
const url = branches[state.branch].urlReleases;
|
|
state.checkingForVRCXUpdate = true;
|
|
let response;
|
|
try {
|
|
response = await webApiService.execute({
|
|
url,
|
|
method: 'GET',
|
|
headers: {
|
|
'VRCX-ID': state.vrcxId
|
|
}
|
|
});
|
|
} finally {
|
|
state.checkingForVRCXUpdate = false;
|
|
}
|
|
const json = JSON.parse(response.data);
|
|
if (AppGlobal.debugWebRequests) {
|
|
console.log(json, response);
|
|
}
|
|
const releases = [];
|
|
if (typeof json !== 'object' || json.message) {
|
|
$app.$message({
|
|
message: t('message.vrcx_updater.failed', {
|
|
message: json.message
|
|
}),
|
|
type: 'error'
|
|
});
|
|
return;
|
|
}
|
|
for (const release of json) {
|
|
for (const asset of release.assets) {
|
|
if (
|
|
(asset.content_type === 'application/x-msdownload' ||
|
|
asset.content_type === 'application/x-msdos-program') &&
|
|
asset.state === 'uploaded'
|
|
) {
|
|
releases.push(release);
|
|
}
|
|
}
|
|
}
|
|
D.releases = releases;
|
|
D.release = json[0].name;
|
|
state.VRCXUpdateDialog.updatePendingIsLatest = false;
|
|
if (D.release === state.pendingVRCXInstall) {
|
|
// update already downloaded and latest version
|
|
state.VRCXUpdateDialog.updatePendingIsLatest = true;
|
|
}
|
|
setBranch(state.branch);
|
|
}
|
|
async function downloadVRCXUpdate(
|
|
downloadUrl,
|
|
downloadName,
|
|
hashUrl,
|
|
size,
|
|
releaseName,
|
|
type
|
|
) {
|
|
if (state.updateInProgress) {
|
|
return;
|
|
}
|
|
try {
|
|
state.updateInProgress = true;
|
|
await downloadFileProgress();
|
|
await AppApi.DownloadUpdate(
|
|
downloadUrl,
|
|
downloadName,
|
|
hashUrl,
|
|
size
|
|
);
|
|
state.pendingVRCXInstall = releaseName;
|
|
} catch (err) {
|
|
console.error(err);
|
|
$app.$message({
|
|
message: `${t('message.vrcx_updater.failed_install')} ${err}`,
|
|
type: 'error'
|
|
});
|
|
} finally {
|
|
state.updateInProgress = false;
|
|
state.updateProgress = 0;
|
|
}
|
|
}
|
|
async function downloadFileProgress() {
|
|
state.updateProgress = await AppApi.CheckUpdateProgress();
|
|
if (state.updateInProgress) {
|
|
workerTimers.setTimeout(() => downloadFileProgress(), 150);
|
|
}
|
|
}
|
|
function installVRCXUpdate() {
|
|
for (const release of state.VRCXUpdateDialog.releases) {
|
|
if (release.name !== state.VRCXUpdateDialog.release) {
|
|
continue;
|
|
}
|
|
let downloadUrl = '';
|
|
let downloadName = '';
|
|
let hashUrl = '';
|
|
let size = 0;
|
|
for (const asset of release.assets) {
|
|
if (asset.state !== 'uploaded') {
|
|
continue;
|
|
}
|
|
if (
|
|
WINDOWS &&
|
|
(asset.content_type === 'application/x-msdownload' ||
|
|
asset.content_type === 'application/x-msdos-program')
|
|
) {
|
|
downloadUrl = asset.browser_download_url;
|
|
downloadName = asset.name;
|
|
size = asset.size;
|
|
continue;
|
|
}
|
|
if (
|
|
LINUX &&
|
|
asset.content_type === 'application/octet-stream'
|
|
) {
|
|
downloadUrl = asset.browser_download_url;
|
|
downloadName = asset.name;
|
|
size = asset.size;
|
|
continue;
|
|
}
|
|
if (
|
|
asset.name === 'SHA256SUMS.txt' &&
|
|
asset.content_type === 'text/plain'
|
|
) {
|
|
hashUrl = asset.browser_download_url;
|
|
continue;
|
|
}
|
|
}
|
|
if (!downloadUrl) {
|
|
return;
|
|
}
|
|
const releaseName = release.name;
|
|
const type = 'Manual';
|
|
downloadVRCXUpdate(
|
|
downloadUrl,
|
|
downloadName,
|
|
hashUrl,
|
|
size,
|
|
releaseName,
|
|
type
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
function showChangeLogDialog() {
|
|
state.changeLogDialog.visible = true;
|
|
checkForVRCXUpdate();
|
|
}
|
|
function restartVRCX(isUpgrade) {
|
|
if (!LINUX) {
|
|
AppApi.RestartApplication(isUpgrade);
|
|
} else {
|
|
window.electron.restartApp();
|
|
}
|
|
}
|
|
function updateProgressText() {
|
|
if (state.updateProgress === 100) {
|
|
return t('message.vrcx_updater.checking_hash');
|
|
}
|
|
return `${state.updateProgress}%`;
|
|
}
|
|
async function cancelUpdate() {
|
|
await AppApi.CancelUpdate();
|
|
state.updateInProgress = false;
|
|
state.updateProgress = 0;
|
|
}
|
|
|
|
initVRCXUpdaterSettings();
|
|
|
|
return {
|
|
state,
|
|
|
|
appVersion,
|
|
autoUpdateVRCX,
|
|
latestAppVersion,
|
|
branch,
|
|
currentVersion,
|
|
vrcxId,
|
|
checkingForVRCXUpdate,
|
|
VRCXUpdateDialog,
|
|
changeLogDialog,
|
|
pendingVRCXUpdate,
|
|
pendingVRCXInstall,
|
|
updateInProgress,
|
|
updateProgress,
|
|
|
|
setAutoUpdateVRCX,
|
|
setBranch,
|
|
|
|
compareAppVersion,
|
|
checkForVRCXUpdate,
|
|
loadBranchVersions,
|
|
installVRCXUpdate,
|
|
showVRCXUpdateDialog,
|
|
showChangeLogDialog,
|
|
restartVRCX,
|
|
updateProgressText,
|
|
cancelUpdate
|
|
};
|
|
});
|