+
@@ -442,6 +442,28 @@ SPDX-License-Identifier: AGPL-3.0-only
+
+
+
+
+ {{ i18n.ts._settings._chat.sendOnEnter }}
+
+
+
+
{{ i18n.ts._settings.ifOn }}:
+
{{ i18n.ts._chat.send }}: Enter
+
{{ i18n.ts._chat.newline }}: Shift + Enter
+
+
+
{{ i18n.ts._settings.ifOff }}:
+
{{ i18n.ts._chat.send }}: Ctrl + Enter
+
{{ i18n.ts._chat.newline }}: Enter
+
+
+
+
+
+
@@ -627,6 +649,7 @@ const useBlurEffectForModal = prefer.model('useBlurEffectForModal');
const useBlurEffect = prefer.model('useBlurEffect');
const defaultFollowWithReplies = prefer.model('defaultFollowWithReplies');
const chatShowSenderName = prefer.model('chat.showSenderName');
+const chatSendOnEnter = prefer.model('chat.sendOnEnter');
watch(lang, () => {
miLocalStorage.setItem('lang', lang.value as string);
@@ -654,6 +677,7 @@ watch([
squareAvatars,
highlightSensitiveMedia,
enableSeasonalScreenEffect,
+ chatShowSenderName,
], async () => {
await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
});
diff --git a/packages/frontend/src/preferences/def.ts b/packages/frontend/src/preferences/def.ts
index 801bb29e8c..b588cc3b5f 100644
--- a/packages/frontend/src/preferences/def.ts
+++ b/packages/frontend/src/preferences/def.ts
@@ -377,6 +377,9 @@ export const PREF_DEF = {
'chat.showSenderName': {
default: false,
},
+ 'chat.sendOnEnter': {
+ default: false,
+ },
'game.dropAndFusion': {
default: {
diff --git a/packages/frontend/src/utility/autogen/settings-search-index.ts b/packages/frontend/src/utility/autogen/settings-search-index.ts
index 1e41dffe22..c939c93425 100644
--- a/packages/frontend/src/utility/autogen/settings-search-index.ts
+++ b/packages/frontend/src/utility/autogen/settings-search-index.ts
@@ -491,55 +491,60 @@ export const searchIndexes: SearchIndexItem[] = [
label: i18n.ts._settings._chat.showSenderName,
keywords: ['show', 'sender', 'name'],
},
+ {
+ id: 'omEy5Q3Ev',
+ label: i18n.ts._settings._chat.sendOnEnter,
+ keywords: ['send', 'enter', 'newline'],
+ },
],
label: i18n.ts.chat,
keywords: ['chat', 'messaging'],
},
{
- id: 'sCscGhMmH',
+ id: '5fy7VEy6i',
children: [
{
- id: 'dLkRNHn3k',
+ id: 'EosiWZvak',
label: i18n.ts.squareAvatars,
keywords: ['avatar', 'icon', 'square'],
},
{
- id: 'BvooTWFW5',
+ id: 'qY5xTzl35',
label: i18n.ts.seasonalScreenEffect,
keywords: ['effect', 'show'],
},
{
- id: 'yzbghkAq0',
+ id: '2VSnj81vC',
label: i18n.ts.openImageInNewTab,
keywords: ['image', 'photo', 'picture', 'media', 'thumbnail', 'new', 'tab'],
},
{
- id: 'aSbKFHbOy',
+ id: 'hdQa7W2H1',
label: i18n.ts.withRepliesByDefaultForNewlyFollowed,
keywords: ['follow', 'replies'],
},
{
- id: '89bn97UgY',
+ id: 'nnj4DkjhP',
label: i18n.ts.whenServerDisconnected,
keywords: ['server', 'disconnect', 'reconnect', 'reload', 'streaming'],
},
{
- id: 'hgf3rgdA6',
+ id: 'Eh7vTluDO',
label: i18n.ts.numberOfPageCache,
keywords: ['cache', 'page'],
},
{
- id: '6FVdHPhhv',
+ id: 'vTRSKf1JA',
label: i18n.ts.forceShowAds,
keywords: ['ad', 'show'],
},
{
- id: '5Bx5DAST1',
+ id: 'dwhQfcLGt',
label: i18n.ts.hemisphere,
keywords: [],
},
{
- id: 'wv7Cwiwb1',
+ id: 'Ar1lj7f7U',
label: i18n.ts.additionalEmojiDictionary,
keywords: ['emoji', 'dictionary', 'additional', 'extra'],
},
From 1736955694336096dd0e6e999c43fefa4c55801b Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Tue, 25 Mar 2025 13:29:03 +0900
Subject: [PATCH 14/30] =?UTF-8?q?fix(backend):=20=E8=87=AA=E5=88=86?=
=?UTF-8?q?=E3=81=8C=E3=82=AA=E3=83=BC=E3=83=8A=E3=83=BC=E3=81=A7=E3=81=AF?=
=?UTF-8?q?=E3=81=AA=E3=81=84=E5=8F=82=E5=8A=A0=E4=B8=AD=E3=81=AE=E3=83=AB?=
=?UTF-8?q?=E3=83=BC=E3=83=A0=E3=81=AB=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC?=
=?UTF-8?q?=E3=82=B8=E3=82=92=E9=80=81=E4=BF=A1=E3=81=99=E3=82=8B=E3=81=A8?=
=?UTF-8?q?=E4=B8=8D=E5=BF=85=E8=A6=81=E3=81=AA=E9=80=9A=E7=9F=A5=E3=81=8C?=
=?UTF-8?q?=E7=99=BA=E7=94=9F=E3=81=99=E3=82=8B=E3=81=AE=E3=82=92=E4=BF=AE?=
=?UTF-8?q?=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
packages/backend/src/core/ChatService.ts | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/packages/backend/src/core/ChatService.ts b/packages/backend/src/core/ChatService.ts
index 57e33af107..3b73a0f6ba 100644
--- a/packages/backend/src/core/ChatService.ts
+++ b/packages/backend/src/core/ChatService.ts
@@ -199,6 +199,8 @@ export class ChatService {
throw new Error('you are not a member of the room');
}
+ const membershipsOtherThanMe = memberships.filter(member => member.userId !== fromUser.id);
+
const message = {
id: this.idService.gen(),
fromUserId: fromUser.id,
@@ -216,7 +218,7 @@ export class ChatService {
this.globalEventService.publishChatRoomStream(toRoom.id, 'message', packedMessage);
const redisPipeline = this.redisClient.pipeline();
- for (const membership of memberships) {
+ for (const membership of membershipsOtherThanMe) {
if (membership.isMuted) continue;
redisPipeline.set(`newRoomChatMessageExists:${membership.userId}:${toRoom.id}`, message.id);
@@ -227,7 +229,7 @@ export class ChatService {
// 3秒経っても既読にならなかったらイベント発行
setTimeout(async () => {
const redisPipeline = this.redisClient.pipeline();
- for (const membership of memberships) {
+ for (const membership of membershipsOtherThanMe) {
redisPipeline.get(`newRoomChatMessageExists:${membership.userId}:${toRoom.id}`);
}
const markers = await redisPipeline.exec();
@@ -237,12 +239,12 @@ export class ChatService {
const packedMessageForTo = await this.chatEntityService.packMessageDetailed(inserted);
- for (let i = 0; i < memberships.length; i++) {
+ for (let i = 0; i < membershipsOtherThanMe.length; i++) {
const marker = markers[i][1];
if (marker == null) continue;
- this.globalEventService.publishMainStream(memberships[i].userId, 'newChatMessage', packedMessageForTo);
- //this.pushNotificationService.pushNotification(memberships[i].userId, 'newChatMessage', packedMessageForTo);
+ this.globalEventService.publishMainStream(membershipsOtherThanMe[i].userId, 'newChatMessage', packedMessageForTo);
+ //this.pushNotificationService.pushNotification(membershipsOtherThanMe[i].userId, 'newChatMessage', packedMessageForTo);
}
}, 3000);
From c51e862b7de460cd7c1b57a63a002156bbfe1b49 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Tue, 25 Mar 2025 13:41:12 +0900
Subject: [PATCH 15/30] =?UTF-8?q?enhance:=20=E9=80=81=E4=BF=A1=E3=81=97?=
=?UTF-8?q?=E3=81=9F=E3=83=81=E3=83=A3=E3=83=83=E3=83=88=E3=83=AB=E3=83=BC?=
=?UTF-8?q?=E3=83=A0=E3=81=B8=E3=81=AE=E6=8B=9B=E5=BE=85=E3=82=92=E7=A2=BA?=
=?UTF-8?q?=E8=AA=8D=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
locales/index.d.ts | 4 ++
locales/ja-JP.yml | 1 +
packages/backend/src/core/ChatService.ts | 10 +++
.../backend/src/server/api/endpoint-list.ts | 1 +
.../chat/rooms/invitations/outbox.ts | 67 ++++++++++++++++++
.../frontend/src/pages/chat/room.members.vue | 32 ++++++++-
packages/misskey-js/etc/misskey-js.api.md | 8 +++
.../misskey-js/src/autogen/apiClientJSDoc.ts | 11 +++
packages/misskey-js/src/autogen/endpoint.ts | 3 +
packages/misskey-js/src/autogen/entities.ts | 2 +
packages/misskey-js/src/autogen/types.ts | 69 +++++++++++++++++++
11 files changed, 205 insertions(+), 3 deletions(-)
create mode 100644 packages/backend/src/server/api/endpoints/chat/rooms/invitations/outbox.ts
diff --git a/locales/index.d.ts b/locales/index.d.ts
index b0da7915dc..eee9de8f0d 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -5424,6 +5424,10 @@ export interface Locale extends ILocale {
* ユーザーを招待
*/
"inviteUser": string;
+ /**
+ * 送信した招待
+ */
+ "sentInvitations": string;
/**
* 参加
*/
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index b95adb1871..e4c17276b1 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -1353,6 +1353,7 @@ _chat:
noHistory: "履歴はありません"
noRooms: "ルームはありません"
inviteUser: "ユーザーを招待"
+ sentInvitations: "送信した招待"
join: "参加"
ignore: "無視"
leave: "ルームから退出"
diff --git a/packages/backend/src/core/ChatService.ts b/packages/backend/src/core/ChatService.ts
index 3b73a0f6ba..062ca96f17 100644
--- a/packages/backend/src/core/ChatService.ts
+++ b/packages/backend/src/core/ChatService.ts
@@ -547,6 +547,16 @@ export class ChatService {
return created;
}
+ @bindThis
+ public async getSentRoomInvitationsWithPagination(roomId: MiChatRoom['id'], limit: number, sinceId?: MiChatRoomInvitation['id'] | null, untilId?: MiChatRoomInvitation['id'] | null) {
+ const query = this.queryService.makePaginationQuery(this.chatRoomInvitationsRepository.createQueryBuilder('invitation'), sinceId, untilId)
+ .where('invitation.roomId = :roomId', { roomId });
+
+ const invitations = await query.take(limit).getMany();
+
+ return invitations;
+ }
+
@bindThis
public async getOwnedRoomsWithPagination(ownerId: MiUser['id'], limit: number, sinceId?: MiChatRoom['id'] | null, untilId?: MiChatRoom['id'] | null) {
const query = this.queryService.makePaginationQuery(this.chatRoomsRepository.createQueryBuilder('room'), sinceId, untilId)
diff --git a/packages/backend/src/server/api/endpoint-list.ts b/packages/backend/src/server/api/endpoint-list.ts
index 9bb29e138b..c8cb87e0ab 100644
--- a/packages/backend/src/server/api/endpoint-list.ts
+++ b/packages/backend/src/server/api/endpoint-list.ts
@@ -417,5 +417,6 @@ export * as 'chat/rooms/members' from './endpoints/chat/rooms/members.js';
export * as 'chat/rooms/invitations/create' from './endpoints/chat/rooms/invitations/create.js';
export * as 'chat/rooms/invitations/ignore' from './endpoints/chat/rooms/invitations/ignore.js';
export * as 'chat/rooms/invitations/inbox' from './endpoints/chat/rooms/invitations/inbox.js';
+export * as 'chat/rooms/invitations/outbox' from './endpoints/chat/rooms/invitations/outbox.js';
export * as 'chat/history' from './endpoints/chat/history.js';
export * as 'v2/admin/emoji/list' from './endpoints/v2/admin/emoji/list.js';
diff --git a/packages/backend/src/server/api/endpoints/chat/rooms/invitations/outbox.ts b/packages/backend/src/server/api/endpoints/chat/rooms/invitations/outbox.ts
new file mode 100644
index 0000000000..12d496e94b
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/chat/rooms/invitations/outbox.ts
@@ -0,0 +1,67 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Inject, Injectable } from '@nestjs/common';
+import ms from 'ms';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { DI } from '@/di-symbols.js';
+import { ApiError } from '@/server/api/error.js';
+import { ChatService } from '@/core/ChatService.js';
+import { ChatEntityService } from '@/core/entities/ChatEntityService.js';
+
+export const meta = {
+ tags: ['chat'],
+
+ requireCredential: true,
+
+ kind: 'read:chat',
+
+ res: {
+ type: 'array',
+ optional: false, nullable: false,
+ items: {
+ type: 'object',
+ optional: false, nullable: false,
+ ref: 'ChatRoomInvitation',
+ },
+ },
+
+ errors: {
+ noSuchRoom: {
+ message: 'No such room.',
+ code: 'NO_SUCH_ROOM',
+ id: 'a3c6b309-9717-4316-ae94-a69b53437237',
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ roomId: { type: 'string', format: 'misskey:id' },
+ limit: { type: 'integer', minimum: 1, maximum: 100, default: 30 },
+ sinceId: { type: 'string', format: 'misskey:id' },
+ untilId: { type: 'string', format: 'misskey:id' },
+ },
+ required: ['roomId'],
+} as const;
+
+@Injectable()
+export default class extends Endpoint
{ // eslint-disable-line import/no-default-export
+ constructor(
+ private chatService: ChatService,
+ private chatEntityService: ChatEntityService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const room = await this.chatService.findMyRoomById(me.id, ps.roomId);
+ if (room == null) {
+ throw new ApiError(meta.errors.noSuchRoom);
+ }
+
+ const invitations = await this.chatService.getSentRoomInvitationsWithPagination(ps.roomId, ps.limit, ps.sinceId, ps.untilId);
+ return this.chatEntityService.packRoomInvitations(invitations, me);
+ });
+ }
+}
diff --git a/packages/frontend/src/pages/chat/room.members.vue b/packages/frontend/src/pages/chat/room.members.vue
index d20216a81c..2b31efab38 100644
--- a/packages/frontend/src/pages/chat/room.members.vue
+++ b/packages/frontend/src/pages/chat/room.members.vue
@@ -18,6 +18,18 @@ SPDX-License-Identifier: AGPL-3.0-only
+
+