Compare commits
No commits in common. "2375c468528686541826cddfb2bbd2a33a0513ca" and "77e9994204b76ff34265ae3809befbedfda7e86c" have entirely different histories.
2375c46852
...
77e9994204
@ -57,7 +57,7 @@
|
|||||||
"reply": "Reply",
|
"reply": "Reply",
|
||||||
"unset": "Unset",
|
"unset": "Unset",
|
||||||
"untitled": "Untitled",
|
"untitled": "Untitled",
|
||||||
"postDetail": "Post Detail",
|
"postDetail": "Post detail",
|
||||||
"postNoun": "Post",
|
"postNoun": "Post",
|
||||||
"postReadMore": "Read more",
|
"postReadMore": "Read more",
|
||||||
"postReadEstimate": "Est read time {}",
|
"postReadEstimate": "Est read time {}",
|
||||||
@ -139,7 +139,6 @@
|
|||||||
"fieldPostTitle": "Title",
|
"fieldPostTitle": "Title",
|
||||||
"fieldPostDescription": "Description",
|
"fieldPostDescription": "Description",
|
||||||
"fieldPostTags": "Tags",
|
"fieldPostTags": "Tags",
|
||||||
"fieldPostCategories": "Categories",
|
|
||||||
"fieldPostAlias": "Alias",
|
"fieldPostAlias": "Alias",
|
||||||
"fieldPostAliasHint": "Optional, used to represent the post in URL, should follow URL-Safe.",
|
"fieldPostAliasHint": "Optional, used to represent the post in URL, should follow URL-Safe.",
|
||||||
"postPublish": "Publish",
|
"postPublish": "Publish",
|
||||||
@ -478,15 +477,5 @@
|
|||||||
"colorSchemeRed": "Red",
|
"colorSchemeRed": "Red",
|
||||||
"colorSchemeWhite": "White",
|
"colorSchemeWhite": "White",
|
||||||
"colorSchemeBlack": "Black",
|
"colorSchemeBlack": "Black",
|
||||||
"colorSchemeApplied": "Color scheme has been applied, may need restart the app to take effect.",
|
"colorSchemeApplied": "Color scheme has been applied, may need restart the app to take effect."
|
||||||
"postCategoryTechnology": "Technology",
|
|
||||||
"postCategoryGaming": "Gaming",
|
|
||||||
"postCategoryLife": "Life",
|
|
||||||
"postCategoryArts": "Arts",
|
|
||||||
"postCategorySports": "Sports",
|
|
||||||
"postCategoryMusic": "Music",
|
|
||||||
"postCategoryNews": "News",
|
|
||||||
"postCategoryKnowledge": "Knowledge",
|
|
||||||
"postCategoryLiterature": "Literature",
|
|
||||||
"postCategoryUncategorized": "Uncategorized"
|
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,6 @@
|
|||||||
"fieldPostTitle": "标题",
|
"fieldPostTitle": "标题",
|
||||||
"fieldPostDescription": "描述",
|
"fieldPostDescription": "描述",
|
||||||
"fieldPostTags": "标签",
|
"fieldPostTags": "标签",
|
||||||
"fieldPostCategories": "分类",
|
|
||||||
"fieldPostAlias": "别名",
|
"fieldPostAlias": "别名",
|
||||||
"fieldPostAliasHint": "可选项,用于在 URL 中表示该帖子,应遵循 URL-Safe 的原则。",
|
"fieldPostAliasHint": "可选项,用于在 URL 中表示该帖子,应遵循 URL-Safe 的原则。",
|
||||||
"postPublish": "发布",
|
"postPublish": "发布",
|
||||||
@ -417,7 +416,7 @@
|
|||||||
"accountStatus": "状态",
|
"accountStatus": "状态",
|
||||||
"accountStatusOnline": "在线",
|
"accountStatusOnline": "在线",
|
||||||
"accountStatusOffline": "离线",
|
"accountStatusOffline": "离线",
|
||||||
"accountStatusLastSeen": "最后一次上线于 {}",
|
"accountStatusLastSeen": "最后一次在 {} 上线",
|
||||||
"postArticle": "Solar Network 上的文章",
|
"postArticle": "Solar Network 上的文章",
|
||||||
"postStory": "Solar Network 上的故事",
|
"postStory": "Solar Network 上的故事",
|
||||||
"articleWrittenAt": "发表于 {}",
|
"articleWrittenAt": "发表于 {}",
|
||||||
@ -476,15 +475,5 @@
|
|||||||
"colorSchemeRed": "红色",
|
"colorSchemeRed": "红色",
|
||||||
"colorSchemeWhite": "白色",
|
"colorSchemeWhite": "白色",
|
||||||
"colorSchemeBlack": "黑色",
|
"colorSchemeBlack": "黑色",
|
||||||
"colorSchemeApplied": "主题色已应用,可能需要重启来生效。",
|
"colorSchemeApplied": "主题色已应用,可能需要重启来生效。"
|
||||||
"postCategoryTechnology": "技术",
|
|
||||||
"postCategoryGaming": "游戏",
|
|
||||||
"postCategoryLife": "生活",
|
|
||||||
"postCategoryArts": "艺术",
|
|
||||||
"postCategorySports": "体育",
|
|
||||||
"postCategoryMusic": "音乐",
|
|
||||||
"postCategoryNews": "新闻",
|
|
||||||
"postCategoryKnowledge": "知识",
|
|
||||||
"postCategoryLiterature": "文学",
|
|
||||||
"postCategoryUncategorized": "未分类"
|
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,6 @@
|
|||||||
"fieldPostTitle": "標題",
|
"fieldPostTitle": "標題",
|
||||||
"fieldPostDescription": "描述",
|
"fieldPostDescription": "描述",
|
||||||
"fieldPostTags": "標籤",
|
"fieldPostTags": "標籤",
|
||||||
"fieldPostCategories": "分類",
|
|
||||||
"fieldPostAlias": "別名",
|
"fieldPostAlias": "別名",
|
||||||
"fieldPostAliasHint": "可選項,用於在 URL 中表示該帖子,應遵循 URL-Safe 的原則。",
|
"fieldPostAliasHint": "可選項,用於在 URL 中表示該帖子,應遵循 URL-Safe 的原則。",
|
||||||
"postPublish": "發佈",
|
"postPublish": "發佈",
|
||||||
@ -417,7 +416,7 @@
|
|||||||
"accountStatus": "狀態",
|
"accountStatus": "狀態",
|
||||||
"accountStatusOnline": "在線",
|
"accountStatusOnline": "在線",
|
||||||
"accountStatusOffline": "離線",
|
"accountStatusOffline": "離線",
|
||||||
"accountStatusLastSeen": "最後一次上線於 {}",
|
"accountStatusLastSeen": "最後一次在 {} 上線",
|
||||||
"postArticle": "Solar Network 上的文章",
|
"postArticle": "Solar Network 上的文章",
|
||||||
"postStory": "Solar Network 上的故事",
|
"postStory": "Solar Network 上的故事",
|
||||||
"articleWrittenAt": "發表於 {}",
|
"articleWrittenAt": "發表於 {}",
|
||||||
@ -476,15 +475,5 @@
|
|||||||
"colorSchemeRed": "紅色",
|
"colorSchemeRed": "紅色",
|
||||||
"colorSchemeWhite": "白色",
|
"colorSchemeWhite": "白色",
|
||||||
"colorSchemeBlack": "黑色",
|
"colorSchemeBlack": "黑色",
|
||||||
"colorSchemeApplied": "主題色已應用,可能需要重啓來生效。",
|
"colorSchemeApplied": "主題色已應用,可能需要重啓來生效。"
|
||||||
"postCategoryTechnology": "技術",
|
|
||||||
"postCategoryGaming": "遊戲",
|
|
||||||
"postCategoryLife": "生活",
|
|
||||||
"postCategoryArts": "藝術",
|
|
||||||
"postCategorySports": "體育",
|
|
||||||
"postCategoryMusic": "音樂",
|
|
||||||
"postCategoryNews": "新聞",
|
|
||||||
"postCategoryKnowledge": "知識",
|
|
||||||
"postCategoryLiterature": "文學",
|
|
||||||
"postCategoryUncategorized": "未分類"
|
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,6 @@
|
|||||||
"fieldPostTitle": "標題",
|
"fieldPostTitle": "標題",
|
||||||
"fieldPostDescription": "描述",
|
"fieldPostDescription": "描述",
|
||||||
"fieldPostTags": "標籤",
|
"fieldPostTags": "標籤",
|
||||||
"fieldPostCategories": "分類",
|
|
||||||
"fieldPostAlias": "別名",
|
"fieldPostAlias": "別名",
|
||||||
"fieldPostAliasHint": "可選項,用於在 URL 中表示該帖子,應遵循 URL-Safe 的原則。",
|
"fieldPostAliasHint": "可選項,用於在 URL 中表示該帖子,應遵循 URL-Safe 的原則。",
|
||||||
"postPublish": "釋出",
|
"postPublish": "釋出",
|
||||||
@ -417,7 +416,7 @@
|
|||||||
"accountStatus": "狀態",
|
"accountStatus": "狀態",
|
||||||
"accountStatusOnline": "線上",
|
"accountStatusOnline": "線上",
|
||||||
"accountStatusOffline": "離線",
|
"accountStatusOffline": "離線",
|
||||||
"accountStatusLastSeen": "最後一次上線於 {}",
|
"accountStatusLastSeen": "最後一次在 {} 上線",
|
||||||
"postArticle": "Solar Network 上的文章",
|
"postArticle": "Solar Network 上的文章",
|
||||||
"postStory": "Solar Network 上的故事",
|
"postStory": "Solar Network 上的故事",
|
||||||
"articleWrittenAt": "發表於 {}",
|
"articleWrittenAt": "發表於 {}",
|
||||||
@ -476,15 +475,5 @@
|
|||||||
"colorSchemeRed": "紅色",
|
"colorSchemeRed": "紅色",
|
||||||
"colorSchemeWhite": "白色",
|
"colorSchemeWhite": "白色",
|
||||||
"colorSchemeBlack": "黑色",
|
"colorSchemeBlack": "黑色",
|
||||||
"colorSchemeApplied": "主題色已應用,可能需要重啟來生效。",
|
"colorSchemeApplied": "主題色已應用,可能需要重啟來生效。"
|
||||||
"postCategoryTechnology": "技術",
|
|
||||||
"postCategoryGaming": "遊戲",
|
|
||||||
"postCategoryLife": "生活",
|
|
||||||
"postCategoryArts": "藝術",
|
|
||||||
"postCategorySports": "體育",
|
|
||||||
"postCategoryMusic": "音樂",
|
|
||||||
"postCategoryNews": "新聞",
|
|
||||||
"postCategoryKnowledge": "知識",
|
|
||||||
"postCategoryLiterature": "文學",
|
|
||||||
"postCategoryUncategorized": "未分類"
|
|
||||||
}
|
}
|
||||||
|
@ -178,7 +178,6 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
List<int> visibleUsers = List.empty();
|
List<int> visibleUsers = List.empty();
|
||||||
List<int> invisibleUsers = List.empty();
|
List<int> invisibleUsers = List.empty();
|
||||||
List<String> tags = List.empty();
|
List<String> tags = List.empty();
|
||||||
List<String> categories = List.empty();
|
|
||||||
PostWriteMedia? thumbnail;
|
PostWriteMedia? thumbnail;
|
||||||
List<PostWriteMedia> attachments = List.empty(growable: true);
|
List<PostWriteMedia> attachments = List.empty(growable: true);
|
||||||
DateTime? publishedAt, publishedUntil;
|
DateTime? publishedAt, publishedUntil;
|
||||||
@ -208,7 +207,6 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
invisibleUsers = List.from(post.invisibleUsersList ?? []);
|
invisibleUsers = List.from(post.invisibleUsersList ?? []);
|
||||||
visibility = post.visibility;
|
visibility = post.visibility;
|
||||||
tags = List.from(post.tags.map((ele) => ele.alias));
|
tags = List.from(post.tags.map((ele) => ele.alias));
|
||||||
categories = List.from(post.categories.map((ele) => ele.alias));
|
|
||||||
attachments.addAll(post.preload?.attachments?.map((ele) => PostWriteMedia(ele)) ?? []);
|
attachments.addAll(post.preload?.attachments?.map((ele) => PostWriteMedia(ele)) ?? []);
|
||||||
|
|
||||||
if (post.preload?.thumbnail != null && (post.preload?.thumbnail?.rid.isNotEmpty ?? false)) {
|
if (post.preload?.thumbnail != null && (post.preload?.thumbnail?.rid.isNotEmpty ?? false)) {
|
||||||
@ -347,7 +345,6 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
if (thumbnail != null && thumbnail!.attachment != null) 'thumbnail': thumbnail!.attachment!.rid,
|
if (thumbnail != null && thumbnail!.attachment != null) 'thumbnail': thumbnail!.attachment!.rid,
|
||||||
'attachments': attachments.where((e) => e.attachment != null).map((e) => e.attachment!.rid).toList(),
|
'attachments': attachments.where((e) => e.attachment != null).map((e) => e.attachment!.rid).toList(),
|
||||||
'tags': tags.map((ele) => {'alias': ele}).toList(),
|
'tags': tags.map((ele) => {'alias': ele}).toList(),
|
||||||
'categories': categories.map((ele) => {'alias': ele}).toList(),
|
|
||||||
'visibility': visibility,
|
'visibility': visibility,
|
||||||
'visible_users_list': visibleUsers,
|
'visible_users_list': visibleUsers,
|
||||||
'invisible_users_list': invisibleUsers,
|
'invisible_users_list': invisibleUsers,
|
||||||
@ -434,11 +431,6 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCategories(List<String> value) {
|
|
||||||
categories = value;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setVisibility(int value) {
|
void setVisibility(int value) {
|
||||||
visibility = value;
|
visibility = value;
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@ -475,9 +467,6 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
titleController.clear();
|
titleController.clear();
|
||||||
descriptionController.clear();
|
descriptionController.clear();
|
||||||
contentController.clear();
|
contentController.clear();
|
||||||
aliasController.clear();
|
|
||||||
tags.clear();
|
|
||||||
categories.clear();
|
|
||||||
attachments.clear();
|
attachments.clear();
|
||||||
editingPost = null;
|
editingPost = null;
|
||||||
replyingPost = null;
|
replyingPost = null;
|
||||||
@ -491,7 +480,6 @@ class PostWriteController extends ChangeNotifier {
|
|||||||
contentController.dispose();
|
contentController.dispose();
|
||||||
titleController.dispose();
|
titleController.dispose();
|
||||||
descriptionController.dispose();
|
descriptionController.dispose();
|
||||||
aliasController.dispose();
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,14 +118,12 @@ class SnPostContentProvider {
|
|||||||
int take = 10,
|
int take = 10,
|
||||||
int offset = 0,
|
int offset = 0,
|
||||||
Iterable<String>? tags,
|
Iterable<String>? tags,
|
||||||
Iterable<String>? categories,
|
|
||||||
}) async {
|
}) async {
|
||||||
final resp = await _sn.client.get('/cgi/co/posts/search', queryParameters: {
|
final resp = await _sn.client.get('/cgi/co/posts/search', queryParameters: {
|
||||||
'take': take,
|
'take': take,
|
||||||
'offset': offset,
|
'offset': offset,
|
||||||
'probe': searchTerm,
|
'probe': searchTerm,
|
||||||
if (tags?.isNotEmpty ?? false) 'tags': tags!.join(','),
|
if (tags?.isNotEmpty ?? false) 'tags': tags!.join(','),
|
||||||
if (categories?.isNotEmpty ?? false) 'categories': categories!.join(','),
|
|
||||||
});
|
});
|
||||||
final List<SnPost> out = await _preloadRelatedDataInBatch(
|
final List<SnPost> out = await _preloadRelatedDataInBatch(
|
||||||
List.from(resp.data['data']?.map((e) => SnPost.fromJson(e)) ?? []),
|
List.from(resp.data['data']?.map((e) => SnPost.fromJson(e)) ?? []),
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:path/path.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:surface/providers/config.dart';
|
import 'package:surface/providers/config.dart';
|
||||||
|
@ -228,13 +228,7 @@ class _UserScreenState extends State<UserScreen> with SingleTickerProviderStateM
|
|||||||
body: CustomScrollView(
|
body: CustomScrollView(
|
||||||
controller: _scrollController,
|
controller: _scrollController,
|
||||||
slivers: [
|
slivers: [
|
||||||
Theme(
|
SliverAppBar(
|
||||||
data: Theme.of(context).copyWith(
|
|
||||||
appBarTheme: Theme.of(context).appBarTheme.copyWith(
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: SliverAppBar(
|
|
||||||
expandedHeight: _appBarHeight,
|
expandedHeight: _appBarHeight,
|
||||||
title: _account == null
|
title: _account == null
|
||||||
? Text('loading').tr()
|
? Text('loading').tr()
|
||||||
@ -244,7 +238,7 @@ class _UserScreenState extends State<UserScreen> with SingleTickerProviderStateM
|
|||||||
TextSpan(
|
TextSpan(
|
||||||
text: _account!.nick,
|
text: _account!.nick,
|
||||||
style: Theme.of(context).textTheme.titleLarge!.copyWith(
|
style: Theme.of(context).textTheme.titleLarge!.copyWith(
|
||||||
color: Colors.white,
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
shadows: labelShadows,
|
shadows: labelShadows,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -252,7 +246,7 @@ class _UserScreenState extends State<UserScreen> with SingleTickerProviderStateM
|
|||||||
TextSpan(
|
TextSpan(
|
||||||
text: '@${_account!.name}',
|
text: '@${_account!.name}',
|
||||||
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
style: Theme.of(context).textTheme.bodySmall!.copyWith(
|
||||||
color: Colors.white,
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
shadows: labelShadows,
|
shadows: labelShadows,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -294,7 +288,6 @@ class _UserScreenState extends State<UserScreen> with SingleTickerProviderStateM
|
|||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
if (_account != null)
|
if (_account != null)
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Column(
|
child: Column(
|
||||||
|
@ -23,7 +23,6 @@ class _PostSearchScreenState extends State<PostSearchScreen> {
|
|||||||
bool _isBusy = false;
|
bool _isBusy = false;
|
||||||
|
|
||||||
List<String> _searchTags = List.empty(growable: true);
|
List<String> _searchTags = List.empty(growable: true);
|
||||||
List<String> _searchCategories = List.empty(growable: true);
|
|
||||||
|
|
||||||
final List<SnPost> _posts = List.empty(growable: true);
|
final List<SnPost> _posts = List.empty(growable: true);
|
||||||
int? _postCount;
|
int? _postCount;
|
||||||
@ -32,7 +31,7 @@ class _PostSearchScreenState extends State<PostSearchScreen> {
|
|||||||
Duration? _lastTook;
|
Duration? _lastTook;
|
||||||
|
|
||||||
Future<void> _fetchPosts() async {
|
Future<void> _fetchPosts() async {
|
||||||
if (_searchTerm.isEmpty && _searchCategories.isEmpty && _searchTags.isEmpty) return;
|
if (_searchTerm.isEmpty && _searchTags.isEmpty) return;
|
||||||
if (_postCount != null && _posts.length >= _postCount!) return;
|
if (_postCount != null && _posts.length >= _postCount!) return;
|
||||||
|
|
||||||
setState(() => _isBusy = true);
|
setState(() => _isBusy = true);
|
||||||
@ -46,7 +45,6 @@ class _PostSearchScreenState extends State<PostSearchScreen> {
|
|||||||
take: 10,
|
take: 10,
|
||||||
offset: _posts.length,
|
offset: _posts.length,
|
||||||
tags: _searchTags,
|
tags: _searchTags,
|
||||||
categories: _searchCategories,
|
|
||||||
);
|
);
|
||||||
final List<SnPost> out = result.$1;
|
final List<SnPost> out = result.$1;
|
||||||
_postCount = result.$2;
|
_postCount = result.$2;
|
||||||
@ -75,20 +73,9 @@ class _PostSearchScreenState extends State<PostSearchScreen> {
|
|||||||
setState(() => _searchTags = value);
|
setState(() => _searchTags = value);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const Gap(4),
|
|
||||||
PostCategoriesField(
|
|
||||||
labelText: 'fieldPostCategories'.tr(),
|
|
||||||
initialCategories: _searchCategories,
|
|
||||||
onUpdate: (value) {
|
|
||||||
setState(() => _searchCategories = value);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
).padding(horizontal: 24, vertical: 16),
|
).padding(horizontal: 24, vertical: 16),
|
||||||
).then((_) {
|
);
|
||||||
_posts.clear();
|
|
||||||
_fetchPosts();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -277,13 +277,7 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> with SingleTi
|
|||||||
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
|
handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context),
|
||||||
sliver: MultiSliver(
|
sliver: MultiSliver(
|
||||||
children: [
|
children: [
|
||||||
Theme(
|
SliverAppBar(
|
||||||
data: Theme.of(context).copyWith(
|
|
||||||
appBarTheme: Theme.of(context).appBarTheme.copyWith(
|
|
||||||
foregroundColor: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: SliverAppBar(
|
|
||||||
expandedHeight: _appBarHeight,
|
expandedHeight: _appBarHeight,
|
||||||
title: _publisher == null
|
title: _publisher == null
|
||||||
? Text('loading').tr()
|
? Text('loading').tr()
|
||||||
@ -293,7 +287,7 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> with SingleTi
|
|||||||
TextSpan(
|
TextSpan(
|
||||||
text: _publisher!.nick,
|
text: _publisher!.nick,
|
||||||
style: Theme.of(context).textTheme.titleLarge!.copyWith(
|
style: Theme.of(context).textTheme.titleLarge!.copyWith(
|
||||||
color: Colors.white,
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
shadows: labelShadows,
|
shadows: labelShadows,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -348,7 +342,6 @@ class _PostPublisherScreenState extends State<PostPublisherScreen> with SingleTi
|
|||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
if (_publisher != null)
|
if (_publisher != null)
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Container(
|
child: Container(
|
||||||
|
@ -19,7 +19,7 @@ class SnPost with _$SnPost {
|
|||||||
required String? alias,
|
required String? alias,
|
||||||
required String? aliasPrefix,
|
required String? aliasPrefix,
|
||||||
@Default([]) List<SnPostTag> tags,
|
@Default([]) List<SnPostTag> tags,
|
||||||
@Default([]) List<SnPostCategory> categories,
|
@Default([]) List<dynamic> categories,
|
||||||
required List<SnPost>? replies,
|
required List<SnPost>? replies,
|
||||||
required int? replyId,
|
required int? replyId,
|
||||||
required int? repostId,
|
required int? repostId,
|
||||||
@ -67,23 +67,6 @@ class SnPostTag with _$SnPostTag {
|
|||||||
_$SnPostTagFromJson(json);
|
_$SnPostTagFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
|
||||||
class SnPostCategory with _$SnPostCategory {
|
|
||||||
const factory SnPostCategory({
|
|
||||||
required int id,
|
|
||||||
required DateTime createdAt,
|
|
||||||
required DateTime updatedAt,
|
|
||||||
required dynamic deletedAt,
|
|
||||||
required String alias,
|
|
||||||
required String name,
|
|
||||||
required String description,
|
|
||||||
required dynamic posts,
|
|
||||||
}) = _SnPostCategory;
|
|
||||||
|
|
||||||
factory SnPostCategory.fromJson(Map<String, Object?> json) =>
|
|
||||||
_$SnPostCategoryFromJson(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
class SnPostPreload with _$SnPostPreload {
|
class SnPostPreload with _$SnPostPreload {
|
||||||
const factory SnPostPreload({
|
const factory SnPostPreload({
|
||||||
|
@ -30,7 +30,7 @@ mixin _$SnPost {
|
|||||||
String? get alias => throw _privateConstructorUsedError;
|
String? get alias => throw _privateConstructorUsedError;
|
||||||
String? get aliasPrefix => throw _privateConstructorUsedError;
|
String? get aliasPrefix => throw _privateConstructorUsedError;
|
||||||
List<SnPostTag> get tags => throw _privateConstructorUsedError;
|
List<SnPostTag> get tags => throw _privateConstructorUsedError;
|
||||||
List<SnPostCategory> get categories => throw _privateConstructorUsedError;
|
List<dynamic> get categories => throw _privateConstructorUsedError;
|
||||||
List<SnPost>? get replies => throw _privateConstructorUsedError;
|
List<SnPost>? get replies => throw _privateConstructorUsedError;
|
||||||
int? get replyId => throw _privateConstructorUsedError;
|
int? get replyId => throw _privateConstructorUsedError;
|
||||||
int? get repostId => throw _privateConstructorUsedError;
|
int? get repostId => throw _privateConstructorUsedError;
|
||||||
@ -77,7 +77,7 @@ abstract class $SnPostCopyWith<$Res> {
|
|||||||
String? alias,
|
String? alias,
|
||||||
String? aliasPrefix,
|
String? aliasPrefix,
|
||||||
List<SnPostTag> tags,
|
List<SnPostTag> tags,
|
||||||
List<SnPostCategory> categories,
|
List<dynamic> categories,
|
||||||
List<SnPost>? replies,
|
List<SnPost>? replies,
|
||||||
int? replyId,
|
int? replyId,
|
||||||
int? repostId,
|
int? repostId,
|
||||||
@ -197,7 +197,7 @@ class _$SnPostCopyWithImpl<$Res, $Val extends SnPost>
|
|||||||
categories: null == categories
|
categories: null == categories
|
||||||
? _value.categories
|
? _value.categories
|
||||||
: categories // ignore: cast_nullable_to_non_nullable
|
: categories // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SnPostCategory>,
|
as List<dynamic>,
|
||||||
replies: freezed == replies
|
replies: freezed == replies
|
||||||
? _value.replies
|
? _value.replies
|
||||||
: replies // ignore: cast_nullable_to_non_nullable
|
: replies // ignore: cast_nullable_to_non_nullable
|
||||||
@ -362,7 +362,7 @@ abstract class _$$SnPostImplCopyWith<$Res> implements $SnPostCopyWith<$Res> {
|
|||||||
String? alias,
|
String? alias,
|
||||||
String? aliasPrefix,
|
String? aliasPrefix,
|
||||||
List<SnPostTag> tags,
|
List<SnPostTag> tags,
|
||||||
List<SnPostCategory> categories,
|
List<dynamic> categories,
|
||||||
List<SnPost>? replies,
|
List<SnPost>? replies,
|
||||||
int? replyId,
|
int? replyId,
|
||||||
int? repostId,
|
int? repostId,
|
||||||
@ -485,7 +485,7 @@ class __$$SnPostImplCopyWithImpl<$Res>
|
|||||||
categories: null == categories
|
categories: null == categories
|
||||||
? _value._categories
|
? _value._categories
|
||||||
: categories // ignore: cast_nullable_to_non_nullable
|
: categories // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SnPostCategory>,
|
as List<dynamic>,
|
||||||
replies: freezed == replies
|
replies: freezed == replies
|
||||||
? _value._replies
|
? _value._replies
|
||||||
: replies // ignore: cast_nullable_to_non_nullable
|
: replies // ignore: cast_nullable_to_non_nullable
|
||||||
@ -584,7 +584,7 @@ class _$SnPostImpl extends _SnPost {
|
|||||||
required this.alias,
|
required this.alias,
|
||||||
required this.aliasPrefix,
|
required this.aliasPrefix,
|
||||||
final List<SnPostTag> tags = const [],
|
final List<SnPostTag> tags = const [],
|
||||||
final List<SnPostCategory> categories = const [],
|
final List<dynamic> categories = const [],
|
||||||
required final List<SnPost>? replies,
|
required final List<SnPost>? replies,
|
||||||
required this.replyId,
|
required this.replyId,
|
||||||
required this.repostId,
|
required this.repostId,
|
||||||
@ -649,10 +649,10 @@ class _$SnPostImpl extends _SnPost {
|
|||||||
return EqualUnmodifiableListView(_tags);
|
return EqualUnmodifiableListView(_tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<SnPostCategory> _categories;
|
final List<dynamic> _categories;
|
||||||
@override
|
@override
|
||||||
@JsonKey()
|
@JsonKey()
|
||||||
List<SnPostCategory> get categories {
|
List<dynamic> get categories {
|
||||||
if (_categories is EqualUnmodifiableListView) return _categories;
|
if (_categories is EqualUnmodifiableListView) return _categories;
|
||||||
// ignore: implicit_dynamic_type
|
// ignore: implicit_dynamic_type
|
||||||
return EqualUnmodifiableListView(_categories);
|
return EqualUnmodifiableListView(_categories);
|
||||||
@ -853,7 +853,7 @@ abstract class _SnPost extends SnPost {
|
|||||||
required final String? alias,
|
required final String? alias,
|
||||||
required final String? aliasPrefix,
|
required final String? aliasPrefix,
|
||||||
final List<SnPostTag> tags,
|
final List<SnPostTag> tags,
|
||||||
final List<SnPostCategory> categories,
|
final List<dynamic> categories,
|
||||||
required final List<SnPost>? replies,
|
required final List<SnPost>? replies,
|
||||||
required final int? replyId,
|
required final int? replyId,
|
||||||
required final int? repostId,
|
required final int? repostId,
|
||||||
@ -899,7 +899,7 @@ abstract class _SnPost extends SnPost {
|
|||||||
@override
|
@override
|
||||||
List<SnPostTag> get tags;
|
List<SnPostTag> get tags;
|
||||||
@override
|
@override
|
||||||
List<SnPostCategory> get categories;
|
List<dynamic> get categories;
|
||||||
@override
|
@override
|
||||||
List<SnPost>? get replies;
|
List<SnPost>? get replies;
|
||||||
@override
|
@override
|
||||||
@ -1253,312 +1253,6 @@ abstract class _SnPostTag implements SnPostTag {
|
|||||||
throw _privateConstructorUsedError;
|
throw _privateConstructorUsedError;
|
||||||
}
|
}
|
||||||
|
|
||||||
SnPostCategory _$SnPostCategoryFromJson(Map<String, dynamic> json) {
|
|
||||||
return _SnPostCategory.fromJson(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
mixin _$SnPostCategory {
|
|
||||||
int get id => throw _privateConstructorUsedError;
|
|
||||||
DateTime get createdAt => throw _privateConstructorUsedError;
|
|
||||||
DateTime get updatedAt => throw _privateConstructorUsedError;
|
|
||||||
dynamic get deletedAt => throw _privateConstructorUsedError;
|
|
||||||
String get alias => throw _privateConstructorUsedError;
|
|
||||||
String get name => throw _privateConstructorUsedError;
|
|
||||||
String get description => throw _privateConstructorUsedError;
|
|
||||||
dynamic get posts => throw _privateConstructorUsedError;
|
|
||||||
|
|
||||||
/// Serializes this SnPostCategory to a JSON map.
|
|
||||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
|
||||||
|
|
||||||
/// Create a copy of SnPostCategory
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
$SnPostCategoryCopyWith<SnPostCategory> get copyWith =>
|
|
||||||
throw _privateConstructorUsedError;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
abstract class $SnPostCategoryCopyWith<$Res> {
|
|
||||||
factory $SnPostCategoryCopyWith(
|
|
||||||
SnPostCategory value, $Res Function(SnPostCategory) then) =
|
|
||||||
_$SnPostCategoryCopyWithImpl<$Res, SnPostCategory>;
|
|
||||||
@useResult
|
|
||||||
$Res call(
|
|
||||||
{int id,
|
|
||||||
DateTime createdAt,
|
|
||||||
DateTime updatedAt,
|
|
||||||
dynamic deletedAt,
|
|
||||||
String alias,
|
|
||||||
String name,
|
|
||||||
String description,
|
|
||||||
dynamic posts});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
class _$SnPostCategoryCopyWithImpl<$Res, $Val extends SnPostCategory>
|
|
||||||
implements $SnPostCategoryCopyWith<$Res> {
|
|
||||||
_$SnPostCategoryCopyWithImpl(this._value, this._then);
|
|
||||||
|
|
||||||
// ignore: unused_field
|
|
||||||
final $Val _value;
|
|
||||||
// ignore: unused_field
|
|
||||||
final $Res Function($Val) _then;
|
|
||||||
|
|
||||||
/// Create a copy of SnPostCategory
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
@override
|
|
||||||
$Res call({
|
|
||||||
Object? id = null,
|
|
||||||
Object? createdAt = null,
|
|
||||||
Object? updatedAt = null,
|
|
||||||
Object? deletedAt = freezed,
|
|
||||||
Object? alias = null,
|
|
||||||
Object? name = null,
|
|
||||||
Object? description = null,
|
|
||||||
Object? posts = freezed,
|
|
||||||
}) {
|
|
||||||
return _then(_value.copyWith(
|
|
||||||
id: null == id
|
|
||||||
? _value.id
|
|
||||||
: id // ignore: cast_nullable_to_non_nullable
|
|
||||||
as int,
|
|
||||||
createdAt: null == createdAt
|
|
||||||
? _value.createdAt
|
|
||||||
: createdAt // ignore: cast_nullable_to_non_nullable
|
|
||||||
as DateTime,
|
|
||||||
updatedAt: null == updatedAt
|
|
||||||
? _value.updatedAt
|
|
||||||
: updatedAt // ignore: cast_nullable_to_non_nullable
|
|
||||||
as DateTime,
|
|
||||||
deletedAt: freezed == deletedAt
|
|
||||||
? _value.deletedAt
|
|
||||||
: deletedAt // ignore: cast_nullable_to_non_nullable
|
|
||||||
as dynamic,
|
|
||||||
alias: null == alias
|
|
||||||
? _value.alias
|
|
||||||
: alias // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
|
||||||
name: null == name
|
|
||||||
? _value.name
|
|
||||||
: name // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
|
||||||
description: null == description
|
|
||||||
? _value.description
|
|
||||||
: description // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
|
||||||
posts: freezed == posts
|
|
||||||
? _value.posts
|
|
||||||
: posts // ignore: cast_nullable_to_non_nullable
|
|
||||||
as dynamic,
|
|
||||||
) as $Val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
abstract class _$$SnPostCategoryImplCopyWith<$Res>
|
|
||||||
implements $SnPostCategoryCopyWith<$Res> {
|
|
||||||
factory _$$SnPostCategoryImplCopyWith(_$SnPostCategoryImpl value,
|
|
||||||
$Res Function(_$SnPostCategoryImpl) then) =
|
|
||||||
__$$SnPostCategoryImplCopyWithImpl<$Res>;
|
|
||||||
@override
|
|
||||||
@useResult
|
|
||||||
$Res call(
|
|
||||||
{int id,
|
|
||||||
DateTime createdAt,
|
|
||||||
DateTime updatedAt,
|
|
||||||
dynamic deletedAt,
|
|
||||||
String alias,
|
|
||||||
String name,
|
|
||||||
String description,
|
|
||||||
dynamic posts});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
class __$$SnPostCategoryImplCopyWithImpl<$Res>
|
|
||||||
extends _$SnPostCategoryCopyWithImpl<$Res, _$SnPostCategoryImpl>
|
|
||||||
implements _$$SnPostCategoryImplCopyWith<$Res> {
|
|
||||||
__$$SnPostCategoryImplCopyWithImpl(
|
|
||||||
_$SnPostCategoryImpl _value, $Res Function(_$SnPostCategoryImpl) _then)
|
|
||||||
: super(_value, _then);
|
|
||||||
|
|
||||||
/// Create a copy of SnPostCategory
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
@override
|
|
||||||
$Res call({
|
|
||||||
Object? id = null,
|
|
||||||
Object? createdAt = null,
|
|
||||||
Object? updatedAt = null,
|
|
||||||
Object? deletedAt = freezed,
|
|
||||||
Object? alias = null,
|
|
||||||
Object? name = null,
|
|
||||||
Object? description = null,
|
|
||||||
Object? posts = freezed,
|
|
||||||
}) {
|
|
||||||
return _then(_$SnPostCategoryImpl(
|
|
||||||
id: null == id
|
|
||||||
? _value.id
|
|
||||||
: id // ignore: cast_nullable_to_non_nullable
|
|
||||||
as int,
|
|
||||||
createdAt: null == createdAt
|
|
||||||
? _value.createdAt
|
|
||||||
: createdAt // ignore: cast_nullable_to_non_nullable
|
|
||||||
as DateTime,
|
|
||||||
updatedAt: null == updatedAt
|
|
||||||
? _value.updatedAt
|
|
||||||
: updatedAt // ignore: cast_nullable_to_non_nullable
|
|
||||||
as DateTime,
|
|
||||||
deletedAt: freezed == deletedAt
|
|
||||||
? _value.deletedAt
|
|
||||||
: deletedAt // ignore: cast_nullable_to_non_nullable
|
|
||||||
as dynamic,
|
|
||||||
alias: null == alias
|
|
||||||
? _value.alias
|
|
||||||
: alias // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
|
||||||
name: null == name
|
|
||||||
? _value.name
|
|
||||||
: name // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
|
||||||
description: null == description
|
|
||||||
? _value.description
|
|
||||||
: description // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
|
||||||
posts: freezed == posts
|
|
||||||
? _value.posts
|
|
||||||
: posts // ignore: cast_nullable_to_non_nullable
|
|
||||||
as dynamic,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
@JsonSerializable()
|
|
||||||
class _$SnPostCategoryImpl implements _SnPostCategory {
|
|
||||||
const _$SnPostCategoryImpl(
|
|
||||||
{required this.id,
|
|
||||||
required this.createdAt,
|
|
||||||
required this.updatedAt,
|
|
||||||
required this.deletedAt,
|
|
||||||
required this.alias,
|
|
||||||
required this.name,
|
|
||||||
required this.description,
|
|
||||||
required this.posts});
|
|
||||||
|
|
||||||
factory _$SnPostCategoryImpl.fromJson(Map<String, dynamic> json) =>
|
|
||||||
_$$SnPostCategoryImplFromJson(json);
|
|
||||||
|
|
||||||
@override
|
|
||||||
final int id;
|
|
||||||
@override
|
|
||||||
final DateTime createdAt;
|
|
||||||
@override
|
|
||||||
final DateTime updatedAt;
|
|
||||||
@override
|
|
||||||
final dynamic deletedAt;
|
|
||||||
@override
|
|
||||||
final String alias;
|
|
||||||
@override
|
|
||||||
final String name;
|
|
||||||
@override
|
|
||||||
final String description;
|
|
||||||
@override
|
|
||||||
final dynamic posts;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return 'SnPostCategory(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, alias: $alias, name: $name, description: $description, posts: $posts)';
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) {
|
|
||||||
return identical(this, other) ||
|
|
||||||
(other.runtimeType == runtimeType &&
|
|
||||||
other is _$SnPostCategoryImpl &&
|
|
||||||
(identical(other.id, id) || other.id == id) &&
|
|
||||||
(identical(other.createdAt, createdAt) ||
|
|
||||||
other.createdAt == createdAt) &&
|
|
||||||
(identical(other.updatedAt, updatedAt) ||
|
|
||||||
other.updatedAt == updatedAt) &&
|
|
||||||
const DeepCollectionEquality().equals(other.deletedAt, deletedAt) &&
|
|
||||||
(identical(other.alias, alias) || other.alias == alias) &&
|
|
||||||
(identical(other.name, name) || other.name == name) &&
|
|
||||||
(identical(other.description, description) ||
|
|
||||||
other.description == description) &&
|
|
||||||
const DeepCollectionEquality().equals(other.posts, posts));
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(
|
|
||||||
runtimeType,
|
|
||||||
id,
|
|
||||||
createdAt,
|
|
||||||
updatedAt,
|
|
||||||
const DeepCollectionEquality().hash(deletedAt),
|
|
||||||
alias,
|
|
||||||
name,
|
|
||||||
description,
|
|
||||||
const DeepCollectionEquality().hash(posts));
|
|
||||||
|
|
||||||
/// Create a copy of SnPostCategory
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
_$$SnPostCategoryImplCopyWith<_$SnPostCategoryImpl> get copyWith =>
|
|
||||||
__$$SnPostCategoryImplCopyWithImpl<_$SnPostCategoryImpl>(
|
|
||||||
this, _$identity);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Map<String, dynamic> toJson() {
|
|
||||||
return _$$SnPostCategoryImplToJson(
|
|
||||||
this,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class _SnPostCategory implements SnPostCategory {
|
|
||||||
const factory _SnPostCategory(
|
|
||||||
{required final int id,
|
|
||||||
required final DateTime createdAt,
|
|
||||||
required final DateTime updatedAt,
|
|
||||||
required final dynamic deletedAt,
|
|
||||||
required final String alias,
|
|
||||||
required final String name,
|
|
||||||
required final String description,
|
|
||||||
required final dynamic posts}) = _$SnPostCategoryImpl;
|
|
||||||
|
|
||||||
factory _SnPostCategory.fromJson(Map<String, dynamic> json) =
|
|
||||||
_$SnPostCategoryImpl.fromJson;
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get id;
|
|
||||||
@override
|
|
||||||
DateTime get createdAt;
|
|
||||||
@override
|
|
||||||
DateTime get updatedAt;
|
|
||||||
@override
|
|
||||||
dynamic get deletedAt;
|
|
||||||
@override
|
|
||||||
String get alias;
|
|
||||||
@override
|
|
||||||
String get name;
|
|
||||||
@override
|
|
||||||
String get description;
|
|
||||||
@override
|
|
||||||
dynamic get posts;
|
|
||||||
|
|
||||||
/// Create a copy of SnPostCategory
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
_$$SnPostCategoryImplCopyWith<_$SnPostCategoryImpl> get copyWith =>
|
|
||||||
throw _privateConstructorUsedError;
|
|
||||||
}
|
|
||||||
|
|
||||||
SnPostPreload _$SnPostPreloadFromJson(Map<String, dynamic> json) {
|
SnPostPreload _$SnPostPreloadFromJson(Map<String, dynamic> json) {
|
||||||
return _SnPostPreload.fromJson(json);
|
return _SnPostPreload.fromJson(json);
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,7 @@ _$SnPostImpl _$$SnPostImplFromJson(Map<String, dynamic> json) => _$SnPostImpl(
|
|||||||
?.map((e) => SnPostTag.fromJson(e as Map<String, dynamic>))
|
?.map((e) => SnPostTag.fromJson(e as Map<String, dynamic>))
|
||||||
.toList() ??
|
.toList() ??
|
||||||
const [],
|
const [],
|
||||||
categories: (json['categories'] as List<dynamic>?)
|
categories: json['categories'] as List<dynamic>? ?? const [],
|
||||||
?.map((e) => SnPostCategory.fromJson(e as Map<String, dynamic>))
|
|
||||||
.toList() ??
|
|
||||||
const [],
|
|
||||||
replies: (json['replies'] as List<dynamic>?)
|
replies: (json['replies'] as List<dynamic>?)
|
||||||
?.map((e) => SnPost.fromJson(e as Map<String, dynamic>))
|
?.map((e) => SnPost.fromJson(e as Map<String, dynamic>))
|
||||||
.toList(),
|
.toList(),
|
||||||
@ -83,7 +80,7 @@ Map<String, dynamic> _$$SnPostImplToJson(_$SnPostImpl instance) =>
|
|||||||
'alias': instance.alias,
|
'alias': instance.alias,
|
||||||
'alias_prefix': instance.aliasPrefix,
|
'alias_prefix': instance.aliasPrefix,
|
||||||
'tags': instance.tags.map((e) => e.toJson()).toList(),
|
'tags': instance.tags.map((e) => e.toJson()).toList(),
|
||||||
'categories': instance.categories.map((e) => e.toJson()).toList(),
|
'categories': instance.categories,
|
||||||
'replies': instance.replies?.map((e) => e.toJson()).toList(),
|
'replies': instance.replies?.map((e) => e.toJson()).toList(),
|
||||||
'reply_id': instance.replyId,
|
'reply_id': instance.replyId,
|
||||||
'repost_id': instance.repostId,
|
'repost_id': instance.repostId,
|
||||||
@ -130,31 +127,6 @@ Map<String, dynamic> _$$SnPostTagImplToJson(_$SnPostTagImpl instance) =>
|
|||||||
'posts': instance.posts,
|
'posts': instance.posts,
|
||||||
};
|
};
|
||||||
|
|
||||||
_$SnPostCategoryImpl _$$SnPostCategoryImplFromJson(Map<String, dynamic> json) =>
|
|
||||||
_$SnPostCategoryImpl(
|
|
||||||
id: (json['id'] as num).toInt(),
|
|
||||||
createdAt: DateTime.parse(json['created_at'] as String),
|
|
||||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
|
||||||
deletedAt: json['deleted_at'],
|
|
||||||
alias: json['alias'] as String,
|
|
||||||
name: json['name'] as String,
|
|
||||||
description: json['description'] as String,
|
|
||||||
posts: json['posts'],
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$$SnPostCategoryImplToJson(
|
|
||||||
_$SnPostCategoryImpl instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'id': instance.id,
|
|
||||||
'created_at': instance.createdAt.toIso8601String(),
|
|
||||||
'updated_at': instance.updatedAt.toIso8601String(),
|
|
||||||
'deleted_at': instance.deletedAt,
|
|
||||||
'alias': instance.alias,
|
|
||||||
'name': instance.name,
|
|
||||||
'description': instance.description,
|
|
||||||
'posts': instance.posts,
|
|
||||||
};
|
|
||||||
|
|
||||||
_$SnPostPreloadImpl _$$SnPostPreloadImplFromJson(Map<String, dynamic> json) =>
|
_$SnPostPreloadImpl _$$SnPostPreloadImplFromJson(Map<String, dynamic> json) =>
|
||||||
_$SnPostPreloadImpl(
|
_$SnPostPreloadImpl(
|
||||||
thumbnail: json['thumbnail'] == null
|
thumbnail: json['thumbnail'] == null
|
||||||
|
@ -179,7 +179,6 @@ class PostItem extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
if (data.visibility > 0) _PostVisibilityHint(data: data),
|
if (data.visibility > 0) _PostVisibilityHint(data: data),
|
||||||
_PostTruncatedHint(data: data),
|
_PostTruncatedHint(data: data),
|
||||||
if (data.tags.isNotEmpty) _PostTagsList(data: data),
|
|
||||||
],
|
],
|
||||||
).padding(horizontal: 12),
|
).padding(horizontal: 12),
|
||||||
const Gap(8),
|
const Gap(8),
|
||||||
@ -187,6 +186,7 @@ class PostItem extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text('postArticle').tr().fontSize(13).opacity(0.75).padding(horizontal: 24, bottom: 8),
|
Text('postArticle').tr().fontSize(13).opacity(0.75).padding(horizontal: 24, bottom: 8),
|
||||||
|
if (data.tags.isNotEmpty) _PostTagsList(data: data).padding(horizontal: 16, bottom: 6),
|
||||||
_PostBottomAction(
|
_PostBottomAction(
|
||||||
data: data,
|
data: data,
|
||||||
showComments: showComments,
|
showComments: showComments,
|
||||||
@ -966,55 +966,23 @@ class _PostTagsList extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return Wrap(
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Wrap(
|
|
||||||
spacing: 4,
|
|
||||||
runSpacing: 4,
|
|
||||||
children: data.categories
|
|
||||||
.map(
|
|
||||||
(ele) => InkWell(
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const Icon(Symbols.category, size: 20),
|
|
||||||
const Gap(4),
|
|
||||||
Text(
|
|
||||||
'postCategory${ele.alias.capitalize()}'.trExists()
|
|
||||||
? 'postCategory${ele.alias.capitalize()}'.tr()
|
|
||||||
: ele.alias,
|
|
||||||
style: GoogleFonts.robotoMono(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
onTap: () {},
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
).opacity(0.8),
|
|
||||||
Wrap(
|
|
||||||
spacing: 4,
|
spacing: 4,
|
||||||
runSpacing: 4,
|
runSpacing: 4,
|
||||||
children: data.tags
|
children: data.tags
|
||||||
.map(
|
.map(
|
||||||
(ele) => InkWell(
|
(ele) => InkWell(
|
||||||
child: Row(
|
child: Text(
|
||||||
mainAxisSize: MainAxisSize.min,
|
'#${ele.alias}',
|
||||||
children: [
|
style: TextStyle(
|
||||||
const Icon(Symbols.label, size: 20),
|
decoration: TextDecoration.underline,
|
||||||
const Gap(4),
|
|
||||||
Text(ele.alias, style: GoogleFonts.robotoMono()),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
|
).fontSize(13),
|
||||||
onTap: () {},
|
onTap: () {},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.toList(),
|
.toList(),
|
||||||
).opacity(0.8),
|
).opacity(0.8);
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1055,7 +1023,6 @@ class _PostTruncatedHint extends StatelessWidget {
|
|||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
child: Row(
|
child: Row(
|
||||||
spacing: 8,
|
|
||||||
children: [
|
children: [
|
||||||
if (data.body['content_length'] != null)
|
if (data.body['content_length'] != null)
|
||||||
Row(
|
Row(
|
||||||
@ -1068,7 +1035,7 @@ class _PostTruncatedHint extends StatelessWidget {
|
|||||||
).inSeconds}s',
|
).inSeconds}s',
|
||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
),
|
).padding(right: 8),
|
||||||
if (data.body['content_length'] != null)
|
if (data.body['content_length'] != null)
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
|
@ -83,9 +83,7 @@ class PostMetaEditor extends StatelessWidget {
|
|||||||
return ListenableBuilder(
|
return ListenableBuilder(
|
||||||
listenable: controller,
|
listenable: controller,
|
||||||
builder: (context, _) {
|
builder: (context, _) {
|
||||||
return SingleChildScrollView(
|
return Column(
|
||||||
padding: EdgeInsets.only(bottom: MediaQuery.of(context).padding.bottom + 8),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
children: [
|
||||||
TextField(
|
TextField(
|
||||||
controller: controller.titleController,
|
controller: controller.titleController,
|
||||||
@ -117,14 +115,6 @@ class PostMetaEditor extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
).padding(horizontal: 24),
|
).padding(horizontal: 24),
|
||||||
const Gap(4),
|
const Gap(4),
|
||||||
PostCategoriesField(
|
|
||||||
initialCategories: controller.categories,
|
|
||||||
labelText: 'fieldPostCategories'.tr(),
|
|
||||||
onUpdate: (value) {
|
|
||||||
controller.setCategories(value);
|
|
||||||
},
|
|
||||||
).padding(horizontal: 24),
|
|
||||||
const Gap(4),
|
|
||||||
TextField(
|
TextField(
|
||||||
controller: controller.aliasController,
|
controller: controller.aliasController,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
@ -253,8 +243,7 @@ class PostMetaEditor extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
).padding(vertical: 8),
|
).padding(vertical: 8);
|
||||||
);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:surface/providers/sn_network.dart';
|
import 'package:surface/providers/sn_network.dart';
|
||||||
import 'package:surface/widgets/dialog.dart';
|
|
||||||
|
|
||||||
class PostTagsField extends StatefulWidget {
|
class PostTagsField extends StatefulWidget {
|
||||||
final List<String>? initialTags;
|
final List<String>? initialTags;
|
||||||
@ -23,9 +21,9 @@ class PostTagsField extends StatefulWidget {
|
|||||||
State<PostTagsField> createState() => _PostTagsFieldState();
|
State<PostTagsField> createState() => _PostTagsFieldState();
|
||||||
}
|
}
|
||||||
|
|
||||||
const List<String> kTagsDividers = [' ', ','];
|
|
||||||
|
|
||||||
class _PostTagsFieldState extends State<PostTagsField> {
|
class _PostTagsFieldState extends State<PostTagsField> {
|
||||||
|
static const List<String> kTagsDividers = [' ', ','];
|
||||||
|
|
||||||
late final _Debounceable<List<String>?, String> _debouncedSearch;
|
late final _Debounceable<List<String>?, String> _debouncedSearch;
|
||||||
|
|
||||||
final List<String> _currentTags = List.empty(growable: true);
|
final List<String> _currentTags = List.empty(growable: true);
|
||||||
@ -102,7 +100,8 @@ class _PostTagsFieldState extends State<PostTagsField> {
|
|||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
),
|
),
|
||||||
margin: const EdgeInsets.only(right: 8),
|
margin: const EdgeInsets.only(right: 8),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 4.0),
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 10.0, vertical: 4.0),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
@ -156,155 +155,6 @@ class _PostTagsFieldState extends State<PostTagsField> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PostCategoriesField extends StatefulWidget {
|
|
||||||
final List<String>? initialCategories;
|
|
||||||
final String labelText;
|
|
||||||
final Function(List<String>) onUpdate;
|
|
||||||
|
|
||||||
const PostCategoriesField({
|
|
||||||
super.key,
|
|
||||||
this.initialCategories,
|
|
||||||
required this.labelText,
|
|
||||||
required this.onUpdate,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<PostCategoriesField> createState() => _PostCategoriesFieldState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _PostCategoriesFieldState extends State<PostCategoriesField> {
|
|
||||||
late final _Debounceable<List<String>?, String> _debouncedSearch;
|
|
||||||
|
|
||||||
final List<String> _currentCategories = List.empty(growable: true);
|
|
||||||
|
|
||||||
String? _currentSearchProbe;
|
|
||||||
List<String> _lastAutocompleteResult = List.empty();
|
|
||||||
TextEditingController? _textEditingController;
|
|
||||||
|
|
||||||
Future<List<String>?> _searchCategories(String probe) async {
|
|
||||||
_currentSearchProbe = probe;
|
|
||||||
|
|
||||||
final sn = context.read<SnNetworkProvider>();
|
|
||||||
final resp = await sn.client.get(
|
|
||||||
'/cgi/co/categories?take=10&probe=$_currentSearchProbe',
|
|
||||||
);
|
|
||||||
|
|
||||||
if (_currentSearchProbe != probe) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
_currentSearchProbe = null;
|
|
||||||
|
|
||||||
return resp.data.map((x) => x['alias']).toList().cast<String>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_debouncedSearch = _debounce<List<String>?, String>(_searchCategories);
|
|
||||||
if (widget.initialCategories != null) {
|
|
||||||
_currentCategories.addAll(widget.initialCategories!);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Autocomplete<String>(
|
|
||||||
optionsBuilder: (TextEditingValue textEditingValue) async {
|
|
||||||
final result = await _debouncedSearch(textEditingValue.text);
|
|
||||||
if (result == null) {
|
|
||||||
return _lastAutocompleteResult;
|
|
||||||
}
|
|
||||||
_lastAutocompleteResult = result;
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
onSelected: (String value) {
|
|
||||||
if (value.isEmpty) return;
|
|
||||||
if (!_currentCategories.contains(value)) {
|
|
||||||
setState(() => _currentCategories.add(value));
|
|
||||||
}
|
|
||||||
_textEditingController?.clear();
|
|
||||||
widget.onUpdate(_currentCategories);
|
|
||||||
},
|
|
||||||
fieldViewBuilder: (context, controller, focusNode, onSubmitted) {
|
|
||||||
_textEditingController = controller;
|
|
||||||
return TextField(
|
|
||||||
controller: controller,
|
|
||||||
focusNode: focusNode,
|
|
||||||
decoration: InputDecoration(
|
|
||||||
label: Text(widget.labelText),
|
|
||||||
border: const UnderlineInputBorder(),
|
|
||||||
prefixIconConstraints: BoxConstraints(
|
|
||||||
maxWidth: MediaQuery.of(context).size.width * 0.75,
|
|
||||||
),
|
|
||||||
prefixIcon: _currentCategories.isNotEmpty
|
|
||||||
? SingleChildScrollView(
|
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
child: Row(
|
|
||||||
children: _currentCategories.map((String category) {
|
|
||||||
return Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
borderRadius: const BorderRadius.all(
|
|
||||||
Radius.circular(20.0),
|
|
||||||
),
|
|
||||||
color: Theme.of(context).colorScheme.primary,
|
|
||||||
),
|
|
||||||
margin: const EdgeInsets.only(right: 8),
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 4.0),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
InkWell(
|
|
||||||
child: Text(
|
|
||||||
'postCategory${category.capitalize()}'.trExists()
|
|
||||||
? 'postCategory${category.capitalize()}'.tr()
|
|
||||||
: '#$category',
|
|
||||||
style: const TextStyle(color: Colors.white),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Gap(4),
|
|
||||||
InkWell(
|
|
||||||
child: const Icon(
|
|
||||||
Icons.cancel,
|
|
||||||
size: 14.0,
|
|
||||||
color: Color.fromARGB(255, 233, 233, 233),
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
setState(() => _currentCategories.remove(category));
|
|
||||||
widget.onUpdate(_currentCategories);
|
|
||||||
},
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
|
||||||
onChanged: (value) {
|
|
||||||
for (final divider in kTagsDividers) {
|
|
||||||
if (value.endsWith(divider)) {
|
|
||||||
final tagValue = value.substring(0, value.length - 1);
|
|
||||||
if (tagValue.isEmpty) return;
|
|
||||||
if (!_currentCategories.contains(tagValue)) {
|
|
||||||
setState(() => _currentCategories.add(tagValue));
|
|
||||||
}
|
|
||||||
controller.clear();
|
|
||||||
widget.onUpdate(_currentCategories);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onSubmitted: (_) {
|
|
||||||
onSubmitted();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef _Debounceable<S, T> = Future<S?> Function(T parameter);
|
typedef _Debounceable<S, T> = Future<S?> Function(T parameter);
|
||||||
|
|
||||||
_Debounceable<S, T> _debounce<S, T>(_Debounceable<S?, T> function) {
|
_Debounceable<S, T> _debounce<S, T>(_Debounceable<S?, T> function) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user