diff --git a/src/client/app/common/scripts/streaming/home.ts b/src/client/app/common/scripts/streaming/home.ts
index dd18c70d70..26729507fb 100644
--- a/src/client/app/common/scripts/streaming/home.ts
+++ b/src/client/app/common/scripts/streaming/home.ts
@@ -50,6 +50,30 @@ export class HomeStream extends Stream {
 			});
 		});
 
+		this.on('unreadMention', () => {
+			os.store.dispatch('mergeMe', {
+				hasUnreadMentions: true
+			});
+		});
+
+		this.on('readAllUnreadMentions', () => {
+			os.store.dispatch('mergeMe', {
+				hasUnreadMentions: false
+			});
+		});
+
+		this.on('unreadSpecifiedNote', () => {
+			os.store.dispatch('mergeMe', {
+				hasUnreadSpecifiedNotes: true
+			});
+		});
+
+		this.on('readAllUnreadSpecifiedNotes', () => {
+			os.store.dispatch('mergeMe', {
+				hasUnreadSpecifiedNotes: false
+			});
+		});
+
 		this.on('clientSettingUpdated', x => {
 			os.store.commit('settings/set', {
 				key: x.key,
diff --git a/src/client/app/desktop/views/components/notes.note.vue b/src/client/app/desktop/views/components/notes.note.vue
index fdf41a52c9..ac2c1ce97f 100644
--- a/src/client/app/desktop/views/components/notes.note.vue
+++ b/src/client/app/desktop/views/components/notes.note.vue
@@ -213,10 +213,14 @@ export default Vue.extend({
 	methods: {
 		capture(withHandler = false) {
 			if (this.$store.getters.isSignedIn) {
-				this.connection.send({
+				const data = {
 					type: 'capture',
 					id: this.p.id
-				});
+				} as any;
+				if ((this.p.visibleUserIds || []).includes(this.$store.state.i.id) || (this.p.mentions || []).includes(this.$store.state.i.id)) {
+					data.read = true;
+				}
+				this.connection.send(data);
 				if (withHandler) this.connection.on('note-updated', this.onStreamNoteUpdated);
 			}
 		},
diff --git a/src/client/app/desktop/views/components/timeline.vue b/src/client/app/desktop/views/components/timeline.vue
index 9f421a68ed..7d683236bb 100644
--- a/src/client/app/desktop/views/components/timeline.vue
+++ b/src/client/app/desktop/views/components/timeline.vue
@@ -8,8 +8,8 @@
 		<span :data-active="src == 'tag'" @click="src = 'tag'" v-if="tagTl">%fa:hashtag% {{ tagTl.title }}</span>
 		<span :data-active="src == 'list'" @click="src = 'list'" v-if="list">%fa:list% {{ list.title }}</span>
 		<div class="buttons">
-			<button :data-active="src == 'mentions'" @click="src = 'mentions'" title="%i18n:@mentions%">%fa:at%</button>
-			<button :data-active="src == 'messages'" @click="src = 'messages'" title="%i18n:@messages%">%fa:envelope R%</button>
+			<button :data-active="src == 'mentions'" @click="src = 'mentions'" title="%i18n:@mentions%">%fa:at%<i class="badge" v-if="$store.state.i.hasUnreadMentions">%fa:circle%</i></button>
+			<button :data-active="src == 'messages'" @click="src = 'messages'" title="%i18n:@messages%">%fa:envelope R%<i class="badge" v-if="$store.state.i.hasUnreadSpecifiedNotes">%fa:circle%</i></button>
 			<button @click="chooseTag" title="%i18n:@hashtag%" ref="tagButton">%fa:hashtag%</button>
 			<button @click="chooseList" title="%i18n:@list%" ref="listButton">%fa:list%</button>
 		</div>
@@ -202,6 +202,13 @@ root(isDark)
 				line-height 42px
 				color isDark ? #9baec8 : #ccc
 
+				> .badge
+					position absolute
+					top -4px
+					right 4px
+					font-size 10px
+					color $theme-color
+
 				&:hover
 					color isDark ? #b2c1d5 : #aaa
 
diff --git a/src/client/app/desktop/views/pages/deck/deck.note.vue b/src/client/app/desktop/views/pages/deck/deck.note.vue
index 980fb03136..99274b0f41 100644
--- a/src/client/app/desktop/views/pages/deck/deck.note.vue
+++ b/src/client/app/desktop/views/pages/deck/deck.note.vue
@@ -147,10 +147,14 @@ export default Vue.extend({
 	methods: {
 		capture(withHandler = false) {
 			if (this.$store.getters.isSignedIn) {
-				this.connection.send({
+				const data = {
 					type: 'capture',
 					id: this.p.id
-				});
+				} as any;
+				if ((this.p.visibleUserIds || []).includes(this.$store.state.i.id) || (this.p.mentions || []).includes(this.$store.state.i.id)) {
+					data.read = true;
+				}
+				this.connection.send(data);
 				if (withHandler) this.connection.on('note-updated', this.onStreamNoteUpdated);
 			}
 		},
diff --git a/src/client/app/mobile/views/components/note.vue b/src/client/app/mobile/views/components/note.vue
index 8787b39a93..0ce72cab11 100644
--- a/src/client/app/mobile/views/components/note.vue
+++ b/src/client/app/mobile/views/components/note.vue
@@ -160,10 +160,14 @@ export default Vue.extend({
 	methods: {
 		capture(withHandler = false) {
 			if (this.$store.getters.isSignedIn) {
-				this.connection.send({
+				const data = {
 					type: 'capture',
 					id: this.p.id
-				});
+				} as any;
+				if ((this.p.visibleUserIds || []).includes(this.$store.state.i.id) || (this.p.mentions || []).includes(this.$store.state.i.id)) {
+					data.read = true;
+				}
+				this.connection.send(data);
 				if (withHandler) this.connection.on('note-updated', this.onStreamNoteUpdated);
 			}
 		},
diff --git a/src/client/app/mobile/views/components/ui.header.vue b/src/client/app/mobile/views/components/ui.header.vue
index c9b3ab51ae..15c8299c2e 100644
--- a/src/client/app/mobile/views/components/ui.header.vue
+++ b/src/client/app/mobile/views/components/ui.header.vue
@@ -188,9 +188,6 @@ root(isDark)
 				overflow hidden
 				text-overflow ellipsis
 
-				[data-fa], [data-icon]
-					margin-right 4px
-
 				> img
 					display inline-block
 					vertical-align bottom
diff --git a/src/client/app/mobile/views/pages/drive.vue b/src/client/app/mobile/views/pages/drive.vue
index 27ac956043..c0fc7b48dc 100644
--- a/src/client/app/mobile/views/pages/drive.vue
+++ b/src/client/app/mobile/views/pages/drive.vue
@@ -1,9 +1,9 @@
 <template>
 <mk-ui>
 	<span slot="header">
-		<template v-if="folder">%fa:R folder-open%{{ folder.name }}</template>
-		<template v-if="file"><mk-file-type-icon data-icon :type="file.type"/>{{ file.name }}</template>
-		<template v-if="!folder && !file">%fa:cloud%%i18n:@drive%</template>
+		<template v-if="folder"><span style="margin-right:4px;">%fa:R folder-open%</span>{{ folder.name }}</template>
+		<template v-if="file"><mk-file-type-icon data-icon :type="file.type" style="margin-right:4px;"/>{{ file.name }}</template>
+		<template v-if="!folder && !file"><span style="margin-right:4px;">%fa:cloud%</span>%i18n:@drive%</template>
 	</span>
 	<template slot="func"><button @click="fn">%fa:ellipsis-h%</button></template>
 	<mk-drive
diff --git a/src/client/app/mobile/views/pages/favorites.vue b/src/client/app/mobile/views/pages/favorites.vue
index 6b9aec6a0c..53512e804c 100644
--- a/src/client/app/mobile/views/pages/favorites.vue
+++ b/src/client/app/mobile/views/pages/favorites.vue
@@ -1,6 +1,6 @@
 <template>
 <mk-ui>
-	<span slot="header">%fa:star%%i18n:@title%</span>
+	<span slot="header"><span style="margin-right:4px;">%fa:star%</span>%i18n:@title%</span>
 
 	<main>
 		<template v-for="favorite in favorites">
diff --git a/src/client/app/mobile/views/pages/games/reversi.vue b/src/client/app/mobile/views/pages/games/reversi.vue
index bdadc88a43..f3bba586de 100644
--- a/src/client/app/mobile/views/pages/games/reversi.vue
+++ b/src/client/app/mobile/views/pages/games/reversi.vue
@@ -1,6 +1,6 @@
 <template>
 <mk-ui>
-	<span slot="header">%fa:gamepad%%i18n:@reversi%</span>
+	<span slot="header"><span style="margin-right:4px;">%fa:gamepad%</span>%i18n:@reversi%</span>
 	<mk-reversi :game-id="$route.params.game" @nav="nav" :self-nav="false"/>
 </mk-ui>
 </template>
diff --git a/src/client/app/mobile/views/pages/home.vue b/src/client/app/mobile/views/pages/home.vue
index 43afc98b45..ca62d4e2f8 100644
--- a/src/client/app/mobile/views/pages/home.vue
+++ b/src/client/app/mobile/views/pages/home.vue
@@ -1,7 +1,7 @@
 <template>
 <mk-ui>
 	<span slot="header" @click="showNav = true">
-		<span>
+		<span :class="$style.title">
 			<span v-if="src == 'home'">%fa:home%%i18n:@home%</span>
 			<span v-if="src == 'local'">%fa:R comments%%i18n:@local%</span>
 			<span v-if="src == 'hybrid'">%fa:share-alt%%i18n:@hybrid%</span>
@@ -15,6 +15,7 @@
 			<template v-if="!showNav">%fa:angle-down%</template>
 			<template v-else>%fa:angle-up%</template>
 		</span>
+		<i :class="$style.badge" v-if="$store.state.i.hasUnreadMentions || $store.state.i.hasUnreadSpecifiedNotes">%fa:circle%</i>
 	</span>
 
 	<template slot="func">
@@ -32,8 +33,8 @@
 					<span :data-active="src == 'hybrid'" @click="src = 'hybrid'" v-if="enableLocalTimeline">%fa:share-alt% %i18n:@hybrid%</span>
 					<span :data-active="src == 'global'" @click="src = 'global'">%fa:globe% %i18n:@global%</span>
 					<div class="hr"></div>
-					<span :data-active="src == 'mentions'" @click="src = 'mentions'">%fa:at% %i18n:@mentions%</span>
-					<span :data-active="src == 'messages'" @click="src = 'messages'">%fa:envelope R% %i18n:@messages%</span>
+					<span :data-active="src == 'mentions'" @click="src = 'mentions'">%fa:at% %i18n:@mentions%<i class="badge" v-if="$store.state.i.hasUnreadMentions">%fa:circle%</i></span>
+					<span :data-active="src == 'messages'" @click="src = 'messages'">%fa:envelope R% %i18n:@messages%<i class="badge" v-if="$store.state.i.hasUnreadSpecifiedNotes">%fa:circle%</i></span>
 					<template v-if="lists">
 						<div class="hr" v-if="lists.length > 0"></div>
 						<span v-for="l in lists" :data-active="src == 'list' && list == l" @click="src = 'list'; list = l" :key="l.id">%fa:list% {{ l.title }}</span>
@@ -220,6 +221,11 @@ root(isDark)
 					&:not([data-active]):hover
 						background isDark ? #353e4a : #eee
 
+					> .badge
+						margin-left 6px
+						font-size 10px
+						color $theme-color
+
 	> .tl
 		max-width 680px
 		margin 0 auto
@@ -238,3 +244,18 @@ main:not([data-darkmode])
 	root(false)
 
 </style>
+
+<style lang="stylus" module>
+@import '~const.styl'
+
+.title
+	i
+		margin-right 4px
+
+.badge
+	margin-left 6px
+	font-size 10px
+	color $theme-color
+	vertical-align middle
+
+</style>
diff --git a/src/client/app/mobile/views/pages/messaging-room.vue b/src/client/app/mobile/views/pages/messaging-room.vue
index 401397d856..750ba26294 100644
--- a/src/client/app/mobile/views/pages/messaging-room.vue
+++ b/src/client/app/mobile/views/pages/messaging-room.vue
@@ -1,7 +1,7 @@
 <template>
 <mk-ui>
 	<span slot="header">
-		<template v-if="user">%fa:R comments%{{ user | userName }}</template>
+		<template v-if="user"><span style="margin-right:4px;">%fa:R comments%</span>{{ user | userName }}</template>
 		<template v-else><mk-ellipsis/></template>
 	</span>
 	<mk-messaging-room v-if="!fetching" :user="user" :is-naked="true"/>
diff --git a/src/client/app/mobile/views/pages/messaging.vue b/src/client/app/mobile/views/pages/messaging.vue
index 3883505281..98ae79fe6c 100644
--- a/src/client/app/mobile/views/pages/messaging.vue
+++ b/src/client/app/mobile/views/pages/messaging.vue
@@ -1,6 +1,6 @@
 <template>
 <mk-ui>
-	<span slot="header">%fa:R comments%%i18n:@messaging%</span>
+	<span slot="header"><span style="margin-right:4px;">%fa:R comments%</span>%i18n:@messaging%</span>
 	<mk-messaging @navigate="navigate" :header-top="48"/>
 </mk-ui>
 </template>
diff --git a/src/client/app/mobile/views/pages/note.vue b/src/client/app/mobile/views/pages/note.vue
index fee60b350e..d7307c79a8 100644
--- a/src/client/app/mobile/views/pages/note.vue
+++ b/src/client/app/mobile/views/pages/note.vue
@@ -1,6 +1,6 @@
 <template>
 <mk-ui>
-	<span slot="header">%fa:R sticky-note%%i18n:@title%</span>
+	<span slot="header"><span style="margin-right:4px;">%fa:R sticky-note%</span>%i18n:@title%</span>
 	<main v-if="!fetching">
 		<div>
 			<mk-note-detail :note="note"/>
diff --git a/src/client/app/mobile/views/pages/notifications.vue b/src/client/app/mobile/views/pages/notifications.vue
index 4d3c8ee534..bddcd457bb 100644
--- a/src/client/app/mobile/views/pages/notifications.vue
+++ b/src/client/app/mobile/views/pages/notifications.vue
@@ -1,6 +1,6 @@
 <template>
 <mk-ui>
-	<span slot="header">%fa:R bell%%i18n:@notifications%</span>
+	<span slot="header"><span style="margin-right:4px;">%fa:R bell%</span>%i18n:@notifications%</span>
 	<template slot="func"><button @click="fn">%fa:check%</button></template>
 
 	<main>
diff --git a/src/client/app/mobile/views/pages/settings.vue b/src/client/app/mobile/views/pages/settings.vue
index f315c058df..9e90416370 100644
--- a/src/client/app/mobile/views/pages/settings.vue
+++ b/src/client/app/mobile/views/pages/settings.vue
@@ -1,6 +1,6 @@
 <template>
 <mk-ui>
-	<span slot="header">%fa:cog%%i18n:@settings%</span>
+	<span slot="header"><span style="margin-right:4px;">%fa:cog%</span>%i18n:@settings%</span>
 	<main :data-darkmode="$store.state.device.darkmode">
 		<div class="signin-as" v-html="'%i18n:@signed-in-as%'.replace('{}', `<b>${name}</b>`)"></div>
 
diff --git a/src/client/app/mobile/views/pages/tag.vue b/src/client/app/mobile/views/pages/tag.vue
index a545e2b839..3f963501e0 100644
--- a/src/client/app/mobile/views/pages/tag.vue
+++ b/src/client/app/mobile/views/pages/tag.vue
@@ -1,6 +1,6 @@
 <template>
 <mk-ui>
-	<span slot="header">%fa:hashtag%{{ $route.params.tag }}</span>
+	<span slot="header"><span style="margin-right:4px;">%fa:hashtag%</span>{{ $route.params.tag }}</span>
 
 	<main>
 		<p v-if="!fetching && empty">%fa:search% {{ '%i18n:no-posts-found%'.split('{}')[0] }}{{ q }}{{ '%i18n:no-posts-found%'.split('{}')[1] }}</p>
diff --git a/src/client/app/mobile/views/pages/widgets.vue b/src/client/app/mobile/views/pages/widgets.vue
index a83103632e..c649529c0e 100644
--- a/src/client/app/mobile/views/pages/widgets.vue
+++ b/src/client/app/mobile/views/pages/widgets.vue
@@ -1,6 +1,6 @@
 <template>
 <mk-ui>
-	<span slot="header">%fa:home%%i18n:@dashboard%</span>
+	<span slot="header"><span style="margin-right:4px;">%fa:home%</span>%i18n:@dashboard%</span>
 	<template slot="func">
 		<button @click="customizing = !customizing">%fa:cog%</button>
 	</template>
diff --git a/src/models/note-unread.ts b/src/models/note-unread.ts
new file mode 100644
index 0000000000..62408d23b6
--- /dev/null
+++ b/src/models/note-unread.ts
@@ -0,0 +1,17 @@
+import * as mongo from 'mongodb';
+import db from '../db/mongodb';
+
+const NoteUnread = db.get<INoteUnread>('noteUnreads');
+NoteUnread.createIndex(['userId', 'noteId'], { unique: true });
+export default NoteUnread;
+
+export interface INoteUnread {
+	_id: mongo.ObjectID;
+	noteId: mongo.ObjectID;
+	userId: mongo.ObjectID;
+	isSpecified: boolean;
+
+	_note: {
+		userId: mongo.ObjectID;
+	};
+}
diff --git a/src/models/note.ts b/src/models/note.ts
index ce307d061a..ba88e9f481 100644
--- a/src/models/note.ts
+++ b/src/models/note.ts
@@ -295,8 +295,8 @@ export const pack = async (
 
 	delete _note._user;
 	delete _note._reply;
-	delete _note.repost;
-	delete _note.mentions;
+	delete _note._renote;
+	delete _note._files;
 	if (_note.geo) delete _note.geo.type;
 
 	// Populate user
diff --git a/src/models/user.ts b/src/models/user.ts
index b595fa8d71..bacae485a8 100644
--- a/src/models/user.ts
+++ b/src/models/user.ts
@@ -348,7 +348,8 @@ export const pack = (
 	me?: string | mongo.ObjectID | IUser,
 	options?: {
 		detail?: boolean,
-		includeSecrets?: boolean
+		includeSecrets?: boolean,
+		includeHasUnreadNotes?: boolean
 	}
 ) => new Promise<any>(async (resolve, reject) => {
 
@@ -510,6 +511,11 @@ export const pack = (
 		}
 	}
 
+	if (!opts.includeHasUnreadNotes) {
+		delete _user.hasUnreadSpecifiedNotes;
+		delete _user.hasUnreadMentions;
+	}
+
 	// resolve promises in _user object
 	_user = await rap(_user);
 
diff --git a/src/server/api/endpoints/i.ts b/src/server/api/endpoints/i.ts
index 1f99ef2d8d..5aa2070650 100644
--- a/src/server/api/endpoints/i.ts
+++ b/src/server/api/endpoints/i.ts
@@ -22,6 +22,7 @@ export default (params: any, user: ILocalUser, app: IApp) => new Promise(async (
 	// Serialize
 	res(await pack(user, user, {
 		detail: true,
+		includeHasUnreadNotes: true,
 		includeSecrets: isSecure
 	}));
 
diff --git a/src/server/api/stream/home.ts b/src/server/api/stream/home.ts
index f1fced42d7..5575d0d523 100644
--- a/src/server/api/stream/home.ts
+++ b/src/server/api/stream/home.ts
@@ -9,6 +9,7 @@ import readNotification from '../common/read-notification';
 import call from '../call';
 import { IApp } from '../../../models/app';
 import shouldMuteThisNote from '../../../misc/should-mute-this-note';
+import readNote from '../../../services/note/read';
 
 const log = debug('misskey');
 
@@ -94,6 +95,9 @@ export default async function(
 				if (!msg.id) return;
 				log(`CAPTURE: ${msg.id} by @${user.username}`);
 				subscriber.on(`note-stream:${msg.id}`, onNoteStream);
+				if (msg.read) {
+					readNote(user._id, msg.id);
+				}
 				break;
 
 			case 'decapture':
diff --git a/src/services/note/create.ts b/src/services/note/create.ts
index 7c1e71dcb3..b62b8c43ba 100644
--- a/src/services/note/create.ts
+++ b/src/services/note/create.ts
@@ -25,6 +25,7 @@ import { TextElementMention } from '../../mfm/parse/elements/mention';
 import { TextElementHashtag } from '../../mfm/parse/elements/hashtag';
 import { updateNoteStats } from '../update-chart';
 import { erase, unique } from '../../prelude/array';
+import insertNoteUnread from './unread';
 
 type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';
 
@@ -170,6 +171,17 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
 	// Increment notes count (user)
 	incNotesCountOfUser(user);
 
+	// 未読通知を作成
+	if (data.visibility == 'specified') {
+		data.visibleUsers.forEach(u => {
+			insertNoteUnread(u, note, true);
+		});
+	} else {
+		mentionedUsers.forEach(u => {
+			insertNoteUnread(u, note, false);
+		});
+	}
+
 	if (data.reply) {
 		saveReply(data.reply, note);
 	}
@@ -314,16 +326,6 @@ async function publish(user: IUser, note: INote, noteObj: any, reply: INote, ren
 		publishGlobalTimelineStream(noteObj);
 	}
 
-	if (note.visibility == 'specified') {
-		visibleUsers.forEach(async (u) => {
-			const n = await pack(note, u, {
-				detail: true
-			});
-			publishUserStream(u._id, 'note', n);
-			publishHybridTimelineStream(u._id, n);
-		});
-	}
-
 	if (['public', 'home', 'followers'].includes(note.visibility)) {
 		// フォロワーに配信
 		publishToFollowers(note, user, noteActivity);
diff --git a/src/services/note/read.ts b/src/services/note/read.ts
new file mode 100644
index 0000000000..46918bc38c
--- /dev/null
+++ b/src/services/note/read.ts
@@ -0,0 +1,62 @@
+import * as mongo from 'mongodb';
+import { publishUserStream } from '../../stream';
+import User from '../../models/user';
+import NoteUnread from '../../models/note-unread';
+
+/**
+ * Mark a note as read
+ */
+export default (
+	user: string | mongo.ObjectID,
+	note: string | mongo.ObjectID
+) => new Promise<any>(async (resolve, reject) => {
+
+	const userId: mongo.ObjectID = mongo.ObjectID.prototype.isPrototypeOf(user)
+		? user as mongo.ObjectID
+		: new mongo.ObjectID(user);
+
+	const noteId: mongo.ObjectID = mongo.ObjectID.prototype.isPrototypeOf(note)
+		? note as mongo.ObjectID
+		: new mongo.ObjectID(note);
+
+	// Remove document
+	await NoteUnread.remove({
+		userId: userId,
+		noteId: noteId
+	});
+
+	const count1 = await NoteUnread
+		.count({
+			userId: userId,
+			isSpecified: false
+		}, {
+			limit: 1
+		});
+
+	const count2 = await NoteUnread
+		.count({
+			userId: userId,
+			isSpecified: true
+		}, {
+			limit: 1
+		});
+
+	if (count1 == 0 || count2 == 0) {
+		User.update({ _id: userId }, {
+			$set: {
+				hasUnreadMentions: count1 != 0 || count2 != 0,
+				hasUnreadSpecifiedNotes: count2 != 0
+			}
+		});
+	}
+
+	if (count1 == 0) {
+		// 全て既読になったイベントを発行
+		publishUserStream(userId, 'readAllUnreadMentions');
+	}
+
+	if (count2 == 0) {
+		// 全て既読になったイベントを発行
+		publishUserStream(userId, 'readAllUnreadSpecifiedNotes');
+	}
+});
diff --git a/src/services/note/unread.ts b/src/services/note/unread.ts
new file mode 100644
index 0000000000..6e10c8b248
--- /dev/null
+++ b/src/services/note/unread.ts
@@ -0,0 +1,47 @@
+import NoteUnread from '../../models/note-unread';
+import User, { IUser } from '../../models/user';
+import { INote } from '../../models/note';
+import Mute from '../../models/mute';
+import { publishUserStream } from '../../stream';
+
+export default async function(user: IUser, note: INote, isSpecified = false) {
+	const unread = await NoteUnread.insert({
+		noteId: note._id,
+		userId: user._id,
+		isSpecified,
+		_note: {
+			userId: note.userId
+		}
+	});
+
+	// 3秒経っても既読にならなかったら「未読の投稿がありますよ」イベントを発行する
+	setTimeout(async () => {
+		const exist = await NoteUnread.findOne({ _id: unread._id });
+		if (exist == null) return;
+
+		//#region ただしミュートされているなら発行しない
+		const mute = await Mute.find({
+			muterId: user._id
+		});
+		const mutedUserIds = mute.map(m => m.muteeId.toString());
+		if (mutedUserIds.includes(note.userId.toString())) return;
+		//#endregion
+
+		User.update({
+			_id: user._id
+		}, {
+			$set: isSpecified ? {
+				hasUnreadSpecifiedNotes: true,
+				hasUnreadMentions: true
+			} : {
+				hasUnreadMentions: true
+			}
+		});
+
+		publishUserStream(user._id, 'unreadMention', note._id);
+
+		if (isSpecified) {
+			publishUserStream(user._id, 'unreadSpecifiedNote', note._id);
+		}
+	}, 3000);
+}