packages upgrade, static analysis migration
This commit is contained in:
parent
cdb676144c
commit
1841c60c09
162 changed files with 706 additions and 441 deletions
|
@ -1,4 +1,4 @@
|
|||
include: package:pedantic/analysis_options.yaml
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
analyzer:
|
||||
exclude:
|
||||
|
@ -12,23 +12,21 @@ analyzer:
|
|||
linter:
|
||||
rules:
|
||||
# from 'effective dart', excluded
|
||||
avoid_classes_with_only_static_members: false # too strict
|
||||
avoid_function_literals_in_foreach_calls: false # benefit?
|
||||
lines_longer_than_80_chars: false # nope
|
||||
avoid_classes_with_only_static_members: false # too strict
|
||||
public_member_api_docs: false # this project is not a library
|
||||
|
||||
# from 'effective dart', undecided
|
||||
prefer_relative_imports: false # check IDE support (auto import, file move)
|
||||
public_member_api_docs: false # maybe?
|
||||
|
||||
# from 'effective dart', included
|
||||
avoid_types_on_closure_parameters: true
|
||||
constant_identifier_names: true
|
||||
prefer_function_declarations_over_variables: true
|
||||
prefer_interpolation_to_compose_strings: true
|
||||
unnecessary_brace_in_string_interps: true
|
||||
unnecessary_lambdas: true
|
||||
|
||||
# misc
|
||||
prefer_const_constructors: true # should specify `const` as Dart does not build constants when using const constructors without it
|
||||
prefer_const_constructors_in_immutables: true
|
||||
prefer_const_declarations: true
|
||||
# from 'pedantic', included
|
||||
always_declare_return_types: true
|
||||
prefer_single_quotes: true
|
||||
sort_child_properties_last: true
|
||||
unawaited_futures: true
|
||||
|
|
|
@ -64,6 +64,7 @@ class EmbeddedDataHandler(private val context: Context) : MethodCallHandler {
|
|||
if (isSupportedByExifInterface(mimeType)) {
|
||||
try {
|
||||
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
|
||||
@Suppress("BlockingMethodInNonBlockingContext")
|
||||
val exif = ExifInterface(input)
|
||||
val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
|
||||
exif.thumbnailBitmap?.let { bitmap ->
|
||||
|
|
|
@ -67,6 +67,7 @@ class RegionFetcher internal constructor(
|
|||
try {
|
||||
if (currentDecoderRef == null) {
|
||||
val newDecoder = StorageUtils.openInputStream(context, uri)?.use { input ->
|
||||
@Suppress("BlockingMethodInNonBlockingContext")
|
||||
BitmapRegionDecoder.newInstance(input, false)
|
||||
}
|
||||
if (newDecoder == null) {
|
||||
|
|
|
@ -19,6 +19,7 @@ class TiffRegionFetcher internal constructor(
|
|||
result: MethodChannel.Result,
|
||||
) {
|
||||
try {
|
||||
@Suppress("BlockingMethodInNonBlockingContext")
|
||||
val fd = context.contentResolver.openFileDescriptor(uri, "r")?.detachFd()
|
||||
if (fd == null) {
|
||||
result.error("getRegion-tiff-fd", "failed to get file descriptor for uri=$uri", null)
|
||||
|
|
|
@ -129,6 +129,7 @@ class ImageByteStreamHandler(private val activity: Activity, private val argumen
|
|||
.load(model)
|
||||
.submit()
|
||||
try {
|
||||
@Suppress("BlockingMethodInNonBlockingContext")
|
||||
var bitmap = target.get()
|
||||
if (needRotationAfterGlide(mimeType)) {
|
||||
bitmap = applyExifOrientation(activity, bitmap, rotationDegrees, isFlipped)
|
||||
|
@ -152,6 +153,7 @@ class ImageByteStreamHandler(private val activity: Activity, private val argumen
|
|||
.load(VideoThumbnail(activity, uri))
|
||||
.submit()
|
||||
try {
|
||||
@Suppress("BlockingMethodInNonBlockingContext")
|
||||
val bitmap = target.get()
|
||||
if (bitmap != null) {
|
||||
success(bitmap.getBytes(canHaveAlpha = false, recycle = false))
|
||||
|
|
|
@ -3,15 +3,15 @@ package deckers.thibault.aves.metadata
|
|||
object TiffTags {
|
||||
// XPosition
|
||||
// Tag = 286 (011E.H)
|
||||
const val TAG_X_POSITION = 0x011e
|
||||
private const val TAG_X_POSITION = 0x011e
|
||||
|
||||
// YPosition
|
||||
// Tag = 287 (011F.H)
|
||||
const val TAG_Y_POSITION = 0x011f
|
||||
private const val TAG_Y_POSITION = 0x011f
|
||||
|
||||
// ColorMap
|
||||
// Tag = 320 (0140.H)
|
||||
const val TAG_COLOR_MAP = 0x0140
|
||||
private const val TAG_COLOR_MAP = 0x0140
|
||||
|
||||
// ExtraSamples
|
||||
// Tag = 338 (0152.H)
|
||||
|
@ -19,7 +19,7 @@ object TiffTags {
|
|||
// EXTRASAMPLE_UNSPECIFIED 0 // unspecified data
|
||||
// EXTRASAMPLE_ASSOCALPHA 1 // associated alpha data
|
||||
// EXTRASAMPLE_UNASSALPHA 2 // unassociated alpha data
|
||||
const val TAG_EXTRA_SAMPLES = 0x0152
|
||||
private const val TAG_EXTRA_SAMPLES = 0x0152
|
||||
|
||||
// SampleFormat
|
||||
// Tag = 339 (0153.H)
|
||||
|
@ -30,7 +30,7 @@ object TiffTags {
|
|||
// SAMPLEFORMAT_VOID 4 // untyped data
|
||||
// SAMPLEFORMAT_COMPLEXINT 5 // complex signed int
|
||||
// SAMPLEFORMAT_COMPLEXIEEEFP 6 // complex ieee floating
|
||||
const val TAG_SAMPLE_FORMAT = 0x0153
|
||||
private const val TAG_SAMPLE_FORMAT = 0x0153
|
||||
|
||||
/*
|
||||
SGI
|
||||
|
@ -40,7 +40,7 @@ object TiffTags {
|
|||
// Matteing
|
||||
// Tag = 32995 (80E3.H)
|
||||
// obsoleted by the 6.0 ExtraSamples (338)
|
||||
const val TAG_MATTEING = 0x80e3
|
||||
private const val TAG_MATTEING = 0x80e3
|
||||
|
||||
/*
|
||||
GeoTIFF
|
||||
|
@ -74,13 +74,13 @@ object TiffTags {
|
|||
// Tag = 34736 (87BO.H)
|
||||
// Type = DOUBLE
|
||||
// Count = variable
|
||||
const val TAG_GEO_DOUBLE_PARAMS = 0x87b0
|
||||
private const val TAG_GEO_DOUBLE_PARAMS = 0x87b0
|
||||
|
||||
// GeoAsciiParamsTag (optional)
|
||||
// Tag = 34737 (87B1.H)
|
||||
// Type = ASCII
|
||||
// Count = variable
|
||||
const val TAG_GEO_ASCII_PARAMS = 0x87b1
|
||||
private const val TAG_GEO_ASCII_PARAMS = 0x87b1
|
||||
|
||||
/*
|
||||
Photoshop
|
||||
|
@ -91,7 +91,7 @@ object TiffTags {
|
|||
// ImageSourceData
|
||||
// Tag = 37724 (935C.H)
|
||||
// Type = UNDEFINED
|
||||
const val TAG_IMAGE_SOURCE_DATA = 0x935c
|
||||
private const val TAG_IMAGE_SOURCE_DATA = 0x935c
|
||||
|
||||
/*
|
||||
DNG
|
||||
|
@ -102,13 +102,13 @@ object TiffTags {
|
|||
// Tag = 50735 (C62F.H)
|
||||
// Type = ASCII
|
||||
// Count = variable
|
||||
const val TAG_CAMERA_SERIAL_NUMBER = 0xc62f
|
||||
private const val TAG_CAMERA_SERIAL_NUMBER = 0xc62f
|
||||
|
||||
// OriginalRawFileName (optional)
|
||||
// Tag = 50827 (C68B.H)
|
||||
// Type = ASCII or BYTE
|
||||
// Count = variable
|
||||
const val TAG_ORIGINAL_RAW_FILE_NAME = 0xc68b
|
||||
private const val TAG_ORIGINAL_RAW_FILE_NAME = 0xc68b
|
||||
|
||||
private val geotiffTags = listOf(
|
||||
TAG_GEO_ASCII_PARAMS,
|
||||
|
|
|
@ -6,13 +6,13 @@ import deckers.thibault.aves.model.SourceEntry
|
|||
import java.io.File
|
||||
|
||||
internal class FileImageProvider : ImageProvider() {
|
||||
override fun fetchSingle(context: Context, uri: Uri, mimeType: String?, callback: ImageOpCallback) {
|
||||
if (mimeType == null) {
|
||||
override fun fetchSingle(context: Context, uri: Uri, sourceMimeType: String?, callback: ImageOpCallback) {
|
||||
if (sourceMimeType == null) {
|
||||
callback.onFailure(Exception("MIME type is null for uri=$uri"))
|
||||
return
|
||||
}
|
||||
|
||||
val entry = SourceEntry(uri, mimeType)
|
||||
val entry = SourceEntry(uri, sourceMimeType)
|
||||
|
||||
val path = uri.path
|
||||
if (path != null) {
|
||||
|
|
|
@ -39,7 +39,7 @@ import kotlin.coroutines.resumeWithException
|
|||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
abstract class ImageProvider {
|
||||
open fun fetchSingle(context: Context, uri: Uri, mimeType: String?, callback: ImageOpCallback) {
|
||||
open fun fetchSingle(context: Context, uri: Uri, sourceMimeType: String?, callback: ImageOpCallback) {
|
||||
callback.onFailure(UnsupportedOperationException())
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ class MediaStoreImageProvider : ImageProvider() {
|
|||
fetchFrom(context, isModified, handleNewEntry, VIDEO_CONTENT_URI, VIDEO_PROJECTION)
|
||||
}
|
||||
|
||||
override fun fetchSingle(context: Context, uri: Uri, mimeType: String?, callback: ImageOpCallback) {
|
||||
override fun fetchSingle(context: Context, uri: Uri, sourceMimeType: String?, callback: ImageOpCallback) {
|
||||
val id = uri.tryParseId()
|
||||
val onSuccess = fun(entry: FieldMap) {
|
||||
entry["uri"] = uri.toString()
|
||||
|
@ -46,11 +46,11 @@ class MediaStoreImageProvider : ImageProvider() {
|
|||
}
|
||||
val alwaysValid = { _: Int, _: Int -> true }
|
||||
if (id != null) {
|
||||
if (mimeType == null || isImage(mimeType)) {
|
||||
if (sourceMimeType == null || isImage(sourceMimeType)) {
|
||||
val contentUri = ContentUris.withAppendedId(IMAGE_CONTENT_URI, id)
|
||||
if (fetchFrom(context, alwaysValid, onSuccess, contentUri, IMAGE_PROJECTION)) return
|
||||
}
|
||||
if (mimeType == null || isVideo(mimeType)) {
|
||||
if (sourceMimeType == null || isVideo(sourceMimeType)) {
|
||||
val contentUri = ContentUris.withAppendedId(VIDEO_CONTENT_URI, id)
|
||||
if (fetchFrom(context, alwaysValid, onSuccess, contentUri, VIDEO_PROJECTION)) return
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ class MediaStoreImageProvider : ImageProvider() {
|
|||
// the uri can be a file media URI (e.g. "content://0@media/external/file/30050")
|
||||
// without an equivalent image/video if it is shared from a file browser
|
||||
// but the file is not publicly visible
|
||||
if (fetchFrom(context, alwaysValid, onSuccess, uri, BASE_PROJECTION, fileMimeType = mimeType)) return
|
||||
if (fetchFrom(context, alwaysValid, onSuccess, uri, BASE_PROJECTION, fileMimeType = sourceMimeType)) return
|
||||
|
||||
callback.onFailure(Exception("failed to fetch entry at uri=$uri"))
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ object BmpWriter {
|
|||
private val pad = ByteArray(3)
|
||||
|
||||
// file header
|
||||
private val bfType = byteArrayOf('B'.toByte(), 'M'.toByte())
|
||||
private val bfType = byteArrayOf('B'.code.toByte(), 'M'.code.toByte())
|
||||
private val bfReserved1 = intToWord(0)
|
||||
private val bfReserved2 = intToWord(0)
|
||||
private val bfOffBits = intToDWord(FILE_HEADER_SIZE + INFO_HEADER_SIZE)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.5.10'
|
||||
ext.kotlin_version = '1.5.20'
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
|
@ -9,7 +9,7 @@ buildscript {
|
|||
classpath 'com.android.tools.build:gradle:4.2.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath 'com.google.gms:google-services:4.3.8'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.7.0'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.7.1'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,9 +2,9 @@ import 'dart:async';
|
|||
import 'dart:ui' as ui show Codec;
|
||||
|
||||
import 'package:aves/services/services.dart';
|
||||
import 'package:aves/utils/pedantic.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:pedantic/pedantic.dart';
|
||||
|
||||
class UriImage extends ImageProvider<UriImage> {
|
||||
final String uri, mimeType;
|
||||
|
|
|
@ -13,7 +13,7 @@ class UriPicture extends PictureProvider<UriPicture> {
|
|||
final String uri, mimeType;
|
||||
|
||||
@override
|
||||
Future<UriPicture> obtainKey(PictureConfiguration configuration) {
|
||||
Future<UriPicture> obtainKey(PictureConfiguration picture) {
|
||||
return SynchronousFuture<UriPicture>(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,5 +29,5 @@ void main() {
|
|||
);
|
||||
}).sendPort);
|
||||
|
||||
runApp(AvesApp());
|
||||
runApp(const AvesApp());
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ class LocationFilter extends CollectionFilter {
|
|||
if (flag != null) {
|
||||
return Text(
|
||||
flag,
|
||||
style: TextStyle(fontSize: size, shadows: []),
|
||||
style: TextStyle(fontSize: size, shadows: const []),
|
||||
textScaleFactor: 1.0,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -139,11 +139,10 @@ class OverlayMetadata {
|
|||
|
||||
OverlayMetadata({
|
||||
double? aperture,
|
||||
String? exposureTime,
|
||||
this.exposureTime,
|
||||
double? focalLength,
|
||||
int? iso,
|
||||
}) : aperture = aperture != null ? 'ƒ/${apertureFormat.format(aperture)}' : null,
|
||||
exposureTime = exposureTime,
|
||||
focalLength = focalLength != null ? '${focalLengthFormat.format(focalLength)} mm' : null,
|
||||
iso = iso != null ? 'ISO$iso' : null;
|
||||
|
||||
|
|
|
@ -4,13 +4,13 @@ import 'package:aves/model/filters/filters.dart';
|
|||
import 'package:aves/model/settings/enums.dart';
|
||||
import 'package:aves/model/settings/screen_on.dart';
|
||||
import 'package:aves/model/source/enums.dart';
|
||||
import 'package:aves/utils/pedantic.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:firebase_analytics/firebase_analytics.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:pedantic/pedantic.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
final Settings settings = Settings._private();
|
||||
|
|
|
@ -12,7 +12,7 @@ class AppShortcutService {
|
|||
// this ability will not change over the lifetime of the app
|
||||
static bool? _canPin;
|
||||
|
||||
static Future<bool > canPin() async {
|
||||
static Future<bool> canPin() async {
|
||||
if (_canPin != null) {
|
||||
return SynchronousFuture(_canPin!);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ class ServicePolicy {
|
|||
Object? key,
|
||||
}) {
|
||||
Completer<T> completer;
|
||||
_Task<T > task;
|
||||
_Task<T> task;
|
||||
key ??= platformCall.hashCode;
|
||||
final toResume = _paused.remove(key);
|
||||
if (toResume != null) {
|
||||
|
@ -57,7 +57,7 @@ class ServicePolicy {
|
|||
final toResume = _paused.remove(key);
|
||||
if (toResume != null) {
|
||||
final priority = toResume.item1;
|
||||
final task = toResume.item2 as _Task<T >;
|
||||
final task = toResume.item2 as _Task<T>;
|
||||
_getQueue(priority)[key] = task;
|
||||
_pickNext();
|
||||
return task.completer.future;
|
||||
|
|
|
@ -67,7 +67,7 @@ class SvgMetadataService {
|
|||
|
||||
final docDir = Map.fromEntries([
|
||||
...root.attributes.where((a) => _attributes.contains(a.name.qualified)).map((a) => MapEntry(formatKey(a.name.qualified), a.value)),
|
||||
..._textElements.map((name) => MapEntry(formatKey(name), root.getElement(name)?.text)).where((kv) => kv.value != null).cast<MapEntry<String, String >>(),
|
||||
..._textElements.map((name) => MapEntry(formatKey(name), root.getElement(name)?.text)).where((kv) => kv.value != null).cast<MapEntry<String, String>>(),
|
||||
]);
|
||||
|
||||
final metadata = root.getElement(_metadataElement);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
// ignore: import_of_legacy_library_into_null_safe
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
|
||||
|
|
|
@ -254,6 +254,12 @@ class Constants {
|
|||
licenseUrl: 'https://github.com/marcojakob/dart-event-bus/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/marcojakob/dart-event-bus',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Flutter Lints',
|
||||
license: 'BSD 3-Clause',
|
||||
licenseUrl: 'https://github.com/flutter/packages/blob/master/packages/flutter_lints/LICENSE',
|
||||
sourceUrl: 'https://github.com/flutter/packages/tree/master/packages/flutter_lints',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Get It',
|
||||
license: 'MIT',
|
||||
|
@ -284,12 +290,6 @@ class Constants {
|
|||
licenseUrl: 'https://github.com/DavBfr/dart_pdf/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/DavBfr/dart_pdf',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Pedantic',
|
||||
license: 'BSD 3-Clause',
|
||||
licenseUrl: 'https://github.com/dart-lang/pedantic/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/dart-lang/pedantic',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Tuple',
|
||||
license: 'BSD 2-Clause',
|
||||
|
|
2
lib/utils/pedantic.dart
Normal file
2
lib/utils/pedantic.dart
Normal file
|
@ -0,0 +1,2 @@
|
|||
// cf https://github.com/google/pedantic/blob/master/lib/pedantic.dart
|
||||
void unawaited(Future<void>? future) {}
|
|
@ -8,6 +8,8 @@ import 'package:flutter/material.dart';
|
|||
class AboutPage extends StatelessWidget {
|
||||
static const routeName = '/about';
|
||||
|
||||
const AboutPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
@ -21,17 +23,17 @@ class AboutPage extends StatelessWidget {
|
|||
padding: const EdgeInsets.only(top: 16),
|
||||
sliver: SliverList(
|
||||
delegate: SliverChildListDelegate(
|
||||
[
|
||||
const [
|
||||
AppReference(),
|
||||
const Divider(),
|
||||
Divider(),
|
||||
AboutUpdate(),
|
||||
AboutCredits(),
|
||||
const Divider(),
|
||||
Divider(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Licenses(),
|
||||
const Licenses(),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -8,6 +8,8 @@ import 'package:flutter/material.dart';
|
|||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
|
||||
class AppReference extends StatefulWidget {
|
||||
const AppReference({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AppReferenceState createState() => _AppReferenceState();
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ import 'package:aves/widgets/common/extensions/build_context.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class AboutCredits extends StatelessWidget {
|
||||
const AboutCredits({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
|
|
|
@ -7,6 +7,8 @@ import 'package:collection/collection.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class Licenses extends StatefulWidget {
|
||||
const Licenses({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_LicensesState createState() => _LicensesState();
|
||||
}
|
||||
|
@ -46,25 +48,25 @@ class _LicensesState extends State<Licenses> {
|
|||
title: context.l10n.aboutLicensesAndroidLibraries,
|
||||
color: BrandColors.android,
|
||||
expandedNotifier: _expandedNotifier,
|
||||
children: _platform.map((package) => LicenseRow(package)).toList(),
|
||||
children: _platform.map((package) => LicenseRow(package: package)).toList(),
|
||||
),
|
||||
AvesExpansionTile(
|
||||
title: context.l10n.aboutLicensesFlutterPlugins,
|
||||
color: BrandColors.flutter,
|
||||
expandedNotifier: _expandedNotifier,
|
||||
children: _flutterPlugins.map((package) => LicenseRow(package)).toList(),
|
||||
children: _flutterPlugins.map((package) => LicenseRow(package: package)).toList(),
|
||||
),
|
||||
AvesExpansionTile(
|
||||
title: context.l10n.aboutLicensesFlutterPackages,
|
||||
color: BrandColors.flutter,
|
||||
expandedNotifier: _expandedNotifier,
|
||||
children: _flutterPackages.map((package) => LicenseRow(package)).toList(),
|
||||
children: _flutterPackages.map((package) => LicenseRow(package: package)).toList(),
|
||||
),
|
||||
AvesExpansionTile(
|
||||
title: context.l10n.aboutLicensesDartPackages,
|
||||
color: BrandColors.flutter,
|
||||
expandedNotifier: _expandedNotifier,
|
||||
children: _dartPackages.map((package) => LicenseRow(package)).toList(),
|
||||
children: _dartPackages.map((package) => LicenseRow(package: package)).toList(),
|
||||
),
|
||||
Center(
|
||||
child: TextButton(
|
||||
|
@ -113,7 +115,10 @@ class _LicensesState extends State<Licenses> {
|
|||
class LicenseRow extends StatelessWidget {
|
||||
final Dependency package;
|
||||
|
||||
const LicenseRow(this.package);
|
||||
const LicenseRow({
|
||||
Key? key,
|
||||
required this.package,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class AboutNewsBadge extends StatelessWidget {
|
||||
const AboutNewsBadge();
|
||||
const AboutNewsBadge({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -6,6 +6,8 @@ import 'package:aves/widgets/common/extensions/build_context.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class AboutUpdate extends StatefulWidget {
|
||||
const AboutUpdate({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AboutUpdateState createState() => _AboutUpdateState();
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@ import 'package:overlay_support/overlay_support.dart';
|
|||
import 'package:provider/provider.dart';
|
||||
|
||||
class AvesApp extends StatefulWidget {
|
||||
const AvesApp({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AvesAppState createState() => _AvesAppState();
|
||||
}
|
||||
|
@ -88,7 +90,7 @@ class _AvesAppState extends State<AvesApp> {
|
|||
darkTheme: Themes.darkTheme,
|
||||
themeMode: ThemeMode.dark,
|
||||
locale: settingsLocale,
|
||||
localizationsDelegates: [
|
||||
localizationsDelegates: const [
|
||||
...AppLocalizations.localizationsDelegates,
|
||||
],
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
|
|
|
@ -12,6 +12,7 @@ import 'package:aves/model/source/enums.dart';
|
|||
import 'package:aves/services/app_shortcut_service.dart';
|
||||
import 'package:aves/theme/durations.dart';
|
||||
import 'package:aves/theme/icons.dart';
|
||||
import 'package:aves/utils/pedantic.dart';
|
||||
import 'package:aves/widgets/collection/entry_set_action_delegate.dart';
|
||||
import 'package:aves/widgets/collection/filter_bar.dart';
|
||||
import 'package:aves/widgets/common/app_bar_subtitle.dart';
|
||||
|
@ -26,7 +27,6 @@ import 'package:aves/widgets/stats/stats.dart';
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
import 'package:pedantic/pedantic.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
|
@ -175,7 +175,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
|||
return [
|
||||
if (collection.isBrowsing && appMode.canSearch)
|
||||
CollectionSearchButton(
|
||||
source,
|
||||
source: source,
|
||||
parentCollection: collection,
|
||||
),
|
||||
if (collection.isSelecting)
|
||||
|
@ -349,7 +349,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
|||
|
||||
Future<void> _showShortcutDialog(BuildContext context) async {
|
||||
final filters = collection.filters;
|
||||
var defaultName;
|
||||
String? defaultName;
|
||||
if (filters.isNotEmpty) {
|
||||
// we compute the default name beforehand
|
||||
// because some filter labels need localization
|
||||
|
|
|
@ -324,8 +324,8 @@ class _CollectionScrollViewState extends State<_CollectionScrollView> {
|
|||
hasScrollBody: false,
|
||||
child: _buildEmptyCollectionPlaceholder(collection),
|
||||
)
|
||||
: SectionedListSliver<AvesEntry>(),
|
||||
BottomPaddingSliver(),
|
||||
: const SectionedListSliver<AvesEntry>(),
|
||||
const BottomPaddingSliver(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -13,7 +13,10 @@ class CollectionPage extends StatefulWidget {
|
|||
|
||||
final CollectionLens collection;
|
||||
|
||||
const CollectionPage(this.collection);
|
||||
const CollectionPage({
|
||||
Key? key,
|
||||
required this.collection,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_CollectionPageState createState() => _CollectionPageState();
|
||||
|
@ -54,7 +57,7 @@ class _CollectionPageState extends State<CollectionPage> {
|
|||
),
|
||||
),
|
||||
),
|
||||
drawer: AppDrawer(),
|
||||
drawer: const AppDrawer(),
|
||||
resizeToAvoidBottomInset: false,
|
||||
),
|
||||
);
|
||||
|
|
|
@ -13,9 +13,10 @@ class CollectionDraggableThumbLabel extends StatelessWidget {
|
|||
final double offsetY;
|
||||
|
||||
const CollectionDraggableThumbLabel({
|
||||
Key? key,
|
||||
required this.collection,
|
||||
required this.offsetY,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -11,6 +11,7 @@ import 'package:aves/services/image_op_events.dart';
|
|||
import 'package:aves/services/services.dart';
|
||||
import 'package:aves/theme/durations.dart';
|
||||
import 'package:aves/utils/android_file_utils.dart';
|
||||
import 'package:aves/utils/pedantic.dart';
|
||||
import 'package:aves/widgets/collection/collection_page.dart';
|
||||
import 'package:aves/widgets/common/action_mixins/feedback.dart';
|
||||
import 'package:aves/widgets/common/action_mixins/permission_aware.dart';
|
||||
|
@ -21,7 +22,6 @@ import 'package:aves/widgets/filter_grids/album_pick.dart';
|
|||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:pedantic/pedantic.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMixin {
|
||||
|
@ -155,11 +155,9 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
|
|||
context,
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: CollectionPage.routeName),
|
||||
builder: (context) {
|
||||
return CollectionPage(
|
||||
targetCollection,
|
||||
);
|
||||
},
|
||||
builder: (context) => CollectionPage(
|
||||
collection: targetCollection,
|
||||
),
|
||||
),
|
||||
));
|
||||
await Future.delayed(Durations.staggeredAnimationPageTarget);
|
||||
|
|
|
@ -9,6 +9,7 @@ class SectionedEntryListLayoutProvider extends SectionedListLayoutProvider<AvesE
|
|||
final CollectionLens collection;
|
||||
|
||||
const SectionedEntryListLayoutProvider({
|
||||
Key? key,
|
||||
required this.collection,
|
||||
required double scrollableWidth,
|
||||
required int columnCount,
|
||||
|
@ -18,6 +19,7 @@ class SectionedEntryListLayoutProvider extends SectionedListLayoutProvider<AvesE
|
|||
required Duration tileAnimationDelay,
|
||||
required Widget child,
|
||||
}) : super(
|
||||
key: key,
|
||||
scrollableWidth: scrollableWidth,
|
||||
columnCount: columnCount,
|
||||
spacing: spacing,
|
||||
|
|
|
@ -18,12 +18,13 @@ class GridSelectionGestureDetector extends StatefulWidget {
|
|||
final Widget child;
|
||||
|
||||
const GridSelectionGestureDetector({
|
||||
Key? key,
|
||||
this.selectable = true,
|
||||
required this.collection,
|
||||
required this.scrollController,
|
||||
required this.appBarHeightNotifier,
|
||||
required this.child,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_GridSelectionGestureDetectorState createState() => _GridSelectionGestureDetectorState();
|
||||
|
@ -39,7 +40,7 @@ class _GridSelectionGestureDetectorState extends State<GridSelectionGestureDetec
|
|||
|
||||
CollectionLens get collection => widget.collection;
|
||||
|
||||
List<AvesEntry > get entries => collection.sortedEntries;
|
||||
List<AvesEntry> get entries => collection.sortedEntries;
|
||||
|
||||
ScrollController get scrollController => widget.scrollController;
|
||||
|
||||
|
|
|
@ -13,10 +13,11 @@ class ErrorThumbnail extends StatefulWidget {
|
|||
final String tooltip;
|
||||
|
||||
const ErrorThumbnail({
|
||||
Key? key,
|
||||
required this.entry,
|
||||
required this.extent,
|
||||
required this.tooltip,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ErrorThumbnailState createState() => _ErrorThumbnailState();
|
||||
|
|
|
@ -10,10 +10,11 @@ class ThumbnailTheme extends StatelessWidget {
|
|||
final Widget child;
|
||||
|
||||
const ThumbnailTheme({
|
||||
Key? key,
|
||||
required this.extent,
|
||||
this.showLocation,
|
||||
required this.child,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -50,10 +50,11 @@ class ReportOverlay<T> extends StatefulWidget {
|
|||
final void Function(Set<T> processed) onDone;
|
||||
|
||||
const ReportOverlay({
|
||||
Key? key,
|
||||
required this.opStream,
|
||||
required this.itemCount,
|
||||
required this.onDone,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ReportOverlayState createState() => _ReportOverlayState<T>();
|
||||
|
|
|
@ -49,7 +49,10 @@ class SourceStateAwareAppBarTitle extends StatelessWidget {
|
|||
class SourceStateSubtitle extends StatelessWidget {
|
||||
final CollectionSource source;
|
||||
|
||||
const SourceStateSubtitle({required this.source});
|
||||
const SourceStateSubtitle({
|
||||
Key? key,
|
||||
required this.source,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -5,9 +5,10 @@ class InteractiveAppBarTitle extends StatelessWidget {
|
|||
final Widget child;
|
||||
|
||||
const InteractiveAppBarTitle({
|
||||
Key? key,
|
||||
this.onTap,
|
||||
required this.child,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -29,14 +29,16 @@ class AvesHighlightView extends StatelessWidget {
|
|||
/// Specify text styles such as font family and font size
|
||||
final TextStyle? textStyle;
|
||||
|
||||
AvesHighlightView(
|
||||
String input, {
|
||||
AvesHighlightView({
|
||||
Key? key,
|
||||
required String input,
|
||||
this.language,
|
||||
this.theme = const {},
|
||||
this.padding,
|
||||
this.textStyle,
|
||||
int tabSize = 8, // TODO: https://github.com/flutter/flutter/issues/50087
|
||||
}) : source = input.replaceAll('\t', ' ' * tabSize);
|
||||
}) : source = input.replaceAll('\t', ' ' * tabSize),
|
||||
super(key: key);
|
||||
|
||||
List<TextSpan> _convert(List<Node> nodes) {
|
||||
final spans = <TextSpan>[];
|
||||
|
|
|
@ -7,6 +7,8 @@ import 'package:provider/provider.dart';
|
|||
// - a vertically scrollable body.
|
||||
// It will prevent the body from scrolling when a user swipe from bottom to use Android Q style navigation gestures.
|
||||
class BottomGestureAreaProtector extends StatelessWidget {
|
||||
const BottomGestureAreaProtector({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Selector<MediaQueryData, double>(
|
||||
|
@ -27,20 +29,25 @@ class BottomGestureAreaProtector extends StatelessWidget {
|
|||
class GestureAreaProtectorStack extends StatelessWidget {
|
||||
final Widget child;
|
||||
|
||||
const GestureAreaProtectorStack({required this.child});
|
||||
const GestureAreaProtectorStack({
|
||||
Key? key,
|
||||
required this.child,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Stack(
|
||||
children: [
|
||||
child,
|
||||
BottomGestureAreaProtector(),
|
||||
const BottomGestureAreaProtector(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class BottomPaddingSliver extends StatelessWidget {
|
||||
const BottomPaddingSliver({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SliverToBoxAdapter(
|
||||
|
|
|
@ -7,12 +7,13 @@ class MultiCrossFader extends StatefulWidget {
|
|||
final Widget child;
|
||||
|
||||
const MultiCrossFader({
|
||||
Key? key,
|
||||
required this.duration,
|
||||
this.fadeCurve = Curves.linear,
|
||||
this.sizeCurve = Curves.linear,
|
||||
this.alignment = Alignment.topCenter,
|
||||
required this.child,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_MultiCrossFaderState createState() => _MultiCrossFaderState();
|
||||
|
|
|
@ -9,7 +9,10 @@ import 'package:flutter/widgets.dart';
|
|||
class QueryBar extends StatefulWidget {
|
||||
final ValueNotifier<String> filterNotifier;
|
||||
|
||||
const QueryBar({required this.filterNotifier});
|
||||
const QueryBar({
|
||||
Key? key,
|
||||
required this.filterNotifier,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_QueryBarState createState() => _QueryBarState();
|
||||
|
|
|
@ -12,8 +12,9 @@ class DoubleBackPopScope extends StatefulWidget {
|
|||
final Widget child;
|
||||
|
||||
const DoubleBackPopScope({
|
||||
Key? key,
|
||||
required this.child,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_DoubleBackPopScopeState createState() => _DoubleBackPopScopeState();
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:aves/theme/durations.dart';
|
||||
import 'package:aves/utils/pedantic.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
import 'package:pedantic/pedantic.dart';
|
||||
|
||||
class Sweeper extends StatefulWidget {
|
||||
final WidgetBuilder builder;
|
||||
|
|
|
@ -15,11 +15,12 @@ class TransitionImage extends StatefulWidget {
|
|||
final bool gaplessPlayback = false;
|
||||
|
||||
const TransitionImage({
|
||||
Key? key,
|
||||
required this.image,
|
||||
required this.animation,
|
||||
this.width,
|
||||
this.height,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_TransitionImageState createState() => _TransitionImageState();
|
||||
|
|
|
@ -9,9 +9,10 @@ class DraggableThumbLabel<T> extends StatelessWidget {
|
|||
final List<String> Function(BuildContext context, T item) lineBuilder;
|
||||
|
||||
const DraggableThumbLabel({
|
||||
Key? key,
|
||||
required this.offsetY,
|
||||
required this.lineBuilder,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -103,10 +103,11 @@ class SectionHeader extends StatelessWidget {
|
|||
// as of Flutter v1.22.3, `RenderParagraph` fails to lay out `WidgetSpan` offscreen
|
||||
// so we use a hair space times a magic number to match width
|
||||
TextSpan(
|
||||
// 23 hair spaces match a width of 40.0
|
||||
text: '\u200A' * (hasLeading ? 23 : 1),
|
||||
// force a higher first line to match leading icon/selector dimension
|
||||
style: TextStyle(height: 2.3 * textScaleFactor),
|
||||
), // 23 hair spaces match a width of 40.0
|
||||
),
|
||||
if (hasTrailing) TextSpan(text: '\u200A' * 17),
|
||||
TextSpan(
|
||||
text: title,
|
||||
|
|
|
@ -18,6 +18,7 @@ abstract class SectionedListLayoutProvider<T> extends StatelessWidget {
|
|||
final Widget child;
|
||||
|
||||
const SectionedListLayoutProvider({
|
||||
Key? key,
|
||||
required this.scrollableWidth,
|
||||
required this.columnCount,
|
||||
required this.spacing,
|
||||
|
@ -25,7 +26,8 @@ abstract class SectionedListLayoutProvider<T> extends StatelessWidget {
|
|||
required this.tileBuilder,
|
||||
required this.tileAnimationDelay,
|
||||
required this.child,
|
||||
}) : assert(scrollableWidth != 0);
|
||||
}) : assert(scrollableWidth != 0),
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -14,6 +14,8 @@ import 'package:provider/provider.dart';
|
|||
// cf https://github.com/flutter/flutter/issues/49027
|
||||
// adapted from `RenderSliverFixedExtentBoxAdaptor`
|
||||
class SectionedListSliver<T> extends StatelessWidget {
|
||||
const SectionedListSliver({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final sectionLayouts = context.watch<SectionedListLayout<T>>().sectionLayouts;
|
||||
|
|
|
@ -12,6 +12,7 @@ class AvesExpansionTile extends StatelessWidget {
|
|||
final List<Widget> children;
|
||||
|
||||
const AvesExpansionTile({
|
||||
Key? key,
|
||||
String? value,
|
||||
this.leading,
|
||||
required this.title,
|
||||
|
@ -20,13 +21,14 @@ class AvesExpansionTile extends StatelessWidget {
|
|||
this.initiallyExpanded = false,
|
||||
this.showHighlight = true,
|
||||
required this.children,
|
||||
}) : value = value ?? title;
|
||||
}) : value = value ?? title,
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final enabled = children.isNotEmpty == true;
|
||||
Widget titleChild = HighlightTitle(
|
||||
title,
|
||||
title: title,
|
||||
color: color,
|
||||
enabled: enabled,
|
||||
showHighlight: showHighlight,
|
||||
|
|
|
@ -4,7 +4,10 @@ import 'package:flutter_svg/flutter_svg.dart';
|
|||
class AvesLogo extends StatelessWidget {
|
||||
final double size;
|
||||
|
||||
const AvesLogo({required this.size});
|
||||
const AvesLogo({
|
||||
Key? key,
|
||||
required this.size,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -6,10 +6,11 @@ class EmptyContent extends StatelessWidget {
|
|||
final AlignmentGeometry alignment;
|
||||
|
||||
const EmptyContent({
|
||||
Key? key,
|
||||
this.icon,
|
||||
required this.text,
|
||||
this.alignment = const FractionalOffset(.5, .35),
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -11,14 +11,15 @@ class HighlightTitle extends StatelessWidget {
|
|||
final bool enabled, selectable;
|
||||
final bool showHighlight;
|
||||
|
||||
const HighlightTitle(
|
||||
this.title, {
|
||||
const HighlightTitle({
|
||||
Key? key,
|
||||
required this.title,
|
||||
this.color,
|
||||
this.fontSize = 18,
|
||||
this.enabled = true,
|
||||
this.selectable = false,
|
||||
this.showHighlight = true,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
static const disabledColor = Colors.grey;
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ class MagnifierGestureRecognizer extends ScaleGestureRecognizer {
|
|||
}
|
||||
|
||||
void _decideIfWeAcceptEvent(PointerEvent event) {
|
||||
if (!(event is PointerMoveEvent)) return;
|
||||
if (event is! PointerMoveEvent) return;
|
||||
|
||||
if (_pointerLocations.keys.length >= 2) {
|
||||
// when there are multiple pointers, we always accept the gesture to scale
|
||||
|
|
|
@ -8,10 +8,11 @@ import 'package:flutter/widgets.dart';
|
|||
/// such as [PageView], [Dismissible], [BottomSheet].
|
||||
class MagnifierGestureDetectorScope extends InheritedWidget {
|
||||
const MagnifierGestureDetectorScope({
|
||||
Key? key,
|
||||
required this.axis,
|
||||
this.touchSlopFactor = .8,
|
||||
required Widget child,
|
||||
}) : super(child: child);
|
||||
}) : super(key: key, child: child);
|
||||
|
||||
static MagnifierGestureDetectorScope? of(BuildContext context) {
|
||||
final scope = context.dependOnInheritedWidgetOfExactType<MagnifierGestureDetectorScope>();
|
||||
|
|
|
@ -5,7 +5,10 @@ import 'package:provider/provider.dart';
|
|||
class HighlightInfoProvider extends StatelessWidget {
|
||||
final Widget child;
|
||||
|
||||
const HighlightInfoProvider({required this.child});
|
||||
const HighlightInfoProvider({
|
||||
Key? key,
|
||||
required this.child,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -4,7 +4,10 @@ import 'package:provider/provider.dart';
|
|||
class MediaQueryDataProvider extends StatelessWidget {
|
||||
final Widget child;
|
||||
|
||||
const MediaQueryDataProvider({required this.child});
|
||||
const MediaQueryDataProvider({
|
||||
Key? key,
|
||||
required this.child,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -7,9 +7,10 @@ class TileExtentControllerProvider extends StatelessWidget {
|
|||
final Widget child;
|
||||
|
||||
const TileExtentControllerProvider({
|
||||
Key? key,
|
||||
required this.controller,
|
||||
required this.child,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -24,12 +24,13 @@ class GridScaleGestureDetector<T> extends StatefulWidget {
|
|||
final Widget child;
|
||||
|
||||
const GridScaleGestureDetector({
|
||||
Key? key,
|
||||
required this.scrollableKey,
|
||||
required this.gridBuilder,
|
||||
required this.scaledBuilder,
|
||||
this.highlightItem,
|
||||
required this.child,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_GridScaleGestureDetectorState createState() => _GridScaleGestureDetectorState<T>();
|
||||
|
@ -140,12 +141,13 @@ class ScaleOverlay extends StatefulWidget {
|
|||
final Widget Function(Offset center, double extent, Widget child) gridBuilder;
|
||||
|
||||
const ScaleOverlay({
|
||||
Key? key,
|
||||
required this.builder,
|
||||
required this.center,
|
||||
required this.viewportWidth,
|
||||
required this.scaledExtentNotifier,
|
||||
required this.gridBuilder,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ScaleOverlayState createState() => _ScaleOverlayState();
|
||||
|
@ -175,7 +177,7 @@ class _ScaleOverlayState extends State<ScaleOverlay> {
|
|||
gradient: RadialGradient(
|
||||
center: FractionalOffset.fromOffsetAndSize(center, context.select<MediaQueryData, Size>((mq) => mq.size)),
|
||||
radius: 1,
|
||||
colors: [
|
||||
colors: const [
|
||||
Colors.black,
|
||||
Colors.black54,
|
||||
],
|
||||
|
|
|
@ -7,6 +7,8 @@ import 'package:collection/collection.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class DebugAndroidAppSection extends StatefulWidget {
|
||||
const DebugAndroidAppSection({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_DebugAndroidAppSectionState createState() => _DebugAndroidAppSectionState();
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ import 'package:aves/widgets/viewer/info/common.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class DebugAndroidDirSection extends StatefulWidget {
|
||||
const DebugAndroidDirSection({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_DebugAndroidDirSectionState createState() => _DebugAndroidDirSectionState();
|
||||
}
|
||||
|
@ -34,7 +36,7 @@ class _DebugAndroidDirSectionState extends State<DebugAndroidDirSection> with Au
|
|||
if (snapshot.hasError) return Text(snapshot.error.toString());
|
||||
if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
|
||||
final data = SplayTreeMap.of(snapshot.data!.map((k, v) => MapEntry(k.toString(), v?.toString() ?? 'null')));
|
||||
return InfoRowGroup(data);
|
||||
return InfoRowGroup(info: data);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
|
@ -6,6 +6,8 @@ import 'package:aves/widgets/viewer/info/common.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class DebugAndroidEnvironmentSection extends StatefulWidget {
|
||||
const DebugAndroidEnvironmentSection({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_DebugAndroidEnvironmentSectionState createState() => _DebugAndroidEnvironmentSectionState();
|
||||
}
|
||||
|
@ -34,7 +36,7 @@ class _DebugAndroidEnvironmentSectionState extends State<DebugAndroidEnvironment
|
|||
if (snapshot.hasError) return Text(snapshot.error.toString());
|
||||
if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
|
||||
final data = SplayTreeMap.of(snapshot.data!.map((k, v) => MapEntry(k.toString(), v?.toString() ?? 'null')));
|
||||
return InfoRowGroup(data);
|
||||
return InfoRowGroup(info: data);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
|
|
@ -19,6 +19,8 @@ import 'package:provider/provider.dart';
|
|||
class AppDebugPage extends StatefulWidget {
|
||||
static const routeName = '/debug';
|
||||
|
||||
const AppDebugPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _AppDebugPageState();
|
||||
}
|
||||
|
@ -42,14 +44,14 @@ class _AppDebugPageState extends State<AppDebugPage> {
|
|||
padding: const EdgeInsets.all(8),
|
||||
children: [
|
||||
_buildGeneralTabView(),
|
||||
DebugAndroidAppSection(),
|
||||
DebugAndroidDirSection(),
|
||||
DebugAndroidEnvironmentSection(),
|
||||
DebugCacheSection(),
|
||||
DebugAppDatabaseSection(),
|
||||
DebugFirebaseSection(),
|
||||
DebugSettingsSection(),
|
||||
DebugStorageSection(),
|
||||
const DebugAndroidAppSection(),
|
||||
const DebugAndroidDirSection(),
|
||||
const DebugAndroidEnvironmentSection(),
|
||||
const DebugCacheSection(),
|
||||
const DebugAppDatabaseSection(),
|
||||
const DebugFirebaseSection(),
|
||||
const DebugSettingsSection(),
|
||||
const DebugStorageSection(),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -83,7 +85,7 @@ class _AppDebugPageState extends State<AppDebugPage> {
|
|||
_taskQueueOverlayEntry?.remove();
|
||||
if (v) {
|
||||
_taskQueueOverlayEntry = OverlayEntry(
|
||||
builder: (context) => DebugTaskQueueOverlay(),
|
||||
builder: (context) => const DebugTaskQueueOverlay(),
|
||||
);
|
||||
Overlay.of(context)!.insert(_taskQueueOverlayEntry!);
|
||||
} else {
|
||||
|
@ -97,7 +99,7 @@ class _AppDebugPageState extends State<AppDebugPage> {
|
|||
Padding(
|
||||
padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8),
|
||||
child: InfoRowGroup(
|
||||
{
|
||||
info: {
|
||||
'All entries': '${source.allEntries.length}',
|
||||
'Visible entries': '${visibleEntries.length}',
|
||||
'Catalogued': '${catalogued.length}',
|
||||
|
|
|
@ -5,6 +5,8 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
|
||||
class DebugCacheSection extends StatefulWidget {
|
||||
const DebugCacheSection({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_DebugCacheSectionState createState() => _DebugCacheSectionState();
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@ import 'package:aves/widgets/common/identity/aves_expansion_tile.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class DebugAppDatabaseSection extends StatefulWidget {
|
||||
const DebugAppDatabaseSection({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_DebugAppDatabaseSectionState createState() => _DebugAppDatabaseSectionState();
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class DebugFirebaseSection extends StatelessWidget {
|
||||
const DebugFirebaseSection({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AvesExpansionTile(
|
||||
|
@ -32,10 +34,12 @@ class DebugFirebaseSection extends StatelessWidget {
|
|||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8),
|
||||
child: InfoRowGroup({
|
||||
child: InfoRowGroup(
|
||||
info: {
|
||||
'Firebase data collection enabled': '${Firebase.app().isAutomaticDataCollectionEnabled}',
|
||||
'Crashlytics collection enabled': '${FirebaseCrashlytics.instance.isCrashlyticsCollectionEnabled}',
|
||||
}),
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
|
|
|
@ -2,6 +2,8 @@ import 'package:aves/services/service_policy.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class DebugTaskQueueOverlay extends StatelessWidget {
|
||||
const DebugTaskQueueOverlay({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return IgnorePointer(
|
||||
|
|
|
@ -9,6 +9,8 @@ import 'package:flutter/material.dart';
|
|||
import 'package:provider/provider.dart';
|
||||
|
||||
class DebugSettingsSection extends StatelessWidget {
|
||||
const DebugSettingsSection({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<Settings>(
|
||||
|
@ -36,7 +38,8 @@ class DebugSettingsSection extends StatelessWidget {
|
|||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8),
|
||||
child: InfoRowGroup({
|
||||
child: InfoRowGroup(
|
||||
info: {
|
||||
'tileExtent - Collection': '${settings.getTileExtent(CollectionPage.routeName)}',
|
||||
'tileExtent - Albums': '${settings.getTileExtent(AlbumListPage.routeName)}',
|
||||
'tileExtent - Countries': '${settings.getTileExtent(CountryListPage.routeName)}',
|
||||
|
@ -50,7 +53,8 @@ class DebugSettingsSection extends StatelessWidget {
|
|||
'lastVersionCheckDate': '${settings.lastVersionCheckDate}',
|
||||
'locale': '${settings.locale}',
|
||||
'systemLocale': '${WidgetsBinding.instance!.window.locale}',
|
||||
}),
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
|
|
@ -6,6 +6,8 @@ import 'package:aves/widgets/viewer/info/common.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class DebugStorageSection extends StatefulWidget {
|
||||
const DebugStorageSection({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_DebugStorageSectionState createState() => _DebugStorageSectionState();
|
||||
}
|
||||
|
@ -38,13 +40,15 @@ class _DebugStorageSectionState extends State<DebugStorageSection> with Automati
|
|||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: InfoRowGroup({
|
||||
'description': '${v.getDescription(context)}',
|
||||
child: InfoRowGroup(
|
||||
info: {
|
||||
'description': v.getDescription(context),
|
||||
'isPrimary': '${v.isPrimary}',
|
||||
'isRemovable': '${v.isRemovable}',
|
||||
'state': '${v.state}',
|
||||
'state': v.state,
|
||||
if (freeSpace != null) 'freeSpace': formatFilesize(freeSpace),
|
||||
}),
|
||||
},
|
||||
),
|
||||
),
|
||||
const Divider(),
|
||||
];
|
||||
|
|
|
@ -19,9 +19,10 @@ class AddShortcutDialog extends StatefulWidget {
|
|||
final String defaultName;
|
||||
|
||||
const AddShortcutDialog({
|
||||
Key? key,
|
||||
required this.collection,
|
||||
required this.defaultName,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AddShortcutDialogState createState() => _AddShortcutDialogState();
|
||||
|
@ -133,7 +134,7 @@ class _AddShortcutDialogState extends State<AddShortcutDialog> {
|
|||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: ItemPickDialog.routeName),
|
||||
builder: (context) => ItemPickDialog(
|
||||
CollectionLens(
|
||||
collection: CollectionLens(
|
||||
source: collection.source,
|
||||
filters: filters,
|
||||
),
|
||||
|
|
|
@ -9,6 +9,7 @@ class AvesDialog extends AlertDialog {
|
|||
static const borderWidth = 1.0;
|
||||
|
||||
AvesDialog({
|
||||
Key? key,
|
||||
required BuildContext context,
|
||||
String? title,
|
||||
ScrollController? scrollController,
|
||||
|
@ -17,6 +18,7 @@ class AvesDialog extends AlertDialog {
|
|||
required List<Widget> actions,
|
||||
}) : assert((scrollableContent != null) ^ (content != null)),
|
||||
super(
|
||||
key: key,
|
||||
title: title != null
|
||||
? Padding(
|
||||
// padding to avoid transparent border overlapping
|
||||
|
@ -64,7 +66,10 @@ class AvesDialog extends AlertDialog {
|
|||
class DialogTitle extends StatelessWidget {
|
||||
final String title;
|
||||
|
||||
const DialogTitle({required this.title});
|
||||
const DialogTitle({
|
||||
Key? key,
|
||||
required this.title,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -13,11 +13,12 @@ class AvesSelectionDialog<T> extends StatefulWidget {
|
|||
final String title;
|
||||
|
||||
const AvesSelectionDialog({
|
||||
Key? key,
|
||||
required this.initialValue,
|
||||
required this.options,
|
||||
this.optionSubtitleBuilder,
|
||||
required this.title,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AvesSelectionDialogState<T> createState() => _AvesSelectionDialogState<T>();
|
||||
|
|
|
@ -17,9 +17,10 @@ class CoverSelectionDialog extends StatefulWidget {
|
|||
final AvesEntry? customEntry;
|
||||
|
||||
const CoverSelectionDialog({
|
||||
Key? key,
|
||||
required this.filter,
|
||||
required this.customEntry,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_CoverSelectionDialogState createState() => _CoverSelectionDialogState();
|
||||
|
@ -118,7 +119,7 @@ class _CoverSelectionDialogState extends State<CoverSelectionDialog> {
|
|||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: ItemPickDialog.routeName),
|
||||
builder: (context) => ItemPickDialog(
|
||||
CollectionLens(
|
||||
collection: CollectionLens(
|
||||
source: context.read<CollectionSource>(),
|
||||
filters: [filter],
|
||||
),
|
||||
|
|
|
@ -11,6 +11,8 @@ import 'package:flutter/widgets.dart';
|
|||
import 'aves_dialog.dart';
|
||||
|
||||
class CreateAlbumDialog extends StatefulWidget {
|
||||
const CreateAlbumDialog({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_CreateAlbumDialogState createState() => _CreateAlbumDialogState();
|
||||
}
|
||||
|
|
|
@ -12,7 +12,10 @@ class ItemPickDialog extends StatefulWidget {
|
|||
|
||||
final CollectionLens collection;
|
||||
|
||||
const ItemPickDialog(this.collection);
|
||||
const ItemPickDialog({
|
||||
Key? key,
|
||||
required this.collection,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_ItemPickDialogState createState() => _ItemPickDialogState();
|
||||
|
|
|
@ -8,7 +8,10 @@ import 'package:flutter/material.dart';
|
|||
class RenameAlbumDialog extends StatefulWidget {
|
||||
final String album;
|
||||
|
||||
const RenameAlbumDialog(this.album);
|
||||
const RenameAlbumDialog({
|
||||
Key? key,
|
||||
required this.album,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_RenameAlbumDialogState createState() => _RenameAlbumDialogState();
|
||||
|
|
|
@ -10,7 +10,10 @@ import 'aves_dialog.dart';
|
|||
class RenameEntryDialog extends StatefulWidget {
|
||||
final AvesEntry entry;
|
||||
|
||||
const RenameEntryDialog(this.entry);
|
||||
const RenameEntryDialog({
|
||||
Key? key,
|
||||
required this.entry,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_RenameEntryDialogState createState() => _RenameEntryDialogState();
|
||||
|
|
|
@ -7,10 +7,11 @@ class VideoSpeedDialog extends StatefulWidget {
|
|||
final double current, min, max;
|
||||
|
||||
const VideoSpeedDialog({
|
||||
Key? key,
|
||||
required this.current,
|
||||
required this.min,
|
||||
required this.max,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_VideoSpeedDialogState createState() => _VideoSpeedDialogState();
|
||||
|
|
|
@ -12,8 +12,9 @@ class VideoStreamSelectionDialog extends StatefulWidget {
|
|||
final Map<StreamSummary, bool> streams;
|
||||
|
||||
const VideoStreamSelectionDialog({
|
||||
Key? key,
|
||||
required this.streams,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_VideoStreamSelectionDialogState createState() => _VideoStreamSelectionDialogState();
|
||||
|
|
|
@ -10,7 +10,10 @@ import 'package:provider/provider.dart';
|
|||
class AlbumTile extends StatelessWidget {
|
||||
final String album;
|
||||
|
||||
const AlbumTile(this.album);
|
||||
const AlbumTile({
|
||||
Key? key,
|
||||
required this.album,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -28,6 +28,8 @@ import 'package:flutter/material.dart';
|
|||
import 'package:provider/provider.dart';
|
||||
|
||||
class AppDrawer extends StatefulWidget {
|
||||
const AppDrawer({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AppDrawerState createState() => _AppDrawerState();
|
||||
}
|
||||
|
@ -141,7 +143,7 @@ class _AppDrawerState extends State<AppDrawer> {
|
|||
children: [
|
||||
OutlinedButton.icon(
|
||||
key: const Key('drawer-about-button'),
|
||||
onPressed: () => goTo(AboutPage.routeName, (_) => AboutPage()),
|
||||
onPressed: () => goTo(AboutPage.routeName, (_) => const AboutPage()),
|
||||
icon: const Icon(AIcons.info),
|
||||
label: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
@ -177,7 +179,7 @@ class _AppDrawerState extends State<AppDrawer> {
|
|||
),
|
||||
OutlinedButton.icon(
|
||||
key: const Key('drawer-settings-button'),
|
||||
onPressed: () => goTo(SettingsPage.routeName, (_) => SettingsPage()),
|
||||
onPressed: () => goTo(SettingsPage.routeName, (_) => const SettingsPage()),
|
||||
icon: const Icon(AIcons.settings),
|
||||
label: Text(context.l10n.settingsPageTitle),
|
||||
),
|
||||
|
@ -204,7 +206,7 @@ class _AppDrawerState extends State<AppDrawer> {
|
|||
return Column(
|
||||
children: [
|
||||
const Divider(),
|
||||
...specialAlbums.map((album) => AlbumTile(album)),
|
||||
...specialAlbums.map((album) => AlbumTile(album: album)),
|
||||
],
|
||||
);
|
||||
});
|
||||
|
@ -238,7 +240,7 @@ class _AppDrawerState extends State<AppDrawer> {
|
|||
builder: (context, _) => Text('${source.rawAlbums.length}'),
|
||||
),
|
||||
routeName: AlbumListPage.routeName,
|
||||
pageBuilder: (_) => AlbumListPage(),
|
||||
pageBuilder: (_) => const AlbumListPage(),
|
||||
);
|
||||
|
||||
Widget get countryListTile => NavTile(
|
||||
|
@ -249,7 +251,7 @@ class _AppDrawerState extends State<AppDrawer> {
|
|||
builder: (context, _) => Text('${source.sortedCountries.length}'),
|
||||
),
|
||||
routeName: CountryListPage.routeName,
|
||||
pageBuilder: (_) => CountryListPage(),
|
||||
pageBuilder: (_) => const CountryListPage(),
|
||||
);
|
||||
|
||||
Widget get tagListTile => NavTile(
|
||||
|
@ -260,7 +262,7 @@ class _AppDrawerState extends State<AppDrawer> {
|
|||
builder: (context, _) => Text('${source.sortedTags.length}'),
|
||||
),
|
||||
routeName: TagListPage.routeName,
|
||||
pageBuilder: (_) => TagListPage(),
|
||||
pageBuilder: (_) => const TagListPage(),
|
||||
);
|
||||
|
||||
Widget get debugTile => NavTile(
|
||||
|
@ -268,6 +270,6 @@ class _AppDrawerState extends State<AppDrawer> {
|
|||
title: 'Debug',
|
||||
topLevel: false,
|
||||
routeName: AppDebugPage.routeName,
|
||||
pageBuilder: (_) => AppDebugPage(),
|
||||
pageBuilder: (_) => const AppDebugPage(),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -13,12 +13,14 @@ class CollectionNavTile extends StatelessWidget {
|
|||
final CollectionFilter? filter;
|
||||
|
||||
const CollectionNavTile({
|
||||
Key? key,
|
||||
required this.leading,
|
||||
required this.title,
|
||||
this.trailing,
|
||||
bool? dense,
|
||||
required this.filter,
|
||||
}) : dense = dense ?? false;
|
||||
}) : dense = dense ?? false,
|
||||
super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -41,10 +43,12 @@ class CollectionNavTile extends StatelessWidget {
|
|||
context,
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: CollectionPage.routeName),
|
||||
builder: (context) => CollectionPage(CollectionLens(
|
||||
builder: (context) => CollectionPage(
|
||||
collection: CollectionLens(
|
||||
source: context.read<CollectionSource>(),
|
||||
filters: [filter],
|
||||
)),
|
||||
),
|
||||
),
|
||||
),
|
||||
(route) => false,
|
||||
);
|
||||
|
|
|
@ -11,13 +11,14 @@ class NavTile extends StatelessWidget {
|
|||
final WidgetBuilder pageBuilder;
|
||||
|
||||
const NavTile({
|
||||
Key? key,
|
||||
required this.icon,
|
||||
required this.title,
|
||||
this.trailing,
|
||||
this.topLevel = true,
|
||||
required this.routeName,
|
||||
required this.pageBuilder,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -30,9 +30,10 @@ class AlbumPickPage extends StatefulWidget {
|
|||
final MoveType moveType;
|
||||
|
||||
const AlbumPickPage({
|
||||
Key? key,
|
||||
required this.source,
|
||||
required this.moveType,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_AlbumPickPageState createState() => _AlbumPickPageState();
|
||||
|
@ -91,11 +92,12 @@ class AlbumPickAppBar extends StatelessWidget {
|
|||
static const preferredHeight = kToolbarHeight + AlbumFilterBar.preferredHeight;
|
||||
|
||||
const AlbumPickAppBar({
|
||||
Key? key,
|
||||
required this.source,
|
||||
required this.moveType,
|
||||
required this.actionDelegate,
|
||||
required this.queryNotifier,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -127,7 +129,7 @@ class AlbumPickAppBar extends StatelessWidget {
|
|||
onPressed: () async {
|
||||
final newAlbum = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (context) => CreateAlbumDialog(),
|
||||
builder: (context) => const CreateAlbumDialog(),
|
||||
);
|
||||
if (newAlbum != null && newAlbum.isNotEmpty) {
|
||||
Navigator.pop<String>(context, newAlbum);
|
||||
|
@ -169,8 +171,9 @@ class AlbumFilterBar extends StatelessWidget implements PreferredSizeWidget {
|
|||
static const preferredHeight = kToolbarHeight;
|
||||
|
||||
const AlbumFilterBar({
|
||||
Key? key,
|
||||
required this.filterNotifier,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Size get preferredSize => const Size.fromHeight(preferredHeight);
|
||||
|
|
|
@ -21,6 +21,8 @@ import 'package:tuple/tuple.dart';
|
|||
class AlbumListPage extends StatelessWidget {
|
||||
static const routeName = '/albums';
|
||||
|
||||
const AlbumListPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final source = context.read<CollectionSource>();
|
||||
|
|
|
@ -43,13 +43,13 @@ class ChipActionDelegate {
|
|||
_showCoverSelectionDialog(context, filter);
|
||||
break;
|
||||
case ChipAction.goToAlbumPage:
|
||||
_goTo(context, filter, AlbumListPage.routeName, (context) => AlbumListPage());
|
||||
_goTo(context, filter, AlbumListPage.routeName, (context) => const AlbumListPage());
|
||||
break;
|
||||
case ChipAction.goToCountryPage:
|
||||
_goTo(context, filter, CountryListPage.routeName, (context) => CountryListPage());
|
||||
_goTo(context, filter, CountryListPage.routeName, (context) => const CountryListPage());
|
||||
break;
|
||||
case ChipAction.goToTagPage:
|
||||
_goTo(context, filter, TagListPage.routeName, (context) => TagListPage());
|
||||
_goTo(context, filter, TagListPage.routeName, (context) => const TagListPage());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -207,7 +207,7 @@ class AlbumChipActionDelegate extends ChipActionDelegate with FeedbackMixin, Per
|
|||
|
||||
final newName = await showDialog<String>(
|
||||
context: context,
|
||||
builder: (context) => RenameAlbumDialog(album),
|
||||
builder: (context) => RenameAlbumDialog(album: album),
|
||||
);
|
||||
if (newName == null || newName.isEmpty) return;
|
||||
|
||||
|
|
|
@ -11,9 +11,10 @@ class FilterDraggableThumbLabel<T extends CollectionFilter> extends StatelessWid
|
|||
final double offsetY;
|
||||
|
||||
const FilterDraggableThumbLabel({
|
||||
Key? key,
|
||||
required this.sortFactor,
|
||||
required this.offsetY,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -91,7 +91,7 @@ class FilterGridPage<T extends CollectionFilter> extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
),
|
||||
drawer: AppDrawer(),
|
||||
drawer: const AppDrawer(),
|
||||
resizeToAvoidBottomInset: false,
|
||||
),
|
||||
);
|
||||
|
@ -454,7 +454,7 @@ class _FilterScrollView<T extends CollectionFilter> extends StatelessWidget {
|
|||
)
|
||||
: SectionedListSliver<FilterGridItem<T>>();
|
||||
}),
|
||||
BottomPaddingSliver(),
|
||||
const BottomPaddingSliver(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ class FilterNavigationPage<T extends CollectionFilter> extends StatelessWidget {
|
|||
final Widget Function() emptyBuilder;
|
||||
|
||||
const FilterNavigationPage({
|
||||
Key? key,
|
||||
required this.source,
|
||||
required this.title,
|
||||
required this.sortFactor,
|
||||
|
@ -47,7 +48,7 @@ class FilterNavigationPage<T extends CollectionFilter> extends StatelessWidget {
|
|||
required this.chipActionsBuilder,
|
||||
required this.filterSections,
|
||||
required this.emptyBuilder,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -80,10 +81,12 @@ class FilterNavigationPage<T extends CollectionFilter> extends StatelessWidget {
|
|||
context,
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: CollectionPage.routeName),
|
||||
builder: (context) => CollectionPage(CollectionLens(
|
||||
builder: (context) => CollectionPage(
|
||||
collection: CollectionLens(
|
||||
source: source,
|
||||
filters: [filter],
|
||||
)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
onLongPress: isMainMode ? _showMenu as OffsetFilterCallback : null,
|
||||
|
@ -111,7 +114,7 @@ class FilterNavigationPage<T extends CollectionFilter> extends StatelessWidget {
|
|||
|
||||
List<Widget> _buildActions(BuildContext context) {
|
||||
return [
|
||||
CollectionSearchButton(source),
|
||||
CollectionSearchButton(source: source),
|
||||
PopupMenuButton<ChipSetAction>(
|
||||
key: const Key('appbar-menu-button'),
|
||||
itemBuilder: (context) {
|
||||
|
|
|
@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
|
|||
|
||||
class SectionedFilterListLayoutProvider<T extends CollectionFilter> extends SectionedListLayoutProvider<FilterGridItem<T>> {
|
||||
const SectionedFilterListLayoutProvider({
|
||||
Key? key,
|
||||
required this.sections,
|
||||
required this.showHeaders,
|
||||
required double scrollableWidth,
|
||||
|
@ -17,6 +18,7 @@ class SectionedFilterListLayoutProvider<T extends CollectionFilter> extends Sect
|
|||
required Duration tileAnimationDelay,
|
||||
required Widget child,
|
||||
}) : super(
|
||||
key: key,
|
||||
scrollableWidth: scrollableWidth,
|
||||
columnCount: columnCount,
|
||||
spacing: spacing,
|
||||
|
|
|
@ -20,6 +20,8 @@ import 'package:tuple/tuple.dart';
|
|||
class CountryListPage extends StatelessWidget {
|
||||
static const routeName = '/countries';
|
||||
|
||||
const CountryListPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final source = context.read<CollectionSource>();
|
||||
|
|
|
@ -20,6 +20,8 @@ import 'package:tuple/tuple.dart';
|
|||
class TagListPage extends StatelessWidget {
|
||||
static const routeName = '/tags';
|
||||
|
||||
const TagListPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final source = context.read<CollectionSource>();
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'package:aves/model/source/collection_source.dart';
|
|||
import 'package:aves/services/services.dart';
|
||||
import 'package:aves/services/viewer_service.dart';
|
||||
import 'package:aves/utils/android_file_utils.dart';
|
||||
import 'package:aves/utils/pedantic.dart';
|
||||
import 'package:aves/widgets/collection/collection_page.dart';
|
||||
import 'package:aves/widgets/common/behaviour/routes.dart';
|
||||
import 'package:aves/widgets/filter_grids/albums_page.dart';
|
||||
|
@ -18,7 +19,6 @@ import 'package:aves/widgets/viewer/entry_viewer_page.dart';
|
|||
import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:pedantic/pedantic.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
|
@ -28,7 +28,10 @@ class HomePage extends StatefulWidget {
|
|||
// untyped map as it is coming from the platform
|
||||
final Map? intentData;
|
||||
|
||||
const HomePage({this.intentData});
|
||||
const HomePage({
|
||||
Key? key,
|
||||
this.intentData,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
_HomePageState createState() => _HomePageState();
|
||||
|
@ -147,7 +150,7 @@ class _HomePageState extends State<HomePage> {
|
|||
case AlbumListPage.routeName:
|
||||
return DirectMaterialPageRoute(
|
||||
settings: const RouteSettings(name: AlbumListPage.routeName),
|
||||
builder: (_) => AlbumListPage(),
|
||||
builder: (_) => const AlbumListPage(),
|
||||
);
|
||||
case SearchPage.routeName:
|
||||
return SearchPageRoute(
|
||||
|
@ -158,7 +161,7 @@ class _HomePageState extends State<HomePage> {
|
|||
return DirectMaterialPageRoute(
|
||||
settings: const RouteSettings(name: CollectionPage.routeName),
|
||||
builder: (_) => CollectionPage(
|
||||
CollectionLens(
|
||||
collection: CollectionLens(
|
||||
source: source,
|
||||
filters: filters,
|
||||
),
|
||||
|
|
|
@ -13,12 +13,13 @@ class ExpandableFilterRow extends StatelessWidget {
|
|||
final FilterCallback onTap;
|
||||
|
||||
const ExpandableFilterRow({
|
||||
Key? key,
|
||||
this.title,
|
||||
required this.filters,
|
||||
required this.expandedNotifier,
|
||||
this.heroTypeBuilder,
|
||||
required this.onTap,
|
||||
});
|
||||
}) : super(key: key);
|
||||
|
||||
static const double horizontalPadding = 8;
|
||||
static const double verticalPadding = 8;
|
||||
|
|
|
@ -8,7 +8,11 @@ class CollectionSearchButton extends StatelessWidget {
|
|||
final CollectionSource source;
|
||||
final CollectionLens? parentCollection;
|
||||
|
||||
const CollectionSearchButton(this.source, {this.parentCollection});
|
||||
const CollectionSearchButton({
|
||||
Key? key,
|
||||
required this.source,
|
||||
this.parentCollection,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -243,10 +243,12 @@ class CollectionSearchDelegate {
|
|||
context,
|
||||
MaterialPageRoute(
|
||||
settings: const RouteSettings(name: CollectionPage.routeName),
|
||||
builder: (context) => CollectionPage(CollectionLens(
|
||||
builder: (context) => CollectionPage(
|
||||
collection: CollectionLens(
|
||||
source: source,
|
||||
filters: [filter],
|
||||
)),
|
||||
),
|
||||
),
|
||||
),
|
||||
(route) => false,
|
||||
);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue