mirror of
https://github.com/git-touch/git-touch
synced 2025-01-31 16:14:49 +01:00
feat(bb): user screen
This commit is contained in:
parent
9eec13df9a
commit
830bceaa36
@ -3,6 +3,7 @@ import 'package:flutter/cupertino.dart';
|
|||||||
import 'package:git_touch/models/auth.dart';
|
import 'package:git_touch/models/auth.dart';
|
||||||
import 'package:git_touch/models/notification.dart';
|
import 'package:git_touch/models/notification.dart';
|
||||||
import 'package:git_touch/models/theme.dart';
|
import 'package:git_touch/models/theme.dart';
|
||||||
|
import 'package:git_touch/screens/bb_user.dart';
|
||||||
import 'package:git_touch/screens/gitea_orgs.dart';
|
import 'package:git_touch/screens/gitea_orgs.dart';
|
||||||
import 'package:git_touch/screens/gitea_user.dart';
|
import 'package:git_touch/screens/gitea_user.dart';
|
||||||
import 'package:git_touch/screens/gitlab_explore.dart';
|
import 'package:git_touch/screens/gitlab_explore.dart';
|
||||||
@ -60,6 +61,14 @@ class _HomeState extends State<Home> {
|
|||||||
return GitlabUserScreen(null);
|
return GitlabUserScreen(null);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case PlatformType.bitbucket:
|
||||||
|
switch (index) {
|
||||||
|
case 0:
|
||||||
|
return BbUserScreen(null);
|
||||||
|
case 1:
|
||||||
|
return BbUserScreen(null);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case PlatformType.gitea:
|
case PlatformType.gitea:
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -134,6 +143,17 @@ class _HomeState extends State<Home> {
|
|||||||
title: Text('Me'),
|
title: Text('Me'),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
case PlatformType.bitbucket:
|
||||||
|
return [
|
||||||
|
BottomNavigationBarItem(
|
||||||
|
icon: Icon(Icons.explore),
|
||||||
|
title: Text('Explore'),
|
||||||
|
),
|
||||||
|
BottomNavigationBarItem(
|
||||||
|
icon: Icon(Icons.person),
|
||||||
|
title: Text('Me'),
|
||||||
|
),
|
||||||
|
];
|
||||||
case PlatformType.gitea:
|
case PlatformType.gitea:
|
||||||
return [
|
return [
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
|
@ -32,7 +32,12 @@ class DataWithPage<T> {
|
|||||||
int cursor;
|
int cursor;
|
||||||
bool hasMore;
|
bool hasMore;
|
||||||
int total;
|
int total;
|
||||||
DataWithPage({this.data, this.cursor, this.hasMore, this.total});
|
DataWithPage({
|
||||||
|
@required this.data,
|
||||||
|
@required this.cursor,
|
||||||
|
@required this.hasMore,
|
||||||
|
this.total,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class AuthModel with ChangeNotifier {
|
class AuthModel with ChangeNotifier {
|
||||||
@ -242,6 +247,30 @@ class AuthModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future fetchBb(String p) async {
|
||||||
|
if (!p.startsWith('/api')) p = '/api/2.0$p';
|
||||||
|
final input = Uri.parse(p);
|
||||||
|
final uri = Uri.parse(activeAccount.domain).replace(
|
||||||
|
userInfo: '${activeAccount.login}:${activeAccount.appPassword}',
|
||||||
|
path: input.path,
|
||||||
|
query: input.query,
|
||||||
|
);
|
||||||
|
final res = await http.get(uri);
|
||||||
|
final info = json.decode(utf8.decode(res.bodyBytes));
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<DataWithPage<List>> fetchBbWithPage(String p) async {
|
||||||
|
final res = await fetchBb(p);
|
||||||
|
final v = BbPagination.fromJson(res);
|
||||||
|
return DataWithPage(
|
||||||
|
cursor: v.page,
|
||||||
|
total: v.size,
|
||||||
|
data: v.values,
|
||||||
|
hasMore: v.next != null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
// Listen scheme
|
// Listen scheme
|
||||||
_sub = getUriLinksStream().listen(_onSchemeDetected, onError: (err) {
|
_sub = getUriLinksStream().listen(_onSchemeDetected, onError: (err) {
|
||||||
|
@ -1,10 +1,24 @@
|
|||||||
import 'package:json_annotation/json_annotation.dart';
|
import 'package:json_annotation/json_annotation.dart';
|
||||||
part 'bitbucket.g.dart';
|
part 'bitbucket.g.dart';
|
||||||
|
|
||||||
|
@JsonSerializable(fieldRename: FieldRename.snake)
|
||||||
|
class BbPagination {
|
||||||
|
int pagelen;
|
||||||
|
int size;
|
||||||
|
int page;
|
||||||
|
String next;
|
||||||
|
List values;
|
||||||
|
BbPagination();
|
||||||
|
factory BbPagination.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$BbPaginationFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
@JsonSerializable(fieldRename: FieldRename.snake)
|
@JsonSerializable(fieldRename: FieldRename.snake)
|
||||||
class BbUser {
|
class BbUser {
|
||||||
String username;
|
String username;
|
||||||
|
String nickname;
|
||||||
String displayName;
|
String displayName;
|
||||||
|
String type; // user, team
|
||||||
bool isStaff;
|
bool isStaff;
|
||||||
DateTime createdOn;
|
DateTime createdOn;
|
||||||
Map<String, dynamic> links;
|
Map<String, dynamic> links;
|
||||||
@ -12,3 +26,22 @@ class BbUser {
|
|||||||
BbUser();
|
BbUser();
|
||||||
factory BbUser.fromJson(Map<String, dynamic> json) => _$BbUserFromJson(json);
|
factory BbUser.fromJson(Map<String, dynamic> json) => _$BbUserFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonSerializable(fieldRename: FieldRename.snake)
|
||||||
|
class BbRepo {
|
||||||
|
String name;
|
||||||
|
BbUser owner;
|
||||||
|
String website;
|
||||||
|
String language;
|
||||||
|
int size;
|
||||||
|
String type; // repository
|
||||||
|
bool isPrivate;
|
||||||
|
DateTime createdOn;
|
||||||
|
DateTime updatedOn;
|
||||||
|
String description;
|
||||||
|
String fullName;
|
||||||
|
Map<String, dynamic> links;
|
||||||
|
String get avatarUrl => links['avatar']['href'];
|
||||||
|
BbRepo();
|
||||||
|
factory BbRepo.fromJson(Map<String, dynamic> json) => _$BbRepoFromJson(json);
|
||||||
|
}
|
||||||
|
@ -6,10 +6,30 @@ part of 'bitbucket.dart';
|
|||||||
// JsonSerializableGenerator
|
// JsonSerializableGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
|
BbPagination _$BbPaginationFromJson(Map<String, dynamic> json) {
|
||||||
|
return BbPagination()
|
||||||
|
..pagelen = json['pagelen'] as int
|
||||||
|
..size = json['size'] as int
|
||||||
|
..page = json['page'] as int
|
||||||
|
..next = json['next'] as String
|
||||||
|
..values = json['values'] as List;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> _$BbPaginationToJson(BbPagination instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'pagelen': instance.pagelen,
|
||||||
|
'size': instance.size,
|
||||||
|
'page': instance.page,
|
||||||
|
'next': instance.next,
|
||||||
|
'values': instance.values,
|
||||||
|
};
|
||||||
|
|
||||||
BbUser _$BbUserFromJson(Map<String, dynamic> json) {
|
BbUser _$BbUserFromJson(Map<String, dynamic> json) {
|
||||||
return BbUser()
|
return BbUser()
|
||||||
..username = json['username'] as String
|
..username = json['username'] as String
|
||||||
|
..nickname = json['nickname'] as String
|
||||||
..displayName = json['display_name'] as String
|
..displayName = json['display_name'] as String
|
||||||
|
..type = json['type'] as String
|
||||||
..isStaff = json['is_staff'] as bool
|
..isStaff = json['is_staff'] as bool
|
||||||
..createdOn = json['created_on'] == null
|
..createdOn = json['created_on'] == null
|
||||||
? null
|
? null
|
||||||
@ -19,8 +39,47 @@ BbUser _$BbUserFromJson(Map<String, dynamic> json) {
|
|||||||
|
|
||||||
Map<String, dynamic> _$BbUserToJson(BbUser instance) => <String, dynamic>{
|
Map<String, dynamic> _$BbUserToJson(BbUser instance) => <String, dynamic>{
|
||||||
'username': instance.username,
|
'username': instance.username,
|
||||||
|
'nickname': instance.nickname,
|
||||||
'display_name': instance.displayName,
|
'display_name': instance.displayName,
|
||||||
|
'type': instance.type,
|
||||||
'is_staff': instance.isStaff,
|
'is_staff': instance.isStaff,
|
||||||
'created_on': instance.createdOn?.toIso8601String(),
|
'created_on': instance.createdOn?.toIso8601String(),
|
||||||
'links': instance.links,
|
'links': instance.links,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
BbRepo _$BbRepoFromJson(Map<String, dynamic> json) {
|
||||||
|
return BbRepo()
|
||||||
|
..name = json['name'] as String
|
||||||
|
..owner = json['owner'] == null
|
||||||
|
? null
|
||||||
|
: BbUser.fromJson(json['owner'] as Map<String, dynamic>)
|
||||||
|
..website = json['website'] as String
|
||||||
|
..language = json['language'] as String
|
||||||
|
..size = json['size'] as int
|
||||||
|
..type = json['type'] as String
|
||||||
|
..isPrivate = json['is_private'] as bool
|
||||||
|
..createdOn = json['created_on'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['created_on'] as String)
|
||||||
|
..updatedOn = json['updated_on'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['updated_on'] as String)
|
||||||
|
..description = json['description'] as String
|
||||||
|
..fullName = json['full_name'] as String
|
||||||
|
..links = json['links'] as Map<String, dynamic>;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> _$BbRepoToJson(BbRepo instance) => <String, dynamic>{
|
||||||
|
'name': instance.name,
|
||||||
|
'owner': instance.owner,
|
||||||
|
'website': instance.website,
|
||||||
|
'language': instance.language,
|
||||||
|
'size': instance.size,
|
||||||
|
'type': instance.type,
|
||||||
|
'is_private': instance.isPrivate,
|
||||||
|
'created_on': instance.createdOn?.toIso8601String(),
|
||||||
|
'updated_on': instance.updatedOn?.toIso8601String(),
|
||||||
|
'description': instance.description,
|
||||||
|
'full_name': instance.fullName,
|
||||||
|
'links': instance.links,
|
||||||
|
};
|
||||||
|
78
lib/screens/bb_user.dart
Normal file
78
lib/screens/bb_user.dart
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
import 'package:git_touch/models/auth.dart';
|
||||||
|
import 'package:git_touch/models/bitbucket.dart';
|
||||||
|
import 'package:git_touch/scaffolds/refresh_stateful.dart';
|
||||||
|
import 'package:git_touch/widgets/action_entry.dart';
|
||||||
|
import 'package:git_touch/widgets/repository_item.dart';
|
||||||
|
import 'package:git_touch/widgets/user_header.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:tuple/tuple.dart';
|
||||||
|
import 'package:git_touch/utils/utils.dart';
|
||||||
|
import 'package:timeago/timeago.dart' as timeago;
|
||||||
|
|
||||||
|
class BbUserScreen extends StatelessWidget {
|
||||||
|
final String login;
|
||||||
|
BbUserScreen(this.login);
|
||||||
|
bool get isViewer => login == null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return RefreshStatefulScaffold<Tuple2<BbUser, Iterable<BbRepo>>>(
|
||||||
|
title: Text(isViewer ? 'Me' : 'User'),
|
||||||
|
fetchData: () async {
|
||||||
|
final auth = Provider.of<AuthModel>(context);
|
||||||
|
final _login = login ?? auth.activeAccount.login;
|
||||||
|
final res = await Future.wait([
|
||||||
|
auth.fetchBb('/users/$_login'),
|
||||||
|
auth.fetchBbWithPage('/repositories/$_login'),
|
||||||
|
]);
|
||||||
|
return Tuple2(
|
||||||
|
BbUser.fromJson(res[0]),
|
||||||
|
[
|
||||||
|
for (var v in (res[1] as DataWithPage<List>).data)
|
||||||
|
BbRepo.fromJson(v)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
action: isViewer
|
||||||
|
? ActionEntry(
|
||||||
|
iconData: Icons.settings,
|
||||||
|
url: '/settings',
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
bodyBuilder: (data, _) {
|
||||||
|
final user = data.item1;
|
||||||
|
final repos = data.item2;
|
||||||
|
return Column(
|
||||||
|
children: <Widget>[
|
||||||
|
UserHeader(
|
||||||
|
login: user.displayName,
|
||||||
|
avatarUrl: user.avatarUrl,
|
||||||
|
name: user.nickname,
|
||||||
|
createdAt: user.createdOn,
|
||||||
|
bio: null,
|
||||||
|
),
|
||||||
|
CommonStyle.border,
|
||||||
|
Column(
|
||||||
|
children: <Widget>[
|
||||||
|
for (var v in repos)
|
||||||
|
RepositoryItem(
|
||||||
|
owner: v.owner.displayName,
|
||||||
|
name: v.name,
|
||||||
|
url: '/bitbucket/${v.fullName}',
|
||||||
|
avatarUrl: v.avatarUrl,
|
||||||
|
avatarLink: '/bitbucket/${v.owner.displayName}',
|
||||||
|
note: 'Updated ${timeago.format(v.updatedOn)}',
|
||||||
|
description: v.description,
|
||||||
|
forkCount: 0,
|
||||||
|
starCount: 0,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user