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": { "logging": {
"header": "Logging", "header": "Logging",
"resource_load": "Log Udon string/image load", "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": { "automation": {
"header": "Automation", "header": "Automation",
@@ -2051,6 +2053,7 @@
"traveling": "Traveling" "traveling": "Traveling"
}, },
"message": { "message": {
"auto_login_delay_countdown": "Auto-login in {seconds}s...",
"vrcx_updater": { "vrcx_updater": {
"failed": "Failed to check for update, {message}", "failed": "Failed to check for update, {message}",
"failed_install": "Failed to install update", "failed_install": "Failed to install update",
@@ -2370,6 +2373,11 @@
"save": "Save", "save": "Save",
"input_error": "Valid number is required" "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": { "proxy_settings": {
"header": "Proxy Settings", "header": "Proxy Settings",
"description": "Enter proxy server address and port", "description": "Enter proxy server address and port",

View File

@@ -12,6 +12,7 @@ import { database } from '../service/database';
import { escapeTag } from '../shared/utils'; import { escapeTag } from '../shared/utils';
import { request } from '../service/request'; import { request } from '../service/request';
import { useAdvancedSettingsStore } from './settings/advanced'; import { useAdvancedSettingsStore } from './settings/advanced';
import { useGeneralSettingsStore } from './settings/general';
import { useModalStore } from './modal'; import { useModalStore } from './modal';
import { useNotificationStore } from './notification'; import { useNotificationStore } from './notification';
import { useUpdateLoopStore } from './updateLoop'; import { useUpdateLoopStore } from './updateLoop';
@@ -22,8 +23,11 @@ import configRepository from '../service/config';
import security from '../service/security'; import security from '../service/security';
import webApiService from '../service/webapi'; import webApiService from '../service/webapi';
import * as workerTimers from 'worker-timers';
export const useAuthStore = defineStore('Auth', () => { export const useAuthStore = defineStore('Auth', () => {
const advancedSettingsStore = useAdvancedSettingsStore(); const advancedSettingsStore = useAdvancedSettingsStore();
const generalSettingsStore = useGeneralSettingsStore();
const notificationStore = useNotificationStore(); const notificationStore = useNotificationStore();
const userStore = useUserStore(); const userStore = useUserStore();
const updateLoopStore = useUpdateLoopStore(); const updateLoopStore = useUpdateLoopStore();
@@ -187,6 +191,7 @@ export const useAuthStore = defineStore('Auth', () => {
AppDebug.endpointDomain = user.loginParams.endpoint; AppDebug.endpointDomain = user.loginParams.endpoint;
AppDebug.websocketDomain = user.loginParams.websocket; AppDebug.websocketDomain = user.loginParams.websocket;
} }
await applyAutoLoginDelay();
// login at startup // login at startup
loginForm.value.loading = true; loginForm.value.loading = true;
authRequest 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() { async function loginComplete() {
await database.initUserTables(userStore.currentUser.id); await database.initUserTables(userStore.currentUser.id);
watchState.isLoggedIn = true; watchState.isLoggedIn = true;

View File

@@ -28,6 +28,8 @@ export const useGeneralSettingsStore = defineStore('GeneralSettings', () => {
const udonExceptionLogging = ref(false); const udonExceptionLogging = ref(false);
const logResourceLoad = ref(false); const logResourceLoad = ref(false);
const logEmptyAvatars = ref(false); const logEmptyAvatars = ref(false);
const autoLoginDelayEnabled = ref(false);
const autoLoginDelaySeconds = ref(0);
const autoStateChangeEnabled = ref(false); const autoStateChangeEnabled = ref(false);
const autoStateChangeAloneStatus = ref('join me'); const autoStateChangeAloneStatus = ref('join me');
const autoStateChangeCompanyStatus = ref('busy'); const autoStateChangeCompanyStatus = ref('busy');
@@ -47,6 +49,8 @@ export const useGeneralSettingsStore = defineStore('GeneralSettings', () => {
udonExceptionLoggingConfig, udonExceptionLoggingConfig,
logResourceLoadConfig, logResourceLoadConfig,
logEmptyAvatarsConfig, logEmptyAvatarsConfig,
autoLoginDelayEnabledConfig,
autoLoginDelaySecondsConfig,
autoStateChangeEnabledConfig, autoStateChangeEnabledConfig,
autoStateChangeAloneStatusConfig, autoStateChangeAloneStatusConfig,
autoStateChangeCompanyStatusConfig, autoStateChangeCompanyStatusConfig,
@@ -64,6 +68,8 @@ export const useGeneralSettingsStore = defineStore('GeneralSettings', () => {
configRepository.getBool('VRCX_udonExceptionLogging', false), configRepository.getBool('VRCX_udonExceptionLogging', false),
configRepository.getBool('VRCX_logResourceLoad', false), configRepository.getBool('VRCX_logResourceLoad', false),
configRepository.getBool('VRCX_logEmptyAvatars', false), configRepository.getBool('VRCX_logEmptyAvatars', false),
configRepository.getBool('VRCX_autoLoginDelayEnabled', false),
configRepository.getInt('VRCX_autoLoginDelaySeconds', 0),
configRepository.getBool('VRCX_autoStateChangeEnabled', false), configRepository.getBool('VRCX_autoStateChangeEnabled', false),
configRepository.getString( configRepository.getString(
'VRCX_autoStateChangeAloneStatus', 'VRCX_autoStateChangeAloneStatus',
@@ -107,6 +113,8 @@ export const useGeneralSettingsStore = defineStore('GeneralSettings', () => {
udonExceptionLogging.value = udonExceptionLoggingConfig; udonExceptionLogging.value = udonExceptionLoggingConfig;
logResourceLoad.value = logResourceLoadConfig; logResourceLoad.value = logResourceLoadConfig;
logEmptyAvatars.value = logEmptyAvatarsConfig; logEmptyAvatars.value = logEmptyAvatarsConfig;
autoLoginDelayEnabled.value = autoLoginDelayEnabledConfig;
autoLoginDelaySeconds.value = autoLoginDelaySecondsConfig;
autoStateChangeEnabled.value = autoStateChangeEnabledConfig; autoStateChangeEnabled.value = autoStateChangeEnabledConfig;
autoStateChangeAloneStatus.value = autoStateChangeAloneStatusConfig; autoStateChangeAloneStatus.value = autoStateChangeAloneStatusConfig;
autoStateChangeCompanyStatus.value = autoStateChangeCompanyStatusConfig; autoStateChangeCompanyStatus.value = autoStateChangeCompanyStatusConfig;
@@ -179,6 +187,40 @@ export const useGeneralSettingsStore = defineStore('GeneralSettings', () => {
logEmptyAvatars.value = !logEmptyAvatars.value; logEmptyAvatars.value = !logEmptyAvatars.value;
configRepository.setBool('VRCX_logEmptyAvatars', 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() { function setAutoStateChangeEnabled() {
autoStateChangeEnabled.value = !autoStateChangeEnabled.value; autoStateChangeEnabled.value = !autoStateChangeEnabled.value;
configRepository.setBool( configRepository.setBool(
@@ -285,6 +327,8 @@ export const useGeneralSettingsStore = defineStore('GeneralSettings', () => {
udonExceptionLogging, udonExceptionLogging,
logResourceLoad, logResourceLoad,
logEmptyAvatars, logEmptyAvatars,
autoLoginDelayEnabled,
autoLoginDelaySeconds,
autoStateChangeEnabled, autoStateChangeEnabled,
autoStateChangeAloneStatus, autoStateChangeAloneStatus,
autoStateChangeCompanyStatus, autoStateChangeCompanyStatus,
@@ -301,6 +345,8 @@ export const useGeneralSettingsStore = defineStore('GeneralSettings', () => {
setUdonExceptionLogging, setUdonExceptionLogging,
setLogResourceLoad, setLogResourceLoad,
setLogEmptyAvatars, setLogEmptyAvatars,
setAutoLoginDelayEnabled,
promptAutoLoginDelaySeconds,
setAutoStateChangeEnabled, setAutoStateChangeEnabled,
setAutoStateChangeAloneStatus, setAutoStateChangeAloneStatus,
setAutoStateChangeCompanyStatus, setAutoStateChangeCompanyStatus,

View File

@@ -139,6 +139,15 @@
:label="t('view.settings.general.logging.empty_avatar')" :label="t('view.settings.general.logging.empty_avatar')"
:value="logEmptyAvatars" :value="logEmptyAvatars"
@change="setLogEmptyAvatars" /> @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>
<div class="options-container"> <div class="options-container">
<span class="header">{{ t('view.settings.general.automation.header') }}</span> <span class="header">{{ t('view.settings.general.automation.header') }}</span>
@@ -333,6 +342,7 @@
udonExceptionLogging, udonExceptionLogging,
logResourceLoad, logResourceLoad,
logEmptyAvatars, logEmptyAvatars,
autoLoginDelayEnabled,
autoStateChangeEnabled, autoStateChangeEnabled,
autoStateChangeAloneStatus, autoStateChangeAloneStatus,
autoStateChangeCompanyStatus, autoStateChangeCompanyStatus,
@@ -350,6 +360,8 @@
setUdonExceptionLogging, setUdonExceptionLogging,
setLogResourceLoad, setLogResourceLoad,
setLogEmptyAvatars, setLogEmptyAvatars,
setAutoLoginDelayEnabled,
promptAutoLoginDelaySeconds,
setAutoStateChangeEnabled, setAutoStateChangeEnabled,
setAutoStateChangeAloneStatus, setAutoStateChangeAloneStatus,
setAutoStateChangeCompanyStatus, setAutoStateChangeCompanyStatus,