diff options
| author | syuilo <syuilotan@yahoo.co.jp> | 2017-10-30 22:12:10 +0900 |
|---|---|---|
| committer | syuilo <syuilotan@yahoo.co.jp> | 2017-10-30 22:12:10 +0900 |
| commit | caa47cb38cfc3950539c78ca2e70f2c50e815d2c (patch) | |
| tree | fc1a70e1c1b105ecf8d74ff4d952eff86ded83f6 /src | |
| parent | i18n (diff) | |
| download | sharkey-caa47cb38cfc3950539c78ca2e70f2c50e815d2c.tar.gz sharkey-caa47cb38cfc3950539c78ca2e70f2c50e815d2c.tar.bz2 sharkey-caa47cb38cfc3950539c78ca2e70f2c50e815d2c.zip | |
未読の通知がある場合アイコンを表示するように
Diffstat (limited to 'src')
| -rw-r--r-- | src/api/common/read-notification.ts | 52 | ||||
| -rw-r--r-- | src/api/endpoints.ts | 8 | ||||
| -rw-r--r-- | src/api/endpoints/i/notifications.ts | 14 | ||||
| -rw-r--r-- | src/api/endpoints/notifications/get_unread_count.ts | 23 | ||||
| -rw-r--r-- | src/api/endpoints/notifications/mark_as_read.ts | 47 | ||||
| -rw-r--r-- | src/api/endpoints/notifications/mark_as_read_all.ts | 32 | ||||
| -rw-r--r-- | src/api/models/notification.ts | 5 | ||||
| -rw-r--r-- | src/api/stream/home.ts | 6 | ||||
| -rw-r--r-- | src/web/app/desktop/tags/notifications.tag | 6 | ||||
| -rw-r--r-- | src/web/app/mobile/tags/index.js | 2 | ||||
| -rw-r--r-- | src/web/app/mobile/tags/notifications.tag | 6 | ||||
| -rw-r--r-- | src/web/app/mobile/tags/page/notifications.tag | 14 | ||||
| -rw-r--r-- | src/web/app/mobile/tags/ui-header.tag | 156 | ||||
| -rw-r--r-- | src/web/app/mobile/tags/ui-nav.tag | 170 | ||||
| -rw-r--r-- | src/web/app/mobile/tags/ui.tag | 368 |
15 files changed, 518 insertions, 391 deletions
diff --git a/src/api/common/read-notification.ts b/src/api/common/read-notification.ts new file mode 100644 index 0000000000..3009cc5d08 --- /dev/null +++ b/src/api/common/read-notification.ts @@ -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'); + } +}); diff --git a/src/api/endpoints.ts b/src/api/endpoints.ts index f05762340c..29a97bcb8a 100644 --- a/src/api/endpoints.ts +++ b/src/api/endpoints.ts @@ -196,17 +196,17 @@ const endpoints: Endpoint[] = [ kind: 'notification-read' }, { - name: 'notifications/delete', + name: 'notifications/get_unread_count', withCredential: true, - kind: 'notification-write' + kind: 'notification-read' }, { - name: 'notifications/delete_all', + name: 'notifications/delete', withCredential: true, kind: 'notification-write' }, { - name: 'notifications/mark_as_read', + name: 'notifications/delete_all', withCredential: true, kind: 'notification-write' }, diff --git a/src/api/endpoints/i/notifications.ts b/src/api/endpoints/i/notifications.ts index 5575fb7412..607e0768a4 100644 --- a/src/api/endpoints/i/notifications.ts +++ b/src/api/endpoints/i/notifications.ts @@ -5,6 +5,7 @@ import $ from 'cafy'; import Notification from '../../models/notification'; import serialize from '../../serializers/notification'; import getFriends from '../../common/get-friends'; +import read from '../../common/read-notification'; /** * Get notifications @@ -91,17 +92,6 @@ module.exports = (params, user) => new Promise(async (res, rej) => { // Mark as read all if (notifications.length > 0 && markAsRead) { - const ids = 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 - }); + read(user._id, notifications); } }); diff --git a/src/api/endpoints/notifications/get_unread_count.ts b/src/api/endpoints/notifications/get_unread_count.ts new file mode 100644 index 0000000000..9514e78713 --- /dev/null +++ b/src/api/endpoints/notifications/get_unread_count.ts @@ -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 + }); +}); diff --git a/src/api/endpoints/notifications/mark_as_read.ts b/src/api/endpoints/notifications/mark_as_read.ts deleted file mode 100644 index 5cce33e850..0000000000 --- a/src/api/endpoints/notifications/mark_as_read.ts +++ /dev/null @@ -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); -}); diff --git a/src/api/endpoints/notifications/mark_as_read_all.ts b/src/api/endpoints/notifications/mark_as_read_all.ts new file mode 100644 index 0000000000..3550e344c4 --- /dev/null +++ b/src/api/endpoints/notifications/mark_as_read_all.ts @@ -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'); +}); diff --git a/src/api/models/notification.ts b/src/api/models/notification.ts index 1c1f429a0d..1065e8baaa 100644 --- a/src/api/models/notification.ts +++ b/src/api/models/notification.ts @@ -1,3 +1,8 @@ +import * as mongo from 'mongodb'; import db from '../../db/mongodb'; export default db.get('notifications') as any; // fuck type definition + +export interface INotification { + _id: mongo.ObjectID; +} diff --git a/src/api/stream/home.ts b/src/api/stream/home.ts index d5fe01c261..7c8f3bfec8 100644 --- a/src/api/stream/home.ts +++ b/src/api/stream/home.ts @@ -4,6 +4,7 @@ import * as debug from 'debug'; import User from '../models/user'; import serializePost from '../serializers/post'; +import readNotification from '../common/read-notification'; const log = debug('misskey'); @@ -45,6 +46,11 @@ export default function homeStream(request: websocket.request, connection: webso }); break; + case 'read_notification': + if (!msg.id) return; + readNotification(user._id, msg.id); + break; + case 'capture': if (!msg.id) return; const postId = msg.id; diff --git a/src/web/app/desktop/tags/notifications.tag b/src/web/app/desktop/tags/notifications.tag index 1046358ce9..a4f66105a8 100644 --- a/src/web/app/desktop/tags/notifications.tag +++ b/src/web/app/desktop/tags/notifications.tag @@ -252,6 +252,12 @@ }); this.onNotification = notification => { + // TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない + this.stream.send({ + type: 'read_notification', + id: notification.id + }); + this.notifications.unshift(notification); this.update(); }; diff --git a/src/web/app/mobile/tags/index.js b/src/web/app/mobile/tags/index.js index c5aafd20ba..a79f4f7e7e 100644 --- a/src/web/app/mobile/tags/index.js +++ b/src/web/app/mobile/tags/index.js @@ -1,6 +1,4 @@ require('./ui.tag'); -require('./ui-header.tag'); -require('./ui-nav.tag'); require('./page/entrance.tag'); require('./page/entrance/signin.tag'); require('./page/entrance/signup.tag'); diff --git a/src/web/app/mobile/tags/notifications.tag b/src/web/app/mobile/tags/notifications.tag index 7370aa84d3..2e95990314 100644 --- a/src/web/app/mobile/tags/notifications.tag +++ b/src/web/app/mobile/tags/notifications.tag @@ -123,6 +123,12 @@ }); this.onNotification = notification => { + // TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない + this.stream.send({ + type: 'read_notification', + id: notification.id + }); + this.notifications.unshift(notification); this.update(); }; diff --git a/src/web/app/mobile/tags/page/notifications.tag b/src/web/app/mobile/tags/page/notifications.tag index 06a5be039f..743de04393 100644 --- a/src/web/app/mobile/tags/page/notifications.tag +++ b/src/web/app/mobile/tags/page/notifications.tag @@ -10,16 +10,30 @@ import ui from '../../scripts/ui-event'; import Progress from '../../../common/scripts/loading'; + this.mixin('api'); + this.on('mount', () => { 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%'); document.documentElement.style.background = '#313a42'; + ui.trigger('func', () => { + this.readAll(); + }, 'check'); + Progress.start(); this.refs.ui.refs.notifications.on('fetched', () => { 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> </mk-notifications-page> diff --git a/src/web/app/mobile/tags/ui-header.tag b/src/web/app/mobile/tags/ui-header.tag deleted file mode 100644 index 10b44b2153..0000000000 --- a/src/web/app/mobile/tags/ui-header.tag +++ /dev/null @@ -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> diff --git a/src/web/app/mobile/tags/ui-nav.tag b/src/web/app/mobile/tags/ui-nav.tag deleted file mode 100644 index 34235ba4f1..0000000000 --- a/src/web/app/mobile/tags/ui-nav.tag +++ /dev/null @@ -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> diff --git a/src/web/app/mobile/tags/ui.tag b/src/web/app/mobile/tags/ui.tag index 9d9cd4d74a..fb8cbcdbd2 100644 --- a/src/web/app/mobile/tags/ui.tag +++ b/src/web/app/mobile/tags/ui.tag @@ -30,9 +30,377 @@ }; this.onStreamNotification = notification => { + // TODO: ユーザーが画面を見てないと思われるとき(ブラウザやタブがアクティブじゃないなど)は送信しない + this.stream.send({ + type: 'read_notification', + id: notification.id + }); + riot.mount(document.body.appendChild(document.createElement('mk-notify')), { notification: notification }); }; </script> </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> |