Skip to content

Conversation

@tokusa-inori
Copy link
Contributor

@tokusa-inori tokusa-inori commented Mar 18, 2025

取り込みご検討をお願いいたします。

関連するイシュー

なし

やったこと

キャラクタープリセット機能の追加

できるようになること(ユーザ目線)

設定画面からクリックで呼び出し、キャラクタープロンプトへ上書きできる。
Shiftキーを押しながらプリセットを選ぶと、現在のキャラクタープロンプトがプリセットに保存される。
Cmd + Shift + 15 (Mac) / Ctrl + Shift + 15 (Windows)でショートカットができる。

スクリーンショット 2025-03-18 160953
スクリーンショット (3)

動作確認

キャラクタープロンプトが上書きされることを確認。キャラクタープリセットが上書きできることを確認
動作確認環境: Windows11 MS Edge localLLM

その他

ショートカットの実装をindex.tsxで行っています。menu.tsxで実装した際、process.envが呼び出せなかったためです。独自のファイルを作成してもprocess.envを呼び出せず、index.tsxで正常な動作を確認できた形になります。
なにか気づいた点がありましたらメッセージをお願いします。

プリセット名の変更機能は実装していません。ただしtranslation.jsonにあるプリセット名(Characterpreset1など)をいじくれば変更できます。

Summary by CodeRabbit

  • 新機能

    • キャラクタープリセット機能が追加され、画面上の新しい設定セクションおよびキーボードショートカット(Cmd+Shift+1~5/Ctrl+Shift+1~5)でキャラクターのプロンプトを迅速に切り替えられるようになりました。
    • プリセット選択時には、ツールチップとトースト通知で操作のフィードバックが提供されます。
    • 新しいキャラクタープリセットメニューコンポーネントが導入され、ユーザーがプリセットを選択しやすくなりました。
  • バグ修正

    • 既存のエラーメッセージや設定が一部修正され、JSONフォーマットの整合性が向上しました。
  • ドキュメント

    • ガイドと各言語の翻訳に、キャラクタープリセットの設定方法およびショートカット操作の詳細が追加され、より分かりやすくなりました。

@vercel
Copy link

vercel bot commented Mar 18, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
aituber-kit ✅ Ready (Inspect) Visit Preview 💬 Add feedback Mar 20, 2025 10:22am

@coderabbitai
Copy link

coderabbitai bot commented Mar 18, 2025

Walkthrough

今回の変更では、各ロケールの翻訳ファイルにキャラクタープリセット用の新規エントリ(characterpresetInfoCharacterpreset1Characterpreset5PresetSwitching)が追加され、既存のキー(例:SpeechRecognitionErrorNoSpeechDetected)に微調整が施されました。さらに、キャラクターコンポーネントと設定ストアに新たなプリセットロジックとツールチップ管理が実装され、ホームページではキーボードショートカットによるプリセット切り替えおよびトースト通知が追加されています。ドキュメントも新しい環境変数と解説が統合されています。

Changes

File(s) 変更の概要
locales/{ar,de,en,es,fr,hi,it,ja,ko,pl,pt,ru,th,vi,zh}/translation.json キャラクタープリセット用の新規キー characterpresetInfoCharacterpreset1Characterpreset5PresetSwitching を追加。既存キー(SpeechRecognitionError 等)の末尾にカンマ追加等、微調整を実施。
src/components/settings/character.tsx キャラクタープリセットのUIを実装。新たに characterPresets 配列、ツールチップ用の状態(tooltipTexttooltip)、および handleMouseMovehandleMouseLeave イベントハンドラが追加され、各プリセットをボタンとしてレンダリング。
src/features/stores/settings.ts Character インターフェイスに characterPreset1characterPreset5 の各プロパティを追加。環境変数またはデフォルトからの初期値設定を含め、状態管理ロジックを更新。
src/pages/index.tsx キーボードイベントハンドリングを追加し、Shift + Cmd/Ctrl + 1~5 の組み合わせで該当プリセットに切り替え。設定ストアの systemPrompt を更新し、 toastStore によるトースト通知を実施。
website/document/…/guide/character/common.md 英語、日本語(または中国語)ドキュメントにおいて、NEXT_PUBLIC_CHARACTER_PRESET1NEXT_PUBLIC_CHARACTER_PRESET5 の環境変数と、キャラクタープリセットの利用方法に関する新セクションを追加。

Sequence Diagram(s)

sequenceDiagram
    participant U as ユーザー
    participant HP as Homeコンポーネント
    participant SS as settingsStore
    participant TS as toastStore

    U->>HP: ショートカットキー (Shift + Cmd/Ctrl + 1~5) を入力
    HP->>HP: キー入力を解析・該当プリセットを決定
    HP->>SS: systemPromptを選択プリセットに更新
    HP->>TS: PresetSwitchingメッセージ付きトースト通知の追加
    TS-->>U: 通知を表示
Loading
sequenceDiagram
    participant U as ユーザー
    participant CC as Characterコンポーネント

    U->>CC: マウス移動イベント
    CC->>CC: handleMouseMoveでツールチップ位置・内容更新
    U->>CC: マウス離脱イベント
    CC->>CC: handleMouseLeaveでツールチップ非表示処理
Loading

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between d8e888b and bea09c6.

📒 Files selected for processing (9)
  • .env.example (1 hunks)
  • locales/de/translation.json (3 hunks)
  • locales/fr/translation.json (3 hunks)
  • locales/it/translation.json (3 hunks)
  • locales/th/translation.json (3 hunks)
  • src/features/stores/settings.ts (3 hunks)
  • website/document/en/guide/character/common.md (2 hunks)
  • website/document/guide/character/common.md (2 hunks)
  • website/document/zh/guide/character/common.md (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • locales/fr/translation.json
  • locales/th/translation.json
  • website/document/en/guide/character/common.md
  • locales/it/translation.json
🔇 Additional comments (10)
website/document/zh/guide/character/common.md (2)

19-31: 環境変数の追加が適切に行われています

各種キャラクタープリセット用の環境変数が適切に追加されています。プリセット名とプリセット内容の両方が含まれており、ドキュメントとしての役割を十分に果たしています。


53-55: キャラクタープリセット機能の説明が明確に追加されています

ユーザーがショートカットキーを使って複数のキャラクタープロンプトを保存・呼び出せることが適切に説明されています。Mac/Windowsの両方のキーボードショートカットが記載されており、ユーザーフレンドリーです。

website/document/guide/character/common.md (2)

19-31: 環境変数の追加が日本語で適切に行われています

各キャラクタープリセット用の環境変数が日本語で適切に追加されています。カスタムプリセット名とキャラクタープリセットの両方が含まれており、ユーザーにとって理解しやすいドキュメントになっています。


53-55: キャラクタープリセット機能の説明が日本語で明確です

ユーザーがキャラクタープロンプトを複数保存できることと、ショートカットキーを使った呼び出し方法が明確に説明されています。この説明は日本語ユーザーにとって理解しやすく、機能の使用を促進するものです。

.env.example (1)

45-57: 環境変数の例が適切に追加されています

カスタムプリセット名とキャラクタープリセットの環境変数が適切に追加されています。コメントも日本語と英語の両方で記載されており、国際的なユーザーにとって理解しやすい構成になっています。

デフォルト値として「あなたはニケという名前のAIアシスタントです。」という基本的なプロンプトが設定されているのは適切です。これにより、ユーザーは自分の好みに合わせてカスタマイズする際の参考にすることができます。

locales/de/translation.json (2)

57-62: キャラクタープリセット関連の翻訳が適切に追加されています

ドイツ語のキャラクタープリセット関連の翻訳が適切に追加されています。プリセットの切り替え方法や保存方法の説明も含まれており、ドイツ語を使用するユーザーにとって便利です。


205-206: プリセット切り替え通知の翻訳が適切に追加されています

プリセット切り替え時の通知文言「Wechsel zu {{presetName}}.」が適切に追加されています。これにより、ユーザーはプリセット切り替え時に適切なフィードバックを受け取ることができます。

src/features/stores/settings.ts (3)

124-136: Character インターフェースへのプリセット関連のプロパティ追加が適切です

Character インターフェースに以下のプロパティが適切に追加されています:

  • キャラクタープリセット(characterPreset1〜5): 各プリセットの内容
  • カスタムプリセット名(customPresetName1〜5): プリセットの表示名
  • 選択中のプリセットインデックス(selectedPresetIndex): 現在選択されているプリセット

これらの追加により、キャラクタープリセット機能の状態を適切に管理できる構成になっています。


279-299: settingsStore へのプリセット関連のプロパティ初期化が適切です

追加されたキャラクタープリセット関連のプロパティが環境変数から適切に初期化されています。環境変数が存在しない場合のフォールバック値も適切に設定されており、堅牢な実装になっています。

特に以下の点が良いです:

  • キャラクタープリセットのデフォルト値として SYSTEM_PROMPT を使用している点
  • カスタムプリセット名にデフォルト値を設定している点
  • selectedPresetIndex を 0 で初期化している点

439-449: partialize 関数へのプリセット関連のプロパティ追加が適切です

状態永続化のための partialize 関数に、新しく追加されたプリセット関連のプロパティが適切に追加されています。これにより、プリセット関連の設定がブラウザのローカルストレージに保存され、ページをリロードしても設定が維持されるようになっています。


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

return () => {
window.removeEventListener("keydown", handleKeyDown);
};
}, []);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ショートカットの実装をindex.tsxで行っています。menu.tsxで実装した際、process.envが呼び出せなかったためです。独自のファイルを作成してもprocess.envを呼び出せず、index.tsxで正常な動作を確認できた形になります。
なにか気づいた点がありましたらメッセージをお願いします。

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (5)
website/document/en/guide/character/common.md (1)

