packages upgrade, static analysis migration

This commit is contained in:
Thibault Deckers 2021-06-25 21:38:56 +09:00
parent cdb676144c
commit 1841c60c09
162 changed files with 706 additions and 441 deletions

View file

@ -1,4 +1,4 @@
include: package:pedantic/analysis_options.yaml include: package:flutter_lints/flutter.yaml
analyzer: analyzer:
exclude: exclude:
@ -12,23 +12,21 @@ analyzer:
linter: linter:
rules: rules:
# from 'effective dart', excluded # from 'effective dart', excluded
avoid_classes_with_only_static_members: false # too strict
avoid_function_literals_in_foreach_calls: false # benefit? avoid_function_literals_in_foreach_calls: false # benefit?
lines_longer_than_80_chars: false # nope 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 # from 'effective dart', undecided
prefer_relative_imports: false # check IDE support (auto import, file move) prefer_relative_imports: false # check IDE support (auto import, file move)
public_member_api_docs: false # maybe?
# from 'effective dart', included # from 'effective dart', included
avoid_types_on_closure_parameters: true avoid_types_on_closure_parameters: true
constant_identifier_names: true
prefer_function_declarations_over_variables: true
prefer_interpolation_to_compose_strings: true prefer_interpolation_to_compose_strings: true
unnecessary_brace_in_string_interps: true
unnecessary_lambdas: true unnecessary_lambdas: true
# misc # from 'pedantic', included
prefer_const_constructors: true # should specify `const` as Dart does not build constants when using const constructors without it always_declare_return_types: true
prefer_const_constructors_in_immutables: true prefer_single_quotes: true
prefer_const_declarations: true sort_child_properties_last: true
unawaited_futures: true

View file

