parent
5174e16f7b
commit
21f8dbf2de
7 changed files with 104 additions and 56 deletions
|
@ -3,9 +3,9 @@
|
|||
<mk-avatar class="avatar" :user="message.user" target="_blank"/>
|
||||
<div class="content">
|
||||
<div class="balloon" :data-no-text="message.text == null">
|
||||
<!-- <button class="delete-button" v-if="isMe" :title="$t('@.delete')">
|
||||
<img src="/assets/desktop/messaging/delete.png" alt="Delete"/>
|
||||
</button> -->
|
||||
<button class="delete-button" v-if="isMe" :title="$t('@.delete')" @click="del">
|
||||
<img src="/assets/desktop/remove.png" alt="Delete"/>
|
||||
</button>
|
||||
<div class="content" v-if="!message.isDeleted">
|
||||
<misskey-flavored-markdown class="text" v-if="message.text" ref="text" :text="message.text" :i="$store.state.i"/>
|
||||
<div class="file" v-if="message.file">
|
||||
|
@ -16,7 +16,7 @@
|
|||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content" v-if="message.isDeleted">
|
||||
<div class="content" v-else>
|
||||
<p class="is-deleted">{{ $t('deleted') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -58,6 +58,13 @@ export default Vue.extend({
|
|||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
del() {
|
||||
this.$root.api('messaging/messages/delete', {
|
||||
messageId: this.message.id
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -79,6 +79,7 @@ export default Vue.extend({
|
|||
|
||||
this.connection.on('message', this.onMessage);
|
||||
this.connection.on('read', this.onRead);
|
||||
this.connection.on('deleted', this.onDeleted);
|
||||
|
||||
if (this.isNaked) {
|
||||
window.addEventListener('scroll', this.onScroll, { passive: true });
|
||||
|
@ -204,6 +205,13 @@ export default Vue.extend({
|
|||
}
|
||||
},
|
||||
|
||||
onDeleted(id) {
|
||||
const msg = this.messages.find(m => m.id === id);
|
||||
if (msg) {
|
||||
this.messages = this.messages.filter(m => m.id !== msg.id);
|
||||
}
|
||||
},
|
||||
|
||||
isBottom() {
|
||||
const asobi = 64;
|
||||
const current = this.isNaked
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
import * as mongo from 'mongodb';
|
||||
import db from '../db/mongodb';
|
||||
|
||||
const MessagingHistory = db.get<IMessagingHistory>('messagingHistories');
|
||||
export default MessagingHistory;
|
||||
|
||||
export type IMessagingHistory = {
|
||||
_id: mongo.ObjectID;
|
||||
updatedAt: Date;
|
||||
userId: mongo.ObjectID;
|
||||
partnerId: mongo.ObjectID;
|
||||
messageId: mongo.ObjectID;
|
||||
};
|
|
@ -7,6 +7,8 @@ import isObjectId from '../misc/is-objectid';
|
|||
import { length } from 'stringz';
|
||||
|
||||
const MessagingMessage = db.get<IMessagingMessage>('messagingMessages');
|
||||
MessagingMessage.createIndex('userId');
|
||||
MessagingMessage.createIndex('recipientId');
|
||||
export default MessagingMessage;
|
||||
|
||||
export interface IMessagingMessage {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import $ from 'cafy';
|
||||
import History from '../../../../models/messaging-history';
|
||||
import Mute from '../../../../models/mute';
|
||||
import { pack } from '../../../../models/messaging-message';
|
||||
import Message, { pack, IMessagingMessage } from '../../../../models/messaging-message';
|
||||
import define from '../../define';
|
||||
|
||||
export const meta = {
|
||||
|
@ -28,19 +27,36 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
|
|||
deletedAt: { $exists: false }
|
||||
});
|
||||
|
||||
// Get history
|
||||
const history = await History
|
||||
.find({
|
||||
userId: user._id,
|
||||
partnerId: {
|
||||
$nin: mute.map(m => m.muteeId)
|
||||
}
|
||||
const history: IMessagingMessage[] = [];
|
||||
|
||||
for (let i = 0; i < ps.limit; i++) {
|
||||
const found = history.map(m => m.userId.equals(user._id) ? m.recipientId : m.userId);
|
||||
|
||||
const message = await Message.findOne({
|
||||
$or: [{
|
||||
userId: user._id
|
||||
}, {
|
||||
recipientId: user._id
|
||||
}],
|
||||
$and: [{
|
||||
userId: { $nin: found },
|
||||
recipientId: { $nin: found }
|
||||
}, {
|
||||
userId: { $nin: mute.map(m => m.muteeId) },
|
||||
recipientId: { $nin: mute.map(m => m.muteeId) }
|
||||
}]
|
||||
}, {
|
||||
limit: ps.limit,
|
||||
sort: {
|
||||
updatedAt: -1
|
||||
createdAt: -1
|
||||
}
|
||||
});
|
||||
|
||||
res(await Promise.all(history.map(h => pack(h.messageId, user))));
|
||||
if (message) {
|
||||
history.push(message);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
res(await Promise.all(history.map(h => pack(h._id, user))));
|
||||
}));
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import Message from '../../../../../models/messaging-message';
|
||||
import { isValidText } from '../../../../../models/messaging-message';
|
||||
import History from '../../../../../models/messaging-history';
|
||||
import User from '../../../../../models/user';
|
||||
import Mute from '../../../../../models/mute';
|
||||
import DriveFile from '../../../../../models/drive-file';
|
||||
|
@ -114,6 +113,7 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
|
|||
// 2秒経っても(今回作成した)メッセージが既読にならなかったら「未読のメッセージがありますよ」イベントを発行する
|
||||
setTimeout(async () => {
|
||||
const freshMessage = await Message.findOne({ _id: message._id }, { isRead: true });
|
||||
if (freshMessage == null) return; // メッセージが削除されている場合もある
|
||||
if (!freshMessage.isRead) {
|
||||
//#region ただしミュートされているなら発行しない
|
||||
const mute = await Mute.find({
|
||||
|
@ -130,30 +130,4 @@ export default define(meta, (ps, user) => new Promise(async (res, rej) => {
|
|||
pushSw(message.recipientId, 'unreadMessagingMessage', messageObj);
|
||||
}
|
||||
}, 2000);
|
||||
|
||||
// 履歴作成(自分)
|
||||
History.update({
|
||||
userId: user._id,
|
||||
partnerId: recipient._id
|
||||
}, {
|
||||
updatedAt: new Date(),
|
||||
userId: user._id,
|
||||
partnerId: recipient._id,
|
||||
messageId: message._id
|
||||
}, {
|
||||
upsert: true
|
||||
});
|
||||
|
||||
// 履歴作成(相手)
|
||||
History.update({
|
||||
userId: recipient._id,
|
||||
partnerId: user._id
|
||||
}, {
|
||||
updatedAt: new Date(),
|
||||
userId: recipient._id,
|
||||
partnerId: user._id,
|
||||
messageId: message._id
|
||||
}, {
|
||||
upsert: true
|
||||
});
|
||||
}));
|
||||
|
|
54
src/server/api/endpoints/messaging/messages/delete.ts
Normal file
54
src/server/api/endpoints/messaging/messages/delete.ts
Normal file
|
@ -0,0 +1,54 @@
|
|||
|
||||
import $ from 'cafy'; import ID, { transform } from '../../../../../misc/cafy-id';
|
||||
import Message from '../../../../../models/messaging-message';
|
||||
import define from '../../../define';
|
||||
import { publishMessagingStream } from '../../../../../stream';
|
||||
const ms = require('ms');
|
||||
|
||||
export const meta = {
|
||||
stability: 'stable',
|
||||
|
||||
desc: {
|
||||
'ja-JP': '指定したメッセージを削除します。',
|
||||
'en-US': 'Delete a message.'
|
||||
},
|
||||
|
||||
requireCredential: true,
|
||||
|
||||
kind: 'messaging-write',
|
||||
|
||||
limit: {
|
||||
duration: ms('1hour'),
|
||||
max: 300,
|
||||
minInterval: ms('1sec')
|
||||
},
|
||||
|
||||
params: {
|
||||
messageId: {
|
||||
validator: $.type(ID),
|
||||
transform: transform,
|
||||
desc: {
|
||||
'ja-JP': '対象のメッセージのID',
|
||||
'en-US': 'Target message ID.'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default define(meta, (ps, user) => new Promise(async (res, rej) => {
|
||||
const message = await Message.findOne({
|
||||
_id: ps.messageId,
|
||||
userId: user._id
|
||||
});
|
||||
|
||||
if (message === null) {
|
||||
return rej('message not found');
|
||||
}
|
||||
|
||||
await Message.remove({ _id: message._id });
|
||||
|
||||
publishMessagingStream(message.userId, message.recipientId, 'deleted', message._id);
|
||||
publishMessagingStream(message.recipientId, message.userId, 'deleted', message._id);
|
||||
|
||||
res();
|
||||
}));
|
Loading…
Reference in a new issue