web feed intermediate
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
import 'package:lensai/features/web_feed/data/database/database.dart';
|
||||
import 'package:lensai/features/web_feed/data/models/feed_filter.dart';
|
||||
import 'package:lensai/features/web_feed/data/models/feed_article.dart';
|
||||
import 'package:lensai/features/web_feed/domain/repositories/feed_repository.dart';
|
||||
import 'package:riverpod/riverpod.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
part 'providers.g.dart';
|
||||
|
||||
@Riverpod()
|
||||
Stream<List<FeedData>> feedList(Ref ref) {
|
||||
final repository = ref.watch(feedRepositoryProvider.notifier);
|
||||
return repository.watchFeeds();
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
Stream<List<FeedArticle>> feedArticleList(Ref ref, FeedFilter filter) {
|
||||
final repository = ref.watch(feedRepositoryProvider.notifier);
|
||||
return repository.watchFeedArticles(filter);
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
Stream<FeedArticle?> feedArticle(Ref ref, String articleId) {
|
||||
final repository = ref.watch(feedRepositoryProvider.notifier);
|
||||
return repository.watchArticle(articleId);
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
Raw<Stream<Map<String, int>>> _unreadArticleCount(Ref ref) {
|
||||
final repository = ref.watch(feedRepositoryProvider.notifier);
|
||||
return repository.watchUnreadFeedArticleCount();
|
||||
}
|
||||
|
||||
@Riverpod()
|
||||
Stream<int?> unreadFeedArticleCount(Ref ref, Uri feedId) {
|
||||
final stream = ref.watch(_unreadArticleCountProvider);
|
||||
return stream.map((counts) => counts[feedId.toString()]);
|
||||
}
|
||||
@@ -0,0 +1,433 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'providers.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$feedListHash() => r'0076186437354768c39fb1d7c8bcfcf7b94c7dd1';
|
||||
|
||||
/// See also [feedList].
|
||||
@ProviderFor(feedList)
|
||||
final feedListProvider = AutoDisposeStreamProvider<List<FeedData>>.internal(
|
||||
feedList,
|
||||
name: r'feedListProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product') ? null : _$feedListHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
typedef FeedListRef = AutoDisposeStreamProviderRef<List<FeedData>>;
|
||||
String _$feedArticleListHash() => r'64e834a1b69d913f1c860b38956b69af9e89a833';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
_SystemHash._();
|
||||
|
||||
static int combine(int hash, int value) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + value);
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||
return hash ^ (hash >> 6);
|
||||
}
|
||||
|
||||
static int finish(int hash) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||
// ignore: parameter_assignments
|
||||
hash = hash ^ (hash >> 11);
|
||||
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||
}
|
||||
}
|
||||
|
||||
/// See also [feedArticleList].
|
||||
@ProviderFor(feedArticleList)
|
||||
const feedArticleListProvider = FeedArticleListFamily();
|
||||
|
||||
/// See also [feedArticleList].
|
||||
class FeedArticleListFamily extends Family<AsyncValue<List<FeedArticle>>> {
|
||||
/// See also [feedArticleList].
|
||||
const FeedArticleListFamily();
|
||||
|
||||
/// See also [feedArticleList].
|
||||
FeedArticleListProvider call(FeedFilter filter) {
|
||||
return FeedArticleListProvider(filter);
|
||||
}
|
||||
|
||||
@override
|
||||
FeedArticleListProvider getProviderOverride(
|
||||
covariant FeedArticleListProvider provider,
|
||||
) {
|
||||
return call(provider.filter);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'feedArticleListProvider';
|
||||
}
|
||||
|
||||
/// See also [feedArticleList].
|
||||
class FeedArticleListProvider
|
||||
extends AutoDisposeStreamProvider<List<FeedArticle>> {
|
||||
/// See also [feedArticleList].
|
||||
FeedArticleListProvider(FeedFilter filter)
|
||||
: this._internal(
|
||||
(ref) => feedArticleList(ref as FeedArticleListRef, filter),
|
||||
from: feedArticleListProvider,
|
||||
name: r'feedArticleListProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$feedArticleListHash,
|
||||
dependencies: FeedArticleListFamily._dependencies,
|
||||
allTransitiveDependencies:
|
||||
FeedArticleListFamily._allTransitiveDependencies,
|
||||
filter: filter,
|
||||
);
|
||||
|
||||
FeedArticleListProvider._internal(
|
||||
super._createNotifier, {
|
||||
required super.name,
|
||||
required super.dependencies,
|
||||
required super.allTransitiveDependencies,
|
||||
required super.debugGetCreateSourceHash,
|
||||
required super.from,
|
||||
required this.filter,
|
||||
}) : super.internal();
|
||||
|
||||
final FeedFilter filter;
|
||||
|
||||
@override
|
||||
Override overrideWith(
|
||||
Stream<List<FeedArticle>> Function(FeedArticleListRef provider) create,
|
||||
) {
|
||||
return ProviderOverride(
|
||||
origin: this,
|
||||
override: FeedArticleListProvider._internal(
|
||||
(ref) => create(ref as FeedArticleListRef),
|
||||
from: from,
|
||||
name: null,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
filter: filter,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AutoDisposeStreamProviderElement<List<FeedArticle>> createElement() {
|
||||
return _FeedArticleListProviderElement(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is FeedArticleListProvider && other.filter == filter;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, filter.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
mixin FeedArticleListRef on AutoDisposeStreamProviderRef<List<FeedArticle>> {
|
||||
/// The parameter `filter` of this provider.
|
||||
FeedFilter get filter;
|
||||
}
|
||||
|
||||
class _FeedArticleListProviderElement
|
||||
extends AutoDisposeStreamProviderElement<List<FeedArticle>>
|
||||
with FeedArticleListRef {
|
||||
_FeedArticleListProviderElement(super.provider);
|
||||
|
||||
@override
|
||||
FeedFilter get filter => (origin as FeedArticleListProvider).filter;
|
||||
}
|
||||
|
||||
String _$feedArticleHash() => r'b1670f2ce11636f42fc0595befe42ada19319880';
|
||||
|
||||
/// See also [feedArticle].
|
||||
@ProviderFor(feedArticle)
|
||||
const feedArticleProvider = FeedArticleFamily();
|
||||
|
||||
/// See also [feedArticle].
|
||||
class FeedArticleFamily extends Family<AsyncValue<FeedArticle?>> {
|
||||
/// See also [feedArticle].
|
||||
const FeedArticleFamily();
|
||||
|
||||
/// See also [feedArticle].
|
||||
FeedArticleProvider call(String articleId) {
|
||||
return FeedArticleProvider(articleId);
|
||||
}
|
||||
|
||||
@override
|
||||
FeedArticleProvider getProviderOverride(
|
||||
covariant FeedArticleProvider provider,
|
||||
) {
|
||||
return call(provider.articleId);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'feedArticleProvider';
|
||||
}
|
||||
|
||||
/// See also [feedArticle].
|
||||
class FeedArticleProvider extends AutoDisposeStreamProvider<FeedArticle?> {
|
||||
/// See also [feedArticle].
|
||||
FeedArticleProvider(String articleId)
|
||||
: this._internal(
|
||||
(ref) => feedArticle(ref as FeedArticleRef, articleId),
|
||||
from: feedArticleProvider,
|
||||
name: r'feedArticleProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$feedArticleHash,
|
||||
dependencies: FeedArticleFamily._dependencies,
|
||||
allTransitiveDependencies: FeedArticleFamily._allTransitiveDependencies,
|
||||
articleId: articleId,
|
||||
);
|
||||
|
||||
FeedArticleProvider._internal(
|
||||
super._createNotifier, {
|
||||
required super.name,
|
||||
required super.dependencies,
|
||||
required super.allTransitiveDependencies,
|
||||
required super.debugGetCreateSourceHash,
|
||||
required super.from,
|
||||
required this.articleId,
|
||||
}) : super.internal();
|
||||
|
||||
final String articleId;
|
||||
|
||||
@override
|
||||
Override overrideWith(
|
||||
Stream<FeedArticle?> Function(FeedArticleRef provider) create,
|
||||
) {
|
||||
return ProviderOverride(
|
||||
origin: this,
|
||||
override: FeedArticleProvider._internal(
|
||||
(ref) => create(ref as FeedArticleRef),
|
||||
from: from,
|
||||
name: null,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
articleId: articleId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AutoDisposeStreamProviderElement<FeedArticle?> createElement() {
|
||||
return _FeedArticleProviderElement(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is FeedArticleProvider && other.articleId == articleId;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, articleId.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
mixin FeedArticleRef on AutoDisposeStreamProviderRef<FeedArticle?> {
|
||||
/// The parameter `articleId` of this provider.
|
||||
String get articleId;
|
||||
}
|
||||
|
||||
class _FeedArticleProviderElement
|
||||
extends AutoDisposeStreamProviderElement<FeedArticle?>
|
||||
with FeedArticleRef {
|
||||
_FeedArticleProviderElement(super.provider);
|
||||
|
||||
@override
|
||||
String get articleId => (origin as FeedArticleProvider).articleId;
|
||||
}
|
||||
|
||||
String _$unreadArticleCountHash() =>
|
||||
r'6fb96215fb3b7739a6cbd594a0358415ced04fca';
|
||||
|
||||
/// See also [_unreadArticleCount].
|
||||
@ProviderFor(_unreadArticleCount)
|
||||
final _unreadArticleCountProvider =
|
||||
AutoDisposeProvider<Raw<Stream<Map<String, int>>>>.internal(
|
||||
_unreadArticleCount,
|
||||
name: r'_unreadArticleCountProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$unreadArticleCountHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
typedef _UnreadArticleCountRef =
|
||||
AutoDisposeProviderRef<Raw<Stream<Map<String, int>>>>;
|
||||
String _$unreadFeedArticleCountHash() =>
|
||||
r'f8573674477f0d9813b42c82d75e8196c1c1445b';
|
||||
|
||||
/// See also [unreadFeedArticleCount].
|
||||
@ProviderFor(unreadFeedArticleCount)
|
||||
const unreadFeedArticleCountProvider = UnreadFeedArticleCountFamily();
|
||||
|
||||
/// See also [unreadFeedArticleCount].
|
||||
class UnreadFeedArticleCountFamily extends Family<AsyncValue<int?>> {
|
||||
/// See also [unreadFeedArticleCount].
|
||||
const UnreadFeedArticleCountFamily();
|
||||
|
||||
/// See also [unreadFeedArticleCount].
|
||||
UnreadFeedArticleCountProvider call(Uri feedId) {
|
||||
return UnreadFeedArticleCountProvider(feedId);
|
||||
}
|
||||
|
||||
@override
|
||||
UnreadFeedArticleCountProvider getProviderOverride(
|
||||
covariant UnreadFeedArticleCountProvider provider,
|
||||
) {
|
||||
return call(provider.feedId);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'unreadFeedArticleCountProvider';
|
||||
}
|
||||
|
||||
/// See also [unreadFeedArticleCount].
|
||||
class UnreadFeedArticleCountProvider extends AutoDisposeStreamProvider<int?> {
|
||||
/// See also [unreadFeedArticleCount].
|
||||
UnreadFeedArticleCountProvider(Uri feedId)
|
||||
: this._internal(
|
||||
(ref) =>
|
||||
unreadFeedArticleCount(ref as UnreadFeedArticleCountRef, feedId),
|
||||
from: unreadFeedArticleCountProvider,
|
||||
name: r'unreadFeedArticleCountProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$unreadFeedArticleCountHash,
|
||||
dependencies: UnreadFeedArticleCountFamily._dependencies,
|
||||
allTransitiveDependencies:
|
||||
UnreadFeedArticleCountFamily._allTransitiveDependencies,
|
||||
feedId: feedId,
|
||||
);
|
||||
|
||||
UnreadFeedArticleCountProvider._internal(
|
||||
super._createNotifier, {
|
||||
required super.name,
|
||||
required super.dependencies,
|
||||
required super.allTransitiveDependencies,
|
||||
required super.debugGetCreateSourceHash,
|
||||
required super.from,
|
||||
required this.feedId,
|
||||
}) : super.internal();
|
||||
|
||||
final Uri feedId;
|
||||
|
||||
@override
|
||||
Override overrideWith(
|
||||
Stream<int?> Function(UnreadFeedArticleCountRef provider) create,
|
||||
) {
|
||||
return ProviderOverride(
|
||||
origin: this,
|
||||
override: UnreadFeedArticleCountProvider._internal(
|
||||
(ref) => create(ref as UnreadFeedArticleCountRef),
|
||||
from: from,
|
||||
name: null,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
feedId: feedId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AutoDisposeStreamProviderElement<int?> createElement() {
|
||||
return _UnreadFeedArticleCountProviderElement(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is UnreadFeedArticleCountProvider && other.feedId == feedId;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, feedId.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
mixin UnreadFeedArticleCountRef on AutoDisposeStreamProviderRef<int?> {
|
||||
/// The parameter `feedId` of this provider.
|
||||
Uri get feedId;
|
||||
}
|
||||
|
||||
class _UnreadFeedArticleCountProviderElement
|
||||
extends AutoDisposeStreamProviderElement<int?>
|
||||
with UnreadFeedArticleCountRef {
|
||||
_UnreadFeedArticleCountProviderElement(super.provider);
|
||||
|
||||
@override
|
||||
Uri get feedId => (origin as UnreadFeedArticleCountProvider).feedId;
|
||||
}
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||
@@ -0,0 +1,26 @@
|
||||
import 'package:lensai/extensions/nullable.dart';
|
||||
import 'package:lensai/features/web_feed/data/models/feed_filter.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
part 'article_filter.g.dart';
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
class ArticleFilter extends _$ArticleFilter {
|
||||
void addTag(String tagId) {
|
||||
final tags = {...?state.tags, tagId};
|
||||
|
||||
state = state.copyWith.tags(tags);
|
||||
}
|
||||
|
||||
void removeTag(String tagId) {
|
||||
if (state.tags.isNotEmpty) {
|
||||
final tags = {...state.tags!}..remove(tagId);
|
||||
state = state.copyWith.tags(tags);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
FeedFilter build() {
|
||||
return FeedFilter();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'article_filter.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$articleFilterHash() => r'dfc997af8a33cbcb995288ef633ff321e95bae8d';
|
||||
|
||||
/// See also [ArticleFilter].
|
||||
@ProviderFor(ArticleFilter)
|
||||
final articleFilterProvider =
|
||||
NotifierProvider<ArticleFilter, FeedFilter>.internal(
|
||||
ArticleFilter.new,
|
||||
name: r'articleFilterProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$articleFilterHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$ArticleFilter = Notifier<FeedFilter>;
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||
@@ -0,0 +1,117 @@
|
||||
import 'package:lensai/extensions/nullable.dart';
|
||||
import 'package:lensai/features/web_feed/data/database/database.dart';
|
||||
import 'package:lensai/features/web_feed/data/models/feed_filter.dart';
|
||||
import 'package:lensai/features/web_feed/data/models/feed_article.dart';
|
||||
import 'package:lensai/features/web_feed/data/providers.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
part 'feed_repository.g.dart';
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
class FeedRepository extends _$FeedRepository {
|
||||
Future<List<FeedData>> getAllFeeds() {
|
||||
return ref.read(feedDatabaseProvider).feedDao.getFeeds().get();
|
||||
}
|
||||
|
||||
Future<void> touchFeedFetched(Uri url) {
|
||||
return ref
|
||||
.read(feedDatabaseProvider)
|
||||
.feedDao
|
||||
.updateFeedFetched(url, DateTime.now());
|
||||
}
|
||||
|
||||
Future<void> upsertFeed(FeedData feedData) {
|
||||
return ref.read(feedDatabaseProvider).feedDao.upsertFeed(feedData);
|
||||
}
|
||||
|
||||
Future<void> upsertArticles(List<FeedArticle> articles) {
|
||||
return ref.read(feedDatabaseProvider).articleDao.upsertArticles(articles);
|
||||
}
|
||||
|
||||
Future<int> deleteFeed(Uri url) {
|
||||
return ref.read(feedDatabaseProvider).feedDao.deleteFeed(url);
|
||||
}
|
||||
|
||||
Future<void> touchArticleRead(String articleId) {
|
||||
return ref
|
||||
.read(feedDatabaseProvider)
|
||||
.articleDao
|
||||
.updateArticleRead(articleId, DateTime.now());
|
||||
}
|
||||
|
||||
Future<void> unsetArticleRead(String articleId) {
|
||||
return ref
|
||||
.read(feedDatabaseProvider)
|
||||
.articleDao
|
||||
.updateArticleRead(articleId, null);
|
||||
}
|
||||
|
||||
Stream<List<FeedData>> watchFeeds() {
|
||||
return ref.read(feedDatabaseProvider).feedDao.getFeeds().watch();
|
||||
}
|
||||
|
||||
Stream<List<FeedArticle>> watchFeedArticles(
|
||||
FeedFilter filter, {
|
||||
int snippetLength = 120,
|
||||
String matchPrefix = '***',
|
||||
String matchSuffix = '***',
|
||||
String ellipsis = '…',
|
||||
}) {
|
||||
final stream =
|
||||
filter.query.isNotEmpty
|
||||
? ref
|
||||
.read(feedDatabaseProvider)
|
||||
.articleDao
|
||||
.queryArticles(
|
||||
matchPrefix: matchPrefix,
|
||||
matchSuffix: matchSuffix,
|
||||
ellipsis: ellipsis,
|
||||
snippetLength: snippetLength,
|
||||
searchString: filter.query!,
|
||||
feedId: filter.feedId,
|
||||
)
|
||||
.watch()
|
||||
: ref
|
||||
.read(feedDatabaseProvider)
|
||||
.articleDao
|
||||
.getFeedArticles(filter.feedId)
|
||||
.watch();
|
||||
|
||||
if (filter.tags.isNotEmpty) {
|
||||
return stream.map(
|
||||
(articles) =>
|
||||
articles
|
||||
.where(
|
||||
(article) =>
|
||||
article.tags?.toSet().containsAll(filter.tags!) ?? false,
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
} else {
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
|
||||
Stream<FeedArticle?> watchArticle(String articleId) {
|
||||
return ref
|
||||
.read(feedDatabaseProvider)
|
||||
.articleDao
|
||||
.getArticleById(articleId)
|
||||
.watchSingleOrNull();
|
||||
}
|
||||
|
||||
Stream<Map<String, int>> watchUnreadFeedArticleCount() {
|
||||
return ref
|
||||
.read(feedDatabaseProvider)
|
||||
.articleDao
|
||||
.getUnreadArticleCount()
|
||||
.watch()
|
||||
.map(
|
||||
(results) =>
|
||||
Map.fromEntries(results.map((e) => MapEntry(e.$1, e.$2))),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void build() {}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'feed_repository.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$feedRepositoryHash() => r'6a050933a6a4eafbe76a66262e1b64bd838a1078';
|
||||
|
||||
/// See also [FeedRepository].
|
||||
@ProviderFor(FeedRepository)
|
||||
final feedRepositoryProvider = NotifierProvider<FeedRepository, void>.internal(
|
||||
FeedRepository.new,
|
||||
name: r'feedRepositoryProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$feedRepositoryHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$FeedRepository = Notifier<void>;
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||
@@ -0,0 +1,45 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:lensai/features/web_feed/data/models/feed_parse_result.dart';
|
||||
import 'package:lensai/features/web_feed/utils/feed_parser.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
part 'feed_reader.g.dart';
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
class FeedReader extends _$FeedReader {
|
||||
Future<FeedParseResult> parseFeed(Uri url) async {
|
||||
final rootIsolateToken = ServicesBinding.rootIsolateToken!;
|
||||
|
||||
final result = await compute((args) async {
|
||||
// Initialize BackgroundIsolateBinaryMessenger with the token
|
||||
BackgroundIsolateBinaryMessenger.ensureInitialized(
|
||||
args['token']! as RootIsolateToken,
|
||||
);
|
||||
|
||||
final client = http.Client();
|
||||
try {
|
||||
final url = Uri.parse(args['url']! as String);
|
||||
final response = await client
|
||||
.get(url)
|
||||
.timeout(const Duration(seconds: 30));
|
||||
|
||||
final parser = FeedParser.parse(url: url, xmlString: response.body);
|
||||
final result = FeedParseResult(
|
||||
feedData: parser.readGeneralData(),
|
||||
articleData: await parser.readArticles(),
|
||||
);
|
||||
|
||||
return result.toJson();
|
||||
} finally {
|
||||
client.close();
|
||||
}
|
||||
}, {'token': rootIsolateToken, 'url': url.toString()});
|
||||
|
||||
return FeedParseResult.fromJson(result);
|
||||
}
|
||||
|
||||
@override
|
||||
void build() {}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'feed_reader.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$feedReaderHash() => r'67b09485e40c522108709ca32b9c624b4db2446b';
|
||||
|
||||
/// See also [FeedReader].
|
||||
@ProviderFor(FeedReader)
|
||||
final feedReaderProvider = NotifierProvider<FeedReader, void>.internal(
|
||||
FeedReader.new,
|
||||
name: r'feedReaderProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product') ? null : _$feedReaderHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$FeedReader = Notifier<void>;
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||
Reference in New Issue
Block a user