Resolve #5978
This commit is contained in:
		
							parent
							
								
									98a87ee75f
								
							
						
					
					
						commit
						d1e9e74cb8
					
				
					 7 changed files with 114 additions and 52 deletions
				
			
		|  | @ -423,6 +423,7 @@ serverLogs: "サーバーログ" | |||
| deleteAll: "全て削除" | ||||
| showFixedPostForm: "タイムライン上部に投稿フォームを表示する" | ||||
| newNoteRecived: "新しいノートがあります" | ||||
| useNotificationsPopup: "通知一覧をポップアップで表示" | ||||
| 
 | ||||
| _ago: | ||||
|   unknown: "謎" | ||||
|  |  | |||
|  | @ -50,21 +50,27 @@ | |||
| 				<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> | ||||
| 				</router-link> | ||||
| 				<button class="item _button notifications" @click="notificationsOpen = !notificationsOpen" ref="notificationButton" v-if="$store.getters.isSignedIn"> | ||||
| 					<fa :icon="faBell" fixed-width/><span class="text">{{ $t('notifications') }}</span> | ||||
| 					<i v-if="$store.state.i.hasUnreadNotification"><fa :icon="faCircle"/></i> | ||||
| 				</button> | ||||
| 				<router-link class="item" active-class="active" to="/my/messaging" v-if="$store.getters.isSignedIn"> | ||||
| 					<fa :icon="faComments" fixed-width/><span class="text">{{ $t('messaging') }}</span> | ||||
| 					<i v-if="$store.state.i.hasUnreadMessagingMessage"><fa :icon="faCircle"/></i> | ||||
| 				</router-link> | ||||
| 				<router-link class="item" active-class="active" to="/my/drive" v-if="$store.getters.isSignedIn"> | ||||
| 					<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.getters.isSignedIn && $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 v-if="$store.getters.isSignedIn"> | ||||
| 					<button class="item _button notifications" @click="notificationsOpen = !notificationsOpen" ref="notificationButton" v-if="$store.state.device.useNotificationsPopup"> | ||||
| 						<fa :icon="faBell" fixed-width/><span class="text">{{ $t('notifications') }}</span> | ||||
| 						<i v-if="$store.state.i.hasUnreadNotification"><fa :icon="faCircle"/></i> | ||||
| 					</button> | ||||
| 					<router-link class="item notifications" active-class="active" to="/my/notifications" ref="notificationButton" v-else> | ||||
| 						<fa :icon="faBell" fixed-width/><span class="text">{{ $t('notifications') }}</span> | ||||
| 						<i v-if="$store.state.i.hasUnreadNotification"><fa :icon="faCircle"/></i> | ||||
| 					</router-link> | ||||
| 					<router-link class="item" active-class="active" to="/my/messaging"> | ||||
| 						<fa :icon="faComments" fixed-width/><span class="text">{{ $t('messaging') }}</span> | ||||
| 						<i v-if="$store.state.i.hasUnreadMessagingMessage"><fa :icon="faCircle"/></i> | ||||
| 					</router-link> | ||||
| 					<router-link class="item" active-class="active" to="/my/drive"> | ||||
| 						<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> | ||||
| 				<router-link class="item" active-class="active" to="/featured"> | ||||
| 					<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 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-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> | ||||
| 	</div> | ||||
| 
 | ||||