18-25: キャラクタープリセット環境変数の追加について
追加された「# character preset」セクションでは、5種類の環境変数(NEXT_PUBLIC_CHARACTER_PRESET1~5)が導入されています。全て同一の文字列値 ("You are an AI assistant named Nike.") が設定されていますが、意図的なものであれば問題ありません。将来的に各プリセットに異なる内容を設定する可能性がある場合は、その点も確認してください。

src/components/settings/character.tsx (2)

325-331: プリセットの実装を改善する提案

プリセットの実装は機能的ですが、以下の改善を提案します:

  1. プリセットのキーを定数として定義
  2. 型安全性の追加
+const CHARACTER_PRESET_KEYS = {
+  PRESET_1: 'characterPreset1',
+  PRESET_2: 'characterPreset2',
+  PRESET_3: 'characterPreset3',
+  PRESET_4: 'characterPreset4',
+  PRESET_5: 'characterPreset5',
+} as const;
+
+type CharacterPreset = {
+  key: keyof typeof CHARACTER_PRESET_KEYS;
+  value: string;
+};

-const characterPresets = [
+const characterPresets: CharacterPreset[] = [
   { key: "characterPreset1", value: settingsStore((s) => s.characterPreset1) },
   { key: "characterPreset2", value: settingsStore((s) => s.characterPreset2) },
   { key: "characterPreset3", value: settingsStore((s) => s.characterPreset3) },
   { key: "characterPreset4", value: settingsStore((s) => s.characterPreset4) },
   { key: "characterPreset5", value: settingsStore((s) => s.characterPreset5) },
];
🧰 Tools
🪛 ESLint

[error] 326-326: Replace ·key:·"characterPreset1",·value:·settingsStore((s)·=>·s.characterPreset1) with ⏎······key:·'characterPreset1',⏎······value:·settingsStore((s)·=>·s.characterPreset1),⏎···

(prettier/prettier)


[error] 327-327: Replace ·key:·"characterPreset2",·value:·settingsStore((s)·=>·s.characterPreset2) with ⏎······key:·'characterPreset2',⏎······value:·settingsStore((s)·=>·s.characterPreset2),⏎···

(prettier/prettier)


[error] 328-328: Replace ·key:·"characterPreset3",·value:·settingsStore((s)·=>·s.characterPreset3) with ⏎······key:·'characterPreset3',⏎······value:·settingsStore((s)·=>·s.characterPreset3),⏎···

(prettier/prettier)


[error] 329-329: Replace ·key:·"characterPreset4",·value:·settingsStore((s)·=>·s.characterPreset4) with ⏎······key:·'characterPreset4',⏎······value:·settingsStore((s)·=>·s.characterPreset4),⏎···

(prettier/prettier)


[error] 330-330: Replace ·key:·"characterPreset5",·value:·settingsStore((s)·=>·s.characterPreset5) with ⏎······key:·'characterPreset5',⏎······value:·settingsStore((s)·=>·s.characterPreset5),⏎···

(prettier/prettier)


[error] 331-331: Delete ;

(prettier/prettier)


332-353: ツールチップのロジックをカスタムフックに抽出

ツールチップの状態管理とハンドラーをカスタムフックに抽出することで、コードの再利用性と保守性が向上します:

+interface TooltipState {
+  x: number;
+  y: number;
+  visible: boolean;
+}
+
+const useTooltip = (offsetX: number, offsetY: number) => {
+  const [tooltipText, setTooltipText] = useState("");
+  const [tooltip, setTooltip] = useState<TooltipState>({
+    x: 0,
+    y: 0,
+    visible: false
+  });
+
+  const handleMouseMove = useCallback((e: React.MouseEvent) => {
+    setTooltip({
+      x: e.clientX + offsetX,
+      y: e.clientY + offsetY,
+      visible: true
+    });
+  }, [offsetX, offsetY]);
+
+  const handleMouseLeave = useCallback(() => {
+    setTooltip(prev => ({ ...prev, visible: false }));
+  }, []);
+
+  return {
+    tooltipText,
+    setTooltipText,
+    tooltip,
+    handleMouseMove,
+    handleMouseLeave
+  };
+};

このカスタムフックを使用することで、コンポーネントのコードがよりクリーンになります。

🧰 Tools
🪛 ESLint

[error] 332-332: Replace ""); with '')

(prettier/prettier)


[error] 334-334: Replace ·x:·number;·y:·number;·visible:·boolean with ⏎····x:·number⏎····y:·number⏎····visible:·boolean⏎·

(prettier/prettier)


[error] 337-337: Insert ,

(prettier/prettier)


[error] 338-338: Delete ;

(prettier/prettier)


[error] 344-344: Delete ;

(prettier/prettier)


[error] 345-345: Delete ;

(prettier/prettier)


[error] 348-348: Replace ·x:·e.clientX·+·tooltipOffsetX,·y:·e.clientY·+·tooltipOffsetY,·visible:·true·}); with ⏎······x:·e.clientX·+·tooltipOffsetX,⏎······y:·e.clientY·+·tooltipOffsetY,⏎······visible:·true,⏎····})

(prettier/prettier)


[error] 349-349: Delete ;

(prettier/prettier)


[error] 352-352: Delete ;

(prettier/prettier)


[error] 353-353: Delete ;

(prettier/prettier)

src/features/stores/settings.ts (1)

417-421: フォーマットの修正が必要です

静的解析ツールが指摘するように、行末の余分なスペースを削除する必要があります。

以下の修正を提案します:

-        characterPreset2: state.characterPreset2, 
-        characterPreset3: state.characterPreset3, 
-        characterPreset4: state.characterPreset4, 
-        characterPreset5: state.characterPreset5, 
+        characterPreset2: state.characterPreset2,
+        characterPreset3: state.characterPreset3,
+        characterPreset4: state.characterPreset4,
+        characterPreset5: state.characterPreset5,
🧰 Tools
🪛 ESLint

[error] 418-418: Delete ·

(prettier/prettier)


[error] 419-419: Delete ·

(prettier/prettier)


