352 lines
12 KiB
Dart
352 lines
12 KiB
Dart
import 'dart:collection';
|
|
|
|
import 'package:aves/model/favourite_repo.dart';
|
|
import 'package:aves/model/image_entry.dart';
|
|
import 'package:aves/model/image_metadata.dart';
|
|
import 'package:aves/model/metadata_db.dart';
|
|
import 'package:aves/model/settings/settings.dart';
|
|
import 'package:aves/model/source/collection_source.dart';
|
|
import 'package:aves/services/android_app_service.dart';
|
|
import 'package:aves/services/image_file_service.dart';
|
|
import 'package:aves/utils/android_file_utils.dart';
|
|
import 'package:aves/utils/file_utils.dart';
|
|
import 'package:aves/widgets/common/data_providers/media_query_data_provider.dart';
|
|
import 'package:aves/widgets/common/icons.dart';
|
|
import 'package:aves/widgets/fullscreen/info/info_page.dart';
|
|
import 'package:firebase_core/firebase_core.dart';
|
|
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/scheduler.dart';
|
|
import 'package:flutter_svg/flutter_svg.dart';
|
|
|
|
class DebugPage extends StatefulWidget {
|
|
static const routeName = '/debug';
|
|
|
|
final CollectionSource source;
|
|
|
|
const DebugPage({this.source});
|
|
|
|
@override
|
|
State<StatefulWidget> createState() => DebugPageState();
|
|
}
|
|
|
|
class DebugPageState extends State<DebugPage> {
|
|
Future<int> _dbFileSizeLoader;
|
|
Future<List<ImageEntry>> _dbEntryLoader;
|
|
Future<List<DateMetadata>> _dbDateLoader;
|
|
Future<List<CatalogMetadata>> _dbMetadataLoader;
|
|
Future<List<AddressDetails>> _dbAddressLoader;
|
|
Future<List<FavouriteRow>> _dbFavouritesLoader;
|
|
Future<Map> _envLoader;
|
|
|
|
List<ImageEntry> get entries => widget.source.rawEntries;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_startDbReport();
|
|
_envLoader = AndroidAppService.getEnv();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return MediaQueryDataProvider(
|
|
child: DefaultTabController(
|
|
length: 4,
|
|
child: Scaffold(
|
|
appBar: AppBar(
|
|
title: Text('Debug'),
|
|
bottom: TabBar(
|
|
tabs: [
|
|
Tab(icon: Icon(AIcons.debug)),
|
|
Tab(icon: Icon(AIcons.settings)),
|
|
Tab(icon: Icon(AIcons.removableStorage)),
|
|
Tab(icon: Icon(AIcons.android)),
|
|
],
|
|
),
|
|
),
|
|
body: SafeArea(
|
|
child: TabBarView(
|
|
children: [
|
|
_buildGeneralTabView(),
|
|
_buildSettingsTabView(),
|
|
_buildStorageTabView(),
|
|
_buildEnvTabView(),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildGeneralTabView() {
|
|
final catalogued = entries.where((entry) => entry.isCatalogued);
|
|
final withGps = catalogued.where((entry) => entry.hasGps);
|
|
final located = withGps.where((entry) => entry.isLocated);
|
|
return ListView(
|
|
padding: EdgeInsets.all(16),
|
|
children: [
|
|
Text('Time dilation'),
|
|
Slider(
|
|
value: timeDilation,
|
|
onChanged: (v) => setState(() => timeDilation = v),
|
|
min: 1.0,
|
|
max: 10.0,
|
|
divisions: 9,
|
|
label: '$timeDilation',
|
|
),
|
|
Divider(),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text('Crashlytics'),
|
|
),
|
|
SizedBox(width: 8),
|
|
RaisedButton(
|
|
onPressed: FirebaseCrashlytics.instance.crash,
|
|
child: Text('Crash'),
|
|
),
|
|
],
|
|
),
|
|
Text('Firebase data collection: ${Firebase.app().isAutomaticDataCollectionEnabled ? 'enabled' : 'disabled'}'),
|
|
Text('Crashlytics collection: ${FirebaseCrashlytics.instance.isCrashlyticsCollectionEnabled ? 'enabled' : 'disabled'}'),
|
|
Divider(),
|
|
Text('Entries: ${entries.length}'),
|
|
Text('Catalogued: ${catalogued.length}'),
|
|
Text('With GPS: ${withGps.length}'),
|
|
Text('With address: ${located.length}'),
|
|
Divider(),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text('Image cache:\n\t${imageCache.currentSize}/${imageCache.maximumSize} items\n\t${formatFilesize(imageCache.currentSizeBytes)}/${formatFilesize(imageCache.maximumSizeBytes)}'),
|
|
),
|
|
SizedBox(width: 8),
|
|
RaisedButton(
|
|
onPressed: () {
|
|
imageCache.clear();
|
|
setState(() {});
|
|
},
|
|
child: Text('Clear'),
|
|
),
|
|
],
|
|
),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text('SVG cache: ${PictureProvider.cacheCount} items'),
|
|
),
|
|
SizedBox(width: 8),
|
|
RaisedButton(
|
|
onPressed: () {
|
|
PictureProvider.clearCache();
|
|
setState(() {});
|
|
},
|
|
child: Text('Clear'),
|
|
),
|
|
],
|
|
),
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text('Glide disk cache: ?'),
|
|
),
|
|
SizedBox(width: 8),
|
|
RaisedButton(
|
|
onPressed: ImageFileService.clearSizedThumbnailDiskCache,
|
|
child: Text('Clear'),
|
|
),
|
|
],
|
|
),
|
|
Divider(),
|
|
FutureBuilder<int>(
|
|
future: _dbFileSizeLoader,
|
|
builder: (context, snapshot) {
|
|
if (snapshot.hasError) return Text(snapshot.error.toString());
|
|
if (snapshot.connectionState != ConnectionState.done) return SizedBox.shrink();
|
|
return Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text('DB file size: ${formatFilesize(snapshot.data)}'),
|
|
),
|
|
SizedBox(width: 8),
|
|
RaisedButton(
|
|
onPressed: () => metadataDb.reset().then((_) => _startDbReport()),
|
|
child: Text('Reset'),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
FutureBuilder<List>(
|
|
future: _dbEntryLoader,
|
|
builder: (context, snapshot) {
|
|
if (snapshot.hasError) return Text(snapshot.error.toString());
|
|
if (snapshot.connectionState != ConnectionState.done) return SizedBox.shrink();
|
|
return Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text('DB entry rows: ${snapshot.data.length}'),
|
|
),
|
|
SizedBox(width: 8),
|
|
RaisedButton(
|
|
onPressed: () => metadataDb.clearEntries().then((_) => _startDbReport()),
|
|
child: Text('Clear'),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
FutureBuilder<List>(
|
|
future: _dbDateLoader,
|
|
builder: (context, snapshot) {
|
|
if (snapshot.hasError) return Text(snapshot.error.toString());
|
|
if (snapshot.connectionState != ConnectionState.done) return SizedBox.shrink();
|
|
return Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text('DB date rows: ${snapshot.data.length}'),
|
|
),
|
|
SizedBox(width: 8),
|
|
RaisedButton(
|
|
onPressed: () => metadataDb.clearDates().then((_) => _startDbReport()),
|
|
child: Text('Clear'),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
FutureBuilder<List>(
|
|
future: _dbMetadataLoader,
|
|
builder: (context, snapshot) {
|
|
if (snapshot.hasError) return Text(snapshot.error.toString());
|
|
if (snapshot.connectionState != ConnectionState.done) return SizedBox.shrink();
|
|
return Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text('DB metadata rows: ${snapshot.data.length}'),
|
|
),
|
|
SizedBox(width: 8),
|
|
RaisedButton(
|
|
onPressed: () => metadataDb.clearMetadataEntries().then((_) => _startDbReport()),
|
|
child: Text('Clear'),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
FutureBuilder<List>(
|
|
future: _dbAddressLoader,
|
|
builder: (context, snapshot) {
|
|
if (snapshot.hasError) return Text(snapshot.error.toString());
|
|
if (snapshot.connectionState != ConnectionState.done) return SizedBox.shrink();
|
|
return Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text('DB address rows: ${snapshot.data.length}'),
|
|
),
|
|
SizedBox(width: 8),
|
|
RaisedButton(
|
|
onPressed: () => metadataDb.clearAddresses().then((_) => _startDbReport()),
|
|
child: Text('Clear'),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
FutureBuilder<List>(
|
|
future: _dbFavouritesLoader,
|
|
builder: (context, snapshot) {
|
|
if (snapshot.hasError) return Text(snapshot.error.toString());
|
|
if (snapshot.connectionState != ConnectionState.done) return SizedBox.shrink();
|
|
return Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text('DB favourite rows: ${snapshot.data.length} (${favourites.count} in memory)'),
|
|
),
|
|
SizedBox(width: 8),
|
|
RaisedButton(
|
|
onPressed: () => favourites.clear().then((_) => _startDbReport()),
|
|
child: Text('Clear'),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildSettingsTabView() {
|
|
return ListView(
|
|
padding: EdgeInsets.all(16),
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text('Settings'),
|
|
),
|
|
SizedBox(width: 8),
|
|
RaisedButton(
|
|
onPressed: () => settings.reset().then((_) => setState(() {})),
|
|
child: Text('Reset'),
|
|
),
|
|
],
|
|
),
|
|
InfoRowGroup({
|
|
'collectionGroupFactor': '${settings.collectionGroupFactor}',
|
|
'collectionSortFactor': '${settings.collectionSortFactor}',
|
|
'collectionTileExtent': '${settings.collectionTileExtent}',
|
|
'infoMapZoom': '${settings.infoMapZoom}',
|
|
}),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildStorageTabView() {
|
|
return ListView(
|
|
padding: EdgeInsets.all(16),
|
|
children: [
|
|
...androidFileUtils.storageVolumes.expand((v) => [
|
|
Text(v.path),
|
|
InfoRowGroup({
|
|
'description': '${v.description}',
|
|
'isEmulated': '${v.isEmulated}',
|
|
'isPrimary': '${v.isPrimary}',
|
|
'isRemovable': '${v.isRemovable}',
|
|
'state': '${v.state}',
|
|
}),
|
|
Divider(),
|
|
])
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _buildEnvTabView() {
|
|
return ListView(
|
|
padding: EdgeInsets.all(16),
|
|
children: [
|
|
FutureBuilder<Map>(
|
|
future: _envLoader,
|
|
builder: (context, snapshot) {
|
|
if (snapshot.hasError) return Text(snapshot.error.toString());
|
|
if (snapshot.connectionState != ConnectionState.done) return SizedBox.shrink();
|
|
final data = SplayTreeMap.of(snapshot.data.map((k, v) => MapEntry(k.toString(), v?.toString() ?? 'null')));
|
|
return InfoRowGroup(data);
|
|
},
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
void _startDbReport() {
|
|
_dbFileSizeLoader = metadataDb.dbFileSize();
|
|
_dbEntryLoader = metadataDb.loadEntries();
|
|
_dbDateLoader = metadataDb.loadDates();
|
|
_dbMetadataLoader = metadataDb.loadMetadataEntries();
|
|
_dbAddressLoader = metadataDb.loadAddresses();
|
|
_dbFavouritesLoader = metadataDb.loadFavourites();
|
|
setState(() {});
|
|
}
|
|
}
|