diff options
| author | tamaina <tamaina@hotmail.co.jp> | 2023-02-09 17:18:27 +0000 |
|---|---|---|
| committer | tamaina <tamaina@hotmail.co.jp> | 2023-02-09 17:18:27 +0000 |
| commit | ca0d53ec5df747bbfba583f161a38af9dfe4d96c (patch) | |
| tree | cdb58f49bad40367bcea77db041250d577b5cc3d | |
| parent | chore: determine dimensions of the helix of cat ears based on the size of ava... (diff) | |
| download | misskey-ca0d53ec5df747bbfba583f161a38af9dfe4d96c.tar.gz misskey-ca0d53ec5df747bbfba583f161a38af9dfe4d96c.tar.bz2 misskey-ca0d53ec5df747bbfba583f161a38af9dfe4d96c.zip | |
enhance(client): /authおよびMiAuthのUIをブラッシュアップ
Fix #9742
| -rw-r--r-- | CHANGELOG.md | 9 | ||||
| -rw-r--r-- | locales/ja-JP.yml | 2 | ||||
| -rw-r--r-- | packages/frontend/src/pages/auth.form.vue | 108 | ||||
| -rw-r--r-- | packages/frontend/src/pages/auth.vue | 170 | ||||
| -rw-r--r-- | packages/frontend/src/pages/miauth.vue | 78 |
5 files changed, 207 insertions, 160 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index c9bda35348..d3ccb5f864 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,15 @@ You should also include the user name that made the change. --> +## 13.x.x (unreleased) + +### Improvements +- 非ログイン時にMiAuthを踏んだ際にMiAuthであることを表示する +- /auth/のUIをアップデート + +### Bugfixes +- + ## 13.5.4 (2023/02/09) ### Improvements diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 09069e7801..60f492d66e 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1628,12 +1628,14 @@ _permissions: "write:gallery-likes": "ギャラリーのいいねを操作する" _auth: + shareAccessTitle: "アプリへのアクセス許可" shareAccess: "「{name}」がアカウントにアクセスすることを許可しますか?" shareAccessAsk: "アカウントへのアクセスを許可しますか?" permissionAsk: "このアプリは次の権限を要求しています" pleaseGoBack: "アプリケーションに戻ってやっていってください" callback: "アプリケーションに戻っています" denied: "アクセスを拒否しました" + pleaseLogin: "アプリケーションにアクセス許可を与えるには、ログインが必要です。" _antennaSources: all: "全てのノート" diff --git a/packages/frontend/src/pages/auth.form.vue b/packages/frontend/src/pages/auth.form.vue index 801295fce9..1a1cd55eee 100644 --- a/packages/frontend/src/pages/auth.form.vue +++ b/packages/frontend/src/pages/auth.form.vue @@ -1,60 +1,66 @@ <template> -<section class=""> - <div class="">{{ $t('_auth.shareAccess', { name: app.name }) }}</div> - <div class=""> - <h2>{{ app.name }}</h2> - <p class="id">{{ app.id }}</p> - <p class="description">{{ app.description }}</p> - </div> - <div class=""> - <h2>{{ $ts._auth.permissionAsk }}</h2> - <ul> - <li v-for="p in app.permission" :key="p">{{ $t(`_permissions.${p}`) }}</li> - </ul> - </div> - <div class=""> - <MkButton inline @click="cancel">{{ $ts.cancel }}</MkButton> - <MkButton inline primary @click="accept">{{ $ts.accept }}</MkButton> - </div> -</section> + <section> + <div v-if="app.permission.length > 0"> + <p>{{ i18n.ts._auth.permissionAsk }}</p> + <ul> + <li v-for="p in app.permission" :key="p">{{ $t(`_permissions.${p}`) }}</li> + </ul> + </div> + <div>{{ i18n.t('_auth.shareAccess', { name: `${name} (${app.id})` }) }}</div> + <div :class="$style.buttons"> + <MkButton inline @click="cancel">{{ i18n.ts.cancel }}</MkButton> + <MkButton inline primary @click="accept">{{ i18n.ts.accept }}</MkButton> + </div> + </section> </template> -<script lang="ts"> -import { defineComponent } from 'vue'; +<script lang="ts" setup> +import { } from 'vue'; import MkButton from '@/components/MkButton.vue'; import * as os from '@/os'; +import { i18n } from '@/i18n'; +import { AuthSession } from 'misskey-js/built/entities'; -export default defineComponent({ - components: { - MkButton, - }, - props: ['session'], - computed: { - name(): string { - const el = document.createElement('div'); - el.textContent = this.app.name; - return el.innerHTML; - }, - app(): any { - return this.session.app; - }, - }, - methods: { - cancel() { - os.api('auth/deny', { - token: this.session.token, - }).then(() => { - this.$emit('denied'); - }); - }, +const props = defineProps<{ + session: AuthSession; +}>(); - accept() { - os.api('auth/accept', { - token: this.session.token, - }).then(() => { - this.$emit('accepted'); - }); - }, - }, +const emit = defineEmits<{ + (event: 'accepted'): void; + (event: 'denied'): void; +}>(); + +const app = $computed(() => props.session.app); + +const name = $computed(() => { + const el = document.createElement('div'); + el.textContent = app.name; + return el.innerHTML; }); + +function cancel() { + os.api('auth/deny', { + token: props.session.token, + }).then(() => { + emit('denied'); + }); +} + +function accept() { + os.api('auth/accept', { + token: props.session.token, + }).then(() => { + emit('accepted'); + }); +} + </script> + +<style lang="scss" module> +.buttons { + margin-top: 16px; + display: flex; + gap: 8px; + flex-wrap: wrap; +} +</style> diff --git a/packages/frontend/src/pages/auth.vue b/packages/frontend/src/pages/auth.vue index b7727ca30d..50afffc460 100644 --- a/packages/frontend/src/pages/auth.vue +++ b/packages/frontend/src/pages/auth.vue @@ -1,93 +1,105 @@ <template> -<div v-if="$i && fetching" class=""> - <MkLoading/> -</div> -<div v-else-if="$i"> - <XForm - v-if="state == 'waiting'" - ref="form" - class="form" - :session="session" - @denied="state = 'denied'" - @accepted="accepted" - /> - <div v-if="state == 'denied'" class="denied"> - <h1>{{ $ts._auth.denied }}</h1> - </div> - <div v-if="state == 'accepted'" class="accepted"> - <h1>{{ session.app.isAuthorized ? $t('already-authorized') : $ts.allowed }}</h1> - <p v-if="session.app.callbackUrl">{{ $ts._auth.callback }}<MkEllipsis/></p> - <p v-if="!session.app.callbackUrl">{{ $ts._auth.pleaseGoBack }}</p> - </div> - <div v-if="state == 'fetch-session-error'" class="error"> - <p>{{ $ts.somethingHappened }}</p> - </div> -</div> -<div v-else class="signin"> - <MkSignin @login="onLogin"/> -</div> +<MkStickyContainer> + <template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs" /></template> + <MkSpacer :content-max="500"> + <div v-if="state == 'fetch-session-error'"> + <p>{{ i18n.ts.somethingHappened }}</p> + </div> + <div v-else-if="$i && !session"> + <MkLoading /> + </div> + <div v-else-if="$i && session"> + <XForm + v-if="state == 'waiting'" + class="form" + :session="session" + @denied="state = 'denied'" + @accepted="accepted" + /> + <div v-if="state == 'denied'"> + <h1>{{ i18n.ts._auth.denied }}</h1> + </div> + <div v-if="state == 'accepted' && session"> + <h1>{{ session.app.isAuthorized ? $t('already-authorized') : i18n.ts.allowed }}</h1> + <p v-if="session.app.callbackUrl">{{ i18n.ts._auth.callback }} + <MkEllipsis /> + </p> + <p v-if="!session.app.callbackUrl">{{ i18n.ts._auth.pleaseGoBack }}</p> + </div> + </div> + <div v-else> + <p :class="$style.loginMessage">{{ i18n.ts._auth.pleaseLogin }}</p> + <MkSignin @login="onLogin" /> + </div> + </MkSpacer> +</MkStickyContainer> </template> -<script lang="ts"> -import { defineComponent } from 'vue'; +<script lang="ts" setup> +import { onMounted } from 'vue'; import XForm from './auth.form.vue'; import MkSignin from '@/components/MkSignin.vue'; import * as os from '@/os'; -import { login } from '@/account'; +import { $i, login } from '@/account'; +import { definePageMetadata } from '@/scripts/page-metadata'; +import { AuthSession } from 'misskey-js/built/entities'; +import { i18n } from '@/i18n'; -export default defineComponent({ - components: { - XForm, - MkSignin, - }, - props: ['token'], - data() { - return { - state: null, - session: null, - fetching: true, - }; - }, - mounted() { - if (!this.$i) return; +const props = defineProps<{ + token: string; +}>(); - // Fetch session - os.api('auth/session/show', { - token: this.token, - }).then(session => { - this.session = session; - this.fetching = false; +let state = $ref<'waiting' | 'accepted' | 'fetch-session-error' | 'denied' | null>(null); +let session = $ref<AuthSession | null>(null); - // 既に連携していた場合 - if (this.session.app.isAuthorized) { - os.api('auth/accept', { - token: this.session.token, - }).then(() => { - this.accepted(); - }); - } else { - this.state = 'waiting'; - } - }).catch(error => { - this.state = 'fetch-session-error'; - this.fetching = false; +function accepted() { + state = 'accepted'; + if (session && session.app.callbackUrl) { + const url = new URL(session.app.callbackUrl); + if (['javascript:', 'file:', 'data:', 'mailto:', 'tel:'].includes(url.protocol)) throw new Error('invalid url'); + location.href = `${session.app.callbackUrl}?token=${session.token}`; + } +} + +function onLogin(res) { + login(res.i); +} + +onMounted(async () => { + if (!$i) return; + + try { + session = await os.api('auth/session/show', { + token: props.token, }); - }, - methods: { - accepted() { - this.state = 'accepted'; - if (this.session.app.callbackUrl) { - const url = new URL(this.session.app.callbackUrl); - if (['javascript:', 'file:', 'data:', 'mailto:', 'tel:'].includes(url.protocol)) throw new Error('invalid url'); - location.href = `${this.session.app.callbackUrl}?token=${this.session.token}`; - } - }, onLogin(res) { - login(res.i); - }, - }, + + // 既に連携していた場合 + if (session.app.isAuthorized) { + await os.api('auth/accept', { + token: session.token, + }); + accepted(); + } else { + state = 'waiting'; + } + } catch (e) { + state = 'fetch-session-error'; + } }); -</script> -<style lang="scss" scoped> +const headerActions = $computed(() => []); + +const headerTabs = $computed(() => []); + +definePageMetadata({ + title: i18n.ts._auth.shareAccessTitle, + icon: 'ti ti-apps', +}); +</script> +<style lang="scss" module> +.loginMessage { + text-align: center; + margin: 8px 0 24px; +} </style> diff --git a/packages/frontend/src/pages/miauth.vue b/packages/frontend/src/pages/miauth.vue index 9a4019e5b1..0a82ef8e44 100644 --- a/packages/frontend/src/pages/miauth.vue +++ b/packages/frontend/src/pages/miauth.vue @@ -1,41 +1,39 @@ <template> -<MkSpacer :content-max="800"> - <div v-if="$i"> - <div v-if="state == 'waiting'" class="waiting"> - <div class=""> +<MkStickyContainer> + <template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs" /></template> + <MkSpacer :content-max="800"> + <div v-if="$i"> + <div v-if="state == 'waiting'"> <MkLoading/> </div> - </div> - <div v-if="state == 'denied'" class="denied"> - <div class=""> + <div v-if="state == 'denied'"> <p>{{ i18n.ts._auth.denied }}</p> </div> - </div> - <div v-else-if="state == 'accepted'" class="accepted"> - <div class=""> + <div v-else-if="state == 'accepted'" class="accepted"> <p v-if="callback">{{ i18n.ts._auth.callback }}<MkEllipsis/></p> <p v-else>{{ i18n.ts._auth.pleaseGoBack }}</p> </div> - </div> - <div v-else class=""> - <div v-if="name" class="">{{ $t('_auth.shareAccess', { name: name }) }}</div> - <div v-else class="">{{ i18n.ts._auth.shareAccessAsk }}</div> - <div class=""> - <p>{{ i18n.ts._auth.permissionAsk }}</p> - <ul> - <li v-for="p in _permissions" :key="p">{{ $t(`_permissions.${p}`) }}</li> - </ul> - </div> - <div class=""> - <MkButton inline @click="deny">{{ i18n.ts.cancel }}</MkButton> - <MkButton inline primary @click="accept">{{ i18n.ts.accept }}</MkButton> + <div v-else> + <div v-if="name">{{ $t('_auth.shareAccess', { name: name }) }}</div> + <div v-else>{{ i18n.ts._auth.shareAccessAsk }}</div> + <div v-if="_permissions.length > 0"> + <p>{{ i18n.ts._auth.permissionAsk }}</p> + <ul> + <li v-for="p in _permissions" :key="p">{{ $t(`_permissions.${p}`) }}</li> + </ul> + </div> + <div :class="$style.buttons"> + <MkButton inline @click="deny">{{ i18n.ts.cancel }}</MkButton> + <MkButton inline primary @click="accept">{{ i18n.ts.accept }}</MkButton> + </div> </div> </div> - </div> - <div v-else class="signin"> - <MkSignin @login="onLogin"/> - </div> -</MkSpacer> + <div v-else> + <p :class="$style.loginMessage">{{ i18n.ts._auth.pleaseLogin }}</p> + <MkSignin @login="onLogin"/> + </div> + </MkSpacer> +</MkStickyContainer> </template> <script lang="ts" setup> @@ -45,6 +43,7 @@ import MkButton from '@/components/MkButton.vue'; import * as os from '@/os'; import { $i, login } from '@/account'; import { i18n } from '@/i18n'; +import { definePageMetadata } from '@/scripts/page-metadata'; const props = defineProps<{ session: string; @@ -54,7 +53,7 @@ const props = defineProps<{ permission: string; // コンマ区切り }>(); -const _permissions = props.permission.split(','); +const _permissions = props.permission ? props.permission.split(',') : []; let state = $ref<string | null>(null); @@ -83,8 +82,27 @@ function deny(): void { function onLogin(res): void { login(res.i); } + +const headerActions = $computed(() => []); + +const headerTabs = $computed(() => []); + +definePageMetadata({ + title: 'MiAuth', + icon: 'ti ti-apps', +}); </script> -<style lang="scss" scoped> +<style lang="scss" module> +.buttons { + margin-top: 16px; + display: flex; + gap: 8px; + flex-wrap: wrap; +} +.loginMessage { + text-align: center; + margin: 8px 0 24px; +} </style> |