log catalog to db; debug shortcut

This commit is contained in:
Thibault Deckers 2025-04-27 22:45:40 +02:00
parent bb6c2c341b
commit 5c1db57965
8 changed files with 91 additions and 3 deletions

View file

@ -302,6 +302,7 @@ open class MainActivity : FlutterFragmentActivity() {
INTENT_DATA_KEY_PAGE to intent.getStringExtra(EXTRA_KEY_PAGE),
INTENT_DATA_KEY_FILTERS to extractFiltersFromIntent(intent),
INTENT_DATA_KEY_EXPLORER_PATH to intent.getStringExtra(EXTRA_KEY_EXPLORER_PATH),
INTENT_DATA_KEY_DEBUG to intent.getBooleanExtra(EXTRA_KEY_DEBUG, false),
)
}
@ -533,7 +534,17 @@ open class MainActivity : FlutterFragmentActivity() {
)
.build()
val shortcutInfoList = listOf(videos, search, map)
val debug = ShortcutInfoCompat.Builder(this, "debug")
.setShortLabel("debug")
.setIntent(
Intent(Intent.ACTION_MAIN, null, this, MainActivity::class.java)
.putExtra(EXTRA_KEY_DEBUG, true)
)
.build()
// val shortcutInfoList = listOf(videos, search, map)
val shortcutInfoList = listOf(debug)
ShortcutManagerCompat.setDynamicShortcuts(this, shortcutInfoList)
Log.i(LOG_TAG, "set shortcuts: ${shortcutInfoList.joinToString(", ") { v -> v.id }}")
}
@ -579,12 +590,14 @@ open class MainActivity : FlutterFragmentActivity() {
const val INTENT_DATA_KEY_SECURE_URIS = "secureUris"
const val INTENT_DATA_KEY_URI = "uri"
const val INTENT_DATA_KEY_WIDGET_ID = "widgetId"
const val INTENT_DATA_KEY_DEBUG = "debug"
const val EXTRA_KEY_PAGE = "page"
const val EXTRA_KEY_EXPLORER_PATH = "explorerPath"
const val EXTRA_KEY_FILTERS_ARRAY = "filters"
const val EXTRA_KEY_FILTERS_STRING = "filtersString"
const val EXTRA_KEY_WIDGET_ID = "widgetId"
const val EXTRA_KEY_DEBUG = "debug"
// dart page routes
const val COLLECTION_PAGE_ROUTE_NAME = "/collection"

View file

@ -24,4 +24,7 @@ class IntentDataKeys {
static const secureUris = 'secureUris';
static const uri = 'uri';
static const widgetId = 'widgetId';
// #977
static const debug = 'debug';
}

View file

@ -22,6 +22,12 @@ abstract class LocalMediaDb {
Future<void> removeIds(Set<int> ids, {Set<EntryDataType>? dataTypes});
// debug
Future<void> logCatalog(String message);
Future<List<String>> getCatalogLog();
// entries
Future<void> clearEntries();

View file

@ -34,6 +34,7 @@ class SqfliteLocalMediaDb implements LocalMediaDb {
static const vaultTable = SqfliteLocalMediaDbSchema.vaultTable;
static const trashTable = SqfliteLocalMediaDbSchema.trashTable;
static const videoPlaybackTable = SqfliteLocalMediaDbSchema.videoPlaybackTable;
static const debugTable = SqfliteLocalMediaDbSchema.debugTable;
static const _entryInsertSliceMaxCount = 10000; // number of entries
static const _queryCursorBufferSize = 1000; // number of rows
@ -48,7 +49,7 @@ class SqfliteLocalMediaDb implements LocalMediaDb {
await path,
onCreate: (db, version) => SqfliteLocalMediaDbSchema.createLatestVersion(db),
onUpgrade: LocalMediaDbUpgrader.upgradeDb,
version: 15,
version: 16,
);
final maxIdRows = await _db.rawQuery('SELECT MAX(id) AS maxId FROM $entryTable');
@ -101,6 +102,19 @@ class SqfliteLocalMediaDb implements LocalMediaDb {
await batch.commit(noResult: true);
}
// debug
@override
Future<void> logCatalog(String message) async {
await _db.insert(debugTable, {'message': message});
}
@override
Future<List<String>> getCatalogLog() async {
final rows = await _db.query(debugTable);
return rows.map((row) => row['message'] as String).toList();
}
// entries
@override

View file

@ -11,6 +11,7 @@ class SqfliteLocalMediaDbSchema {
static const vaultTable = 'vaults';
static const trashTable = 'trash';
static const videoPlaybackTable = 'videoPlayback';
static const debugTable = 'debug';
static const allTables = [
entryTable,
@ -23,6 +24,7 @@ class SqfliteLocalMediaDbSchema {
vaultTable,
trashTable,
videoPlaybackTable,
debugTable,
];
static Future<void> createLatestVersion(Database db) async {
@ -111,6 +113,11 @@ class SqfliteLocalMediaDbSchema {
'id INTEGER PRIMARY KEY'
', resumeTimeMillis INTEGER'
')');
case debugTable:
return db.execute('CREATE TABLE $debugTable('
'id INTEGER PRIMARY KEY AUTOINCREMENT'
', message TEXT'
')');
default:
throw Exception('unknown table=$table');
}

View file

@ -18,6 +18,7 @@ class LocalMediaDbUpgrader {
static const vaultTable = SqfliteLocalMediaDbSchema.vaultTable;
static const trashTable = SqfliteLocalMediaDbSchema.trashTable;
static const videoPlaybackTable = SqfliteLocalMediaDbSchema.videoPlaybackTable;
static const debugTable = SqfliteLocalMediaDbSchema.debugTable;
// warning: "ALTER TABLE ... RENAME COLUMN ..." is not supported
// on SQLite <3.25.0, bundled on older Android devices
@ -53,6 +54,8 @@ class LocalMediaDbUpgrader {
await _upgradeFrom13(db);
case 14:
await _upgradeFrom14(db);
case 15:
await _upgradeFrom15(db);
}
oldVersion++;
}
@ -500,4 +503,13 @@ class LocalMediaDbUpgrader {
// (dateTakenTable, metadataTable, addressTable, trashTable, videoPlaybackTable)
// for users with a potentially corrupted DB following upgrade to v1.12.4
}
static Future<void> _upgradeFrom15(Database db) async {
debugPrint('upgrading DB from v15');
await db.execute('CREATE TABLE $debugTable('
'id INTEGER PRIMARY KEY AUTOINCREMENT'
', message TEXT'
')');
}
}

View file

@ -68,6 +68,9 @@ class PlatformMetadataFetchService implements MetadataFetchService {
Future<CatalogMetadata?> getCatalogMetadata(AvesEntry entry, {bool background = false}) async {
if (entry.isSvg) return null;
// #977
await localMediaDb.logCatalog('${DateTime.now().toIso8601String()} ${entry.path ?? entry.uri}');
Future<CatalogMetadata?> call() async {
try {
// returns map with:

View file

@ -1,4 +1,6 @@
import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'package:aves/app_mode.dart';
import 'package:aves/geo/uri.dart';
@ -14,6 +16,8 @@ import 'package:aves/model/settings/enums/home_page.dart';
import 'package:aves/model/settings/settings.dart';
import 'package:aves/model/source/collection_lens.dart';
import 'package:aves/model/source/collection_source.dart';
import 'package:aves/ref/locales.dart';
import 'package:aves/ref/mime_types.dart';
import 'package:aves/services/analysis_service.dart';
import 'package:aves/services/common/services.dart';
import 'package:aves/services/global_search.dart';
@ -22,6 +26,7 @@ import 'package:aves/services/widget_service.dart';
import 'package:aves/theme/themes.dart';
import 'package:aves/utils/android_file_utils.dart';
import 'package:aves/widgets/collection/collection_page.dart';
import 'package:aves/widgets/common/action_mixins/feedback.dart';
import 'package:aves/widgets/common/basic/scaffold.dart';
import 'package:aves/widgets/common/behaviour/routes.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
@ -42,6 +47,7 @@ import 'package:aves/widgets/wallpaper_page.dart';
import 'package:aves_model/aves_model.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:latlong2/latlong.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
@ -61,7 +67,7 @@ class HomePage extends StatefulWidget {
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
class _HomePageState extends State<HomePage> with FeedbackMixin {
AvesEntry? _viewerEntry;
int? _widgetId;
String? _initialRouteName, _initialSearchQuery;
@ -108,11 +114,35 @@ class _HomePageState extends State<HomePage> {
var appMode = AppMode.main;
var error = false;
final intentData = widget.intentData ?? await IntentService.getIntentData();
final debug = intentData[IntentDataKeys.debug] ?? false;
final intentAction = intentData[IntentDataKeys.action] as String?;
_initialFilters = null;
_initialExplorerPath = null;
_secureUris = null;
if (debug) {
await localMediaDb.init();
final logs = await localMediaDb.getCatalogLog();
final success = await storageService.createFile(
'aves_issue977_logs-${DateFormat('yyyyMMdd_HHmmss', asciiLocale).format(DateTime.now())}.txt',
MimeTypes.plainText,
Uint8List.fromList(utf8.encode(logs.join('\n'))),
);
if (success != null) {
if (success) {
showFeedback(context, FeedbackType.info, context.l10n.genericSuccessFeedback);
} else {
showFeedback(context, FeedbackType.warn, context.l10n.genericFailureFeedback);
}
}
unawaited(Navigator.maybeOf(context)?.pushAndRemoveUntil(
await _getRedirectRoute(appMode),
(route) => false,
));
return;
}
await availability.onNewIntent();
await androidFileUtils.init();
if (!{