add auto-login delay setting and prompt

This commit is contained in:
pa
2026-02-01 23:25:17 +09:00
parent 7a0b0b8bd4
commit 2dab3733fd
4 changed files with 100 additions and 1 deletions

View File

@@ -547,7 +547,9 @@
"logging": {
"header": "Logging",
"resource_load": "Log Udon string/image load",
"empty_avatar": "Log avatars in feed without names"
"empty_avatar": "Log avatars in feed without names",
"auto_login_delay": "Auto-login delay",
"auto_login_delay_button": "Set delay seconds"
},
"automation": {
"header": "Automation",
@@ -2051,6 +2053,7 @@
"traveling": "Traveling"
},
"message": {
"auto_login_delay_countdown": "Auto-login in {seconds}s...",
"vrcx_updater": {
"failed": "Failed to check for update, {message}",
"failed_install": "Failed to install update",
@@ -2370,6 +2373,11 @@
"save": "Save",
"input_error": "Valid number is required"
},
"auto_login_delay": {
"header": "Auto-login delay",
"description": "Enter delay in seconds (0 to disable, max 10).",
"input_error": "Please enter a whole number from 0 to 10."
},
"proxy_settings": {
"header": "Proxy Settings",
"description": "Enter proxy server address and port",

View File

@@ -12,6 +12,7 @@ import { database } from '../service/database';
import { escapeTag } from '../shared/utils';
import { request } from '../service/request';
import { useAdvancedSettingsStore } from './settings/advanced';
import { useGeneralSettingsStore } from './settings/general';
import { useModalStore } from './modal';
import { useNotificationStore } from './notification';
import { useUpdateLoopStore } from './updateLoop';
@@ -22,8 +23,11 @@ import configRepository from '../service/config';
import security from '../service/security';
import webApiService from '../service/webapi';
import * as workerTimers from 'worker-timers';
export const useAuthStore = defineStore('Auth', () => {
const advancedSettingsStore = useAdvancedSettingsStore();
const generalSettingsStore = useGeneralSettingsStore();
const notificationStore = useNotificationStore();
const userStore = useUserStore();
const updateLoopStore = useUpdateLoopStore();
@@ -187,6 +191,7 @@ export const useAuthStore = defineStore('Auth', () => {
AppDebug.endpointDomain = user.loginParams.endpoint;
AppDebug.websocketDomain = user.loginParams.websocket;
}
await applyAutoLoginDelay();
// login at startup
loginForm.value.loading = true;
authRequest
@@ -847,6 +852,34 @@ export const useAuthStore = defineStore('Auth', () => {
});
}
async function applyAutoLoginDelay() {
if (!generalSettingsStore.autoLoginDelayEnabled) {
return;
}
const seconds = generalSettingsStore.autoLoginDelaySeconds;
if (!seconds || seconds <= 0) {
return;
}
let toastId = null;
for (let remaining = seconds; remaining > 0; remaining--) {
if (toastId) {
toast.dismiss(toastId);
}
toastId = toast.info(
t('message.auto_login_delay_countdown', {
seconds: remaining
}),
{ duration: Infinity }
);
await new Promise((resolve) => {
workerTimers.setTimeout(resolve, 1000);
});
}
if (toastId) {
toast.dismiss(toastId);
}
}
async function loginComplete() {
await database.initUserTables(userStore.currentUser.id);
watchState.isLoggedIn = true;

View File

@@ -28,6 +28,8 @@ export const useGeneralSettingsStore = defineStore('GeneralSettings', () => {
const udonExceptionLogging = ref(false);
const logResourceLoad = ref(false);
const logEmptyAvatars = ref(false);
const autoLoginDelayEnabled = ref(false);
const autoLoginDelaySeconds = ref(0);
const autoStateChangeEnabled = ref(false);
const autoStateChangeAloneStatus = ref('join me');
const autoStateChangeCompanyStatus = ref('busy');
@@ -47,6 +49,8 @@ export const useGeneralSettingsStore = defineStore('GeneralSettings', () => {
udonExceptionLoggingConfig,
logResourceLoadConfig,
logEmptyAvatarsConfig,
autoLoginDelayEnabledConfig,
autoLoginDelaySecondsConfig,
autoStateChangeEnabledConfig,
autoStateChangeAloneStatusConfig,
autoStateChangeCompanyStatusConfig,
@@ -64,6 +68,8 @@ export const useGeneralSettingsStore = defineStore('GeneralSettings', () => {
configRepository.getBool('VRCX_udonExceptionLogging', false),
configRepository.getBool('VRCX_logResourceLoad', false),
configRepository.getBool('VRCX_logEmptyAvatars', false),
configRepository.getBool('VRCX_autoLoginDelayEnabled', false),
configRepository.getInt('VRCX_autoLoginDelaySeconds', 0),
configRepository.getBool('VRCX_autoStateChangeEnabled', false),
configRepository.getString(
'VRCX_autoStateChangeAloneStatus',
@@ -107,6 +113,8 @@ export const useGeneralSettingsStore = defineStore('GeneralSettings', () => {
udonExceptionLogging.value = udonExceptionLoggingConfig;
logResourceLoad.value = logResourceLoadConfig;
logEmptyAvatars.value = logEmptyAvatarsConfig;
autoLoginDelayEnabled.value = autoLoginDelayEnabledConfig;
autoLoginDelaySeconds.value = autoLoginDelaySecondsConfig;
autoStateChangeEnabled.value = autoStateChangeEnabledConfig;
autoStateChangeAloneStatus.value = autoStateChangeAloneStatusConfig;
autoStateChangeCompanyStatus.value = autoStateChangeCompanyStatusConfig;
@@ -179,6 +187,40 @@ export const useGeneralSettingsStore = defineStore('GeneralSettings', () => {
logEmptyAvatars.value = !logEmptyAvatars.value;
configRepository.setBool('VRCX_logEmptyAvatars', logEmptyAvatars.value);
}
function setAutoLoginDelayEnabled() {
autoLoginDelayEnabled.value = !autoLoginDelayEnabled.value;
configRepository.setBool(
'VRCX_autoLoginDelayEnabled',
autoLoginDelayEnabled.value
);
}
function setAutoLoginDelaySeconds(value) {
const parsed = parseInt(value, 10);
autoLoginDelaySeconds.value = Number.isNaN(parsed)
? 0
: Math.min(10, Math.max(0, parsed));
configRepository.setInt(
'VRCX_autoLoginDelaySeconds',
autoLoginDelaySeconds.value
);
}
function promptAutoLoginDelaySeconds() {
modalStore
.prompt({
title: t('prompt.auto_login_delay.header'),
description: t('prompt.auto_login_delay.description'),
inputValue: String(autoLoginDelaySeconds.value),
pattern: /^(10|[0-9])$/,
errorMessage: t('prompt.auto_login_delay.input_error')
})
.then(({ ok, value }) => {
if (!ok) return;
setAutoLoginDelaySeconds(value);
})
.catch((err) => {
console.error(err);
});
}
function setAutoStateChangeEnabled() {
autoStateChangeEnabled.value = !autoStateChangeEnabled.value;
configRepository.setBool(
@@ -285,6 +327,8 @@ export const useGeneralSettingsStore = defineStore('GeneralSettings', () => {
udonExceptionLogging,
logResourceLoad,
logEmptyAvatars,
autoLoginDelayEnabled,
autoLoginDelaySeconds,
autoStateChangeEnabled,
autoStateChangeAloneStatus,
autoStateChangeCompanyStatus,
@@ -301,6 +345,8 @@ export const useGeneralSettingsStore = defineStore('GeneralSettings', () => {
setUdonExceptionLogging,
setLogResourceLoad,
setLogEmptyAvatars,
setAutoLoginDelayEnabled,
promptAutoLoginDelaySeconds,
setAutoStateChangeEnabled,
setAutoStateChangeAloneStatus,
setAutoStateChangeCompanyStatus,

View File

@@ -139,6 +139,15 @@
:label="t('view.settings.general.logging.empty_avatar')"
:value="logEmptyAvatars"
@change="setLogEmptyAvatars" />
<simple-switch
:label="t('view.settings.general.logging.auto_login_delay')"
:value="autoLoginDelayEnabled"
@change="setAutoLoginDelayEnabled" />
<div v-if="autoLoginDelayEnabled" class="options-container-item">
<Button size="sm" variant="outline" @click="promptAutoLoginDelaySeconds">
{{ t('view.settings.general.logging.auto_login_delay_button') }}
</Button>
</div>
</div>
<div class="options-container">
<span class="header">{{ t('view.settings.general.automation.header') }}</span>
@@ -333,6 +342,7 @@
udonExceptionLogging,
logResourceLoad,
logEmptyAvatars,
autoLoginDelayEnabled,
autoStateChangeEnabled,
autoStateChangeAloneStatus,
autoStateChangeCompanyStatus,
@@ -350,6 +360,8 @@
setUdonExceptionLogging,
setLogResourceLoad,
setLogEmptyAvatars,
setAutoLoginDelayEnabled,
promptAutoLoginDelaySeconds,
setAutoStateChangeEnabled,
setAutoStateChangeAloneStatus,
setAutoStateChangeCompanyStatus,