Skip to content
This repository was archived by the owner on Feb 23, 2026. It is now read-only.

Commit a4a2d24

Browse files
committed
point送信UIを追加
1 parent 719f0f0 commit a4a2d24

File tree

5 files changed

+75
-0
lines changed

5 files changed

+75
-0
lines changed

locales/index.d.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,28 @@ export interface Locale extends ILocale {
470470
* ポイント
471471
*/
472472
"point": string;
473+
/**
474+
* {pointName}を送る
475+
*/
476+
"sendPoints": ParameterizedString<"pointName">;
477+
/**
478+
* {name}に{pointName}を送る
479+
*/
480+
"sendPointsTo": ParameterizedString<"name" | "pointName">;
481+
/**
482+
* {name}に{points}{pointName}を送信します。
483+
* よろしいですか?
484+
* ※送信後は取り消すことができません。
485+
*/
486+
"sendPointsConfirm": ParameterizedString<"name" | "points" | "pointName">;
487+
/**
488+
* {pointName}が足りません
489+
*/
490+
"notEnoughPoints": ParameterizedString<"pointName">;
491+
/**
492+
* {pointName}は数字で入力してください
493+
*/
494+
"pointsMustBeNumber": ParameterizedString<"pointName">;
473495
/**
474496
* フォローされています
475497
*/

locales/ja-JP.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,11 @@ notes: "ノート"
113113
following: "フォロー"
114114
followers: "フォロワー"
115115
point: "ポイント"
116+
sendPoints: "{pointName}を送る"
117+
sendPointsTo: "{name}に{pointName}を送る"
118+
sendPointsConfirm: "{name}に{points}{pointName}を送信します。\nよろしいですか?\n※送信後は取り消すことができません。"
119+
notEnoughPoints: "{pointName}が足りません"
120+
pointsMustBeNumber: "{pointName}は数字で入力してください"
116121
followsYou: "フォローされています"
117122
createList: "リスト作成"
118123
manageLists: "リストの管理"

packages/backend/src/models/json-schema/role.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,10 @@ export const packedRolePoliciesSchema = {
304304
type: 'boolean',
305305
optional: false, nullable: false,
306306
},
307+
canSendPoints: {
308+
type: 'boolean',
309+
optional: false, nullable: false,
310+
},
307311
},
308312
} as const;
309313

packages/frontend/src/scripts/get-user-menu.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,16 @@ import { IRouter } from '@/nirax.js';
1919
import { antennasCache, rolesCache, userListsCache } from '@/cache.js';
2020
import { mainRouter } from '@/router/main.js';
2121
import { genEmbedCode } from '@/scripts/get-embed-code.js';
22+
import { instance } from '@/instance.js';
23+
import { parse } from 'path';
2224

2325
export function getUserMenu(user: Misskey.entities.UserDetailed, router: IRouter = mainRouter) {
2426
const meId = $i ? $i.id : null;
2527

2628
const cleanups = [] as (() => void)[];
2729

30+
const pointName = instance.pointName ?? i18n.ts.point;
31+
2832
async function toggleMute() {
2933
if (user.isMuted) {
3034
os.apiWithDialog('mute/delete', {
@@ -357,6 +361,45 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: IRouter
357361
});
358362
}
359363

364+
if ( $i.policies.canSendPoints) {
365+
menuItems.push({
366+
icon: 'ti ti-coin',
367+
text: i18n.tsx.sendPoints({ pointName: instance.pointName ?? i18n.ts.point }),
368+
action: async () => {
369+
const { canceled, result } = await os.inputNumber({
370+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
371+
title: i18n.tsx.sendPointsTo({ name: user.username ?? user.name, pointName: pointName }),
372+
});
373+
if (canceled) return;
374+
if (!result) return;
375+
const points = result;
376+
if (points <= 0) {
377+
await os.alert({
378+
type: 'error',
379+
text: i18n.ts.pointsMustBePositive,
380+
});
381+
return;
382+
}
383+
384+
if (($i?.getPoints != null && points >= $i.getPoints) || ($i?.getPoints == null)) {
385+
await os.alert({
386+
type: 'error',
387+
text: i18n.tsx.notEnoughPoints({ pointName: pointName }),
388+
});
389+
return;
390+
}
391+
os.confirm({
392+
type: 'warning',
393+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
394+
text: i18n.tsx.sendPointsConfirm({ name: user.username ?? user.name, pointName: instance.pointName ?? i18n.ts.point, points: points }),
395+
}).then(async ({ canceled }) => {
396+
if (canceled) return;
397+
await misskeyApi('point/send', { userId: user.id, points });
398+
});
399+
},
400+
});
401+
}
402+
360403
// フォローしたとしても user.isFollowing はリアルタイム更新されないので不便なため
361404
//if (user.isFollowing) {
362405
const withRepliesRef = ref(user.withReplies ?? false);

packages/misskey-js/src/autogen/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5106,6 +5106,7 @@ export type components = {
51065106
canImportFollowing: boolean;
51075107
canImportMuting: boolean;
51085108
canImportUserLists: boolean;
5109+
canSendPoints: boolean;
51095110
};
51105111
ReversiGameLite: {
51115112
/** Format: id */

0 commit comments

Comments
 (0)