@ -64,6 +64,7 @@ class EmbeddedDataHandler(private val context: Context) : MethodCallHandler {
if (isSupportedByExifInterface(mimeType)) { if (isSupportedByExifInterface(mimeType)) {
try { try {
Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input -> Metadata.openSafeInputStream(context, uri, mimeType, sizeBytes)?.use { input ->
@Suppress("BlockingMethodInNonBlockingContext")
val exif = ExifInterface(input) val exif = ExifInterface(input)
val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL) val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL)
exif.thumbnailBitmap?.let { bitmap -> exif.thumbnailBitmap?.let { bitmap ->

View file

@ -67,6 +67,7 @@ class RegionFetcher internal constructor(
try { try {
if (currentDecoderRef == null) { if (currentDecoderRef == null) {
val newDecoder = StorageUtils.openInputStream(context, uri)?.use { input -> val newDecoder = StorageUtils.openInputStream(context, uri)?.use { input ->
@Suppress("BlockingMethodInNonBlockingContext")
BitmapRegionDecoder.newInstance(input, false) BitmapRegionDecoder.newInstance(input, false)
} }
if (newDecoder == null) { if (newDecoder == null) {

View file

@ -19,6 +19,7 @@ class TiffRegionFetcher internal constructor(
result: MethodChannel.Result, result: MethodChannel.Result,
) { ) {
try { try {
@Suppress("BlockingMethodInNonBlockingContext")
val fd = context.contentResolver.openFileDescriptor(uri, "r")?.detachFd() val fd = context.contentResolver.openFileDescriptor(uri, "r")?.detachFd()
if (fd == null) { if (fd == null) {
result.error("getRegion-tiff-fd", "failed to get file descriptor for uri=$uri", null) result.error("getRegion-tiff-fd", "failed to get file descriptor for uri=$uri", null)

View file

@ -129,6 +129,7 @@ class ImageByteStreamHandler(private val activity: Activity, private val argumen
.load(model) .load(model)
.submit() .submit()
try { try {
@Suppress("BlockingMethodInNonBlockingContext")
var bitmap = target.get() var bitmap = target.get()
if (needRotationAfterGlide(mimeType)) { if (needRotationAfterGlide(mimeType)) {
bitmap = applyExifOrientation(activity, bitmap, rotationDegrees, isFlipped) bitmap = applyExifOrientation(activity, bitmap, rotationDegrees, isFlipped)
@ -152,6 +153,7 @@ class ImageByteStreamHandler(private val activity: Activity, private val argumen
.load(VideoThumbnail(activity, uri)) .load(VideoThumbnail(activity, uri))
.submit() .submit()
try { try {
@Suppress("BlockingMethodInNonBlockingContext")
val bitmap = target.get() val bitmap = target.get()
if (bitmap != null) { if (bitmap != null) {
success(bitmap.getBytes(canHaveAlpha = false, recycle = false)) success(bitmap.getBytes(canHaveAlpha = false, recycle = false))

View file

@ -3,15 +3,15 @@ package deckers.thibault.aves.metadata
object TiffTags { object TiffTags {
// XPosition // XPosition
// Tag = 286 (011E.H) // Tag = 286 (011E.H)
const val TAG_X_POSITION = 0x011e private const val TAG_X_POSITION = 0x011e
// YPosition // YPosition
// Tag = 287 (011F.H) // Tag = 287 (011F.H)
const val TAG_Y_POSITION = 0x011f private const val TAG_Y_POSITION = 0x011f
// ColorMap // ColorMap
// Tag = 320 (0140.H) // Tag = 320 (0140.H)
const val TAG_COLOR_MAP = 0x0140 private const val TAG_COLOR_MAP = 0x0140
// ExtraSamples // ExtraSamples
// Tag = 338 (0152.H) // Tag = 338 (0152.H)
@ -19,7 +19,7 @@ object TiffTags {
// EXTRASAMPLE_UNSPECIFIED 0 // unspecified data // EXTRASAMPLE_UNSPECIFIED 0 // unspecified data
// EXTRASAMPLE_ASSOCALPHA 1 // associated alpha data // EXTRASAMPLE_ASSOCALPHA 1 // associated alpha data
// EXTRASAMPLE_UNASSALPHA 2 // unassociated alpha data // EXTRASAMPLE_UNASSALPHA 2 // unassociated alpha data
const val TAG_EXTRA_SAMPLES = 0x0152 private const val TAG_EXTRA_SAMPLES = 0x0152
// SampleFormat // SampleFormat
// Tag = 339 (0153.H) // Tag = 339 (0153.H)
@ -30,7 +30,7 @@ object TiffTags {
// SAMPLEFORMAT_VOID 4 // untyped data // SAMPLEFORMAT_VOID 4 // untyped data
// SAMPLEFORMAT_COMPLEXINT 5 // complex signed int // SAMPLEFORMAT_COMPLEXINT 5 // complex signed int
// SAMPLEFORMAT_COMPLEXIEEEFP 6 // complex ieee floating // SAMPLEFORMAT_COMPLEXIEEEFP 6 // complex ieee floating
const val TAG_SAMPLE_FORMAT = 0x0153 private const val TAG_SAMPLE_FORMAT = 0x0153
/* /*
SGI SGI
@ -40,7 +40,7 @@ object TiffTags {
// Matteing // Matteing
// Tag = 32995 (80E3.H) // Tag = 32995 (80E3.H)
// obsoleted by the 6.0 ExtraSamples (338) // obsoleted by the 6.0 ExtraSamples (338)
const val TAG_MATTEING = 0x80e3 private const val TAG_MATTEING = 0x80e3
/* /*
GeoTIFF GeoTIFF
@ -74,13 +74,13 @@ object TiffTags {
// Tag = 34736 (87BO.H) // Tag = 34736 (87BO.H)
// Type = DOUBLE // Type = DOUBLE
// Count = variable // Count = variable
const val TAG_GEO_DOUBLE_PARAMS = 0x87b0 private const val TAG_GEO_DOUBLE_PARAMS = 0x87b0
// GeoAsciiParamsTag (optional) // GeoAsciiParamsTag (optional)
// Tag = 34737 (87B1.H) // Tag = 34737 (87B1.H)
// Type = ASCII // Type = ASCII
// Count = variable // Count = variable
const val TAG_GEO_ASCII_PARAMS = 0x87b1 private const val TAG_GEO_ASCII_PARAMS = 0x87b1
/* /*
Photoshop Photoshop
@ -91,7 +91,7 @@ object TiffTags {
// ImageSourceData // ImageSourceData
// Tag = 37724 (935C.H) // Tag = 37724 (935C.H)
// Type = UNDEFINED // Type = UNDEFINED
const val TAG_IMAGE_SOURCE_DATA = 0x935c private const val TAG_IMAGE_SOURCE_DATA = 0x935c
/* /*
DNG DNG
@ -102,13 +102,13 @@ object TiffTags {
// Tag = 50735 (C62F.H) // Tag = 50735 (C62F.H)
// Type = ASCII // Type = ASCII
// Count = variable // Count = variable
const val TAG_CAMERA_SERIAL_NUMBER = 0xc62f private const val TAG_CAMERA_SERIAL_NUMBER = 0xc62f
// OriginalRawFileName (optional) // OriginalRawFileName (optional)
// Tag = 50827 (C68B.H) // Tag = 50827 (C68B.H)
// Type = ASCII or BYTE // Type = ASCII or BYTE
// Count = variable // Count = variable
const val TAG_ORIGINAL_RAW_FILE_NAME = 0xc68b private const val TAG_ORIGINAL_RAW_FILE_NAME = 0xc68b
private val geotiffTags = listOf( private val geotiffTags = listOf(
TAG_GEO_ASCII_PARAMS, TAG_GEO_ASCII_PARAMS,

View file

@ -6,13 +6,13 @@ import deckers.thibault.aves.model.SourceEntry
import java.io.File import java.io.File
internal class FileImageProvider : ImageProvider() { internal class FileImageProvider : ImageProvider() {
override fun fetchSingle(context: Context, uri: Uri, mimeType: String?, callback: ImageOpCallback) { override fun fetchSingle(context: Context, uri: Uri, sourceMimeType: String?, callback: ImageOpCallback) {
if (mimeType == null) { if (sourceMimeType == null) {
callback.onFailure(Exception("MIME type is null for uri=$uri")) callback.onFailure(Exception("MIME type is null for uri=$uri"))
return return
} }
val entry = SourceEntry(uri, mimeType) val entry = SourceEntry(uri, sourceMimeType)
val path = uri.path val path = uri.path
if (path != null) { if (path != null) {

View file

@ -39,7 +39,7 @@ import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine import kotlin.coroutines.suspendCoroutine
abstract class ImageProvider { 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()) callback.onFailure(UnsupportedOperationException())
} }

View file

@ -38,7 +38,7 @@ class MediaStoreImageProvider : ImageProvider() {
fetchFrom(context, isModified, handleNewEntry, VIDEO_CONTENT_URI, VIDEO_PROJECTION) 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 id = uri.tryParseId()
val onSuccess = fun(entry: FieldMap) { val onSuccess = fun(entry: FieldMap) {
entry["uri"] = uri.toString() entry["uri"] = uri.toString()
@ -46,11 +46,11 @@ class MediaStoreImageProvider : ImageProvider() {
} }
val alwaysValid = { _: Int, _: Int -> true } val alwaysValid = { _: Int, _: Int -> true }
if (id != null) { if (id != null) {
if (mimeType == null || isImage(mimeType)) { if (sourceMimeType == null || isImage(sourceMimeType)) {
val contentUri = ContentUris.withAppendedId(IMAGE_CONTENT_URI, id) val contentUri = ContentUris.withAppendedId(IMAGE_CONTENT_URI, id)
if (fetchFrom(context, alwaysValid, onSuccess, contentUri, IMAGE_PROJECTION)) return 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) val contentUri = ContentUris.withAppendedId(VIDEO_CONTENT_URI, id)
if (fetchFrom(context, alwaysValid, onSuccess, contentUri, VIDEO_PROJECTION)) return 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") // 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 // without an equivalent image/video if it is shared from a file browser
// but the file is not publicly visible // 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")) callback.onFailure(Exception("failed to fetch entry at uri=$uri"))
} }

View file

@ -11,7 +11,7 @@ object BmpWriter {
private val pad = ByteArray(3) private val pad = ByteArray(3)
// file header // 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 bfReserved1 = intToWord(0)
private val bfReserved2 = intToWord(0) private val bfReserved2 = intToWord(0)
private val bfOffBits = intToDWord(FILE_HEADER_SIZE + INFO_HEADER_SIZE) private val bfOffBits = intToDWord(FILE_HEADER_SIZE + INFO_HEADER_SIZE)

View file

@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = '1.5.10' ext.kotlin_version = '1.5.20'
repositories { repositories {
google() google()
mavenCentral() mavenCentral()
@ -9,7 +9,7 @@ buildscript {
classpath 'com.android.tools.build:gradle:4.2.1' classpath 'com.android.tools.build:gradle:4.2.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.8' 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'
} }
} }

View file

@ -2,9 +2,9 @@ import 'dart:async';
import 'dart:ui' as ui show Codec; import 'dart:ui' as ui show Codec;
import 'package:aves/services/services.dart'; import 'package:aves/services/services.dart';
import 'package:aves/utils/pedantic.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:pedantic/pedantic.dart';
class UriImage extends ImageProvider<UriImage> { class UriImage extends ImageProvider<UriImage> {
final String uri, mimeType; final String uri, mimeType;

View file

@ -13,7 +13,7 @@ class UriPicture extends PictureProvider<UriPicture> {
final String uri, mimeType; final String uri, mimeType;
@override @override
Future<UriPicture> obtainKey(PictureConfiguration configuration) { Future<UriPicture> obtainKey(PictureConfiguration picture) {
return SynchronousFuture<UriPicture>(this); return SynchronousFuture<UriPicture>(this);
} }

View file

@ -29,5 +29,5 @@ void main() {
); );
}).sendPort); }).sendPort);
runApp(AvesApp()); runApp(const AvesApp());
} }

View file

@ -62,7 +62,7 @@ class LocationFilter extends CollectionFilter {
if (flag != null) { if (flag != null) {
return Text( return Text(
flag, flag,
style: TextStyle(fontSize: size, shadows: []), style: TextStyle(fontSize: size, shadows: const []),
textScaleFactor: 1.0, textScaleFactor: 1.0,
); );
} }

View file

@ -139,11 +139,10 @@ class OverlayMetadata {
OverlayMetadata({ OverlayMetadata({
double? aperture, double? aperture,
String? exposureTime, this.exposureTime,
double? focalLength, double? focalLength,
int? iso, int? iso,
}) : aperture = aperture != null ? 'ƒ/${apertureFormat.format(aperture)}' : null, }) : aperture = aperture != null ? 'ƒ/${apertureFormat.format(aperture)}' : null,
exposureTime = exposureTime,
focalLength = focalLength != null ? '${focalLengthFormat.format(focalLength)} mm' : null, focalLength = focalLength != null ? '${focalLengthFormat.format(focalLength)} mm' : null,
iso = iso != null ? 'ISO$iso' : null; iso = iso != null ? 'ISO$iso' : null;

View file

@ -4,13 +4,13 @@ import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/settings/enums.dart'; import 'package:aves/model/settings/enums.dart';
import 'package:aves/model/settings/screen_on.dart'; import 'package:aves/model/settings/screen_on.dart';
import 'package:aves/model/source/enums.dart'; import 'package:aves/model/source/enums.dart';
import 'package:aves/utils/pedantic.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:firebase_analytics/firebase_analytics.dart'; import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:pedantic/pedantic.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
final Settings settings = Settings._private(); final Settings settings = Settings._private();

View file

@ -1,5 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
// ignore: import_of_legacy_library_into_null_safe // ignore: import_of_legacy_library_into_null_safe
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart'; import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';

View file

@ -254,6 +254,12 @@ class Constants {
licenseUrl: 'https://github.com/marcojakob/dart-event-bus/blob/master/LICENSE', licenseUrl: 'https://github.com/marcojakob/dart-event-bus/blob/master/LICENSE',
sourceUrl: 'https://github.com/marcojakob/dart-event-bus', 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( Dependency(
name: 'Get It', name: 'Get It',
license: 'MIT', license: 'MIT',
@ -284,12 +290,6 @@ class Constants {
licenseUrl: 'https://github.com/DavBfr/dart_pdf/blob/master/LICENSE', licenseUrl: 'https://github.com/DavBfr/dart_pdf/blob/master/LICENSE',
sourceUrl: 'https://github.com/DavBfr/dart_pdf', 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( Dependency(
name: 'Tuple', name: 'Tuple',
license: 'BSD 2-Clause', license: 'BSD 2-Clause',

2
lib/utils/pedantic.dart Normal file
View file

@ -0,0 +1,2 @@
// cf https://github.com/google/pedantic/blob/master/lib/pedantic.dart
void unawaited(Future<void>? future) {}

View file

@ -8,6 +8,8 @@ import 'package:flutter/material.dart';
class AboutPage extends StatelessWidget { class AboutPage extends StatelessWidget {
static const routeName = '/about'; static const routeName = '/about';
const AboutPage({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -21,17 +23,17 @@ class AboutPage extends StatelessWidget {
padding: const EdgeInsets.only(top: 16), padding: const EdgeInsets.only(top: 16),
sliver: SliverList( sliver: SliverList(
delegate: SliverChildListDelegate( delegate: SliverChildListDelegate(
[ const [
AppReference(), AppReference(),
const Divider(), Divider(),
AboutUpdate(), AboutUpdate(),
AboutCredits(), AboutCredits(),
const Divider(), Divider(),
], ],
), ),
), ),
), ),
Licenses(), const Licenses(),
], ],
), ),
), ),

View file

@ -8,6 +8,8 @@ import 'package:flutter/material.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
class AppReference extends StatefulWidget { class AppReference extends StatefulWidget {
const AppReference({Key? key}) : super(key: key);
@override @override
_AppReferenceState createState() => _AppReferenceState(); _AppReferenceState createState() => _AppReferenceState();
} }

View file

@ -6,6 +6,8 @@ import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class AboutCredits extends StatelessWidget { class AboutCredits extends StatelessWidget {
const AboutCredits({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( return Padding(

View file

@ -7,6 +7,8 @@ import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class Licenses extends StatefulWidget { class Licenses extends StatefulWidget {
const Licenses({Key? key}) : super(key: key);
@override @override
_LicensesState createState() => _LicensesState(); _LicensesState createState() => _LicensesState();
} }
@ -46,25 +48,25 @@ class _LicensesState extends State<Licenses> {
title: context.l10n.aboutLicensesAndroidLibraries, title: context.l10n.aboutLicensesAndroidLibraries,
color: BrandColors.android, color: BrandColors.android,
expandedNotifier: _expandedNotifier, expandedNotifier: _expandedNotifier,
children: _platform.map((package) => LicenseRow(package)).toList(), children: _platform.map((package) => LicenseRow(package: package)).toList(),
), ),
AvesExpansionTile( AvesExpansionTile(
title: context.l10n.aboutLicensesFlutterPlugins, title: context.l10n.aboutLicensesFlutterPlugins,
color: BrandColors.flutter, color: BrandColors.flutter,
expandedNotifier: _expandedNotifier, expandedNotifier: _expandedNotifier,
children: _flutterPlugins.map((package) => LicenseRow(package)).toList(), children: _flutterPlugins.map((package) => LicenseRow(package: package)).toList(),
), ),
AvesExpansionTile( AvesExpansionTile(
title: context.l10n.aboutLicensesFlutterPackages, title: context.l10n.aboutLicensesFlutterPackages,
color: BrandColors.flutter, color: BrandColors.flutter,
expandedNotifier: _expandedNotifier, expandedNotifier: _expandedNotifier,
children: _flutterPackages.map((package) => LicenseRow(package)).toList(), children: _flutterPackages.map((package) => LicenseRow(package: package)).toList(),
), ),
AvesExpansionTile( AvesExpansionTile(
title: context.l10n.aboutLicensesDartPackages, title: context.l10n.aboutLicensesDartPackages,
color: BrandColors.flutter, color: BrandColors.flutter,
expandedNotifier: _expandedNotifier, expandedNotifier: _expandedNotifier,
children: _dartPackages.map((package) => LicenseRow(package)).toList(), children: _dartPackages.map((package) => LicenseRow(package: package)).toList(),
), ),
Center( Center(
child: TextButton( child: TextButton(
@ -113,7 +115,10 @@ class _LicensesState extends State<Licenses> {
class LicenseRow extends StatelessWidget { class LicenseRow extends StatelessWidget {
final Dependency package; final Dependency package;
const LicenseRow(this.package); const LicenseRow({
Key? key,
required this.package,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class AboutNewsBadge extends StatelessWidget { class AboutNewsBadge extends StatelessWidget {
const AboutNewsBadge(); const AboutNewsBadge({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -6,6 +6,8 @@ import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class AboutUpdate extends StatefulWidget { class AboutUpdate extends StatefulWidget {
const AboutUpdate({Key? key}) : super(key: key);
@override @override
_AboutUpdateState createState() => _AboutUpdateState(); _AboutUpdateState createState() => _AboutUpdateState();
} }

View file

@ -27,6 +27,8 @@ import 'package:overlay_support/overlay_support.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class AvesApp extends StatefulWidget { class AvesApp extends StatefulWidget {
const AvesApp({Key? key}) : super(key: key);
@override @override
_AvesAppState createState() => _AvesAppState(); _AvesAppState createState() => _AvesAppState();
} }
@ -88,7 +90,7 @@ class _AvesAppState extends State<AvesApp> {
darkTheme: Themes.darkTheme, darkTheme: Themes.darkTheme,
themeMode: ThemeMode.dark, themeMode: ThemeMode.dark,
locale: settingsLocale, locale: settingsLocale,
localizationsDelegates: [ localizationsDelegates: const [
...AppLocalizations.localizationsDelegates, ...AppLocalizations.localizationsDelegates,
], ],
supportedLocales: AppLocalizations.supportedLocales, supportedLocales: AppLocalizations.supportedLocales,

View file

@ -12,6 +12,7 @@ import 'package:aves/model/source/enums.dart';
import 'package:aves/services/app_shortcut_service.dart'; import 'package:aves/services/app_shortcut_service.dart';
import 'package:aves/theme/durations.dart'; import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.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/entry_set_action_delegate.dart';
import 'package:aves/widgets/collection/filter_bar.dart'; import 'package:aves/widgets/collection/filter_bar.dart';
import 'package:aves/widgets/common/app_bar_subtitle.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/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
import 'package:pedantic/pedantic.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:tuple/tuple.dart'; import 'package:tuple/tuple.dart';
@ -175,7 +175,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
return [ return [
if (collection.isBrowsing && appMode.canSearch) if (collection.isBrowsing && appMode.canSearch)
CollectionSearchButton( CollectionSearchButton(
source, source: source,
parentCollection: collection, parentCollection: collection,
), ),
if (collection.isSelecting) if (collection.isSelecting)
@ -349,7 +349,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
Future<void> _showShortcutDialog(BuildContext context) async { Future<void> _showShortcutDialog(BuildContext context) async {
final filters = collection.filters; final filters = collection.filters;
var defaultName; String? defaultName;
if (filters.isNotEmpty) { if (filters.isNotEmpty) {
// we compute the default name beforehand // we compute the default name beforehand
// because some filter labels need localization // because some filter labels need localization

View file

@ -324,8 +324,8 @@ class _CollectionScrollViewState extends State<_CollectionScrollView> {
hasScrollBody: false, hasScrollBody: false,
child: _buildEmptyCollectionPlaceholder(collection), child: _buildEmptyCollectionPlaceholder(collection),
) )
: SectionedListSliver<AvesEntry>(), : const SectionedListSliver<AvesEntry>(),
BottomPaddingSliver(), const BottomPaddingSliver(),
], ],
); );
} }

View file

@ -13,7 +13,10 @@ class CollectionPage extends StatefulWidget {
final CollectionLens collection; final CollectionLens collection;
const CollectionPage(this.collection); const CollectionPage({
Key? key,
required this.collection,
}) : super(key: key);
@override @override
_CollectionPageState createState() => _CollectionPageState(); _CollectionPageState createState() => _CollectionPageState();
@ -54,7 +57,7 @@ class _CollectionPageState extends State<CollectionPage> {
), ),
), ),
), ),
drawer: AppDrawer(), drawer: const AppDrawer(),
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
), ),
); );

View file

@ -13,9 +13,10 @@ class CollectionDraggableThumbLabel extends StatelessWidget {
final double offsetY; final double offsetY;
const CollectionDraggableThumbLabel({ const CollectionDraggableThumbLabel({
Key? key,
required this.collection, required this.collection,
required this.offsetY, required this.offsetY,
}); }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -11,6 +11,7 @@ import 'package:aves/services/image_op_events.dart';
import 'package:aves/services/services.dart'; import 'package:aves/services/services.dart';
import 'package:aves/theme/durations.dart'; import 'package:aves/theme/durations.dart';
import 'package:aves/utils/android_file_utils.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/collection/collection_page.dart';
import 'package:aves/widgets/common/action_mixins/feedback.dart'; import 'package:aves/widgets/common/action_mixins/feedback.dart';
import 'package:aves/widgets/common/action_mixins/permission_aware.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:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:pedantic/pedantic.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMixin { class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMixin {
@ -155,11 +155,9 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
context, context,
MaterialPageRoute( MaterialPageRoute(
settings: const RouteSettings(name: CollectionPage.routeName), settings: const RouteSettings(name: CollectionPage.routeName),
builder: (context) { builder: (context) => CollectionPage(
return CollectionPage( collection: targetCollection,
targetCollection, ),
);
},
), ),
)); ));
await Future.delayed(Durations.staggeredAnimationPageTarget); await Future.delayed(Durations.staggeredAnimationPageTarget);

View file

@ -9,6 +9,7 @@ class SectionedEntryListLayoutProvider extends SectionedListLayoutProvider<AvesE
final CollectionLens collection; final CollectionLens collection;
const SectionedEntryListLayoutProvider({ const SectionedEntryListLayoutProvider({
Key? key,
required this.collection, required this.collection,
required double scrollableWidth, required double scrollableWidth,
required int columnCount, required int columnCount,
@ -18,6 +19,7 @@ class SectionedEntryListLayoutProvider extends SectionedListLayoutProvider<AvesE
required Duration tileAnimationDelay, required Duration tileAnimationDelay,
required Widget child, required Widget child,
}) : super( }) : super(
key: key,
scrollableWidth: scrollableWidth, scrollableWidth: scrollableWidth,
columnCount: columnCount, columnCount: columnCount,
spacing: spacing, spacing: spacing,

View file

@ -18,12 +18,13 @@ class GridSelectionGestureDetector extends StatefulWidget {
final Widget child; final Widget child;
const GridSelectionGestureDetector({ const GridSelectionGestureDetector({
Key? key,
this.selectable = true, this.selectable = true,
required this.collection, required this.collection,
required this.scrollController, required this.scrollController,
required this.appBarHeightNotifier, required this.appBarHeightNotifier,
required this.child, required this.child,
}); }) : super(key: key);
@override @override
_GridSelectionGestureDetectorState createState() => _GridSelectionGestureDetectorState(); _GridSelectionGestureDetectorState createState() => _GridSelectionGestureDetectorState();

View file

@ -13,10 +13,11 @@ class ErrorThumbnail extends StatefulWidget {
final String tooltip; final String tooltip;
const ErrorThumbnail({ const ErrorThumbnail({
Key? key,
required this.entry, required this.entry,
required this.extent, required this.extent,
required this.tooltip, required this.tooltip,
}); }) : super(key: key);
@override @override
_ErrorThumbnailState createState() => _ErrorThumbnailState(); _ErrorThumbnailState createState() => _ErrorThumbnailState();

View file

@ -10,10 +10,11 @@ class ThumbnailTheme extends StatelessWidget {
final Widget child; final Widget child;
const ThumbnailTheme({ const ThumbnailTheme({
Key? key,
required this.extent, required this.extent,
this.showLocation, this.showLocation,
required this.child, required this.child,
}); }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -50,10 +50,11 @@ class ReportOverlay<T> extends StatefulWidget {
final void Function(Set<T> processed) onDone; final void Function(Set<T> processed) onDone;
const ReportOverlay({ const ReportOverlay({
Key? key,
required this.opStream, required this.opStream,
required this.itemCount, required this.itemCount,
required this.onDone, required this.onDone,
}); }) : super(key: key);
@override @override
_ReportOverlayState createState() => _ReportOverlayState<T>(); _ReportOverlayState createState() => _ReportOverlayState<T>();

View file

@ -49,7 +49,10 @@ class SourceStateAwareAppBarTitle extends StatelessWidget {
class SourceStateSubtitle extends StatelessWidget { class SourceStateSubtitle extends StatelessWidget {
final CollectionSource source; final CollectionSource source;
const SourceStateSubtitle({required this.source}); const SourceStateSubtitle({
Key? key,
required this.source,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -5,9 +5,10 @@ class InteractiveAppBarTitle extends StatelessWidget {
final Widget child; final Widget child;
const InteractiveAppBarTitle({ const InteractiveAppBarTitle({
Key? key,
this.onTap, this.onTap,
required this.child, required this.child,
}); }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -29,14 +29,16 @@ class AvesHighlightView extends StatelessWidget {
/// Specify text styles such as font family and font size /// Specify text styles such as font family and font size
final TextStyle? textStyle; final TextStyle? textStyle;
AvesHighlightView( AvesHighlightView({
String input, { Key? key,
required String input,
this.language, this.language,
this.theme = const {}, this.theme = const {},
this.padding, this.padding,
this.textStyle, this.textStyle,
int tabSize = 8, // TODO: https://github.com/flutter/flutter/issues/50087 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) { List<TextSpan> _convert(List<Node> nodes) {
final spans = <TextSpan>[]; final spans = <TextSpan>[];

View file

@ -7,6 +7,8 @@ import 'package:provider/provider.dart';
// - a vertically scrollable body. // - a vertically scrollable body.
// It will prevent the body from scrolling when a user swipe from bottom to use Android Q style navigation gestures. // It will prevent the body from scrolling when a user swipe from bottom to use Android Q style navigation gestures.
class BottomGestureAreaProtector extends StatelessWidget { class BottomGestureAreaProtector extends StatelessWidget {
const BottomGestureAreaProtector({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Selector<MediaQueryData, double>( return Selector<MediaQueryData, double>(
@ -27,20 +29,25 @@ class BottomGestureAreaProtector extends StatelessWidget {
class GestureAreaProtectorStack extends StatelessWidget { class GestureAreaProtectorStack extends StatelessWidget {
final Widget child; final Widget child;
const GestureAreaProtectorStack({required this.child}); const GestureAreaProtectorStack({
Key? key,
required this.child,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Stack( return Stack(
children: [ children: [
child, child,
BottomGestureAreaProtector(), const BottomGestureAreaProtector(),
], ],
); );
} }
} }
class BottomPaddingSliver extends StatelessWidget { class BottomPaddingSliver extends StatelessWidget {
const BottomPaddingSliver({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SliverToBoxAdapter( return SliverToBoxAdapter(

View file

@ -7,12 +7,13 @@ class MultiCrossFader extends StatefulWidget {
final Widget child; final Widget child;
const MultiCrossFader({ const MultiCrossFader({
Key? key,
required this.duration, required this.duration,
this.fadeCurve = Curves.linear, this.fadeCurve = Curves.linear,
this.sizeCurve = Curves.linear, this.sizeCurve = Curves.linear,
this.alignment = Alignment.topCenter, this.alignment = Alignment.topCenter,
required this.child, required this.child,
}); }) : super(key: key);
@override @override
_MultiCrossFaderState createState() => _MultiCrossFaderState(); _MultiCrossFaderState createState() => _MultiCrossFaderState();

View file

@ -9,7 +9,10 @@ import 'package:flutter/widgets.dart';
class QueryBar extends StatefulWidget { class QueryBar extends StatefulWidget {
final ValueNotifier<String> filterNotifier; final ValueNotifier<String> filterNotifier;
const QueryBar({required this.filterNotifier}); const QueryBar({
Key? key,
required this.filterNotifier,
}) : super(key: key);
@override @override
_QueryBarState createState() => _QueryBarState(); _QueryBarState createState() => _QueryBarState();

View file

@ -12,8 +12,9 @@ class DoubleBackPopScope extends StatefulWidget {
final Widget child; final Widget child;
const DoubleBackPopScope({ const DoubleBackPopScope({
Key? key,
required this.child, required this.child,
}); }) : super(key: key);
@override @override
_DoubleBackPopScopeState createState() => _DoubleBackPopScopeState(); _DoubleBackPopScopeState createState() => _DoubleBackPopScopeState();

View file

@ -1,9 +1,9 @@
import 'dart:math'; import 'dart:math';
import 'package:aves/theme/durations.dart'; import 'package:aves/theme/durations.dart';
import 'package:aves/utils/pedantic.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart'; import 'package:flutter/scheduler.dart';
import 'package:pedantic/pedantic.dart';
class Sweeper extends StatefulWidget { class Sweeper extends StatefulWidget {
final WidgetBuilder builder; final WidgetBuilder builder;

View file

@ -15,11 +15,12 @@ class TransitionImage extends StatefulWidget {
final bool gaplessPlayback = false; final bool gaplessPlayback = false;
const TransitionImage({ const TransitionImage({
Key? key,
required this.image, required this.image,
required this.animation, required this.animation,
this.width, this.width,
this.height, this.height,
}); }) : super(key: key);
@override @override
_TransitionImageState createState() => _TransitionImageState(); _TransitionImageState createState() => _TransitionImageState();

View file

@ -9,9 +9,10 @@ class DraggableThumbLabel<T> extends StatelessWidget {
final List<String> Function(BuildContext context, T item) lineBuilder; final List<String> Function(BuildContext context, T item) lineBuilder;
const DraggableThumbLabel({ const DraggableThumbLabel({
Key? key,
required this.offsetY, required this.offsetY,
required this.lineBuilder, required this.lineBuilder,
}); }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -103,10 +103,11 @@ class SectionHeader extends StatelessWidget {
// as of Flutter v1.22.3, `RenderParagraph` fails to lay out `WidgetSpan` offscreen // 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 // so we use a hair space times a magic number to match width
TextSpan( TextSpan(
// 23 hair spaces match a width of 40.0
text: '\u200A' * (hasLeading ? 23 : 1), text: '\u200A' * (hasLeading ? 23 : 1),
// force a higher first line to match leading icon/selector dimension // force a higher first line to match leading icon/selector dimension
style: TextStyle(height: 2.3 * textScaleFactor), style: TextStyle(height: 2.3 * textScaleFactor),
), // 23 hair spaces match a width of 40.0 ),
if (hasTrailing) TextSpan(text: '\u200A' * 17), if (hasTrailing) TextSpan(text: '\u200A' * 17),
TextSpan( TextSpan(
text: title, text: title,

View file

@ -18,6 +18,7 @@ abstract class SectionedListLayoutProvider<T> extends StatelessWidget {
final Widget child; final Widget child;
const SectionedListLayoutProvider({ const SectionedListLayoutProvider({
Key? key,
required this.scrollableWidth, required this.scrollableWidth,
required this.columnCount, required this.columnCount,
required this.spacing, required this.spacing,
@ -25,7 +26,8 @@ abstract class SectionedListLayoutProvider<T> extends StatelessWidget {
required this.tileBuilder, required this.tileBuilder,
required this.tileAnimationDelay, required this.tileAnimationDelay,
required this.child, required this.child,
}) : assert(scrollableWidth != 0); }) : assert(scrollableWidth != 0),
super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -14,6 +14,8 @@ import 'package:provider/provider.dart';
// cf https://github.com/flutter/flutter/issues/49027 // cf https://github.com/flutter/flutter/issues/49027
// adapted from `RenderSliverFixedExtentBoxAdaptor` // adapted from `RenderSliverFixedExtentBoxAdaptor`
class SectionedListSliver<T> extends StatelessWidget { class SectionedListSliver<T> extends StatelessWidget {
const SectionedListSliver({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final sectionLayouts = context.watch<SectionedListLayout<T>>().sectionLayouts; final sectionLayouts = context.watch<SectionedListLayout<T>>().sectionLayouts;

View file

@ -12,6 +12,7 @@ class AvesExpansionTile extends StatelessWidget {
final List<Widget> children; final List<Widget> children;
const AvesExpansionTile({ const AvesExpansionTile({
Key? key,
String? value, String? value,
this.leading, this.leading,
required this.title, required this.title,
@ -20,13 +21,14 @@ class AvesExpansionTile extends StatelessWidget {
this.initiallyExpanded = false, this.initiallyExpanded = false,
this.showHighlight = true, this.showHighlight = true,
required this.children, required this.children,
}) : value = value ?? title; }) : value = value ?? title,
super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final enabled = children.isNotEmpty == true; final enabled = children.isNotEmpty == true;
Widget titleChild = HighlightTitle( Widget titleChild = HighlightTitle(
title, title: title,
color: color, color: color,
enabled: enabled, enabled: enabled,
showHighlight: showHighlight, showHighlight: showHighlight,

View file

@ -4,7 +4,10 @@ import 'package:flutter_svg/flutter_svg.dart';
class AvesLogo extends StatelessWidget { class AvesLogo extends StatelessWidget {
final double size; final double size;
const AvesLogo({required this.size}); const AvesLogo({
Key? key,
required this.size,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -6,10 +6,11 @@ class EmptyContent extends StatelessWidget {
final AlignmentGeometry alignment; final AlignmentGeometry alignment;
const EmptyContent({ const EmptyContent({
Key? key,
this.icon, this.icon,
required this.text, required this.text,
this.alignment = const FractionalOffset(.5, .35), this.alignment = const FractionalOffset(.5, .35),
}); }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -11,14 +11,15 @@ class HighlightTitle extends StatelessWidget {
final bool enabled, selectable; final bool enabled, selectable;
final bool showHighlight; final bool showHighlight;
const HighlightTitle( const HighlightTitle({
this.title, { Key? key,
required this.title,
this.color, this.color,
this.fontSize = 18, this.fontSize = 18,
this.enabled = true, this.enabled = true,
this.selectable = false, this.selectable = false,
this.showHighlight = true, this.showHighlight = true,
}); }) : super(key: key);
static const disabledColor = Colors.grey; static const disabledColor = Colors.grey;

View file

@ -96,7 +96,7 @@ class MagnifierGestureRecognizer extends ScaleGestureRecognizer {
} }
void _decideIfWeAcceptEvent(PointerEvent event) { void _decideIfWeAcceptEvent(PointerEvent event) {
if (!(event is PointerMoveEvent)) return; if (event is! PointerMoveEvent) return;
if (_pointerLocations.keys.length >= 2) { if (_pointerLocations.keys.length >= 2) {
// when there are multiple pointers, we always accept the gesture to scale // when there are multiple pointers, we always accept the gesture to scale

View file

@ -8,10 +8,11 @@ import 'package:flutter/widgets.dart';
/// such as [PageView], [Dismissible], [BottomSheet]. /// such as [PageView], [Dismissible], [BottomSheet].
class MagnifierGestureDetectorScope extends InheritedWidget { class MagnifierGestureDetectorScope extends InheritedWidget {
const MagnifierGestureDetectorScope({ const MagnifierGestureDetectorScope({
Key? key,
required this.axis, required this.axis,
this.touchSlopFactor = .8, this.touchSlopFactor = .8,
required Widget child, required Widget child,
}) : super(child: child); }) : super(key: key, child: child);
static MagnifierGestureDetectorScope? of(BuildContext context) { static MagnifierGestureDetectorScope? of(BuildContext context) {
final scope = context.dependOnInheritedWidgetOfExactType<MagnifierGestureDetectorScope>(); final scope = context.dependOnInheritedWidgetOfExactType<MagnifierGestureDetectorScope>();

View file

@ -5,7 +5,10 @@ import 'package:provider/provider.dart';
class HighlightInfoProvider extends StatelessWidget { class HighlightInfoProvider extends StatelessWidget {
final Widget child; final Widget child;
const HighlightInfoProvider({required this.child}); const HighlightInfoProvider({
Key? key,
required this.child,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -4,7 +4,10 @@ import 'package:provider/provider.dart';
class MediaQueryDataProvider extends StatelessWidget { class MediaQueryDataProvider extends StatelessWidget {
final Widget child; final Widget child;
const MediaQueryDataProvider({required this.child}); const MediaQueryDataProvider({
Key? key,
required this.child,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -7,9 +7,10 @@ class TileExtentControllerProvider extends StatelessWidget {
final Widget child; final Widget child;
const TileExtentControllerProvider({ const TileExtentControllerProvider({
Key? key,
required this.controller, required this.controller,
required this.child, required this.child,
}); }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -24,12 +24,13 @@ class GridScaleGestureDetector<T> extends StatefulWidget {
final Widget child; final Widget child;
const GridScaleGestureDetector({ const GridScaleGestureDetector({
Key? key,
required this.scrollableKey, required this.scrollableKey,
required this.gridBuilder, required this.gridBuilder,
required this.scaledBuilder, required this.scaledBuilder,
this.highlightItem, this.highlightItem,
required this.child, required this.child,
}); }) : super(key: key);
@override @override
_GridScaleGestureDetectorState createState() => _GridScaleGestureDetectorState<T>(); _GridScaleGestureDetectorState createState() => _GridScaleGestureDetectorState<T>();
@ -140,12 +141,13 @@ class ScaleOverlay extends StatefulWidget {
final Widget Function(Offset center, double extent, Widget child) gridBuilder; final Widget Function(Offset center, double extent, Widget child) gridBuilder;
const ScaleOverlay({ const ScaleOverlay({
Key? key,
required this.builder, required this.builder,
required this.center, required this.center,
required this.viewportWidth, required this.viewportWidth,
required this.scaledExtentNotifier, required this.scaledExtentNotifier,
required this.gridBuilder, required this.gridBuilder,
}); }) : super(key: key);
@override @override
_ScaleOverlayState createState() => _ScaleOverlayState(); _ScaleOverlayState createState() => _ScaleOverlayState();
@ -175,7 +177,7 @@ class _ScaleOverlayState extends State<ScaleOverlay> {
gradient: RadialGradient( gradient: RadialGradient(
center: FractionalOffset.fromOffsetAndSize(center, context.select<MediaQueryData, Size>((mq) => mq.size)), center: FractionalOffset.fromOffsetAndSize(center, context.select<MediaQueryData, Size>((mq) => mq.size)),
radius: 1, radius: 1,
colors: [ colors: const [
Colors.black, Colors.black,
Colors.black54, Colors.black54,
], ],

View file

@ -7,6 +7,8 @@ import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class DebugAndroidAppSection extends StatefulWidget { class DebugAndroidAppSection extends StatefulWidget {
const DebugAndroidAppSection({Key? key}) : super(key: key);
@override @override
_DebugAndroidAppSectionState createState() => _DebugAndroidAppSectionState(); _DebugAndroidAppSectionState createState() => _DebugAndroidAppSectionState();
} }

View file

@ -6,6 +6,8 @@ import 'package:aves/widgets/viewer/info/common.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class DebugAndroidDirSection extends StatefulWidget { class DebugAndroidDirSection extends StatefulWidget {
const DebugAndroidDirSection({Key? key}) : super(key: key);
@override @override
_DebugAndroidDirSectionState createState() => _DebugAndroidDirSectionState(); _DebugAndroidDirSectionState createState() => _DebugAndroidDirSectionState();
} }
@ -34,7 +36,7 @@ class _DebugAndroidDirSectionState extends State<DebugAndroidDirSection> with Au
if (snapshot.hasError) return Text(snapshot.error.toString()); if (snapshot.hasError) return Text(snapshot.error.toString());
if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink(); if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
final data = SplayTreeMap.of(snapshot.data!.map((k, v) => MapEntry(k.toString(), v?.toString() ?? 'null'))); final data = SplayTreeMap.of(snapshot.data!.map((k, v) => MapEntry(k.toString(), v?.toString() ?? 'null')));
return InfoRowGroup(data); return InfoRowGroup(info: data);
}, },
), ),
), ),

View file

@ -6,6 +6,8 @@ import 'package:aves/widgets/viewer/info/common.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class DebugAndroidEnvironmentSection extends StatefulWidget { class DebugAndroidEnvironmentSection extends StatefulWidget {
const DebugAndroidEnvironmentSection({Key? key}) : super(key: key);
@override @override
_DebugAndroidEnvironmentSectionState createState() => _DebugAndroidEnvironmentSectionState(); _DebugAndroidEnvironmentSectionState createState() => _DebugAndroidEnvironmentSectionState();
} }
@ -34,7 +36,7 @@ class _DebugAndroidEnvironmentSectionState extends State<DebugAndroidEnvironment
if (snapshot.hasError) return Text(snapshot.error.toString()); if (snapshot.hasError) return Text(snapshot.error.toString());
if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink(); if (snapshot.connectionState != ConnectionState.done) return const SizedBox.shrink();
final data = SplayTreeMap.of(snapshot.data!.map((k, v) => MapEntry(k.toString(), v?.toString() ?? 'null'))); final data = SplayTreeMap.of(snapshot.data!.map((k, v) => MapEntry(k.toString(), v?.toString() ?? 'null')));
return InfoRowGroup(data); return InfoRowGroup(info: data);
}, },
), ),
), ),

View file

@ -19,6 +19,8 @@ import 'package:provider/provider.dart';
class AppDebugPage extends StatefulWidget { class AppDebugPage extends StatefulWidget {
static const routeName = '/debug'; static const routeName = '/debug';
const AppDebugPage({Key? key}) : super(key: key);
@override @override
State<StatefulWidget> createState() => _AppDebugPageState(); State<StatefulWidget> createState() => _AppDebugPageState();
} }
@ -42,14 +44,14 @@ class _AppDebugPageState extends State<AppDebugPage> {
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(8),
children: [ children: [
_buildGeneralTabView(), _buildGeneralTabView(),
DebugAndroidAppSection(), const DebugAndroidAppSection(),
DebugAndroidDirSection(), const DebugAndroidDirSection(),
DebugAndroidEnvironmentSection(), const DebugAndroidEnvironmentSection(),
DebugCacheSection(), const DebugCacheSection(),
DebugAppDatabaseSection(), const DebugAppDatabaseSection(),
DebugFirebaseSection(), const DebugFirebaseSection(),
DebugSettingsSection(), const DebugSettingsSection(),
DebugStorageSection(), const DebugStorageSection(),
], ],
), ),
), ),
@ -83,7 +85,7 @@ class _AppDebugPageState extends State<AppDebugPage> {
_taskQueueOverlayEntry?.remove(); _taskQueueOverlayEntry?.remove();
if (v) { if (v) {
_taskQueueOverlayEntry = OverlayEntry( _taskQueueOverlayEntry = OverlayEntry(
builder: (context) => DebugTaskQueueOverlay(), builder: (context) => const DebugTaskQueueOverlay(),
); );
Overlay.of(context)!.insert(_taskQueueOverlayEntry!); Overlay.of(context)!.insert(_taskQueueOverlayEntry!);
} else { } else {
@ -97,7 +99,7 @@ class _AppDebugPageState extends State<AppDebugPage> {
Padding( Padding(
padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8), padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8),
child: InfoRowGroup( child: InfoRowGroup(
{ info: {
'All entries': '${source.allEntries.length}', 'All entries': '${source.allEntries.length}',
'Visible entries': '${visibleEntries.length}', 'Visible entries': '${visibleEntries.length}',
'Catalogued': '${catalogued.length}', 'Catalogued': '${catalogued.length}',

View file

@ -5,6 +5,8 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
class DebugCacheSection extends StatefulWidget { class DebugCacheSection extends StatefulWidget {
const DebugCacheSection({Key? key}) : super(key: key);
@override @override
_DebugCacheSectionState createState() => _DebugCacheSectionState(); _DebugCacheSectionState createState() => _DebugCacheSectionState();
} }

View file

@ -8,6 +8,8 @@ import 'package:aves/widgets/common/identity/aves_expansion_tile.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class DebugAppDatabaseSection extends StatefulWidget { class DebugAppDatabaseSection extends StatefulWidget {
const DebugAppDatabaseSection({Key? key}) : super(key: key);
@override @override
_DebugAppDatabaseSectionState createState() => _DebugAppDatabaseSectionState(); _DebugAppDatabaseSectionState createState() => _DebugAppDatabaseSectionState();
} }

View file

@ -6,6 +6,8 @@ import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class DebugFirebaseSection extends StatelessWidget { class DebugFirebaseSection extends StatelessWidget {
const DebugFirebaseSection({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AvesExpansionTile( return AvesExpansionTile(
@ -32,10 +34,12 @@ class DebugFirebaseSection extends StatelessWidget {
), ),
Padding( Padding(
padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8), padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8),
child: InfoRowGroup({ child: InfoRowGroup(
info: {
'Firebase data collection enabled': '${Firebase.app().isAutomaticDataCollectionEnabled}', 'Firebase data collection enabled': '${Firebase.app().isAutomaticDataCollectionEnabled}',
'Crashlytics collection enabled': '${FirebaseCrashlytics.instance.isCrashlyticsCollectionEnabled}', 'Crashlytics collection enabled': '${FirebaseCrashlytics.instance.isCrashlyticsCollectionEnabled}',
}), },
),
) )
], ],
); );

View file

@ -2,6 +2,8 @@ import 'package:aves/services/service_policy.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class DebugTaskQueueOverlay extends StatelessWidget { class DebugTaskQueueOverlay extends StatelessWidget {
const DebugTaskQueueOverlay({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return IgnorePointer( return IgnorePointer(

View file

@ -9,6 +9,8 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class DebugSettingsSection extends StatelessWidget { class DebugSettingsSection extends StatelessWidget {
const DebugSettingsSection({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Consumer<Settings>( return Consumer<Settings>(
@ -36,7 +38,8 @@ class DebugSettingsSection extends StatelessWidget {
), ),
Padding( Padding(
padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8), padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8),
child: InfoRowGroup({ child: InfoRowGroup(
info: {
'tileExtent - Collection': '${settings.getTileExtent(CollectionPage.routeName)}', 'tileExtent - Collection': '${settings.getTileExtent(CollectionPage.routeName)}',
'tileExtent - Albums': '${settings.getTileExtent(AlbumListPage.routeName)}', 'tileExtent - Albums': '${settings.getTileExtent(AlbumListPage.routeName)}',
'tileExtent - Countries': '${settings.getTileExtent(CountryListPage.routeName)}', 'tileExtent - Countries': '${settings.getTileExtent(CountryListPage.routeName)}',
@ -50,7 +53,8 @@ class DebugSettingsSection extends StatelessWidget {
'lastVersionCheckDate': '${settings.lastVersionCheckDate}', 'lastVersionCheckDate': '${settings.lastVersionCheckDate}',
'locale': '${settings.locale}', 'locale': '${settings.locale}',
'systemLocale': '${WidgetsBinding.instance!.window.locale}', 'systemLocale': '${WidgetsBinding.instance!.window.locale}',
}), },
),
), ),
], ],
); );

View file

@ -6,6 +6,8 @@ import 'package:aves/widgets/viewer/info/common.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class DebugStorageSection extends StatefulWidget { class DebugStorageSection extends StatefulWidget {
const DebugStorageSection({Key? key}) : super(key: key);
@override @override
_DebugStorageSectionState createState() => _DebugStorageSectionState(); _DebugStorageSectionState createState() => _DebugStorageSectionState();
} }
@ -38,13 +40,15 @@ class _DebugStorageSectionState extends State<DebugStorageSection> with Automati
), ),
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 8), padding: const EdgeInsets.symmetric(horizontal: 8),
child: InfoRowGroup({ child: InfoRowGroup(
'description': '${v.getDescription(context)}', info: {
'description': v.getDescription(context),
'isPrimary': '${v.isPrimary}', 'isPrimary': '${v.isPrimary}',
'isRemovable': '${v.isRemovable}', 'isRemovable': '${v.isRemovable}',
'state': '${v.state}', 'state': v.state,
if (freeSpace != null) 'freeSpace': formatFilesize(freeSpace), if (freeSpace != null) 'freeSpace': formatFilesize(freeSpace),
}), },
),
), ),
const Divider(), const Divider(),
]; ];

View file

@ -19,9 +19,10 @@ class AddShortcutDialog extends StatefulWidget {
final String defaultName; final String defaultName;
const AddShortcutDialog({ const AddShortcutDialog({
Key? key,
required this.collection, required this.collection,
required this.defaultName, required this.defaultName,
}); }) : super(key: key);
@override @override
_AddShortcutDialogState createState() => _AddShortcutDialogState(); _AddShortcutDialogState createState() => _AddShortcutDialogState();
@ -133,7 +134,7 @@ class _AddShortcutDialogState extends State<AddShortcutDialog> {
MaterialPageRoute( MaterialPageRoute(
settings: const RouteSettings(name: ItemPickDialog.routeName), settings: const RouteSettings(name: ItemPickDialog.routeName),
builder: (context) => ItemPickDialog( builder: (context) => ItemPickDialog(
CollectionLens( collection: CollectionLens(
source: collection.source, source: collection.source,
filters: filters, filters: filters,
), ),

View file

@ -9,6 +9,7 @@ class AvesDialog extends AlertDialog {
static const borderWidth = 1.0; static const borderWidth = 1.0;
AvesDialog({ AvesDialog({
Key? key,
required BuildContext context, required BuildContext context,
String? title, String? title,
ScrollController? scrollController, ScrollController? scrollController,
@ -17,6 +18,7 @@ class AvesDialog extends AlertDialog {
required List<Widget> actions, required List<Widget> actions,
}) : assert((scrollableContent != null) ^ (content != null)), }) : assert((scrollableContent != null) ^ (content != null)),
super( super(
key: key,
title: title != null title: title != null
? Padding( ? Padding(
// padding to avoid transparent border overlapping // padding to avoid transparent border overlapping
@ -64,7 +66,10 @@ class AvesDialog extends AlertDialog {
class DialogTitle extends StatelessWidget { class DialogTitle extends StatelessWidget {
final String title; final String title;
const DialogTitle({required this.title}); const DialogTitle({
Key? key,
required this.title,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -13,11 +13,12 @@ class AvesSelectionDialog<T> extends StatefulWidget {
final String title; final String title;
const AvesSelectionDialog({ const AvesSelectionDialog({
Key? key,
required this.initialValue, required this.initialValue,
required this.options, required this.options,
this.optionSubtitleBuilder, this.optionSubtitleBuilder,
required this.title, required this.title,
}); }) : super(key: key);
@override @override
_AvesSelectionDialogState<T> createState() => _AvesSelectionDialogState<T>(); _AvesSelectionDialogState<T> createState() => _AvesSelectionDialogState<T>();

View file

@ -17,9 +17,10 @@ class CoverSelectionDialog extends StatefulWidget {
final AvesEntry? customEntry; final AvesEntry? customEntry;
const CoverSelectionDialog({ const CoverSelectionDialog({
Key? key,
required this.filter, required this.filter,
required this.customEntry, required this.customEntry,
}); }) : super(key: key);
@override @override
_CoverSelectionDialogState createState() => _CoverSelectionDialogState(); _CoverSelectionDialogState createState() => _CoverSelectionDialogState();
@ -118,7 +119,7 @@ class _CoverSelectionDialogState extends State<CoverSelectionDialog> {
MaterialPageRoute( MaterialPageRoute(
settings: const RouteSettings(name: ItemPickDialog.routeName), settings: const RouteSettings(name: ItemPickDialog.routeName),
builder: (context) => ItemPickDialog( builder: (context) => ItemPickDialog(
CollectionLens( collection: CollectionLens(
source: context.read<CollectionSource>(), source: context.read<CollectionSource>(),
filters: [filter], filters: [filter],
), ),

View file

@ -11,6 +11,8 @@ import 'package:flutter/widgets.dart';
import 'aves_dialog.dart'; import 'aves_dialog.dart';
class CreateAlbumDialog extends StatefulWidget { class CreateAlbumDialog extends StatefulWidget {
const CreateAlbumDialog({Key? key}) : super(key: key);
@override @override
_CreateAlbumDialogState createState() => _CreateAlbumDialogState(); _CreateAlbumDialogState createState() => _CreateAlbumDialogState();
} }

View file

@ -12,7 +12,10 @@ class ItemPickDialog extends StatefulWidget {
final CollectionLens collection; final CollectionLens collection;
const ItemPickDialog(this.collection); const ItemPickDialog({
Key? key,
required this.collection,
}) : super(key: key);
@override @override
_ItemPickDialogState createState() => _ItemPickDialogState(); _ItemPickDialogState createState() => _ItemPickDialogState();

View file

@ -8,7 +8,10 @@ import 'package:flutter/material.dart';
class RenameAlbumDialog extends StatefulWidget { class RenameAlbumDialog extends StatefulWidget {
final String album; final String album;
const RenameAlbumDialog(this.album); const RenameAlbumDialog({
Key? key,
required this.album,
}) : super(key: key);
@override @override
_RenameAlbumDialogState createState() => _RenameAlbumDialogState(); _RenameAlbumDialogState createState() => _RenameAlbumDialogState();

View file

@ -10,7 +10,10 @@ import 'aves_dialog.dart';
class RenameEntryDialog extends StatefulWidget { class RenameEntryDialog extends StatefulWidget {
final AvesEntry entry; final AvesEntry entry;
const RenameEntryDialog(this.entry); const RenameEntryDialog({
Key? key,
required this.entry,
}) : super(key: key);
@override @override
_RenameEntryDialogState createState() => _RenameEntryDialogState(); _RenameEntryDialogState createState() => _RenameEntryDialogState();

View file

@ -7,10 +7,11 @@ class VideoSpeedDialog extends StatefulWidget {
final double current, min, max; final double current, min, max;
const VideoSpeedDialog({ const VideoSpeedDialog({
Key? key,
required this.current, required this.current,
required this.min, required this.min,
required this.max, required this.max,
}); }) : super(key: key);
@override @override
_VideoSpeedDialogState createState() => _VideoSpeedDialogState(); _VideoSpeedDialogState createState() => _VideoSpeedDialogState();

View file

@ -12,8 +12,9 @@ class VideoStreamSelectionDialog extends StatefulWidget {
final Map<StreamSummary, bool> streams; final Map<StreamSummary, bool> streams;
const VideoStreamSelectionDialog({ const VideoStreamSelectionDialog({
Key? key,
required this.streams, required this.streams,
}); }) : super(key: key);
@override @override
_VideoStreamSelectionDialogState createState() => _VideoStreamSelectionDialogState(); _VideoStreamSelectionDialogState createState() => _VideoStreamSelectionDialogState();

View file

@ -10,7 +10,10 @@ import 'package:provider/provider.dart';
class AlbumTile extends StatelessWidget { class AlbumTile extends StatelessWidget {
final String album; final String album;
const AlbumTile(this.album); const AlbumTile({
Key? key,
required this.album,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -28,6 +28,8 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class AppDrawer extends StatefulWidget { class AppDrawer extends StatefulWidget {
const AppDrawer({Key? key}) : super(key: key);
@override @override
_AppDrawerState createState() => _AppDrawerState(); _AppDrawerState createState() => _AppDrawerState();
} }
@ -141,7 +143,7 @@ class _AppDrawerState extends State<AppDrawer> {
children: [ children: [
OutlinedButton.icon( OutlinedButton.icon(
key: const Key('drawer-about-button'), key: const Key('drawer-about-button'),
onPressed: () => goTo(AboutPage.routeName, (_) => AboutPage()), onPressed: () => goTo(AboutPage.routeName, (_) => const AboutPage()),
icon: const Icon(AIcons.info), icon: const Icon(AIcons.info),
label: Row( label: Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -177,7 +179,7 @@ class _AppDrawerState extends State<AppDrawer> {
), ),
OutlinedButton.icon( OutlinedButton.icon(
key: const Key('drawer-settings-button'), key: const Key('drawer-settings-button'),
onPressed: () => goTo(SettingsPage.routeName, (_) => SettingsPage()), onPressed: () => goTo(SettingsPage.routeName, (_) => const SettingsPage()),
icon: const Icon(AIcons.settings), icon: const Icon(AIcons.settings),
label: Text(context.l10n.settingsPageTitle), label: Text(context.l10n.settingsPageTitle),
), ),
@ -204,7 +206,7 @@ class _AppDrawerState extends State<AppDrawer> {
return Column( return Column(
children: [ children: [
const Divider(), 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}'), builder: (context, _) => Text('${source.rawAlbums.length}'),
), ),
routeName: AlbumListPage.routeName, routeName: AlbumListPage.routeName,
pageBuilder: (_) => AlbumListPage(), pageBuilder: (_) => const AlbumListPage(),
); );
Widget get countryListTile => NavTile( Widget get countryListTile => NavTile(
@ -249,7 +251,7 @@ class _AppDrawerState extends State<AppDrawer> {
builder: (context, _) => Text('${source.sortedCountries.length}'), builder: (context, _) => Text('${source.sortedCountries.length}'),
), ),
routeName: CountryListPage.routeName, routeName: CountryListPage.routeName,
pageBuilder: (_) => CountryListPage(), pageBuilder: (_) => const CountryListPage(),
); );
Widget get tagListTile => NavTile( Widget get tagListTile => NavTile(
@ -260,7 +262,7 @@ class _AppDrawerState extends State<AppDrawer> {
builder: (context, _) => Text('${source.sortedTags.length}'), builder: (context, _) => Text('${source.sortedTags.length}'),
), ),
routeName: TagListPage.routeName, routeName: TagListPage.routeName,
pageBuilder: (_) => TagListPage(), pageBuilder: (_) => const TagListPage(),
); );
Widget get debugTile => NavTile( Widget get debugTile => NavTile(
@ -268,6 +270,6 @@ class _AppDrawerState extends State<AppDrawer> {
title: 'Debug', title: 'Debug',
topLevel: false, topLevel: false,
routeName: AppDebugPage.routeName, routeName: AppDebugPage.routeName,
pageBuilder: (_) => AppDebugPage(), pageBuilder: (_) => const AppDebugPage(),
); );
} }

View file

@ -13,12 +13,14 @@ class CollectionNavTile extends StatelessWidget {
final CollectionFilter? filter; final CollectionFilter? filter;
const CollectionNavTile({ const CollectionNavTile({
Key? key,
required this.leading, required this.leading,
required this.title, required this.title,
this.trailing, this.trailing,
bool? dense, bool? dense,
required this.filter, required this.filter,
}) : dense = dense ?? false; }) : dense = dense ?? false,
super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -41,10 +43,12 @@ class CollectionNavTile extends StatelessWidget {
context, context,
MaterialPageRoute( MaterialPageRoute(
settings: const RouteSettings(name: CollectionPage.routeName), settings: const RouteSettings(name: CollectionPage.routeName),
builder: (context) => CollectionPage(CollectionLens( builder: (context) => CollectionPage(
collection: CollectionLens(
source: context.read<CollectionSource>(), source: context.read<CollectionSource>(),
filters: [filter], filters: [filter],
)), ),
),
), ),
(route) => false, (route) => false,
); );

View file

@ -11,13 +11,14 @@ class NavTile extends StatelessWidget {
final WidgetBuilder pageBuilder; final WidgetBuilder pageBuilder;
const NavTile({ const NavTile({
Key? key,
required this.icon, required this.icon,
required this.title, required this.title,
this.trailing, this.trailing,
this.topLevel = true, this.topLevel = true,
required this.routeName, required this.routeName,
required this.pageBuilder, required this.pageBuilder,
}); }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -30,9 +30,10 @@ class AlbumPickPage extends StatefulWidget {
final MoveType moveType; final MoveType moveType;
const AlbumPickPage({ const AlbumPickPage({
Key? key,
required this.source, required this.source,
required this.moveType, required this.moveType,
}); }) : super(key: key);
@override @override
_AlbumPickPageState createState() => _AlbumPickPageState(); _AlbumPickPageState createState() => _AlbumPickPageState();
@ -91,11 +92,12 @@ class AlbumPickAppBar extends StatelessWidget {
static const preferredHeight = kToolbarHeight + AlbumFilterBar.preferredHeight; static const preferredHeight = kToolbarHeight + AlbumFilterBar.preferredHeight;
const AlbumPickAppBar({ const AlbumPickAppBar({
Key? key,
required this.source, required this.source,
required this.moveType, required this.moveType,
required this.actionDelegate, required this.actionDelegate,
required this.queryNotifier, required this.queryNotifier,
}); }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -127,7 +129,7 @@ class AlbumPickAppBar extends StatelessWidget {
onPressed: () async { onPressed: () async {
final newAlbum = await showDialog<String>( final newAlbum = await showDialog<String>(
context: context, context: context,
builder: (context) => CreateAlbumDialog(), builder: (context) => const CreateAlbumDialog(),
); );
if (newAlbum != null && newAlbum.isNotEmpty) { if (newAlbum != null && newAlbum.isNotEmpty) {
Navigator.pop<String>(context, newAlbum); Navigator.pop<String>(context, newAlbum);
@ -169,8 +171,9 @@ class AlbumFilterBar extends StatelessWidget implements PreferredSizeWidget {
static const preferredHeight = kToolbarHeight; static const preferredHeight = kToolbarHeight;
const AlbumFilterBar({ const AlbumFilterBar({
Key? key,
required this.filterNotifier, required this.filterNotifier,
}); }) : super(key: key);
@override @override
Size get preferredSize => const Size.fromHeight(preferredHeight); Size get preferredSize => const Size.fromHeight(preferredHeight);

View file

@ -21,6 +21,8 @@ import 'package:tuple/tuple.dart';
class AlbumListPage extends StatelessWidget { class AlbumListPage extends StatelessWidget {
static const routeName = '/albums'; static const routeName = '/albums';
const AlbumListPage({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final source = context.read<CollectionSource>(); final source = context.read<CollectionSource>();

View file

@ -43,13 +43,13 @@ class ChipActionDelegate {
_showCoverSelectionDialog(context, filter); _showCoverSelectionDialog(context, filter);
break; break;
case ChipAction.goToAlbumPage: case ChipAction.goToAlbumPage:
_goTo(context, filter, AlbumListPage.routeName, (context) => AlbumListPage()); _goTo(context, filter, AlbumListPage.routeName, (context) => const AlbumListPage());
break; break;
case ChipAction.goToCountryPage: case ChipAction.goToCountryPage:
_goTo(context, filter, CountryListPage.routeName, (context) => CountryListPage()); _goTo(context, filter, CountryListPage.routeName, (context) => const CountryListPage());
break; break;
case ChipAction.goToTagPage: case ChipAction.goToTagPage:
_goTo(context, filter, TagListPage.routeName, (context) => TagListPage()); _goTo(context, filter, TagListPage.routeName, (context) => const TagListPage());
break; break;
default: default:
break; break;
@ -207,7 +207,7 @@ class AlbumChipActionDelegate extends ChipActionDelegate with FeedbackMixin, Per
final newName = await showDialog<String>( final newName = await showDialog<String>(
context: context, context: context,
builder: (context) => RenameAlbumDialog(album), builder: (context) => RenameAlbumDialog(album: album),
); );
if (newName == null || newName.isEmpty) return; if (newName == null || newName.isEmpty) return;

View file

@ -11,9 +11,10 @@ class FilterDraggableThumbLabel<T extends CollectionFilter> extends StatelessWid
final double offsetY; final double offsetY;
const FilterDraggableThumbLabel({ const FilterDraggableThumbLabel({
Key? key,
required this.sortFactor, required this.sortFactor,
required this.offsetY, required this.offsetY,
}); }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -91,7 +91,7 @@ class FilterGridPage<T extends CollectionFilter> extends StatelessWidget {
), ),
), ),
), ),
drawer: AppDrawer(), drawer: const AppDrawer(),
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
), ),
); );
@ -454,7 +454,7 @@ class _FilterScrollView<T extends CollectionFilter> extends StatelessWidget {
) )
: SectionedListSliver<FilterGridItem<T>>(); : SectionedListSliver<FilterGridItem<T>>();
}), }),
BottomPaddingSliver(), const BottomPaddingSliver(),
], ],
); );
} }

View file

@ -37,6 +37,7 @@ class FilterNavigationPage<T extends CollectionFilter> extends StatelessWidget {
final Widget Function() emptyBuilder; final Widget Function() emptyBuilder;
const FilterNavigationPage({ const FilterNavigationPage({
Key? key,
required this.source, required this.source,
required this.title, required this.title,
required this.sortFactor, required this.sortFactor,
@ -47,7 +48,7 @@ class FilterNavigationPage<T extends CollectionFilter> extends StatelessWidget {
required this.chipActionsBuilder, required this.chipActionsBuilder,
required this.filterSections, required this.filterSections,
required this.emptyBuilder, required this.emptyBuilder,
}); }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -80,10 +81,12 @@ class FilterNavigationPage<T extends CollectionFilter> extends StatelessWidget {
context, context,
MaterialPageRoute( MaterialPageRoute(
settings: const RouteSettings(name: CollectionPage.routeName), settings: const RouteSettings(name: CollectionPage.routeName),
builder: (context) => CollectionPage(CollectionLens( builder: (context) => CollectionPage(
collection: CollectionLens(
source: source, source: source,
filters: [filter], filters: [filter],
)), ),
),
), ),
), ),
onLongPress: isMainMode ? _showMenu as OffsetFilterCallback : null, onLongPress: isMainMode ? _showMenu as OffsetFilterCallback : null,
@ -111,7 +114,7 @@ class FilterNavigationPage<T extends CollectionFilter> extends StatelessWidget {
List<Widget> _buildActions(BuildContext context) { List<Widget> _buildActions(BuildContext context) {
return [ return [
CollectionSearchButton(source), CollectionSearchButton(source: source),
PopupMenuButton<ChipSetAction>( PopupMenuButton<ChipSetAction>(
key: const Key('appbar-menu-button'), key: const Key('appbar-menu-button'),
itemBuilder: (context) { itemBuilder: (context) {

View file

@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
class SectionedFilterListLayoutProvider<T extends CollectionFilter> extends SectionedListLayoutProvider<FilterGridItem<T>> { class SectionedFilterListLayoutProvider<T extends CollectionFilter> extends SectionedListLayoutProvider<FilterGridItem<T>> {
const SectionedFilterListLayoutProvider({ const SectionedFilterListLayoutProvider({
Key? key,
required this.sections, required this.sections,
required this.showHeaders, required this.showHeaders,
required double scrollableWidth, required double scrollableWidth,
@ -17,6 +18,7 @@ class SectionedFilterListLayoutProvider<T extends CollectionFilter> extends Sect
required Duration tileAnimationDelay, required Duration tileAnimationDelay,
required Widget child, required Widget child,
}) : super( }) : super(
key: key,
scrollableWidth: scrollableWidth, scrollableWidth: scrollableWidth,
columnCount: columnCount, columnCount: columnCount,
spacing: spacing, spacing: spacing,

View file

@ -20,6 +20,8 @@ import 'package:tuple/tuple.dart';
class CountryListPage extends StatelessWidget { class CountryListPage extends StatelessWidget {
static const routeName = '/countries'; static const routeName = '/countries';
const CountryListPage({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final source = context.read<CollectionSource>(); final source = context.read<CollectionSource>();

View file

@ -20,6 +20,8 @@ import 'package:tuple/tuple.dart';
class TagListPage extends StatelessWidget { class TagListPage extends StatelessWidget {
static const routeName = '/tags'; static const routeName = '/tags';
const TagListPage({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final source = context.read<CollectionSource>(); final source = context.read<CollectionSource>();

View file

@ -9,6 +9,7 @@ import 'package:aves/model/source/collection_source.dart';
import 'package:aves/services/services.dart'; import 'package:aves/services/services.dart';
import 'package:aves/services/viewer_service.dart'; import 'package:aves/services/viewer_service.dart';
import 'package:aves/utils/android_file_utils.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/collection/collection_page.dart';
import 'package:aves/widgets/common/behaviour/routes.dart'; import 'package:aves/widgets/common/behaviour/routes.dart';
import 'package:aves/widgets/filter_grids/albums_page.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:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:pedantic/pedantic.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -28,7 +28,10 @@ class HomePage extends StatefulWidget {
// untyped map as it is coming from the platform // untyped map as it is coming from the platform
final Map? intentData; final Map? intentData;
const HomePage({this.intentData}); const HomePage({
Key? key,
this.intentData,
}) : super(key: key);
@override @override
_HomePageState createState() => _HomePageState(); _HomePageState createState() => _HomePageState();
@ -147,7 +150,7 @@ class _HomePageState extends State<HomePage> {
case AlbumListPage.routeName: case AlbumListPage.routeName:
return DirectMaterialPageRoute( return DirectMaterialPageRoute(
settings: const RouteSettings(name: AlbumListPage.routeName), settings: const RouteSettings(name: AlbumListPage.routeName),
builder: (_) => AlbumListPage(), builder: (_) => const AlbumListPage(),
); );
case SearchPage.routeName: case SearchPage.routeName:
return SearchPageRoute( return SearchPageRoute(
@ -158,7 +161,7 @@ class _HomePageState extends State<HomePage> {
return DirectMaterialPageRoute( return DirectMaterialPageRoute(
settings: const RouteSettings(name: CollectionPage.routeName), settings: const RouteSettings(name: CollectionPage.routeName),
builder: (_) => CollectionPage( builder: (_) => CollectionPage(
CollectionLens( collection: CollectionLens(
source: source, source: source,
filters: filters, filters: filters,
), ),

View file

@ -13,12 +13,13 @@ class ExpandableFilterRow extends StatelessWidget {
final FilterCallback onTap; final FilterCallback onTap;
const ExpandableFilterRow({ const ExpandableFilterRow({
Key? key,
this.title, this.title,
required this.filters, required this.filters,
required this.expandedNotifier, required this.expandedNotifier,
this.heroTypeBuilder, this.heroTypeBuilder,
required this.onTap, required this.onTap,
}); }) : super(key: key);
static const double horizontalPadding = 8; static const double horizontalPadding = 8;
static const double verticalPadding = 8; static const double verticalPadding = 8;

View file

@ -8,7 +8,11 @@ class CollectionSearchButton extends StatelessWidget {
final CollectionSource source; final CollectionSource source;
final CollectionLens? parentCollection; final CollectionLens? parentCollection;
const CollectionSearchButton(this.source, {this.parentCollection}); const CollectionSearchButton({
Key? key,
required this.source,
this.parentCollection,
}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -243,10 +243,12 @@ class CollectionSearchDelegate {
context, context,
MaterialPageRoute( MaterialPageRoute(
settings: const RouteSettings(name: CollectionPage.routeName), settings: const RouteSettings(name: CollectionPage.routeName),
builder: (context) => CollectionPage(CollectionLens( builder: (context) => CollectionPage(
collection: CollectionLens(
source: source, source: source,
filters: [filter], filters: [filter],
)), ),
),
), ),
(route) => false, (route) => false,
); );

View file

@ -12,9 +12,10 @@ class SearchPage extends StatefulWidget {
final Animation<double> animation; final Animation<double> animation;
const SearchPage({ const SearchPage({
Key? key,
required this.delegate, required this.delegate,
required this.animation, required this.animation,
}); }) : super(key: key);
@override @override
_SearchPageState createState() => _SearchPageState(); _SearchPageState createState() => _SearchPageState();

View file

@ -7,11 +7,12 @@ class ActionButton extends StatelessWidget {
final bool enabled, showCaption; final bool enabled, showCaption;
const ActionButton({ const ActionButton({
Key? key,
required this.text, required this.text,
required this.icon, required this.icon,
this.enabled = true, this.enabled = true,
this.showCaption = true, this.showCaption = true,
}); }) : super(key: key);
static const padding = 8.0; static const padding = 8.0;

View file

@ -6,9 +6,10 @@ class ActionPanel extends StatelessWidget {
final Widget child; final Widget child;
const ActionPanel({ const ActionPanel({
Key? key,
this.highlight = false, this.highlight = false,
required this.child, required this.child,
}); }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

Some files were not shown because too many files have changed in this diff Show more