mirror of
https://github.com/pd4d10/git-touch.git
synced 2026-04-29 19:13:36 -05:00
feat: add trending screen
This commit is contained in:
@@ -9,6 +9,7 @@ import 'screens/me.dart';
|
|||||||
import 'screens/login.dart';
|
import 'screens/login.dart';
|
||||||
import 'screens/issue.dart';
|
import 'screens/issue.dart';
|
||||||
import 'screens/repos.dart';
|
import 'screens/repos.dart';
|
||||||
|
import 'screens/trending.dart';
|
||||||
|
|
||||||
class Home extends StatefulWidget {
|
class Home extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
@@ -49,6 +50,10 @@ class _HomeState extends State<Home> {
|
|||||||
icon: _buildNotificationIcon(context),
|
icon: _buildNotificationIcon(context),
|
||||||
title: Text('Notification'),
|
title: Text('Notification'),
|
||||||
),
|
),
|
||||||
|
BottomNavigationBarItem(
|
||||||
|
icon: Icon(Icons.trending_up),
|
||||||
|
title: Text('Trending'),
|
||||||
|
),
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: Icon(Icons.search),
|
icon: Icon(Icons.search),
|
||||||
title: Text('Search'),
|
title: Text('Search'),
|
||||||
@@ -63,14 +68,17 @@ class _HomeState extends State<Home> {
|
|||||||
_buildScreen(int index) {
|
_buildScreen(int index) {
|
||||||
// return IssueScreen(number: 29, owner: 'reactjs', name: 'rfcs');
|
// return IssueScreen(number: 29, owner: 'reactjs', name: 'rfcs');
|
||||||
// return ReposScreen('pd4d10');
|
// return ReposScreen('pd4d10');
|
||||||
|
// return TrendingScreen();
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
return NewsScreen();
|
return NewsScreen();
|
||||||
case 1:
|
case 1:
|
||||||
return NotificationScreen();
|
return NotificationScreen();
|
||||||
case 2:
|
case 2:
|
||||||
return SearchScreen();
|
return TrendingScreen();
|
||||||
case 3:
|
case 3:
|
||||||
|
return SearchScreen();
|
||||||
|
case 4:
|
||||||
return MeScreen();
|
return MeScreen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
97
lib/screens/trending.dart
Normal file
97
lib/screens/trending.dart
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:html/parser.dart' show parse;
|
||||||
|
import '../scaffolds/refresh.dart';
|
||||||
|
import '../widgets/repo_item.dart';
|
||||||
|
|
||||||
|
// class TrendingRepo {
|
||||||
|
// String owner;
|
||||||
|
// String name;
|
||||||
|
// String description;
|
||||||
|
// String languageName;
|
||||||
|
// String languageColor;
|
||||||
|
// int starCount;
|
||||||
|
// int forkCount;
|
||||||
|
// int stars;
|
||||||
|
// }
|
||||||
|
|
||||||
|
class TrendingScreen extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_TrendingScreenState createState() => _TrendingScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TrendingScreenState extends State<TrendingScreen> {
|
||||||
|
Future<List<dynamic>> _fetchTrendingRepos() async {
|
||||||
|
var res = await http.get('https://github.com/trending');
|
||||||
|
// print(res.body);
|
||||||
|
var document = parse(res.body);
|
||||||
|
var items = document.querySelectorAll('.repo-list>li');
|
||||||
|
|
||||||
|
return items.map((item) {
|
||||||
|
Map<String, String> lang;
|
||||||
|
var colorNode = item.querySelector('.repo-language-color');
|
||||||
|
if (colorNode != null) {
|
||||||
|
lang = {
|
||||||
|
'name': colorNode.nextElementSibling.innerHtml.trim(),
|
||||||
|
'color': RegExp(r'(#\w{6})')
|
||||||
|
.firstMatch(colorNode.attributes['style'])
|
||||||
|
.group(0),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var payload = {
|
||||||
|
'owner': {
|
||||||
|
'login': item
|
||||||
|
.querySelector('h3>a>span')
|
||||||
|
?.innerHtml
|
||||||
|
?.replaceFirst('/', '')
|
||||||
|
?.trim()
|
||||||
|
},
|
||||||
|
'name': item
|
||||||
|
.querySelector('h3>a')
|
||||||
|
?.innerHtml
|
||||||
|
?.replaceFirst(RegExp(r'^[\s\S]*span>'), '')
|
||||||
|
?.trim(),
|
||||||
|
'description': item.children[2].querySelector('p')?.innerHtml?.trim(),
|
||||||
|
'stargazers': {
|
||||||
|
'totalCount': item.children[3]
|
||||||
|
.querySelectorAll('a')[0]
|
||||||
|
?.innerHtml
|
||||||
|
?.replaceFirst(RegExp(r'^[\s\S]*svg>'), '')
|
||||||
|
?.trim()
|
||||||
|
},
|
||||||
|
'forks': {
|
||||||
|
'totalCount': item.children[3]
|
||||||
|
.querySelectorAll('a')[1]
|
||||||
|
?.innerHtml
|
||||||
|
?.replaceFirst(RegExp(r'^[\s\S]*svg>'), '')
|
||||||
|
?.trim(),
|
||||||
|
},
|
||||||
|
'primaryLanguage': lang,
|
||||||
|
'isPrivate': false,
|
||||||
|
'isFork': false // TODO:
|
||||||
|
};
|
||||||
|
// print(payload);
|
||||||
|
return payload;
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return RefreshScaffold(
|
||||||
|
title: Text('Trending'),
|
||||||
|
onRefresh: _fetchTrendingRepos,
|
||||||
|
bodyBuilder: (payload) {
|
||||||
|
return Column(
|
||||||
|
children: payload.map<Widget>((repo) {
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border(bottom: BorderSide(color: Colors.black12))),
|
||||||
|
child: RepoItem(repo),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,15 +5,15 @@ import '../screens/repo.dart';
|
|||||||
import 'link.dart';
|
import 'link.dart';
|
||||||
|
|
||||||
class RepoItem extends StatelessWidget {
|
class RepoItem extends StatelessWidget {
|
||||||
final Map<String, dynamic> item;
|
final Map<String, dynamic> payload;
|
||||||
|
|
||||||
RepoItem(this.item);
|
RepoItem(this.payload);
|
||||||
|
|
||||||
IconData _buildIconData() {
|
IconData _buildIconData() {
|
||||||
if (item['isPrivate']) {
|
if (payload['isPrivate']) {
|
||||||
return Octicons.lock;
|
return Octicons.lock;
|
||||||
}
|
}
|
||||||
if (item['isFork']) {
|
if (payload['isFork']) {
|
||||||
return Octicons.repo_forked;
|
return Octicons.repo_forked;
|
||||||
}
|
}
|
||||||
return Octicons.repo;
|
return Octicons.repo;
|
||||||
@@ -22,7 +22,8 @@ class RepoItem extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Link(
|
return Link(
|
||||||
screenBuilder: (_) => RepoScreen(item['owner']['login'], item['name']),
|
screenBuilder: (_) =>
|
||||||
|
RepoScreen(payload['owner']['login'], payload['name']),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: EdgeInsets.all(10),
|
padding: EdgeInsets.all(10),
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -33,24 +34,24 @@ class RepoItem extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(
|
Text(
|
||||||
item['owner']['login'] + '/' + item['name'],
|
payload['owner']['login'] + '/' + payload['name'],
|
||||||
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 15),
|
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 15),
|
||||||
),
|
),
|
||||||
Padding(padding: EdgeInsets.only(top: 6)),
|
Padding(padding: EdgeInsets.only(top: 6)),
|
||||||
Text(item['description'] ?? 'No description provided yet'),
|
Text(payload['description'] ?? 'No description provided yet'),
|
||||||
Padding(padding: EdgeInsets.only(top: 6)),
|
Padding(padding: EdgeInsets.only(top: 6)),
|
||||||
DefaultTextStyle(
|
DefaultTextStyle(
|
||||||
style: TextStyle(color: Colors.black54, fontSize: 13),
|
style: TextStyle(color: Colors.black54, fontSize: 13),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Icon(Octicons.star, size: 14, color: Colors.black54),
|
Icon(Octicons.star, size: 14, color: Colors.black54),
|
||||||
Text(item['stargazers']['totalCount'].toString()),
|
Text(payload['stargazers']['totalCount'].toString()),
|
||||||
Padding(padding: EdgeInsets.only(left: 16)),
|
Padding(padding: EdgeInsets.only(left: 16)),
|
||||||
Icon(Octicons.repo_forked,
|
Icon(Octicons.repo_forked,
|
||||||
size: 14, color: Colors.black54),
|
size: 14, color: Colors.black54),
|
||||||
Text(item['forks']['totalCount'].toString()),
|
Text(payload['forks']['totalCount'].toString()),
|
||||||
Padding(padding: EdgeInsets.only(left: 16)),
|
Padding(padding: EdgeInsets.only(left: 16)),
|
||||||
item['primaryLanguage'] == null
|
payload['primaryLanguage'] == null
|
||||||
? Container()
|
? Container()
|
||||||
: Row(children: <Widget>[
|
: Row(children: <Widget>[
|
||||||
Container(
|
Container(
|
||||||
@@ -58,12 +59,12 @@ class RepoItem extends StatelessWidget {
|
|||||||
height: 10,
|
height: 10,
|
||||||
decoration: new BoxDecoration(
|
decoration: new BoxDecoration(
|
||||||
color: convertColor(
|
color: convertColor(
|
||||||
item['primaryLanguage']['color']),
|
payload['primaryLanguage']['color']),
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Padding(padding: EdgeInsets.only(left: 4)),
|
Padding(padding: EdgeInsets.only(left: 4)),
|
||||||
Text(item['primaryLanguage']['name']),
|
Text(payload['primaryLanguage']['name']),
|
||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ dependencies:
|
|||||||
nanoid: ^0.0.6
|
nanoid: ^0.0.6
|
||||||
share: ^0.6.0
|
share: ^0.6.0
|
||||||
flutter_vector_icons: ^0.0.2
|
flutter_vector_icons: ^0.0.2
|
||||||
|
html: ^0.13.3
|
||||||
|
|
||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
# Use with the CupertinoIcons class for iOS style icons.
|
||||||
|
|||||||
Reference in New Issue
Block a user