diff options
| author | syuilo <syuilotan@yahoo.co.jp> | 2018-09-19 14:18:34 +0900 |
|---|---|---|
| committer | syuilo <syuilotan@yahoo.co.jp> | 2018-09-19 14:18:34 +0900 |
| commit | d9f0e158a35eec183da77e84a3b038fab645bf62 (patch) | |
| tree | a7cbad45883ff56d35771d849f95dbd911e3e45c /src/services/note | |
| parent | 8.55.0 (diff) | |
| download | sharkey-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.ts | 22 | ||||
| -rw-r--r-- | src/services/note/read.ts | 62 | ||||
| -rw-r--r-- | src/services/note/unread.ts | 47 |
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); +} |