Merge branch 'develop' into pr/16456
This commit is contained in:
commit
ae452dbb54
|
@ -4,6 +4,8 @@
|
|||
- Enhance: 広告ごとにセンシティブフラグを設定できるようになりました
|
||||
|
||||
### Client
|
||||
- Enhance: チャットの日本語名称がダイレクトメッセージに戻るとともに、ベータ版機能ではなくなりました
|
||||
- Enhance: 画像編集にマスクエフェクトを追加
|
||||
- Enhance: 時刻計算のための基準値を一か所で管理するようにし、パフォーマンスを向上
|
||||
|
||||
### Server
|
||||
|
|
|
@ -1227,7 +1227,7 @@ export interface Locale extends ILocale {
|
|||
*/
|
||||
"noMoreHistory": string;
|
||||
/**
|
||||
* チャットを始める
|
||||
* メッセージを送る
|
||||
*/
|
||||
"startChat": string;
|
||||
/**
|
||||
|
@ -1927,7 +1927,7 @@ export interface Locale extends ILocale {
|
|||
*/
|
||||
"markAsReadAllUnreadNotes": string;
|
||||
/**
|
||||
* すべてのチャットを既読にする
|
||||
* すべてのダイレクトメッセージを既読にする
|
||||
*/
|
||||
"markAsReadAllTalkMessages": string;
|
||||
/**
|
||||
|
@ -5390,6 +5390,14 @@ export interface Locale extends ILocale {
|
|||
* チャット
|
||||
*/
|
||||
"chat": string;
|
||||
/**
|
||||
* ダイレクトメッセージ
|
||||
*/
|
||||
"directMessage": string;
|
||||
/**
|
||||
* メッセージ
|
||||
*/
|
||||
"directMessage_short": string;
|
||||
/**
|
||||
* 旧設定情報を移行
|
||||
*/
|
||||
|
@ -5529,6 +5537,10 @@ export interface Locale extends ILocale {
|
|||
* ベータ版の検証にご協力いただきありがとうございます!
|
||||
*/
|
||||
"thankYouForTestingBeta": string;
|
||||
/**
|
||||
* ユーザー指定ノートを作成
|
||||
*/
|
||||
"createUserSpecifiedNote": string;
|
||||
"_order": {
|
||||
/**
|
||||
* 新しい順
|
||||
|
@ -5540,6 +5552,10 @@ export interface Locale extends ILocale {
|
|||
"oldest": string;
|
||||
};
|
||||
"_chat": {
|
||||
/**
|
||||
* メッセージ
|
||||
*/
|
||||
"messages": string;
|
||||
/**
|
||||
* まだメッセージはありません
|
||||
*/
|
||||
|
@ -5549,36 +5565,36 @@ export interface Locale extends ILocale {
|
|||
*/
|
||||
"newMessage": string;
|
||||
/**
|
||||
* 個人チャット
|
||||
* 個別
|
||||
*/
|
||||
"individualChat": string;
|
||||
/**
|
||||
* 特定ユーザーとの一対一のチャットができます。
|
||||
* 特定ユーザーと個別にメッセージのやりとりができます。
|
||||
*/
|
||||
"individualChat_description": string;
|
||||
/**
|
||||
* ルームチャット
|
||||
* グループ
|
||||
*/
|
||||
"roomChat": string;
|
||||
/**
|
||||
* 複数人でのチャットができます。
|
||||
* また、個人チャットを許可していないユーザーとでも、相手が受け入れればチャットができます。
|
||||
* 複数人でメッセージのやりとりができます。
|
||||
* また、個別のメッセージを許可していないユーザーとでも、相手が受け入れればやりとりできます。
|
||||
*/
|
||||
"roomChat_description": string;
|
||||
/**
|
||||
* ルームを作成
|
||||
* グループを作成
|
||||
*/
|
||||
"createRoom": string;
|
||||
/**
|
||||
* ユーザーを招待してチャットを始めましょう
|
||||
* ユーザーを招待してメッセージを送信しましょう
|
||||
*/
|
||||
"inviteUserToChat": string;
|
||||
/**
|
||||
* 作成したルーム
|
||||
* 作成したグループ
|
||||
*/
|
||||
"yourRooms": string;
|
||||
/**
|
||||
* 参加中のルーム
|
||||
* 参加中のグループ
|
||||
*/
|
||||
"joiningRooms": string;
|
||||
/**
|
||||
|
@ -5598,7 +5614,7 @@ export interface Locale extends ILocale {
|
|||
*/
|
||||
"noHistory": string;
|
||||
/**
|
||||
* ルームはありません
|
||||
* グループはありません
|
||||
*/
|
||||
"noRooms": string;
|
||||
/**
|
||||
|
@ -5618,7 +5634,7 @@ export interface Locale extends ILocale {
|
|||
*/
|
||||
"ignore": string;
|
||||
/**
|
||||
* ルームから退出
|
||||
* グループから退出
|
||||
*/
|
||||
"leave": string;
|
||||
/**
|
||||
|
@ -5642,35 +5658,35 @@ export interface Locale extends ILocale {
|
|||
*/
|
||||
"newline": string;
|
||||
/**
|
||||
* このルームをミュート
|
||||
* このグループをミュート
|
||||
*/
|
||||
"muteThisRoom": string;
|
||||
/**
|
||||
* ルームを削除
|
||||
* グループを削除
|
||||
*/
|
||||
"deleteRoom": string;
|
||||
/**
|
||||
* このサーバー、またはこのアカウントでチャットは有効化されていません。
|
||||
* このサーバー、またはこのアカウントでダイレクトメッセージは有効化されていません。
|
||||
*/
|
||||
"chatNotAvailableForThisAccountOrServer": string;
|
||||
/**
|
||||
* このサーバー、またはこのアカウントでチャットは読み取り専用となっています。新たに書き込んだり、チャットルームを作成・参加したりすることはできません。
|
||||
* このサーバー、またはこのアカウントでダイレクトメッセージは読み取り専用となっています。新たに書き込んだり、グループを作成・参加したりすることはできません。
|
||||
*/
|
||||
"chatIsReadOnlyForThisAccountOrServer": string;
|
||||
/**
|
||||
* 相手のアカウントでチャット機能が使えない状態になっています。
|
||||
* 相手のアカウントでダイレクトメッセージが使えない状態になっています。
|
||||
*/
|
||||
"chatNotAvailableInOtherAccount": string;
|
||||
/**
|
||||
* このユーザーとのチャットを開始できません
|
||||
* このユーザーとのダイレクトメッセージを開始できません
|
||||
*/
|
||||
"cannotChatWithTheUser": string;
|
||||
/**
|
||||
* チャットが使えない状態になっているか、相手がチャットを開放していません。
|
||||
* ダイレクトメッセージが使えない状態になっているか、相手がダイレクトメッセージを開放していません。
|
||||
*/
|
||||
"cannotChatWithTheUser_description": string;
|
||||
/**
|
||||
* あなたはこのルームの参加者ではありませんが、招待が届いています。参加するには、招待を承認してください。
|
||||
* あなたはこのグループの参加者ではありませんが、招待が届いています。参加するには、招待を承認してください。
|
||||
*/
|
||||
"youAreNotAMemberOfThisRoomButInvited": string;
|
||||
/**
|
||||
|
@ -5678,31 +5694,31 @@ export interface Locale extends ILocale {
|
|||
*/
|
||||
"doYouAcceptInvitation": string;
|
||||
/**
|
||||
* チャットする
|
||||
* ダイレクトメッセージ
|
||||
*/
|
||||
"chatWithThisUser": string;
|
||||
/**
|
||||
* このユーザーはフォロワーからのみチャットを受け付けています。
|
||||
* このユーザーはフォロワーからのみメッセージを受け付けています。
|
||||
*/
|
||||
"thisUserAllowsChatOnlyFromFollowers": string;
|
||||
/**
|
||||
* このユーザーは、このユーザーがフォローしているユーザーからのみチャットを受け付けています。
|
||||
* このユーザーは、このユーザーがフォローしているユーザーからのみメッセージを受け付けています。
|
||||
*/
|
||||
"thisUserAllowsChatOnlyFromFollowing": string;
|
||||
/**
|
||||
* このユーザーは相互フォローのユーザーからのみチャットを受け付けています。
|
||||
* このユーザーは相互フォローのユーザーからのみメッセージを受け付けています。
|
||||
*/
|
||||
"thisUserAllowsChatOnlyFromMutualFollowing": string;
|
||||
/**
|
||||
* このユーザーは誰からもチャットを受け付けていません。
|
||||
* このユーザーは誰からもメッセージを受け付けていません。
|
||||
*/
|
||||
"thisUserNotAllowedChatAnyone": string;
|
||||
/**
|
||||
* チャットを許可する相手
|
||||
* メッセージを許可する相手
|
||||
*/
|
||||
"chatAllowedUsers": string;
|
||||
/**
|
||||
* 自分からチャットメッセージを送った相手とはこの設定に関わらずチャットが可能です。
|
||||
* 自分からメッセージを送った相手とはこの設定に関わらずメッセージの送受信が可能です。
|
||||
*/
|
||||
"chatAllowedUsers_note": string;
|
||||
"_chatAllowedUsers": {
|
||||
|
@ -7856,7 +7872,7 @@ export interface Locale extends ILocale {
|
|||
*/
|
||||
"canImportUserLists": string;
|
||||
/**
|
||||
* チャットを許可
|
||||
* ダイレクトメッセージを許可
|
||||
*/
|
||||
"chatAvailability": string;
|
||||
/**
|
||||
|
@ -8706,7 +8722,7 @@ export interface Locale extends ILocale {
|
|||
*/
|
||||
"badge": string;
|
||||
/**
|
||||
* チャットの背景
|
||||
* メッセージの背景
|
||||
*/
|
||||
"messageBg": string;
|
||||
/**
|
||||
|
@ -8733,7 +8749,7 @@ export interface Locale extends ILocale {
|
|||
*/
|
||||
"reaction": string;
|
||||
/**
|
||||
* チャットのメッセージ
|
||||
* ダイレクトメッセージ
|
||||
*/
|
||||
"chatMessage": string;
|
||||
};
|
||||
|
@ -9017,11 +9033,11 @@ export interface Locale extends ILocale {
|
|||
*/
|
||||
"write:following": string;
|
||||
/**
|
||||
* チャットを見る
|
||||
* ダイレクトメッセージを見る
|
||||
*/
|
||||
"read:messaging": string;
|
||||
/**
|
||||
* チャットを操作する
|
||||
* ダイレクトメッセージを操作する
|
||||
*/
|
||||
"write:messaging": string;
|
||||
/**
|
||||
|
@ -9313,11 +9329,11 @@ export interface Locale extends ILocale {
|
|||
*/
|
||||
"write:report-abuse": string;
|
||||
/**
|
||||
* チャットを操作する
|
||||
* ダイレクトメッセージを操作する
|
||||
*/
|
||||
"write:chat": string;
|
||||
/**
|
||||
* チャットを閲覧する
|
||||
* ダイレクトメッセージを閲覧する
|
||||
*/
|
||||
"read:chat": string;
|
||||
};
|
||||
|
@ -9543,7 +9559,7 @@ export interface Locale extends ILocale {
|
|||
*/
|
||||
"birthdayFollowings": string;
|
||||
/**
|
||||
* チャット
|
||||
* ダイレクトメッセージ
|
||||
*/
|
||||
"chat": string;
|
||||
};
|
||||
|
@ -10283,7 +10299,7 @@ export interface Locale extends ILocale {
|
|||
*/
|
||||
"roleAssigned": string;
|
||||
/**
|
||||
* チャットルームへ招待されました
|
||||
* ダイレクトメッセージのグループへ招待されました
|
||||
*/
|
||||
"chatRoomInvitationReceived": string;
|
||||
/**
|
||||
|
@ -10396,7 +10412,7 @@ export interface Locale extends ILocale {
|
|||
*/
|
||||
"roleAssigned": string;
|
||||
/**
|
||||
* チャットルームへ招待された
|
||||
* ダイレクトメッセージのグループへ招待された
|
||||
*/
|
||||
"chatRoomInvitationReceived": string;
|
||||
/**
|
||||
|
@ -10578,7 +10594,7 @@ export interface Locale extends ILocale {
|
|||
*/
|
||||
"roleTimeline": string;
|
||||
/**
|
||||
* チャット
|
||||
* ダイレクトメッセージ
|
||||
*/
|
||||
"chat": string;
|
||||
};
|
||||
|
@ -10945,7 +10961,7 @@ export interface Locale extends ILocale {
|
|||
*/
|
||||
"deleteGalleryPost": string;
|
||||
/**
|
||||
* チャットルームを削除
|
||||
* ダイレクトメッセージのグループを削除
|
||||
*/
|
||||
"deleteChatRoom": string;
|
||||
/**
|
||||
|
@ -12362,6 +12378,10 @@ export interface Locale extends ILocale {
|
|||
* ティアリング
|
||||
*/
|
||||
"tearing": string;
|
||||
/**
|
||||
* 塗りつぶし(四角)
|
||||
*/
|
||||
"fillSquare": string;
|
||||
};
|
||||
"_fxProps": {
|
||||
/**
|
||||
|
@ -12376,6 +12396,10 @@ export interface Locale extends ILocale {
|
|||
* サイズ
|
||||
*/
|
||||
"size": string;
|
||||
/**
|
||||
* 位置
|
||||
*/
|
||||
"offset": string;
|
||||
/**
|
||||
* 色
|
||||
*/
|
||||
|
|
|
@ -302,7 +302,7 @@ uploadNFiles: "{n}個のファイルをアップロード"
|
|||
explore: "みつける"
|
||||
messageRead: "既読"
|
||||
noMoreHistory: "これより過去の履歴はありません"
|
||||
startChat: "チャットを始める"
|
||||
startChat: "メッセージを送る"
|
||||
nUsersRead: "{n}人が読みました"
|
||||
agreeTo: "{0}に同意"
|
||||
agree: "同意する"
|
||||
|
@ -477,7 +477,7 @@ notFoundDescription: "指定されたURLに該当するページはありませ
|
|||
uploadFolder: "既定アップロード先"
|
||||
markAsReadAllNotifications: "すべての通知を既読にする"
|
||||
markAsReadAllUnreadNotes: "すべての投稿を既読にする"
|
||||
markAsReadAllTalkMessages: "すべてのチャットを既読にする"
|
||||
markAsReadAllTalkMessages: "すべてのダイレクトメッセージを既読にする"
|
||||
help: "ヘルプ"
|
||||
inputMessageHere: "ここにメッセージを入力"
|
||||
close: "閉じる"
|
||||
|
@ -1343,6 +1343,8 @@ postForm: "投稿フォーム"
|
|||
textCount: "文字数"
|
||||
information: "情報"
|
||||
chat: "チャット"
|
||||
directMessage: "ダイレクトメッセージ"
|
||||
directMessage_short: "メッセージ"
|
||||
migrateOldSettings: "旧設定情報を移行"
|
||||
migrateOldSettings_description: "通常これは自動で行われていますが、何らかの理由により上手く移行されなかった場合は手動で移行処理をトリガーできます。現在の設定情報は上書きされます。"
|
||||
compress: "圧縮"
|
||||
|
@ -1377,53 +1379,55 @@ pluginsAreDisabledBecauseSafeMode: "セーフモードが有効なため、プ
|
|||
customCssIsDisabledBecauseSafeMode: "セーフモードが有効なため、カスタムCSSは適用されていません。"
|
||||
themeIsDefaultBecauseSafeMode: "セーフモードが有効な間はデフォルトのテーマが使用されます。セーフモードをオフにすると元に戻ります。"
|
||||
thankYouForTestingBeta: "ベータ版の検証にご協力いただきありがとうございます!"
|
||||
createUserSpecifiedNote: "ユーザー指定ノートを作成"
|
||||
|
||||
_order:
|
||||
newest: "新しい順"
|
||||
oldest: "古い順"
|
||||
|
||||
_chat:
|
||||
messages: "メッセージ"
|
||||
noMessagesYet: "まだメッセージはありません"
|
||||
newMessage: "新しいメッセージ"
|
||||
individualChat: "個人チャット"
|
||||
individualChat_description: "特定ユーザーとの一対一のチャットができます。"
|
||||
roomChat: "ルームチャット"
|
||||
roomChat_description: "複数人でのチャットができます。\nまた、個人チャットを許可していないユーザーとでも、相手が受け入れればチャットができます。"
|
||||
createRoom: "ルームを作成"
|
||||
inviteUserToChat: "ユーザーを招待してチャットを始めましょう"
|
||||
yourRooms: "作成したルーム"
|
||||
joiningRooms: "参加中のルーム"
|
||||
individualChat: "個別"
|
||||
individualChat_description: "特定ユーザーと個別にメッセージのやりとりができます。"
|
||||
roomChat: "グループ"
|
||||
roomChat_description: "複数人でメッセージのやりとりができます。\nまた、個別のメッセージを許可していないユーザーとでも、相手が受け入れればやりとりできます。"
|
||||
createRoom: "グループを作成"
|
||||
inviteUserToChat: "ユーザーを招待してメッセージを送信しましょう"
|
||||
yourRooms: "作成したグループ"
|
||||
joiningRooms: "参加中のグループ"
|
||||
invitations: "招待"
|
||||
noInvitations: "招待はありません"
|
||||
history: "履歴"
|
||||
noHistory: "履歴はありません"
|
||||
noRooms: "ルームはありません"
|
||||
noRooms: "グループはありません"
|
||||
inviteUser: "ユーザーを招待"
|
||||
sentInvitations: "送信した招待"
|
||||
join: "参加"
|
||||
ignore: "無視"
|
||||
leave: "ルームから退出"
|
||||
leave: "グループから退出"
|
||||
members: "メンバー"
|
||||
searchMessages: "メッセージを検索"
|
||||
home: "ホーム"
|
||||
send: "送信"
|
||||
newline: "改行"
|
||||
muteThisRoom: "このルームをミュート"
|
||||
deleteRoom: "ルームを削除"
|
||||
chatNotAvailableForThisAccountOrServer: "このサーバー、またはこのアカウントでチャットは有効化されていません。"
|
||||
chatIsReadOnlyForThisAccountOrServer: "このサーバー、またはこのアカウントでチャットは読み取り専用となっています。新たに書き込んだり、チャットルームを作成・参加したりすることはできません。"
|
||||
chatNotAvailableInOtherAccount: "相手のアカウントでチャット機能が使えない状態になっています。"
|
||||
cannotChatWithTheUser: "このユーザーとのチャットを開始できません"
|
||||
cannotChatWithTheUser_description: "チャットが使えない状態になっているか、相手がチャットを開放していません。"
|
||||
youAreNotAMemberOfThisRoomButInvited: "あなたはこのルームの参加者ではありませんが、招待が届いています。参加するには、招待を承認してください。"
|
||||
muteThisRoom: "このグループをミュート"
|
||||
deleteRoom: "グループを削除"
|
||||
chatNotAvailableForThisAccountOrServer: "このサーバー、またはこのアカウントでダイレクトメッセージは有効化されていません。"
|
||||
chatIsReadOnlyForThisAccountOrServer: "このサーバー、またはこのアカウントでダイレクトメッセージは読み取り専用となっています。新たに書き込んだり、グループを作成・参加したりすることはできません。"
|
||||
chatNotAvailableInOtherAccount: "相手のアカウントでダイレクトメッセージが使えない状態になっています。"
|
||||
cannotChatWithTheUser: "このユーザーとのダイレクトメッセージを開始できません"
|
||||
cannotChatWithTheUser_description: "ダイレクトメッセージが使えない状態になっているか、相手がダイレクトメッセージを開放していません。"
|
||||
youAreNotAMemberOfThisRoomButInvited: "あなたはこのグループの参加者ではありませんが、招待が届いています。参加するには、招待を承認してください。"
|
||||
doYouAcceptInvitation: "招待を承認しますか?"
|
||||
chatWithThisUser: "チャットする"
|
||||
thisUserAllowsChatOnlyFromFollowers: "このユーザーはフォロワーからのみチャットを受け付けています。"
|
||||
thisUserAllowsChatOnlyFromFollowing: "このユーザーは、このユーザーがフォローしているユーザーからのみチャットを受け付けています。"
|
||||
thisUserAllowsChatOnlyFromMutualFollowing: "このユーザーは相互フォローのユーザーからのみチャットを受け付けています。"
|
||||
thisUserNotAllowedChatAnyone: "このユーザーは誰からもチャットを受け付けていません。"
|
||||
chatAllowedUsers: "チャットを許可する相手"
|
||||
chatAllowedUsers_note: "自分からチャットメッセージを送った相手とはこの設定に関わらずチャットが可能です。"
|
||||
chatWithThisUser: "ダイレクトメッセージ"
|
||||
thisUserAllowsChatOnlyFromFollowers: "このユーザーはフォロワーからのみメッセージを受け付けています。"
|
||||
thisUserAllowsChatOnlyFromFollowing: "このユーザーは、このユーザーがフォローしているユーザーからのみメッセージを受け付けています。"
|
||||
thisUserAllowsChatOnlyFromMutualFollowing: "このユーザーは相互フォローのユーザーからのみメッセージを受け付けています。"
|
||||
thisUserNotAllowedChatAnyone: "このユーザーは誰からもメッセージを受け付けていません。"
|
||||
chatAllowedUsers: "メッセージを許可する相手"
|
||||
chatAllowedUsers_note: "自分からメッセージを送った相手とはこの設定に関わらずメッセージの送受信が可能です。"
|
||||
_chatAllowedUsers:
|
||||
everyone: "誰でも"
|
||||
followers: "自分のフォロワーのみ"
|
||||
|
@ -2034,7 +2038,7 @@ _role:
|
|||
canImportFollowing: "フォローのインポートを許可"
|
||||
canImportMuting: "ミュートのインポートを許可"
|
||||
canImportUserLists: "リストのインポートを許可"
|
||||
chatAvailability: "チャットを許可"
|
||||
chatAvailability: "ダイレクトメッセージを許可"
|
||||
uploadableFileTypes: "アップロード可能なファイル種別"
|
||||
uploadableFileTypes_caption: "MIMEタイプを指定します。改行で区切って複数指定できるほか、アスタリスク(*)でワイルドカード指定できます。(例: image/*)"
|
||||
uploadableFileTypes_caption2: "ファイルによっては種別を判定できないことがあります。そのようなファイルを許可する場合は {x} を指定に追加してください。"
|
||||
|
@ -2281,7 +2285,7 @@ _theme:
|
|||
buttonHoverBg: "ボタンの背景 (ホバー)"
|
||||
inputBorder: "入力ボックスの縁取り"
|
||||
badge: "バッジ"
|
||||
messageBg: "チャットの背景"
|
||||
messageBg: "メッセージの背景"
|
||||
fgHighlighted: "強調された文字"
|
||||
|
||||
_sfx:
|
||||
|
@ -2289,7 +2293,7 @@ _sfx:
|
|||
noteMy: "ノート(自分)"
|
||||
notification: "通知"
|
||||
reaction: "リアクション選択時"
|
||||
chatMessage: "チャットのメッセージ"
|
||||
chatMessage: "ダイレクトメッセージ"
|
||||
|
||||
_soundSettings:
|
||||
driveFile: "ドライブの音声を使用"
|
||||
|
@ -2369,8 +2373,8 @@ _permissions:
|
|||
"write:favorites": "お気に入りを操作する"
|
||||
"read:following": "フォローの情報を見る"
|
||||
"write:following": "フォロー・フォロー解除する"
|
||||
"read:messaging": "チャットを見る"
|
||||
"write:messaging": "チャットを操作する"
|
||||
"read:messaging": "ダイレクトメッセージを見る"
|
||||
"write:messaging": "ダイレクトメッセージを操作する"
|
||||
"read:mutes": "ミュートを見る"
|
||||
"write:mutes": "ミュートを操作する"
|
||||
"write:notes": "ノートを作成・削除する"
|
||||
|
@ -2443,8 +2447,8 @@ _permissions:
|
|||
"read:clip-favorite": "クリップのいいねを見る"
|
||||
"read:federation": "連合に関する情報を取得する"
|
||||
"write:report-abuse": "違反を報告する"
|
||||
"write:chat": "チャットを操作する"
|
||||
"read:chat": "チャットを閲覧する"
|
||||
"write:chat": "ダイレクトメッセージを操作する"
|
||||
"read:chat": "ダイレクトメッセージを閲覧する"
|
||||
|
||||
_auth:
|
||||
shareAccessTitle: "アプリへのアクセス許可"
|
||||
|
@ -2507,7 +2511,7 @@ _widgets:
|
|||
chooseList: "リストを選択"
|
||||
clicker: "クリッカー"
|
||||
birthdayFollowings: "今日誕生日のユーザー"
|
||||
chat: "チャット"
|
||||
chat: "ダイレクトメッセージ"
|
||||
|
||||
_cw:
|
||||
hide: "隠す"
|
||||
|
@ -2714,7 +2718,7 @@ _notification:
|
|||
newNote: "新しい投稿"
|
||||
unreadAntennaNote: "アンテナ {name}"
|
||||
roleAssigned: "ロールが付与されました"
|
||||
chatRoomInvitationReceived: "チャットルームへ招待されました"
|
||||
chatRoomInvitationReceived: "ダイレクトメッセージのグループへ招待されました"
|
||||
emptyPushNotificationMessage: "プッシュ通知の更新をしました"
|
||||
achievementEarned: "実績を獲得"
|
||||
testNotification: "通知テスト"
|
||||
|
@ -2744,7 +2748,7 @@ _notification:
|
|||
receiveFollowRequest: "フォロー申請を受け取った"
|
||||
followRequestAccepted: "フォローが受理された"
|
||||
roleAssigned: "ロールが付与された"
|
||||
chatRoomInvitationReceived: "チャットルームへ招待された"
|
||||
chatRoomInvitationReceived: "ダイレクトメッセージのグループへ招待された"
|
||||
achievementEarned: "実績の獲得"
|
||||
exportCompleted: "エクスポートが完了した"
|
||||
login: "ログイン"
|
||||
|
@ -2794,7 +2798,7 @@ _deck:
|
|||
mentions: "メンション"
|
||||
direct: "指名"
|
||||
roleTimeline: "ロールタイムライン"
|
||||
chat: "チャット"
|
||||
chat: "ダイレクトメッセージ"
|
||||
|
||||
_dialog:
|
||||
charactersExceeded: "最大文字数を超えています! 現在 {current} / 制限 {max}"
|
||||
|
@ -2897,7 +2901,7 @@ _moderationLogTypes:
|
|||
deletePage: "ページを削除"
|
||||
deleteFlash: "Playを削除"
|
||||
deleteGalleryPost: "ギャラリーの投稿を削除"
|
||||
deleteChatRoom: "チャットルームを削除"
|
||||
deleteChatRoom: "ダイレクトメッセージのグループを削除"
|
||||
updateProxyAccountDescription: "プロキシアカウントの説明を更新"
|
||||
|
||||
_fileViewer:
|
||||
|
@ -3310,11 +3314,13 @@ _imageEffector:
|
|||
checker: "チェッカー"
|
||||
blockNoise: "ブロックノイズ"
|
||||
tearing: "ティアリング"
|
||||
fillSquare: "塗りつぶし(四角)"
|
||||
|
||||
_fxProps:
|
||||
angle: "角度"
|
||||
scale: "サイズ"
|
||||
size: "サイズ"
|
||||
offset: "位置"
|
||||
color: "色"
|
||||
opacity: "不透明度"
|
||||
normalize: "正規化"
|
||||
|
|
|
@ -109,6 +109,7 @@ export const DEFAULT_POLICIES: RolePolicies = {
|
|||
chatAvailability: 'available',
|
||||
uploadableFileTypes: [
|
||||
'text/plain',
|
||||
'text/csv',
|
||||
'application/json',
|
||||
'image/*',
|
||||
'video/*',
|
||||
|
|
|
@ -19,9 +19,12 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div :class="$style.root">
|
||||
<div :class="$style.container">
|
||||
<div :class="$style.preview">
|
||||
<canvas ref="canvasEl" :class="$style.previewCanvas"></canvas>
|
||||
<canvas ref="canvasEl" :class="$style.previewCanvas" @pointerdown="onImagePointerdown"></canvas>
|
||||
<div :class="$style.previewContainer">
|
||||
<div class="_acrylic" :class="$style.previewTitle">{{ i18n.ts.preview }}</div>
|
||||
<div class="_acrylic" :class="$style.editControls">
|
||||
<button class="_button" :class="[$style.previewControlsButton, fillSquare ? $style.active : null]" @click="fillSquare = true"><i class="ti ti-pencil"></i></button>
|
||||
</div>
|
||||
<div class="_acrylic" :class="$style.previewControls">
|
||||
<button class="_button" :class="[$style.previewControlsButton, !enabled ? $style.active : null]" @click="enabled = false">Before</button>
|
||||
<button class="_button" :class="[$style.previewControlsButton, enabled ? $style.active : null]" @click="enabled = true">After</button>
|
||||
|
@ -212,6 +215,100 @@ watch(enabled, () => {
|
|||
renderer.render();
|
||||
}
|
||||
});
|
||||
|
||||
const fillSquare = ref(false);
|
||||
|
||||
function onImagePointerdown(ev: PointerEvent) {
|
||||
if (canvasEl.value == null || imageBitmap == null || !fillSquare.value) return;
|
||||
|
||||
const AW = canvasEl.value.clientWidth;
|
||||
const AH = canvasEl.value.clientHeight;
|
||||
const BW = imageBitmap.width;
|
||||
const BH = imageBitmap.height;
|
||||
|
||||
let xOffset = 0;
|
||||
let yOffset = 0;
|
||||
|
||||
if (AW / AH < BW / BH) { // 横長
|
||||
yOffset = AH - BH * (AW / BW);
|
||||
} else { // 縦長
|
||||
xOffset = AW - BW * (AH / BH);
|
||||
}
|
||||
|
||||
xOffset /= 2;
|
||||
yOffset /= 2;
|
||||
|
||||
let startX = ev.offsetX - xOffset;
|
||||
let startY = ev.offsetY - yOffset;
|
||||
|
||||
if (AW / AH < BW / BH) { // 横長
|
||||
startX = startX / (Math.max(AW, AH) / Math.max(BH / BW, 1));
|
||||
startY = startY / (Math.max(AW, AH) / Math.max(BW / BH, 1));
|
||||
} else { // 縦長
|
||||
startX = startX / (Math.min(AW, AH) / Math.max(BH / BW, 1));
|
||||
startY = startY / (Math.min(AW, AH) / Math.max(BW / BH, 1));
|
||||
}
|
||||
|
||||
const id = genId();
|
||||
layers.push({
|
||||
id,
|
||||
fxId: 'fillSquare',
|
||||
params: {
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
scaleX: 0.1,
|
||||
scaleY: 0.1,
|
||||
angle: 0,
|
||||
opacity: 1,
|
||||
color: [1, 1, 1],
|
||||
},
|
||||
});
|
||||
|
||||
_move(ev.offsetX, ev.offsetY);
|
||||
|
||||
function _move(pointerX: number, pointerY: number) {
|
||||
let x = pointerX - xOffset;
|
||||
let y = pointerY - yOffset;
|
||||
|
||||
if (AW / AH < BW / BH) { // 横長
|
||||
x = x / (Math.max(AW, AH) / Math.max(BH / BW, 1));
|
||||
y = y / (Math.max(AW, AH) / Math.max(BW / BH, 1));
|
||||
} else { // 縦長
|
||||
x = x / (Math.min(AW, AH) / Math.max(BH / BW, 1));
|
||||
y = y / (Math.min(AW, AH) / Math.max(BW / BH, 1));
|
||||
}
|
||||
|
||||
const scaleX = Math.abs(x - startX);
|
||||
const scaleY = Math.abs(y - startY);
|
||||
|
||||
const layerIndex = layers.findIndex((l) => l.id === id);
|
||||
const layer = layerIndex !== -1 ? layers[layerIndex] : null;
|
||||
if (layer != null) {
|
||||
layer.params.offsetX = (x + startX) - 1;
|
||||
layer.params.offsetY = (y + startY) - 1;
|
||||
layer.params.scaleX = scaleX;
|
||||
layer.params.scaleY = scaleY;
|
||||
layers[layerIndex] = layer;
|
||||
}
|
||||
}
|
||||
|
||||
function move(ev: PointerEvent) {
|
||||
_move(ev.offsetX, ev.offsetY);
|
||||
}
|
||||
|
||||
function up() {
|
||||
canvasEl.value?.removeEventListener('pointermove', move);
|
||||
canvasEl.value?.removeEventListener('pointerup', up);
|
||||
canvasEl.value?.removeEventListener('pointercancel', up);
|
||||
canvasEl.value?.releasePointerCapture(ev.pointerId);
|
||||
|
||||
fillSquare.value = false;
|
||||
}
|
||||
|
||||
canvasEl.value.addEventListener('pointermove', move);
|
||||
canvasEl.value.addEventListener('pointerup', up);
|
||||
canvasEl.value.setPointerCapture(ev.pointerId);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style module>
|
||||
|
@ -251,6 +348,18 @@ watch(enabled, () => {
|
|||
font-size: 85%;
|
||||
}
|
||||
|
||||
.editControls {
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
bottom: 8px;
|
||||
left: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 6px 10px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.previewControls {
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
|
@ -283,9 +392,11 @@ watch(enabled, () => {
|
|||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 20px;
|
||||
width: -webkit-fill-available;
|
||||
width: stretch;
|
||||
height: -webkit-fill-available;
|
||||
height: stretch;
|
||||
margin: 20px;
|
||||
box-sizing: border-box;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ export const navbarItemDef = reactive({
|
|||
to: '/channels',
|
||||
},
|
||||
chat: {
|
||||
title: i18n.ts.chat,
|
||||
title: i18n.ts.directMessage_short,
|
||||
icon: 'ti ti-messages',
|
||||
to: '/chat',
|
||||
show: computed(() => $i != null && $i.policies.chatAvailability !== 'unavailable'),
|
||||
|
|
|
@ -48,7 +48,7 @@ const headerTabs = computed(() => [{
|
|||
}]);
|
||||
|
||||
definePage(() => ({
|
||||
title: i18n.ts.chat + ' (beta)',
|
||||
title: i18n.ts.directMessage,
|
||||
icon: 'ti ti-messages',
|
||||
}));
|
||||
</script>
|
||||
|
|
|
@ -46,6 +46,6 @@ onMounted(() => {
|
|||
});
|
||||
|
||||
definePage({
|
||||
title: i18n.ts.chat,
|
||||
title: i18n.ts.directMessage,
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -421,7 +421,7 @@ const tab = ref('chat');
|
|||
|
||||
const headerTabs = computed(() => room.value ? [{
|
||||
key: 'chat',
|
||||
title: i18n.ts.chat,
|
||||
title: i18n.ts._chat.messages,
|
||||
icon: 'ti ti-messages',
|
||||
}, {
|
||||
key: 'members',
|
||||
|
@ -437,7 +437,7 @@ const headerTabs = computed(() => room.value ? [{
|
|||
icon: 'ti ti-info-circle',
|
||||
}] : [{
|
||||
key: 'chat',
|
||||
title: i18n.ts.chat,
|
||||
title: i18n.ts._chat.messages,
|
||||
icon: 'ti ti-messages',
|
||||
}, {
|
||||
key: 'search',
|
||||
|
@ -466,12 +466,12 @@ definePage(computed(() => {
|
|||
};
|
||||
} else {
|
||||
return {
|
||||
title: i18n.ts.chat,
|
||||
title: i18n.ts.directMessage,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
title: i18n.ts.chat,
|
||||
title: i18n.ts.directMessage,
|
||||
};
|
||||
}
|
||||
}));
|
||||
|
|
|
@ -414,7 +414,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template v-if="$i.policies.chatAvailability !== 'unavailable'">
|
||||
<SearchMarker v-slot="slotProps" :keywords="['chat', 'messaging']">
|
||||
<MkFolder :defaultOpen="slotProps.isParentOfTarget">
|
||||
<template #label><SearchLabel>{{ i18n.ts.chat }}</SearchLabel></template>
|
||||
<template #label><SearchLabel>{{ i18n.ts.directMessage }}</SearchLabel></template>
|
||||
<template #icon><SearchIcon><i class="ti ti-messages"></i></SearchIcon></template>
|
||||
|
||||
<div class="_gaps_s">
|
||||
|
|
|
@ -74,7 +74,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
|
||||
<SearchMarker :keywords="['chat']">
|
||||
<FormSection>
|
||||
<template #label><SearchLabel>{{ i18n.ts.chat }}</SearchLabel></template>
|
||||
<template #label><SearchLabel>{{ i18n.ts.directMessage }}</SearchLabel></template>
|
||||
|
||||
<div class="_gaps_m">
|
||||
<MkInfo v-if="$i.policies.chatAvailability === 'unavailable'">{{ i18n.ts._chat.chatNotAvailableForThisAccountOrServer }}</MkInfo>
|
||||
|
|
|
@ -376,8 +376,8 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: Router
|
|||
//}
|
||||
|
||||
menuItems.push({ type: 'divider' }, {
|
||||
icon: 'ti ti-mail',
|
||||
text: i18n.ts.sendMessage,
|
||||
icon: 'ti ti-pencil-heart',
|
||||
text: i18n.ts.createUserSpecifiedNote,
|
||||
action: () => {
|
||||
const canonical = user.host === null ? `@${user.username}` : `@${user.username}@${user.host}`;
|
||||
os.post({ specified: user, initialText: `${canonical} ` });
|
||||
|
|
|
@ -18,6 +18,7 @@ import { FX_stripe } from './fxs/stripe.js';
|
|||
import { FX_threshold } from './fxs/threshold.js';
|
||||
import { FX_zoomLines } from './fxs/zoomLines.js';
|
||||
import { FX_blockNoise } from './fxs/blockNoise.js';
|
||||
import { FX_fillSquare } from './fxs/fillSquare.js';
|
||||
import type { ImageEffectorFx } from './ImageEffector.js';
|
||||
|
||||
export const FXS = [
|
||||
|
@ -36,4 +37,5 @@ export const FXS = [
|
|||
FX_chromaticAberration,
|
||||
FX_tearing,
|
||||
FX_blockNoise,
|
||||
FX_fillSquare,
|
||||
] as const satisfies ImageEffectorFx<string, any>[];
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { defineImageEffectorFx } from '../ImageEffector.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
||||
const shader = `#version 300 es
|
||||
precision mediump float;
|
||||
|
||||
const float PI = 3.141592653589793;
|
||||
const float TWO_PI = 6.283185307179586;
|
||||
const float HALF_PI = 1.5707963267948966;
|
||||
|
||||
in vec2 in_uv;
|
||||
uniform sampler2D in_texture;
|
||||
uniform vec2 in_resolution;
|
||||
uniform vec2 u_offset;
|
||||
uniform vec2 u_scale;
|
||||
uniform float u_angle;
|
||||
uniform vec3 u_color;
|
||||
uniform float u_opacity;
|
||||
out vec4 out_color;
|
||||
|
||||
void main() {
|
||||
vec4 in_color = texture(in_texture, in_uv);
|
||||
//float x_ratio = max(in_resolution.x / in_resolution.y, 1.0);
|
||||
//float y_ratio = max(in_resolution.y / in_resolution.x, 1.0);
|
||||
|
||||
float angle = -(u_angle * PI);
|
||||
vec2 centeredUv = in_uv - vec2(0.5, 0.5) - u_offset;
|
||||
vec2 rotatedUV = vec2(
|
||||
centeredUv.x * cos(angle) - centeredUv.y * sin(angle),
|
||||
centeredUv.x * sin(angle) + centeredUv.y * cos(angle)
|
||||
) + u_offset;
|
||||
|
||||
bool isInside = rotatedUV.x > u_offset.x - u_scale.x && rotatedUV.x < u_offset.x + u_scale.x && rotatedUV.y > u_offset.y - u_scale.y && rotatedUV.y < u_offset.y + u_scale.y;
|
||||
|
||||
out_color = isInside ? vec4(
|
||||
mix(in_color.r, u_color.r, u_opacity),
|
||||
mix(in_color.g, u_color.g, u_opacity),
|
||||
mix(in_color.b, u_color.b, u_opacity),
|
||||
in_color.a
|
||||
) : in_color;
|
||||
}
|
||||
`;
|
||||
|
||||
export const FX_fillSquare = defineImageEffectorFx({
|
||||
id: 'fillSquare',
|
||||
name: i18n.ts._imageEffector._fxs.fillSquare,
|
||||
shader,
|
||||
uniforms: ['offset', 'scale', 'angle', 'color', 'opacity'] as const,
|
||||
params: {
|
||||
offsetX: {
|
||||
label: i18n.ts._imageEffector._fxProps.offset + ' X',
|
||||
type: 'number',
|
||||
default: 0.0,
|
||||
min: -1.0,
|
||||
max: 1.0,
|
||||
step: 0.01,
|
||||
toViewValue: v => Math.round(v * 100) + '%',
|
||||
},
|
||||
offsetY: {
|
||||
label: i18n.ts._imageEffector._fxProps.offset + ' Y',
|
||||
type: 'number',
|
||||
default: 0.0,
|
||||
min: -1.0,
|
||||
max: 1.0,
|
||||
step: 0.01,
|
||||
toViewValue: v => Math.round(v * 100) + '%',
|
||||
},
|
||||
scaleX: {
|
||||
label: i18n.ts._imageEffector._fxProps.scale + ' X',
|
||||
type: 'number',
|
||||
default: 0.5,
|
||||
min: 0.0,
|
||||
max: 1.0,
|
||||
step: 0.01,
|
||||
toViewValue: v => Math.round(v * 100) + '%',
|
||||
},
|
||||
scaleY: {
|
||||
label: i18n.ts._imageEffector._fxProps.scale + ' Y',
|
||||
type: 'number',
|
||||
default: 0.5,
|
||||
min: 0.0,
|
||||
max: 1.0,
|
||||
step: 0.01,
|
||||
toViewValue: v => Math.round(v * 100) + '%',
|
||||
},
|
||||
angle: {
|
||||
label: i18n.ts._imageEffector._fxProps.angle,
|
||||
type: 'number',
|
||||
default: 0,
|
||||
min: -1.0,
|
||||
max: 1.0,
|
||||
step: 0.01,
|
||||
toViewValue: v => Math.round(v * 90) + '°',
|
||||
},
|
||||
color: {
|
||||
label: i18n.ts._imageEffector._fxProps.color,
|
||||
type: 'color',
|
||||
default: [1, 1, 1],
|
||||
},
|
||||
opacity: {
|
||||
label: i18n.ts._imageEffector._fxProps.opacity,
|
||||
type: 'number',
|
||||
default: 1.0,
|
||||
min: 0.0,
|
||||
max: 1.0,
|
||||
step: 0.01,
|
||||
toViewValue: v => Math.round(v * 100) + '%',
|
||||
},
|
||||
},
|
||||
main: ({ gl, u, params }) => {
|
||||
gl.uniform2f(u.offset, params.offsetX / 2, params.offsetY / 2);
|
||||
gl.uniform2f(u.scale, params.scaleX / 2, params.scaleY / 2);
|
||||
gl.uniform1f(u.angle, params.angle / 2);
|
||||
gl.uniform3f(u.color, params.color[0], params.color[1], params.color[2]);
|
||||
gl.uniform1f(u.opacity, params.opacity);
|
||||
},
|
||||
});
|
Loading…
Reference in New Issue