|  | @ -1206,15 +1213,17 @@ export default Vue.extend({ | |||
| 		left: 0; | ||||
| 		right: 0; | ||||
| 		margin: 0 auto; | ||||
| 		padding: 8px 8px 0 8px; | ||||
| 		z-index: 10001; | ||||
| 		width: 350px; | ||||
| 		height: 400px; | ||||
| 		box-sizing: border-box; | ||||
| 		background: var(--vocsgcxy); | ||||
| 		-webkit-backdrop-filter: blur(12px); | ||||
| 		backdrop-filter: blur(12px); | ||||
| 		border-radius: 6px; | ||||
| 		box-shadow: 0 3px 12px rgba(27, 31, 35, 0.15); | ||||
| 		overflow: hidden; | ||||
| 		overflow: auto; | ||||
| 
 | ||||
| 		@media (max-width: 800px) { | ||||
| 			width: 320px; | ||||
|  |  | |||
|  | @ -1,19 +1,17 @@ | |||
| <template> | ||||
| <div class="mk-notifications"> | ||||
| 	<div class="contents"> | ||||
| 		<x-list class="notifications" :items="items" v-slot="{ item: notification, i }"> | ||||
| 			<x-notification :notification="notification" :with-time="true" :full="true" class="notification" :key="notification.id"/> | ||||
| 		</x-list> | ||||
| <div class="mk-notifications" :class="{ page }"> | ||||
| 	<x-list class="notifications" :items="items" v-slot="{ item: notification }"> | ||||
| 		<x-notification :notification="notification" :with-time="true" :full="true" class="notification" :class="{ _panel: page }" :key="notification.id"/> | ||||
| 	</x-list> | ||||
| 
 | ||||
| 		<button class="more _button" v-if="more" @click="fetchMore" :disabled="moreFetching"> | ||||
| 			<template v-if="!moreFetching">{{ $t('loadMore') }}</template> | ||||
| 			<template v-if="moreFetching"><fa :icon="faSpinner" pulse fixed-width/></template> | ||||
| 		</button> | ||||
| 	<button class="more _button" v-if="more" @click="fetchMore" :disabled="moreFetching"> | ||||
| 		<template v-if="!moreFetching">{{ $t('loadMore') }}</template> | ||||
| 		<template v-if="moreFetching"><fa :icon="faSpinner" pulse fixed-width/></template> | ||||
| 	</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()"/> | ||||
| 	</div> | ||||
| 	<mk-error v-if="error" @retry="init()"/> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
|  | @ -42,7 +40,7 @@ export default Vue.extend({ | |||
| 			type: String, | ||||
| 			required: false | ||||
| 		}, | ||||
| 		wide: { | ||||
| 		page: { | ||||
| 			type: Boolean, | ||||
| 			required: false, | ||||
| 			default: false | ||||
|  | @ -93,11 +91,15 @@ export default Vue.extend({ | |||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .mk-notifications { | ||||
| 	> .contents { | ||||
| 		overflow: auto; | ||||
| 		height: 100%; | ||||
| 		padding: 8px 8px 0 8px; | ||||
| 	&.page { | ||||
| 		> .notifications { | ||||
| 			> ::v-deep * { | ||||
| 				margin-bottom: var(--margin); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	&:not(.page) { | ||||
| 		> .notifications { | ||||
| 			> ::v-deep * { | ||||
| 				margin-bottom: 8px; | ||||
|  | @ -109,28 +111,28 @@ export default Vue.extend({ | |||
| 				box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 		> .more { | ||||
| 			display: block; | ||||
| 			width: 100%; | ||||
| 			padding: 16px; | ||||
| 	> .more { | ||||
| 		display: block; | ||||
| 		width: 100%; | ||||
| 		padding: 16px; | ||||
| 
 | ||||
| 			> [data-icon] { | ||||
| 				margin-right: 4px; | ||||
| 			} | ||||
| 		> [data-icon] { | ||||
| 			margin-right: 4px; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 		> .empty { | ||||
| 			margin: 0; | ||||
| 			padding: 16px; | ||||
| 			text-align: center; | ||||
| 			color: var(--fg); | ||||
| 		} | ||||
| 	> .empty { | ||||
| 		margin: 0; | ||||
| 		padding: 16px; | ||||
| 		text-align: center; | ||||
| 		color: var(--fg); | ||||
| 	} | ||||
| 
 | ||||
| 		> .placeholder { | ||||
| 			padding: 32px; | ||||
| 			opacity: 0.3; | ||||
| 		} | ||||
| 	> .placeholder { | ||||
| 		padding: 32px; | ||||
| 		opacity: 0.3; | ||||
| 	} | ||||
| } | ||||
| </style> | ||||
|  |  | |||
							
								
								
									
										42
									
								
								src/client/pages/notifications.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/client/pages/notifications.vue
									
										
									
									
									
										Normal 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> | ||||
|  | @ -20,7 +20,8 @@ | |||
| 				{{ $t('useOsNativeEmojis') }} | ||||
| 				<template #desc><mfm text="🍮🍦🍭🍩🍰🍫🍬🥞🍪"/></template> | ||||
| 			</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 class="_content"> | ||||
| 			<mk-select v-model="lang"> | ||||
|  | @ -111,6 +112,11 @@ export default Vue.extend({ | |||
| 			get() { return this.$store.state.device.showFixedPostForm; }, | ||||
| 			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: { | ||||
|  |  | |||
|  | @ -27,6 +27,7 @@ export const router = new VueRouter({ | |||
| 		{ path: '/explore', component: page('explore') }, | ||||
| 		{ path: '/explore/tags/:tag', props: true, component: page('explore') }, | ||||
| 		{ path: '/search', component: page('search') }, | ||||
| 		{ path: '/my/notifications', component: page('notifications') }, | ||||
| 		{ path: '/my/favorites', component: page('favorites') }, | ||||
| 		{ path: '/my/messages', component: page('messages') }, | ||||
| 		{ path: '/my/mentions', component: page('mentions') }, | ||||
|  |  | |||
|  | @ -40,6 +40,7 @@ const defaultDeviceSettings = { | |||
| 	animatedMfm: true, | ||||
| 	imageNewTab: false, | ||||
| 	showFixedPostForm: false, | ||||
| 	useNotificationsPopup: true, | ||||
| 	userData: {}, | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue