Merge remote-tracking branch 'refs/remotes/origin/master' into bbs
This commit is contained in:
		
						commit
						0e95cdb04c
					
				
					 19 changed files with 526 additions and 393 deletions
				
			
		|  | @ -2,6 +2,10 @@ ChangeLog (Release Notes) | ||||||
| ========================= | ========================= | ||||||
| 主に notable な changes を書いていきます | 主に notable な changes を書いていきます | ||||||
| 
 | 
 | ||||||
|  | 2752 (2017/10/30) | ||||||
|  | ----------------- | ||||||
|  | * New: 未読の通知がある場合アイコンを表示するように | ||||||
|  | 
 | ||||||
| 2747 (2017/10/25) | 2747 (2017/10/25) | ||||||
| ----------------- | ----------------- | ||||||
| * Fix: 非ログイン状態ですべてのページが致命的な問題を発生させる (#89) | * Fix: 非ログイン状態ですべてのページが致命的な問題を発生させる (#89) | ||||||
|  |  | ||||||
|  | @ -395,6 +395,7 @@ mobile: | ||||||
| 
 | 
 | ||||||
|     mk-notifications-page: |     mk-notifications-page: | ||||||
|       notifications: "Notifications" |       notifications: "Notifications" | ||||||
|  |       read-all: "Are you sure you want to mark as read all your notifications?" | ||||||
| 
 | 
 | ||||||
|     mk-post-page: |     mk-post-page: | ||||||
|       title: "Post" |       title: "Post" | ||||||
|  |  | ||||||
|  | @ -395,6 +395,7 @@ mobile: | ||||||
| 
 | 
 | ||||||
|     mk-notifications-page: |     mk-notifications-page: | ||||||
|       notifications: "通知" |       notifications: "通知" | ||||||
|  |       read-all: "すべての通知を既読にしますか?" | ||||||
| 
 | 
 | ||||||
|     mk-post-page: |     mk-post-page: | ||||||
|       title: "投稿" |       title: "投稿" | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| { | { | ||||||
|   "name": "misskey", |   "name": "misskey", | ||||||
|   "author": "syuilo <i@syuilo.com>", |   "author": "syuilo <i@syuilo.com>", | ||||||
|   "version": "0.0.2747", |   "version": "0.0.2752", | ||||||
|   "license": "MIT", |   "license": "MIT", | ||||||
|   "description": "A miniblog-based SNS", |   "description": "A miniblog-based SNS", | ||||||
|   "bugs": "https://github.com/syuilo/misskey/issues", |   "bugs": "https://github.com/syuilo/misskey/issues", | ||||||
|  |  | ||||||
							
								
								
									
										52
									
								
								src/api/common/read-notification.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								src/api/common/read-notification.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,52 @@ | ||||||
|  | import * as mongo from 'mongodb'; | ||||||
|  | import { default as Notification, INotification } from '../models/notification'; | ||||||
|  | import publishUserStream from '../event'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Mark as read notification(s) | ||||||
|  |  */ | ||||||
|  | export default ( | ||||||
|  | 	user: string | mongo.ObjectID, | ||||||
|  | 	message: string | string[] | INotification | INotification[] | mongo.ObjectID | mongo.ObjectID[] | ||||||
|  | ) => new Promise<any>(async (resolve, reject) => { | ||||||
|  | 
 | ||||||
|  | 	const userId = mongo.ObjectID.prototype.isPrototypeOf(user) | ||||||
|  | 		? user | ||||||
|  | 		: new mongo.ObjectID(user); | ||||||
|  | 
 | ||||||
|  | 	const ids: mongo.ObjectID[] = Array.isArray(message) | ||||||
|  | 		? mongo.ObjectID.prototype.isPrototypeOf(message[0]) | ||||||
|  | 			? (message as mongo.ObjectID[]) | ||||||
|  | 			: typeof message[0] === 'string' | ||||||
|  | 				? (message as string[]).map(m => new mongo.ObjectID(m)) | ||||||
|  | 				: (message as INotification[]).map(m => m._id) | ||||||
|  | 		: mongo.ObjectID.prototype.isPrototypeOf(message) | ||||||
|  | 			? [(message as mongo.ObjectID)] | ||||||
|  | 			: typeof message === 'string' | ||||||
|  | 				? [new mongo.ObjectID(message)] | ||||||
|  | 				: [(message as INotification)._id]; | ||||||
|  | 
 | ||||||
|  | 	// Update documents
 | ||||||
|  | 	await Notification.update({ | ||||||
|  | 		_id: { $in: ids }, | ||||||
|  | 		is_read: false | ||||||
|  | 	}, { | ||||||
|  | 		$set: { | ||||||
|  | 			is_read: true | ||||||
|  | 		} | ||||||
|  | 	}, { | ||||||
|  | 		multi: true | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
|  | 	// Calc count of my unread notifications
 | ||||||
|  | 	const count = await Notification | ||||||
|  | 		.count({ | ||||||
|  | 			notifiee_id: userId, | ||||||
|  | 			is_read: false | ||||||
|  | 		}); | ||||||
|  | 
 | ||||||
|  | 	if (count == 0) { | ||||||
|  | 		// 全ての(いままで未読だった)通知を(これで)読みましたよというイベントを発行
 | ||||||
|  | 		publishUserStream(userId, 'read_all_notifications'); | ||||||
|  | 	} | ||||||
|  | }); | ||||||
|  | @ -195,6 +195,11 @@ const endpoints: Endpoint[] = [ | ||||||
| 		withCredential: true, | 		withCredential: true, | ||||||
| 		kind: 'notification-read' | 		kind: 'notification-read' | ||||||
| 	}, | 	}, | ||||||
|  | 	{ | ||||||
|  | 		name: 'notifications/get_unread_count', | ||||||
|  | 		withCredential: true, | ||||||
|  | 		kind: 'notification-read' | ||||||
|  | 	}, | ||||||
| 	{ | 	{ | ||||||
| 		name: 'notifications/delete', | 		name: 'notifications/delete', | ||||||
| 		withCredential: true, | 		withCredential: true, | ||||||
|  | @ -205,11 +210,6 @@ const endpoints: Endpoint[] = [ | ||||||
| 		withCredential: true, | 		withCredential: true, | ||||||
| 		kind: 'notification-write' | 		kind: 'notification-write' | ||||||
| 	}, | 	}, | ||||||
| 	{ |  | ||||||
| 		name: 'notifications/mark_as_read', |  | ||||||
| 		withCredential: true, |  | ||||||
| 		kind: 'notification-write' |  | ||||||
| 	}, |  | ||||||
| 	{ | 	{ | ||||||
| 		name: 'notifications/mark_as_read_all', | 		name: 'notifications/mark_as_read_all', | ||||||
| 		withCredential: true, | 		withCredential: true, | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ import $ from 'cafy'; | ||||||
| import Notification from '../../models/notification'; | import Notification from '../../models/notification'; | ||||||
| import serialize from '../../serializers/notification'; | import serialize from '../../serializers/notification'; | ||||||
| import getFriends from '../../common/get-friends'; | import getFriends from '../../common/get-friends'; | ||||||
|  | import read from '../../common/read-notification'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Get notifications |  * Get notifications | ||||||
|  | @ -91,17 +92,6 @@ module.exports = (params, user) => new Promise(async (res, rej) => { | ||||||
| 
 | 
 | ||||||
| 	// Mark as read all
 | 	// Mark as read all
 | ||||||
| 	if (notifications.length > 0 && markAsRead) { | 	if (notifications.length > 0 && markAsRead) { | ||||||
| 		const ids = notifications | 		read(user._id, notifications); | ||||||
| 			.filter(x => x.is_read == false) |  | ||||||
| 			.map(x => x._id); |  | ||||||
| 
 |  | ||||||
| 		// Update documents
 |  | ||||||
| 		await Notification.update({ |  | ||||||
| 			_id: { $in: ids } |  | ||||||
| 		}, { |  | ||||||
| 			$set: { is_read: true } |  | ||||||
| 		}, { |  | ||||||
| 			multi: true |  | ||||||
| 		}); |  | ||||||
| 	} | 	} | ||||||
| }); | }); | ||||||
|  |  | ||||||
							
								
								
									
										23
									
								
								src/api/endpoints/notifications/get_unread_count.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/api/endpoints/notifications/get_unread_count.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | ||||||
|  | /** | ||||||
|  |  * Module dependencies | ||||||
|  |  */ | ||||||
|  | import Notification from '../../models/notification'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Get count of unread notifications | ||||||
|  |  * | ||||||
|  |  * @param {any} params | ||||||
|  |  * @param {any} user | ||||||
|  |  * @return {Promise<any>} | ||||||
|  |  */ | ||||||
|  | module.exports = (params, user) => new Promise(async (res, rej) => { | ||||||
|  | 	const count = await Notification | ||||||
|  | 		.count({ | ||||||
|  | 			notifiee_id: user._id, | ||||||
|  | 			is_read: false | ||||||
|  | 		}); | ||||||
|  | 
 | ||||||
|  | 	res({ | ||||||
|  | 		count: count | ||||||
|  | 	}); | ||||||
|  | }); | ||||||
|  | @ -1,47 +0,0 @@ | ||||||
| /** |  | ||||||
|  * Module dependencies |  | ||||||
|  */ |  | ||||||
| import $ from 'cafy'; |  | ||||||
| import Notification from '../../models/notification'; |  | ||||||
| import serialize from '../../serializers/notification'; |  | ||||||
| import event from '../../event'; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Mark as read a notification |  | ||||||
|  * |  | ||||||
|  * @param {any} params |  | ||||||
|  * @param {any} user |  | ||||||
|  * @return {Promise<any>} |  | ||||||
|  */ |  | ||||||
| module.exports = (params, user) => new Promise(async (res, rej) => { |  | ||||||
| 	const [notificationId, notificationIdErr] = $(params.notification_id).id().$; |  | ||||||
| 	if (notificationIdErr) return rej('invalid notification_id param'); |  | ||||||
| 
 |  | ||||||
| 	// Get notification
 |  | ||||||
| 	const notification = await Notification |  | ||||||
| 		.findOne({ |  | ||||||
| 			_id: notificationId, |  | ||||||
| 			i: user._id |  | ||||||
| 		}); |  | ||||||
| 
 |  | ||||||
| 	if (notification === null) { |  | ||||||
| 		return rej('notification-not-found'); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Update
 |  | ||||||
| 	notification.is_read = true; |  | ||||||
| 	Notification.update({ _id: notification._id }, { |  | ||||||
| 		$set: { |  | ||||||
| 			is_read: true |  | ||||||
| 		} |  | ||||||
| 	}); |  | ||||||
| 
 |  | ||||||
| 	// Response
 |  | ||||||
| 	res(); |  | ||||||
| 
 |  | ||||||
| 	// Serialize
 |  | ||||||
| 	const notificationObj = await serialize(notification); |  | ||||||
| 
 |  | ||||||
| 	// Publish read_notification event
 |  | ||||||
| 	event(user._id, 'read_notification', notificationObj); |  | ||||||
| }); |  | ||||||
							
								
								
									
										32
									
								
								src/api/endpoints/notifications/mark_as_read_all.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/api/endpoints/notifications/mark_as_read_all.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,32 @@ | ||||||
|  | /** | ||||||
|  |  * Module dependencies | ||||||
|  |  */ | ||||||
|  | import Notification from '../../models/notification'; | ||||||
|  | import event from '../../event'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Mark as read all notifications | ||||||
|  |  * | ||||||
|  |  * @param {any} params | ||||||
|  |  * @param {any} user | ||||||
|  |  * @return {Promise<any>} | ||||||
|  |  */ | ||||||
|  | module.exports = (params, user) => new Promise(async (res, rej) => { | ||||||
|  | 	// Update documents
 | ||||||
|  | 	await Notification.update({ | ||||||
|  | 		notifiee_id: user._id, | ||||||
|  | 		is_read: false | ||||||
|  | 	}, { | ||||||
|  | 		$set: { | ||||||
|  | 			is_read: true | ||||||
|  | 		} | ||||||
|  | 	}, { | ||||||
|  | 		multi: true | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
|  | 	// Response
 | ||||||
|  | 	res(); | ||||||
|  | 
 | ||||||
|  | 	// 全ての通知を読みましたよというイベントを発行
 | ||||||
|  | 	event(user._id, 'read_all_notifications'); | ||||||
|  | }); | ||||||
|  | @ -1,3 +1,8 @@ | ||||||
|  | import * as mongo from 'mongodb'; | ||||||
| import db from '../../db/mongodb'; | import db from '../../db/mongodb'; | ||||||
| 
 | 
 | ||||||
| export default db.get('notifications') as any; // fuck type definition
 | export default db.get('notifications') as any; // fuck type definition
 | ||||||
|  | 
 | ||||||
|  | export interface INotification { | ||||||
|  | 	_id: mongo.ObjectID; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ import * as debug from 'debug'; | ||||||
| 
 | 
 | ||||||
| import User from '../models/user'; | import User from '../models/user'; | ||||||
| import serializePost from '../serializers/post'; | import serializePost from '../serializers/post'; | ||||||
|  | import readNotification from '../common/read-notification'; | ||||||
| 
 | 
 | ||||||
| const log = debug('misskey'); | const log = debug('misskey'); | ||||||
| 
 | 
 | ||||||
|  | @ -45,6 +46,11 @@ export default function homeStream(request: websocket.request, connection: webso | ||||||
| 				}); | 				}); | ||||||
| 				break; | 				break; | ||||||
| 
 | 
 | ||||||
|  | 			case 'read_notification': | ||||||
|  | 				if (!msg.id) return; | ||||||
|  | 				readNotification(user._id, msg.id); | ||||||
|  | 				break; | ||||||
|  | 
 | ||||||
| 			case 'capture': | 			case 'capture': | ||||||
| 				if (!msg.id) return; | 				if (!msg.id) return; | ||||||
| 				const postId = msg.id; | 				const postId = msg.id; | ||||||
|  |  | ||||||
|  | @ -252,6 +252,12 @@ | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
| 		this.onNotification = notification => { | 		this.onNotification = notification => { | ||||||
|  | 			// TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない | ||||||
|  | 			this.stream.send({ | ||||||
|  | 				type: 'read_notification', | ||||||
|  | 				id: notification.id | ||||||
|  | 			}); | ||||||
|  | 
 | ||||||
| 			this.notifications.unshift(notification); | 			this.notifications.unshift(notification); | ||||||
| 			this.update(); | 			this.update(); | ||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
|  | @ -1,6 +1,4 @@ | ||||||
| require('./ui.tag'); | require('./ui.tag'); | ||||||
| require('./ui-header.tag'); |  | ||||||
| require('./ui-nav.tag'); |  | ||||||
| require('./page/entrance.tag'); | require('./page/entrance.tag'); | ||||||
| require('./page/entrance/signin.tag'); | require('./page/entrance/signin.tag'); | ||||||
| require('./page/entrance/signup.tag'); | require('./page/entrance/signup.tag'); | ||||||
|  |  | ||||||
|  | @ -123,6 +123,12 @@ | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
| 		this.onNotification = notification => { | 		this.onNotification = notification => { | ||||||
|  | 			// TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない | ||||||
|  | 			this.stream.send({ | ||||||
|  | 				type: 'read_notification', | ||||||
|  | 				id: notification.id | ||||||
|  | 			}); | ||||||
|  | 
 | ||||||
| 			this.notifications.unshift(notification); | 			this.notifications.unshift(notification); | ||||||
| 			this.update(); | 			this.update(); | ||||||
| 		}; | 		}; | ||||||
|  |  | ||||||
|  | @ -10,16 +10,30 @@ | ||||||
| 		import ui from '../../scripts/ui-event'; | 		import ui from '../../scripts/ui-event'; | ||||||
| 		import Progress from '../../../common/scripts/loading'; | 		import Progress from '../../../common/scripts/loading'; | ||||||
| 
 | 
 | ||||||
|  | 		this.mixin('api'); | ||||||
|  | 
 | ||||||
| 		this.on('mount', () => { | 		this.on('mount', () => { | ||||||
| 			document.title = 'Misskey | %i18n:mobile.tags.mk-notifications-page.notifications%'; | 			document.title = 'Misskey | %i18n:mobile.tags.mk-notifications-page.notifications%'; | ||||||
| 			ui.trigger('title', '<i class="fa fa-bell-o"></i>%i18n:mobile.tags.mk-notifications-page.notifications%'); | 			ui.trigger('title', '<i class="fa fa-bell-o"></i>%i18n:mobile.tags.mk-notifications-page.notifications%'); | ||||||
| 			document.documentElement.style.background = '#313a42'; | 			document.documentElement.style.background = '#313a42'; | ||||||
| 
 | 
 | ||||||
|  | 			ui.trigger('func', () => { | ||||||
|  | 				this.readAll(); | ||||||
|  | 			}, 'check'); | ||||||
|  | 
 | ||||||
| 			Progress.start(); | 			Progress.start(); | ||||||
| 
 | 
 | ||||||
| 			this.refs.ui.refs.notifications.on('fetched', () => { | 			this.refs.ui.refs.notifications.on('fetched', () => { | ||||||
| 				Progress.done(); | 				Progress.done(); | ||||||
| 			}); | 			}); | ||||||
| 		}); | 		}); | ||||||
|  | 
 | ||||||
|  | 		this.readAll = () => { | ||||||
|  | 			const ok = window.confirm('%i18n:mobile.tags.mk-notifications-page.read-all%'); | ||||||
|  | 
 | ||||||
|  | 			if (!ok) return; | ||||||
|  | 
 | ||||||
|  | 			this.api('notifications/mark_as_read_all'); | ||||||
|  | 		}; | ||||||
| 	</script> | 	</script> | ||||||
| </mk-notifications-page> | </mk-notifications-page> | ||||||
|  |  | ||||||
|  | @ -1,156 +0,0 @@ | ||||||
| <mk-ui-header> |  | ||||||
| 	<mk-special-message/> |  | ||||||
| 	<div class="main"> |  | ||||||
| 		<div class="backdrop"></div> |  | ||||||
| 		<div class="content"> |  | ||||||
| 			<button class="nav" onclick={ parent.toggleDrawer }><i class="fa fa-bars"></i></button> |  | ||||||
| 			<i class="fa fa-circle" if={ hasUnreadMessagingMessages }></i> |  | ||||||
| 			<h1 ref="title">Misskey</h1> |  | ||||||
| 			<button if={ func } onclick={ func }><i class="fa fa-{ funcIcon }"></i></button> |  | ||||||
| 		</div> |  | ||||||
| 	</div> |  | ||||||
| 	<style> |  | ||||||
| 		:scope |  | ||||||
| 			$height = 48px |  | ||||||
| 
 |  | ||||||
| 			display block |  | ||||||
| 			position fixed |  | ||||||
| 			top 0 |  | ||||||
| 			z-index 1024 |  | ||||||
| 			width 100% |  | ||||||
| 			box-shadow 0 1px 0 rgba(#000, 0.075) |  | ||||||
| 
 |  | ||||||
| 			> .main |  | ||||||
| 				color rgba(#fff, 0.9) |  | ||||||
| 
 |  | ||||||
| 				> .backdrop |  | ||||||
| 					position absolute |  | ||||||
| 					top 0 |  | ||||||
| 					z-index 1023 |  | ||||||
| 					width 100% |  | ||||||
| 					height $height |  | ||||||
| 					-webkit-backdrop-filter blur(12px) |  | ||||||
| 					backdrop-filter blur(12px) |  | ||||||
| 					background-color rgba(#1b2023, 0.75) |  | ||||||
| 
 |  | ||||||
| 				> .content |  | ||||||
| 					z-index 1024 |  | ||||||
| 
 |  | ||||||
| 					> h1 |  | ||||||
| 						display block |  | ||||||
| 						margin 0 auto |  | ||||||
| 						padding 0 |  | ||||||
| 						width 100% |  | ||||||
| 						max-width calc(100% - 112px) |  | ||||||
| 						text-align center |  | ||||||
| 						font-size 1.1em |  | ||||||
| 						font-weight normal |  | ||||||
| 						line-height $height |  | ||||||
| 						white-space nowrap |  | ||||||
| 						overflow hidden |  | ||||||
| 						text-overflow ellipsis |  | ||||||
| 
 |  | ||||||
| 						> i |  | ||||||
| 						> .icon |  | ||||||
| 							margin-right 8px |  | ||||||
| 
 |  | ||||||
| 						> img |  | ||||||
| 							display inline-block |  | ||||||
| 							vertical-align bottom |  | ||||||
| 							width ($height - 16px) |  | ||||||
| 							height ($height - 16px) |  | ||||||
| 							margin 8px |  | ||||||
| 							border-radius 6px |  | ||||||
| 
 |  | ||||||
| 					> .nav |  | ||||||
| 						display block |  | ||||||
| 						position absolute |  | ||||||
| 						top 0 |  | ||||||
| 						left 0 |  | ||||||
| 						width $height |  | ||||||
| 						font-size 1.4em |  | ||||||
| 						line-height $height |  | ||||||
| 						border-right solid 1px rgba(#000, 0.1) |  | ||||||
| 
 |  | ||||||
| 						> i |  | ||||||
| 							transition all 0.2s ease |  | ||||||
| 
 |  | ||||||
| 					> i |  | ||||||
| 						position absolute |  | ||||||
| 						top 8px |  | ||||||
| 						left 8px |  | ||||||
| 						pointer-events none |  | ||||||
| 						font-size 10px |  | ||||||
| 						color $theme-color |  | ||||||
| 
 |  | ||||||
| 					> button:last-child |  | ||||||
| 						display block |  | ||||||
| 						position absolute |  | ||||||
| 						top 0 |  | ||||||
| 						right 0 |  | ||||||
| 						width $height |  | ||||||
| 						text-align center |  | ||||||
| 						font-size 1.4em |  | ||||||
| 						color inherit |  | ||||||
| 						line-height $height |  | ||||||
| 						border-left solid 1px rgba(#000, 0.1) |  | ||||||
| 
 |  | ||||||
| 	</style> |  | ||||||
| 	<script> |  | ||||||
| 		import ui from '../scripts/ui-event'; |  | ||||||
| 
 |  | ||||||
| 		this.mixin('api'); |  | ||||||
| 		this.mixin('stream'); |  | ||||||
| 
 |  | ||||||
| 		this.func = null; |  | ||||||
| 		this.funcIcon = null; |  | ||||||
| 
 |  | ||||||
| 		this.on('mount', () => { |  | ||||||
| 			this.stream.on('read_all_messaging_messages', this.onReadAllMessagingMessages); |  | ||||||
| 			this.stream.on('unread_messaging_message', this.onUnreadMessagingMessage); |  | ||||||
| 
 |  | ||||||
| 			// Fetch count of unread messaging messages |  | ||||||
| 			this.api('messaging/unread').then(res => { |  | ||||||
| 				if (res.count > 0) { |  | ||||||
| 					this.update({ |  | ||||||
| 						hasUnreadMessagingMessages: true |  | ||||||
| 					}); |  | ||||||
| 				} |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
| 
 |  | ||||||
| 		this.on('unmount', () => { |  | ||||||
| 			this.stream.off('read_all_messaging_messages', this.onReadAllMessagingMessages); |  | ||||||
| 			this.stream.off('unread_messaging_message', this.onUnreadMessagingMessage); |  | ||||||
| 
 |  | ||||||
| 			ui.off('title', this.setTitle); |  | ||||||
| 			ui.off('func', this.setFunc); |  | ||||||
| 		}); |  | ||||||
| 
 |  | ||||||
| 		this.onReadAllMessagingMessages = () => { |  | ||||||
| 			this.update({ |  | ||||||
| 				hasUnreadMessagingMessages: false |  | ||||||
| 			}); |  | ||||||
| 		}; |  | ||||||
| 
 |  | ||||||
| 		this.onUnreadMessagingMessage = () => { |  | ||||||
| 			this.update({ |  | ||||||
| 				hasUnreadMessagingMessages: true |  | ||||||
| 			}); |  | ||||||
| 		}; |  | ||||||
| 
 |  | ||||||
| 		this.setTitle = title => { |  | ||||||
| 			this.refs.title.innerHTML = title; |  | ||||||
| 		}; |  | ||||||
| 
 |  | ||||||
| 		this.setFunc = (fn, icon) => { |  | ||||||
| 			this.update({ |  | ||||||
| 				func: fn, |  | ||||||
| 				funcIcon: icon |  | ||||||
| 			}); |  | ||||||
| 		}; |  | ||||||
| 
 |  | ||||||
| 		ui.on('title', this.setTitle); |  | ||||||
| 		ui.on('func', this.setFunc); |  | ||||||
| 	</script> |  | ||||||
| </mk-ui-header> |  | ||||||
|  | @ -1,170 +0,0 @@ | ||||||
| <mk-ui-nav> |  | ||||||
| 	<div class="backdrop" onclick={ parent.toggleDrawer }></div> |  | ||||||
| 	<div class="body"> |  | ||||||
| 		<a class="me" if={ SIGNIN } href={ '/' + I.username }> |  | ||||||
| 			<img class="avatar" src={ I.avatar_url + '?thumbnail&size=128' } alt="avatar"/> |  | ||||||
| 			<p class="name">{ I.name }</p> |  | ||||||
| 		</a> |  | ||||||
| 		<div class="links"> |  | ||||||
| 			<ul> |  | ||||||
| 				<li><a href="/"><i class="fa fa-home"></i>%i18n:mobile.tags.mk-ui-nav.home%<i class="fa fa-angle-right"></i></a></li> |  | ||||||
| 				<li><a href="/i/notifications"><i class="fa fa-bell-o"></i>%i18n:mobile.tags.mk-ui-nav.notifications%<i class="fa fa-angle-right"></i></a></li> |  | ||||||
| 				<li><a href="/i/messaging"><i class="fa fa-comments-o"></i>%i18n:mobile.tags.mk-ui-nav.messaging%<i class="i fa fa-circle" if={ hasUnreadMessagingMessages }></i><i class="fa fa-angle-right"></i></a></li> |  | ||||||
| 			</ul> |  | ||||||
| 			<ul> |  | ||||||
| 				<li><a onclick={ search }><i class="fa fa-search"></i>%i18n:mobile.tags.mk-ui-nav.search%<i class="fa fa-angle-right"></i></a></li> |  | ||||||
| 			</ul> |  | ||||||
| 			<ul> |  | ||||||
| 				<li><a href="/i/drive"><i class="fa fa-cloud"></i>%i18n:mobile.tags.mk-ui-nav.drive%<i class="fa fa-angle-right"></i></a></li> |  | ||||||
| 			</ul> |  | ||||||
| 			<ul> |  | ||||||
| 				<li><a href="/i/settings"><i class="fa fa-cog"></i>%i18n:mobile.tags.mk-ui-nav.settings%<i class="fa fa-angle-right"></i></a></li> |  | ||||||
| 			</ul> |  | ||||||
| 		</div> |  | ||||||
| 		<a href={ CONFIG.aboutUrl }><p class="about">%i18n:mobile.tags.mk-ui-nav.about%</p></a> |  | ||||||
| 	</div> |  | ||||||
| 	<style> |  | ||||||
| 		:scope |  | ||||||
| 			display none |  | ||||||
| 
 |  | ||||||
| 			.backdrop |  | ||||||
| 				position fixed |  | ||||||
| 				top 0 |  | ||||||
| 				left 0 |  | ||||||
| 				z-index 1025 |  | ||||||
| 				width 100% |  | ||||||
| 				height 100% |  | ||||||
| 				background rgba(0, 0, 0, 0.2) |  | ||||||
| 
 |  | ||||||
| 			.body |  | ||||||
| 				position fixed |  | ||||||
| 				top 0 |  | ||||||
| 				left 0 |  | ||||||
| 				z-index 1026 |  | ||||||
| 				width 240px |  | ||||||
| 				height 100% |  | ||||||
| 				overflow auto |  | ||||||
| 				-webkit-overflow-scrolling touch |  | ||||||
| 				color #777 |  | ||||||
| 				background #fff |  | ||||||
| 
 |  | ||||||
| 			.me |  | ||||||
| 				display block |  | ||||||
| 				margin 0 |  | ||||||
| 				padding 16px |  | ||||||
| 
 |  | ||||||
| 				.avatar |  | ||||||
| 					display inline |  | ||||||
| 					max-width 64px |  | ||||||
| 					border-radius 32px |  | ||||||
| 					vertical-align middle |  | ||||||
| 
 |  | ||||||
| 				.name |  | ||||||
| 					display block |  | ||||||
| 					margin 0 16px |  | ||||||
| 					position absolute |  | ||||||
| 					top 0 |  | ||||||
| 					left 80px |  | ||||||
| 					padding 0 |  | ||||||
| 					width calc(100% - 112px) |  | ||||||
| 					color #777 |  | ||||||
| 					line-height 96px |  | ||||||
| 					overflow hidden |  | ||||||
| 					text-overflow ellipsis |  | ||||||
| 					white-space nowrap |  | ||||||
| 
 |  | ||||||
| 			ul |  | ||||||
| 				display block |  | ||||||
| 				margin 16px 0 |  | ||||||
| 				padding 0 |  | ||||||
| 				list-style none |  | ||||||
| 
 |  | ||||||
| 				&:first-child |  | ||||||
| 					margin-top 0 |  | ||||||
| 
 |  | ||||||
| 				li |  | ||||||
| 					display block |  | ||||||
| 					font-size 1em |  | ||||||
| 					line-height 1em |  | ||||||
| 
 |  | ||||||
| 					a |  | ||||||
| 						display block |  | ||||||
| 						padding 0 20px |  | ||||||
| 						line-height 3rem |  | ||||||
| 						line-height calc(1rem + 30px) |  | ||||||
| 						color #777 |  | ||||||
| 						text-decoration none |  | ||||||
| 
 |  | ||||||
| 						> i:first-child |  | ||||||
| 							margin-right 0.5em |  | ||||||
| 
 |  | ||||||
| 						> .i |  | ||||||
| 							margin-left 6px |  | ||||||
| 							vertical-align super |  | ||||||
| 							font-size 10px |  | ||||||
| 							color $theme-color |  | ||||||
| 
 |  | ||||||
| 						> i:last-child |  | ||||||
| 							position absolute |  | ||||||
| 							top 0 |  | ||||||
| 							right 0 |  | ||||||
| 							padding 0 20px |  | ||||||
| 							font-size 1.2em |  | ||||||
| 							line-height calc(1rem + 30px) |  | ||||||
| 							color #ccc |  | ||||||
| 
 |  | ||||||
| 			.about |  | ||||||
| 				margin 0 |  | ||||||
| 				padding 1em 0 |  | ||||||
| 				text-align center |  | ||||||
| 				font-size 0.8em |  | ||||||
| 				opacity 0.5 |  | ||||||
| 
 |  | ||||||
| 				a |  | ||||||
| 					color #777 |  | ||||||
| 
 |  | ||||||
| 	</style> |  | ||||||
| 	<script> |  | ||||||
| 		this.mixin('i'); |  | ||||||
| 		this.mixin('page'); |  | ||||||
| 		this.mixin('api'); |  | ||||||
| 		this.mixin('stream'); |  | ||||||
| 
 |  | ||||||
| 		this.on('mount', () => { |  | ||||||
| 			this.stream.on('read_all_messaging_messages', this.onReadAllMessagingMessages); |  | ||||||
| 			this.stream.on('unread_messaging_message', this.onUnreadMessagingMessage); |  | ||||||
| 
 |  | ||||||
| 			// Fetch count of unread messaging messages |  | ||||||
| 			this.api('messaging/unread').then(res => { |  | ||||||
| 				if (res.count > 0) { |  | ||||||
| 					this.update({ |  | ||||||
| 						hasUnreadMessagingMessages: true |  | ||||||
| 					}); |  | ||||||
| 				} |  | ||||||
| 			}); |  | ||||||
| 		}); |  | ||||||
| 
 |  | ||||||
| 		this.on('unmount', () => { |  | ||||||
| 			this.stream.off('read_all_messaging_messages', this.onReadAllMessagingMessages); |  | ||||||
| 			this.stream.off('unread_messaging_message', this.onUnreadMessagingMessage); |  | ||||||
| 		}); |  | ||||||
| 
 |  | ||||||
| 		this.onReadAllMessagingMessages = () => { |  | ||||||
| 			this.update({ |  | ||||||
| 				hasUnreadMessagingMessages: false |  | ||||||
| 			}); |  | ||||||
| 		}; |  | ||||||
| 
 |  | ||||||
| 		this.onUnreadMessagingMessage = () => { |  | ||||||
| 			this.update({ |  | ||||||
| 				hasUnreadMessagingMessages: true |  | ||||||
| 			}); |  | ||||||
| 		}; |  | ||||||
| 
 |  | ||||||
| 		this.search = () => { |  | ||||||
| 			const query = window.prompt('%i18n:mobile.tags.mk-ui-nav.search%'); |  | ||||||
| 			if (query == null || query == '') return; |  | ||||||
| 			this.page('/search:' + query); |  | ||||||
| 		}; |  | ||||||
| 	</script> |  | ||||||
| </mk-ui-nav> |  | ||||||
|  | @ -30,9 +30,377 @@ | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		this.onStreamNotification = notification => { | 		this.onStreamNotification = notification => { | ||||||
|  | 			// TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない | ||||||
|  | 			this.stream.send({ | ||||||
|  | 				type: 'read_notification', | ||||||
|  | 				id: notification.id | ||||||
|  | 			}); | ||||||
|  | 
 | ||||||
| 			riot.mount(document.body.appendChild(document.createElement('mk-notify')), { | 			riot.mount(document.body.appendChild(document.createElement('mk-notify')), { | ||||||
| 				notification: notification | 				notification: notification | ||||||
| 			}); | 			}); | ||||||
| 		}; | 		}; | ||||||
| 	</script> | 	</script> | ||||||
| </mk-ui> | </mk-ui> | ||||||
|  | 
 | ||||||
|  | <mk-ui-header> | ||||||
|  | 	<mk-special-message/> | ||||||
|  | 	<div class="main"> | ||||||
|  | 		<div class="backdrop"></div> | ||||||
|  | 		<div class="content"> | ||||||
|  | 			<button class="nav" onclick={ parent.toggleDrawer }><i class="fa fa-bars"></i></button> | ||||||
|  | 			<i class="fa fa-circle" if={ hasUnreadNotifications || hasUnreadMessagingMessages }></i> | ||||||
|  | 			<h1 ref="title">Misskey</h1> | ||||||
|  | 			<button if={ func } onclick={ func }><i class="fa fa-{ funcIcon }"></i></button> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | 	<style> | ||||||
|  | 		:scope | ||||||
|  | 			$height = 48px | ||||||
|  | 
 | ||||||
|  | 			display block | ||||||
|  | 			position fixed | ||||||
|  | 			top 0 | ||||||
|  | 			z-index 1024 | ||||||
|  | 			width 100% | ||||||
|  | 			box-shadow 0 1px 0 rgba(#000, 0.075) | ||||||
|  | 
 | ||||||
|  | 			> .main | ||||||
|  | 				color rgba(#fff, 0.9) | ||||||
|  | 
 | ||||||
|  | 				> .backdrop | ||||||
|  | 					position absolute | ||||||
|  | 					top 0 | ||||||
|  | 					z-index 1023 | ||||||
|  | 					width 100% | ||||||
|  | 					height $height | ||||||
|  | 					-webkit-backdrop-filter blur(12px) | ||||||
|  | 					backdrop-filter blur(12px) | ||||||
|  | 					background-color rgba(#1b2023, 0.75) | ||||||
|  | 
 | ||||||
|  | 				> .content | ||||||
|  | 					z-index 1024 | ||||||
|  | 
 | ||||||
|  | 					> h1 | ||||||
|  | 						display block | ||||||
|  | 						margin 0 auto | ||||||
|  | 						padding 0 | ||||||
|  | 						width 100% | ||||||
|  | 						max-width calc(100% - 112px) | ||||||
|  | 						text-align center | ||||||
|  | 						font-size 1.1em | ||||||
|  | 						font-weight normal | ||||||
|  | 						line-height $height | ||||||
|  | 						white-space nowrap | ||||||
|  | 						overflow hidden | ||||||
|  | 						text-overflow ellipsis | ||||||
|  | 
 | ||||||
|  | 						> i | ||||||
|  | 						> .icon | ||||||
|  | 							margin-right 8px | ||||||
|  | 
 | ||||||
|  | 						> img | ||||||
|  | 							display inline-block | ||||||
|  | 							vertical-align bottom | ||||||
|  | 							width ($height - 16px) | ||||||
|  | 							height ($height - 16px) | ||||||
|  | 							margin 8px | ||||||
|  | 							border-radius 6px | ||||||
|  | 
 | ||||||
|  | 					> .nav | ||||||
|  | 						display block | ||||||
|  | 						position absolute | ||||||
|  | 						top 0 | ||||||
|  | 						left 0 | ||||||
|  | 						width $height | ||||||
|  | 						font-size 1.4em | ||||||
|  | 						line-height $height | ||||||
|  | 						border-right solid 1px rgba(#000, 0.1) | ||||||
|  | 
 | ||||||
|  | 						> i | ||||||
|  | 							transition all 0.2s ease | ||||||
|  | 
 | ||||||
|  | 					> i | ||||||
|  | 						position absolute | ||||||
|  | 						top 8px | ||||||
|  | 						left 8px | ||||||
|  | 						pointer-events none | ||||||
|  | 						font-size 10px | ||||||
|  | 						color $theme-color | ||||||
|  | 
 | ||||||
|  | 					> button:last-child | ||||||
|  | 						display block | ||||||
|  | 						position absolute | ||||||
|  | 						top 0 | ||||||
|  | 						right 0 | ||||||
|  | 						width $height | ||||||
|  | 						text-align center | ||||||
|  | 						font-size 1.4em | ||||||
|  | 						color inherit | ||||||
|  | 						line-height $height | ||||||
|  | 						border-left solid 1px rgba(#000, 0.1) | ||||||
|  | 
 | ||||||
|  | 	</style> | ||||||
|  | 	<script> | ||||||
|  | 		import ui from '../scripts/ui-event'; | ||||||
|  | 
 | ||||||
|  | 		this.mixin('api'); | ||||||
|  | 		this.mixin('stream'); | ||||||
|  | 
 | ||||||
|  | 		this.func = null; | ||||||
|  | 		this.funcIcon = null; | ||||||
|  | 
 | ||||||
|  | 		this.on('mount', () => { | ||||||
|  | 			this.stream.on('read_all_notifications', this.onReadAllNotifications); | ||||||
|  | 			this.stream.on('read_all_messaging_messages', this.onReadAllMessagingMessages); | ||||||
|  | 			this.stream.on('unread_messaging_message', this.onUnreadMessagingMessage); | ||||||
|  | 
 | ||||||
|  | 			// Fetch count of unread notifications | ||||||
|  | 			this.api('notifications/get_unread_count').then(res => { | ||||||
|  | 				if (res.count > 0) { | ||||||
|  | 					this.update({ | ||||||
|  | 						hasUnreadNotifications: true | ||||||
|  | 					}); | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  | 
 | ||||||
|  | 			// Fetch count of unread messaging messages | ||||||
|  | 			this.api('messaging/unread').then(res => { | ||||||
|  | 				if (res.count > 0) { | ||||||
|  | 					this.update({ | ||||||
|  | 						hasUnreadMessagingMessages: true | ||||||
|  | 					}); | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  | 		}); | ||||||
|  | 
 | ||||||
|  | 		this.on('unmount', () => { | ||||||
|  | 			this.stream.off('read_all_notifications', this.onReadAllNotifications); | ||||||
|  | 			this.stream.off('read_all_messaging_messages', this.onReadAllMessagingMessages); | ||||||
|  | 			this.stream.off('unread_messaging_message', this.onUnreadMessagingMessage); | ||||||
|  | 
 | ||||||
|  | 			ui.off('title', this.setTitle); | ||||||
|  | 			ui.off('func', this.setFunc); | ||||||
|  | 		}); | ||||||
|  | 
 | ||||||
|  | 		this.onReadAllNotifications = () => { | ||||||
|  | 			this.update({ | ||||||
|  | 				hasUnreadNotifications: false | ||||||
|  | 			}); | ||||||
|  | 		}; | ||||||
|  | 
 | ||||||
|  | 		this.onReadAllMessagingMessages = () => { | ||||||
|  | 			this.update({ | ||||||
|  | 				hasUnreadMessagingMessages: false | ||||||
|  | 			}); | ||||||
|  | 		}; | ||||||
|  | 
 | ||||||
|  | 		this.onUnreadMessagingMessage = () => { | ||||||
|  | 			this.update({ | ||||||
|  | 				hasUnreadMessagingMessages: true | ||||||
|  | 			}); | ||||||
|  | 		}; | ||||||
|  | 
 | ||||||
|  | 		this.setTitle = title => { | ||||||
|  | 			this.refs.title.innerHTML = title; | ||||||
|  | 		}; | ||||||
|  | 
 | ||||||
|  | 		this.setFunc = (fn, icon) => { | ||||||
|  | 			this.update({ | ||||||
|  | 				func: fn, | ||||||
|  | 				funcIcon: icon | ||||||
|  | 			}); | ||||||
|  | 		}; | ||||||
|  | 
 | ||||||
|  | 		ui.on('title', this.setTitle); | ||||||
|  | 		ui.on('func', this.setFunc); | ||||||
|  | 	</script> | ||||||
|  | </mk-ui-header> | ||||||
|  | 
 | ||||||
|  | <mk-ui-nav> | ||||||
|  | 	<div class="backdrop" onclick={ parent.toggleDrawer }></div> | ||||||
|  | 	<div class="body"> | ||||||
|  | 		<a class="me" if={ SIGNIN } href={ '/' + I.username }> | ||||||
|  | 			<img class="avatar" src={ I.avatar_url + '?thumbnail&size=128' } alt="avatar"/> | ||||||
|  | 			<p class="name">{ I.name }</p> | ||||||
|  | 		</a> | ||||||
|  | 		<div class="links"> | ||||||
|  | 			<ul> | ||||||
|  | 				<li><a href="/"><i class="fa fa-home"></i>%i18n:mobile.tags.mk-ui-nav.home%<i class="fa fa-angle-right"></i></a></li> | ||||||
|  | 				<li><a href="/i/notifications"><i class="fa fa-bell-o"></i>%i18n:mobile.tags.mk-ui-nav.notifications%<i class="i fa fa-circle" if={ hasUnreadNotifications }></i><i class="fa fa-angle-right"></i></a></li> | ||||||
|  | 				<li><a href="/i/messaging"><i class="fa fa-comments-o"></i>%i18n:mobile.tags.mk-ui-nav.messaging%<i class="i fa fa-circle" if={ hasUnreadMessagingMessages }></i><i class="fa fa-angle-right"></i></a></li> | ||||||
|  | 			</ul> | ||||||
|  | 			<ul> | ||||||
|  | 				<li><a onclick={ search }><i class="fa fa-search"></i>%i18n:mobile.tags.mk-ui-nav.search%<i class="fa fa-angle-right"></i></a></li> | ||||||
|  | 			</ul> | ||||||
|  | 			<ul> | ||||||
|  | 				<li><a href="/i/drive"><i class="fa fa-cloud"></i>%i18n:mobile.tags.mk-ui-nav.drive%<i class="fa fa-angle-right"></i></a></li> | ||||||
|  | 			</ul> | ||||||
|  | 			<ul> | ||||||
|  | 				<li><a href="/i/settings"><i class="fa fa-cog"></i>%i18n:mobile.tags.mk-ui-nav.settings%<i class="fa fa-angle-right"></i></a></li> | ||||||
|  | 			</ul> | ||||||
|  | 		</div> | ||||||
|  | 		<a href={ CONFIG.aboutUrl }><p class="about">%i18n:mobile.tags.mk-ui-nav.about%</p></a> | ||||||
|  | 	</div> | ||||||
|  | 	<style> | ||||||
|  | 		:scope | ||||||
|  | 			display none | ||||||
|  | 
 | ||||||
|  | 			.backdrop | ||||||
|  | 				position fixed | ||||||
|  | 				top 0 | ||||||
|  | 				left 0 | ||||||
|  | 				z-index 1025 | ||||||
|  | 				width 100% | ||||||
|  | 				height 100% | ||||||
|  | 				background rgba(0, 0, 0, 0.2) | ||||||
|  | 
 | ||||||
|  | 			.body | ||||||
|  | 				position fixed | ||||||
|  | 				top 0 | ||||||
|  | 				left 0 | ||||||
|  | 				z-index 1026 | ||||||
|  | 				width 240px | ||||||
|  | 				height 100% | ||||||
|  | 				overflow auto | ||||||
|  | 				-webkit-overflow-scrolling touch | ||||||
|  | 				color #777 | ||||||
|  | 				background #fff | ||||||
|  | 
 | ||||||
|  | 			.me | ||||||
|  | 				display block | ||||||
|  | 				margin 0 | ||||||
|  | 				padding 16px | ||||||
|  | 
 | ||||||
|  | 				.avatar | ||||||
|  | 					display inline | ||||||
|  | 					max-width 64px | ||||||
|  | 					border-radius 32px | ||||||
|  | 					vertical-align middle | ||||||
|  | 
 | ||||||
|  | 				.name | ||||||
|  | 					display block | ||||||
|  | 					margin 0 16px | ||||||
|  | 					position absolute | ||||||
|  | 					top 0 | ||||||
|  | 					left 80px | ||||||
|  | 					padding 0 | ||||||
|  | 					width calc(100% - 112px) | ||||||
|  | 					color #777 | ||||||
|  | 					line-height 96px | ||||||
|  | 					overflow hidden | ||||||
|  | 					text-overflow ellipsis | ||||||
|  | 					white-space nowrap | ||||||
|  | 
 | ||||||
|  | 			ul | ||||||
|  | 				display block | ||||||
|  | 				margin 16px 0 | ||||||
|  | 				padding 0 | ||||||
|  | 				list-style none | ||||||
|  | 
 | ||||||
|  | 				&:first-child | ||||||
|  | 					margin-top 0 | ||||||
|  | 
 | ||||||
|  | 				li | ||||||
|  | 					display block | ||||||
|  | 					font-size 1em | ||||||
|  | 					line-height 1em | ||||||
|  | 
 | ||||||
|  | 					a | ||||||
|  | 						display block | ||||||
|  | 						padding 0 20px | ||||||
|  | 						line-height 3rem | ||||||
|  | 						line-height calc(1rem + 30px) | ||||||
|  | 						color #777 | ||||||
|  | 						text-decoration none | ||||||
|  | 
 | ||||||
|  | 						> i:first-child | ||||||
|  | 							margin-right 0.5em | ||||||
|  | 
 | ||||||
|  | 						> .i | ||||||
|  | 							margin-left 6px | ||||||
|  | 							vertical-align super | ||||||
|  | 							font-size 10px | ||||||
|  | 							color $theme-color | ||||||
|  | 
 | ||||||
|  | 						> i:last-child | ||||||
|  | 							position absolute | ||||||
|  | 							top 0 | ||||||
|  | 							right 0 | ||||||
|  | 							padding 0 20px | ||||||
|  | 							font-size 1.2em | ||||||
|  | 							line-height calc(1rem + 30px) | ||||||
|  | 							color #ccc | ||||||
|  | 
 | ||||||
|  | 			.about | ||||||
|  | 				margin 0 | ||||||
|  | 				padding 1em 0 | ||||||
|  | 				text-align center | ||||||
|  | 				font-size 0.8em | ||||||
|  | 				opacity 0.5 | ||||||
|  | 
 | ||||||
|  | 				a | ||||||
|  | 					color #777 | ||||||
|  | 
 | ||||||
|  | 	</style> | ||||||
|  | 	<script> | ||||||
|  | 		this.mixin('i'); | ||||||
|  | 		this.mixin('page'); | ||||||
|  | 		this.mixin('api'); | ||||||
|  | 		this.mixin('stream'); | ||||||
|  | 
 | ||||||
|  | 		this.on('mount', () => { | ||||||
|  | 			this.stream.on('read_all_notifications', this.onReadAllNotifications); | ||||||
|  | 			this.stream.on('read_all_messaging_messages', this.onReadAllMessagingMessages); | ||||||
|  | 			this.stream.on('unread_messaging_message', this.onUnreadMessagingMessage); | ||||||
|  | 
 | ||||||
|  | 			// Fetch count of unread notifications | ||||||
|  | 			this.api('notifications/get_unread_count').then(res => { | ||||||
|  | 				if (res.count > 0) { | ||||||
|  | 					this.update({ | ||||||
|  | 						hasUnreadNotifications: true | ||||||
|  | 					}); | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  | 
 | ||||||
|  | 			// Fetch count of unread messaging messages | ||||||
|  | 			this.api('messaging/unread').then(res => { | ||||||
|  | 				if (res.count > 0) { | ||||||
|  | 					this.update({ | ||||||
|  | 						hasUnreadMessagingMessages: true | ||||||
|  | 					}); | ||||||
|  | 				} | ||||||
|  | 			}); | ||||||
|  | 		}); | ||||||
|  | 
 | ||||||
|  | 		this.on('unmount', () => { | ||||||
|  | 			this.stream.off('read_all_notifications', this.onReadAllNotifications); | ||||||
|  | 			this.stream.off('read_all_messaging_messages', this.onReadAllMessagingMessages); | ||||||
|  | 			this.stream.off('unread_messaging_message', this.onUnreadMessagingMessage); | ||||||
|  | 		}); | ||||||
|  | 
 | ||||||
|  | 		this.onReadAllNotifications = () => { | ||||||
|  | 			this.update({ | ||||||
|  | 				hasUnreadNotifications: false | ||||||
|  | 			}); | ||||||
|  | 		}; | ||||||
|  | 
 | ||||||
|  | 		this.onReadAllMessagingMessages = () => { | ||||||
|  | 			this.update({ | ||||||
|  | 				hasUnreadMessagingMessages: false | ||||||
|  | 			}); | ||||||
|  | 		}; | ||||||
|  | 
 | ||||||
|  | 		this.onUnreadMessagingMessage = () => { | ||||||
|  | 			this.update({ | ||||||
|  | 				hasUnreadMessagingMessages: true | ||||||
|  | 			}); | ||||||
|  | 		}; | ||||||
|  | 
 | ||||||
|  | 		this.search = () => { | ||||||
|  | 			const query = window.prompt('%i18n:mobile.tags.mk-ui-nav.search%'); | ||||||
|  | 			if (query == null || query == '') return; | ||||||
|  | 			this.page('/search:' + query); | ||||||
|  | 		}; | ||||||
|  | 	</script> | ||||||
|  | </mk-ui-nav> | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue