import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; import '../services/auth_service.dart'; class GiteaCard extends StatefulWidget { const GiteaCard({super.key}); @override State createState() => _GiteaCardState(); } class _GiteaCardState extends State { List _activities = []; bool _isLoading = false; String? _error; String _getOperationTypeText(String opType) { switch (opType) { case 'create_repo': return '创建仓库'; case 'commit_repo': return '提交代码'; case 'push_tag': return '推送标签'; case 'create_issue': return '创建 Issue'; case 'comment_issue': return '评论 Issue'; case 'create_pull_request': return '创建 Pull Request'; case 'merge_pull_request': return '合并 Pull Request'; default: return opType; } } Widget _buildCommitContent(String content) { try { final data = jsonDecode(content); final commits = data['Commits'] as List; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: commits.map((commit) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( commit['Message'], style: const TextStyle(fontWeight: FontWeight.bold), ), Text( '作者: ${commit['AuthorName']} <${commit['AuthorEmail']}>', style: const TextStyle(fontSize: 12, color: Colors.grey), ), Text( '提交时间: ${commit['Timestamp']}', style: const TextStyle(fontSize: 12, color: Colors.grey), ), ], ), ); }).toList(), ); } catch (e) { return Text(content); } } Future _fetchActivities() async { setState(() { _isLoading = true; _error = null; }); try { final authService = Provider.of(context, listen: false); final token = authService.credentials['gitea']; final username = authService.credentials['gitea_username']; if (token == null || token.isEmpty) { throw Exception('未配置 Gitea Token'); } if (username == null || username.isEmpty) { throw Exception('未配置 Gitea 用户名'); } final response = await http.get( Uri.parse( 'https://git.jdysya.top/api/v1/users/$username/activities/feeds', ), headers: {'Authorization': 'token $token'}, ); if (response.statusCode == 200) { setState(() { _activities = jsonDecode(response.body); _isLoading = false; }); } else { throw Exception('请求失败: ${response.statusCode}'); } } catch (e) { setState(() { _error = e.toString(); _isLoading = false; }); } } @override void initState() { super.initState(); _fetchActivities(); } @override Widget build(BuildContext context) { return Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( 'Gitea 最近活动', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), IconButton( icon: const Icon(Icons.refresh), onPressed: _isLoading ? null : _fetchActivities, ), ], ), if (_isLoading) const Center( child: Padding( padding: EdgeInsets.all(16.0), child: CircularProgressIndicator(), ), ) else if (_error != null) Center( child: Padding( padding: const EdgeInsets.all(16.0), child: Text( _error!, style: const TextStyle(color: Colors.red), ), ), ) else if (_activities.isEmpty) const Center( child: Padding( padding: EdgeInsets.all(16.0), child: Text('暂无活动记录'), ), ) else Expanded( child: ListView.builder( itemCount: _activities.length, itemBuilder: (context, index) { final activity = _activities[index]; final repo = activity['repo']; final created = DateTime.parse(activity['created']); return Card( margin: const EdgeInsets.symmetric(vertical: 4.0), child: Padding( padding: const EdgeInsets.all(12.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ CircleAvatar( radius: 16, child: Text( activity['act_user']['login'][0] .toUpperCase(), ), ), const SizedBox(width: 8), Text( activity['act_user']['login'], style: const TextStyle( fontWeight: FontWeight.bold, ), ), const SizedBox(width: 8), Text( _getOperationTypeText(activity['op_type']), ), ], ), const SizedBox(height: 8), if (repo != null) Text( repo['full_name'], style: const TextStyle( color: Colors.blue, fontWeight: FontWeight.bold, ), ), if (activity['content'] != null) Padding( padding: const EdgeInsets.only(top: 8.0), child: activity['op_type'] == 'commit_repo' ? _buildCommitContent( activity['content'], ) : Text(activity['content']), ), const SizedBox(height: 8), Text( '时间: ${created.toString().substring(0, 19)}', style: const TextStyle( fontSize: 12, color: Colors.grey, ), ), ], ), ), ); }, ), ), ], ), ), ); } }