feat: add HTML providers for Realbooru and Paheal, hidden posts screen, and UI/search enhancements

This commit is contained in:
2026-09-03 16:40:37 +03:00
parent 7cccb2cd8d
commit 45faa12133
55 changed files with 4263 additions and 2076 deletions
+56 -1
View File
@@ -221,6 +221,19 @@ class _DownloadPanel extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final scheme = Theme.of(context).colorScheme;
final strings = ref.watch(appStringsProvider);
final manager = ref.read(downloadManagerServiceProvider);
final paused = manager.queuePaused;
final activeTasks = tasks
.where((task) =>
task.status == DownloadTaskStatus.queued ||
task.status == DownloadTaskStatus.running)
.toList();
final finishedTasks = tasks
.where((task) =>
task.status == DownloadTaskStatus.completed ||
task.status == DownloadTaskStatus.failed ||
task.status == DownloadTaskStatus.canceled)
.toList();
return Material(
elevation: 12,
borderRadius: BorderRadius.circular(16),
@@ -232,6 +245,39 @@ class _DownloadPanel extends ConsumerWidget {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
children: [
Text(
strings.download,
style: Theme.of(context).textTheme.titleSmall,
),
const Spacer(),
IconButton(
tooltip: paused ? 'Resume queue' : 'Pause queue',
onPressed:
paused ? manager.resumeQueue : manager.pauseQueue,
icon: Icon(paused
? Icons.play_arrow_rounded
: Icons.pause_rounded),
),
if (activeTasks.isNotEmpty)
IconButton(
tooltip: 'Cancel active',
onPressed: () {
for (final task in activeTasks) {
manager.cancel(task.id);
}
},
icon: const Icon(Icons.cancel_rounded),
),
if (finishedTasks.isNotEmpty)
IconButton(
tooltip: 'Clear finished',
onPressed: manager.clearFinished,
icon: const Icon(Icons.clear_all_rounded),
),
],
),
for (final task in tasks) ...[
Row(
children: [
@@ -252,6 +298,15 @@ class _DownloadPanel extends ConsumerWidget {
.retry(task.id),
icon: const Icon(Icons.refresh_rounded),
),
if (task.status == DownloadTaskStatus.queued ||
task.status == DownloadTaskStatus.running)
IconButton(
tooltip: 'Cancel',
onPressed: () => ref
.read(downloadManagerServiceProvider)
.cancel(task.id),
icon: const Icon(Icons.close_rounded),
),
],
),
const SizedBox(height: 6),
@@ -344,7 +399,7 @@ class _StartupErrorScreen extends ConsumerWidget {
const SizedBox(height: 16),
Text(
strings.ru
? 'Не удалось открыть локальную базу'
? '\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u0443\u044e \u0431\u0430\u0437\u0443'
: 'Could not start local database',
style: Theme.of(context).textTheme.titleLarge,
textAlign: TextAlign.center,
+3 -3
View File
@@ -75,8 +75,8 @@ class AppStrings {
String get hideViewed => ru ? 'Скрывать просмотренное' : 'Hide viewed posts';
String get smartBlacklist => ru ? 'Умный blacklist' : 'Smart blacklist';
String get whitelistedTags => ru ? 'Whitelist тегов' : 'Whitelisted tags';
String get cacheMaxItems => ru ? 'Лимит кэша' : 'Cache max items';
String get clearCache => ru ? 'Очистить кэш' : 'Clear cache';
String get cacheMaxItems => ru ? 'Лимит кеша' : 'Cache max items';
String get clearCache => ru ? 'Очистить кеш' : 'Clear cache';
String get clearViewed => ru ? 'Очистить историю' : 'Clear viewed history';
String get exportJson => ru ? 'Экспорт JSON' : 'Export JSON';
String get importJson => ru ? 'Импорт JSON' : 'Import JSON';
@@ -98,5 +98,5 @@ class AppStrings {
String get disableRepeat => ru ? 'Отключить повтор' : 'Disable repeat';
String get fullscreen => ru ? 'На весь экран' : 'Fullscreen';
String get exitFullscreen =>
ru ? 'Выйти из полного экрана' : 'Exit fullscreen';
ru ? 'Выйти из полноэкранного режима' : 'Exit fullscreen';
}
+7 -9
View File
@@ -43,29 +43,27 @@ const lunarisChangelog = [
),
LunarisChange(
version: '1.1.0',
title: 'Lunaris rebrand and CosBooru',
title: 'Lunaris rebrand and providers',
bullets: [
'RuleGel is now Lunaris while keeping the same package identity for updates.',
'CosBooru now uses the working Danbooru-compatible API at cos.lycore.co.',
'Xbooru was added as a default Gelbooru-compatible provider.',
'Rule34 Paheal was removed from providers.',
'Rule34 Paheal is available as an HTML provider.',
'Video player UI preferences are saved across fullscreen, details and restarts.',
],
),
LunarisChange(
version: '1.0.2',
title: 'Realbooru safety fix',
title: 'Provider safety fix',
bullets: [
'Realbooru stays available in Providers, but is disabled by default while its public DAPI is offline.',
'Provider diagnostics now surface the Realbooru API reason instead of a generic exception.',
'Existing enabled Realbooru configs are disabled on startup so the main feed is not polluted by a known-offline API.',
'Known-offline legacy providers are disabled on startup.',
'Provider diagnostics now surface API reasons instead of generic exceptions.',
'Existing enabled legacy configs are disabled so the main feed is not polluted by known-offline APIs.',
],
),
LunarisChange(
version: '1.0.1',
title: 'Realbooru and mobile polish',
title: 'Mobile polish',
bullets: [
'Added Realbooru as a default enabled provider.',
'Startup update checks now look for new Gitea releases every launch.',
'Refresh-rate controls are Android-only; desktop keeps stable app motion.',
'Tag chip input no longer jumps while typing.',
+5
View File
@@ -15,6 +15,7 @@ import '../features/providers/presentation/provider_check_screen.dart';
import '../features/providers/presentation/provider_form_screen.dart';
import '../features/providers/presentation/providers_screen.dart';
import '../features/search/presentation/search_screen.dart';
import '../features/settings/presentation/hidden_posts_screen.dart';
import '../features/settings/presentation/settings_screen.dart';
import '../features/viewed/presentation/viewed_screen.dart';
import '../shared/widgets/app_shell.dart';
@@ -105,6 +106,10 @@ final appRouterProvider = Provider<GoRouter>((ref) {
path: '/settings',
builder: (context, state) => const SettingsScreen(),
),
GoRoute(
path: '/settings/hidden',
builder: (context, state) => const HiddenPostsScreen(),
),
],
),
],