Prepare RuleGel 1.0

This commit is contained in:
2026-05-24 22:06:15 +03:00
parent 1adfc1fa0c
commit 16e86fb9d5
18 changed files with 413 additions and 6 deletions
@@ -1,7 +1,9 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../app/app.dart';
import '../../../app/app_version.dart';
import '../../../backend/backend.dart';
import '../../../core/utils/logger.dart';
import '../../../core/utils/result.dart';
final settingsControllerProvider =
@@ -30,6 +32,34 @@ class SettingsController extends AsyncNotifier<AppSettings> {
ref.invalidate(viewedKeysProvider);
}
Future<void> clearHiddenPosts() async {
await ref.read(settingsServiceProvider).clearHiddenPosts();
ref.invalidate(appSettingsProvider);
ref.invalidateSelf();
}
Future<String> diagnosticsReport() async {
final result =
await ref.read(settingsServiceProvider).buildDiagnosticsReport(
appVersion: appDisplayVersion,
buildNumber: appBuildNumber,
);
return result is Success<String> ? result.data : '{}';
}
Future<String> diagnosticLogs() async {
final settings = state.value ?? AppSettings.defaults;
final persistent = settings.diagnosticLogLines;
final runtime = AppLogger.lines;
return [...persistent, ...runtime].join('\n');
}
Future<void> clearDiagnosticLogs() async {
AppLogger.clear();
await ref.read(settingsServiceProvider).clearDiagnosticLogs();
ref.invalidateSelf();
}
Future<String> exportJson() async {
final result =
await ref.read(settingsServiceProvider).exportSettingsToJson();
@@ -5,6 +5,7 @@ import 'package:go_router/go_router.dart';
import 'package:url_launcher/url_launcher.dart';
import '../../../app/app_version.dart';
import '../../../app/changelog.dart';
import '../../../backend/backend.dart';
import '../../../core/utils/result.dart';
import '../../../shared/widgets/adaptive_scaffold.dart';
@@ -151,6 +152,15 @@ class SettingsScreen extends ConsumerWidget {
label: const Text('Clear cache'),
),
const SizedBox(height: 12),
FilledButton.tonalIcon(
onPressed: () => ref
.read(settingsControllerProvider.notifier)
.clearHiddenPosts(),
icon: const Icon(Icons.visibility_off_rounded),
label: Text(
'Clear hidden posts (${settings.hiddenPostKeys.length})'),
),
const SizedBox(height: 12),
FilledButton.tonalIcon(
onPressed: () => ref
.read(settingsControllerProvider.notifier)
@@ -186,8 +196,54 @@ class SettingsScreen extends ConsumerWidget {
icon: const Icon(Icons.system_update_alt_rounded),
label: const Text('Check for updates'),
),
const SizedBox(height: 12),
FilledButton.tonalIcon(
onPressed: () async {
final report = await ref
.read(settingsControllerProvider.notifier)
.diagnosticsReport();
await Clipboard.setData(ClipboardData(text: report));
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Diagnostics copied')),
);
}
},
icon: const Icon(Icons.bug_report_rounded),
label: const Text('Copy diagnostics report'),
),
const SizedBox(height: 12),
FilledButton.tonalIcon(
onPressed: () async {
final logs = await ref
.read(settingsControllerProvider.notifier)
.diagnosticLogs();
await Clipboard.setData(ClipboardData(text: logs));
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Diagnostic logs copied')),
);
}
},
icon: const Icon(Icons.receipt_long_rounded),
label: const Text('Copy local logs'),
),
const SizedBox(height: 12),
FilledButton.tonalIcon(
onPressed: () => ref
.read(settingsControllerProvider.notifier)
.clearDiagnosticLogs(),
icon: const Icon(Icons.delete_sweep_rounded),
label: const Text('Clear local logs'),
),
const SizedBox(height: 12),
FilledButton.tonalIcon(
onPressed: () => _showChangelog(context),
icon: const Icon(Icons.new_releases_rounded),
label: const Text('What changed'),
),
const SizedBox(height: 24),
const Text('Version $appDisplayVersion'),
const Text('Version $appDisplayVersion ($appBuildNumber)'),
],
),
),
@@ -305,6 +361,45 @@ class SettingsScreen extends ConsumerWidget {
);
ref.invalidate(settingsControllerProvider);
}
Future<void> _showChangelog(BuildContext context) {
return showDialog<void>(
context: context,
builder: (context) => AlertDialog(
title: const Text('RuleGel changelog'),
content: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 560),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
for (final change in ruleGelChangelog) ...[
Text(
'${change.version} - ${change.title}',
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 6),
for (final bullet in change.bullets)
Padding(
padding: const EdgeInsets.only(left: 8, bottom: 4),
child: Text('- $bullet'),
),
const SizedBox(height: 12),
],
],
),
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('Close'),
),
],
),
);
}
}
class _TagListEditor extends StatefulWidget {