Conversation
App.tsx 3381 → 3102行(-279)。挙動不変。依存の浅い順に1段ずつ進める最初の2段。 - hooks/useTimelineNavigation.ts: view / timelineStart / monthCursor / dayCount / withNavLock と 各種ナビゲーション。外部 I/O ゼロなので App の先頭で呼ぶ - hooks/useGlobalShortcuts.ts: keydown effect のみを分離。**当初案の単一フックは実現不可能だった** ―― canCreateEvent の元(defaultWriteTarget)と helpOpen は App の後半で定義される一方、 view/timelineStart/dayCount/monthCursor は前半の fetch effect の依存配列に現れる。依存配列は レンダー中に評価されるためフック呼び出しを後ろへ動かすと TDZ になる。よって「I/O なしの状態部分は 先頭」「keydown effect は元と同じ位置」に2分割し、effect の登録順・依存粒度を保った - hooks/useBlockRules.ts / useMcpTokens.ts: state + 取得 + 作成/削除。取得条件(me.connected で1回 / panelOpen が true になった瞬間だけ)と非2xx フォールバックは逐語維持。upsertBlockRule のテスト4件 - role="dialog" による他オーバーレイ抑止はコメントごと逐語移植(個別 state の列挙は導入しない)。 withNavLock/NAV_LOCK_MS、スワイプだけロックを通さない挙動、view の localStorage 永続化も不変 - Escape は setHelpOpen(false)、? はトグルで意味が違うため onToggleHelp/onCloseHelp を分けた (両方 App 側で useCallback 安定化。インラインだと毎レンダー listener が張り替わる) - JSX は1文字も変更していない(返り値を旧変数名で destructure) - sync/blockRules.ts の「呼び出しは App.tsx が行う」コメントを useBlockRules.ts に追従 web 875 tests, typecheck/build clean。lint 警告は 12 → 12(内訳同一、行番号のみ移動)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HGESE2zBNzoW8MYvtEySBQ
App.tsx 3102 → 2732行(-370)。挙動不変、JSX は1行も変更なし。 - hooks/useGitHubData.ts を新設: items / activity / CI / 作業キュー / repos・repo-issues / githubAuthExpired / clearGitHubData を集約 - 内部ヘルパー useGitHubRangeResource で、activity と CI の**ほぼ逐語コピーだった effect 2本 (66行 + 65行)を1本に**。呼び出し側は path/viaGh/ラベル/初期表示の差分だけ(各14行) - 401/409/!ok の三分岐を純関数 classifyGitHubResponse に切り出し(テスト4件)、5経路 (items/activity/ci/queue/pr-commits)すべてで共通化。分岐後の処理(409 を空にするか無視するか)は 経路ごとに違うので呼び出し側に残した - PR commit 推定は別フック useGitHubPrCommitEstimates に(依存する needsActualsData 等が App 後半で しか確定せず、effect 登録順を保つ位置からは TDZ で触れないため)。401 は同じ githubAuthExpired へ合流 壊していない点: 300ms デバウンス、month/未連携では取得しない条件、isTauri() 分岐と両経路の エラーハンドリングの非対称性(gh は [] に畳む / サーバーは 502・ネットワークエラーで前回表示を維持)、 意図的な exhaustive-deps 無効化2箇所、items の全消し→全書き込みの順序、effect の登録順。 **useGitHubRangeResource の引数を enabled boolean に畳まなかった**のは、me.github の オブジェクト同一性が依存から消えると online 復帰時の再フェッチが起きなくなるため(挙動が変わる)。 web 879 tests, typecheck/build clean。lint 警告 12 → 12(同一ルール、行番号のみシフト)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HGESE2zBNzoW8MYvtEySBQ
App.tsx 2732 → 2054行(-678)。累計 3381 → 2054(-1327)。挙動不変、JSX は1行も変更なし。 - hooks/useEventMutations.ts: ドラッグ/リサイズ確定・編集保存・削除・新規作成・RSVP・移動確認・ 保存エラー表示・タスク完了トグル - hooks/useWorkLogs.ts / useTimers.ts / usePlannedBlockHandlers.ts: 実績の取得と CRUD / 開区間の45秒ポーリングと start・stop・1秒 tick・timeEntryStore への射影 / 予定ブロックの作成・移動・削除 - sync/overridePatch.ts を新設: putOverride の patch マージを純関数化(直近バグだった箇所)。 patch:null(キャンセル済み)・location:undefined による明示クリア・既存 conferenceUrl の保持を テスト9件で固定。lint 警告が 12 → 9 に減ったのはこの集約による副産物 - sync/openIntervals.ts に buildWorkIntervalStopRequest を追加(開区間の生 repo/issueRef 優先 → 射影へフォールバック、number=0 なら issueRef 省略)+ テスト4件 移設の忠実性は「コメント/空白を除去しリネームを適用した正規化差分」で機械的に確認済み。 壊していない点: 楽観更新→ロールバックの順序とエラーメッセージ、422→RsvpNotAttendeeError の 振り替え順序、1秒 tick の依存(本数ではなく 0↔非0 の遷移)、projectedRunning を plannedVersion で 張る形(plannedStore.getAll() は依存に入れない)、45秒ポーリングの条件(me.github の オブジェクト同一性)、停止失敗時に走行中のまま残す挙動、409 work_log_conflict の現挙動。 既知の相対順序変化1件: work-logs 取得 effect が開区間ポーリング/tick/射影より前に登録される (旧 effect が work-logs と開区間再取得を1本に同居させていたため分離が必要だった)。発火条件は 両者同一で、読み書きする state も完全に分離しているため不活性と判断。 web 892 tests, typecheck/build clean。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HGESE2zBNzoW8MYvtEySBQ
App.tsx 2054 → 1285行。フェーズ2 全体で 3381 → 1285(-2096、約62%減)。挙動不変、JSX は無変更。
- hooks/useGoogleAccounts.ts: me / calendarsByAccount / visibleCalendars / taskListsByAccount /
tasksScopeMissingAccounts / hiddenTaskLists / declinedVisibility と checkMe(online 復帰込み)・
一覧取得・永続化・トグル・連携解除・設定パネル再フェッチ
- hooks/useCalendarSync.ts: syncCalendarOnce / syncCalendar / syncTaskList / selectedTargets /
defaultWriteTarget / runSync / runSyncBackfillIfNeeded / SSE 配線 / 起動時自動同期
- db/bootstrap.ts: 起動時の IndexedDB 読み込みシーケンス。**フックにせず純粋な async 関数**にした
(フック化すると引数がレンダー中評価になり後段フックが TDZ になる/effect 登録順が変わる)。
テスト11件で「各ストアの通知が1回ずつ、通知時点で5ストアすべて埋まっている」= batch ネストの
意図そのものを固定。openDatabase/expand をテスト用の差し替え口として optional に
- sync/visibleCalendars.ts に純関数 nextVisibleCalendarsForAccount を追加(テスト6件)
循環の解き方: useGoogleAccounts は state と fetcher のみ、useCalendarSync はそれを一方向に受ける。
逆向きの結線は App.tsx の3グルーに残した。autoSyncedTaskListsRef の掃除は移設前「state 畳み込みと
ローカルデータ削除の間」にあったため、掃除関数を引数で渡して同じ位置で呼ぶ形にし順序を保存。
壊していない点: runSync → backfill の直列性(並列化すると syncScheduler 上で forceFull と通常同期が
競合する)、visibleCalendars の prev 優先マージ(「一生 primary が選ばれず {} が永続化される」既知
バグの修正コード)、syncScheduler のカレンダー単位直列化、pendingVisiblePuts の再送、/api/sync の
エラーメッセージに (accountId/calendarId) が入る形、backfill 版数は全成功時のみ保存、意図的な
exhaustive-deps 無効化。
既知の effect 登録順の変更2箇所: useGoogleAccounts が me を後段フックへ渡すため前に置く必要があり、
永続化3本と一覧取得3本が GitHub 系より先に登録される(初回はガードで空振り、以後も読み書きする
state が分離)。useMasuVisible は syncStatus が返り値になったため useCalendarSync の直後へ移動。
web 909 tests, typecheck/build clean。lint 警告 9(ベースラインと同数・同内容)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HGESE2zBNzoW8MYvtEySBQ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
App.tsx を依存の浅い順に7段でカスタムフックへ水平分割。3381 → 1285行(-2096、約62%減)。挙動不変、JSX は1行も変更なし。
useTimelineNavigation/useGlobalShortcutsuseBlockRules/useMcpTokensuseGitHubData(+useGitHubRangeResourceで activity/CI の逐語コピー2本を1本に、classifyGitHubResponseを純関数化)/useGitHubPrCommitEstimatesuseEventMutations(+sync/overridePatch.tsで patch マージを純関数化)useWorkLogs/useTimers/usePlannedBlockHandlersuseGoogleAccounts→useCalendarSync(循環はグルーを App に残して解く)db/bootstrap.ts(純粋な async 関数。テスト11件で batch ネストの意図を固定)壊していないことの担保
runSync → backfillの直列性、visibleCalendarsの prev 優先マージ(既知バグの修正コード)、syncScheduler の直列化、role="dialog"によるショートカット抑止、1秒 tick の「0↔非0」依存、projectedRunningの plannedVersion 依存、45秒ポーリング条件、意図的な exhaustive-deps 無効化検証
web 909 tests(871→+38)/ typecheck / build clean、lint 警告は 12 → 9 に減少。
加えて実ブラウザ(dev +
?demo=1)で描画・ビュー切替・日付移動・ズーム(48→56px と localStorage 保存、プリセット外の「56px」表示)を確認。React/フック順のエラーなし。🤖 Generated with Claude Code
https://claude.ai/code/session_01HGESE2zBNzoW8MYvtEySBQ