[error] 420-420: Delete ·

(prettier/prettier)


[error] 421-421: Delete ·

(prettier/prettier)

src/pages/index.tsx (1)

32-38: characterPresetsの定義をより効率的に実装することを提案します。

配列の定義をより簡潔にできます。また、型安全性も向上させることができます。

以下の実装を提案します:

-  const characterPresets = [
-    { key: "characterPreset1", value: settingsStore((s) => s.characterPreset1) },
-    { key: "characterPreset2", value: settingsStore((s) => s.characterPreset2) },
-    { key: "characterPreset3", value: settingsStore((s) => s.characterPreset3) },
-    { key: "characterPreset4", value: settingsStore((s) => s.characterPreset4) },
-    { key: "characterPreset5", value: settingsStore((s) => s.characterPreset5) },
-  ];
+  const characterPresets = Array.from({ length: 5 }, (_, i) => ({
+    key: `characterPreset${i + 1}`,
+    value: settingsStore((s) => s[`characterPreset${i + 1}`])
+  }));
🧰 Tools
🪛 ESLint

[error] 33-33: Replace ·key:·"characterPreset1",·value:·settingsStore((s)·=>·s.characterPreset1) with ⏎······key:·'characterPreset1',⏎······value:·settingsStore((s)·=>·s.characterPreset1),⏎···

(prettier/prettier)


[error] 34-34: Replace ·key:·"characterPreset2",·value:·settingsStore((s)·=>·s.characterPreset2) with ⏎······key:·'characterPreset2',⏎······value:·settingsStore((s)·=>·s.characterPreset2),⏎···

(prettier/prettier)


[error] 35-35: Replace ·key:·"characterPreset3",·value:·settingsStore((s)·=>·s.characterPreset3) with ⏎······key:·'characterPreset3',⏎······value:·settingsStore((s)·=>·s.characterPreset3),⏎···

(prettier/prettier)


[error] 36-36: Replace ·key:·"characterPreset4",·value:·settingsStore((s)·=>·s.characterPreset4) with ⏎······key:·'characterPreset4',⏎······value:·settingsStore((s)·=>·s.characterPreset4),⏎···

(prettier/prettier)


[error] 37-37: Replace ·key:·"characterPreset5",·value:·settingsStore((s)·=>·s.characterPreset5) with ⏎······key:·'characterPreset5',⏎······value:·settingsStore((s)·=>·s.characterPreset5),⏎···

(prettier/prettier)


[error] 38-38: Delete ;

(prettier/prettier)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 462bf24 and 4220647.

📒 Files selected for processing (21)
  • locales/ar/translation.json (2 hunks)
  • locales/de/translation.json (2 hunks)
  • locales/en/translation.json (2 hunks)
  • locales/es/translation.json (2 hunks)
  • locales/fr/translation.json (2 hunks)
  • locales/hi/translation.json (2 hunks)
  • locales/it/translation.json (2 hunks)
  • locales/ja/translation.json (2 hunks)
  • locales/ko/translation.json (2 hunks)
  • locales/pl/translation.json (2 hunks)
  • locales/pt/translation.json (2 hunks)
  • locales/ru/translation.json (2 hunks)
  • locales/th/translation.json (2 hunks)
  • locales/vi/translation.json (2 hunks)
  • locales/zh/translation.json (2 hunks)
  • src/components/settings/character.tsx (2 hunks)
  • src/features/stores/settings.ts (3 hunks)
  • src/pages/index.tsx (3 hunks)
  • website/document/en/guide/character/common.md (2 hunks)
  • website/document/guide/character/common.md (2 hunks)
  • website/document/zh/guide/character/common.md (2 hunks)
🧰 Additional context used
🪛 ESLint
src/components/settings/character.tsx

[error] 326-326: Replace ·key:·"characterPreset1",·value:·settingsStore((s)·=>·s.characterPreset1) with ⏎······key:·'characterPreset1',⏎······value:·settingsStore((s)·=>·s.characterPreset1),⏎···

(prettier/prettier)


[error] 327-327: Replace ·key:·"characterPreset2",·value:·settingsStore((s)·=>·s.characterPreset2) with ⏎······key:·'characterPreset2',⏎······value:·settingsStore((s)·=>·s.characterPreset2),⏎···

(prettier/prettier)


[error] 328-328: Replace ·key:·"characterPreset3",·value:·settingsStore((s)·=>·s.characterPreset3) with ⏎······key:·'characterPreset3',⏎······value:·settingsStore((s)·=>·s.characterPreset3),⏎···

(prettier/prettier)


[error] 329-329: Replace ·key:·"characterPreset4",·value:·settingsStore((s)·=>·s.characterPreset4) with ⏎······key:·'characterPreset4',⏎······value:·settingsStore((s)·=>·s.characterPreset4),⏎···

(prettier/prettier)


[error] 330-330: Replace ·key:·"characterPreset5",·value:·settingsStore((s)·=>·s.characterPreset5) with ⏎······key:·'characterPreset5',⏎······value:·settingsStore((s)·=>·s.characterPreset5),⏎···

(prettier/prettier)


[error] 331-331: Delete ;

(prettier/prettier)


[error] 332-332: Replace ""); with '')

(prettier/prettier)


[error] 334-334: Replace ·x:·number;·y:·number;·visible:·boolean with ⏎····x:·number⏎····y:·number⏎····visible:·boolean⏎·

(prettier/prettier)


[error] 337-337: Insert ,

(prettier/prettier)


[error] 338-338: Delete ;

(prettier/prettier)


[error] 344-344: Delete ;

(prettier/prettier)


[error] 345-345: Delete ;

(prettier/prettier)


[error] 348-348: Replace ·x:·e.clientX·+·tooltipOffsetX,·y:·e.clientY·+·tooltipOffsetY,·visible:·true·}); with ⏎······x:·e.clientX·+·tooltipOffsetX,⏎······y:·e.clientY·+·tooltipOffsetY,⏎······visible:·true,⏎····})

(prettier/prettier)


[error] 349-349: Delete ;

(prettier/prettier)


[error] 352-352: Delete ;

(prettier/prettier)


[error] 353-353: Delete ;

(prettier/prettier)


[error] 532-532: Delete ;

(prettier/prettier)


[error] 533-533: Delete ;

(prettier/prettier)


[error] 535-535: Delete ;

(prettier/prettier)


[error] 536-536: Delete ;

(prettier/prettier)


[error] 540-540: Delete ;

(prettier/prettier)


[error] 541-541: Delete ;

(prettier/prettier)


[error] 544-544: Delete ;

(prettier/prettier)


[error] 545-545: Replace ""); with '')

(prettier/prettier)

src/pages/index.tsx

[error] 33-33: Replace ·key:·"characterPreset1",·value:·settingsStore((s)·=>·s.characterPreset1) with ⏎······key:·'characterPreset1',⏎······value:·settingsStore((s)·=>·s.characterPreset1),⏎···

(prettier/prettier)


[error] 34-34: Replace ·key:·"characterPreset2",·value:·settingsStore((s)·=>·s.characterPreset2) with ⏎······key:·'characterPreset2',⏎······value:·settingsStore((s)·=>·s.characterPreset2),⏎···

(prettier/prettier)


[error] 35-35: Replace ·key:·"characterPreset3",·value:·settingsStore((s)·=>·s.characterPreset3) with ⏎······key:·'characterPreset3',⏎······value:·settingsStore((s)·=>·s.characterPreset3),⏎···

(prettier/prettier)


[error] 36-36: Replace ·key:·"characterPreset4",·value:·settingsStore((s)·=>·s.characterPreset4) with ⏎······key:·'characterPreset4',⏎······value:·settingsStore((s)·=>·s.characterPreset4),⏎···

(prettier/prettier)


[error] 37-37: Replace ·key:·"characterPreset5",·value:·settingsStore((s)·=>·s.characterPreset5) with ⏎······key:·'characterPreset5',⏎······value:·settingsStore((s)·=>·s.characterPreset5),⏎···

(prettier/prettier)


[error] 38-38: Delete ;

(prettier/prettier)


[error] 42-42: Delete ·

(prettier/prettier)


[error] 50-50: Delete ;

(prettier/prettier)


[error] 52-52: Delete ;

(prettier/prettier)


[error] 55-55: Replace ·systemPrompt:·characterPresets[keyNumber·-·1].value·}); with ⏎············systemPrompt:·characterPresets[keyNumber·-·1].value,⏎··········})

(prettier/prettier)


[error] 57-57: Replace ·presetName:·t(Characterpreset${keyNumber}) with ⏎··············presetName:·t(Characterpreset${keyNumber}),⏎···········

(prettier/prettier)


[error] 63-63: Delete ;

(prettier/prettier)


[error] 64-64: Delete ··

(prettier/prettier)


[error] 65-65: Replace "keydown",·handleKeyDown); with 'keydown',·handleKeyDown)

(prettier/prettier)


[error] 67-67: Replace "keydown",·handleKeyDown); with 'keydown',·handleKeyDown)

(prettier/prettier)


[error] 68-68: Delete ;

(prettier/prettier)


[error] 69-69: Delete ;

(prettier/prettier)

src/features/stores/settings.ts

[error] 273-273: Insert ⏎·······

(prettier/prettier)


[error] 274-274: Insert ⏎·······

(prettier/prettier)


[error] 275-275: Insert ⏎·······

(prettier/prettier)


[error] 276-276: Insert ⏎·······

(prettier/prettier)


[error] 277-277: Insert ⏎·······

(prettier/prettier)


[error] 418-418: Delete ·

(prettier/prettier)


[error] 419-419: Delete ·

(prettier/prettier)


[error] 420-420: Delete ·

(prettier/prettier)


[error] 421-421: Delete ·

(prettier/prettier)

🔇 Additional comments (27)
website/document/guide/character/common.md (1)

46-49: キャラクタープリセット説明セクションの追加について
「### キャラクタープリセット」セクションで、複数のキャラクタープロンプトを保存する方法とキーボードショートカット(Cmd + Shift + 15 / Ctrl + Shift + 15)の利用方法が明記されています。説明文も明瞭で読みやすく、ユーザー向けの手順として適切です。

locales/fr/translation.json (1)

57-62: 新規翻訳キー(フランス語)の追加について
フランス語の翻訳ファイルにおいて、「characterpresetInfo」及び「Characterpreset1」~「Characterpreset5」のキーが追加されています。文言は明確で、キーボードショートカットの説明も含んでおり、JSON構文も正しい状態です。

locales/ja/translation.json (2)

57-62: 新規翻訳キー(日本語)の追加について
日本語翻訳ファイルに、「characterpresetInfo」と「Characterpreset1」~「Characterpreset5」が追加されています。文言はユーザーにとって分かりやすく、設定項目として問題なく統一されています。


211-212: PresetSwitching メッセージの追加について
Toastsセクションにおいて、「PresetSwitching」キーが追加され、プリセット切り替え時の通知メッセージが適切に設定されています。プレースホルダー「{{presetName}}」も正しく使用されており、ユーザーへのフィードバックが明確です。

website/document/zh/guide/character/common.md (1)

18-24: 字元預設セクションの追加について
中国語のドキュメントにおいて、「# 字元預設」セクションが追加され、5種類の環境変数(NEXT_PUBLIC_CHARACTER_PRESET1~5)が定義されています。値は「您是一位名叫 Nique 的 AI 助理。」と設定されており、他言語版との一貫性も保たれています。

locales/ru/translation.json (2)

57-62: 新規キャラクタープリセットキーの追加について
新たに追加された "characterpresetInfo" と "Characterpreset1" ~ "Characterpreset5" は、ユーザーがキャラクタープリセット機能を直感的に理解できるよう、詳細な指示文と一貫した命名で記述されています。PRの目的に沿って実装されており、問題はありません。


205-206: Toasts セクションの更新について
"SpeechRecognitionError" の文言更新および新規追加された "PresetSwitching" キーは、ユーザーに対して適切なフィードバックを提供するために有効です。特に、プリセット切替の成功時に {{presetName}} を表示する実装が明確に伝わります。

locales/zh/translation.json (2)

57-62: キャラクタープリセット関連の新規エントリ(中国語)の実装について
"characterpresetInfo" および "Characterpreset1" ~ "Characterpreset5" の追加は、PRの仕様に沿っており、ユーザーへの操作説明が明確に伝わる内容です。中国語としての表現も一貫しており、内容に問題は見受けられません。


207-208: PresetSwitching キーの実装について
"PresetSwitching" キーが追加され、キャラクタープリセットの切り替え時に「切換至 {{presetName}}。」という通知が表示されるようになっており、ユーザーへのフィードバックが適切に実現されています。

locales/en/translation.json (2)

57-62: Character Preset Entries の追加(英語版)について
"characterpresetInfo" および "Characterpreset1" ~ "Characterpreset5" のエントリが正確に追加され、ユーザーに対してキャラクタープリセット機能の使い方を明確に説明しています。UIの一貫性と利便性が向上していると評価できます。


207-209: PresetSwitching キーの追加(英語版)について
Toasts セクションにおいて、新たに "PresetSwitching" キーが導入され、プリセットの切り替え時に "{{presetName}}" の情報を含む通知が行われるようになっています。この変更はフィードバック機能を強化しており、意図通りの動作が期待できます。

locales/es/translation.json (1)

57-62: キャラクタープリセットエントリの追加(スペイン語版)について
"characterpresetInfo" と "Characterpreset1" ~ "Characterpreset5" の追加により、スペイン語ユーザーにもキャラクタープリセット機能の説明が分かりやすく提示されています。命名規則と内容が一貫しており、正しい情報が伝わっています。

locales/ko/translation.json (2)

57-62: 캐릭터 프리셋 관련 신규 항목 추가(韓国語版)について
"characterpresetInfo" と "Characterpreset1" ~ "Characterpreset5" のエントリが新たに追加され、韓国語においても操作説明が明確に記述されています。表記や内容が一貫しており、機能実装の目的に適合しています。


207-208: PresetSwitching 키의 추가について
Toasts 섹션에 "PresetSwitching" 키가 추가되어, 프리셋 전환 시 "{{presetName}}으로 전환되었습니다."라는 알림이 표시되도록 구현되었습니다。この変更により、ユーザーへのフィ드バックが明確になり、ユーザビリティが向上しています。

locales/vi/translation.json (1)

57-62: 翻訳の実装は適切です

各言語ファイルでプリセット機能の翻訳が適切に実装されています。

locales/ar/translation.json (1)

57-62: 翻訳の実装は適切です

アラビア語のプリセット機能の翻訳が適切に実装されています。

locales/hi/translation.json (1)

57-62: 翻訳の実装は適切です

ヒンディー語のプリセット機能の翻訳が適切に実装されています。

src/features/stores/settings.ts (2)

126-130: インターフェースの実装は適切です

キャラクタープリセット機能のための新しいプロパティが適切に追加されています。


273-277: 環境変数の初期化は適切です

各プリセットがSYSTEM_PROMPTにフォールバックする実装は適切です。

🧰 Tools
🪛 ESLint

[error] 273-273: Insert ⏎·······

(prettier/prettier)


[error] 274-274: Insert ⏎·······

(prettier/prettier)


[error] 275-275: Insert ⏎·······

(prettier/prettier)


[error] 276-276: Insert ⏎·······

(prettier/prettier)


[error] 277-277: Insert ⏎·······

(prettier/prettier)

locales/th/translation.json (2)

57-62: 翻訳の実装は適切です

キャラクタープリセット機能の翻訳が適切に実装されています。各言語で一貫性が保たれています。


206-207: トースト通知の翻訳は適切です

プリセット切り替え時のトースト通知の翻訳が適切に実装されています。

