This commit is contained in:
syuilo
2025-03-22 19:49:59 +09:00
parent 7e826ce5d6
commit 34760459b2
7 changed files with 67 additions and 63 deletions

16
locales/index.d.ts vendored
View File

@@ -1978,14 +1978,6 @@ export interface Locale extends ILocale {
* クリップボードのテキストが長いです。テキストファイルとして添付しますか?
*/
"attachAsFileQuestion": string;
/**
* まだチャットはありません
*/
"noMessagesYet": string;
/**
* 新しいメッセージがあります
*/
"newMessageExists": string;
/**
* メッセージに添付できるファイルはひとつです
*/
@@ -5359,6 +5351,14 @@ export interface Locale extends ILocale {
*/
"chat": string;
"_chat": {
/**
* まだメッセージはありません
*/
"noMessagesYet": string;
/**
* 新しいメッセージ
*/
"newMessage": string;
/**
* 個人チャット
*/

View File

@@ -490,8 +490,6 @@ noteOf: "{user}のノート"
quoteAttached: "引用付き"
quoteQuestion: "引用として添付しますか?"
attachAsFileQuestion: "クリップボードのテキストが長いです。テキストファイルとして添付しますか?"
noMessagesYet: "まだチャットはありません"
newMessageExists: "新しいメッセージがあります"
onlyOneFileCanBeAttached: "メッセージに添付できるファイルはひとつです"
signinRequired: "続行する前に、登録またはログインが必要です"
signinOrContinueOnRemote: "続行するには、お使いのサーバーに移動するか、このサーバーに登録・ログインする必要があります"
@@ -1337,6 +1335,8 @@ information: "情報"
chat: "チャット"
_chat:
noMessagesYet: "まだメッセージはありません"
newMessage: "新しいメッセージ"
individualChat: "個人チャット"
individualChat_description: "特定ユーザーとの一対一のチャットができます。"
roomChat: "ルームチャット"

View File

@@ -90,27 +90,27 @@ export class ChatService {
if (!otherApprovedMe) {
if (toUser.chatScope === 'none') {
throw new Error('recipient is cannot chat');
throw new Error('recipient is cannot chat (none)');
} else if (toUser.chatScope === 'followers') {
const isFollower = await this.userFollowingService.isFollowing(fromUser.id, toUser.id);
if (!isFollower) {
throw new Error('recipient is cannot chat');
throw new Error('recipient is cannot chat (followers)');
}
} else if (toUser.chatScope === 'following') {
const isFollowing = await this.userFollowingService.isFollowing(toUser.id, fromUser.id);
if (!isFollowing) {
throw new Error('recipient is cannot chat');
throw new Error('recipient is cannot chat (following)');
}
} else if (toUser.chatScope === 'mutual') {
const isMutual = await this.userFollowingService.isMutual(fromUser.id, toUser.id);
if (!isMutual) {
throw new Error('recipient is cannot chat');
throw new Error('recipient is cannot chat (mutual)');
}
}
}
if ((await this.roleService.getUserPolicies(toUser.id)).canChat) {
throw new Error('recipient is cannot chat');
if (!(await this.roleService.getUserPolicies(toUser.id)).canChat) {
throw new Error('recipient is cannot chat (policy)');
}
const blocked = await this.userBlockingService.checkBlocked(toUser.id, fromUser.id);

View File

@@ -292,7 +292,7 @@ const $swSubscriptionsRepository: Provider = {
const $systemAccountsRepository: Provider = {
provide: DI.systemAccountsRepository,
useFactory: (db: DataSource) => db.getRepository(MiSystemAccount),
useFactory: (db: DataSource) => db.getRepository(MiSystemAccount).extend(miRepository as MiRepository<MiSystemAccount>),
inject: [DI.db],
};
@@ -310,7 +310,7 @@ const $abuseUserReportsRepository: Provider = {
const $abuseReportNotificationRecipientRepository: Provider = {
provide: DI.abuseReportNotificationRecipientRepository,
useFactory: (db: DataSource) => db.getRepository(MiAbuseReportNotificationRecipient),
useFactory: (db: DataSource) => db.getRepository(MiAbuseReportNotificationRecipient).extend(miRepository as MiRepository<MiAbuseReportNotificationRecipient>),
inject: [DI.db],
};
@@ -442,7 +442,7 @@ const $webhooksRepository: Provider = {
const $systemWebhooksRepository: Provider = {
provide: DI.systemWebhooksRepository,
useFactory: (db: DataSource) => db.getRepository(MiSystemWebhook),
useFactory: (db: DataSource) => db.getRepository(MiSystemWebhook).extend(miRepository as MiRepository<MiSystemWebhook>),
inject: [DI.db],
};
@@ -514,7 +514,7 @@ const $chatRoomMembershipsRepository: Provider = {
const $chatApprovalsRepository: Provider = {
provide: DI.chatApprovalsRepository,
useFactory: (db: DataSource) => db.getRepository(MiChatApproval),
useFactory: (db: DataSource) => db.getRepository(MiChatApproval).extend(miRepository as MiRepository<MiChatApproval>),
inject: [DI.db],
};

View File

@@ -125,9 +125,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
throw err;
});
return await this.chatService.createMessage({
fromUser: me,
toUser,
return await this.chatService.createMessage(me, toUser, {
text: ps.text,
file: file,
});

View File

@@ -9,8 +9,14 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkSpacer :contentMax="700">
<MkPagination v-if="pagination" ref="pagingComponent" :key="userId || roomId" :pagination="pagination" :disableAutoLoad="true" :scrollReversed="true">
<template #empty>
<div class="_fullinfo">
<div class="_gaps" style="text-align: center;">
<div>{{ i18n.ts.noMessagesYet }}</div>
<template v-if="user">
<div v-if="user.chatScope === 'followers'">{{ i18n.ts._chat.thisUserAllowsChatOnlyFromFollowers }}</div>
<div v-else-if="user.chatScope === 'following'">{{ i18n.ts._chat.thisUserAllowsChatOnlyFromFollowing }}</div>
<div v-else-if="user.chatScope === 'mutual'">{{ i18n.ts._chat.thisUserAllowsChatOnlyFromMutualFollowing }}</div>
<div v-else>{{ i18n.ts._chat.thisUserNotAllowedChatAnyone }}</div>
</template>
</div>
</template>
<template #default="{ items: messages }">

View File

@@ -151,6 +151,16 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: Router
const menuItems: MenuItem[] = [];
if (iAmModerator) {
menuItems.push({
icon: 'ti ti-user-exclamation',
text: i18n.ts.moderation,
action: () => {
router.push(`/admin/user/${user.id}`);
},
}, { type: 'divider' });
}
menuItems.push({
icon: 'ti ti-at',
text: i18n.ts.copyUsername,
@@ -159,25 +169,14 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: Router
},
});
if (notesSearchAvailable && (user.host == null || canSearchNonLocalNotes)) {
menuItems.push({
icon: 'ti ti-search',
text: i18n.ts.searchThisUsersNotes,
icon: 'ti ti-share',
text: i18n.ts.copyProfileUrl,
action: () => {
router.push(`/search?username=${encodeURIComponent(user.username)}${user.host != null ? '&host=' + encodeURIComponent(user.host) : ''}`);
const canonical = user.host === null ? `@${user.username}` : `@${user.username}@${toUnicode(user.host)}`;
copyToClipboard(`${url}/${canonical}`);
},
});
}
if (iAmModerator) {
menuItems.push({
icon: 'ti ti-user-exclamation',
text: i18n.ts.moderation,
action: () => {
router.push(`/admin/user/${user.id}`);
},
});
}
menuItems.push({
icon: 'ti ti-rss',
@@ -210,29 +209,18 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: Router
});
}
if (notesSearchAvailable && (user.host == null || canSearchNonLocalNotes)) {
menuItems.push({
icon: 'ti ti-share',
text: i18n.ts.copyProfileUrl,
icon: 'ti ti-search',
text: i18n.ts.searchThisUsersNotes,
action: () => {
const canonical = user.host === null ? `@${user.username}` : `@${user.username}@${toUnicode(user.host)}`;
copyToClipboard(`${url}/${canonical}`);
router.push(`/search?username=${encodeURIComponent(user.username)}${user.host != null ? '&host=' + encodeURIComponent(user.host) : ''}`);
},
});
}
if ($i) {
menuItems.push({ type: 'divider' }, {
icon: 'ti ti-mail',
text: i18n.ts.sendMessage,
action: () => {
const canonical = user.host === null ? `@${user.username}` : `@${user.username}@${user.host}`;
os.post({ specified: user, initialText: `${canonical} ` });
},
}, {
type: 'link',
icon: 'ti ti-messages',
text: i18n.ts._chat.chatWithThisUser,
to: `/chat/user/${user.id}`,
}, { type: 'divider' }, {
icon: 'ti ti-pencil',
text: i18n.ts.editMemo,
action: editMemo,
@@ -368,6 +356,18 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: Router
//}
menuItems.push({ type: 'divider' }, {
icon: 'ti ti-mail',
text: i18n.ts.sendMessage,
action: () => {
const canonical = user.host === null ? `@${user.username}` : `@${user.username}@${user.host}`;
os.post({ specified: user, initialText: `${canonical} ` });
},
}, {
type: 'link',
icon: 'ti ti-messages',
text: i18n.ts._chat.chatWithThisUser,
to: `/chat/user/${user.id}`,
}, { type: 'divider' }, {
icon: user.isMuted ? 'ti ti-eye' : 'ti ti-eye-off',
text: user.isMuted ? i18n.ts.unmute : i18n.ts.mute,
action: toggleMute,