feat: gitlab search screen (#81)

* feat: gitlab search screen

* fix: remove implicit dynamic

* fix: lint error

* fix: newer version flutter_svg
This commit is contained in:
Shreyas Thirumalai 2020-05-09 11:07:36 +05:30 committed by GitHub
parent 508f9861d9
commit bc3a204c2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 180 additions and 2 deletions

View File

@ -6,6 +6,7 @@ import 'package:git_touch/models/theme.dart';
import 'package:git_touch/screens/bb_explore.dart';
import 'package:git_touch/screens/bb_teams.dart';
import 'package:git_touch/screens/bb_user.dart';
import 'package:git_touch/screens/gl_search.dart';
import 'package:git_touch/screens/gt_orgs.dart';
import 'package:git_touch/screens/gt_user.dart';
import 'package:git_touch/screens/gl_explore.dart';
@ -62,6 +63,8 @@ class _HomeState extends State<Home> {
case 1:
return GlGroupsScreenn();
case 2:
return GlSearchScreen();
case 3:
return GlUserScreen(null);
}
break;
@ -144,6 +147,10 @@ class _HomeState extends State<Home> {
icon: Icon(Icons.group),
title: Text('Groups'),
),
BottomNavigationBarItem(
icon: Icon(Icons.search),
title: Text('Search'),
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
title: Text('Me'),

171
lib/screens/gl_search.dart Normal file
View File

@ -0,0 +1,171 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:git_touch/models/theme.dart';
import 'package:git_touch/scaffolds/common.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/loading.dart';
import 'package:git_touch/widgets/user_item.dart';
import 'package:primer/primer.dart';
import 'package:provider/provider.dart';
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/widgets/repository_item.dart';
import 'package:timeago/timeago.dart' as timeago;
import 'package:git_touch/models/gitlab.dart';
class GlSearchScreen extends StatefulWidget {
@override
_GlSearchScreenState createState() => _GlSearchScreenState();
}
class _GlSearchScreenState extends State<GlSearchScreen> {
int _activeTab = 0;
bool _loading = false;
List<GitlabProject> _projects = List<GitlabProject>();
List<GitlabUser> _users = List<GitlabUser>();
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;
setState(() {
_loading = true;
});
try {
final projects = await Provider.of<AuthModel>(context)
.fetchGitlabWithPage('/search?scope=projects&search=$keyword');
final users = await Provider.of<AuthModel>(context)
.fetchGitlabWithPage('/search?scope=users&search=$keyword');
_projects = [for (var v in projects.data) GitlabProject.fromJson(v)];
_users = [for (var v in users.data) GitlabUser.fromJson(v)];
} finally {
setState(() {
_loading = false;
});
}
}
Widget _buildInput() {
final theme = Provider.of<ThemeModel>(context);
switch (Provider.of<ThemeModel>(context).theme) {
case AppThemeType.cupertino:
return Container(
color: theme.palette.background,
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,
),
);
default:
return TextField(
decoration: InputDecoration.collapsed(hintText: 'Search'),
textInputAction: TextInputAction.go,
onSubmitted: (_) => _query(),
controller: _controller,
);
}
}
_onTabSwitch(int index) {
setState(() {
_activeTab = index;
});
if (_projects.isEmpty || _users.isEmpty) {
_query();
}
}
static const tabs = ['Projects', 'Users'];
Widget _buildItem(p) {
switch (_activeTab) {
case 0:
final updatedAt = timeago.format(p.lastActivityAt);
return RepositoryItem.gl(
payload: p,
note: 'Updated $updatedAt',
);
case 1:
return UserItem(
login: p.username,
url: '/gitlab/user/${p.id}',
avatarUrl: p.avatarUrl,
bio: Text(p.bio ?? ''),
);
}
}
@override
Widget build(BuildContext context) {
final theme = Provider.of<ThemeModel>(context).theme;
final scaffold = CommonScaffold(
title: _buildInput(),
body: SingleChildScrollView(
child: Column(
children: [
if (theme == AppThemeType.cupertino)
Center(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 8),
child: CupertinoSlidingSegmentedControl(
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)),
))),
),
),
),
if (_loading)
Loading()
else if (_activeTab == 0)
..._projects.map(_buildItem).toList()
else
..._users.map(_buildItem).toList(),
],
),
),
bottom: TabBar(
onTap: _onTabSwitch,
tabs: tabs.map((text) => Tab(text: text.toUpperCase())).toList(),
),
);
if (theme == AppThemeType.material) {
return DefaultTabController(
length: tabs.length,
child: scaffold,
);
} else {
return scaffold;
}
}
}

View File

@ -68,7 +68,7 @@ class RepositoryItem extends StatelessWidget {
url = '/gitlab/projects/${payload.id}',
avatarLink = payload.namespace.kind == 'group'
? '/gitlab/group/${payload.namespace.id}'
: '/gitlab/user/${payload.owner.id}',
: '/gitlab/user/${payload.namespace.id}',
iconData = _buildGlIconData(payload.visibility);
RepositoryItem.gh({

View File

@ -27,7 +27,7 @@ dependencies:
flutter_markdown: ^0.3.3
shared_preferences: ^0.5.6
share: ^0.6.0
flutter_svg: ^0.13.0
flutter_svg: ^0.17.4
launch_review: ^2.0.0
timeago: ^2.0.18
provider: ^3.1.0