Reason Pun

增加了一言搜索页面

......@@ -95,18 +95,18 @@ class JsonConvert {
}
//list is returned by type
static M? _getListChildType<M>(List<dynamic> data) {
static M? _getListChildType<M>(List<Map<String, dynamic>> data) {
if(<UserEntity>[] is M){
return data.map<UserEntity>((e) => UserEntity.fromJson(e)).toList() as M;
return data.map<UserEntity>((Map<String, dynamic> e) => UserEntity.fromJson(e)).toList() as M;
}
if(<CategoryItemEntity>[] is M){
return data.map<CategoryItemEntity>((e) => CategoryItemEntity.fromJson(e)).toList() as M;
return data.map<CategoryItemEntity>((Map<String, dynamic> e) => CategoryItemEntity.fromJson(e)).toList() as M;
}
if(<FriendEntity>[] is M){
return data.map<FriendEntity>((e) => FriendEntity.fromJson(e)).toList() as M;
return data.map<FriendEntity>((Map<String, dynamic> e) => FriendEntity.fromJson(e)).toList() as M;
}
if(<FriendData>[] is M){
return data.map<FriendData>((e) => FriendData.fromJson(e)).toList() as M;
return data.map<FriendData>((Map<String, dynamic> e) => FriendData.fromJson(e)).toList() as M;
}
print("${M.toString()} not found");
......@@ -117,9 +117,8 @@ class JsonConvert {
static M? fromJsonAsT<M>(dynamic json) {
if(json == null){
return null;
}
if (json is List) {
return _getListChildType<M>(json);
} if (json is List) {
return _getListChildType<M>(json.map((e) => e as Map<String, dynamic>).toList());
} else {
return _fromJsonSingle<M>(json as Map<String, dynamic>);
}
......
import 'package:one_poem/generated/json/base/json_convert_content.dart';
import 'package:one_poem/poem/models/search_entity.dart';
SearchEntity $SearchEntityFromJson(Map<String, dynamic> json) {
final SearchEntity searchEntity = SearchEntity();
final int? totalCount = jsonConvert.convert<int>(json['total_count']);
if (totalCount != null) {
searchEntity.totalCount = totalCount;
}
final bool? incompleteResults =
jsonConvert.convert<bool>(json['incomplete_results']);
if (incompleteResults != null) {
searchEntity.incompleteResults = incompleteResults;
}
final List<SearchItems>? items =
jsonConvert.convertListNotNull<SearchItems>(json['items']);
if (items != null) {
searchEntity.items = items;
}
return searchEntity;
}
Map<String, dynamic> $SearchEntityToJson(SearchEntity entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['total_count'] = entity.totalCount;
data['incomplete_results'] = entity.incompleteResults;
data['items'] = entity.items?.map((v) => v.toJson()).toList();
return data;
}
SearchItems $SearchItemsFromJson(Map<String, dynamic> json) {
final SearchItems searchItems = SearchItems();
final int? id = jsonConvert.convert<int>(json['id']);
if (id != null) {
searchItems.id = id;
}
final String? nodeId = jsonConvert.convert<String>(json['node_id']);
if (nodeId != null) {
searchItems.nodeId = nodeId;
}
final String? name = jsonConvert.convert<String>(json['name']);
if (name != null) {
searchItems.name = name;
}
final String? fullName = jsonConvert.convert<String>(json['full_name']);
if (fullName != null) {
searchItems.fullName = fullName;
}
final bool? private = jsonConvert.convert<bool>(json['private']);
if (private != null) {
searchItems.private = private;
}
final SearchItemsOwner? owner =
jsonConvert.convert<SearchItemsOwner>(json['owner']);
if (owner != null) {
searchItems.owner = owner;
}
final String? htmlUrl = jsonConvert.convert<String>(json['html_url']);
if (htmlUrl != null) {
searchItems.htmlUrl = htmlUrl;
}
final String? description = jsonConvert.convert<String>(json['description']);
if (description != null) {
searchItems.description = description;
}
final bool? fork = jsonConvert.convert<bool>(json['fork']);
if (fork != null) {
searchItems.fork = fork;
}
final String? url = jsonConvert.convert<String>(json['url']);
if (url != null) {
searchItems.url = url;
}
final String? forksUrl = jsonConvert.convert<String>(json['forks_url']);
if (forksUrl != null) {
searchItems.forksUrl = forksUrl;
}
final String? keysUrl = jsonConvert.convert<String>(json['keys_url']);
if (keysUrl != null) {
searchItems.keysUrl = keysUrl;
}
final String? collaboratorsUrl =
jsonConvert.convert<String>(json['collaborators_url']);
if (collaboratorsUrl != null) {
searchItems.collaboratorsUrl = collaboratorsUrl;
}
final String? teamsUrl = jsonConvert.convert<String>(json['teams_url']);
if (teamsUrl != null) {
searchItems.teamsUrl = teamsUrl;
}
final String? hooksUrl = jsonConvert.convert<String>(json['hooks_url']);
if (hooksUrl != null) {
searchItems.hooksUrl = hooksUrl;
}
final String? issueEventsUrl =
jsonConvert.convert<String>(json['issue_events_url']);
if (issueEventsUrl != null) {
searchItems.issueEventsUrl = issueEventsUrl;
}
final String? eventsUrl = jsonConvert.convert<String>(json['events_url']);
if (eventsUrl != null) {
searchItems.eventsUrl = eventsUrl;
}
final String? assigneesUrl =
jsonConvert.convert<String>(json['assignees_url']);
if (assigneesUrl != null) {
searchItems.assigneesUrl = assigneesUrl;
}
final String? branchesUrl = jsonConvert.convert<String>(json['branches_url']);
if (branchesUrl != null) {
searchItems.branchesUrl = branchesUrl;
}
final String? tagsUrl = jsonConvert.convert<String>(json['tags_url']);
if (tagsUrl != null) {
searchItems.tagsUrl = tagsUrl;
}
final String? blobsUrl = jsonConvert.convert<String>(json['blobs_url']);
if (blobsUrl != null) {
searchItems.blobsUrl = blobsUrl;
}
final String? gitTagsUrl = jsonConvert.convert<String>(json['git_tags_url']);
if (gitTagsUrl != null) {
searchItems.gitTagsUrl = gitTagsUrl;
}
final String? gitRefsUrl = jsonConvert.convert<String>(json['git_refs_url']);
if (gitRefsUrl != null) {
searchItems.gitRefsUrl = gitRefsUrl;
}
final String? treesUrl = jsonConvert.convert<String>(json['trees_url']);
if (treesUrl != null) {
searchItems.treesUrl = treesUrl;
}
final String? statusesUrl = jsonConvert.convert<String>(json['statuses_url']);
if (statusesUrl != null) {
searchItems.statusesUrl = statusesUrl;
}
final String? languagesUrl =
jsonConvert.convert<String>(json['languages_url']);
if (languagesUrl != null) {
searchItems.languagesUrl = languagesUrl;
}
final String? stargazersUrl =
jsonConvert.convert<String>(json['stargazers_url']);
if (stargazersUrl != null) {
searchItems.stargazersUrl = stargazersUrl;
}
final String? contributorsUrl =
jsonConvert.convert<String>(json['contributors_url']);
if (contributorsUrl != null) {
searchItems.contributorsUrl = contributorsUrl;
}
final String? subscribersUrl =
jsonConvert.convert<String>(json['subscribers_url']);
if (subscribersUrl != null) {
searchItems.subscribersUrl = subscribersUrl;
}
final String? subscriptionUrl =
jsonConvert.convert<String>(json['subscription_url']);
if (subscriptionUrl != null) {
searchItems.subscriptionUrl = subscriptionUrl;
}
final String? commitsUrl = jsonConvert.convert<String>(json['commits_url']);
if (commitsUrl != null) {
searchItems.commitsUrl = commitsUrl;
}
final String? gitCommitsUrl =
jsonConvert.convert<String>(json['git_commits_url']);
if (gitCommitsUrl != null) {
searchItems.gitCommitsUrl = gitCommitsUrl;
}
final String? commentsUrl = jsonConvert.convert<String>(json['comments_url']);
if (commentsUrl != null) {
searchItems.commentsUrl = commentsUrl;
}
final String? issueCommentUrl =
jsonConvert.convert<String>(json['issue_comment_url']);
if (issueCommentUrl != null) {
searchItems.issueCommentUrl = issueCommentUrl;
}
final String? contentsUrl = jsonConvert.convert<String>(json['contents_url']);
if (contentsUrl != null) {
searchItems.contentsUrl = contentsUrl;
}
final String? compareUrl = jsonConvert.convert<String>(json['compare_url']);
if (compareUrl != null) {
searchItems.compareUrl = compareUrl;
}
final String? mergesUrl = jsonConvert.convert<String>(json['merges_url']);
if (mergesUrl != null) {
searchItems.mergesUrl = mergesUrl;
}
final String? archiveUrl = jsonConvert.convert<String>(json['archive_url']);
if (archiveUrl != null) {
searchItems.archiveUrl = archiveUrl;
}
final String? downloadsUrl =
jsonConvert.convert<String>(json['downloads_url']);
if (downloadsUrl != null) {
searchItems.downloadsUrl = downloadsUrl;
}
final String? issuesUrl = jsonConvert.convert<String>(json['issues_url']);
if (issuesUrl != null) {
searchItems.issuesUrl = issuesUrl;
}
final String? pullsUrl = jsonConvert.convert<String>(json['pulls_url']);
if (pullsUrl != null) {
searchItems.pullsUrl = pullsUrl;
}
final String? milestonesUrl =
jsonConvert.convert<String>(json['milestones_url']);
if (milestonesUrl != null) {
searchItems.milestonesUrl = milestonesUrl;
}
final String? notificationsUrl =
jsonConvert.convert<String>(json['notifications_url']);
if (notificationsUrl != null) {
searchItems.notificationsUrl = notificationsUrl;
}
final String? labelsUrl = jsonConvert.convert<String>(json['labels_url']);
if (labelsUrl != null) {
searchItems.labelsUrl = labelsUrl;
}
final String? releasesUrl = jsonConvert.convert<String>(json['releases_url']);
if (releasesUrl != null) {
searchItems.releasesUrl = releasesUrl;
}
final String? deploymentsUrl =
jsonConvert.convert<String>(json['deployments_url']);
if (deploymentsUrl != null) {
searchItems.deploymentsUrl = deploymentsUrl;
}
final String? createdAt = jsonConvert.convert<String>(json['created_at']);
if (createdAt != null) {
searchItems.createdAt = createdAt;
}
final String? updatedAt = jsonConvert.convert<String>(json['updated_at']);
if (updatedAt != null) {
searchItems.updatedAt = updatedAt;
}
final String? pushedAt = jsonConvert.convert<String>(json['pushed_at']);
if (pushedAt != null) {
searchItems.pushedAt = pushedAt;
}
final String? gitUrl = jsonConvert.convert<String>(json['git_url']);
if (gitUrl != null) {
searchItems.gitUrl = gitUrl;
}
final String? sshUrl = jsonConvert.convert<String>(json['ssh_url']);
if (sshUrl != null) {
searchItems.sshUrl = sshUrl;
}
final String? cloneUrl = jsonConvert.convert<String>(json['clone_url']);
if (cloneUrl != null) {
searchItems.cloneUrl = cloneUrl;
}
final String? svnUrl = jsonConvert.convert<String>(json['svn_url']);
if (svnUrl != null) {
searchItems.svnUrl = svnUrl;
}
final String? homepage = jsonConvert.convert<String>(json['homepage']);
if (homepage != null) {
searchItems.homepage = homepage;
}
final int? size = jsonConvert.convert<int>(json['size']);
if (size != null) {
searchItems.size = size;
}
final int? stargazersCount =
jsonConvert.convert<int>(json['stargazers_count']);
if (stargazersCount != null) {
searchItems.stargazersCount = stargazersCount;
}
final int? watchersCount = jsonConvert.convert<int>(json['watchers_count']);
if (watchersCount != null) {
searchItems.watchersCount = watchersCount;
}
final String? language = jsonConvert.convert<String>(json['language']);
if (language != null) {
searchItems.language = language;
}
final bool? hasIssues = jsonConvert.convert<bool>(json['has_issues']);
if (hasIssues != null) {
searchItems.hasIssues = hasIssues;
}
final bool? hasProjects = jsonConvert.convert<bool>(json['has_projects']);
if (hasProjects != null) {
searchItems.hasProjects = hasProjects;
}
final bool? hasDownloads = jsonConvert.convert<bool>(json['has_downloads']);
if (hasDownloads != null) {
searchItems.hasDownloads = hasDownloads;
}
final bool? hasWiki = jsonConvert.convert<bool>(json['has_wiki']);
if (hasWiki != null) {
searchItems.hasWiki = hasWiki;
}
final bool? hasPages = jsonConvert.convert<bool>(json['has_pages']);
if (hasPages != null) {
searchItems.hasPages = hasPages;
}
final int? forksCount = jsonConvert.convert<int>(json['forks_count']);
if (forksCount != null) {
searchItems.forksCount = forksCount;
}
final bool? archived = jsonConvert.convert<bool>(json['archived']);
if (archived != null) {
searchItems.archived = archived;
}
final bool? disabled = jsonConvert.convert<bool>(json['disabled']);
if (disabled != null) {
searchItems.disabled = disabled;
}
final int? openIssuesCount =
jsonConvert.convert<int>(json['open_issues_count']);
if (openIssuesCount != null) {
searchItems.openIssuesCount = openIssuesCount;
}
final SearchItemsLicense? license =
jsonConvert.convert<SearchItemsLicense>(json['license']);
if (license != null) {
searchItems.license = license;
}
final int? forks = jsonConvert.convert<int>(json['forks']);
if (forks != null) {
searchItems.forks = forks;
}
final int? openIssues = jsonConvert.convert<int>(json['open_issues']);
if (openIssues != null) {
searchItems.openIssues = openIssues;
}
final int? watchers = jsonConvert.convert<int>(json['watchers']);
if (watchers != null) {
searchItems.watchers = watchers;
}
final String? defaultBranch =
jsonConvert.convert<String>(json['default_branch']);
if (defaultBranch != null) {
searchItems.defaultBranch = defaultBranch;
}
final double? score = jsonConvert.convert<double>(json['score']);
if (score != null) {
searchItems.score = score;
}
return searchItems;
}
Map<String, dynamic> $SearchItemsToJson(SearchItems entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = entity.id;
data['node_id'] = entity.nodeId;
data['name'] = entity.name;
data['full_name'] = entity.fullName;
data['private'] = entity.private;
data['owner'] = entity.owner?.toJson();
data['html_url'] = entity.htmlUrl;
data['description'] = entity.description;
data['fork'] = entity.fork;
data['url'] = entity.url;
data['forks_url'] = entity.forksUrl;
data['keys_url'] = entity.keysUrl;
data['collaborators_url'] = entity.collaboratorsUrl;
data['teams_url'] = entity.teamsUrl;
data['hooks_url'] = entity.hooksUrl;
data['issue_events_url'] = entity.issueEventsUrl;
data['events_url'] = entity.eventsUrl;
data['assignees_url'] = entity.assigneesUrl;
data['branches_url'] = entity.branchesUrl;
data['tags_url'] = entity.tagsUrl;
data['blobs_url'] = entity.blobsUrl;
data['git_tags_url'] = entity.gitTagsUrl;
data['git_refs_url'] = entity.gitRefsUrl;
data['trees_url'] = entity.treesUrl;
data['statuses_url'] = entity.statusesUrl;
data['languages_url'] = entity.languagesUrl;
data['stargazers_url'] = entity.stargazersUrl;
data['contributors_url'] = entity.contributorsUrl;
data['subscribers_url'] = entity.subscribersUrl;
data['subscription_url'] = entity.subscriptionUrl;
data['commits_url'] = entity.commitsUrl;
data['git_commits_url'] = entity.gitCommitsUrl;
data['comments_url'] = entity.commentsUrl;
data['issue_comment_url'] = entity.issueCommentUrl;
data['contents_url'] = entity.contentsUrl;
data['compare_url'] = entity.compareUrl;
data['merges_url'] = entity.mergesUrl;
data['archive_url'] = entity.archiveUrl;
data['downloads_url'] = entity.downloadsUrl;
data['issues_url'] = entity.issuesUrl;
data['pulls_url'] = entity.pullsUrl;
data['milestones_url'] = entity.milestonesUrl;
data['notifications_url'] = entity.notificationsUrl;
data['labels_url'] = entity.labelsUrl;
data['releases_url'] = entity.releasesUrl;
data['deployments_url'] = entity.deploymentsUrl;
data['created_at'] = entity.createdAt;
data['updated_at'] = entity.updatedAt;
data['pushed_at'] = entity.pushedAt;
data['git_url'] = entity.gitUrl;
data['ssh_url'] = entity.sshUrl;
data['clone_url'] = entity.cloneUrl;
data['svn_url'] = entity.svnUrl;
data['homepage'] = entity.homepage;
data['size'] = entity.size;
data['stargazers_count'] = entity.stargazersCount;
data['watchers_count'] = entity.watchersCount;
data['language'] = entity.language;
data['has_issues'] = entity.hasIssues;
data['has_projects'] = entity.hasProjects;
data['has_downloads'] = entity.hasDownloads;
data['has_wiki'] = entity.hasWiki;
data['has_pages'] = entity.hasPages;
data['forks_count'] = entity.forksCount;
data['archived'] = entity.archived;
data['disabled'] = entity.disabled;
data['open_issues_count'] = entity.openIssuesCount;
data['license'] = entity.license?.toJson();
data['forks'] = entity.forks;
data['open_issues'] = entity.openIssues;
data['watchers'] = entity.watchers;
data['default_branch'] = entity.defaultBranch;
data['score'] = entity.score;
return data;
}
SearchItemsOwner $SearchItemsOwnerFromJson(Map<String, dynamic> json) {
final SearchItemsOwner searchItemsOwner = SearchItemsOwner();
final String? login = jsonConvert.convert<String>(json['login']);
if (login != null) {
searchItemsOwner.login = login;
}
final int? id = jsonConvert.convert<int>(json['id']);
if (id != null) {
searchItemsOwner.id = id;
}
final String? nodeId = jsonConvert.convert<String>(json['node_id']);
if (nodeId != null) {
searchItemsOwner.nodeId = nodeId;
}
final String? avatarUrl = jsonConvert.convert<String>(json['avatar_url']);
if (avatarUrl != null) {
searchItemsOwner.avatarUrl = avatarUrl;
}
final String? gravatarId = jsonConvert.convert<String>(json['gravatar_id']);
if (gravatarId != null) {
searchItemsOwner.gravatarId = gravatarId;
}
final String? url = jsonConvert.convert<String>(json['url']);
if (url != null) {
searchItemsOwner.url = url;
}
final String? htmlUrl = jsonConvert.convert<String>(json['html_url']);
if (htmlUrl != null) {
searchItemsOwner.htmlUrl = htmlUrl;
}
final String? followersUrl =
jsonConvert.convert<String>(json['followers_url']);
if (followersUrl != null) {
searchItemsOwner.followersUrl = followersUrl;
}
final String? followingUrl =
jsonConvert.convert<String>(json['following_url']);
if (followingUrl != null) {
searchItemsOwner.followingUrl = followingUrl;
}
final String? gistsUrl = jsonConvert.convert<String>(json['gists_url']);
if (gistsUrl != null) {
searchItemsOwner.gistsUrl = gistsUrl;
}
final String? starredUrl = jsonConvert.convert<String>(json['starred_url']);
if (starredUrl != null) {
searchItemsOwner.starredUrl = starredUrl;
}
final String? subscriptionsUrl =
jsonConvert.convert<String>(json['subscriptions_url']);
if (subscriptionsUrl != null) {
searchItemsOwner.subscriptionsUrl = subscriptionsUrl;
}
final String? organizationsUrl =
jsonConvert.convert<String>(json['organizations_url']);
if (organizationsUrl != null) {
searchItemsOwner.organizationsUrl = organizationsUrl;
}
final String? reposUrl = jsonConvert.convert<String>(json['repos_url']);
if (reposUrl != null) {
searchItemsOwner.reposUrl = reposUrl;
}
final String? eventsUrl = jsonConvert.convert<String>(json['events_url']);
if (eventsUrl != null) {
searchItemsOwner.eventsUrl = eventsUrl;
}
final String? receivedEventsUrl =
jsonConvert.convert<String>(json['received_events_url']);
if (receivedEventsUrl != null) {
searchItemsOwner.receivedEventsUrl = receivedEventsUrl;
}
final String? type = jsonConvert.convert<String>(json['type']);
if (type != null) {
searchItemsOwner.type = type;
}
final bool? siteAdmin = jsonConvert.convert<bool>(json['site_admin']);
if (siteAdmin != null) {
searchItemsOwner.siteAdmin = siteAdmin;
}
return searchItemsOwner;
}
Map<String, dynamic> $SearchItemsOwnerToJson(SearchItemsOwner entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['login'] = entity.login;
data['id'] = entity.id;
data['node_id'] = entity.nodeId;
data['avatar_url'] = entity.avatarUrl;
data['gravatar_id'] = entity.gravatarId;
data['url'] = entity.url;
data['html_url'] = entity.htmlUrl;
data['followers_url'] = entity.followersUrl;
data['following_url'] = entity.followingUrl;
data['gists_url'] = entity.gistsUrl;
data['starred_url'] = entity.starredUrl;
data['subscriptions_url'] = entity.subscriptionsUrl;
data['organizations_url'] = entity.organizationsUrl;
data['repos_url'] = entity.reposUrl;
data['events_url'] = entity.eventsUrl;
data['received_events_url'] = entity.receivedEventsUrl;
data['type'] = entity.type;
data['site_admin'] = entity.siteAdmin;
return data;
}
SearchItemsLicense $SearchItemsLicenseFromJson(Map<String, dynamic> json) {
final SearchItemsLicense searchItemsLicense = SearchItemsLicense();
final String? key = jsonConvert.convert<String>(json['key']);
if (key != null) {
searchItemsLicense.key = key;
}
final String? name = jsonConvert.convert<String>(json['name']);
if (name != null) {
searchItemsLicense.name = name;
}
final String? spdxId = jsonConvert.convert<String>(json['spdx_id']);
if (spdxId != null) {
searchItemsLicense.spdxId = spdxId;
}
final String? url = jsonConvert.convert<String>(json['url']);
if (url != null) {
searchItemsLicense.url = url;
}
final String? nodeId = jsonConvert.convert<String>(json['node_id']);
if (nodeId != null) {
searchItemsLicense.nodeId = nodeId;
}
return searchItemsLicense;
}
Map<String, dynamic> $SearchItemsLicenseToJson(SearchItemsLicense entity) {
final Map<String, dynamic> data = <String, dynamic>{};
data['key'] = entity.key;
data['name'] = entity.name;
data['spdx_id'] = entity.spdxId;
data['url'] = entity.url;
data['node_id'] = entity.nodeId;
return data;
}
import 'base_page.dart';
import 'base_page_presenter.dart';
import 'base_presenter.dart';
/// 管理多个Presenter,实现复用。
class PowerPresenter<IMvpView> extends BasePresenter {
PowerPresenter(BasePageMixin state) {
_state = state;
}
......@@ -43,10 +40,10 @@ class PowerPresenter<IMvpView> extends BasePresenter {
@override
void didUpdateWidgets<W>(W oldWidget) {
void _didUpdateWidgets(BasePagePresenter presenter) {
presenter.didUpdateWidgets<W>(oldWidget);
}
_presenters.forEach(_didUpdateWidgets);
}
......@@ -67,5 +64,4 @@ class PowerPresenter<IMvpView> extends BasePresenter {
void _initState(BasePagePresenter presenter) {
presenter.initState();
}
}
......
import 'package:one_poem/mvp/mvps.dart';
import 'package:one_poem/poem/models/search_entity.dart';
import 'package:one_poem/poem/provider/base_list_provider.dart';
abstract class PoemSearchIMvpView implements IMvpView {
BaseListProvider<SearchItems> get provider;
}
import 'package:one_poem/generated/json/base/json_field.dart';
import 'package:one_poem/generated/json/search_entity.g.dart';
@JsonSerializable()
class SearchEntity {
SearchEntity();
factory SearchEntity.fromJson(Map<String, dynamic> json) => $SearchEntityFromJson(json);
Map<String, dynamic> toJson() => $SearchEntityToJson(this);
@JSONField(name: 'total_count')
int? totalCount;
@JSONField(name: 'incomplete_results')
bool? incompleteResults;
List<SearchItems>? items;
}
@JsonSerializable()
class SearchItems {
SearchItems();
factory SearchItems.fromJson(Map<String, dynamic> json) => $SearchItemsFromJson(json);
Map<String, dynamic> toJson() => $SearchItemsToJson(this);
int? id;
@JSONField(name: 'node_id')
String? nodeId;
String? name;
@JSONField(name: 'full_name')
String? fullName;
bool? private;
SearchItemsOwner? owner;
@JSONField(name: 'html_url')
String? htmlUrl;
String? description;
bool? fork;
String? url;
@JSONField(name: 'forks_url')
String? forksUrl;
@JSONField(name: 'keys_url')
String? keysUrl;
@JSONField(name: 'collaborators_url')
String? collaboratorsUrl;
@JSONField(name: 'teams_url')
String? teamsUrl;
@JSONField(name: 'hooks_url')
String? hooksUrl;
@JSONField(name: 'issue_events_url')
String? issueEventsUrl;
@JSONField(name: 'events_url')
String? eventsUrl;
@JSONField(name: 'assignees_url')
String? assigneesUrl;
@JSONField(name: 'branches_url')
String? branchesUrl;
@JSONField(name: 'tags_url')
String? tagsUrl;
@JSONField(name: 'blobs_url')
String? blobsUrl;
@JSONField(name: 'git_tags_url')
String? gitTagsUrl;
@JSONField(name: 'git_refs_url')
String? gitRefsUrl;
@JSONField(name: 'trees_url')
String? treesUrl;
@JSONField(name: 'statuses_url')
String? statusesUrl;
@JSONField(name: 'languages_url')
String? languagesUrl;
@JSONField(name: 'stargazers_url')
String? stargazersUrl;
@JSONField(name: 'contributors_url')
String? contributorsUrl;
@JSONField(name: 'subscribers_url')
String? subscribersUrl;
@JSONField(name: 'subscription_url')
String? subscriptionUrl;
@JSONField(name: 'commits_url')
String? commitsUrl;
@JSONField(name: 'git_commits_url')
String? gitCommitsUrl;
@JSONField(name: 'comments_url')
String? commentsUrl;
@JSONField(name: 'issue_comment_url')
String? issueCommentUrl;
@JSONField(name: 'contents_url')
String? contentsUrl;
@JSONField(name: 'compare_url')
String? compareUrl;
@JSONField(name: 'merges_url')
String? mergesUrl;
@JSONField(name: 'archive_url')
String? archiveUrl;
@JSONField(name: 'downloads_url')
String? downloadsUrl;
@JSONField(name: 'issues_url')
String? issuesUrl;
@JSONField(name: 'pulls_url')
String? pullsUrl;
@JSONField(name: 'milestones_url')
String? milestonesUrl;
@JSONField(name: 'notifications_url')
String? notificationsUrl;
@JSONField(name: 'labels_url')
String? labelsUrl;
@JSONField(name: 'releases_url')
String? releasesUrl;
@JSONField(name: 'deployments_url')
String? deploymentsUrl;
@JSONField(name: 'created_at')
String? createdAt;
@JSONField(name: 'updated_at')
String? updatedAt;
@JSONField(name: 'pushed_at')
String? pushedAt;
@JSONField(name: 'git_url')
String? gitUrl;
@JSONField(name: 'ssh_url')
String? sshUrl;
@JSONField(name: 'clone_url')
String? cloneUrl;
@JSONField(name: 'svn_url')
String? svnUrl;
String? homepage;
int? size;
@JSONField(name: 'stargazers_count')
int? stargazersCount;
@JSONField(name: 'watchers_count')
int? watchersCount;
String? language;
@JSONField(name: 'has_issues')
bool? hasIssues;
@JSONField(name: 'has_projects')
bool? hasProjects;
@JSONField(name: 'has_downloads')
bool? hasDownloads;
@JSONField(name: 'has_wiki')
bool? hasWiki;
@JSONField(name: 'has_pages')
bool? hasPages;
@JSONField(name: 'forks_count')
int? forksCount;
bool? archived;
bool? disabled;
@JSONField(name: 'open_issues_count')
int? openIssuesCount;
SearchItemsLicense? license;
int? forks;
@JSONField(name: 'open_issues')
int? openIssues;
int? watchers;
@JSONField(name: 'default_branch')
String? defaultBranch;
double? score;
}
@JsonSerializable()
class SearchItemsOwner {
SearchItemsOwner();
factory SearchItemsOwner.fromJson(Map<String, dynamic> json) => $SearchItemsOwnerFromJson(json);
Map<String, dynamic> toJson() => $SearchItemsOwnerToJson(this);
String? login;
int? id;
@JSONField(name: 'node_id')
String? nodeId;
@JSONField(name: 'avatar_url')
String? avatarUrl;
@JSONField(name: 'gravatar_id')
String? gravatarId;
String? url;
@JSONField(name: 'html_url')
String? htmlUrl;
@JSONField(name: 'followers_url')
String? followersUrl;
@JSONField(name: 'following_url')
String? followingUrl;
@JSONField(name: 'gists_url')
String? gistsUrl;
@JSONField(name: 'starred_url')
String? starredUrl;
@JSONField(name: 'subscriptions_url')
String? subscriptionsUrl;
@JSONField(name: 'organizations_url')
String? organizationsUrl;
@JSONField(name: 'repos_url')
String? reposUrl;
@JSONField(name: 'events_url')
String? eventsUrl;
@JSONField(name: 'received_events_url')
String? receivedEventsUrl;
String? type;
@JSONField(name: 'site_admin')
bool? siteAdmin;
}
@JsonSerializable()
class SearchItemsLicense {
SearchItemsLicense();
factory SearchItemsLicense.fromJson(Map<String, dynamic> json) => $SearchItemsLicenseFromJson(json);
Map<String, dynamic> toJson() => $SearchItemsLicenseToJson(this);
String? key;
String? name;
@JSONField(name: 'spdx_id')
String? spdxId;
String? url;
@JSONField(name: 'node_id')
String? nodeId;
}
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:one_poem/category/category_router.dart';
import 'package:one_poem/poem/poem_router.dart';
import 'package:one_poem/routers/fluro_navigator.dart';
import 'package:one_poem/tiktok/controller/tiktok_video_list_controller.dart';
import 'package:one_poem/tiktok/mock/video.dart';
......@@ -134,7 +134,10 @@ class _PoemPageState extends State<PoemPage> with WidgetsBindingObserver {
Icons.search,
color: Colors.white,
),
onPressed: () {},
onPressed: () {
NavigatorUtils.push(context, PoemRouter.poemSearchPage);
_videoListController.currentPlayer.pause();
},
),
),
leftPage: searchPage,
......
import 'package:flutter/material.dart';
import 'package:one_poem/mvp/base_page.dart';
import 'package:one_poem/mvp/power_presenter.dart';
import 'package:one_poem/poem/iview/poem_search_iview.dart';
import 'package:one_poem/poem/models/search_entity.dart';
import 'package:one_poem/poem/presenter/poem_search_presenter.dart';
import 'package:one_poem/poem/provider/base_list_provider.dart';
import 'package:one_poem/widgets/my_refresh_list.dart';
import 'package:one_poem/widgets/search_bar.dart';
import 'package:one_poem/widgets/state_layout.dart';
import 'package:provider/provider.dart';
import 'package:one_poem/extension/int_extension.dart';
class PoemSearchPage extends StatefulWidget {
const PoemSearchPage({Key? key}) : super(key: key);
@override
_PoemSearchPageState createState() => _PoemSearchPageState();
}
class _PoemSearchPageState extends State<PoemSearchPage>
with BasePageMixin<PoemSearchPage, PowerPresenter>
implements PoemSearchIMvpView {
@override
BaseListProvider<SearchItems> provider = BaseListProvider<SearchItems>();
late String _keyword;
int _page = 1;
@override
void initState() {
provider.stateType = StateType.empty;
super.initState();
}
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider<BaseListProvider<SearchItems>>(
create: (_) => provider,
child: Scaffold(
appBar: SearchBar(
hintText: '请输入要查询的内容',
onPressed: (text) {
if (text.isEmpty) {
showToast('搜索关键字不能为空!');
return;
}
_keyword = text;
provider.setStateType(StateType.loading);
_page = 1;
_poemSearchPresenter.search(_keyword, _page, true);
},
),
body:
Consumer<BaseListProvider<SearchItems>>(builder: (_, provider, __) {
return DeerListView(
key: const Key('poem_search_list'),
itemCount: provider.list.length,
stateType: provider.stateType,
onRefresh: _onRefresh,
loadMore: _loadMore,
itemExtent: 50.0,
hasMore: provider.hasMore,
itemBuilder: (_, index) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 16.px),
alignment: Alignment.centerLeft,
child: Text(provider.list[index].name!),
);
},
);
}),
),
);
}
Future<void> _onRefresh() async {
_page = 1;
await _poemSearchPresenter.search(_keyword, _page, false);
}
Future<void> _loadMore() async {
_page++;
await _poemSearchPresenter.search(_keyword, _page, false);
}
late PoemSearchPresenter _poemSearchPresenter;
@override
PowerPresenter createPresenter() {
final PowerPresenter powerPresenter = PowerPresenter<dynamic>(this);
_poemSearchPresenter = PoemSearchPresenter();
powerPresenter.requestPresenter([_poemSearchPresenter]);
return powerPresenter;
}
}
import 'package:fluro/fluro.dart';
import 'package:one_poem/poem/page/poem_record_audio.dart';
import 'package:one_poem/poem/page/poem_search_page.dart';
import 'package:one_poem/routers/i_router.dart';
import 'page/poem_complete_page.dart';
import 'page/poem_detail.dart';
......@@ -16,6 +17,7 @@ class PoemRouter implements IRouterProvider {
static String poemVideoPlayer = '/poem/video/player';
static String poemPublish = '/poem/publish';
static String poemCompletePage = '/poem/complete';
static String poemSearchPage = '/poem/search';
@override
void initRouter(FluroRouter router) {
......@@ -25,6 +27,7 @@ class PoemRouter implements IRouterProvider {
handlerFunc: (_, __) => const PoemPage(),
),
);
router.define(
poemDetailPage,
handler: Handler(
......@@ -95,5 +98,8 @@ class PoemRouter implements IRouterProvider {
},
),
);
router.define(poemSearchPage,
handler: Handler(handlerFunc: (_, __) => const PoemSearchPage()));
}
}
......
import 'package:one_poem/mvp/base_page_presenter.dart';
import 'package:one_poem/net/dio_utils.dart';
import 'package:one_poem/net/http_api.dart';
import 'package:one_poem/poem/iview/poem_search_iview.dart';
import 'package:one_poem/poem/models/search_entity.dart';
import 'package:one_poem/widgets/state_layout.dart';
class PoemSearchPresenter extends BasePagePresenter<PoemSearchIMvpView> {
Future search(String text, int page, bool isShowDialog) {
final Map<String, String> params = <String, String>{};
params['q'] = text;
params['page'] = page.toString();
params['l'] = 'Dart';
return requestNetwork<SearchEntity>(Method.get,
url: HttpApi.search,
queryParameters: params,
isShow: isShowDialog,
onSuccess: (data) {
if (data != null && data.items != null) {
/// 一页30条数据,等于30条认为有下一页
/// 具体的处理逻辑根据具体的接口情况处理,这部分可以抽离出来
view.provider.hasMore = data.items!.length == 30;
if (page == 1) {
/// 刷新
view.provider.list.clear();
if (data.items!.isEmpty) {
view.provider.setStateType(StateType.order);
} else {
view.provider.addAll(data.items!);
}
} else {
view.provider.addAll(data.items!);
}
} else {
/// 加载失败
view.provider.hasMore = false;
view.provider.setStateType(StateType.network);
}
},
onError: (_, __) {
/// 加载失败
view.provider.hasMore = false;
view.provider.setStateType(StateType.network);
}
);
}
}
import 'package:flutter/material.dart';
import 'package:one_poem/widgets/state_layout.dart';
class BaseListProvider<T> extends ChangeNotifier {
final List<T> _list = <T>[];
List<T> get list => _list;
bool hasMore = true;
StateType stateType = StateType.loading;
void setStateType(StateType stateType) {
this.stateType = stateType;
notifyListeners();
}
void add(T data) {
_list.add(data);
notifyListeners();
}
void addAll(List<T> data) {
_list.addAll(data);
notifyListeners();
}
void insert(int i, T data) {
_list.insert(i, data);
notifyListeners();
}
void insertAll(int i, List<T> data) {
_list.insertAll(i, data);
notifyListeners();
}
void remove(T data) {
_list.remove(data);
notifyListeners();
}
void removeAt(int i) {
_list.removeAt(i);
notifyListeners();
}
void clear() {
_list.clear();
notifyListeners();
}
void refresh() {
notifyListeners();
}
}
......@@ -3,19 +3,18 @@ import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:one_poem/res/resources.dart';
import 'package:one_poem/util/theme_utils.dart';
import 'package:one_poem/extension/int_extension.dart';
import 'load_image.dart';
import 'my_button.dart';
/// 搜索页的AppBar
class SearchBar extends StatefulWidget implements PreferredSizeWidget {
const SearchBar({
Key? key,
this.hintText = '',
this.backImg = 'assets/images/ic_back_black.png',
this.onPressed,
}): super(key: key);
}) : super(key: key);
final String backImg;
final String hintText;
......@@ -25,11 +24,10 @@ class SearchBar extends StatefulWidget implements PreferredSizeWidget {
_SearchBarState createState() => _SearchBarState();
@override
Size get preferredSize => const Size.fromHeight(48.0);
Size get preferredSize => Size.fromHeight(48.px);
}
class _SearchBarState extends State<SearchBar> {
final TextEditingController _controller = TextEditingController();
final FocusNode _focus = FocusNode();
......@@ -40,34 +38,26 @@ class _SearchBarState extends State<SearchBar> {
super.dispose();
}
// @override
// void initState() {
// WidgetsBinding.instance!.addPostFrameCallback((_) async {
// SystemChannels.textInput.invokeMethod<void>('TextInput.updateConfig', const TextInputConfiguration().toJson());
// SystemChannels.textInput.invokeMethod<void>('TextInput.hide');
// });
// super.initState();
// }
@override
Widget build(BuildContext context) {
final bool isDark = context.isDark;
final Color iconColor = isDark ? Colours.dark_text_gray : Colours.text_gray_c;
final Color iconColor =
isDark ? Colours.dark_text_gray : Colours.text_gray_c;
final Widget back = Semantics(
label: '返回',
child: SizedBox(
width: 48.0,
height: 48.0,
width: 48.px,
height: 48.px,
child: InkWell(
onTap: () {
_focus.unfocus();
Navigator.maybePop(context);
},
borderRadius: BorderRadius.circular(24.0),
borderRadius: BorderRadius.circular(24.px),
child: Padding(
key: const Key('search_back'),
padding: const EdgeInsets.all(12.0),
padding: EdgeInsets.all(12.px),
child: Image.asset(
widget.backImg,
color: isDark ? Colours.dark_text : Colours.text,
......@@ -77,43 +67,15 @@ class _SearchBarState extends State<SearchBar> {
),
);
/// 使用2.0.0新增CupertinoSearchTextField 实现, 需添加依赖 cupertino_icons: ^1.0.2
// final Widget textField1 = Expanded(child: Container(
// height: 32.0,
// child: CupertinoSearchTextField(
// key: const Key('search_text_field'),
// controller: _controller,
// focusNode: _focus,
// placeholder: widget.hintText,
// placeholderStyle: Theme.of(context).inputDecorationTheme.hintStyle,
// padding: const EdgeInsetsDirectional.fromSTEB(3.8, 0, 5, 0),
// prefixInsets: const EdgeInsetsDirectional.fromSTEB(8, 0, 0, 0),
// suffixInsets: const EdgeInsetsDirectional.fromSTEB(0, 0, 8, 0),
// style: Theme.of(context).textTheme.subtitle1,
// itemSize: 16.0,
// itemColor: iconColor,
// decoration: BoxDecoration(
// color: isDark ? Colours.dark_material_bg : Colours.bg_gray,
// borderRadius: BorderRadius.circular(4.0),
// ),
// onSubmitted: (String val) {
// _focus.unfocus();
// // 点击软键盘的动作按钮时的回调
// widget.onPressed(val);
// },
// )
// ));
final Widget textField = Expanded(
child: Container(
height: 32.0,
height: 32.px,
decoration: BoxDecoration(
color: isDark ? Colours.dark_material_bg : Colours.bg_gray,
borderRadius: BorderRadius.circular(4.0),
borderRadius: BorderRadius.circular(4.px),
),
child: TextField(
key: const Key('search_text_field'),
// autofocus: true,
controller: _controller,
focusNode: _focus,
textInputAction: TextInputAction.search,
......@@ -123,19 +85,24 @@ class _SearchBarState extends State<SearchBar> {
widget.onPressed?.call(val);
},
decoration: InputDecoration(
contentPadding: const EdgeInsets.only(left: -8.0, right: -16.0, bottom: 14.0),
contentPadding:
EdgeInsets.only(left: -8.px, right: -16.px, bottom: 14.px),
border: InputBorder.none,
icon: Padding(
padding: const EdgeInsets.only(top: 8.0, bottom: 8.0, left: 8.0),
child: LoadAssetImage('poem/order_search', color: iconColor,),
padding: EdgeInsets.only(top: 8.px, bottom: 8.px, left: 8.px),
child: LoadAssetImage(
'poem/poem_search',
color: iconColor,
),
),
hintText: widget.hintText,
suffixIcon: GestureDetector(
child: Semantics(
label: '清空',
child: Padding(
padding: const EdgeInsets.only(left: 16.0, top: 8.0, bottom: 8.0),
child: LoadAssetImage('poem/order_delete', color: iconColor),
padding:
EdgeInsets.only(left: 16.px, top: 8.px, bottom: 8.px),
child: LoadAssetImage('poem/poem_delete', color: iconColor),
),
),
onTap: () {
......@@ -151,13 +118,13 @@ class _SearchBarState extends State<SearchBar> {
);
final Widget search = MyButton(
minHeight: 32.0,
minWidth: 44.0,
minHeight: 32.px,
minWidth: 44.px,
fontSize: Dimens.font_sp14,
radius: 4.0,
padding: const EdgeInsets.symmetric(horizontal: 8.0),
radius: 4.px,
padding: EdgeInsets.symmetric(horizontal: 8.px),
text: '搜索',
onPressed:() {
onPressed: () {
_focus.unfocus();
widget.onPressed?.call(_controller.text);
},
......