# 機能設計書 15-リーディングリスト管理

## 概要

本ドキュメントは、Wikipedia iOSアプリにおける「リーディングリスト管理」機能の設計を記述する。この機能は、ユーザーがリーディングリストの作成、編集、削除、および記事の整理を行うものである。

### 本機能の処理概要

**業務上の目的・背景**：ユーザーが保存した記事をカテゴリ別に整理できるようにすることで、大量の保存記事を効率的に管理できるようにする。仕事用、趣味用、学習用など、目的別にリストを分けることで、必要な情報へのアクセスが容易になる。

**機能の利用シーン**：Saved画面からリーディングリスト一覧にアクセスし、リストの追加/編集/削除、リスト内の記事の移動/削除、リスト名・説明の変更などを行う。また、記事をあるリストから別のリストに移動することも可能。

**主要な処理内容**：
1. リーディングリストの一覧表示
2. 新規リストの作成
3. リストの名前・説明の編集
4. リストの削除
5. リスト間での記事の移動
6. リスト内の記事の削除
7. 複数選択による一括操作

**関連システム・外部連携**：ReadingListsController（WMFReadingListsController）と連携し、Core Data経由でデータを永続化する。

**権限による制御**：本機能は認証不要で利用可能。ログイン済みユーザーはサーバー同期が可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | Saved画面 | 主画面 | リーディングリスト一覧と操作 |

## 機能種別

データ管理 / CRUD操作 / 一覧表示

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | String | Yes | リスト名 | 空白でないこと、重複しないこと |
| description | String? | No | リストの説明 | - |
| articles | [WMFArticle] | No | 追加する記事配列 | - |

### 入力データソース

- 画面操作：編集モード、スワイプアクション
- ダイアログ入力：リスト名・説明の入力

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| readingLists | [ReadingList] | リーディングリスト配列 |
| countOfEntries | Int64 | リスト内の記事数 |
| name | String | リスト名 |
| description | String? | リスト説明 |

### 出力先

- 画面表示：ReadingListsViewController
- Core Data：ReadingList エンティティ

## 処理フロー

### 処理シーケンス

```
1. リーディングリスト一覧画面表示
   └─ NSFetchedResultsControllerで取得
2. リスト作成
   └─ createReadingList(named:description:with:) を呼び出し
3. リスト編集
   └─ updateReadingList(readingList:with:newName:newDescription:)
4. リスト削除
   └─ delete(readingLists:) を呼び出し
5. 記事移動
   └─ moveArticles(readingListEntries:from:to:) を呼び出し
6. 記事削除
   └─ unsave(readingListEntries:) を呼び出し
7. 同期処理トリガー
   └─ sync() で変更をサーバーに反映
```

### フローチャート

