summaryrefslogtreecommitdiff
path: root/src/services/note
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2018-09-19 14:18:34 +0900
committersyuilo <syuilotan@yahoo.co.jp>2018-09-19 14:18:34 +0900
commitd9f0e158a35eec183da77e84a3b038fab645bf62 (patch)
treea7cbad45883ff56d35771d849f95dbd911e3e45c /src/services/note
parent8.55.0 (diff)
downloadsharkey-d9f0e158a35eec183da77e84a3b038fab645bf62.tar.gz
sharkey-d9f0e158a35eec183da77e84a3b038fab645bf62.tar.bz2
sharkey-d9f0e158a35eec183da77e84a3b038fab645bf62.zip
Implement #2736
Diffstat (limited to 'src/services/note')
-rw-r--r--src/services/note/create.ts22
-rw-r--r--src/services/note/read.ts62
-rw-r--r--src/services/note/unread.ts47
3 files changed, 121 insertions, 10 deletions
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);
+}