機能開発の目的と成果
従来のリポジトリ閲覧機能を拡張し、複数開発者間の協働をサポートするため、ブランチ管理機能を追加しました。主な実装内容は以下の通りです:
- リポジトリ詳細ページにブランチ一覧と管理パネルを追加
- コラボレーションページでブランチ作成、切り替え、削除、マージリクエストの発行機能を実装
ブランチモデルの実装
lib/models/branch.dartの実装例:
class Branch {
final String branchName;
final String repositoryOwner;
final String repositoryName;
final String commitHash;
final String commitMessage;
final bool isProtected;
final DateTime? updatedAt;
final bool isDefaultBranch;
factory Branch.fromMap(Map data, String repoFullName) {
final name = data['name']?.toString() ?? '';
final commitData = data['commit'] as Map;
final sha = commitData['sha']?.toString() ?? '';
final commitInfo = commitData['commit'] as Map;
final message = commitInfo['message']?.toString() ?? 'コミット情報なし';
bool protected = false;
if (data.containsKey('protection')) {
protected = data['protection']['enabled'] as bool? ?? false;
}
final parts = repoFullName.split('/');
final owner = parts.sublist(0, parts.length - 1).join('/');
final repo = parts.last;
final date = _parseDateTime(commitInfo['committer']['date']);
return Branch(
branchName: name,
repositoryOwner: owner,
repositoryName: repo,
commitHash: sha,
commitMessage: message,
isProtected: protected,
updatedAt: date,
isDefaultBranch: data['default'] ?? false,
);
}
static DateTime? _parseDateTime(String? str) {
if (str == null) return null;
try {
return DateTime.parse(str);
} catch (e) {
return null;
}
}
}
コードの特徴:リポジトリ名を分割し、所有者とリポジトリ名を取得。保護状態やデフォルトブランチの識別を強化し、API操作のためのパラメータを準備しています。
ブランチリストと操作インターフェース
lib/pages/repository_detail_page.dartの実装例:
Widget _buildBranchList() {
return RefreshIndicator(
onRefresh: _loadBranches,
child: ListView.separated(
padding: EdgeInsets.all(16),
itemCount: branches.length,
separatorBuilder: (_, __) => Divider(height: 8),
itemBuilder: (context, index) {
final branch = branches[index];
return ListTile(
leading: branch.isDefaultBranch
? Icon(Icons.star, color: Colors.amber)
: Icon(Icons.code_branch),
title: Text(branch.branchName),
subtitle: Text(
'${branch.commitHash.substring(0, 7)} ・ ${branch.commitMessage}',
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
trailing: _buildActionButtons(branch),
onTap: () => _switchBranch(branch),
);
},
),
);
}
Widget _buildActionButtons(Branch branch) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: Icon(Icons.merge),
onPressed: () => _showMergeDialog(branch),
tooltip: 'マージリクエストを発行',
),
IconButton(
icon: Icon(Icons.delete),
onPressed: branch.isProtected || branch.isDefaultBranch
? null
: () => _confirmDelete(branch),
tooltip: branch.isProtected ? '保護されたブランチ' : 'ブランチを削除',
disabledColor: Colors.grey[300],
),
],
);
}
APIサービス層の実装
lib/services/api_service.dartの実装例:
static Future>> fetchRepositoryBranches(String owner, String repo) async {
final url = Uri.parse('https://api.example.com/repos/$owner/$repo/branches');
final response = await _httpGet(url);
if (response.statusCode == 200) {
final jsonData = json.decode(response.body);
if (jsonData is List) {
return jsonData.cast
マージリクエスト機能
lib/pages/merge_request_page.dartの実装内容:
- ソースブランチとターゲットブランチの選択機能
- コンフリクト検出APIによる事前チェック
- マージタイトル、説明、レビュアーの指定
- マージリクエストの状態追跡(未審査、承認、却下、マージ中、完了)
ユーザーエクスペリエンスの最適化
- 操作結果のトースト通知(3秒自動消去)
- コンフリクト結果のハイライト表示とファイル確認リンク
- ローディングダイアログで重複操作防止
- デフォルトブランチと保護ブランチのアイコン表示
- ブランチリストの更新順ソート
- キーワード検索によるフィルタリング
- ネットワークエラー時のリトライボタン
- 権限不足時の明確なエラーメッセージと権限申請リンク
- 削除時の二次確認ダイアログ
テスト結果
| テストケース | 内容 | 結果 |
|---|---|---|
| ブランチ管理 | 一般ブランチ、デフォルトブランチ、保護ブランチの作成・削除 | 成功(保護・デフォルトブランチの削除は無効化) |
| マージリクエスト | コンフリクトなし、あり、レビュアー指定 | 成功(コンフリクト検出正確、状態追跡正常) |
| エラーシナリオ | ネットワーク中断、権限不足、重複ブランチ作成 | 成功(エラーメッセージ明確、リトライ可能) |
| パフォーマンス | 100+ブランチの読み込み、一括削除 | 成功(1秒以内、カクつきなし) |
今後の改善計画
- ブランチ履歴のビジュアル化
- ブランチネットワーク拓扑図の実装
- 細かい権限管理の追加
- マージリクエストテンプレートの導入
- レビューノーティフィケーション機能
- オフラインキャッシュの強化
- オフライン操作の同期機能