```mermaid
flowchart TD
    A[リスト一覧表示] --> B{ユーザー操作}
    B -->|新規作成| C[リスト作成ダイアログ]
    B -->|編集| D[リスト編集ダイアログ]
    B -->|削除| E[削除確認]
    B -->|記事移動| F[移動先リスト選択]
    C --> G[createReadingList]
    D --> H[updateReadingList]
    E --> I[delete]
    F --> J[moveArticles]
    G --> K[Core Data保存]
    H --> K
    I --> K
    J --> K
    K --> L{ログイン済み?}
    L -->|Yes| M[sync]
    L -->|No| N[処理完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-15-01 | リスト名一意性 | 同一名称のリストは作成不可 | リスト作成・編集時 |
| BR-15-02 | デフォルトリスト | デフォルトリストは削除・名前変更不可 | デフォルトリスト操作時 |
| BR-15-03 | リスト上限 | ユーザーあたりのリスト数上限あり | リスト作成時 |
| BR-15-04 | エントリ上限 | リストあたりの記事数上限あり | 記事追加時 |
| BR-15-05 | 一括操作 | 複数選択モードで一括削除・移動が可能 | 編集モード時 |

### 計算ロジック

リスト数上限チェック:
```swift
let listLimit = moc.wmf_readingListsConfigMaxListsPerUser
let readingListsCount = try moc.allReadingListsCount()
guard readingListsCount + 1 <= listLimit else {
    throw ReadingListError.listLimitReached(limit: listLimit)
}
```

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| リスト作成 | ReadingList | INSERT | 新しいリーディングリストを作成 |
| リスト編集 | ReadingList | UPDATE | リスト名・説明を更新 |
| リスト削除 | ReadingList | DELETE | リーディングリストを削除 |
| 記事移動 | ReadingListEntry | UPDATE | エントリのlistを変更 |
| 記事削除 | ReadingListEntry | DELETE | エントリを削除 |

### テーブル別操作詳細

#### ReadingList

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | リスト名 | 必須 |
| INSERT | readingListDescription | リスト説明 | 任意 |
| INSERT | createdDate | 作成日時 | 自動設定 |
| UPDATE | name | 新しいリスト名 | - |
| UPDATE | readingListDescription | 新しい説明 | - |
| DELETE | - | 対象リストID | - |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| listExistsWithTheSameName | ビジネスエラー | 同名リストが存在 | エラーメッセージ表示 |
| unableToCreateList | 処理エラー | 作成処理失敗 | エラーメッセージ表示 |
| unableToDeleteList | 処理エラー | 削除処理失敗 | エラーメッセージ表示 |
| unableToUpdateList | 処理エラー | 更新処理失敗 | エラーメッセージ表示 |
| listLimitReached | ビジネスエラー | リスト数上限超過 | エラーメッセージ表示 |

### リトライ仕様

自動リトライは行わない。

## トランザクション仕様

Core Dataコンテキストの保存は操作完了後に行う。削除時はカスケード削除でエントリも削除。

## パフォーマンス要件

- リスト一覧表示は即座に実行
- NSFetchedResultsControllerでインクリメンタル更新

## セキュリティ考慮事項

- リストデータはローカルデバイスに保存
- サーバー同期はHTTPS経由

## 備考

デフォルトリーディングリストは特殊な扱いを受け、isDefault属性がtrueに設定される。

---

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

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

リーディングリストのデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ReadingList | `WMF Framework/` | リーディングリストCore Dataエンティティ、name/description/entries/isDefault |
| 1-2 | ReadingListEntry | `WMF Framework/` | リストエントリCore Dataエンティティ、articleKey/list関連 |

**読解のコツ**: ReadingListは複数のReadingListEntryを持ち、entriesリレーションで関連付けられる。isDefaultがtrueのリストがデフォルトリスト。

#### Step 2: コントローラーを理解する

ReadingListsControllerがリスト操作の中心。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ReadingListsController.swift | `Wikipedia/Code/ReadingListsController.swift` | リーディングリストのCRUD操作 |

**主要処理フロー**:
1. **159-177行目**: createReadingList - リスト作成、名前重複チェック
2. **179-198行目**: throwLimitErrorIfNecessary - 上限チェック
3. delete, update メソッド群

#### Step 3: 表示画面を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ReadingListsViewController.swift | `Wikipedia/Code/ReadingListsViewController.swift` | リスト一覧表示ViewController |

**主要処理フロー**:
- NSFetchedResultsControllerDelegateによるリスト更新
- 編集モードでの複数選択操作
- スワイプアクションでの削除

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

```
ReadingListsViewController
    │
    ├─ NSFetchedResultsController
    │      └─ ReadingList一覧取得
    │
    ├─ ReadingListsController
    │      ├─ createReadingList()
    │      ├─ updateReadingList()
    │      ├─ delete()
    │      └─ moveArticles()
    │
    └─ CreateReadingListViewController
           └─ リスト作成/編集ダイアログ
```

### データフロー図

```
[入力]              [処理]                       [出力]

ユーザー操作 ───▶ ReadingListsViewController ───▶ 画面更新
                        │
                        ├─▶ ReadingListsController
                        │      └─▶ Core Data操作
                        │
                        └─▶ NSFetchedResultsController
                               └─▶ 変更通知→UI更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ReadingListsViewController.swift | `Wikipedia/Code/` | ソース | リスト一覧表示 |
| ReadingListsController.swift | `Wikipedia/Code/` | ソース | リスト操作管理 |
| ReadingListDetailViewController.swift | `Wikipedia/Code/` | ソース | リスト詳細表示 |
| CreateReadingListViewController.swift | `Wikipedia/Code/` | ソース | リスト作成/編集 |
| ReadingList+CoreDataClass | `WMF Framework/` | ソース | リストエンティティ |
| ReadingListEntry+CoreDataClass | `WMF Framework/` | ソース | エントリエンティティ |
