diff options
Diffstat (limited to 'packages/client/src/pages/settings')
17 files changed, 582 insertions, 625 deletions
diff --git a/packages/client/src/pages/settings/2fa.vue b/packages/client/src/pages/settings/2fa.vue index 8921480271..cffd10a0ee 100644 --- a/packages/client/src/pages/settings/2fa.vue +++ b/packages/client/src/pages/settings/2fa.vue @@ -1,69 +1,66 @@ <template> -<section class="_card"> - <div class="_title"><i class="fas fa-lock"></i> {{ $ts.twoStepAuthentication }}</div> - <div class="_content"> - <MkButton v-if="!data && !$i.twoFactorEnabled" @click="register">{{ $ts._2fa.registerDevice }}</MkButton> - <template v-if="$i.twoFactorEnabled"> - <p>{{ $ts._2fa.alreadyRegistered }}</p> - <MkButton @click="unregister">{{ $ts.unregister }}</MkButton> +<div> + <MkButton v-if="!data && !$i.twoFactorEnabled" @click="register">{{ $ts._2fa.registerDevice }}</MkButton> + <template v-if="$i.twoFactorEnabled"> + <p>{{ $ts._2fa.alreadyRegistered }}</p> + <MkButton @click="unregister">{{ $ts.unregister }}</MkButton> - <template v-if="supportsCredentials"> - <hr class="totp-method-sep"> + <template v-if="supportsCredentials"> + <hr class="totp-method-sep"> - <h2 class="heading">{{ $ts.securityKey }}</h2> - <p>{{ $ts._2fa.securityKeyInfo }}</p> - <div class="key-list"> - <div v-for="key in $i.securityKeysList" class="key"> - <h3>{{ key.name }}</h3> - <div class="last-used">{{ $ts.lastUsed }}<MkTime :time="key.lastUsed"/></div> - <MkButton @click="unregisterKey(key)">{{ $ts.unregister }}</MkButton> - </div> + <h2 class="heading">{{ $ts.securityKey }}</h2> + <p>{{ $ts._2fa.securityKeyInfo }}</p> + <div class="key-list"> + <div v-for="key in $i.securityKeysList" class="key"> + <h3>{{ key.name }}</h3> + <div class="last-used">{{ $ts.lastUsed }}<MkTime :time="key.lastUsed"/></div> + <MkButton @click="unregisterKey(key)">{{ $ts.unregister }}</MkButton> </div> + </div> - <MkSwitch v-if="$i.securityKeysList.length > 0" v-model="usePasswordLessLogin" @update:modelValue="updatePasswordLessLogin">{{ $ts.passwordLessLogin }}</MkSwitch> + <MkSwitch v-if="$i.securityKeysList.length > 0" v-model="usePasswordLessLogin" @update:modelValue="updatePasswordLessLogin">{{ $ts.passwordLessLogin }}</MkSwitch> - <MkInfo v-if="registration && registration.error" warn>{{ $ts.error }} {{ registration.error }}</MkInfo> - <MkButton v-if="!registration || registration.error" @click="addSecurityKey">{{ $ts._2fa.registerKey }}</MkButton> + <MkInfo v-if="registration && registration.error" warn>{{ $ts.error }} {{ registration.error }}</MkInfo> + <MkButton v-if="!registration || registration.error" @click="addSecurityKey">{{ $ts._2fa.registerKey }}</MkButton> - <ol v-if="registration && !registration.error"> - <li v-if="registration.stage >= 0"> - {{ $ts.tapSecurityKey }} - <i v-if="registration.saving && registration.stage == 0" class="fas fa-spinner fa-pulse fa-fw"></i> - </li> - <li v-if="registration.stage >= 1"> - <MkForm :disabled="registration.stage != 1 || registration.saving"> - <MkInput v-model="keyName" :max="30"> - <template #label>{{ $ts.securityKeyName }}</template> - </MkInput> - <MkButton :disabled="keyName.length == 0" @click="registerKey">{{ $ts.registerSecurityKey }}</MkButton> - <i v-if="registration.saving && registration.stage == 1" class="fas fa-spinner fa-pulse fa-fw"></i> - </MkForm> - </li> - </ol> - </template> - </template> - <div v-if="data && !$i.twoFactorEnabled"> - <ol style="margin: 0; padding: 0 0 0 1em;"> - <li> - <I18n :src="$ts._2fa.step1" tag="span"> - <template #a> - <a href="https://authy.com/" rel="noopener" target="_blank" class="_link">Authy</a> - </template> - <template #b> - <a href="https://support.google.com/accounts/answer/1066447" rel="noopener" target="_blank" class="_link">Google Authenticator</a> - </template> - </I18n> + <ol v-if="registration && !registration.error"> + <li v-if="registration.stage >= 0"> + {{ $ts.tapSecurityKey }} + <i v-if="registration.saving && registration.stage == 0" class="fas fa-spinner fa-pulse fa-fw"></i> </li> - <li>{{ $ts._2fa.step2 }}<br><img :src="data.qr"></li> - <li>{{ $ts._2fa.step3 }}<br> - <MkInput v-model="token" type="text" pattern="^[0-9]{6}$" autocomplete="off" spellcheck="false"><template #label>{{ $ts.token }}</template></MkInput> - <MkButton primary @click="submit">{{ $ts.done }}</MkButton> + <li v-if="registration.stage >= 1"> + <MkForm :disabled="registration.stage != 1 || registration.saving"> + <MkInput v-model="keyName" :max="30"> + <template #label>{{ $ts.securityKeyName }}</template> + </MkInput> + <MkButton :disabled="keyName.length == 0" @click="registerKey">{{ $ts.registerSecurityKey }}</MkButton> + <i v-if="registration.saving && registration.stage == 1" class="fas fa-spinner fa-pulse fa-fw"></i> + </MkForm> </li> </ol> - <MkInfo>{{ $ts._2fa.step4 }}</MkInfo> - </div> + </template> + </template> + <div v-if="data && !$i.twoFactorEnabled"> + <ol style="margin: 0; padding: 0 0 0 1em;"> + <li> + <I18n :src="$ts._2fa.step1" tag="span"> + <template #a> + <a href="https://authy.com/" rel="noopener" target="_blank" class="_link">Authy</a> + </template> + <template #b> + <a href="https://support.google.com/accounts/answer/1066447" rel="noopener" target="_blank" class="_link">Google Authenticator</a> + </template> + </I18n> + </li> + <li>{{ $ts._2fa.step2 }}<br><img :src="data.qr"></li> + <li>{{ $ts._2fa.step3 }}<br> + <MkInput v-model="token" type="text" pattern="^[0-9]{6}$" autocomplete="off" spellcheck="false"><template #label>{{ $ts.token }}</template></MkInput> + <MkButton primary @click="submit">{{ $ts.done }}</MkButton> + </li> + </ol> + <MkInfo>{{ $ts._2fa.step4 }}</MkInfo> </div> -</section> +</div> </template> <script lang="ts"> @@ -82,18 +79,11 @@ import * as symbols from '@/symbols'; export default defineComponent({ components: { - FormBase, MkButton, MkInfo, MkInput, MkSwitch }, - emits: ['info'], - data() { return { - [symbols.PAGE_INFO]: { - title: this.$ts.twoStepAuthentication, - icon: 'fas fa-lock' - }, data: null, supportsCredentials: !!navigator.credentials, usePasswordLessLogin: this.$i.usePasswordLessLogin, diff --git a/packages/client/src/pages/settings/drive.vue b/packages/client/src/pages/settings/drive.vue index 1fcfed2114..9ab99c6efe 100644 --- a/packages/client/src/pages/settings/drive.vue +++ b/packages/client/src/pages/settings/drive.vue @@ -1,44 +1,43 @@ <template> -<FormBase class=""> - <FormGroup v-if="!fetching"> +<div class="_formRoot"> + <FormSection v-if="!fetching"> <template #label>{{ $ts.usageAmount }}</template> - <div class="_debobigegoItem uawsfosz"> - <div class="_debobigegoPanel"> - <div class="meter"><div :style="meterStyle"></div></div> - </div> + <div class="_formBlock uawsfosz"> + <div class="meter"><div :style="meterStyle"></div></div> </div> - <FormKeyValueView> - <template #key>{{ $ts.capacity }}</template> - <template #value>{{ bytes(capacity, 1) }}</template> - </FormKeyValueView> - <FormKeyValueView> - <template #key>{{ $ts.inUse }}</template> - <template #value>{{ bytes(usage, 1) }}</template> - </FormKeyValueView> - </FormGroup> - - <div class="_debobigegoItem"> - <div class="_debobigegoLabel">{{ $ts.statistics }}</div> - <div class="_debobigegoPanel"> - <div ref="chart"></div> + <div class="_inputSplit _formBlock"> + <MkKeyValue class="_formBlock"> + <template #key>{{ $ts.capacity }}</template> + <template #value>{{ bytes(capacity, 1) }}</template> + </MkKeyValue> + <MkKeyValue class="_formBlock"> + <template #key>{{ $ts.inUse }}</template> + <template #value>{{ bytes(usage, 1) }}</template> + </MkKeyValue> </div> - </div> + </FormSection> + + <FormSection> + <template #label>{{ $ts.statistics }}</template> + <div ref="chart"></div> + </FormSection> - <FormButton :center="false" primary @click="chooseUploadFolder()"> - {{ $ts.uploadFolder }} - <template #suffix>{{ uploadFolder ? uploadFolder.name : '-' }}</template> - <template #suffixIcon><i class="fas fa-folder-open"></i></template> - </FormButton> -</FormBase> + <FormSection> + <FormLink @click="chooseUploadFolder()"> + {{ $ts.uploadFolder }} + <template #suffix>{{ uploadFolder ? uploadFolder.name : '-' }}</template> + <template #suffixIcon><i class="fas fa-folder-open"></i></template> + </FormLink> + </FormSection> +</div> </template> <script lang="ts"> import { defineComponent } from 'vue'; import * as tinycolor from 'tinycolor2'; -import FormButton from '@/components/debobigego/button.vue'; -import FormGroup from '@/components/debobigego/group.vue'; -import FormKeyValueView from '@/components/debobigego/key-value-view.vue'; -import FormBase from '@/components/debobigego/base.vue'; +import FormLink from '@/components/form/link.vue'; +import FormSection from '@/components/form/section.vue'; +import MkKeyValue from '@/components/key-value.vue'; import * as os from '@/os'; import bytes from '@/filters/bytes'; import * as symbols from '@/symbols'; @@ -47,10 +46,9 @@ import * as symbols from '@/symbols'; export default defineComponent({ components: { - FormBase, - FormButton, - FormGroup, - FormKeyValueView, + FormLink, + FormSection, + MkKeyValue, }, emits: ['info'], @@ -128,19 +126,16 @@ export default defineComponent({ @use "sass:math"; .uawsfosz { - > div { - padding: 24px; - > .meter { - $size: 12px; - background: rgba(0, 0, 0, 0.1); - border-radius: math.div($size, 2); - overflow: hidden; + > .meter { + $size: 12px; + background: rgba(0, 0, 0, 0.1); + border-radius: math.div($size, 2); + overflow: hidden; - > div { - height: $size; - border-radius: math.div($size, 2); - } + > div { + height: $size; + border-radius: math.div($size, 2); } } } diff --git a/packages/client/src/pages/settings/email-address.vue b/packages/client/src/pages/settings/email-address.vue deleted file mode 100644 index c8ce61716f..0000000000 --- a/packages/client/src/pages/settings/email-address.vue +++ /dev/null @@ -1,68 +0,0 @@ -<template> -<FormBase> - <FormGroup> - <FormInput v-model="emailAddress" type="email"> - {{ $ts.emailAddress }} - <template v-if="$i.email && !$i.emailVerified" #desc>{{ $ts.verificationEmailSent }}</template> - <template v-else-if="emailAddress === $i.email && $i.emailVerified" #desc>{{ $ts.emailVerified }}</template> - </FormInput> - </FormGroup> - <FormButton primary @click="save">{{ $ts.save }}</FormButton> -</FormBase> -</template> - -<script lang="ts"> -import { defineComponent } from 'vue'; -import FormButton from '@/components/debobigego/button.vue'; -import FormInput from '@/components/form/input.vue'; -import FormBase from '@/components/debobigego/base.vue'; -import FormGroup from '@/components/debobigego/group.vue'; -import * as os from '@/os'; -import * as symbols from '@/symbols'; - -export default defineComponent({ - components: { - FormBase, - FormInput, - FormButton, - FormGroup, - }, - - emits: ['info'], - - data() { - return { - [symbols.PAGE_INFO]: { - title: this.$ts.emailAddress, - icon: 'fas fa-envelope', - bg: 'var(--bg)', - }, - emailAddress: null, - code: null, - } - }, - - created() { - this.emailAddress = this.$i.email; - }, - - mounted() { - this.$emit('info', this[symbols.PAGE_INFO]); - }, - - methods: { - save() { - os.inputText({ - title: this.$ts.password, - type: 'password' - }).then(({ canceled, result: password }) => { - if (canceled) return; - os.apiWithDialog('i/update-email', { - password: password, - email: this.emailAddress, - }); - }); - } - } -}); -</script> diff --git a/packages/client/src/pages/settings/email-notification.vue b/packages/client/src/pages/settings/email-notification.vue deleted file mode 100644 index c1735a0728..0000000000 --- a/packages/client/src/pages/settings/email-notification.vue +++ /dev/null @@ -1,91 +0,0 @@ -<template> -<FormBase> - <FormGroup> - <FormSwitch v-model="mention"> - {{ $ts._notification._types.mention }} - </FormSwitch> - <FormSwitch v-model="reply"> - {{ $ts._notification._types.reply }} - </FormSwitch> - <FormSwitch v-model="quote"> - {{ $ts._notification._types.quote }} - </FormSwitch> - <FormSwitch v-model="follow"> - {{ $ts._notification._types.follow }} - </FormSwitch> - <FormSwitch v-model="receiveFollowRequest"> - {{ $ts._notification._types.receiveFollowRequest }} - </FormSwitch> - <FormSwitch v-model="groupInvited"> - {{ $ts._notification._types.groupInvited }} - </FormSwitch> - </FormGroup> -</FormBase> -</template> - -<script lang="ts"> -import { defineComponent } from 'vue'; -import FormButton from '@/components/debobigego/button.vue'; -import FormSwitch from '@/components/form/switch.vue'; -import FormBase from '@/components/debobigego/base.vue'; -import FormGroup from '@/components/debobigego/group.vue'; -import * as os from '@/os'; -import * as symbols from '@/symbols'; -import * as symbols from '@/symbols'; - -export default defineComponent({ - components: { - FormBase, - FormSwitch, - FormButton, - FormGroup, - }, - - emits: ['info'], - - data() { - return { - [symbols.PAGE_INFO]: { - title: this.$ts.emailNotification, - icon: 'fas fa-envelope', - bg: 'var(--bg)', - }, - - mention: this.$i.emailNotificationTypes.includes('mention'), - reply: this.$i.emailNotificationTypes.includes('reply'), - quote: this.$i.emailNotificationTypes.includes('quote'), - follow: this.$i.emailNotificationTypes.includes('follow'), - receiveFollowRequest: this.$i.emailNotificationTypes.includes('receiveFollowRequest'), - groupInvited: this.$i.emailNotificationTypes.includes('groupInvited'), - } - }, - - created() { - this.$watch('mention', this.save); - this.$watch('reply', this.save); - this.$watch('quote', this.save); - this.$watch('follow', this.save); - this.$watch('receiveFollowRequest', this.save); - this.$watch('groupInvited', this.save); - }, - - mounted() { - this.$emit('info', this[symbols.PAGE_INFO]); - }, - - methods: { - save() { - os.api('i/update', { - emailNotificationTypes: [ - ...[this.mention ? 'mention' : null], - ...[this.reply ? 'reply' : null], - ...[this.quote ? 'quote' : null], - ...[this.follow ? 'follow' : null], - ...[this.receiveFollowRequest ? 'receiveFollowRequest' : null], - ...[this.groupInvited ? 'groupInvited' : null], - ].filter(x => x != null) - }); - } - } -}); -</script> diff --git a/packages/client/src/pages/settings/email.vue b/packages/client/src/pages/settings/email.vue index d1dda20f00..b04295cce0 100644 --- a/packages/client/src/pages/settings/email.vue +++ b/packages/client/src/pages/settings/email.vue @@ -1,66 +1,133 @@ <template> -<FormBase> - <FormGroup> +<div class="_formRoot"> + <FormSection> <template #label>{{ $ts.emailAddress }}</template> - <FormLink to="/settings/email/address"> - <template v-if="$i.email && !$i.emailVerified" #icon><i class="fas fa-exclamation-triangle" style="color: var(--warn);"></i></template> - <template v-else-if="$i.email && $i.emailVerified" #icon><i class="fas fa-check" style="color: var(--success);"></i></template> - {{ $i.email || $ts.notSet }} - </FormLink> - </FormGroup> + <FormInput v-model="emailAddress" type="email" manual-save> + <template #prefix><i class="fas fa-envelope"></i></template> + <template v-if="$i.email && !$i.emailVerified" #caption>{{ $ts.verificationEmailSent }}</template> + <template v-else-if="emailAddress === $i.email && $i.emailVerified" #caption><i class="fas fa-check" style="color: var(--success);"></i> {{ $ts.emailVerified }}</template> + </FormInput> + </FormSection> - <FormLink to="/settings/email/notification"> - <template #icon><i class="fas fa-bell"></i></template> - {{ $ts.emailNotification }} - </FormLink> + <FormSection> + <FormSwitch :value="$i.receiveAnnouncementEmail" @update:modelValue="onChangeReceiveAnnouncementEmail"> + {{ $ts.receiveAnnouncementFromInstance }} + </FormSwitch> + </FormSection> - <FormSwitch :value="$i.receiveAnnouncementEmail" @update:modelValue="onChangeReceiveAnnouncementEmail"> - {{ $ts.receiveAnnouncementFromInstance }} - </FormSwitch> -</FormBase> + <FormSection> + <template #label>{{ $ts.emailNotification }}</template> + <FormSwitch v-model="emailNotification_mention" class="_formBlock"> + {{ $ts._notification._types.mention }} + </FormSwitch> + <FormSwitch v-model="emailNotification_reply" class="_formBlock"> + {{ $ts._notification._types.reply }} + </FormSwitch> + <FormSwitch v-model="emailNotification_quote" class="_formBlock"> + {{ $ts._notification._types.quote }} + </FormSwitch> + <FormSwitch v-model="emailNotification_follow" class="_formBlock"> + {{ $ts._notification._types.follow }} + </FormSwitch> + <FormSwitch v-model="emailNotification_receiveFollowRequest" class="_formBlock"> + {{ $ts._notification._types.receiveFollowRequest }} + </FormSwitch> + <FormSwitch v-model="emailNotification_groupInvited" class="_formBlock"> + {{ $ts._notification._types.groupInvited }} + </FormSwitch> + </FormSection> +</div> </template> <script lang="ts"> -import { defineComponent } from 'vue'; +import { defineComponent, onMounted, ref, watch } from 'vue'; import FormButton from '@/components/debobigego/button.vue'; import FormLink from '@/components/debobigego/link.vue'; -import FormBase from '@/components/debobigego/base.vue'; -import FormGroup from '@/components/debobigego/group.vue'; -import FormSwitch from '@/components/debobigego/switch.vue'; +import FormSection from '@/components/form/section.vue'; +import FormInput from '@/components/form/input.vue'; +import FormSwitch from '@/components/form/switch.vue'; import * as os from '@/os'; import * as symbols from '@/symbols'; +import { $i } from '@/account'; +import { i18n } from '@/i18n'; export default defineComponent({ components: { - FormBase, + FormSection, FormLink, FormButton, FormSwitch, - FormGroup, + FormInput, }, emits: ['info'], - - data() { - return { - [symbols.PAGE_INFO]: { - title: this.$ts.email, - icon: 'fas fa-envelope', - bg: 'var(--bg)', - }, - } - }, - mounted() { - this.$emit('info', this[symbols.PAGE_INFO]); - }, + setup(props, context) { + const emailAddress = ref($i.email); - methods: { - onChangeReceiveAnnouncementEmail(v) { + const INFO = { + title: i18n.locale.email, + icon: 'fas fa-envelope', + bg: 'var(--bg)', + }; + + const onChangeReceiveAnnouncementEmail = (v) => { os.api('i/update', { receiveAnnouncementEmail: v }); - }, - } + }; + + const saveEmailAddress = () => { + os.inputText({ + title: i18n.locale.password, + type: 'password' + }).then(({ canceled, result: password }) => { + if (canceled) return; + os.apiWithDialog('i/update-email', { + password: password, + email: emailAddress.value, + }); + }); + }; + + const emailNotification_mention = ref($i.emailNotificationTypes.includes('mention')); + const emailNotification_reply = ref($i.emailNotificationTypes.includes('reply')); + const emailNotification_quote = ref($i.emailNotificationTypes.includes('quote')); + const emailNotification_follow = ref($i.emailNotificationTypes.includes('follow')); + const emailNotification_receiveFollowRequest = ref($i.emailNotificationTypes.includes('receiveFollowRequest')); + const emailNotification_groupInvited = ref($i.emailNotificationTypes.includes('groupInvited')); + + const saveNotificationSettings = () => { + os.api('i/update', { + emailNotificationTypes: [ + ...[emailNotification_mention.value ? 'mention' : null], + ...[emailNotification_reply.value ? 'reply' : null], + ...[emailNotification_quote.value ? 'quote' : null], + ...[emailNotification_follow.value ? 'follow' : null], + ...[emailNotification_receiveFollowRequest.value ? 'receiveFollowRequest' : null], + ...[emailNotification_groupInvited.value ? 'groupInvited' : null], + ].filter(x => x != null) + }); + }; + + watch([emailNotification_mention, emailNotification_reply, emailNotification_quote, emailNotification_follow, emailNotification_receiveFollowRequest, emailNotification_groupInvited], () => { + saveNotificationSettings(); + }); + + onMounted(() => { + context.emit('info', INFO); + + watch(emailAddress, () => { + saveEmailAddress(); + }); + }); + + return { + [symbols.PAGE_INFO]: INFO, + emailAddress, + onChangeReceiveAnnouncementEmail, + emailNotification_mention, emailNotification_reply, emailNotification_quote, emailNotification_follow, emailNotification_receiveFollowRequest, emailNotification_groupInvited, + }; + }, }); </script> diff --git a/packages/client/src/pages/settings/general.vue b/packages/client/src/pages/settings/general.vue index ac8e04511c..57a4b25574 100644 --- a/packages/client/src/pages/settings/general.vue +++ b/packages/client/src/pages/settings/general.vue @@ -1,8 +1,6 @@ <template> -<FormBase> - <FormSwitch v-model="showFixedPostForm">{{ $ts.showFixedPostForm }}</FormSwitch> - - <FormSelect v-model="lang"> +<div class="_formRoot"> + <FormSelect v-model="lang" class="_formBlock"> <template #label>{{ $ts.uiLanguage }}</template> <option v-for="x in langs" :key="x[0]" :value="x[0]">{{ x[1] }}</option> <template #caption> @@ -14,57 +12,59 @@ </template> </FormSelect> - <FormGroup> + <FormSwitch v-model="showFixedPostForm" class="_formBlock">{{ $ts.showFixedPostForm }}</FormSwitch> + + <FormSection> <template #label>{{ $ts.behavior }}</template> - <FormSwitch v-model="imageNewTab">{{ $ts.openImageInNewTab }}</FormSwitch> - <FormSwitch v-model="enableInfiniteScroll">{{ $ts.enableInfiniteScroll }}</FormSwitch> - <FormSwitch v-model="useReactionPickerForContextMenu">{{ $ts.useReactionPickerForContextMenu }}</FormSwitch> - <FormSwitch v-model="disablePagesScript">{{ $ts.disablePagesScript }}</FormSwitch> - </FormGroup> + <FormSwitch v-model="imageNewTab" class="_formBlock">{{ $ts.openImageInNewTab }}</FormSwitch> + <FormSwitch v-model="enableInfiniteScroll" class="_formBlock">{{ $ts.enableInfiniteScroll }}</FormSwitch> + <FormSwitch v-model="useReactionPickerForContextMenu" class="_formBlock">{{ $ts.useReactionPickerForContextMenu }}</FormSwitch> + <FormSwitch v-model="disablePagesScript" class="_formBlock">{{ $ts.disablePagesScript }}</FormSwitch> - <FormSelect v-model="serverDisconnectedBehavior"> - <template #label>{{ $ts.whenServerDisconnected }}</template> - <option value="reload">{{ $ts._serverDisconnectedBehavior.reload }}</option> - <option value="dialog">{{ $ts._serverDisconnectedBehavior.dialog }}</option> - <option value="quiet">{{ $ts._serverDisconnectedBehavior.quiet }}</option> - </FormSelect> + <FormSelect v-model="serverDisconnectedBehavior" class="_formBlock"> + <template #label>{{ $ts.whenServerDisconnected }}</template> + <option value="reload">{{ $ts._serverDisconnectedBehavior.reload }}</option> + <option value="dialog">{{ $ts._serverDisconnectedBehavior.dialog }}</option> + <option value="quiet">{{ $ts._serverDisconnectedBehavior.quiet }}</option> + </FormSelect> + </FormSection> - <FormGroup> + <FormSection> <template #label>{{ $ts.appearance }}</template> - <FormSwitch v-model="disableAnimatedMfm">{{ $ts.disableAnimatedMfm }}</FormSwitch> - <FormSwitch v-model="reduceAnimation">{{ $ts.reduceUiAnimation }}</FormSwitch> - <FormSwitch v-model="useBlurEffect">{{ $ts.useBlurEffect }}</FormSwitch> - <FormSwitch v-model="useBlurEffectForModal">{{ $ts.useBlurEffectForModal }}</FormSwitch> - <FormSwitch v-model="showGapBetweenNotesInTimeline">{{ $ts.showGapBetweenNotesInTimeline }}</FormSwitch> - <FormSwitch v-model="loadRawImages">{{ $ts.loadRawImages }}</FormSwitch> - <FormSwitch v-model="disableShowingAnimatedImages">{{ $ts.disableShowingAnimatedImages }}</FormSwitch> - <FormSwitch v-model="squareAvatars">{{ $ts.squareAvatars }}</FormSwitch> - <FormSwitch v-model="useSystemFont">{{ $ts.useSystemFont }}</FormSwitch> - <FormSwitch v-model="useOsNativeEmojis">{{ $ts.useOsNativeEmojis }} + <FormSwitch v-model="disableAnimatedMfm" class="_formBlock">{{ $ts.disableAnimatedMfm }}</FormSwitch> + <FormSwitch v-model="reduceAnimation" class="_formBlock">{{ $ts.reduceUiAnimation }}</FormSwitch> + <FormSwitch v-model="useBlurEffect" class="_formBlock">{{ $ts.useBlurEffect }}</FormSwitch> + <FormSwitch v-model="useBlurEffectForModal" class="_formBlock">{{ $ts.useBlurEffectForModal }}</FormSwitch> + <FormSwitch v-model="showGapBetweenNotesInTimeline" class="_formBlock">{{ $ts.showGapBetweenNotesInTimeline }}</FormSwitch> + <FormSwitch v-model="loadRawImages" class="_formBlock">{{ $ts.loadRawImages }}</FormSwitch> + <FormSwitch v-model="disableShowingAnimatedImages" class="_formBlock">{{ $ts.disableShowingAnimatedImages }}</FormSwitch> + <FormSwitch v-model="squareAvatars" class="_formBlock">{{ $ts.squareAvatars }}</FormSwitch> + <FormSwitch v-model="useSystemFont" class="_formBlock">{{ $ts.useSystemFont }}</FormSwitch> + <FormSwitch v-model="useOsNativeEmojis" class="_formBlock">{{ $ts.useOsNativeEmojis }} <div><Mfm :key="useOsNativeEmojis" text="๐ฎ๐ฆ๐ญ๐ฉ๐ฐ๐ซ๐ฌ๐ฅ๐ช"/></div> </FormSwitch> - </FormGroup> - <FormGroup> - <FormSwitch v-model="aiChanMode">{{ $ts.aiChanMode }}</FormSwitch> - </FormGroup> + <FormRadios v-model="fontSize" class="_formBlock"> + <template #label>{{ $ts.fontSize }}</template> + <option value="small"><span style="font-size: 14px;">Aa</span></option> + <option :value="null"><span style="font-size: 16px;">Aa</span></option> + <option value="large"><span style="font-size: 18px;">Aa</span></option> + <option value="veryLarge"><span style="font-size: 20px;">Aa</span></option> + </FormRadios> + </FormSection> - <FormRadios v-model="fontSize"> - <template #desc>{{ $ts.fontSize }}</template> - <option value="small"><span style="font-size: 14px;">Aa</span></option> - <option :value="null"><span style="font-size: 16px;">Aa</span></option> - <option value="large"><span style="font-size: 18px;">Aa</span></option> - <option value="veryLarge"><span style="font-size: 20px;">Aa</span></option> - </FormRadios> + <FormSection> + <FormSwitch v-model="aiChanMode">{{ $ts.aiChanMode }}</FormSwitch> + </FormSection> - <FormSelect v-model="instanceTicker"> + <FormSelect v-model="instanceTicker" class="_formBlock"> <template #label>{{ $ts.instanceTicker }}</template> <option value="none">{{ $ts._instanceTicker.none }}</option> <option value="remote">{{ $ts._instanceTicker.remote }}</option> <option value="always">{{ $ts._instanceTicker.always }}</option> </FormSelect> - <FormSelect v-model="nsfw"> + <FormSelect v-model="nsfw" class="_formBlock"> <template #label>{{ $ts.nsfw }}</template> <option value="respect">{{ $ts._nsfw.respect }}</option> <option value="ignore">{{ $ts._nsfw.ignore }}</option> @@ -76,28 +76,27 @@ <FormSwitch v-model="defaultSideView">{{ $ts.openInSideView }}</FormSwitch> </FormGroup> - <FormSelect v-model="chatOpenBehavior"> + <FormSelect v-model="chatOpenBehavior" class="_formBlock"> <template #label>{{ $ts.chatOpenBehavior }}</template> <option value="page">{{ $ts.showInPage }}</option> <option value="window">{{ $ts.openInWindow }}</option> <option value="popout">{{ $ts.popout }}</option> </FormSelect> - <FormLink to="/settings/deck">{{ $ts.deck }}</FormLink> + <FormLink to="/settings/deck" class="_formBlock">{{ $ts.deck }}</FormLink> - <FormLink to="/settings/custom-css"><template #icon><i class="fas fa-code"></i></template>{{ $ts.customCss }}</FormLink> -</FormBase> + <FormLink to="/settings/custom-css" class="_formBlock"><template #icon><i class="fas fa-code"></i></template>{{ $ts.customCss }}</FormLink> +</div> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import FormSwitch from '@/components/debobigego/switch.vue'; -import FormSelect from '@/components/debobigego/select.vue'; -import FormRadios from '@/components/debobigego/radios.vue'; -import FormBase from '@/components/debobigego/base.vue'; -import FormGroup from '@/components/debobigego/group.vue'; -import FormLink from '@/components/debobigego/link.vue'; -import FormButton from '@/components/debobigego/button.vue'; +import FormSwitch from '@/components/form/switch.vue'; +import FormSelect from '@/components/form/select.vue'; +import FormRadios from '@/components/form/radios.vue'; +import FormGroup from '@/components/form/group.vue'; +import FormSection from '@/components/form/section.vue'; +import FormLink from '@/components/form/link.vue'; import MkLink from '@/components/link.vue'; import { langs } from '@/config'; import { defaultStore } from '@/store'; @@ -112,10 +111,9 @@ export default defineComponent({ FormSwitch, FormSelect, FormRadios, - FormBase, FormGroup, FormLink, - FormButton, + FormSection, }, emits: ['info'], diff --git a/packages/client/src/pages/settings/import-export.vue b/packages/client/src/pages/settings/import-export.vue index 4cc92adfb3..5b5b704695 100644 --- a/packages/client/src/pages/settings/import-export.vue +++ b/packages/client/src/pages/settings/import-export.vue @@ -1,5 +1,5 @@ <template> -<div style="margin: 16px;"> +<div class="_formRoot"> <FormSection> <template #label>{{ $ts._exportOrImport.allNotes }}</template> <MkButton :class="$style.button" inline @click="doExport('notes')"><i class="fas fa-download"></i> {{ $ts.export }}</MkButton> diff --git a/packages/client/src/pages/settings/index.vue b/packages/client/src/pages/settings/index.vue index 333d07c9c6..7a22a8dcd9 100644 --- a/packages/client/src/pages/settings/index.vue +++ b/packages/client/src/pages/settings/index.vue @@ -10,7 +10,12 @@ </MkSpacer> </div> <div class="main"> - <component :is="component" :key="page" v-bind="pageProps"/> + <MkSpacer :content-max="600" :margin-min="20"> + <div class="bkzroven"> + <div v-if="childInfo" class="title">{{ childInfo.title }}</div> + <component :is="component" :key="page" v-bind="pageProps" @info="onInfo"/> + </div> + </MkSpacer> </div> </div> </template> @@ -52,6 +57,7 @@ export default defineComponent({ const narrow = ref(false); const view = ref(null); const el = ref(null); + const childInfo = ref(null); const menuDef = computed(() => [{ title: i18n.locale.basicSettings, items: [{ @@ -192,8 +198,6 @@ export default defineComponent({ case 'other': return defineAsyncComponent(() => import('./other.vue')); case 'general': return defineAsyncComponent(() => import('./general.vue')); case 'email': return defineAsyncComponent(() => import('./email.vue')); - case 'email/address': return defineAsyncComponent(() => import('./email-address.vue')); - case 'email/notification': return defineAsyncComponent(() => import('./email-notification.vue')); case 'theme': return defineAsyncComponent(() => import('./theme.vue')); case 'theme/install': return defineAsyncComponent(() => import('./theme.install.vue')); case 'theme/manage': return defineAsyncComponent(() => import('./theme.manage.vue')); @@ -259,6 +263,10 @@ export default defineComponent({ const emailNotConfigured = computed(() => instance.enableEmail && ($i.email == null || !$i.emailVerified)); + const onInfo = (info) => { + childInfo.value = info; + }; + return { [symbols.PAGE_INFO]: INFO, page, @@ -269,6 +277,8 @@ export default defineComponent({ pageProps, component, emailNotConfigured, + onInfo, + childInfo, }; }, }); @@ -285,7 +295,7 @@ export default defineComponent({ } > .info { - margin: 0 16px; + margin: 16px 0; } > .accounts { @@ -299,6 +309,16 @@ export default defineComponent({ } } + > .main { + .bkzroven { + > .title { + margin: 4px 0 20px 0; + font-size: 1.5em; + font-weight: bold; + } + } + } + &.wide { display: flex; max-width: 1000px; @@ -321,6 +341,12 @@ export default defineComponent({ flex: 1; min-width: 0; overflow: auto; + + .bkzroven { + > .title { + margin: 6px 0 24px 0; + } + } } } } diff --git a/packages/client/src/pages/settings/menu.vue b/packages/client/src/pages/settings/menu.vue index 47cc4256b0..19d26be89a 100644 --- a/packages/client/src/pages/settings/menu.vue +++ b/packages/client/src/pages/settings/menu.vue @@ -1,28 +1,28 @@ <template> -<FormBase> - <FormTextarea v-model="items" tall manual-save> - <span>{{ $ts.menu }}</span> - <template #desc><button class="_textButton" @click="addItem">{{ $ts.addItem }}</button></template> +<div class="_formRoot"> + <FormTextarea v-model="items" tall manual-save class="_formBlock"> + <template #label>{{ $ts.menu }}</template> + <template #caption><button class="_textButton" @click="addItem">{{ $ts.addItem }}</button></template> </FormTextarea> - <FormRadios v-model="menuDisplay"> - <template #desc>{{ $ts.display }}</template> + <FormRadios v-model="menuDisplay" class="_formBlock"> + <template #label>{{ $ts.display }}</template> <option value="sideFull">{{ $ts._menuDisplay.sideFull }}</option> <option value="sideIcon">{{ $ts._menuDisplay.sideIcon }}</option> <option value="top">{{ $ts._menuDisplay.top }}</option> <!-- <MkRadio v-model="menuDisplay" value="hide" disabled>{{ $ts._menuDisplay.hide }}</MkRadio>--> <!-- TODO: ใตใคใใใผใๅฎๅ
จใซ้ ใใใใใซใใใจใๅฅ้ใใณใใผใฌใผใใฟใณใฎใใใชใใฎใUIใซ่กจ็คบใใๅฟ
่ฆใใใ้ขๅ --> </FormRadios> - <FormButton danger @click="reset()"><i class="fas fa-redo"></i> {{ $ts.default }}</FormButton> -</FormBase> + <FormButton danger class="_formBlock" @click="reset()"><i class="fas fa-redo"></i> {{ $ts.default }}</FormButton> +</div> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import FormTextarea from '@/components/debobigego/textarea.vue'; -import FormRadios from '@/components/debobigego/radios.vue'; +import FormTextarea from '@/components/form/textarea.vue'; +import FormRadios from '@/components/form/radios.vue'; import FormBase from '@/components/debobigego/base.vue'; -import FormButton from '@/components/debobigego/button.vue'; +import FormButton from '@/components/ui/button.vue'; import * as os from '@/os'; import { menuDef } from '@/menu'; import { defaultStore } from '@/store'; diff --git a/packages/client/src/pages/settings/notifications.vue b/packages/client/src/pages/settings/notifications.vue index 7de10a182c..d3ada0d7ef 100644 --- a/packages/client/src/pages/settings/notifications.vue +++ b/packages/client/src/pages/settings/notifications.vue @@ -1,20 +1,20 @@ <template> -<FormBase> - <FormLink @click="configure">{{ $ts.notificationSetting }}</FormLink> - <FormGroup> - <FormButton @click="readAllNotifications">{{ $ts.markAsReadAllNotifications }}</FormButton> - <FormButton @click="readAllUnreadNotes">{{ $ts.markAsReadAllUnreadNotes }}</FormButton> - <FormButton @click="readAllMessagingMessages">{{ $ts.markAsReadAllTalkMessages }}</FormButton> - </FormGroup> -</FormBase> +<div class="_formRoot"> + <FormLink class="_formBlock" @click="configure"><template #icon><i class="fas fa-cog"></i></template>{{ $ts.notificationSetting }}</FormLink> + <FormSection> + <FormLink class="_formBlock" @click="readAllNotifications">{{ $ts.markAsReadAllNotifications }}</FormLink> + <FormLink class="_formBlock" @click="readAllUnreadNotes">{{ $ts.markAsReadAllUnreadNotes }}</FormLink> + <FormLink class="_formBlock" @click="readAllMessagingMessages">{{ $ts.markAsReadAllTalkMessages }}</FormLink> + </FormSection> +</div> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import FormButton from '@/components/debobigego/button.vue'; -import FormLink from '@/components/debobigego/link.vue'; +import FormButton from '@/components/ui/button.vue'; +import FormLink from '@/components/form/link.vue'; import FormBase from '@/components/debobigego/base.vue'; -import FormGroup from '@/components/debobigego/group.vue'; +import FormSection from '@/components/form/section.vue'; import { notificationTypes } from 'misskey-js'; import * as os from '@/os'; import * as symbols from '@/symbols'; @@ -24,7 +24,7 @@ export default defineComponent({ FormBase, FormLink, FormButton, - FormGroup, + FormSection, }, emits: ['info'], diff --git a/packages/client/src/pages/settings/privacy.vue b/packages/client/src/pages/settings/privacy.vue index 94afba9aa4..78a0ea8b8d 100644 --- a/packages/client/src/pages/settings/privacy.vue +++ b/packages/client/src/pages/settings/privacy.vue @@ -1,64 +1,66 @@ <template> -<FormBase> - <FormGroup> - <FormSwitch v-model="isLocked" @update:modelValue="save()">{{ $ts.makeFollowManuallyApprove }}</FormSwitch> - <FormSwitch v-model="autoAcceptFollowed" :disabled="!isLocked" @update:modelValue="save()">{{ $ts.autoAcceptFollowed }}</FormSwitch> - <template #caption>{{ $ts.lockedAccountInfo }}</template> - </FormGroup> - <FormSwitch v-model="publicReactions" @update:modelValue="save()"> +<div class="_formRoot"> + <FormSwitch v-model="isLocked" class="_formBlock" @update:modelValue="save()">{{ $ts.makeFollowManuallyApprove }}<template #caption>{{ $ts.lockedAccountInfo }}</template></FormSwitch> + <FormSwitch v-if="isLocked" v-model="autoAcceptFollowed" class="_formBlock" @update:modelValue="save()">{{ $ts.autoAcceptFollowed }}</FormSwitch> + + <FormSwitch v-model="publicReactions" class="_formBlock" @update:modelValue="save()"> {{ $ts.makeReactionsPublic }} - <template #desc>{{ $ts.makeReactionsPublicDescription }}</template> + <template #caption>{{ $ts.makeReactionsPublicDescription }}</template> </FormSwitch> - <FormGroup> + + <FormSelect v-model="ffVisibility" class="_formBlock"> <template #label>{{ $ts.ffVisibility }}</template> - <FormSelect v-model="ffVisibility"> - <option value="public">{{ $ts._ffVisibility.public }}</option> - <option value="followers">{{ $ts._ffVisibility.followers }}</option> - <option value="private">{{ $ts._ffVisibility.private }}</option> - </FormSelect> + <option value="public">{{ $ts._ffVisibility.public }}</option> + <option value="followers">{{ $ts._ffVisibility.followers }}</option> + <option value="private">{{ $ts._ffVisibility.private }}</option> <template #caption>{{ $ts.ffVisibilityDescription }}</template> - </FormGroup> - <FormSwitch v-model="hideOnlineStatus" @update:modelValue="save()"> + </FormSelect> + + <FormSwitch v-model="hideOnlineStatus" class="_formBlock" @update:modelValue="save()"> {{ $ts.hideOnlineStatus }} - <template #desc>{{ $ts.hideOnlineStatusDescription }}</template> + <template #caption>{{ $ts.hideOnlineStatusDescription }}</template> </FormSwitch> - <FormSwitch v-model="noCrawle" @update:modelValue="save()"> + <FormSwitch v-model="noCrawle" class="_formBlock" @update:modelValue="save()"> {{ $ts.noCrawle }} - <template #desc>{{ $ts.noCrawleDescription }}</template> + <template #caption>{{ $ts.noCrawleDescription }}</template> </FormSwitch> - <FormSwitch v-model="isExplorable" @update:modelValue="save()"> + <FormSwitch v-model="isExplorable" class="_formBlock" @update:modelValue="save()"> {{ $ts.makeExplorable }} - <template #desc>{{ $ts.makeExplorableDescription }}</template> + <template #caption>{{ $ts.makeExplorableDescription }}</template> </FormSwitch> - <FormSwitch v-model="rememberNoteVisibility" @update:modelValue="save()">{{ $ts.rememberNoteVisibility }}</FormSwitch> - <FormGroup v-if="!rememberNoteVisibility"> - <template #label>{{ $ts.defaultNoteVisibility }}</template> - <FormSelect v-model="defaultNoteVisibility"> - <option value="public">{{ $ts._visibility.public }}</option> - <option value="home">{{ $ts._visibility.home }}</option> - <option value="followers">{{ $ts._visibility.followers }}</option> - <option value="specified">{{ $ts._visibility.specified }}</option> - </FormSelect> - <FormSwitch v-model="defaultNoteLocalOnly">{{ $ts._visibility.localOnly }}</FormSwitch> - </FormGroup> - <FormSwitch v-model="keepCw" @update:modelValue="save()">{{ $ts.keepCw }}</FormSwitch> -</FormBase> + + <FormSection> + <FormSwitch v-model="rememberNoteVisibility" class="_formBlock" @update:modelValue="save()">{{ $ts.rememberNoteVisibility }}</FormSwitch> + <FormGroup v-if="!rememberNoteVisibility" class="_formBlock"> + <template #label>{{ $ts.defaultNoteVisibility }}</template> + <FormSelect v-model="defaultNoteVisibility" class="_formBlock"> + <option value="public">{{ $ts._visibility.public }}</option> + <option value="home">{{ $ts._visibility.home }}</option> + <option value="followers">{{ $ts._visibility.followers }}</option> + <option value="specified">{{ $ts._visibility.specified }}</option> + </FormSelect> + <FormSwitch v-model="defaultNoteLocalOnly" class="_formBlock">{{ $ts._visibility.localOnly }}</FormSwitch> + </FormGroup> + </FormSection> + + <FormSwitch v-model="keepCw" class="_formBlock" @update:modelValue="save()">{{ $ts.keepCw }}</FormSwitch> +</div> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import FormSwitch from '@/components/debobigego/switch.vue'; -import FormSelect from '@/components/debobigego/select.vue'; -import FormBase from '@/components/debobigego/base.vue'; -import FormGroup from '@/components/debobigego/group.vue'; +import FormSwitch from '@/components/form/switch.vue'; +import FormSelect from '@/components/form/select.vue'; +import FormSection from '@/components/form/section.vue'; +import FormGroup from '@/components/form/group.vue'; import * as os from '@/os'; import { defaultStore } from '@/store'; import * as symbols from '@/symbols'; export default defineComponent({ components: { - FormBase, FormSelect, + FormSection, FormGroup, FormSwitch, }, diff --git a/packages/client/src/pages/settings/profile.vue b/packages/client/src/pages/settings/profile.vue index ce55c57c09..2eaf9a9f83 100644 --- a/packages/client/src/pages/settings/profile.vue +++ b/packages/client/src/pages/settings/profile.vue @@ -1,59 +1,58 @@ <template> -<FormBase> - <FormGroup> - <div class="_debobigegoItem _debobigegoPanel llvierxe" :style="{ backgroundImage: $i.bannerUrl ? `url(${ $i.bannerUrl })` : null }"> - <MkAvatar class="avatar" :user="$i"/> +<div class="_formRoot"> + <div class="llvierxe" :style="{ backgroundImage: $i.bannerUrl ? `url(${ $i.bannerUrl })` : null }"> + <div class="avatar _acrylic"> + <MkAvatar class="avatar" :user="$i" :disable-link="true" @click="changeAvatar"/> + <MkButton primary class="avatarEdit" @click="changeAvatar">{{ $ts._profile.changeAvatar }}</MkButton> </div> - <FormButton primary @click="changeAvatar">{{ $ts._profile.changeAvatar }}</FormButton> - <FormButton primary @click="changeBanner">{{ $ts._profile.changeBanner }}</FormButton> - </FormGroup> + <MkButton primary class="bannerEdit" @click="changeBanner">{{ $ts._profile.changeBanner }}</MkButton> + </div> - <FormInput v-model="name" :max="30" manual-save> - <span>{{ $ts._profile.name }}</span> + <FormInput v-model="name" :max="30" manual-save class="_formBlock"> + <template #label>{{ $ts._profile.name }}</template> </FormInput> - <FormTextarea v-model="description" :max="500" tall manual-save> - <span>{{ $ts._profile.description }}</span> - <template #desc>{{ $ts._profile.youCanIncludeHashtags }}</template> + <FormTextarea v-model="description" :max="500" tall manual-save class="_formBlock"> + <template #label>{{ $ts._profile.description }}</template> + <template #caption>{{ $ts._profile.youCanIncludeHashtags }}</template> </FormTextarea> - <FormInput v-model="location" manual-save> - <span>{{ $ts.location }}</span> + <FormInput v-model="location" manual-save class="_formBlock"> + <template #label>{{ $ts.location }}</template> <template #prefix><i class="fas fa-map-marker-alt"></i></template> </FormInput> - <FormInput v-model="birthday" type="date" manual-save> - <span>{{ $ts.birthday }}</span> + <FormInput v-model="birthday" type="date" manual-save class="_formBlock"> + <template #label>{{ $ts.birthday }}</template> <template #prefix><i class="fas fa-birthday-cake"></i></template> </FormInput> - <FormSelect v-model="lang"> + <FormSelect v-model="lang" class="_formBlock"> <template #label>{{ $ts.language }}</template> <option v-for="x in langs" :key="x[0]" :value="x[0]">{{ x[1] }}</option> </FormSelect> - <FormGroup> - <FormButton primary @click="editMetadata">{{ $ts._profile.metadataEdit }}</FormButton> + <FormSlot> + <MkButton @click="editMetadata">{{ $ts._profile.metadataEdit }}</MkButton> <template #caption>{{ $ts._profile.metadataDescription }}</template> - </FormGroup> + </FormSlot> - <FormSwitch v-model="isCat">{{ $ts.flagAsCat }}<template #desc>{{ $ts.flagAsCatDescription }}</template></FormSwitch> + <FormSwitch v-model="isCat" class="_formBlock">{{ $ts.flagAsCat }}<template #caption>{{ $ts.flagAsCatDescription }}</template></FormSwitch> - <FormSwitch v-model="isBot">{{ $ts.flagAsBot }}<template #desc>{{ $ts.flagAsBotDescription }}</template></FormSwitch> + <FormSwitch v-model="isBot" class="_formBlock">{{ $ts.flagAsBot }}<template #caption>{{ $ts.flagAsBotDescription }}</template></FormSwitch> - <FormSwitch v-model="alwaysMarkNsfw">{{ $ts.alwaysMarkSensitive }}</FormSwitch> -</FormBase> + <FormSwitch v-model="alwaysMarkNsfw" class="_formBlock">{{ $ts.alwaysMarkSensitive }}</FormSwitch> +</div> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import FormButton from '@/components/debobigego/button.vue'; -import FormInput from '@/components/debobigego/input.vue'; -import FormTextarea from '@/components/debobigego/textarea.vue'; -import FormSwitch from '@/components/debobigego/switch.vue'; -import FormSelect from '@/components/debobigego/select.vue'; -import FormBase from '@/components/debobigego/base.vue'; -import FormGroup from '@/components/debobigego/group.vue'; +import MkButton from '@/components/ui/button.vue'; +import FormInput from '@/components/form/input.vue'; +import FormTextarea from '@/components/form/textarea.vue'; +import FormSwitch from '@/components/form/switch.vue'; +import FormSelect from '@/components/form/select.vue'; +import FormSlot from '@/components/form/slot.vue'; import { host, langs } from '@/config'; import { selectFile } from '@/scripts/select-file'; import * as os from '@/os'; @@ -61,13 +60,12 @@ import * as symbols from '@/symbols'; export default defineComponent({ components: { - FormButton, + MkButton, FormInput, FormTextarea, FormSwitch, FormSelect, - FormBase, - FormGroup, + FormSlot, }, emits: ['info'], @@ -257,25 +255,28 @@ export default defineComponent({ <style lang="scss" scoped> .llvierxe { position: relative; - height: 150px; background-size: cover; background-position: center; + border-radius: 10px; + overflow: clip; - > * { - pointer-events: none; + > .avatar { + display: inline-block; + text-align: center; + padding: 16px; + + > .avatar { + display: inline-block; + width: 72px; + height: 72px; + margin: 0 auto 16px auto; + } } - > .avatar { + > .bannerEdit { position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - display: block; - width: 72px; - height: 72px; - margin: auto; - box-shadow: 0 0 0 6px rgba(0, 0, 0, 0.5); + top: 16px; + right: 16px; } } </style> diff --git a/packages/client/src/pages/settings/reaction.vue b/packages/client/src/pages/settings/reaction.vue index 5864020cb9..4d500f5b47 100644 --- a/packages/client/src/pages/settings/reaction.vue +++ b/packages/client/src/pages/settings/reaction.vue @@ -1,8 +1,8 @@ <template> -<FormBase> - <div class="_debobigegoItem"> - <div class="_debobigegoLabel">{{ $ts.reactionSettingDescription }}</div> - <div class="_debobigegoPanel"> +<div class="_formRoot"> + <FromSlot class="_formBlock"> + <template #label>{{ $ts.reactionSettingDescription }}</template> + <div v-panel style="border-radius: 6px;"> <XDraggable v-model="reactions" class="zoaiodol" :item-key="item => item" animation="150" delay="100" delay-on-touch-only="true"> <template #item="{element}"> <button class="_button item" @click="remove(element, $event)"> @@ -14,33 +14,38 @@ </template> </XDraggable> </div> - <div class="_debobigegoCaption">{{ $ts.reactionSettingDescription2 }} <button class="_textButton" @click="preview">{{ $ts.preview }}</button></div> - </div> + <template #caption>{{ $ts.reactionSettingDescription2 }} <button class="_textButton" @click="preview">{{ $ts.preview }}</button></template> + </FromSlot> - <FormRadios v-model="reactionPickerWidth"> - <template #desc>{{ $ts.width }}</template> + <FormRadios v-model="reactionPickerWidth" class="_formBlock"> + <template #label>{{ $ts.width }}</template> <option :value="1">{{ $ts.small }}</option> <option :value="2">{{ $ts.medium }}</option> <option :value="3">{{ $ts.large }}</option> </FormRadios> - <FormRadios v-model="reactionPickerHeight"> - <template #desc>{{ $ts.height }}</template> + <FormRadios v-model="reactionPickerHeight" class="_formBlock"> + <template #label>{{ $ts.height }}</template> <option :value="1">{{ $ts.small }}</option> <option :value="2">{{ $ts.medium }}</option> <option :value="3">{{ $ts.large }}</option> </FormRadios> - <FormButton @click="preview"><i class="fas fa-eye"></i> {{ $ts.preview }}</FormButton> - <FormButton danger @click="setDefault"><i class="fas fa-undo"></i> {{ $ts.default }}</FormButton> -</FormBase> + <FormSection> + <FormButton @click="preview"><i class="fas fa-eye"></i> {{ $ts.preview }}</FormButton> + </FormSection> + <FormSection> + <FormButton danger @click="setDefault"><i class="fas fa-undo"></i> {{ $ts.default }}</FormButton> + </FormSection> +</div> </template> <script lang="ts"> import { defineComponent } from 'vue'; import XDraggable from 'vuedraggable'; -import FormInput from '@/components/debobigego/input.vue'; -import FormRadios from '@/components/debobigego/radios.vue'; -import FormBase from '@/components/debobigego/base.vue'; -import FormButton from '@/components/debobigego/button.vue'; +import FormInput from '@/components/form/input.vue'; +import FormRadios from '@/components/form/radios.vue'; +import FromSlot from '@/components/form/slot.vue'; +import FormButton from '@/components/ui/button.vue'; +import FormSection from '@/components/form/section.vue'; import * as os from '@/os'; import { defaultStore } from '@/store'; import * as symbols from '@/symbols'; @@ -49,8 +54,9 @@ export default defineComponent({ components: { FormInput, FormButton, - FormBase, + FromSlot, FormRadios, + FormSection, XDraggable, }, @@ -135,7 +141,8 @@ export default defineComponent({ <style lang="scss" scoped> .zoaiodol { - padding: 16px; + padding: 12px; + font-size: 1.1em; > .item { display: inline-block; diff --git a/packages/client/src/pages/settings/security.vue b/packages/client/src/pages/settings/security.vue index c18edd80b0..33dc299f5d 100644 --- a/packages/client/src/pages/settings/security.vue +++ b/packages/client/src/pages/settings/security.vue @@ -1,45 +1,61 @@ <template> -<FormBase> - <X2fa/> - <FormLink to="/settings/2fa"><template #icon><i class="fas fa-mobile-alt"></i></template>{{ $ts.twoStepAuthentication }}</FormLink> - <FormButton primary @click="change()">{{ $ts.changePassword }}</FormButton> - <FormPagination :pagination="pagination"> +<div class="_formRoot"> + <FormSection> + <template #label>{{ $ts.password }}</template> + <FormButton primary @click="change()">{{ $ts.changePassword }}</FormButton> + </FormSection> + + <FormSection> + <template #label>{{ $ts.twoStepAuthentication }}</template> + <X2fa/> + </FormSection> + + <FormSection> <template #label>{{ $ts.signinHistory }}</template> - <template #default="{items}"> - <div v-for="item in items" :key="item.id" class="_debobigegoPanel timnmucd"> - <header> - <i v-if="item.success" class="fas fa-check icon succ"></i> - <i v-else class="fas fa-times-circle icon fail"></i> - <code class="ip _monospace">{{ item.ip }}</code> - <MkTime :time="item.createdAt" class="time"/> - </header> - </div> - </template> - </FormPagination> - <FormGroup> - <FormButton danger @click="regenerateToken"><i class="fas fa-sync-alt"></i> {{ $ts.regenerateLoginToken }}</FormButton> - <template #caption>{{ $ts.regenerateLoginTokenDescription }}</template> - </FormGroup> -</FormBase> + <FormPagination :pagination="pagination"> + <template #default="{items}"> + <div> + <div v-for="item in items" :key="item.id" v-panel class="timnmucd"> + <header> + <i v-if="item.success" class="fas fa-check icon succ"></i> + <i v-else class="fas fa-times-circle icon fail"></i> + <code class="ip _monospace">{{ item.ip }}</code> + <MkTime :time="item.createdAt" class="time"/> + </header> + </div> + </div> + </template> + </FormPagination> + </FormSection> + + <FormSection> + <FormSlot> + <FormButton danger @click="regenerateToken"><i class="fas fa-sync-alt"></i> {{ $ts.regenerateLoginToken }}</FormButton> + <template #caption>{{ $ts.regenerateLoginTokenDescription }}</template> + </FormSlot> + </FormSection> +</div> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import FormBase from '@/components/debobigego/base.vue'; +import FormSection from '@/components/form/section.vue'; import FormLink from '@/components/debobigego/link.vue'; -import FormGroup from '@/components/debobigego/group.vue'; -import FormButton from '@/components/debobigego/button.vue'; -import FormPagination from '@/components/debobigego/pagination.vue'; +import FormSlot from '@/components/form/slot.vue'; +import FormButton from '@/components/ui/button.vue'; +import FormPagination from '@/components/form/pagination.vue'; +import X2fa from './2fa.vue'; import * as os from '@/os'; import * as symbols from '@/symbols'; export default defineComponent({ components: { - FormBase, + FormSection, FormLink, FormButton, FormPagination, - FormGroup, + FormSlot, + X2fa, }, emits: ['info'], @@ -115,6 +131,20 @@ export default defineComponent({ .timnmucd { padding: 16px; + &:first-child { + border-top-left-radius: 6px; + border-top-right-radius: 6px; + } + + &:last-child { + border-bottom-left-radius: 6px; + border-bottom-right-radius: 6px; + } + + &:not(:last-child) { + border-bottom: solid 0.5px var(--divider); + } + > header { display: flex; align-items: center; diff --git a/packages/client/src/pages/settings/sounds.vue b/packages/client/src/pages/settings/sounds.vue index 7bea50976e..1492a989a2 100644 --- a/packages/client/src/pages/settings/sounds.vue +++ b/packages/client/src/pages/settings/sounds.vue @@ -1,29 +1,28 @@ <template> -<FormBase> - <FormRange v-model="masterVolume" :min="0" :max="1" :step="0.05"> - <template #label><i class="fas fa-volume-icon"></i> {{ $ts.masterVolume }}</template> +<div class="_formRoot"> + <FormRange v-model="masterVolume" :min="0" :max="1" :step="0.05" :text-converter="(v) => `${Math.floor(v * 100)}%`" class="_formBlock"> + <template #label>{{ $ts.masterVolume }}</template> </FormRange> - <FormGroup> + <FormSection> <template #label>{{ $ts.sounds }}</template> - <FormButton v-for="type in Object.keys(sounds)" :key="type" :center="false" @click="edit(type)"> + <FormLink v-for="type in Object.keys(sounds)" :key="type" style="margin-bottom: 8px;" @click="edit(type)"> {{ $t('_sfx.' + type) }} <template #suffix>{{ sounds[type].type || $ts.none }}</template> <template #suffixIcon><i class="fas fa-chevron-down"></i></template> - </FormButton> - </FormGroup> + </FormLink> + </FormSection> - <FormButton danger @click="reset()"><i class="fas fa-redo"></i> {{ $ts.default }}</FormButton> -</FormBase> + <FormButton danger class="_formBlock" @click="reset()"><i class="fas fa-redo"></i> {{ $ts.default }}</FormButton> +</div> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import FormRange from '@/components/debobigego/range.vue'; -import FormSelect from '@/components/debobigego/select.vue'; -import FormBase from '@/components/debobigego/base.vue'; -import FormButton from '@/components/debobigego/button.vue'; -import FormGroup from '@/components/debobigego/group.vue'; +import FormRange from '@/components/form/range.vue'; +import FormButton from '@/components/ui/button.vue'; +import FormLink from '@/components/form/link.vue'; +import FormSection from '@/components/form/section.vue'; import * as os from '@/os'; import { ColdDeviceStorage } from '@/store'; import { playFile } from '@/scripts/sound'; @@ -58,11 +57,10 @@ const soundsTypes = [ export default defineComponent({ components: { - FormSelect, + FormLink, FormButton, - FormBase, FormRange, - FormGroup, + FormSection, }, emits: ['info'], diff --git a/packages/client/src/pages/settings/theme.vue b/packages/client/src/pages/settings/theme.vue index 2420966c51..2f4daa26c0 100644 --- a/packages/client/src/pages/settings/theme.vue +++ b/packages/client/src/pages/settings/theme.vue @@ -1,34 +1,35 @@ <template> -<FormBase> - <FormGroup> - <div class="rfqxtzch _debobigegoItem _debobigegoPanel"> - <div class="darkMode"> - <div class="toggleWrapper"> - <input id="dn" v-model="darkMode" type="checkbox" class="dn"/> - <label for="dn" class="toggle"> - <span class="before">{{ $ts.light }}</span> - <span class="after">{{ $ts.dark }}</span> - <span class="toggle__handler"> - <span class="crater crater--1"></span> - <span class="crater crater--2"></span> - <span class="crater crater--3"></span> - </span> - <span class="star star--1"></span> - <span class="star star--2"></span> - <span class="star star--3"></span> - <span class="star star--4"></span> - <span class="star star--5"></span> - <span class="star star--6"></span> - </label> - </div> +<div class="_formRoot"> + <div v-panel class="rfqxtzch _formBlock"> + <div class="toggle"> + <div class="toggleWrapper"> + <input id="dn" v-model="darkMode" type="checkbox" class="dn"/> + <label for="dn" class="toggle"> + <span class="before">{{ $ts.light }}</span> + <span class="after">{{ $ts.dark }}</span> + <span class="toggle__handler"> + <span class="crater crater--1"></span> + <span class="crater crater--2"></span> + <span class="crater crater--3"></span> + </span> + <span class="star star--1"></span> + <span class="star star--2"></span> + <span class="star star--3"></span> + <span class="star star--4"></span> + <span class="star star--5"></span> + <span class="star star--6"></span> + </label> </div> </div> - <FormSwitch v-model="syncDeviceDarkMode">{{ $ts.syncDeviceDarkMode }}</FormSwitch> - </FormGroup> + <div class="sync"> + <FormSwitch v-model="syncDeviceDarkMode">{{ $ts.syncDeviceDarkMode }}</FormSwitch> + </div> + </div> <template v-if="darkMode"> - <FormSelect v-model="darkThemeId"> + <FormSelect v-model="darkThemeId" class="_formBlock"> <template #label>{{ $ts.themeForDarkMode }}</template> + <template #prefix><i class="fas fa-moon"></i></template> <optgroup :label="$ts.darkThemes"> <option v-for="x in darkThemes" :key="x.id" :value="x.id">{{ x.name }}</option> </optgroup> @@ -36,8 +37,9 @@ <option v-for="x in lightThemes" :key="x.id" :value="x.id">{{ x.name }}</option> </optgroup> </FormSelect> - <FormSelect v-model="lightThemeId"> + <FormSelect v-model="lightThemeId" class="_formBlock"> <template #label>{{ $ts.themeForLightMode }}</template> + <template #prefix><i class="fas fa-sun"></i></template> <optgroup :label="$ts.lightThemes"> <option v-for="x in lightThemes" :key="x.id" :value="x.id">{{ x.name }}</option> </optgroup> @@ -47,8 +49,9 @@ </FormSelect> </template> <template v-else> - <FormSelect v-model="lightThemeId"> + <FormSelect v-model="lightThemeId" class="_formBlock"> <template #label>{{ $ts.themeForLightMode }}</template> + <template #prefix><i class="fas fa-sun"></i></template> <optgroup :label="$ts.lightThemes"> <option v-for="x in lightThemes" :key="x.id" :value="x.id">{{ x.name }}</option> </optgroup> @@ -56,8 +59,9 @@ <option v-for="x in darkThemes" :key="x.id" :value="x.id">{{ x.name }}</option> </optgroup> </FormSelect> - <FormSelect v-model="darkThemeId"> + <FormSelect v-model="darkThemeId" class="_formBlock"> <template #label>{{ $ts.themeForDarkMode }}</template> + <template #prefix><i class="fas fa-moon"></i></template> <optgroup :label="$ts.darkThemes"> <option v-for="x in darkThemes" :key="x.id" :value="x.id">{{ x.name }}</option> </optgroup> @@ -67,31 +71,28 @@ </FormSelect> </template> - <FormButton v-if="wallpaper == null" primary @click="setWallpaper">{{ $ts.setWallpaper }}</FormButton> - <FormButton v-else primary @click="wallpaper = null">{{ $ts.removeWallpaper }}</FormButton> - - <FormGroup> - <FormLink to="https://assets.misskey.io/theme/list" external><template #icon><i class="fas fa-globe"></i></template>{{ $ts._theme.explore }}</FormLink> - <FormLink to="/settings/theme/install"><template #icon><i class="fas fa-download"></i></template>{{ $ts._theme.install }}</FormLink> - </FormGroup> - - <FormGroup> - <FormLink to="/theme-editor"><template #icon><i class="fas fa-paint-roller"></i></template>{{ $ts._theme.make }}</FormLink> - <!--<FormLink to="/advanced-theme-editor"><template #icon><i class="fas fa-paint-roller"></i></template>{{ $ts._theme.make }} ({{ $ts.advanced }})</FormLink>--> - </FormGroup> + <FormSection> + <div class="_formLinksGrid"> + <FormLink to="/settings/theme/manage"><template #icon><i class="fas fa-folder-open"></i></template>{{ $ts._theme.manage }}<template #suffix>{{ themesCount }}</template></FormLink> + <FormLink to="https://assets.misskey.io/theme/list" external><template #icon><i class="fas fa-globe"></i></template>{{ $ts._theme.explore }}</FormLink> + <FormLink to="/settings/theme/install"><template #icon><i class="fas fa-download"></i></template>{{ $ts._theme.install }}</FormLink> + <FormLink to="/theme-editor"><template #icon><i class="fas fa-paint-roller"></i></template>{{ $ts._theme.make }}</FormLink> + </div> + </FormSection> - <FormLink to="/settings/theme/manage"><template #icon><i class="fas fa-folder-open"></i></template>{{ $ts._theme.manage }}<template #suffix>{{ themesCount }}</template></FormLink> -</FormBase> + <FormButton v-if="wallpaper == null" class="_formBlock" @click="setWallpaper">{{ $ts.setWallpaper }}</FormButton> + <FormButton v-else class="_formBlock" @click="wallpaper = null">{{ $ts.removeWallpaper }}</FormButton> +</div> </template> <script lang="ts"> import { computed, defineComponent, onActivated, onMounted, ref, watch } from 'vue'; -import FormSwitch from '@/components/debobigego/switch.vue'; -import FormSelect from '@/components/debobigego/select.vue'; -import FormBase from '@/components/debobigego/base.vue'; -import FormGroup from '@/components/debobigego/group.vue'; -import FormLink from '@/components/debobigego/link.vue'; -import FormButton from '@/components/debobigego/button.vue'; +import FormSwitch from '@/components/form/switch.vue'; +import FormSelect from '@/components/form/select.vue'; +import FormGroup from '@/components/form/group.vue'; +import FormSection from '@/components/form/section.vue'; +import FormLink from '@/components/form/link.vue'; +import FormButton from '@/components/ui/button.vue'; import { builtinThemes } from '@/scripts/theme'; import { selectFile } from '@/scripts/select-file'; import { isDeviceDarkmode } from '@/scripts/is-device-darkmode'; @@ -105,8 +106,8 @@ export default defineComponent({ components: { FormSwitch, FormSelect, - FormBase, FormGroup, + FormSection, FormLink, FormButton, }, @@ -198,11 +199,12 @@ export default defineComponent({ <style lang="scss" scoped> .rfqxtzch { - padding: 16px; + border-radius: 6px; - > .darkMode { + > .toggle { position: relative; - padding: 32px 0; + padding: 26px 0; + text-align: center; &.disabled { opacity: 0.7; @@ -212,13 +214,11 @@ export default defineComponent({ } } - .toggleWrapper { - position: absolute; - top: 50%; - left: 50%; - overflow: hidden; + > .toggleWrapper { + display: inline-block; + text-align: left; + overflow: clip; padding: 0 100px; - transform: translate3d(-50%, -50%, 0); input { position: absolute; @@ -239,7 +239,6 @@ export default defineComponent({ > .before, > .after { position: absolute; top: 15px; - font-size: 18px; transition: color 1s ease; } @@ -420,5 +419,10 @@ export default defineComponent({ } } } + + > .sync { + padding: 14px 16px; + border-top: solid 0.5px var(--divider); + } } </style> diff --git a/packages/client/src/pages/settings/word-mute.vue b/packages/client/src/pages/settings/word-mute.vue index f97557ece3..068f88740a 100644 --- a/packages/client/src/pages/settings/word-mute.vue +++ b/packages/client/src/pages/settings/word-mute.vue @@ -1,32 +1,30 @@ <template> -<div> - <MkTab v-model="tab"> +<div class="_formRoot"> + <MkTab v-model="tab" class="_formBlock"> <option value="soft">{{ $ts._wordMute.soft }}</option> <option value="hard">{{ $ts._wordMute.hard }}</option> </MkTab> - <FormBase> - <div class="_debobigegoItem"> - <div v-show="tab === 'soft'"> - <FormInfo>{{ $ts._wordMute.softDescription }}</FormInfo> - <FormTextarea v-model="softMutedWords"> - <span>{{ $ts._wordMute.muteWords }}</span> - <template #desc>{{ $ts._wordMute.muteWordsDescription }}<br>{{ $ts._wordMute.muteWordsDescription2 }}</template> - </FormTextarea> - </div> - <div v-show="tab === 'hard'"> - <FormInfo>{{ $ts._wordMute.hardDescription }}</FormInfo> - <FormTextarea v-model="hardMutedWords"> - <span>{{ $ts._wordMute.muteWords }}</span> - <template #desc>{{ $ts._wordMute.muteWordsDescription }}<br>{{ $ts._wordMute.muteWordsDescription2 }}</template> - </FormTextarea> - <FormKeyValueView v-if="hardWordMutedNotesCount != null"> - <template #key>{{ $ts._wordMute.mutedNotes }}</template> - <template #value>{{ number(hardWordMutedNotesCount) }}</template> - </FormKeyValueView> - </div> + <div class="_formBlock"> + <div v-show="tab === 'soft'"> + <MkInfo class="_formBlock">{{ $ts._wordMute.softDescription }}</MkInfo> + <FormTextarea v-model="softMutedWords" class="_formBlock"> + <span>{{ $ts._wordMute.muteWords }}</span> + <template #caption>{{ $ts._wordMute.muteWordsDescription }}<br>{{ $ts._wordMute.muteWordsDescription2 }}</template> + </FormTextarea> </div> - <FormButton primary inline :disabled="!changed" @click="save()"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton> - </FormBase> + <div v-show="tab === 'hard'"> + <MkInfo class="_formBlock">{{ $ts._wordMute.hardDescription }}</MkInfo> + <FormTextarea v-model="hardMutedWords" class="_formBlock"> + <span>{{ $ts._wordMute.muteWords }}</span> + <template #caption>{{ $ts._wordMute.muteWordsDescription }}<br>{{ $ts._wordMute.muteWordsDescription2 }}</template> + </FormTextarea> + <MkKeyValue v-if="hardWordMutedNotesCount != null" class="_formBlock"> + <template #key>{{ $ts._wordMute.mutedNotes }}</template> + <template #value>{{ number(hardWordMutedNotesCount) }}</template> + </MkKeyValue> + </div> + </div> + <MkButton primary inline :disabled="!changed" @click="save()"><i class="fas fa-save"></i> {{ $ts.save }}</MkButton> </div> </template> @@ -34,9 +32,9 @@ import { defineComponent } from 'vue'; import FormTextarea from '@/components/form/textarea.vue'; import FormBase from '@/components/debobigego/base.vue'; -import FormKeyValueView from '@/components/debobigego/key-value-view.vue'; -import FormButton from '@/components/debobigego/button.vue'; -import FormInfo from '@/components/debobigego/info.vue'; +import MkKeyValue from '@/components/key-value.vue'; +import MkButton from '@/components/ui/button.vue'; +import MkInfo from '@/components/ui/info.vue'; import MkTab from '@/components/tab.vue'; import * as os from '@/os'; import number from '@/filters/number'; @@ -45,11 +43,11 @@ import * as symbols from '@/symbols'; export default defineComponent({ components: { FormBase, - FormButton, + MkButton, FormTextarea, - FormKeyValueView, + MkKeyValue, MkTab, - FormInfo, + MkInfo, }, emits: ['info'], |