summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2017-10-30 22:12:10 +0900
committersyuilo <syuilotan@yahoo.co.jp>2017-10-30 22:12:10 +0900
commitcaa47cb38cfc3950539c78ca2e70f2c50e815d2c (patch)
treefc1a70e1c1b105ecf8d74ff4d952eff86ded83f6 /src
parenti18n (diff)
downloadsharkey-caa47cb38cfc3950539c78ca2e70f2c50e815d2c.tar.gz
sharkey-caa47cb38cfc3950539c78ca2e70f2c50e815d2c.tar.bz2
sharkey-caa47cb38cfc3950539c78ca2e70f2c50e815d2c.zip
未読の通知がある場合アイコンを表示するように
Diffstat (limited to 'src')
-rw-r--r--src/api/common/read-notification.ts52
-rw-r--r--src/api/endpoints.ts8
-rw-r--r--src/api/endpoints/i/notifications.ts14
-rw-r--r--src/api/endpoints/notifications/get_unread_count.ts23
-rw-r--r--src/api/endpoints/notifications/mark_as_read.ts47
-rw-r--r--src/api/endpoints/notifications/mark_as_read_all.ts32
-rw-r--r--src/api/models/notification.ts5
-rw-r--r--src/api/stream/home.ts6
-rw-r--r--src/web/app/desktop/tags/notifications.tag6
-rw-r--r--src/web/app/mobile/tags/index.js2
-rw-r--r--src/web/app/mobile/tags/notifications.tag6
-rw-r--r--src/web/app/mobile/tags/page/notifications.tag14
-rw-r--r--src/web/app/mobile/tags/ui-header.tag156
-rw-r--r--src/web/app/mobile/tags/ui-nav.tag170
-rw-r--r--src/web/app/mobile/tags/ui.tag368
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>