upgrade min sdk; run formatter
This commit is contained in:
@@ -10,8 +10,9 @@ class FetchArticlesController extends _$FetchArticlesController {
|
||||
Future<void> fetchAllArticles() async {
|
||||
state = const AsyncLoading();
|
||||
state = await AsyncValue.guard(() async {
|
||||
final feeds =
|
||||
await ref.read(feedRepositoryProvider.notifier).getAllFeeds();
|
||||
final feeds = await ref
|
||||
.read(feedRepositoryProvider.notifier)
|
||||
.getAllFeeds();
|
||||
|
||||
await Future.wait(
|
||||
feeds.map((feed) async {
|
||||
|
||||
@@ -11,19 +11,19 @@ String _$fetchArticlesControllerHash() =>
|
||||
|
||||
/// See also [FetchArticlesController].
|
||||
@ProviderFor(FetchArticlesController)
|
||||
final fetchArticlesControllerProvider = AutoDisposeNotifierProvider<
|
||||
FetchArticlesController,
|
||||
AsyncValue<void>
|
||||
>.internal(
|
||||
FetchArticlesController.new,
|
||||
name: r'fetchArticlesControllerProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
final fetchArticlesControllerProvider =
|
||||
AutoDisposeNotifierProvider<
|
||||
FetchArticlesController,
|
||||
AsyncValue<void>
|
||||
>.internal(
|
||||
FetchArticlesController.new,
|
||||
name: r'fetchArticlesControllerProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$fetchArticlesControllerHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$FetchArticlesController = AutoDisposeNotifier<AsyncValue<void>>;
|
||||
// ignore_for_file: type=lint
|
||||
|
||||
@@ -91,121 +91,118 @@ class FeedArticleScreen extends HookConsumerWidget {
|
||||
}, [article]);
|
||||
|
||||
return NestedScrollView(
|
||||
headerSliverBuilder:
|
||||
(context, innerBoxIsScrolled) => [
|
||||
SliverAppBar.large(
|
||||
pinned: false,
|
||||
flexibleSpace: FlexibleSpaceBar(
|
||||
centerTitle: false,
|
||||
titlePadding: EdgeInsetsDirectional.only(
|
||||
start: 72,
|
||||
end: 72,
|
||||
bottom: bottomHeight + 16,
|
||||
),
|
||||
title: Text(
|
||||
article.displayTitle,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
background: articleImages?.firstOrNull.mapNotNull(
|
||||
(img) => Image.network(
|
||||
img.toString(),
|
||||
fit: BoxFit.cover,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.surface.withAlpha(200),
|
||||
colorBlendMode: BlendMode.darken,
|
||||
),
|
||||
),
|
||||
),
|
||||
bottom: PreferredSize(
|
||||
preferredSize: Size(double.infinity, bottomHeight),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Divider(),
|
||||
Text(
|
||||
'Published: ${hasArticleCreated ? ref.read(formatProvider.notifier).fullDateTimeWithTimezone(article.created!) : 'N/A'}',
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(fontStyle: FontStyle.italic),
|
||||
),
|
||||
if (hasArticleUpdated)
|
||||
Text(
|
||||
'Updated: ${ref.read(formatProvider.notifier).fullDateTimeWithTimezone(article.updated!)}',
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(fontStyle: FontStyle.italic),
|
||||
),
|
||||
if (hasAuthors)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
const Text('Authors:'),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: AuthorsHorizontalList(
|
||||
authors: article.authors!,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (hasTags)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
const Text('Tags:'),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: TagsHorizontalList(
|
||||
tags: article.tags!,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
if (articleLink != null)
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
await ref
|
||||
.read(tabRepositoryProvider.notifier)
|
||||
.addTab(url: articleLink.uri);
|
||||
|
||||
if (context.mounted) {
|
||||
BrowserRoute().go(context);
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.open_in_browser),
|
||||
),
|
||||
],
|
||||
headerSliverBuilder: (context, innerBoxIsScrolled) => [
|
||||
SliverAppBar.large(
|
||||
pinned: false,
|
||||
flexibleSpace: FlexibleSpaceBar(
|
||||
centerTitle: false,
|
||||
titlePadding: EdgeInsetsDirectional.only(
|
||||
start: 72,
|
||||
end: 72,
|
||||
bottom: bottomHeight + 16,
|
||||
),
|
||||
// SliverToBoxAdapter(
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(8.0),
|
||||
// child: TabBar(
|
||||
// controller: tabController,
|
||||
// tabs: [
|
||||
// ...tabs.map(
|
||||
// (tab) => switch (tab) {
|
||||
// _Pages.summary => const Tab(text: 'Summary'),
|
||||
// _Pages.content => const Tab(text: 'Article'),
|
||||
// },
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
title: Text(
|
||||
article.displayTitle,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
background: articleImages?.firstOrNull.mapNotNull(
|
||||
(img) => Image.network(
|
||||
img.toString(),
|
||||
fit: BoxFit.cover,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.surface.withAlpha(200),
|
||||
colorBlendMode: BlendMode.darken,
|
||||
),
|
||||
),
|
||||
),
|
||||
bottom: PreferredSize(
|
||||
preferredSize: Size(double.infinity, bottomHeight),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Divider(),
|
||||
Text(
|
||||
'Published: ${hasArticleCreated ? ref.read(formatProvider.notifier).fullDateTimeWithTimezone(article.created!) : 'N/A'}',
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(fontStyle: FontStyle.italic),
|
||||
),
|
||||
if (hasArticleUpdated)
|
||||
Text(
|
||||
'Updated: ${ref.read(formatProvider.notifier).fullDateTimeWithTimezone(article.updated!)}',
|
||||
style: Theme.of(context).textTheme.bodySmall
|
||||
?.copyWith(fontStyle: FontStyle.italic),
|
||||
),
|
||||
if (hasAuthors)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
const Text('Authors:'),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: AuthorsHorizontalList(
|
||||
authors: article.authors!,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (hasTags)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
const Text('Tags:'),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: TagsHorizontalList(
|
||||
tags: article.tags!,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
if (articleLink != null)
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
await ref
|
||||
.read(tabRepositoryProvider.notifier)
|
||||
.addTab(url: articleLink.uri);
|
||||
|
||||
if (context.mounted) {
|
||||
BrowserRoute().go(context);
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.open_in_browser),
|
||||
),
|
||||
],
|
||||
),
|
||||
// SliverToBoxAdapter(
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(8.0),
|
||||
// child: TabBar(
|
||||
// controller: tabController,
|
||||
// tabs: [
|
||||
// ...tabs.map(
|
||||
// (tab) => switch (tab) {
|
||||
// _Pages.summary => const Tab(text: 'Summary'),
|
||||
// _Pages.content => const Tab(text: 'Article'),
|
||||
// },
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
body: TabBarView(
|
||||
controller: tabController,
|
||||
children: [
|
||||
@@ -230,17 +227,17 @@ class FeedArticleScreen extends HookConsumerWidget {
|
||||
}
|
||||
}
|
||||
},
|
||||
styleSheet: MarkdownStyleSheet.fromTheme(
|
||||
Theme.of(context),
|
||||
).copyWith(
|
||||
blockquoteDecoration: BoxDecoration(
|
||||
color:
|
||||
Theme.of(
|
||||
styleSheet:
|
||||
MarkdownStyleSheet.fromTheme(
|
||||
Theme.of(context),
|
||||
).copyWith(
|
||||
blockquoteDecoration: BoxDecoration(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.secondaryContainer,
|
||||
borderRadius: BorderRadius.circular(2.0),
|
||||
),
|
||||
),
|
||||
borderRadius: BorderRadius.circular(2.0),
|
||||
),
|
||||
),
|
||||
data: switch (tab) {
|
||||
_Pages.summary => article.summaryMarkdown!,
|
||||
_Pages.content => article.contentMarkdown!,
|
||||
@@ -253,13 +250,12 @@ class FeedArticleScreen extends HookConsumerWidget {
|
||||
},
|
||||
);
|
||||
},
|
||||
error:
|
||||
(error, stackTrace) => Center(
|
||||
child: FailureWidget(
|
||||
title: 'Failed reading article',
|
||||
exception: error,
|
||||
),
|
||||
),
|
||||
error: (error, stackTrace) => Center(
|
||||
child: FailureWidget(
|
||||
title: 'Failed reading article',
|
||||
exception: error,
|
||||
),
|
||||
),
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -70,21 +70,20 @@ class FeedArticleListScreen extends HookConsumerWidget {
|
||||
controller: searchTextController,
|
||||
decoration: InputDecoration(
|
||||
label: const Text('Search'),
|
||||
suffixIcon:
|
||||
hasText
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
searchTextController.clear();
|
||||
focusNode.requestFocus();
|
||||
},
|
||||
icon: const Icon(Icons.clear),
|
||||
)
|
||||
: SpeechToTextButton(
|
||||
onTextReceived: (data) {
|
||||
searchTextController.text =
|
||||
data.toString();
|
||||
},
|
||||
),
|
||||
suffixIcon: hasText
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
searchTextController.clear();
|
||||
focusNode.requestFocus();
|
||||
},
|
||||
icon: const Icon(Icons.clear),
|
||||
)
|
||||
: SpeechToTextButton(
|
||||
onTextReceived: (data) {
|
||||
searchTextController.text = data
|
||||
.toString();
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
@@ -99,30 +98,29 @@ class FeedArticleListScreen extends HookConsumerWidget {
|
||||
controller: controller,
|
||||
shrinkWrap: true,
|
||||
scrollDirection: Axis.horizontal,
|
||||
children:
|
||||
tags
|
||||
.map(
|
||||
(tag) => Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
right: 8.0,
|
||||
),
|
||||
child: FilterChip(
|
||||
label: Text(tag),
|
||||
showCheckmark: false,
|
||||
selected: true,
|
||||
onSelected: (value) {},
|
||||
onDeleted: () {
|
||||
ref
|
||||
.read(
|
||||
articleFilterProvider
|
||||
.notifier,
|
||||
)
|
||||
.removeTag(tag);
|
||||
},
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
children: tags
|
||||
.map(
|
||||
(tag) => Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
right: 8.0,
|
||||
),
|
||||
child: FilterChip(
|
||||
label: Text(tag),
|
||||
showCheckmark: false,
|
||||
selected: true,
|
||||
onSelected: (value) {},
|
||||
onDeleted: () {
|
||||
ref
|
||||
.read(
|
||||
articleFilterProvider
|
||||
.notifier,
|
||||
)
|
||||
.removeTag(tag);
|
||||
},
|
||||
),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -175,13 +173,12 @@ class FeedArticleListScreen extends HookConsumerWidget {
|
||||
),
|
||||
);
|
||||
},
|
||||
error:
|
||||
(error, stackTrace) => Center(
|
||||
child: FailureWidget(
|
||||
title: 'Failed to load Articles',
|
||||
exception: error,
|
||||
),
|
||||
),
|
||||
error: (error, stackTrace) => Center(
|
||||
child: FailureWidget(
|
||||
title: 'Failed to load Articles',
|
||||
exception: error,
|
||||
),
|
||||
),
|
||||
loading: () => const SizedBox.shrink(),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -60,39 +60,34 @@ class FeedEditScreen extends HookConsumerWidget {
|
||||
|
||||
return _FeedEditContent(mode: _mode, initialFeed: initialFeed);
|
||||
},
|
||||
error:
|
||||
(error, stackTrace) => Scaffold(
|
||||
key: const ValueKey('error'),
|
||||
appBar: AppBar(),
|
||||
body: Center(
|
||||
child: FailureWidget(
|
||||
title: 'Failed to load feed',
|
||||
exception: error,
|
||||
error: (error, stackTrace) => Scaffold(
|
||||
key: const ValueKey('error'),
|
||||
appBar: AppBar(),
|
||||
body: Center(
|
||||
child: FailureWidget(title: 'Failed to load feed', exception: error),
|
||||
),
|
||||
),
|
||||
loading: () => Scaffold(
|
||||
key: const ValueKey('loading'),
|
||||
appBar: AppBar(
|
||||
title: Text(switch (_mode) {
|
||||
_DialogMode.create => 'New Feed',
|
||||
_DialogMode.edit => 'Edit Feed',
|
||||
}),
|
||||
),
|
||||
body: const Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
CircularProgressIndicator(),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 8.0),
|
||||
child: Text('Fetching feed...'),
|
||||
),
|
||||
),
|
||||
),
|
||||
loading:
|
||||
() => Scaffold(
|
||||
key: const ValueKey('loading'),
|
||||
appBar: AppBar(
|
||||
title: Text(switch (_mode) {
|
||||
_DialogMode.create => 'New Feed',
|
||||
_DialogMode.edit => 'Edit Feed',
|
||||
}),
|
||||
),
|
||||
body: const Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
CircularProgressIndicator(),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 8.0),
|
||||
child: Text('Fetching feed...'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -141,11 +136,10 @@ class _FeedEditContent extends HookConsumerWidget {
|
||||
onPressed: () async {
|
||||
if (formKey.currentState?.validate() ?? false) {
|
||||
final feedData = FeedData(
|
||||
url:
|
||||
uri_parser.tryParseUrl(
|
||||
urlTextController.text,
|
||||
eagerParsing: true,
|
||||
)!,
|
||||
url: uri_parser.tryParseUrl(
|
||||
urlTextController.text,
|
||||
eagerParsing: true,
|
||||
)!,
|
||||
authors: initialFeed.authors,
|
||||
description: descriptionTextController.text.whenNotEmpty,
|
||||
icon: uri_parser.tryParseUrl(
|
||||
|
||||
@@ -32,17 +32,16 @@ class FeedListScreen extends HookConsumerWidget {
|
||||
),
|
||||
);
|
||||
},
|
||||
error:
|
||||
(error, stackTrace) => Center(
|
||||
child: FailureWidget(
|
||||
title: 'Failed to load Feeds',
|
||||
exception: error,
|
||||
onRetry: () {
|
||||
// ignore: unused_result
|
||||
ref.refresh(feedListProvider);
|
||||
},
|
||||
),
|
||||
),
|
||||
error: (error, stackTrace) => Center(
|
||||
child: FailureWidget(
|
||||
title: 'Failed to load Feeds',
|
||||
exception: error,
|
||||
onRetry: () {
|
||||
// ignore: unused_result
|
||||
ref.refresh(feedListProvider);
|
||||
},
|
||||
),
|
||||
),
|
||||
loading: () => const SizedBox.shrink(),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
|
||||
@@ -15,51 +15,44 @@ class SelectFeedDialog extends HookConsumerWidget {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return SimpleDialog(
|
||||
title: const Text('Add Feed'),
|
||||
children:
|
||||
feedUris
|
||||
.map(
|
||||
(uri) => HookConsumer(
|
||||
builder: (context, ref, child) {
|
||||
final feedAsync = ref.watch(fetchWebFeedProvider(uri));
|
||||
children: feedUris
|
||||
.map(
|
||||
(uri) => HookConsumer(
|
||||
builder: (context, ref, child) {
|
||||
final feedAsync = ref.watch(fetchWebFeedProvider(uri));
|
||||
|
||||
return feedAsync.when(
|
||||
data: (data) {
|
||||
return ListTile(
|
||||
title: Text(
|
||||
data.feedData.title.whenNotEmpty ?? 'Unnamed Feed',
|
||||
),
|
||||
subtitle: Text(uri.toString()),
|
||||
trailing: const Icon(Icons.add),
|
||||
onTap: () {
|
||||
FeedCreateRoute(
|
||||
feedId: uri,
|
||||
).pushReplacement(context);
|
||||
},
|
||||
);
|
||||
return feedAsync.when(
|
||||
data: (data) {
|
||||
return ListTile(
|
||||
title: Text(
|
||||
data.feedData.title.whenNotEmpty ?? 'Unnamed Feed',
|
||||
),
|
||||
subtitle: Text(uri.toString()),
|
||||
trailing: const Icon(Icons.add),
|
||||
onTap: () {
|
||||
FeedCreateRoute(feedId: uri).pushReplacement(context);
|
||||
},
|
||||
error:
|
||||
(error, stackTrace) => FailureWidget(
|
||||
title: 'Failed to fetch Feed',
|
||||
exception: error,
|
||||
onRetry: () {
|
||||
// ignore: unused_result
|
||||
ref.refresh(fetchWebFeedProvider(uri));
|
||||
},
|
||||
),
|
||||
loading:
|
||||
() => Skeletonizer(
|
||||
child: ListTile(
|
||||
title: Text(BoneMock.title),
|
||||
subtitle: Skeleton.keep(
|
||||
child: Text(uri.toString()),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
error: (error, stackTrace) => FailureWidget(
|
||||
title: 'Failed to fetch Feed',
|
||||
exception: error,
|
||||
onRetry: () {
|
||||
// ignore: unused_result
|
||||
ref.refresh(fetchWebFeedProvider(uri));
|
||||
},
|
||||
),
|
||||
loading: () => Skeletonizer(
|
||||
child: ListTile(
|
||||
title: Text(BoneMock.title),
|
||||
subtitle: Skeleton.keep(child: Text(uri.toString())),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,26 +11,25 @@ class AuthorsHorizontalList extends StatelessWidget {
|
||||
Set<String> selectedTags = const {},
|
||||
void Function(String tagId, bool value)? onTagSelected,
|
||||
}) {
|
||||
_authors =
|
||||
authors.map((author) {
|
||||
final label = Text(
|
||||
'${author.name ?? ''} ${author.email.mapNotNull((email) => '($email)') ?? ''}'
|
||||
.trim(),
|
||||
);
|
||||
_authors = authors.map((author) {
|
||||
final label = Text(
|
||||
'${author.name ?? ''} ${author.email.mapNotNull((email) => '($email)') ?? ''}'
|
||||
.trim(),
|
||||
);
|
||||
|
||||
return onTagSelected.mapNotNull(
|
||||
(onTagSelected) => FilterChip(
|
||||
label: label,
|
||||
selected: selectedTags.contains(author.name),
|
||||
onSelected: (value) {
|
||||
if (author.name.isNotEmpty) {
|
||||
onTagSelected(author.name!, value);
|
||||
}
|
||||
},
|
||||
),
|
||||
) ??
|
||||
Chip(label: label);
|
||||
}).toList();
|
||||
return onTagSelected.mapNotNull(
|
||||
(onTagSelected) => FilterChip(
|
||||
label: label,
|
||||
selected: selectedTags.contains(author.name),
|
||||
onSelected: (value) {
|
||||
if (author.name.isNotEmpty) {
|
||||
onTagSelected(author.name!, value);
|
||||
}
|
||||
},
|
||||
),
|
||||
) ??
|
||||
Chip(label: label);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -70,11 +70,12 @@ class FeedArticleCard extends HookConsumerWidget {
|
||||
MarkdownBody(
|
||||
data: titleHighlight!,
|
||||
styleSheet: MarkdownStyleSheet(
|
||||
p: Theme.of(
|
||||
context,
|
||||
).textTheme.titleMedium?.copyWith(
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
p: Theme.of(context).textTheme.titleMedium
|
||||
?.copyWith(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (titleHighlight.isEmpty)
|
||||
@@ -86,23 +87,19 @@ class FeedArticleCard extends HookConsumerWidget {
|
||||
MarkdownBody(
|
||||
data: searchSnippet!,
|
||||
styleSheet: MarkdownStyleSheet(
|
||||
p: Theme.of(
|
||||
context,
|
||||
).textTheme.bodyMedium?.copyWith(
|
||||
color:
|
||||
Theme.of(
|
||||
p: Theme.of(context).textTheme.bodyMedium
|
||||
?.copyWith(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
a: Theme.of(
|
||||
context,
|
||||
).textTheme.bodyMedium?.copyWith(
|
||||
color:
|
||||
Theme.of(
|
||||
),
|
||||
a: Theme.of(context).textTheme.bodyMedium
|
||||
?.copyWith(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
decoration: TextDecoration.none,
|
||||
),
|
||||
decoration: TextDecoration.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (searchSnippet.isEmpty &&
|
||||
|
||||
@@ -108,16 +108,18 @@ class FeedCard extends HookConsumerWidget {
|
||||
Icon(
|
||||
MdiIcons.newspaperVariantMultipleOutline,
|
||||
size: 18,
|
||||
color:
|
||||
Theme.of(context).colorScheme.onPrimary,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onPrimary,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
count.toString(),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color:
|
||||
Theme.of(context).colorScheme.onPrimary,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onPrimary,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -31,17 +31,16 @@ class TagField extends HookWidget {
|
||||
const SizedBox(height: 4),
|
||||
Wrap(
|
||||
spacing: 8.0,
|
||||
children:
|
||||
tags.value
|
||||
.map(
|
||||
(tag) => InputChip(
|
||||
label: Text(tag),
|
||||
onDeleted: () {
|
||||
tags.value = {...tags.value}..remove(tag);
|
||||
},
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
children: tags.value
|
||||
.map(
|
||||
(tag) => InputChip(
|
||||
label: Text(tag),
|
||||
onDeleted: () {
|
||||
tags.value = {...tags.value}..remove(tag);
|
||||
},
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
TextField(
|
||||
controller: textController,
|
||||
@@ -68,12 +67,11 @@ class TagField extends HookWidget {
|
||||
},
|
||||
onSubmitted: (value) {
|
||||
if (value.isNotEmpty) {
|
||||
final values =
|
||||
value
|
||||
.split(_tagSplitPatter)
|
||||
.map((str) => str.trim())
|
||||
.where((str) => str.isNotEmpty)
|
||||
.toList();
|
||||
final values = value
|
||||
.split(_tagSplitPatter)
|
||||
.map((str) => str.trim())
|
||||
.where((str) => str.isNotEmpty)
|
||||
.toList();
|
||||
|
||||
if (values.isNotEmpty) {
|
||||
textController.clear();
|
||||
|
||||
@@ -11,28 +11,26 @@ class TagsHorizontalList extends StatelessWidget {
|
||||
Set<String> selectedTags = const {},
|
||||
void Function(String tagId, bool value)? onTagSelected,
|
||||
}) {
|
||||
_tags =
|
||||
tags.map((tag) {
|
||||
final label = Text(
|
||||
'${tag.id} ${tag.title.mapNotNull((title) => '($title)') ?? ''}'
|
||||
.trim(),
|
||||
);
|
||||
_tags = tags.map((tag) {
|
||||
final label = Text(
|
||||
'${tag.id} ${tag.title.mapNotNull((title) => '($title)') ?? ''}'.trim(),
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child:
|
||||
onTagSelected.mapNotNull(
|
||||
(onTagSelected) => FilterChip(
|
||||
label: label,
|
||||
selected: selectedTags.contains(tag.id),
|
||||
onSelected: (value) {
|
||||
onTagSelected(tag.id, value);
|
||||
},
|
||||
),
|
||||
) ??
|
||||
Chip(label: label),
|
||||
);
|
||||
}).toList();
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child:
|
||||
onTagSelected.mapNotNull(
|
||||
(onTagSelected) => FilterChip(
|
||||
label: label,
|
||||
selected: selectedTags.contains(tag.id),
|
||||
onSelected: (value) {
|
||||
onTagSelected(tag.id, value);
|
||||
},
|
||||
),
|
||||
) ??
|
||||
Chip(label: label),
|
||||
);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
Reference in New Issue
Block a user