# 機能設計書: タイムライン

## 1. 機能概要

### 1.1 機能名
タイムライン（Timeline）

### 1.2 機能ID
No.30

### 1.3 概要説明
タイムライン機能は、現在開いているファイルの変更履歴を時系列で表示するビューである。Gitの履歴、ローカルファイルの変更履歴、その他の拡張機能が提供するタイムライン情報を統合して表示する。各エントリをクリックすることで、過去の状態との差分表示や、その時点のファイル内容の確認が可能である。

### 1.4 関連画面
- タイムラインビュー（エクスプローラーサイドバー内）
- タイムラインエントリリスト

## 2. 機能要件

### 2.1 ビジネス要件
- アクティブファイルの変更履歴を表示すること
- 複数のタイムラインプロバイダーを統合表示すること
- 過去バージョンとの差分表示が可能なこと
- タイムラインソースの切り替えが可能なこと

### 2.2 機能要件詳細

| 要件ID | 要件名 | 説明 |
|--------|--------|------|
| TIME-001 | 履歴表示 | ファイルの変更履歴を時系列表示 |
| TIME-002 | 差分表示 | 過去バージョンとの差分表示 |
| TIME-003 | マルチソース | 複数プロバイダーの統合表示 |
| TIME-004 | フィルタ | ソースによるフィルタリング |
| TIME-005 | 追従 | アクティブエディタへの追従 |
| TIME-006 | ページネーション | 履歴の追加読み込み |
| TIME-007 | 相対時間 | 相対時間での表示 |

## 3. アーキテクチャ設計

### 3.1 コンポーネント構成

```
┌─────────────────────────────────────────────────────────┐
│                   Timeline Pane                         │
│  ┌──────────────────────────────────────────────────┐  │
│  │  Message Area (No timeline / Loading)             │  │
│  ├──────────────────────────────────────────────────┤  │
│  │  Timeline Tree (WorkbenchObjectTree)              │  │
│  │  ┌────────────────────────────────────────────┐  │  │
│  │  │ ○ 2 minutes ago - Edit made                │  │  │
│  │  │ ○ 5 minutes ago - File saved               │  │  │
│  │  │ ○ 1 hour ago - Git commit: "Fix bug"       │  │  │
│  │  │ ○ Yesterday - File created                 │  │  │
│  │  │ ⟳ Load more...                             │  │  │
│  │  └────────────────────────────────────────────┘  │  │
│  └──────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│                  ITimelineService                       │
│  ┌────────────────────────────────────────────────────┐│
│  │  - providers: ITimelineProvider[]                  ││
│  │  - getTimeline()                                   ││
│  │  - registerTimelineProvider()                      ││
│  └────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│              Timeline Provider (Extension)              │
│  ┌────────────────────────────────────────────────────┐│
│  │  Git History / Local History / Custom Provider     ││
│  └────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────┘
```

### 3.2 クラス図

```
┌─────────────────────────┐
│      TimelinePane       │
│    extends ViewPane     │
├─────────────────────────┤
│ - $container            │
│ - $message              │
│ - $tree                 │
│ - tree                  │
│ - commands              │
│ - timelinesBySource     │
├─────────────────────────┤
│ + followActiveEditor    │
│ + refresh()             │
└───────────┬─────────────┘
            │
            ▼
┌─────────────────────────┐      ┌─────────────────────────┐
│    TimelineAggregate    │      │   ITimelineService      │
├─────────────────────────┤      │    <<interface>>        │
│ + items: TimelineItem[] │      ├─────────────────────────┤
│ + source: string        │      │ + providers             │
│ + cursor                │      │ + getTimeline()         │
│ + more                  │      │ + registerProvider()    │
├─────────────────────────┤      │ + onDidChangeTimeline   │
│ + add()                 │      └─────────────────────────┘
│ + invalidate()          │
└─────────────────────────┘

┌─────────────────────────┐
│     TimelineItem        │
├─────────────────────────┤
│ + handle: string        │
│ + timestamp: number     │
│ + label: string         │
│ + description           │
│ + relativeTime          │
│ + icon                  │
└─────────────────────────┘
```

## 4. 詳細設計

### 4.1 データ構造

#### TimelineItem
```typescript
interface TimelineItem {
    handle: string;
    timestamp: number;
    source: string;
    label: string;
    description?: string;
    tooltip?: string | IMarkdownString;
    relativeTime?: string;
    relativeTimeFullWord?: string;
    hideRelativeTime?: boolean;
    icon?: URI;
    iconDark?: URI;
    themeIcon?: ThemeIcon;
    contextValue?: string;
}
```

#### TimelineAggregate
```typescript
class TimelineAggregate {
    readonly items: TimelineItem[];
    readonly source: string;
    lastRenderedIndex: number;

    get cursor(): string | undefined;
    get more(): boolean;
    get newest(): TimelineItem | undefined;
    get oldest(): TimelineItem | undefined;

    add(timeline: Timeline, options: TimelineOptions): boolean;
    invalidate(requiresReset: boolean): void;
}
```

#### LoadMoreCommand
```typescript
class LoadMoreCommand {
    readonly handle = 'vscode-command:loadMore';
    readonly timestamp = 0;
    loading: boolean;

    get label(): string;
    get ariaLabel(): string;
}
```

### 4.2 処理フロー

