diff options
Diffstat (limited to 'packages/frontend/src')
| -rw-r--r-- | packages/frontend/src/pages/settings/general.vue | 22 | ||||
| -rw-r--r-- | packages/frontend/src/store.ts | 8 | ||||
| -rw-r--r-- | packages/frontend/src/ui/_common_/common.vue | 108 |
3 files changed, 114 insertions, 24 deletions
diff --git a/packages/frontend/src/pages/settings/general.vue b/packages/frontend/src/pages/settings/general.vue index a487a4622a..0a53ed2c8d 100644 --- a/packages/frontend/src/pages/settings/general.vue +++ b/packages/frontend/src/pages/settings/general.vue @@ -93,6 +93,26 @@ </FormSection> <FormSection> + <template #label>{{ i18n.ts.notificationDisplay }}</template> + + <div class="_gaps_m"> + <MkRadios v-model="notificationPosition"> + <template #label>{{ i18n.ts.position }}</template> + <option value="leftTop"><i class="ti ti-align-box-left-top"></i> {{ i18n.ts.leftTop }}</option> + <option value="rightTop"><i class="ti ti-align-box-right-top"></i> {{ i18n.ts.rightTop }}</option> + <option value="leftBottom"><i class="ti ti-align-box-left-bottom"></i> {{ i18n.ts.leftBottom }}</option> + <option value="rightBottom"><i class="ti ti-align-box-right-bottom"></i> {{ i18n.ts.rightBottom }}</option> + </MkRadios> + + <MkRadios v-model="notificationStackAxis"> + <template #label>{{ i18n.ts.stackAxis }}</template> + <option value="vertical"><i class="ti ti-carousel-vertical"></i> {{ i18n.ts.vertical }}</option> + <option value="horizontal"><i class="ti ti-carousel-horizontal"></i> {{ i18n.ts.horizontal }}</option> + </MkRadios> + </div> + </FormSection> + + <FormSection> <MkSwitch v-model="aiChanMode">{{ i18n.ts.aiChanMode }}</MkSwitch> </FormSection> @@ -181,6 +201,8 @@ const useReactionPickerForContextMenu = computed(defaultStore.makeGetterSetter(' const squareAvatars = computed(defaultStore.makeGetterSetter('squareAvatars')); const aiChanMode = computed(defaultStore.makeGetterSetter('aiChanMode')); const mediaListWithOneImageAppearance = computed(defaultStore.makeGetterSetter('mediaListWithOneImageAppearance')); +const notificationPosition = computed(defaultStore.makeGetterSetter('notificationPosition')); +const notificationStackAxis = computed(defaultStore.makeGetterSetter('notificationStackAxis')); watch(lang, () => { miLocalStorage.setItem('lang', lang.value as string); diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts index a4f0f65e14..710b08d9e0 100644 --- a/packages/frontend/src/store.ts +++ b/packages/frontend/src/store.ts @@ -314,6 +314,14 @@ export const defaultStore = markRaw(new Storage('base', { where: 'device', default: 'expand' as 'expand' | '16_9' | '1_1' | '2_3', }, + notificationPosition: { + where: 'device', + default: 'rightBottom' as 'leftTop' | 'leftBottom' | 'rightTop' | 'rightBottom', + }, + notificationStackAxis: { + where: 'device', + default: 'horizontal' as 'vertical' | 'horizontal', + }, })); // TODO: 他のタブと永続化されたstateを同期 diff --git a/packages/frontend/src/ui/_common_/common.vue b/packages/frontend/src/ui/_common_/common.vue index 5a32c076a4..71a4285e9d 100644 --- a/packages/frontend/src/ui/_common_/common.vue +++ b/packages/frontend/src/ui/_common_/common.vue @@ -10,14 +10,16 @@ <XUpload v-if="uploads.length > 0"/> <TransitionGroup - tag="div" :class="$style.notifications" + tag="div" :class="[$style.notifications, $style[`notificationsPosition-${defaultStore.state.notificationPosition}`], $style[`notificationsStackAxis-${defaultStore.state.notificationStackAxis}`]]" :move-class="defaultStore.state.animation ? $style.transition_notification_move : ''" :enter-active-class="defaultStore.state.animation ? $style.transition_notification_enterActive : ''" :leave-active-class="defaultStore.state.animation ? $style.transition_notification_leaveActive : ''" :enter-from-class="defaultStore.state.animation ? $style.transition_notification_enterFrom : ''" :leave-to-class="defaultStore.state.animation ? $style.transition_notification_leaveTo : ''" > - <XNotification v-for="notification in notifications" :key="notification.id" :notification="notification" :class="$style.notification"/> + <div v-for="notification in notifications" :key="notification.id" :class="$style.notification"> + <XNotification :notification="notification"/> + </div> </TransitionGroup> <XStreamIndicator/> @@ -30,7 +32,7 @@ </template> <script lang="ts" setup> -import { defineAsyncComponent } from 'vue'; +import { defineAsyncComponent, ref } from 'vue'; import * as misskey from 'misskey-js'; import { swInject } from './sw-inject'; import XNotification from './notification.vue'; @@ -85,7 +87,10 @@ if ($i) { .transition_notification_leaveActive { transition: opacity 0.3s, transform 0.3s !important; } -.transition_notification_enterFrom, +.transition_notification_enterFrom { + opacity: 0; + transform: translateX(250px); +} .transition_notification_leaveTo { opacity: 0; transform: translateX(-250px); @@ -94,35 +99,90 @@ if ($i) { .notifications { position: fixed; z-index: 3900000; - left: 0; - width: 250px; - top: 32px; - padding: 0 32px; + padding: 0 var(--margin); pointer-events: none; - container-type: inline-size; -} + display: flex; -.notification { - & + .notification { - margin-top: 8px; + &.notificationsPosition-leftTop { + top: var(--margin); + left: 0; + } + + &.notificationsPosition-rightTop { + top: var(--margin); + right: 0; + } + + &.notificationsPosition-leftBottom { + bottom: calc(var(--minBottomSpacing) + var(--margin)); + left: 0; } -} -@media (max-width: 500px) { - .notifications { - top: initial; + &.notificationsPosition-rightBottom { bottom: calc(var(--minBottomSpacing) + var(--margin)); - padding: 0 var(--margin); - display: flex; - flex-direction: column-reverse; + right: 0; } - .notification { - & + .notification { - margin-top: 0; - margin-bottom: 8px; + &.notificationsStackAxis-vertical { + width: 250px; + + &.notificationsPosition-leftTop, + &.notificationsPosition-rightTop { + flex-direction: column; + + .notification { + & + .notification { + margin-top: 8px; + } + } + } + + &.notificationsPosition-leftBottom, + &.notificationsPosition-rightBottom { + flex-direction: column-reverse; + + .notification { + & + .notification { + margin-bottom: 8px; + } + } } } + + &.notificationsStackAxis-horizontal { + width: 100%; + + &.notificationsPosition-leftTop, + &.notificationsPosition-leftBottom { + flex-direction: row; + + .notification { + & + .notification { + margin-left: 8px; + } + } + } + + &.notificationsPosition-rightTop, + &.notificationsPosition-rightBottom { + flex-direction: row-reverse; + + .notification { + & + .notification { + margin-right: 8px; + } + } + } + + .notification { + width: 250px; + flex-shrink: 0; + } + } +} + +.notification { + container-type: inline-size; } </style> |