show waiting state while redirecting to the OAuth 2.0 authorization page

This commit is contained in:
MaysWind
2025-10-23 00:42:29 +08:00
parent 234e7a55ff
commit b21fff5b15
4 changed files with 43 additions and 35 deletions
+4 -2
View File
@@ -29,7 +29,8 @@ export function useLoginPageBase(platform: 'mobile' | 'desktop') {
const twoFAVerifyType = ref<string>('passcode');
const oauth2ClientSessionId = ref<string>('');
const logining = ref<boolean>(false);
const loggingInByPassword = ref<boolean>(false);
const loggingInByOAuth2 = ref<boolean>(false);
const verifying = ref<boolean>(false);
const inputIsEmpty = computed<boolean>(() => !username.value || !password.value);
@@ -73,7 +74,8 @@ export function useLoginPageBase(platform: 'mobile' | 'desktop') {
tempToken,
twoFAVerifyType,
oauth2ClientSessionId,
logining,
loggingInByPassword,
loggingInByOAuth2,
verifying,
// computed states
inputIsEmpty,
+17 -14
View File
@@ -36,7 +36,7 @@
type="text"
autocomplete="username"
:autofocus="true"
:disabled="show2faInput || logining || verifying"
:disabled="show2faInput || loggingInByPassword || loggingInByOAuth2 || verifying"
:label="tt('Username')"
:placeholder="tt('Your username or email')"
v-model="username"
@@ -50,7 +50,7 @@
autocomplete="current-password"
ref="passwordInput"
type="password"
:disabled="show2faInput || logining || verifying"
:disabled="show2faInput || loggingInByPassword || loggingInByOAuth2 || verifying"
:label="tt('Password')"
:placeholder="tt('Your password')"
v-model="password"
@@ -64,7 +64,7 @@
type="number"
autocomplete="one-time-code"
ref="passcodeInput"
:disabled="logining || verifying"
:disabled="loggingInByPassword || loggingInByOAuth2 || verifying"
:label="tt('Passcode')"
:placeholder="tt('Passcode')"
:append-inner-icon="mdiHelpCircleOutline"
@@ -75,7 +75,7 @@
/>
<v-text-field
type="text"
:disabled="logining || verifying"
:disabled="loggingInByPassword || loggingInByOAuth2 || verifying"
:label="tt('Backup Code')"
:placeholder="tt('Backup Code')"
:append-inner-icon="mdiOnepassword"
@@ -100,10 +100,10 @@
</v-col>
<v-col cols="12">
<v-btn block :disabled="inputIsEmpty || logining || verifying"
<v-btn block :disabled="inputIsEmpty || loggingInByPassword || loggingInByOAuth2 || verifying"
@click="login" v-if="isInternalAuthEnabled() && !show2faInput">
{{ tt('Log In') }}
<v-progress-circular indeterminate size="22" class="ms-2" v-if="logining"></v-progress-circular>
<v-progress-circular indeterminate size="22" class="ms-2" v-if="loggingInByPassword"></v-progress-circular>
</v-btn>
<v-col cols="12" class="d-flex align-center px-0" v-if="isInternalAuthEnabled() && isOAuth2Enabled()">
@@ -112,10 +112,12 @@
<v-divider class="ms-3" />
</v-col>
<v-btn block :disabled="logining || verifying" :href="oauth2LoginUrl" v-if="isOAuth2Enabled()">
<v-btn block :disabled="loggingInByPassword || loggingInByOAuth2 || verifying" :href="oauth2LoginUrl"
@click="loggingInByOAuth2 = true" v-if="isOAuth2Enabled()">
{{ oauth2LoginDisplayName }}
<v-progress-circular indeterminate size="22" class="ms-2" v-if="loggingInByOAuth2"></v-progress-circular>
</v-btn>
<v-btn block :disabled="twoFAInputIsEmpty || logining || verifying"
<v-btn block :disabled="twoFAInputIsEmpty || loggingInByPassword || loggingInByOAuth2 || verifying"
@click="verify" v-else-if="show2faInput">
{{ tt('Continue') }}
<v-progress-circular indeterminate size="22" class="ms-2" v-if="verifying"></v-progress-circular>
@@ -140,7 +142,7 @@
<v-card-text class="pt-0">
<v-row>
<v-col cols="12" class="text-center">
<language-select-button :disabled="logining || verifying" />
<language-select-button :disabled="loggingInByPassword || loggingInByOAuth2 || verifying" />
</v-col>
<v-col cols="12" class="d-flex align-center pt-0">
@@ -212,7 +214,8 @@ const {
tempToken,
twoFAVerifyType,
oauth2ClientSessionId,
logining,
loggingInByPassword,
loggingInByOAuth2,
verifying,
inputIsEmpty,
twoFAInputIsEmpty,
@@ -247,17 +250,17 @@ function login(): void {
return;
}
if (logining.value) {
if (loggingInByPassword.value) {
return;
}
logining.value = true;
loggingInByPassword.value = true;
rootStore.authorize({
loginName: username.value,
password: password.value
}).then(authResponse => {
logining.value = false;
loggingInByPassword.value = false;
if (authResponse.need2FA) {
tempToken.value = authResponse.token;
@@ -276,7 +279,7 @@ function login(): void {
doAfterLogin(authResponse);
router.replace('/');
}).catch(error => {
logining.value = false;
loggingInByPassword.value = false;
if (isUserVerifyEmailEnabled() && error.error && error.error.errorCode === KnownErrorCode.UserEmailNotVerified && error.error.context && error.error.context.email) {
router.push(`/verify_email?email=${encodeURIComponent(error.error.context.email)}&emailSent=${error.error.context.hasValidEmailVerifyToken || false}`);
+12 -12
View File
@@ -38,7 +38,7 @@
type="password"
autocomplete="password"
:autofocus="true"
:disabled="logining"
:disabled="loggingInByOAuth2"
:label="tt('Password')"
:placeholder="tt('Your password')"
v-model="password"
@@ -47,15 +47,15 @@
</v-col>
<v-col cols="12">
<v-btn block type="submit" :disabled="!password || logining" @click="verifyAndLogin">
<v-btn block type="submit" :disabled="!password || loggingInByOAuth2" @click="verifyAndLogin">
{{ tt('Continue') }}
<v-progress-circular indeterminate size="22" class="ms-2" v-if="logining"></v-progress-circular>
<v-progress-circular indeterminate size="22" class="ms-2" v-if="loggingInByOAuth2"></v-progress-circular>
</v-btn>
</v-col>
<v-col cols="12">
<router-link class="d-flex align-center justify-center" to="/login"
:class="{ 'disabled': logining }">
:class="{ 'disabled': loggingInByOAuth2 }">
<v-icon class="icon-with-direction" :icon="mdiChevronLeft"/>
<span>{{ tt('Back to login page') }}</span>
</router-link>
@@ -71,7 +71,7 @@
<v-card-text class="pt-0">
<v-row>
<v-col cols="12" class="text-center">
<language-select-button :disabled="logining" />
<language-select-button :disabled="loggingInByOAuth2" />
</v-col>
<v-col cols="12" class="d-flex align-center pt-0">
@@ -146,7 +146,7 @@ const rootStore = useRootStore();
const {
version,
password,
logining,
loggingInByOAuth2,
doAfterLogin
} = useLoginPageBase('desktop');
@@ -197,17 +197,17 @@ function verifyAndLogin(): void {
return;
}
logining.value = true;
loggingInByOAuth2.value = true;
rootStore.authorizeOAuth2({
password: password.value,
token: props.token || ''
}).then(authResponse => {
logining.value = false;
loggingInByOAuth2.value = false;
doAfterLogin(authResponse);
navigateToHome();
}).catch(error => {
logining.value = false;
loggingInByOAuth2.value = false;
if (isUserVerifyEmailEnabled() && error.error && error.error.errorCode === KnownErrorCode.UserEmailNotVerified && error.error.context && error.error.context.email) {
router.push(`/verify_email?email=${encodeURIComponent(error.error.context.email)}&emailSent=${error.error.context.hasValidEmailVerifyToken || false}`);
@@ -221,16 +221,16 @@ function verifyAndLogin(): void {
}
if (!error.value && props.platform && props.token && !props.userName) {
logining.value = true;
loggingInByOAuth2.value = true;
rootStore.authorizeOAuth2({
token: props.token
}).then(authResponse => {
logining.value = false;
loggingInByOAuth2.value = false;
doAfterLogin(authResponse);
navigateToHome();
}).catch(error => {
logining.value = false;
loggingInByOAuth2.value = false;
if (isUserVerifyEmailEnabled() && error.error && error.error.errorCode === KnownErrorCode.UserEmailNotVerified && error.error.context && error.error.context.email) {
router.push(`/verify_email?email=${encodeURIComponent(error.error.context.email)}&emailSent=${error.error.context.hasValidEmailVerifyToken || false}`);
+10 -7
View File
@@ -47,13 +47,15 @@
</f7-list>
<f7-list class="margin-vertical-half">
<f7-list-button :class="{ 'disabled': inputIsEmpty || logining }" :text="tt('Log In')" @click="login" v-if="isInternalAuthEnabled()"></f7-list-button>
<f7-list-button :class="{ 'disabled': inputIsEmpty || loggingInByPassword || loggingInByOAuth2 }" :text="tt('Log In')"
@click="login" v-if="isInternalAuthEnabled()"></f7-list-button>
<f7-list-item class="login-divider display-flex align-items-center" v-if="isInternalAuthEnabled() && isOAuth2Enabled()">
<hr class="margin-inline-end-half" />
<small>{{ tt('or') }}</small>
<hr class="margin-inline-start-half" />
</f7-list-item>
<f7-list-button external :class="{ 'disabled': logining }" :href="oauth2LoginUrl" :text="oauth2LoginDisplayName" v-if="isOAuth2Enabled()"></f7-list-button>
<f7-list-button external :class="{ 'disabled': loggingInByPassword || loggingInByOAuth2 }" :href="oauth2LoginUrl" :text="oauth2LoginDisplayName"
@click="loggingInByOAuth2 = true" v-if="isOAuth2Enabled()"></f7-list-button>
<f7-block-footer v-if="isInternalAuthEnabled()">
<span>{{ tt('Don\'t have an account?') }}</span>&nbsp;
<f7-link :class="{'disabled': !isUserRegistrationEnabled()}" href="/signup" :text="tt('Create an account')"></f7-link>
@@ -212,7 +214,8 @@ const {
tempToken,
twoFAVerifyType,
oauth2ClientSessionId,
logining,
loggingInByPassword,
loggingInByOAuth2,
verifying,
inputIsEmpty,
twoFAInputIsEmpty,
@@ -258,17 +261,17 @@ function login(): void {
return;
}
logining.value = true;
loggingInByPassword.value = true;
resendVerifyEmail.value = '';
hasValidEmailVerifyToken.value = false;
currentPasswordForResendVerifyEmail.value = '';
showLoading(() => logining.value);
showLoading(() => loggingInByPassword.value);
rootStore.authorize({
loginName: username.value,
password: password.value
}).then(authResponse => {
logining.value = false;
loggingInByPassword.value = false;
hideLoading();
if (authResponse.need2FA) {
@@ -280,7 +283,7 @@ function login(): void {
doAfterLogin(authResponse);
router.refreshPage();
}).catch(error => {
logining.value = false;
loggingInByPassword.value = false;
hideLoading();
if (isUserVerifyEmailEnabled() && error.error && error.error.errorCode === KnownErrorCode.UserEmailNotVerified && error.error.context && error.error.context.email) {