#### タイムライン取得フロー
```
1. エディタ変更検出
   │
   ├─2. TimelinePane.onEditorChanged()
   │    │
   │    └─ URI取得とプロバイダー確認
   │
   ├─3. ITimelineService.getTimeline()
   │    │
   │    ├─ 各プロバイダーに問い合わせ
   │    │
   │    └─ TimelineAggregate.add()
   │
   └─4. ツリー更新
        │
        ├─ アイテムのソート（timestamp順）
        │
        └─ WorkbenchObjectTree.setChildren()
```

### 4.3 主要メソッド

#### TimelineAggregate.add()
```typescript
add(timeline: Timeline, options: TimelineOptions): boolean {
    let updated = false;

    if (timeline.items.length !== 0 && this.items.length !== 0) {
        updated = true;

        // 重複除去
        const ids = new Set();
        const timestamps = new Set();
        for (const item of timeline.items) {
            if (item.id === undefined) {
                timestamps.add(item.timestamp);
            } else {
                ids.add(item.id);
            }
        }

        // 既存アイテムから重複を削除
        let i = this.items.length;
        while (i--) {
            const item = this.items[i];
            if ((item.id !== undefined && ids.has(item.id)) || timestamps.has(item.timestamp)) {
                this.items.splice(i, 1);
            }
        }

        // 新規アイテムの追加
        if (timeline.items[timeline.items.length - 1]?.timestamp >= this.newest?.timestamp) {
            this.items.splice(0, 0, ...timeline.items);
        } else {
            this.items.push(...timeline.items);
        }
    }

    // ソート
    if (updated) {
        this.items.sort((a, b) => (b.timestamp - a.timestamp));
    }

    return updated;
}
```

## 5. インターフェース設計

### 5.1 サービスインターフェース

```typescript
interface ITimelineService {
    readonly _serviceBrand: undefined;

    // プロバイダー管理
    registerTimelineProvider(provider: ITimelineProvider): IDisposable;
    unregisterTimelineProvider(id: string): void;

    // タイムライン取得
    getTimeline(
        id: string,
        uri: URI,
        options: TimelineOptions,
        tokenSource: CancellationTokenSource
    ): TimelineRequest;

    // イベント
    readonly onDidChangeProviders: Event<TimelineProvidersChangeEvent>;
    readonly onDidChangeTimeline: Event<TimelineChangeEvent>;
    readonly onDidChangeUri: Event<URI>;
}
```

### 5.2 プロバイダーインターフェース

```typescript
interface ITimelineProvider {
    readonly id: string;
    readonly label: string;
    readonly scheme: string | string[];

    provideTimeline(
        uri: URI,
        options: TimelineOptions,
        token: CancellationToken
    ): Promise<Timeline | undefined>;
}
```

## 6. コンテキストキー

```typescript
// タイムライン関連コンテキストキー
const TimelineFollowActiveEditorContext: RawContextKey<boolean>;
const TimelineExcludeSources: RawContextKey<string>;
const TimelineViewFocusedContext: RawContextKey<boolean>;
```

## 7. コードリーディングガイド

### 7.1 推奨読解順序

1. **ペイン層**: `src/vs/workbench/contrib/timeline/browser/timelinePane.ts`
   - **61-84行目**: 定数とヘルパー関数
   - **86-192行目**: TimelineAggregateクラス
   - **194-231行目**: LoadMoreCommandクラス
   - **241-297行目**: TimelinePaneクラスの初期化

2. **タイムラインサービス**: `src/vs/workbench/contrib/timeline/common/timeline.ts`
   - ITimelineService、ITimelineProviderインターフェース

3. **レンダラー**: 同ファイル内
   - TimelineTreeRenderer

### 7.2 プログラム呼び出し階層図

```
TimelinePane
├── TimelinePaneCommands
├── WorkbenchObjectTree
│   ├── TimelineTreeRenderer
│   │   ├── TimelineItem
│   │   └── LoadMoreCommand
│   └── TimelineAccessibilityProvider
├── TimelineAggregate[]
│   └── TimelineItem[]
└── ITimelineService
    ├── ITimelineProvider[]
    │   ├── Git Timeline Provider
    │   ├── Local History Provider
    │   └── Extension Providers
    └── Timeline Events
```

### 7.3 データフロー図

```
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│ Active Editor   │────▶│  TimelinePane   │────▶│ITimelineService │
│ (URI Change)    │     │                 │     │                 │
└─────────────────┘     └─────────────────┘     └────────┬────────┘
                                                         │
                                                         ▼
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  Timeline Tree  │◀────│TimelineAggregate│◀────│Timeline Provider│
│   (Display)     │     │   (Merged)      │     │   (Git/Local)   │
└─────────────────┘     └─────────────────┘     └─────────────────┘
```

### 7.4 関連ファイル一覧

| パス | 種別 | 役割 |
|------|------|------|
| `src/vs/workbench/contrib/timeline/browser/timelinePane.ts` | ペイン | タイムラインペイン実装 |
| `src/vs/workbench/contrib/timeline/common/timeline.ts` | 共通 | インターフェース定義 |
| `src/vs/workbench/contrib/timeline/browser/timelineService.ts` | サービス | タイムラインサービス |

## 8. 変更履歴

| 日付 | バージョン | 変更内容 | 作成者 |
|------|-----------|---------|--------|
| 2026-01-27 | 1.0 | 初版作成 | Claude |