locales/pt/translation.json (1)

57-62: 翻訳の実装が適切に行われています。

キャラクタープリセット機能に関する翻訳が完全に実装されており、キーボードショートカットの説明も明確です。

Also applies to: 205-206

locales/de/translation.json (1)

57-62: 翻訳の実装が適切に行われています。

キャラクタープリセット機能に関するドイツ語の翻訳が完全に実装されており、キーボードショートカットの説明も明確です。

Also applies to: 205-206

locales/pl/translation.json (2)

57-62: キャラクタープリセットの新規エントリ追加について
新たに追加されたキー("characterpresetInfo"、"Characterpreset1"~"Characterpreset5")は、ユーザーがキャラクタープリセットの機能を理解しやすいように、具体的な説明とショートカット情報を提供しており、非常に良い実装です。


206-207: エラーメッセージの更新について
"SpeechRecognitionError" の末尾のカンマ追加および新規に導入された "PresetSwitching" は、ユーザーに対するフィードバックを改善しており、一貫性も確保されています。

locales/it/translation.json (2)

57-62: キャラクタープリセット情報の追加について
イタリア語版にも、"characterpresetInfo" と "Characterpreset1"~"Characterpreset5" が追加され、ショートカットの操作方法が明確に記載されています。ユーザー向けの説明が分かりやすく、実装内容は適切です。


205-206: エラーメッセージの改善について
"SpeechRecognitionError" の表示内容と、新規に追加された "PresetSwitching" メッセージにより、エラー発生時のユーザーへの案内が強化されています。全体として翻訳の一貫性が保たれており、良好な変更です。

Comment on lines 40 to 69
useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if ((event.metaKey || event.ctrlKey) && event.shiftKey ) {
// shiftキーを押しながら数字キーを押すためのマッピング
const keyMap: { [key: string]: number } = {
Digit1: 1,
Digit2: 2,
Digit3: 3,
Digit4: 4,
Digit5: 5,
};

const keyNumber = keyMap[event.code];

if (keyNumber) {
settingsStore.setState({ systemPrompt: characterPresets[keyNumber - 1].value });
toastStore.getState().addToast({
message: t('Toasts.PresetSwitching', { presetName: t(`Characterpreset${keyNumber}`) }),
type: 'info',
tag: `character-preset-switching-${keyNumber}`,
})
}
}
};

window.addEventListener("keydown", handleKeyDown);
return () => {
window.removeEventListener("keydown", handleKeyDown);
};
}, []);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

useEffectの依存配列とパフォーマンスの最適化を提案します。

  1. 空の依存配列は、t関数への参照が古くなる可能性があります。
  2. イベントハンドラーをメモ化することで、不要な再生成を防ぐことができます。

以下の実装を提案します:

+  const handleKeyDown = useCallback((event: KeyboardEvent) => {
+    if ((event.metaKey || event.ctrlKey) && event.shiftKey ) {
+      const keyMap: { [key: string]: number } = {
+        Digit1: 1,
+        Digit2: 2,
+        Digit3: 3,
+        Digit4: 4,
+        Digit5: 5,
+      };
+
+      const keyNumber = keyMap[event.code];
+
+      if (keyNumber) {
+        settingsStore.setState({ systemPrompt: characterPresets[keyNumber - 1].value });
+        toastStore.getState().addToast({
+          message: t('Toasts.PresetSwitching', { presetName: t(`Characterpreset${keyNumber}`) }),
+          type: 'info',
+          tag: `character-preset-switching-${keyNumber}`,
+        })
+      }
+    }
+  }, [t, characterPresets]);
+
   useEffect(() => {
-    const handleKeyDown = (event: KeyboardEvent) => {
-      if ((event.metaKey || event.ctrlKey) && event.shiftKey ) {
-        const keyMap: { [key: string]: number } = {
-          Digit1: 1,
-          Digit2: 2,
-          Digit3: 3,
-          Digit4: 4,
-          Digit5: 5,
-        };
-
-        const keyNumber = keyMap[event.code];
-
-        if (keyNumber) {
-          settingsStore.setState({ systemPrompt: characterPresets[keyNumber - 1].value });
-          toastStore.getState().addToast({
-            message: t('Toasts.PresetSwitching', { presetName: t(`Characterpreset${keyNumber}`) }),
-            type: 'info',
-            tag: `character-preset-switching-${keyNumber}`,
-          })
-        }
-      }
-    };
-  
     window.addEventListener("keydown", handleKeyDown);
     return () => {
       window.removeEventListener("keydown", handleKeyDown);
     };
-  }, []);
+  }, [handleKeyDown]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if ((event.metaKey || event.ctrlKey) && event.shiftKey ) {
// shiftキーを押しながら数字キーを押すためのマッピング
const keyMap: { [key: string]: number } = {
Digit1: 1,
Digit2: 2,
Digit3: 3,
Digit4: 4,
Digit5: 5,
};
const keyNumber = keyMap[event.code];
if (keyNumber) {
settingsStore.setState({ systemPrompt: characterPresets[keyNumber - 1].value });
toastStore.getState().addToast({
message: t('Toasts.PresetSwitching', { presetName: t(`Characterpreset${keyNumber}`) }),
type: 'info',
tag: `character-preset-switching-${keyNumber}`,
})
}
}
};
window.addEventListener("keydown", handleKeyDown);
return () => {
window.removeEventListener("keydown", handleKeyDown);
};
}, []);
const handleKeyDown = useCallback((event: KeyboardEvent) => {
if ((event.metaKey || event.ctrlKey) && event.shiftKey) {
const keyMap: { [key: string]: number } = {
Digit1: 1,
Digit2: 2,
Digit3: 3,
Digit4: 4,
Digit5: 5,
};
const keyNumber = keyMap[event.code];
if (keyNumber) {
settingsStore.setState({ systemPrompt: characterPresets[keyNumber - 1].value });
toastStore.getState().addToast({
message: t('Toasts.PresetSwitching', { presetName: t(`Characterpreset${keyNumber}`) }),
type: 'info',
tag: `character-preset-switching-${keyNumber}`,
})
}
}
}, [t, characterPresets]);
useEffect(() => {
window.addEventListener("keydown", handleKeyDown);
return () => {
window.removeEventListener("keydown", handleKeyDown);
};
}, [handleKeyDown]);
🧰 Tools
🪛 ESLint

[error] 42-42: Delete ·

(prettier/prettier)


[error] 50-50: Delete ;

(prettier/prettier)


[error] 52-52: Delete ;

(prettier/prettier)


[error] 55-55: Replace ·systemPrompt:·characterPresets[keyNumber·-·1].value·}); with ⏎············systemPrompt:·characterPresets[keyNumber·-·1].value,⏎··········})

(prettier/prettier)


[error] 57-57: Replace ·presetName:·t(Characterpreset${keyNumber}) with ⏎··············presetName:·t(Characterpreset${keyNumber}),⏎···········

(prettier/prettier)


[error] 63-63: Delete ;

(prettier/prettier)


[error] 64-64: Delete ··

(prettier/prettier)


[error] 65-65: Replace "keydown",·handleKeyDown); with 'keydown',·handleKeyDown)

(prettier/prettier)


[error] 67-67: Replace "keydown",·handleKeyDown); with 'keydown',·handleKeyDown)

(prettier/prettier)


[error] 68-68: Delete ;

(prettier/prettier)


[error] 69-69: Delete ;

(prettier/prettier)

@tegnike tegnike changed the base branch from main to develop March 18, 2025 08:32
@tokusa-inori
Copy link
Contributor Author

lintが落ちているため確認します。

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/components/settings/character.tsx (2)

366-372: マウス移動ごとのState更新に注意してください。
onMouseMove で毎回 State を更新すると、多数の再レンダリングが発生する可能性があります。パフォーマンスを考慮する場合、throttleやrequestAnimationFrameなどを検討しても良いでしょう。


