1
0
mirror of https://github.com/git-touch/git-touch synced 2025-02-10 00:20:35 +01:00

257 lines
6.7 KiB
Dart
Raw Normal View History

2019-02-03 00:28:51 +08:00
import 'package:flutter/material.dart';
2019-01-23 19:52:51 +08:00
import 'package:flutter/cupertino.dart';
import 'package:git_touch/models/theme.dart';
2019-10-02 14:58:11 +08:00
import 'package:git_touch/scaffolds/common.dart';
2020-01-11 19:25:33 +08:00
import 'package:git_touch/utils/utils.dart';
2019-09-25 20:51:23 +08:00
import 'package:git_touch/widgets/issue_item.dart';
2019-09-29 22:10:15 +08:00
import 'package:git_touch/widgets/loading.dart';
2019-09-25 20:51:23 +08:00
import 'package:git_touch/widgets/user_item.dart';
2019-09-29 22:10:15 +08:00
import 'package:primer/primer.dart';
import 'package:provider/provider.dart';
2019-09-27 20:52:38 +08:00
import 'package:git_touch/models/auth.dart';
2019-09-23 18:28:33 +08:00
import 'package:git_touch/widgets/repository_item.dart';
2020-01-11 19:25:33 +08:00
import 'package:timeago/timeago.dart' as timeago;
2019-01-23 19:52:51 +08:00
2020-02-07 14:17:05 +08:00
class GhSearchScreen extends StatefulWidget {
2019-01-23 19:52:51 +08:00
@override
2020-02-07 14:17:05 +08:00
_GhSearchScreenState createState() => _GhSearchScreenState();
2019-02-03 00:28:51 +08:00
}
2020-02-07 14:17:05 +08:00
class _GhSearchScreenState extends State<GhSearchScreen> {
2019-09-25 20:51:23 +08:00
int _activeTab = 0;
bool _loading = false;
List<List> _payloads = [[], [], []];
2019-01-23 19:52:51 +08:00
2019-09-25 20:51:23 +08:00
TextEditingController _controller;
String get _keyword => _controller.text?.trim() ?? '';
@override
void initState() {
super.initState();
_controller = TextEditingController();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
Future<void> _query() async {
if (_loading || _keyword.isEmpty) return;
var keyword = _controller.text;
2019-02-10 13:42:02 +08:00
setState(() {
2019-09-25 20:51:23 +08:00
_loading = true;
2019-02-10 13:42:02 +08:00
});
try {
2020-10-04 20:37:23 +08:00
final auth = context.read<AuthModel>();
final data = await auth.query('''
2019-02-10 13:42:02 +08:00
{
2019-09-25 20:51:23 +08:00
repository: search(first: $pageSize, type: REPOSITORY, query: "$keyword") {
2019-02-10 13:42:02 +08:00
nodes {
... on Repository {
2020-01-11 17:25:01 +08:00
owner {
__typename
login
avatarUrl
}
name
description
isPrivate
isFork
2020-01-11 19:25:33 +08:00
updatedAt
2020-01-11 17:25:01 +08:00
stargazers {
totalCount
}
forks {
totalCount
}
primaryLanguage {
color
name
}
2019-02-10 13:42:02 +08:00
}
}
}
2019-09-25 20:51:23 +08:00
user: search(first: $pageSize, type: USER, query: "$keyword") {
nodes {
... on Organization {
__typename
name
avatarUrl
bio: description
login
}
... on User {
$userGqlChunk
}
}
}
issue: search(first: $pageSize, type: ISSUE, query: "$keyword") {
nodes {
... on PullRequest {
__typename
$issueGqlChunk
}
... on Issue {
$issueGqlChunk
}
}
}
2019-02-10 13:42:02 +08:00
}
''');
2019-09-25 20:51:23 +08:00
_payloads[0] = data['repository']['nodes'];
_payloads[1] = data['user']['nodes'];
_payloads[2] = data['issue']['nodes'];
2019-02-10 13:42:02 +08:00
} finally {
setState(() {
2019-09-25 20:51:23 +08:00
_loading = false;
2019-02-10 13:42:02 +08:00
});
}
}
Widget _buildInput() {
2020-04-16 11:36:48 +08:00
final theme = Provider.of<ThemeModel>(context);
switch (Provider.of<ThemeModel>(context).theme) {
2019-09-19 21:10:50 +08:00
case AppThemeType.cupertino:
2019-09-29 22:10:15 +08:00
return Container(
2020-02-09 20:21:46 +05:30
color: theme.palette.background,
2019-09-29 22:10:15 +08:00
child: CupertinoTextField(
prefix: Row(
children: <Widget>[
SizedBox(width: 8),
Icon(Octicons.search, size: 20, color: PrimerColors.gray400),
],
),
placeholder: 'Search',
clearButtonMode: OverlayVisibilityMode.editing,
textInputAction: TextInputAction.go,
onSubmitted: (_) => _query(),
controller: _controller,
),
2019-09-25 20:51:23 +08:00
);
default:
return TextField(
2019-10-03 10:46:53 +08:00
decoration: InputDecoration.collapsed(hintText: 'Search'),
2019-09-29 22:10:15 +08:00
textInputAction: TextInputAction.go,
2019-09-25 20:51:23 +08:00
onSubmitted: (_) => _query(),
controller: _controller,
);
}
}
2019-09-29 22:10:15 +08:00
_onTabSwitch(int index) {
setState(() {
_activeTab = index;
});
if (_payloads[_activeTab].isEmpty) {
_query();
}
}
static const tabs = ['Repositories', 'Users', 'Issues'];
2020-01-11 17:25:01 +08:00
static IconData _buildIconData(p) {
if (p['isPrivate']) {
return Octicons.lock;
}
if (p['isFork']) {
return Octicons.repo_forked;
}
return Octicons.repo;
}
Widget _buildItem(p) {
2019-09-25 20:51:23 +08:00
switch (_activeTab) {
case 0:
2020-01-11 19:25:33 +08:00
final updatedAt = timeago.format(DateTime.parse(p['updatedAt']));
2020-01-11 19:52:17 +08:00
return RepositoryItem.gh(
2020-01-29 13:06:55 +08:00
owner: p['owner']['login'],
avatarUrl: p['owner']['avatarUrl'],
name: p['name'],
description: p['description'],
starCount: p['stargazers']['totalCount'],
forkCount: p['forks']['totalCount'],
primaryLanguageName: p['primaryLanguage'] == null
? null
: p['primaryLanguage']['name'],
primaryLanguageColor: p['primaryLanguage'] == null
? null
: p['primaryLanguage']['color'],
note: 'Updated $updatedAt',
2020-01-11 19:52:17 +08:00
isPrivate: p['isPrivate'],
isFork: p['isFork'],
2020-01-11 17:25:01 +08:00
);
2019-09-25 20:51:23 +08:00
case 1:
2020-02-01 10:32:29 +08:00
return UserItem.gh(
2020-01-11 17:25:01 +08:00
login: p['login'],
2020-02-01 10:32:29 +08:00
// name: p['name'],
2020-01-11 17:25:01 +08:00
avatarUrl: p['avatarUrl'],
bio: Text(p['bio'] ?? ''),
2020-01-01 15:58:49 +08:00
);
2019-09-25 20:51:23 +08:00
case 2:
2019-02-03 00:28:51 +08:00
default:
2019-09-25 20:51:23 +08:00
return IssueItem(
2020-01-28 23:19:05 +08:00
author: p['author']['login'],
avatarUrl: p['author']['avatarUrl'],
commentCount: p['comments']['totalCount'],
number: p['number'],
title: p['title'],
updatedAt: DateTime.parse(p['updatedAt']),
url: '/github' + Uri.parse(p['url']).path,
2020-01-28 23:19:05 +08:00
isPr: p['__typename'] == 'PullRequest',
);
2019-02-03 00:28:51 +08:00
}
2019-01-23 19:52:51 +08:00
}
2019-02-10 13:42:02 +08:00
@override
Widget build(BuildContext context) {
2019-09-29 22:10:15 +08:00
final theme = Provider.of<ThemeModel>(context).theme;
final scaffold = CommonScaffold(
title: _buildInput(),
body: SingleChildScrollView(
2019-10-03 10:46:53 +08:00
child: Column(
children: [
if (theme == AppThemeType.cupertino)
Center(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 8),
child: CupertinoSlidingSegmentedControl(
2019-10-03 10:46:53 +08:00
groupValue: _activeTab,
onValueChanged: _onTabSwitch,
children: tabs.asMap().map((key, text) => MapEntry(
key,
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Text(text, style: TextStyle(fontSize: 14)),
))),
),
),
2019-09-29 22:10:15 +08:00
),
2019-10-03 10:46:53 +08:00
if (_loading)
Loading()
else
..._payloads[_activeTab].map(_buildItem).toList(),
],
),
2019-09-29 22:10:15 +08:00
),
bottom: TabBar(
onTap: _onTabSwitch,
tabs: tabs.map((text) => Tab(text: text.toUpperCase())).toList(),
2019-09-25 14:24:20 +08:00
),
2019-02-10 13:42:02 +08:00
);
2019-09-29 22:10:15 +08:00
if (theme == AppThemeType.material) {
return DefaultTabController(
length: tabs.length,
child: scaffold,
);
} else {
return scaffold;
}
2019-02-10 13:42:02 +08:00
}
2019-01-23 19:52:51 +08:00
}