1
0
mirror of https://github.com/MisskeyIO/misskey synced 2024-11-27 06:18:40 +09:00

feat(client): improve toast component and show welcome message

This commit is contained in:
syuilo 2021-12-18 14:55:53 +09:00
parent f9e3fd7001
commit d6e85ffb59
6 changed files with 126 additions and 40 deletions

View File

@ -816,6 +816,7 @@ hide: "隠す"
leaveGroup: "グループから抜ける"
leaveGroupConfirm: "「{name}」から抜けますか?"
useDrawerReactionPickerForMobile: "モバイルデバイスのときドロワーで表示"
welcomeBackWithName: "おかえりなさい、{name}さん"
_emailUnavailable:
used: "既に使用されています"

View File

@ -0,0 +1,74 @@
<template>
<div class="mk-notification-toast" :style="{ zIndex }">
<transition name="notification-toast" appear @after-leave="$emit('closed')">
<XNotification v-if="showing" :notification="notification" class="notification _acrylic"/>
</transition>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import XNotification from './notification.vue';
import * as os from '@/os';
export default defineComponent({
components: {
XNotification
},
props: {
notification: {
type: Object,
required: true
}
},
emits: ['closed'],
data() {
return {
showing: true,
zIndex: os.claimZIndex('high'),
};
},
mounted() {
setTimeout(() => {
this.showing = false;
}, 6000);
}
});
</script>
<style lang="scss" scoped>
.notification-toast-enter-active, .notification-toast-leave-active {
transition: opacity 0.3s, transform 0.3s !important;
}
.notification-toast-enter-from, .notification-toast-leave-to {
opacity: 0;
transform: translateX(-250px);
}
.mk-notification-toast {
position: fixed;
left: 0;
width: 250px;
top: 32px;
padding: 0 32px;
pointer-events: none;
@media (max-width: 700px) {
top: initial;
bottom: 112px;
padding: 0 16px;
}
@media (max-width: 500px) {
bottom: 92px;
padding: 0 8px;
}
> .notification {
height: 100%;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
border-radius: 8px;
overflow: hidden;
}
}
</style>

View File

@ -1,25 +1,25 @@
<template>
<div class="mk-toast" :style="{ zIndex }">
<transition name="notification-slide" appear @after-leave="$emit('closed')">
<XNotification v-if="showing" :notification="notification" class="notification _acrylic"/>
<div class="mk-toast">
<transition name="toast" appear @after-leave="$emit('closed')">
<div v-if="showing" class="body _acrylic" :style="{ zIndex }">
<div class="message">
{{ message }}
</div>
</div>
</transition>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import XNotification from './notification.vue';
import * as os from '@/os';
export default defineComponent({
components: {
XNotification
},
props: {
notification: {
type: Object,
required: true
}
message: {
type: String,
required: true,
},
},
emits: ['closed'],
data() {
@ -31,44 +31,41 @@ export default defineComponent({
mounted() {
setTimeout(() => {
this.showing = false;
}, 6000);
}, 4000);
}
});
</script>
<style lang="scss" scoped>
.notification-slide-enter-active, .notification-slide-leave-active {
.toast-enter-active, .toast-leave-active {
transition: opacity 0.3s, transform 0.3s !important;
}
.notification-slide-enter-from, .notification-slide-leave-to {
.toast-enter-from, .toast-leave-to {
opacity: 0;
transform: translateX(-250px);
transform: translateY(calc(0px - (100% - 32px)));
}
.mk-toast {
position: fixed;
left: 0;
width: 250px;
top: 32px;
padding: 0 32px;
pointer-events: none;
@media (max-width: 700px) {
top: initial;
bottom: 112px;
padding: 0 16px;
}
@media (max-width: 500px) {
bottom: 92px;
padding: 0 8px;
}
> .notification {
height: 100%;
> .body {
position: fixed;
left: 0;
right: 0;
top: 0;
margin: 0 auto;
padding-top: 32px;
margin-top: -32px;
min-width: 300px;
max-width: calc(100% - 32px);
width: min-content;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.3);
border-radius: 8px;
overflow: hidden;
border-radius: 0 0 8px 8px;
overflow: clip;
text-align: center;
pointer-events: none;
> .message {
padding: 16px 24px;
}
}
}
</style>

View File

@ -26,7 +26,7 @@ import { router } from '@/router';
import { applyTheme } from '@/scripts/theme';
import { isDeviceDarkmode } from '@/scripts/is-device-darkmode';
import { i18n } from '@/i18n';
import { stream, confirm, alert, post, popup } from '@/os';
import { stream, confirm, alert, post, popup, toast } from '@/os';
import * as sound from '@/scripts/sound';
import { $i, refreshAccount, login, updateAccount, signout } from '@/account';
import { defaultStore, ColdDeviceStorage } from '@/store';
@ -342,6 +342,18 @@ if ($i) {
});
}
const lastUsed = localStorage.getItem('lastUsed');
if (lastUsed) {
const lastUsedDate = parseInt(lastUsed, 10);
// 二時間以上前なら
if (Date.now() - lastUsedDate > 1000 * 60 * 60 * 2) {
toast(i18n.t('welcomeBackWithName', {
name: $i.name || $i.username,
}));
}
}
localStorage.setItem('lastUsed', Date.now().toString());
if ('Notification' in window) {
// 許可を得ていなかったらリクエスト
if (Notification.permission === 'default') {

View File

@ -221,7 +221,9 @@ export function modalPageWindow(path: string) {
}
export function toast(message: string) {
// TODO
popup(import('@/components/toast.vue'), {
message
}, {}, 'closed');
}
export function alert(props: {

View File

@ -34,7 +34,7 @@ export default defineComponent({
id: notification.id
});
popup(import('@/components/toast.vue'), {
popup(import('@/components/notification-toast.vue'), {
notification
}, {}, 'closed');
}