This commit is contained in:
syuilo 2020-02-19 06:16:49 +09:00
parent 98a87ee75f
commit d1e9e74cb8
7 changed files with 114 additions and 52 deletions

View file

@ -423,6 +423,7 @@ serverLogs: "サーバーログ"
deleteAll: "全て削除" deleteAll: "全て削除"
showFixedPostForm: "タイムライン上部に投稿フォームを表示する" showFixedPostForm: "タイムライン上部に投稿フォームを表示する"
newNoteRecived: "新しいノートがあります" newNoteRecived: "新しいノートがあります"
useNotificationsPopup: "通知一覧をポップアップで表示"
_ago: _ago:
unknown: "謎" unknown: "謎"

View file

@ -50,21 +50,27 @@
<router-link class="item index" active-class="active" to="/" exact v-else> <router-link class="item index" active-class="active" to="/" exact v-else>
<fa :icon="faHome" fixed-width/><span class="text">{{ $store.getters.isSignedIn ? $t('timeline') : $t('home') }}</span> <fa :icon="faHome" fixed-width/><span class="text">{{ $store.getters.isSignedIn ? $t('timeline') : $t('home') }}</span>
</router-link> </router-link>
<button class="item _button notifications" @click="notificationsOpen = !notificationsOpen" ref="notificationButton" v-if="$store.getters.isSignedIn"> <template v-if="$store.getters.isSignedIn">
<fa :icon="faBell" fixed-width/><span class="text">{{ $t('notifications') }}</span> <button class="item _button notifications" @click="notificationsOpen = !notificationsOpen" ref="notificationButton" v-if="$store.state.device.useNotificationsPopup">
<i v-if="$store.state.i.hasUnreadNotification"><fa :icon="faCircle"/></i> <fa :icon="faBell" fixed-width/><span class="text">{{ $t('notifications') }}</span>
</button> <i v-if="$store.state.i.hasUnreadNotification"><fa :icon="faCircle"/></i>
<router-link class="item" active-class="active" to="/my/messaging" v-if="$store.getters.isSignedIn"> </button>
<fa :icon="faComments" fixed-width/><span class="text">{{ $t('messaging') }}</span> <router-link class="item notifications" active-class="active" to="/my/notifications" ref="notificationButton" v-else>
<i v-if="$store.state.i.hasUnreadMessagingMessage"><fa :icon="faCircle"/></i> <fa :icon="faBell" fixed-width/><span class="text">{{ $t('notifications') }}</span>
</router-link> <i v-if="$store.state.i.hasUnreadNotification"><fa :icon="faCircle"/></i>
<router-link class="item" active-class="active" to="/my/drive" v-if="$store.getters.isSignedIn"> </router-link>
<fa :icon="faCloud" fixed-width/><span class="text">{{ $t('drive') }}</span> <router-link class="item" active-class="active" to="/my/messaging">
</router-link> <fa :icon="faComments" fixed-width/><span class="text">{{ $t('messaging') }}</span>
<router-link class="item" active-class="active" to="/my/follow-requests" v-if="$store.getters.isSignedIn && $store.state.i.isLocked"> <i v-if="$store.state.i.hasUnreadMessagingMessage"><fa :icon="faCircle"/></i>
<fa :icon="faUserClock" fixed-width/><span class="text">{{ $t('followRequests') }}</span> </router-link>
<i v-if="$store.state.i.hasPendingReceivedFollowRequest"><fa :icon="faCircle"/></i> <router-link class="item" active-class="active" to="/my/drive">
</router-link> <fa :icon="faCloud" fixed-width/><span class="text">{{ $t('drive') }}</span>
</router-link>
<router-link class="item" active-class="active" to="/my/follow-requests" v-if="$store.state.i.isLocked">
<fa :icon="faUserClock" fixed-width/><span class="text">{{ $t('followRequests') }}</span>
<i v-if="$store.state.i.hasPendingReceivedFollowRequest"><fa :icon="faCircle"/></i>
</router-link>
</template>
<div class="divider"></div> <div class="divider"></div>
<router-link class="item" active-class="active" to="/featured"> <router-link class="item" active-class="active" to="/featured">
<fa :icon="faFireAlt" fixed-width/><span class="text">{{ $t('featured') }}</span> <fa :icon="faFireAlt" fixed-width/><span class="text">{{ $t('featured') }}</span>
@ -143,7 +149,8 @@
<button class="button nav _button" @click="showNav = true" ref="navButton"><fa :icon="faBars"/><i v-if="$store.getters.isSignedIn && ($store.state.i.hasUnreadSpecifiedNotes || $store.state.i.hasPendingReceivedFollowRequest || $store.state.i.hasUnreadMessagingMessage || $store.state.i.hasUnreadAnnouncement)"><fa :icon="faCircle"/></i></button> <button class="button nav _button" @click="showNav = true" ref="navButton"><fa :icon="faBars"/><i v-if="$store.getters.isSignedIn && ($store.state.i.hasUnreadSpecifiedNotes || $store.state.i.hasPendingReceivedFollowRequest || $store.state.i.hasUnreadMessagingMessage || $store.state.i.hasUnreadAnnouncement)"><fa :icon="faCircle"/></i></button>
<button v-if="$route.name === 'index'" class="button home _button" @click="top()"><fa :icon="faHome"/></button> <button v-if="$route.name === 'index'" class="button home _button" @click="top()"><fa :icon="faHome"/></button>
<button v-else class="button home _button" @click="$router.push('/')"><fa :icon="faHome"/></button> <button v-else class="button home _button" @click="$router.push('/')"><fa :icon="faHome"/></button>
<button v-if="$store.getters.isSignedIn" class="button notifications _button" @click="notificationsOpen = !notificationsOpen" ref="notificationButton2"><fa :icon="notificationsOpen ? faTimes : faBell"/><i v-if="$store.state.i.hasUnreadNotification"><fa :icon="faCircle"/></i></button> <button v-if="$store.getters.isSignedIn && $store.state.device.useNotificationsPopup" class="button notifications _button" @click="notificationsOpen = !notificationsOpen" ref="notificationButton2"><fa :icon="notificationsOpen ? faTimes : faBell"/><i v-if="$store.state.i.hasUnreadNotification"><fa :icon="faCircle"/></i></button>
<button v-if="$store.getters.isSignedIn && !$store.state.device.useNotificationsPopup" class="button notifications _button" @click="$router.push('/my/notifications')" ref="notificationButton2"><fa :icon="faBell"/><i v-if="$store.state.i.hasUnreadNotification"><fa :icon="faCircle"/></i></button>
<button v-if="$store.getters.isSignedIn" class="button post _buttonPrimary" @click="post()"><fa :icon="faPencilAlt"/></button> <button v-if="$store.getters.isSignedIn" class="button post _buttonPrimary" @click="post()"><fa :icon="faPencilAlt"/></button>
</div> </div>
@ -1206,15 +1213,17 @@ export default Vue.extend({
left: 0; left: 0;
right: 0; right: 0;
margin: 0 auto; margin: 0 auto;
padding: 8px 8px 0 8px;
z-index: 10001; z-index: 10001;
width: 350px; width: 350px;
height: 400px; height: 400px;
box-sizing: border-box;
background: var(--vocsgcxy); background: var(--vocsgcxy);
-webkit-backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
backdrop-filter: blur(12px); backdrop-filter: blur(12px);
border-radius: 6px; border-radius: 6px;
box-shadow: 0 3px 12px rgba(27, 31, 35, 0.15); box-shadow: 0 3px 12px rgba(27, 31, 35, 0.15);
overflow: hidden; overflow: auto;
@media (max-width: 800px) { @media (max-width: 800px) {
width: 320px; width: 320px;

View file

@ -1,19 +1,17 @@
<template> <template>
<div class="mk-notifications"> <div class="mk-notifications" :class="{ page }">
<div class="contents"> <x-list class="notifications" :items="items" v-slot="{ item: notification }">
<x-list class="notifications" :items="items" v-slot="{ item: notification, i }"> <x-notification :notification="notification" :with-time="true" :full="true" class="notification" :class="{ _panel: page }" :key="notification.id"/>
<x-notification :notification="notification" :with-time="true" :full="true" class="notification" :key="notification.id"/> </x-list>
</x-list>
<button class="more _button" v-if="more" @click="fetchMore" :disabled="moreFetching"> <button class="more _button" v-if="more" @click="fetchMore" :disabled="moreFetching">
<template v-if="!moreFetching">{{ $t('loadMore') }}</template> <template v-if="!moreFetching">{{ $t('loadMore') }}</template>
<template v-if="moreFetching"><fa :icon="faSpinner" pulse fixed-width/></template> <template v-if="moreFetching"><fa :icon="faSpinner" pulse fixed-width/></template>
</button> </button>
<p class="empty" v-if="empty">{{ $t('noNotifications') }}</p> <p class="empty" v-if="empty">{{ $t('noNotifications') }}</p>
<mk-error v-if="error" @retry="init()"/> <mk-error v-if="error" @retry="init()"/>
</div>
</div> </div>
</template> </template>
@ -42,7 +40,7 @@ export default Vue.extend({
type: String, type: String,
required: false required: false
}, },
wide: { page: {
type: Boolean, type: Boolean,
required: false, required: false,
default: false default: false
@ -93,11 +91,15 @@ export default Vue.extend({
<style lang="scss" scoped> <style lang="scss" scoped>
.mk-notifications { .mk-notifications {
> .contents { &.page {
overflow: auto; > .notifications {
height: 100%; > ::v-deep * {
padding: 8px 8px 0 8px; margin-bottom: var(--margin);
}
}
}
&:not(.page) {
> .notifications { > .notifications {
> ::v-deep * { > ::v-deep * {
margin-bottom: 8px; margin-bottom: 8px;
@ -109,28 +111,28 @@ export default Vue.extend({
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
} }
} }
}
> .more { > .more {
display: block; display: block;
width: 100%; width: 100%;
padding: 16px; padding: 16px;
> [data-icon] { > [data-icon] {
margin-right: 4px; margin-right: 4px;
}
} }
}
> .empty { > .empty {
margin: 0; margin: 0;
padding: 16px; padding: 16px;
text-align: center; text-align: center;
color: var(--fg); color: var(--fg);
} }
> .placeholder { > .placeholder {
padding: 32px; padding: 32px;
opacity: 0.3; opacity: 0.3;
}
} }
} }
</style> </style>

View file

@ -0,0 +1,42 @@
<template>
<div>
<portal to="icon"><fa :icon="faBell"/></portal>
<portal to="title">{{ $t('notifications') }}</portal>
<x-notifications @before="before" @after="after" page/>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import { faBell } from '@fortawesome/free-solid-svg-icons';
import Progress from '../scripts/loading';
import XNotifications from '../components/notifications.vue';
export default Vue.extend({
metaInfo() {
return {
title: this.$t('notifications') as string
};
},
components: {
XNotifications
},
data() {
return {
faBell
};
},
methods: {
before() {
Progress.start();
},
after() {
Progress.done();
}
}
});
</script>

View file

@ -21,6 +21,7 @@
<template #desc><mfm text="🍮🍦🍭🍩🍰🍫🍬🥞🍪"/></template> <template #desc><mfm text="🍮🍦🍭🍩🍰🍫🍬🥞🍪"/></template>
</mk-switch> </mk-switch>
<mk-switch v-model="showFixedPostForm">{{ $t('showFixedPostForm') }}</mk-switch> <mk-switch v-model="showFixedPostForm">{{ $t('showFixedPostForm') }}</mk-switch>
<mk-switch v-model="useNotificationsPopup">{{ $t('useNotificationsPopup') }}</mk-switch>
</div> </div>
<div class="_content"> <div class="_content">
<mk-select v-model="lang"> <mk-select v-model="lang">
@ -111,6 +112,11 @@ export default Vue.extend({
get() { return this.$store.state.device.showFixedPostForm; }, get() { return this.$store.state.device.showFixedPostForm; },
set(value) { this.$store.commit('device/set', { key: 'showFixedPostForm', value }); } set(value) { this.$store.commit('device/set', { key: 'showFixedPostForm', value }); }
}, },
useNotificationsPopup: {
get() { return this.$store.state.device.useNotificationsPopup; },
set(value) { this.$store.commit('device/set', { key: 'useNotificationsPopup', value }); }
},
}, },
watch: { watch: {

View file

@ -27,6 +27,7 @@ export const router = new VueRouter({
{ path: '/explore', component: page('explore') }, { path: '/explore', component: page('explore') },
{ path: '/explore/tags/:tag', props: true, component: page('explore') }, { path: '/explore/tags/:tag', props: true, component: page('explore') },
{ path: '/search', component: page('search') }, { path: '/search', component: page('search') },
{ path: '/my/notifications', component: page('notifications') },
{ path: '/my/favorites', component: page('favorites') }, { path: '/my/favorites', component: page('favorites') },
{ path: '/my/messages', component: page('messages') }, { path: '/my/messages', component: page('messages') },
{ path: '/my/mentions', component: page('mentions') }, { path: '/my/mentions', component: page('mentions') },

View file

@ -40,6 +40,7 @@ const defaultDeviceSettings = {
animatedMfm: true, animatedMfm: true,
imageNewTab: false, imageNewTab: false,
showFixedPostForm: false, showFixedPostForm: false,
useNotificationsPopup: true,
userData: {}, userData: {},
}; };