refactor(github_card): 重构 GitHub 卡片组件
- 优化了 GitHub 事件加载和显示逻辑 - 添加了事件类型文本转换功能 - 改进了错误处理和加载状态显示 - 调整了卡片样式和布局
This commit is contained in:
parent
bfedef58f4
commit
f7d2fc10a4
20
README.md
20
README.md
@ -1,16 +1,10 @@
|
||||
# dashboard
|
||||
## dashboard
|
||||
|
||||
A new Flutter project.
|
||||
个人项目信息面板
|
||||
|
||||
## Getting Started
|
||||
## 配置获取
|
||||
|
||||
This project is a starting point for a Flutter application.
|
||||
|
||||
A few resources to get you started if this is your first Flutter project:
|
||||
|
||||
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
|
||||
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
|
||||
|
||||
For help getting started with Flutter development, view the
|
||||
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
||||
samples, guidance on mobile development, and a full API reference.
|
||||
- leetcode:浏览器获取随便找一个xhr请求,从Header中获取cookie,user-slug在个人页面url中
|
||||
- gitea: 用户设置 >> 应用 >> 生成令牌(授予全部权限)
|
||||
- kodbox: 参考官方文档[获取accesstoken](https://doc.kodcloud.com/v2/#/user/user?id=%e8%8e%b7%e5%8f%96accesstoken)的方式
|
||||
- github: Settings >> Developer Settings >> Personal access tokens (classic)
|
||||
@ -14,101 +14,200 @@ class GithubCard extends StatefulWidget {
|
||||
|
||||
class _GithubCardState extends State<GithubCard> {
|
||||
final GithubService _githubService = GithubService();
|
||||
late Future<List<GithubEvent>> _eventsFuture;
|
||||
List<GithubEvent> _events = [];
|
||||
bool _isLoading = false;
|
||||
String? _error;
|
||||
|
||||
String _getEventTypeText(String type) {
|
||||
switch (type) {
|
||||
case 'PushEvent':
|
||||
return '推送代码';
|
||||
case 'CreateEvent':
|
||||
return '创建仓库';
|
||||
case 'IssuesEvent':
|
||||
return 'Issue 操作';
|
||||
case 'PullRequestEvent':
|
||||
return 'Pull Request 操作';
|
||||
case 'ForkEvent':
|
||||
return 'Fork 仓库';
|
||||
case 'WatchEvent':
|
||||
return '关注仓库';
|
||||
case 'StarEvent':
|
||||
return 'Star 仓库';
|
||||
default:
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildCommitContent(List<Commit> commits) {
|
||||
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.author.name} <${commit.author.email}>',
|
||||
style: const TextStyle(fontSize: 12, color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _fetchEvents() async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
});
|
||||
|
||||
try {
|
||||
final authService = Provider.of<AuthService>(context, listen: false);
|
||||
final username = authService.credentials['github_username'];
|
||||
final token = authService.credentials['github_token'];
|
||||
|
||||
if (username == null || token == null) {
|
||||
throw Exception('请在设置中配置 GitHub 用户名和 Token');
|
||||
}
|
||||
|
||||
final events = await _githubService.getUserEvents(username, token);
|
||||
setState(() {
|
||||
_events = events;
|
||||
_isLoading = false;
|
||||
});
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
_error = e.toString();
|
||||
_isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadEvents();
|
||||
}
|
||||
|
||||
void _loadEvents() {
|
||||
final authService = Provider.of<AuthService>(context, listen: false);
|
||||
final username = authService.credentials['github_username'];
|
||||
final token = authService.credentials['github_token'];
|
||||
|
||||
if (username != null && token != null) {
|
||||
_eventsFuture = _githubService.getUserEvents(username, token);
|
||||
}
|
||||
_fetchEvents();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final authService = Provider.of<AuthService>(context);
|
||||
final username = authService.credentials['github_username'];
|
||||
final token = authService.credentials['github_token'];
|
||||
|
||||
if (username == null || token == null) {
|
||||
return const Center(child: Text('请在设置中配置 GitHub 用户名和 Token'));
|
||||
}
|
||||
|
||||
return FutureBuilder<List<GithubEvent>>(
|
||||
future: _eventsFuture,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
|
||||
if (snapshot.hasError) {
|
||||
return Center(child: Text('加载失败: ${snapshot.error}'));
|
||||
}
|
||||
|
||||
if (!snapshot.hasData || snapshot.data!.isEmpty) {
|
||||
return const Center(child: Text('暂无活动数据'));
|
||||
}
|
||||
|
||||
return ListView.builder(
|
||||
itemCount: snapshot.data!.length,
|
||||
itemBuilder: (context, index) {
|
||||
final event = snapshot.data![index];
|
||||
return Card(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: ListTile(
|
||||
leading: CircleAvatar(
|
||||
backgroundImage: NetworkImage(event.actor.avatarUrl),
|
||||
return Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
'GitHub 最近活动',
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
title: Text(
|
||||
_getEventTitle(event),
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.refresh),
|
||||
onPressed: _isLoading ? null : _fetchEvents,
|
||||
),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('仓库: ${event.repo.name}'),
|
||||
Text(
|
||||
'时间: ${timeago.format(event.createdAt, locale: "zh_CN")}',
|
||||
),
|
||||
if (event.type == 'PushEvent' &&
|
||||
event.payload.commits != null)
|
||||
...event.payload.commits!.map(
|
||||
(commit) => Text(
|
||||
'提交: ${commit.message}',
|
||||
style: const TextStyle(fontSize: 12),
|
||||
],
|
||||
),
|
||||
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 (_events.isEmpty)
|
||||
const Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
child: Text('暂无活动记录'),
|
||||
),
|
||||
)
|
||||
else
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: _events.length,
|
||||
itemBuilder: (context, index) {
|
||||
final event = _events[index];
|
||||
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(
|
||||
backgroundImage: NetworkImage(
|
||||
event.actor.avatarUrl,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
event.actor.login,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(_getEventTypeText(event.type)),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
event.repo.name,
|
||||
style: const TextStyle(
|
||||
color: Colors.blue,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
if (event.type == 'PushEvent' &&
|
||||
event.payload.commits != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: _buildCommitContent(
|
||||
event.payload.commits!,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'时间: ${timeago.format(event.createdAt, locale: 'zh_CN')}',
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
isThreeLine: true,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _getEventTitle(GithubEvent event) {
|
||||
switch (event.type) {
|
||||
case 'WatchEvent':
|
||||
return '${event.actor.login} 关注了 ${event.repo.name}';
|
||||
case 'PushEvent':
|
||||
return '${event.actor.login} 推送了代码到 ${event.repo.name}';
|
||||
case 'CreateEvent':
|
||||
return '${event.actor.login} 创建了 ${event.repo.name}';
|
||||
case 'ForkEvent':
|
||||
return '${event.actor.login} Fork 了 ${event.repo.name}';
|
||||
default:
|
||||
return '${event.actor.login} 在 ${event.repo.name} 进行了 ${event.type} 操作';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user