549-589: プリセットボタンとツールチップの連動は良好ですがARIA対応を検討してください。
Shiftキー判定でプリセットを上書き・読み込みするロジックは明快です。ツールチップにもキーボード/スクリーンリーダ対応を考慮したARIA属性を追加すれば、アクセシビリティが向上します。

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between 4220647 and 228f32b.

📒 Files selected for processing (3)
  • src/components/settings/character.tsx (2 hunks)
  • src/features/stores/settings.ts (3 hunks)
  • src/pages/index.tsx (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/features/stores/settings.ts
🔇 Additional comments (9)
src/components/settings/character.tsx (5)

325-346: キャラクタープリセット配列の定義が適切です。
特に問題は見当たりませんが、パフォーマンスの観点から、レンダリング毎に settingsStore の状態を配列生成で参照する場合はメモ化(useMemoなど)を検討しても良いかもしれません。


347-358: ツールチップ用のState管理は妥当です。
この実装で大きな問題はなく、可読性も良好です。


359-365: ツールチップの定数設定が明確です。
ツールチップの最大表示サイズやオフセットなどを定数化してあるのはメンテナビリティに優れています。


374-376: マウスリーブ時のツールチップ非表示ロジックは分かりやすいです。
問題なく実装されています。


546-548: キャラクタープリセットの説明テキストの追加は適切です。
ユーザーへのガイダンスとして有用なため、翻訳リソースの管理もしやすい実装です。

src/pages/index.tsx (4)

1-2: 必要な依存のimport追加が正しく行われています。
特に問題ありません。


18-18: toastStore のインポートに問題はありません。
トースト通知のためにストアを参照する設計は適切です。


31-53: キャラクタープリセット配列の再定義は正しく機能しそうです。
settingsStore からの参照方法は一貫しており、変更時もリスクが低いと考えられます。


55-88: useEffect の依存関係に注意してください。
翻訳関数や characterPresets などを使用しているため、過去のコメントでも指摘があったように依存配列への変数指定によるメモ化が望ましいです。今のままだと翻訳文言が変わったときに再レンダリングされず、トーストの内容が古い可能性があります。

@tegnike
Copy link
Owner

tegnike commented Mar 19, 2025

@tokusa-inori

ご対応ありがとうございます。
動作確認しましたが、問題なさそうです。

ただ、スマホ利用だとキー操作が使えないので、そこはちょっと私の方で代替案を考えようと思います。

あとUIを少し調整したいのですが、そちらは今ちょうど別のプルリクで対応しているので、マージ後に対応します。

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/components/settings/character.tsx (1)

569-652: 🛠️ Refactor suggestion

プリセット機能のUI実装は適切ですが、アクセシビリティに課題があります

プリセット機能のUIは機能的に問題ありませんが、アクセシビリティとキーボードナビゲーションのサポートに改善の余地があります。

以下の改善を検討してください:

 <button
   key={key}
   onClick={() => {
     // プリセット選択時に内容を表示し、systemPromptも更新
     settingsStore.setState({
       selectedPresetIndex: index,
       systemPrompt: value,
     })

     toastStore.getState().addToast({
       message: t('Toasts.PresetSwitching', {
         presetName: customName,
       }),
       type: 'info',
       tag: `character-preset-switching-${index + 1}`,
     })
   }}
+  role="tab"
+  aria-selected={isSelected}
+  tabIndex={0}
+  onKeyDown={(e) => {
+    if (e.key === 'Enter' || e.key === ' ') {
+      e.preventDefault();
+      settingsStore.setState({
+        selectedPresetIndex: index,
+        systemPrompt: value,
+      });
+      
+      toastStore.getState().addToast({
+        message: t('Toasts.PresetSwitching', {
+          presetName: customName,
+        }),
+        type: 'info',
+        tag: `character-preset-switching-${index + 1}`,
+      });
+    }
+  }}
   className={`px-4 py-2 rounded-md text-sm ${
     isSelected
       ? 'bg-primary text-white'
       : 'bg-surface1 hover:bg-surface1-hover text-gray-800'
   }`}
 >

また、テキストエリアとテキスト入力にもラベルとARIA属性を追加することをお勧めします:

 <input
   type="text"
   value={customName}
   onChange={(e) => {
     settingsStore.setState({
       [customNameKey]: e.target.value,
     })
   }}
+  aria-label={t('PresetNameLabel')}
   className="px-3 py-2 bg-white border border-gray-300 rounded-md text-sm w-full"
   placeholder={t(`Characterpreset${index + 1}`)}
 />
 <textarea
   value={systemPrompt}
   onChange={(e) => {
     const newValue = e.target.value
     // システムプロンプトとプリセットの内容を同時に更新
     settingsStore.setState({
       systemPrompt: newValue,
       [key]: newValue,
     })
   }}
+  aria-label={t('SystemPromptLabel')}
   className="px-3 py-2 bg-white border border-gray-300 rounded-md w-full h-64 text-sm"
 />
🧹 Nitpick comments (5)
src/components/characterPresetMenu.tsx (2)

45-64: handlePresetClickの実装は適切ですが、アクセシビリティ改善の余地があります

関数は適切に実装されていますが、キーボードナビゲーションのサポートが不足しています。

以下の改善を検討してください:

 const handlePresetClick = (
   key: string,
   value: string,
   customName: string,
   index: number
 ) => {
   settingsStore.setState({
     systemPrompt: value,
     selectedPresetIndex: index,
   })

   toastStore.getState().addToast({
     message: t('Toasts.PresetSwitching', {
       presetName: customName,
     }),
     type: 'info',
     tag: `character-preset-switching-${index + 1}`,
   })
   setIsOpen(false)
 }
+
+// キーボードイベントハンドラを追加
+const handleKeyDown = (
+  e: React.KeyboardEvent,
+  key: string,
+  value: string,
+  customName: string,
+  index: number
+) => {
+  if (e.key === 'Enter' || e.key === ' ') {
+    e.preventDefault();
+    handlePresetClick(key, value, customName, index);
+  }
+}

66-107: メインボタンのアクセシビリティを改善できます

ボタンの実装は機能的ですが、アクセシビリティの観点からいくつかの改善点があります。

以下の改善を検討してください:

 <button
   onClick={() => setIsOpen(!isOpen)}
   className="w-12 h-12 rounded-full bg-primary text-white shadow-lg flex items-center justify-center"
   aria-label={t('CharacterSettingsPrompt')}
+  aria-expanded={isOpen}
+  aria-controls="preset-menu"
 >
   {isOpen ? (
     // 上向き矢印(メニューオープン時)
src/components/settings/character.tsx (2)

11-31: Character型の定義は適切ですが、コメントに改善の余地があります

型定義は明確ですが、各フィールドの目的を説明するJSDocコメントがあるとより良いでしょう。

以下のように各フィールドグループにコメントを追加することを検討してください:

 // Character型の定義
 type Character = Pick<
   SettingsState,
+  // キャラクター名と表示設定
   | 'characterName'
+  | 'showAssistantText'
+  | 'showCharacterName'
+  | 'systemPrompt'
+  // キャラクタープリセット
   | 'characterPreset1'
   | 'characterPreset2'
   | 'characterPreset3'
   | 'characterPreset4'
   | 'characterPreset5'
+  // プリセット名
   | 'customPresetName1'
   | 'customPresetName2'
   | 'customPresetName3'
   | 'customPresetName4'
   | 'customPresetName5'
   | 'selectedPresetIndex'
-  | 'showAssistantText'
-  | 'showCharacterName'
-  | 'systemPrompt'
+  // モデルパス
   | 'selectedVrmPath'
   | 'selectedLive2DPath'
 >

348-369: characterPresetsの配列定義は適切ですが、最適化の余地があります

配列の定義は問題ありませんが、メモ化することでパフォーマンスを向上させることができます。

useMemoを使用して配列を最適化することを検討してください:

-const characterPresets = [
+const characterPresets = useMemo(() => [
   {
     key: 'characterPreset1',
     value: settingsStore((s) => s.characterPreset1),
   },
   {
     key: 'characterPreset2',
     value: settingsStore((s) => s.characterPreset2),
   },
   {
     key: 'characterPreset3',
     value: settingsStore((s) => s.characterPreset3),
   },
   {
     key: 'characterPreset4',
     value: settingsStore((s) => s.characterPreset4),
   },
   {
     key: 'characterPreset5',
     value: settingsStore((s) => s.characterPreset5),
   },
-]
+], [])
src/features/stores/settings.ts (1)

279-294: ストア内のプリセット初期化は適切ですが、デフォルト値のローカライゼーションに課題があります

プリセットの初期化は機能的に問題ありませんが、ハードコードされた日本語のプリセット名は国際化の観点から課題があります。

以下のように、言語に依存しないデフォルト値を使用し、後で翻訳するアプローチを検討してください:

 characterPreset5:
   process.env.NEXT_PUBLIC_CHARACTER_PRESET5 || SYSTEM_PROMPT,
-customPresetName1: 'プリセット1',
-customPresetName2: 'プリセット2',
-customPresetName3: 'プリセット3',
-customPresetName4: 'プリセット4',
-customPresetName5: 'プリセット5',
+customPresetName1: 'Preset 1',
+customPresetName2: 'Preset 2',
+customPresetName3: 'Preset 3',
+customPresetName4: 'Preset 4',
+customPresetName5: 'Preset 5',
 selectedPresetIndex: 0,

このようにすれば、アプリケーションが起動したときに現在の言語に基づいて翻訳されるデフォルト値を持つことができます。

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between 228f32b and da4b156.

📒 Files selected for processing (5)
  • locales/ja/translation.json (3 hunks)
  • src/components/characterPresetMenu.tsx (1 hunks)
  • src/components/settings/character.tsx (3 hunks)
  • src/features/stores/settings.ts (3 hunks)
  • src/pages/index.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • locales/ja/translation.json
  • src/pages/index.tsx
🧰 Additional context used
🧬 Code Definitions (1)
src/components/settings/character.tsx (1)
src/features/stores/settings.ts (1) (1)
  • SettingsState (171-177)
🔇 Additional comments (9)
src/components/characterPresetMenu.tsx (4)

1-5: 適切なインポートが行われています

必要なモジュールが正しくインポートされており、特に問題は見られません。


6-11: コンポーネントの基本構造が適切に設計されています

React Hooks(useState)とi18nが適切に設定されており、ストアからの状態取得も問題ありません。


12-43: プリセット配列の構造が明確です

各プリセットがkey、value、nameKey、customNameを持つオブジェクトとして定義されており、データ構造が明確です。


137-139: エクスポート宣言は適切です

コンポーネントのエクスポート宣言に問題はありません。

src/components/settings/character.tsx (3)

6-8: インポートステートメントの追加は適切です

新しいインポートステートメントが適切に追加されています。


370-381: ツールチップ状態の管理が適切に実装されています

ツールチップの状態管理が適切に実装されており、問題ありません。


382-399: ツールチップの定数とイベントハンドラの実装は適切です

ツールチップの定数と関連するマウスイベントハンドラが適切に実装されています。

src/features/stores/settings.ts (2)

124-142: Character インターフェースへの新しいプロパティの追加は適切です

新しいプリセット関連のプロパティがCharacterインターフェースに適切に追加されています。


434-444: プリセットの永続化設定は適切に実装されています

新しいプリセット関連のプロパティが状態の永続化に適切に追加されています。

@tegnike
Copy link
Owner

tegnike commented Mar 19, 2025

@tokusa-inori
スマホ利用も考慮し、キー操作無しで変更できるようにしました(UIスタイル移行中につき少し崩れています)
トップページでは、右下のアイコンからプリセットを変更できます。

いちおうショートカットキーも残していますが、Command + Shift + 数字はショートカットと被りやすい & プリセット切り替えにそこまで操作性が必要なのか不明なので、明日また確認したときに削除するかも知れません。

CleanShot 2025-03-19 at 21 14 01

@tokusa-inori
Copy link
Contributor Author

@tegnike
おー!!
修正ありがとうございます!
プリセット名の変更機能も追加してくれてうれしいです!
ショートカットキーに関してはニケちゃん様の判断に任せます!!(私は削除しても構いません。)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
locales/hi/translation.json (2)

57-62: キャラクタープリセットの翻訳キー追加の確認
新たに追加された「characterpresetInfo」と「Characterpreset1」~「Characterpreset5」は、キャラクタープリセット機能の概要やショートカット操作の説明が明確に記述されており、機能の利用方法がユーザに伝わる内容になっています。
ただし、他の言語ファイルとの文言の一貫性や、ユーザにとって直感的な表現になっているかを再度確認することを推奨します。


205-206: エラーメッセージおよびフィードバック表示文言の調整確認
「SpeechRecognitionError」の変更と、新たに追加された「PresetSwitching」は、それぞれ音声認識エラーおよびプリセット切替時のフィードバックを提供するものとして適切に見受けられます。
他のロケールファイルとの整合性も含め、文言の最終確認をお願いします。

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between da4b156 and 97302a9.

📒 Files selected for processing (14)
  • locales/ar/translation.json (2 hunks)
  • locales/de/translation.json (2 hunks)
  • locales/es/translation.json (2 hunks)
  • locales/fr/translation.json (2 hunks)
  • locales/hi/translation.json (2 hunks)
  • locales/it/translation.json (2 hunks)
  • locales/ja/translation.json (2 hunks)
  • locales/ko/translation.json (2 hunks)
  • locales/pl/translation.json (2 hunks)
  • locales/pt/translation.json (2 hunks)
  • locales/ru/translation.json (2 hunks)
  • locales/th/translation.json (2 hunks)
  • locales/vi/translation.json (2 hunks)
  • locales/zh/translation.json (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (13)
  • locales/fr/translation.json
  • locales/ar/translation.json
  • locales/zh/translation.json
  • locales/ru/translation.json
  • locales/ja/translation.json
  • locales/de/translation.json
  • locales/vi/translation.json
  • locales/pl/translation.json
  • locales/th/translation.json
  • locales/es/translation.json
  • locales/it/translation.json
  • locales/ko/translation.json
  • locales/pt/translation.json

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/components/settings/character.tsx (1)

569-678: プリセット管理UIの実装が包括的です

プリセット管理UIの実装が以下の点で優れています:

  • プリセット選択のタブUIが視覚的にわかりやすい
  • 選択中のプリセットが強調表示される
  • プリセット名の変更機能が実装されている
  • キーボード操作が適切にサポートされている
  • プリセット内容の編集とリアルタイムな更新機能

ただし、コードの一部が src/components/characterPresetMenu.tsx と重複しており、将来的なメンテナンス性に影響する可能性があります。

コードの共通部分を抽出して共有ロジックとして実装することを検討してください。例えば、プリセット関連の操作を行うカスタムフックを作成して両方のコンポーネントで使用することで、コードの重複を減らすことができます。

// 例: src/hooks/useCharacterPresets.tsx
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import settingsStore from '@/features/stores/settings';
import toastStore from '@/features/stores/toast';

export function useCharacterPresets() {
  const { t } = useTranslation();
  const selectedPresetIndex = settingsStore(s => s.selectedPresetIndex);
  
  const characterPresets = [
    // プリセット定義...
  ];
  
  const handlePresetClick = (key, value, customName, index) => {
    // 共通のプリセット切り替えロジック
  };
  
  return {
    characterPresets,
    selectedPresetIndex,
    handlePresetClick
  };
}
locales/de/translation.json (1)

57-62: 新規翻訳キーの追加の確認
"characterpresetInfo" および "Characterpreset1" ~ "Characterpreset5" のエントリは、キャラクタープリセット機能に対応するために追加されています。各エントリが他のロケールファイルと整合性が取れているか、また意図した文言になっているか確認してください。

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between 97302a9 and d8e888b.

📒 Files selected for processing (18)
  • locales/ar/translation.json (3 hunks)
  • locales/de/translation.json (3 hunks)
  • locales/en/translation.json (3 hunks)
  • locales/es/translation.json (3 hunks)
  • locales/fr/translation.json (3 hunks)
  • locales/hi/translation.json (3 hunks)
  • locales/it/translation.json (3 hunks)
  • locales/ja/translation.json (2 hunks)
  • locales/ko/translation.json (3 hunks)
  • locales/pl/translation.json (3 hunks)
  • locales/pt/translation.json (3 hunks)
  • locales/ru/translation.json (3 hunks)
  • locales/th/translation.json (3 hunks)
  • locales/vi/translation.json (3 hunks)
  • locales/zh/translation.json (3 hunks)
  • src/components/characterPresetMenu.tsx (1 hunks)
  • src/components/settings/character.tsx (3 hunks)
  • src/features/stores/settings.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (13)
  • locales/ru/translation.json
  • locales/fr/translation.json
  • locales/pl/translation.json
  • locales/vi/translation.json
  • locales/hi/translation.json
  • locales/ko/translation.json
  • locales/es/translation.json
  • locales/th/translation.json
  • locales/ar/translation.json
  • locales/it/translation.json
  • locales/zh/translation.json
  • locales/pt/translation.json
  • src/features/stores/settings.ts
🧰 Additional context used
🧬 Code Definitions (1)
src/components/settings/character.tsx (1)
src/features/stores/settings.ts (1) (1)
  • SettingsState (171-177)
🔇 Additional comments (15)
locales/ja/translation.json (2)

57-62: 新しい翻訳キーが適切に追加されています!

キャラクタープリセット機能のための翻訳キーが適切に追加されています。プリセット選択の説明とショートカットキーの情報が明確に記述されています。


211-212: JSONフォーマットの修正と新しいトースト通知の追加

  1. 行211:カンマの追加によりJSONフォーマットが正しく修正されています
  2. 行212:プリセット切り替え時の通知メッセージが適切に追加されています
src/components/characterPresetMenu.tsx (7)

1-5: 必要なインポートが適切に設定されています

必要なReactフックやストア、多言語サポートのためのライブラリが適切にインポートされています。


6-44: キャラクタープリセットの構造が適切に定義されています

コンポーネントの状態管理とキャラクタープリセットの配列が適切に定義されています。各プリセットにキー、値、名前キー、カスタム名が含まれており、データ構造が整理されています。


45-64: プリセットクリック処理の実装が適切です

プリセットクリック時の処理が適切に実装されています。システムプロンプトの更新、選択インデックスの保存、トースト通知の表示などの機能が実装されています。


66-78: キーボードイベントハンドラは良いアクセシビリティ実装です

キーボードでの操作をサポートするイベントハンドラが実装されており、アクセシビリティの観点から優れています。Enterキーやスペースキーでプリセットを選択できる機能は、キーボードユーザーにとって重要です。


80-123: メインボタンのUI実装とアクセシビリティが適切です

  • 固定配置されたボタンの実装が適切です
  • アクセシビリティ属性(aria-label、aria-expanded、aria-controls)が正しく設定されています
  • SVGアイコンの切り替え表示も適切に実装されています

125-160: プリセットメニューUIの実装が良好です

プリセットメニューのUI実装は以下の点で優れています:

  • 視覚的なフィードバック(選択中のアイテムのハイライト表示)
  • プリセット名の表示
  • 適切なアクセシビリティ属性(role、tabIndex、aria-current)
  • キーボードイベントハンドラの連携

161-166: コンポーネントのエクスポートが適切に行われています

コンポーネントが適切にエクスポートされており、他のファイルから簡単にインポートして使用できます。

locales/en/translation.json (2)

57-62: 英語の翻訳キーが適切に追加されています

キャラクタープリセット機能のための英語の翻訳キーが適切に追加されています。プリセット選択の説明とショートカットキーの情報が明確に記述されています。


208-209: トースト通知の翻訳が追加されています

音声認識関連のメッセージとプリセット切り替え通知の翻訳が適切に追加されています。

src/components/settings/character.tsx (3)

6-31: Character型の定義が適切に拡張されています

Character型がSettingsStateから必要なプロパティをPickを使って選択し、明確に型定義されています。キャラクタープリセットに関連するプロパティが適切に含まれています。


348-369: プリセット配列の定義が適切です

キャラクタープリセットの配列定義が適切に実装されています。各プリセットがキーと値を持ち、settingsStoreから値を取得しています。


370-399: ツールチップ機能の実装が適切です

ツールチップのための状態管理と表示・非表示の制御が適切に実装されています。位置調整のための定数も明確に定義されています。

locales/de/translation.json (1)

205-206: トーストメッセージの更新確認
"SpeechRecognitionError" の表現修正と "PresetSwitching" の追加は、ユーザーへのフィードバックとして適切です。実際の動作と合致しているか、また文言の一貫性を再確認してください。

Comment on lines +254 to +255
"DocumentationDescription": "For detailed usage and tutorials of AITuberKit, please visit the URL below.",
"CharacterpresetInfo": "Selecting a preset will change the character prompt.\nYou can use shortcuts with Cmd + Shift + 1~5 (Mac) / Ctrl + Shift + 1~5 (Windows)."
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

重複する翻訳キーが存在します

CharacterpresetInfoというキーが57行目と255行目に重複して定義されています。これにより、後者のみが有効になり、予期しない動作を引き起こす可能性があります。

以下のいずれかの修正を行ってください:

  1. 重複するキーを削除する
  2. 異なるキー名に変更する(例:CharacterpresetInfoShort
- "CharacterpresetInfo": "Selecting a preset will change the character prompt.\nYou can use shortcuts with Cmd + Shift + 1~5 (Mac) / Ctrl + Shift + 1~5 (Windows)."
+ "CharacterpresetInfoShort": "Selecting a preset will change the character prompt.\nYou can use shortcuts with Cmd + Shift + 1~5 (Mac) / Ctrl + Shift + 1~5 (Windows)."
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"DocumentationDescription": "For detailed usage and tutorials of AITuberKit, please visit the URL below.",
"CharacterpresetInfo": "Selecting a preset will change the character prompt.\nYou can use shortcuts with Cmd + Shift + 1~5 (Mac) / Ctrl + Shift + 1~5 (Windows)."
"DocumentationDescription": "For detailed usage and tutorials of AITuberKit, please visit the URL below.",
"CharacterpresetInfoShort": "Selecting a preset will change the character prompt.\nYou can use shortcuts with Cmd + Shift + 1~5 (Mac) / Ctrl + Shift + 1~5 (Windows)."

Comment on lines 251 to 252
"DocumentationDescription": "Detaillierte Anleitungen und Tutorials zur Verwendung von AITuberKit finden Sie unter der folgenden URL.",
"CharacterpresetInfo": "Wenn Sie ein Preset auswählen, wird der Charakterprompt geändert.\nCmd + Shift + 1~5 (Mac) / Ctrl + Shift + 1~5 (Windows) ermöglicht Shortcuts."
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

重複キーの可能性についての警告
行57で "characterpresetInfo" が定義されているのに対し、行252で大文字始まりの "CharacterpresetInfo" が再定義されています。JSON ではキーが重複すると予期せぬ挙動を引き起こす可能性があるため、キー名を統一するか、不要なエントリを削除するようご検討ください。

@tegnike tegnike merged commit e14e125 into tegnike:develop Mar 20, 2025
3 checks passed
@tokusa-inori tokusa-inori deleted the feature/character-preset branch March 20, 2025 11:12
terisuke pushed a commit to terisuke/aituber-kit that referenced this pull request Dec 5, 2025
…eset

キャラクタープリセット機能を実装
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants