2020-05-09 07:37:36 +02:00
|
|
|
import 'package:flutter/cupertino.dart';
|
2022-09-17 14:35:45 +02:00
|
|
|
import 'package:flutter_gen/gen_l10n/S.dart';
|
|
|
|
import 'package:git_touch/models/auth.dart';
|
|
|
|
import 'package:git_touch/models/gitlab.dart';
|
2020-05-09 07:37:36 +02:00
|
|
|
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';
|
2022-09-17 14:35:45 +02:00
|
|
|
import 'package:git_touch/widgets/repository_item.dart';
|
2020-05-09 07:37:36 +02:00
|
|
|
import 'package:git_touch/widgets/user_item.dart';
|
|
|
|
import 'package:primer/primer.dart';
|
|
|
|
import 'package:provider/provider.dart';
|
|
|
|
import 'package:timeago/timeago.dart' as timeago;
|
|
|
|
|
|
|
|
class GlSearchScreen extends StatefulWidget {
|
|
|
|
@override
|
|
|
|
_GlSearchScreenState createState() => _GlSearchScreenState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _GlSearchScreenState extends State<GlSearchScreen> {
|
2021-05-16 09:16:35 +02:00
|
|
|
int? _activeTab = 0;
|
2020-05-09 07:37:36 +02:00
|
|
|
bool _loading = false;
|
2021-05-16 07:23:31 +02:00
|
|
|
List<GitlabProject> _projects = [];
|
|
|
|
List<GitlabUser> _users = [];
|
2020-05-09 07:37:36 +02:00
|
|
|
|
2021-05-16 09:16:35 +02:00
|
|
|
TextEditingController? _controller;
|
2020-05-09 07:37:36 +02:00
|
|
|
|
2021-06-05 07:54:52 +02:00
|
|
|
String get _keyword => _controller!.text.trim();
|
2020-05-09 07:37:36 +02:00
|
|
|
|
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
super.initState();
|
|
|
|
_controller = TextEditingController();
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void dispose() {
|
2021-05-16 09:16:35 +02:00
|
|
|
_controller!.dispose();
|
2020-05-09 07:37:36 +02:00
|
|
|
super.dispose();
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> _query() async {
|
|
|
|
if (_loading || _keyword.isEmpty) return;
|
|
|
|
|
2021-05-16 09:16:35 +02:00
|
|
|
var keyword = _controller!.text;
|
2020-05-09 07:37:36 +02:00
|
|
|
setState(() {
|
|
|
|
_loading = true;
|
|
|
|
});
|
|
|
|
try {
|
2020-10-04 14:37:23 +02:00
|
|
|
final auth = context.read<AuthModel>();
|
|
|
|
final projects = await auth
|
2020-05-09 07:37:36 +02:00
|
|
|
.fetchGitlabWithPage('/search?scope=projects&search=$keyword');
|
2020-10-04 14:37:23 +02:00
|
|
|
final users =
|
|
|
|
await auth.fetchGitlabWithPage('/search?scope=users&search=$keyword');
|
2020-05-09 07:37:36 +02:00
|
|
|
_projects = [for (var v in projects.data) GitlabProject.fromJson(v)];
|
|
|
|
_users = [for (var v in users.data) GitlabUser.fromJson(v)];
|
|
|
|
} finally {
|
|
|
|
setState(() {
|
|
|
|
_loading = false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-16 09:16:35 +02:00
|
|
|
_onTabSwitch(int? index) {
|
2020-05-09 07:37:36 +02:00
|
|
|
setState(() {
|
|
|
|
_activeTab = index;
|
|
|
|
});
|
|
|
|
if (_projects.isEmpty || _users.isEmpty) {
|
|
|
|
_query();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static const tabs = ['Projects', 'Users'];
|
|
|
|
|
2022-09-06 18:32:56 +02:00
|
|
|
Widget _buildItem(project) {
|
2021-01-30 08:42:02 +01:00
|
|
|
if (_activeTab == 0) {
|
2022-09-06 18:32:56 +02:00
|
|
|
final p = project as GitlabProject;
|
2021-05-16 09:16:35 +02:00
|
|
|
final updatedAt = timeago.format(p.lastActivityAt!);
|
2021-01-30 08:42:02 +01:00
|
|
|
return RepositoryItem.gl(
|
|
|
|
payload: p,
|
|
|
|
note: 'Updated $updatedAt',
|
|
|
|
);
|
|
|
|
} else {
|
2022-09-06 18:32:56 +02:00
|
|
|
final p = project as GitlabUser;
|
2021-01-30 08:42:02 +01:00
|
|
|
return UserItem.gitlab(
|
|
|
|
login: p.username,
|
|
|
|
name: p.name,
|
|
|
|
id: p.id,
|
|
|
|
avatarUrl: p.avatarUrl,
|
|
|
|
bio: Text(p.bio ?? ''),
|
|
|
|
);
|
2020-05-09 07:37:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2022-09-17 14:35:45 +02:00
|
|
|
final theme = Provider.of<ThemeModel>(context);
|
2020-05-09 07:37:36 +02:00
|
|
|
|
2022-09-17 14:35:45 +02:00
|
|
|
return CommonScaffold(
|
|
|
|
title: Container(
|
|
|
|
color: theme.palette.background,
|
|
|
|
child: CupertinoTextField(
|
|
|
|
prefix: Row(
|
|
|
|
children: const <Widget>[
|
|
|
|
SizedBox(width: 8),
|
|
|
|
Icon(Octicons.search, size: 20, color: PrimerColors.gray400),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
placeholder: AppLocalizations.of(context)!.search,
|
|
|
|
clearButtonMode: OverlayVisibilityMode.editing,
|
|
|
|
textInputAction: TextInputAction.go,
|
|
|
|
onSubmitted: (_) => _query(),
|
|
|
|
controller: _controller,
|
|
|
|
),
|
|
|
|
),
|
2020-05-09 07:37:36 +02:00
|
|
|
body: SingleChildScrollView(
|
|
|
|
child: Column(
|
|
|
|
children: [
|
2022-09-17 14:35:45 +02:00
|
|
|
Center(
|
|
|
|
child: Padding(
|
|
|
|
padding: const 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: const TextStyle(fontSize: 14)),
|
|
|
|
))),
|
2020-05-09 07:37:36 +02:00
|
|
|
),
|
|
|
|
),
|
2022-09-17 14:35:45 +02:00
|
|
|
),
|
2020-05-09 07:37:36 +02:00
|
|
|
if (_loading)
|
2022-09-06 18:32:56 +02:00
|
|
|
const Loading()
|
2020-05-09 07:37:36 +02:00
|
|
|
else if (_activeTab == 0)
|
|
|
|
..._projects.map(_buildItem).toList()
|
|
|
|
else
|
|
|
|
..._users.map(_buildItem).toList(),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|