1
0
mirror of https://github.com/git-touch/git-touch synced 2025-02-23 06:47:46 +01:00

feat(gitee): watch, star a repo (#157)

* feat(gitee): watch, star a repo

* fix: pass in props as Tuple

* feat: bitbucket branches

* fix: use class instead of map
This commit is contained in:
Shreyas Thirumalai 2021-01-11 20:01:54 +05:30 committed by GitHub
parent 2017014ffd
commit c75288ef97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 145 additions and 26 deletions

View File

@ -337,7 +337,15 @@ class AuthModel with ChangeNotifier {
'${activeAccount.domain}/api/v5$p',
headers: headers,
);
break;
return;
}
case 'PUT':
{
await http.put(
'${activeAccount.domain}/api/v5$p',
headers: headers,
);
return;
}
case 'POST':
{
@ -357,6 +365,12 @@ class AuthModel with ChangeNotifier {
);
break;
}
case 'NO CONTENT':
{
res = await http.get('${activeAccount.domain}/api/v5$p',
headers: headers);
return res;
}
default:
{
res = await http.get('${activeAccount.domain}/api/v5$p',
@ -364,12 +378,9 @@ class AuthModel with ChangeNotifier {
break;
}
}
if (requestType != 'DELETE') {
final info = json.decode(utf8.decode(res.bodyBytes));
return info;
}
return;
}
Future<DataWithPage> fetchGiteeWithPage(String path,
{int page, int limit}) async {

View File

@ -144,3 +144,12 @@ class BbComment {
factory BbComment.fromJson(Map<String, dynamic> json) =>
_$BbCommentFromJson(json);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class BbBranch {
String name;
String type;
BbBranch();
factory BbBranch.fromJson(Map<String, dynamic> json) =>
_$BbBranchFromJson(json);
}

View File

@ -247,3 +247,14 @@ Map<String, dynamic> _$BbCommentToJson(BbComment instance) => <String, dynamic>{
'content': instance.content,
'user': instance.user,
};
BbBranch _$BbBranchFromJson(Map<String, dynamic> json) {
return BbBranch()
..name = json['name'] as String
..type = json['type'] as String;
}
Map<String, dynamic> _$BbBranchToJson(BbBranch instance) => <String, dynamic>{
'name': instance.name,
'type': instance.type,
};

View File

@ -426,11 +426,14 @@ class BitbucketRouter {
'/:login',
(context, parameters) => BbUserScreen(parameters['login'].first,
isTeam: parameters['team'].first == '1'));
static final repo = RouterScreen(
'/:owner/:name',
(context, parameters) =>
BbRepoScreen(parameters['owner'].first, parameters['name'].first),
);
static final repo = RouterScreen('/:owner/:name', (context, parameters) {
if (parameters['branch'] == null) {
return BbRepoScreen(parameters['owner'].first, parameters['name'].first);
} else {
return BbRepoScreen(parameters['owner'].first, parameters['name'].first,
branch: parameters['branch'].first);
}
});
static final object = RouterScreen(
'/:owner/:name/src/:ref',
(context, parameters) => BbObjectScreen(

View File

@ -18,11 +18,12 @@ import '../generated/l10n.dart';
class BbRepoScreen extends StatelessWidget {
final String owner;
final String name;
BbRepoScreen(this.owner, this.name);
final String branch;
BbRepoScreen(this.owner, this.name, {this.branch});
@override
Widget build(BuildContext context) {
return RefreshStatefulScaffold<Tuple2<BbRepo, String>>(
return RefreshStatefulScaffold<Tuple3<BbRepo, String, List<BbBranch>>>(
title: AppBarTitle(S.of(context).repository),
fetch: () async {
final auth = context.read<AuthModel>();
@ -32,11 +33,17 @@ class BbRepoScreen extends StatelessWidget {
'/repositories/$owner/$name/src/${repo.mainbranch.name}/README.md');
final readme =
res.statusCode >= 400 ? null : utf8.decode(res.bodyBytes);
return Tuple2(repo, readme);
final branches = await auth
.fetchBbWithPage('/repositories/$owner/$name/refs/branches')
.then((v) {
return [for (var branch in v.data) BbBranch.fromJson(branch)];
});
return Tuple3(repo, readme, branches);
},
bodyBuilder: (t, setState) {
final theme = Provider.of<ThemeModel>(context);
final p = t.item1;
final branches = t.item3;
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
@ -56,7 +63,8 @@ class BbRepoScreen extends StatelessWidget {
leftIconData: Octicons.code,
text: Text('Code'),
rightWidget: Text(filesize(p.size)),
url: '/bitbucket/$owner/$name/src/${p.mainbranch.name}',
url:
'/bitbucket/$owner/$name/src/${branch == null ? p.mainbranch.name : branch}',
),
TableViewItem(
leftIconData: Octicons.issue_opened,
@ -71,7 +79,37 @@ class BbRepoScreen extends StatelessWidget {
TableViewItem(
leftIconData: Octicons.history,
text: Text('Commits'),
url: '/bitbucket/$owner/$name/commits/${p.mainbranch.name}',
url:
'/bitbucket/$owner/$name/commits/${branch == null ? p.mainbranch.name : branch}',
),
if (branches != null)
TableViewItem(
leftIconData: Octicons.git_branch,
text: Text(S.of(context).branches),
rightWidget: Text(
(branch == null ? p.mainbranch.name : branch) +
'' +
branches.length.toString()),
onTap: () async {
if (branches.length < 2) return;
await theme.showPicker(
context,
PickerGroupItem(
value: branch,
items: branches
.map((b) => PickerItem(b.name, text: b.name))
.toList(),
onClose: (ref) {
if (ref != branch) {
theme.push(context,
'/bitbucket/$owner/$name?branch=$ref',
replace: true);
}
},
),
);
},
),
],
),

View File

@ -1,4 +1,5 @@
import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/models/gitee.dart';
@ -8,6 +9,7 @@ import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:git_touch/widgets/entry_item.dart';
import 'package:git_touch/widgets/markdown_view.dart';
import 'package:git_touch/widgets/mutation_button.dart';
import 'package:git_touch/widgets/repo_header.dart';
import 'package:git_touch/widgets/table_view.dart';
import 'package:provider/provider.dart';
@ -15,6 +17,12 @@ import 'package:tuple/tuple.dart';
import 'package:http/http.dart' as http;
import '../generated/l10n.dart';
class StatusPayload {
bool isWatching;
bool isStarred;
StatusPayload(this.isWatching, this.isStarred);
}
class GeRepoScreen extends StatelessWidget {
final String owner;
final String name;
@ -24,7 +32,7 @@ class GeRepoScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return RefreshStatefulScaffold<
Tuple3<GiteeRepo, MarkdownViewData, List<GiteeBranch>>>(
Tuple4<GiteeRepo, MarkdownViewData, List<GiteeBranch>, StatusPayload>>(
title: AppBarTitle(S.of(context).repository),
fetch: () async {
final auth = context.read<AuthModel>();
@ -49,7 +57,15 @@ class GeRepoScreen extends StatelessWidget {
await auth.fetchGitee('/repos/$owner/$name/branches').then((v) {
return [for (var branch in v) GiteeBranch.fromJson(branch)];
});
return Tuple3(repo, readmeData, branches);
bool isStarred = await auth
.fetchGitee('/user/starred/$owner/$name', requestType: 'NO CONTENT')
.then((v) => v.statusCode == HttpStatus.noContent);
bool isWatching = await auth
.fetchGitee('/user/subscriptions/$owner/$name',
requestType: 'NO CONTENT')
.then((v) => v.statusCode == HttpStatus.noContent);
StatusPayload statusPayload = StatusPayload(isWatching, isStarred);
return Tuple4(repo, readmeData, branches, statusPayload);
},
bodyBuilder: (t, setState) {
final p = t.item1;
@ -65,11 +81,42 @@ class GeRepoScreen extends StatelessWidget {
name: p.path,
description: p.description,
homepageUrl: p.homepage,
actions: [
Row(children: <Widget>[
MutationButton(
active: t.item4.isWatching,
text: t.item4.isWatching ? 'Ignore' : 'Watch',
onTap: () async {
final String watchType =
t.item4.isWatching ? 'ignoring' : 'watching';
await context.read<AuthModel>().fetchGitee(
'/user/subscriptions/$owner/$name?watch_type=$watchType',
requestType: t.item4.isWatching ? 'DELETE' : 'PUT');
setState(() {
t.item4.isWatching = !t.item4.isWatching;
});
},
),
CommonStyle.border,
SizedBox(width: 8),
MutationButton(
active: t.item4.isStarred,
text: t.item4.isStarred ? 'Unstar' : 'Star',
onTap: () async {
await context.read<AuthModel>().fetchGitee(
'/user/starred/$owner/$name',
requestType: t.item4.isStarred ? 'DELETE' : 'PUT');
setState(() {
t.item4.isStarred = !t.item4.isStarred;
});
},
)
])
]),
Row(
children: <Widget>[
EntryItem(
count: p.watchersCount,
text: 'Watchers',
url: '/gitee/$owner/$name/watchers',
),