124 lines
4.2 KiB
Dart
124 lines
4.2 KiB
Dart
import '../database/database.dart';
|
|
import 'controllers/bookmarks_controller.dart';
|
|
import 'controllers/reader_settings_controller.dart'
|
|
show ReaderSettingsController;
|
|
import 'controllers/subscriptions_controller.dart';
|
|
import 'pages/mews_urls.dart';
|
|
|
|
/// Applies the change an action address encodes, e.g. mews:do/set-theme.
|
|
/// Returns whether anything changed, so the navigator can skip a rerender that
|
|
/// would show the same page.
|
|
///
|
|
/// An unknown verb or a missing argument does nothing and reports nothing: the
|
|
/// only links carrying these addresses are the ones the client builds, so a
|
|
/// miss is a bug rather than something to explain to the reader.
|
|
class InternalActions {
|
|
InternalActions({
|
|
required MewsDatabase db,
|
|
required ReaderSettingsController settings,
|
|
required BookmarksController bookmarks,
|
|
required SubscriptionsController subscriptions,
|
|
}) : _db = db,
|
|
_settings = settings,
|
|
_bookmarks = bookmarks,
|
|
_subscriptions = subscriptions;
|
|
|
|
final MewsDatabase _db;
|
|
final ReaderSettingsController _settings;
|
|
final BookmarksController _bookmarks;
|
|
final SubscriptionsController _subscriptions;
|
|
|
|
Future<bool> apply(String url) async {
|
|
final verb = MewsUrls.verbOf(url);
|
|
if (verb == null) return false;
|
|
final args = Uri.parse(url).queryParameters;
|
|
return switch (verb) {
|
|
'set-font' => _settings.setFont(args['value'] ?? ''),
|
|
'set-size' => _setSize(args['step']),
|
|
'set-theme' => _settings.setThemeMode(args['value'] ?? ''),
|
|
'set-colors' => _settings.setVariant(args['value'] ?? ''),
|
|
'mark-read' => _markRead(args, read: true),
|
|
'mark-unread' => _markRead(args, read: false),
|
|
'refresh-subscriptions' => _refreshAll(),
|
|
'refresh-subscription' => _refreshOne(args['url']),
|
|
'remove-bookmark' => _withUrl(args, _bookmarks.remove),
|
|
'unsubscribe' => _withUrl(args, _subscriptions.remove),
|
|
'forget-page' => _withUrl(args, _db.forgetPage),
|
|
'clear-history' => _clearHistory(),
|
|
'add-tag' => _changeTag(args, add: true),
|
|
'remove-tag' => _changeTag(args, add: false),
|
|
'delete-tag' => _deleteTag(args['tag']),
|
|
_ => false,
|
|
};
|
|
}
|
|
|
|
Future<bool> _setSize(String? step) => switch (step) {
|
|
'up' => _settings.increaseSize(),
|
|
'down' => _settings.decreaseSize(),
|
|
_ => Future.value(false),
|
|
};
|
|
|
|
/// Runs [change] on the address the action names, if it names one.
|
|
Future<bool> _withUrl(
|
|
Map<String, String> args, Future<void> Function(String) change) async {
|
|
final url = args['url'];
|
|
if (url == null || url.isEmpty) return false;
|
|
await change(url);
|
|
return true;
|
|
}
|
|
|
|
/// Adds or removes one tag. An empty name is refused, so submitting an
|
|
/// empty box does nothing.
|
|
Future<bool> _changeTag(Map<String, String> args, {required bool add}) async {
|
|
final kind = switch (args['kind']) {
|
|
'bookmark' => TagKind.bookmark,
|
|
'subscription' => TagKind.subscription,
|
|
_ => null,
|
|
};
|
|
final url = args['url'];
|
|
final tag = args['tag']?.trim();
|
|
if (kind == null || url == null || url.isEmpty) return false;
|
|
if (tag == null || tag.isEmpty) return false;
|
|
if (add) {
|
|
await _db.addTag(kind, url, tag);
|
|
} else {
|
|
await _db.removeTag(kind, url, tag);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
Future<bool> _deleteTag(String? tag) async {
|
|
if (tag == null || tag.isEmpty) return false;
|
|
await _db.deleteTag(tag);
|
|
return true;
|
|
}
|
|
|
|
Future<bool> _clearHistory() async {
|
|
await _db.clearHistory();
|
|
return true;
|
|
}
|
|
|
|
Future<bool> _markRead(Map<String, String> args, {required bool read}) async {
|
|
final url = args['url'];
|
|
if (url == null || url.isEmpty) return false;
|
|
final site = args['site'];
|
|
if (read) {
|
|
await _subscriptions.markRead(url, siteUrl: site);
|
|
} else {
|
|
await _subscriptions.markUnread(url, siteUrl: site);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// The check redraws the page itself as it runs, so the caller need not.
|
|
Future<bool> _refreshAll() async {
|
|
await _subscriptions.refreshAll();
|
|
return false;
|
|
}
|
|
|
|
Future<bool> _refreshOne(String? siteUrl) async {
|
|
if (siteUrl == null || siteUrl.isEmpty) return false;
|
|
await _subscriptions.refreshOne(siteUrl);
|
|
return false;
|
|
}
|
|
}
|