From 1841c60c09985b084264a9fa81841a482ce9fe98 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Fri, 25 Jun 2021 21:38:56 +0900 Subject: [PATCH] packages upgrade, static analysis migration --- analysis_options.yaml | 18 ++- .../aves/channel/calls/EmbeddedDataHandler.kt | 1 + .../channel/calls/fetchers/RegionFetcher.kt | 1 + .../calls/fetchers/TiffRegionFetcher.kt | 1 + .../channel/streams/ImageByteStreamHandler.kt | 2 + .../thibault/aves/metadata/TiffTags.kt | 22 ++-- .../aves/model/provider/FileImageProvider.kt | 6 +- .../aves/model/provider/ImageProvider.kt | 2 +- .../model/provider/MediaStoreImageProvider.kt | 8 +- .../deckers/thibault/aves/utils/BmpWriter.kt | 2 +- android/build.gradle | 4 +- lib/image_providers/uri_image_provider.dart | 2 +- lib/image_providers/uri_picture_provider.dart | 2 +- lib/main.dart | 2 +- lib/model/filters/location.dart | 2 +- lib/model/metadata.dart | 3 +- lib/model/settings/settings.dart | 2 +- lib/services/app_shortcut_service.dart | 2 +- lib/services/service_policy.dart | 4 +- lib/services/svg_metadata_service.dart | 2 +- lib/theme/icons.dart | 1 - lib/utils/constants.dart | 12 +- lib/utils/pedantic.dart | 2 + lib/widgets/about/about_page.dart | 10 +- lib/widgets/about/app_ref.dart | 2 + lib/widgets/about/credits.dart | 2 + lib/widgets/about/licenses.dart | 15 ++- lib/widgets/about/news_badge.dart | 2 +- lib/widgets/about/update.dart | 2 + lib/widgets/aves_app.dart | 4 +- lib/widgets/collection/app_bar.dart | 6 +- lib/widgets/collection/collection_grid.dart | 4 +- lib/widgets/collection/collection_page.dart | 7 +- .../collection/draggable_thumb_label.dart | 3 +- .../collection/entry_set_action_delegate.dart | 10 +- .../collection/grid/section_layout.dart | 2 + lib/widgets/collection/grid/selector.dart | 5 +- lib/widgets/collection/thumbnail/error.dart | 3 +- lib/widgets/collection/thumbnail/theme.dart | 3 +- .../common/action_mixins/feedback.dart | 3 +- lib/widgets/common/app_bar_subtitle.dart | 5 +- lib/widgets/common/app_bar_title.dart | 3 +- lib/widgets/common/aves_highlight.dart | 8 +- lib/widgets/common/basic/insets.dart | 11 +- .../common/basic/multi_cross_fader.dart | 3 +- lib/widgets/common/basic/query_bar.dart | 5 +- .../common/behaviour/double_back_pop.dart | 3 +- lib/widgets/common/fx/sweeper.dart | 2 +- lib/widgets/common/fx/transition_image.dart | 3 +- .../common/grid/draggable_thumb_label.dart | 3 +- lib/widgets/common/grid/header.dart | 3 +- lib/widgets/common/grid/section_layout.dart | 4 +- lib/widgets/common/grid/sliver.dart | 2 + .../common/identity/aves_expansion_tile.dart | 6 +- lib/widgets/common/identity/aves_logo.dart | 5 +- lib/widgets/common/identity/empty.dart | 3 +- .../common/identity/highlight_title.dart | 7 +- .../core/scale_gesture_recognizer.dart | 2 +- .../magnifier/pan/gesture_detector_scope.dart | 3 +- .../providers/highlight_info_provider.dart | 5 +- .../providers/media_query_data_provider.dart | 5 +- .../tile_extent_controller_provider.dart | 3 +- lib/widgets/common/scaling.dart | 8 +- lib/widgets/debug/android_apps.dart | 2 + lib/widgets/debug/android_dirs.dart | 4 +- lib/widgets/debug/android_env.dart | 4 +- lib/widgets/debug/app_debug_page.dart | 22 ++-- lib/widgets/debug/cache.dart | 2 + lib/widgets/debug/database.dart | 2 + lib/widgets/debug/firebase.dart | 12 +- lib/widgets/debug/overlay.dart | 2 + lib/widgets/debug/settings.dart | 34 ++--- lib/widgets/debug/storage.dart | 18 +-- lib/widgets/dialogs/add_shortcut_dialog.dart | 5 +- lib/widgets/dialogs/aves_dialog.dart | 7 +- .../dialogs/aves_selection_dialog.dart | 3 +- .../dialogs/cover_selection_dialog.dart | 5 +- lib/widgets/dialogs/create_album_dialog.dart | 2 + lib/widgets/dialogs/item_pick_dialog.dart | 5 +- lib/widgets/dialogs/rename_album_dialog.dart | 5 +- lib/widgets/dialogs/rename_entry_dialog.dart | 5 +- lib/widgets/dialogs/video_speed_dialog.dart | 3 +- .../video_stream_selection_dialog.dart | 3 +- lib/widgets/drawer/album_tile.dart | 5 +- lib/widgets/drawer/app_drawer.dart | 16 +-- lib/widgets/drawer/collection_tile.dart | 14 ++- lib/widgets/drawer/tile.dart | 3 +- lib/widgets/filter_grids/album_pick.dart | 11 +- lib/widgets/filter_grids/albums_page.dart | 2 + .../common/chip_action_delegate.dart | 8 +- .../common/draggable_thumb_label.dart | 3 +- .../filter_grids/common/filter_grid_page.dart | 4 +- .../filter_grids/common/filter_nav_page.dart | 15 ++- .../filter_grids/common/section_layout.dart | 2 + lib/widgets/filter_grids/countries_page.dart | 2 + lib/widgets/filter_grids/tags_page.dart | 2 + lib/widgets/home_page.dart | 11 +- lib/widgets/search/expandable_filter_row.dart | 3 +- lib/widgets/search/search_button.dart | 6 +- lib/widgets/search/search_delegate.dart | 10 +- lib/widgets/search/search_page.dart | 3 +- .../common/quick_actions/action_button.dart | 3 +- .../common/quick_actions/action_panel.dart | 3 +- .../quick_actions/available_actions.dart | 3 +- .../common/quick_actions/editor_page.dart | 5 +- .../common/quick_actions/placeholder.dart | 3 +- .../common/quick_actions/quick_actions.dart | 3 +- lib/widgets/settings/language/language.dart | 2 +- lib/widgets/settings/language/locale.dart | 4 +- .../settings/privacy/access_grants.dart | 6 +- .../settings/privacy/hidden_filters.dart | 6 +- lib/widgets/settings/privacy/privacy.dart | 4 +- lib/widgets/settings/settings_page.dart | 2 + .../settings/video/subtitle_theme.dart | 6 +- lib/widgets/settings/video/video.dart | 4 +- .../settings/video/video_actions_editor.dart | 2 + .../settings/viewer/entry_background.dart | 3 +- lib/widgets/settings/viewer/viewer.dart | 2 +- .../viewer/viewer_actions_editor.dart | 2 + lib/widgets/stats/filter_table.dart | 9 +- lib/widgets/stats/stats.dart | 15 ++- lib/widgets/viewer/debug/db.dart | 79 +++++++----- lib/widgets/viewer/debug/debug_page.dart | 119 ++++++++++-------- lib/widgets/viewer/debug/metadata.dart | 7 +- lib/widgets/viewer/entry_action_delegate.dart | 12 +- .../viewer/entry_horizontal_pager.dart | 10 +- lib/widgets/viewer/entry_vertical_pager.dart | 3 +- lib/widgets/viewer/entry_viewer_stack.dart | 4 +- lib/widgets/viewer/info/basic_section.dart | 23 ++-- lib/widgets/viewer/info/common.dart | 18 +-- lib/widgets/viewer/info/info_app_bar.dart | 3 +- lib/widgets/viewer/info/info_page.dart | 2 +- lib/widgets/viewer/info/location_section.dart | 12 +- lib/widgets/viewer/info/maps/common.dart | 11 +- lib/widgets/viewer/info/maps/leaflet_map.dart | 12 +- lib/widgets/viewer/info/maps/marker.dart | 3 +- lib/widgets/viewer/info/maps/scale_layer.dart | 6 +- .../info/metadata/metadata_dir_tile.dart | 7 +- .../info/metadata/metadata_section.dart | 15 ++- .../viewer/info/metadata/xmp_namespaces.dart | 4 +- .../viewer/info/metadata/xmp_structs.dart | 14 ++- .../viewer/info/metadata/xmp_tile.dart | 3 +- lib/widgets/viewer/overlay/bottom/common.dart | 4 +- .../viewer/overlay/bottom/panorama.dart | 2 +- lib/widgets/viewer/overlay/bottom/video.dart | 2 +- lib/widgets/viewer/overlay/minimap.dart | 3 +- lib/widgets/viewer/panorama_page.dart | 5 +- lib/widgets/viewer/printer.dart | 2 +- lib/widgets/viewer/source_viewer_page.dart | 5 +- lib/widgets/viewer/video_action_delegate.dart | 10 +- lib/widgets/viewer/visual/error.dart | 3 +- lib/widgets/viewer/visual/raster.dart | 6 +- .../viewer/visual/subtitle/ass_parser.dart | 2 +- .../viewer/visual/subtitle/subtitle.dart | 16 ++- lib/widgets/viewer/visual/vector.dart | 3 +- lib/widgets/welcome_page.dart | 6 +- pubspec.lock | 36 ++++-- pubspec.yaml | 2 +- test/fake/metadata_db.dart | 26 ++-- test/model/collection_source_test.dart | 2 +- test/widget_test.dart | 2 +- test_driver/app_test.dart | 3 +- 162 files changed, 706 insertions(+), 441 deletions(-) create mode 100644 lib/utils/pedantic.dart diff --git a/analysis_options.yaml b/analysis_options.yaml index 537f9f075..bfd8aadb8 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -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 diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/EmbeddedDataHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/EmbeddedDataHandler.kt index 534f5c520..6a663064e 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/EmbeddedDataHandler.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/EmbeddedDataHandler.kt @@ -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 -> diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/RegionFetcher.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/RegionFetcher.kt index 01a4785b1..19a1374de 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/RegionFetcher.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/RegionFetcher.kt @@ -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) { diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/TiffRegionFetcher.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/TiffRegionFetcher.kt index 12666d371..56cb7c199 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/TiffRegionFetcher.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/fetchers/TiffRegionFetcher.kt @@ -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) diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ImageByteStreamHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ImageByteStreamHandler.kt index 9d4e73edc..2b2f73fc1 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ImageByteStreamHandler.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/streams/ImageByteStreamHandler.kt @@ -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)) diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/TiffTags.kt b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/TiffTags.kt index 230c1e630..2f8a9c23c 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/metadata/TiffTags.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/metadata/TiffTags.kt @@ -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, diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/FileImageProvider.kt b/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/FileImageProvider.kt index c87b4b312..5ce04ce10 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/FileImageProvider.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/FileImageProvider.kt @@ -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) { diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/ImageProvider.kt b/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/ImageProvider.kt index 6cbcb77c2..6057abddb 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/ImageProvider.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/ImageProvider.kt @@ -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()) } diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/MediaStoreImageProvider.kt b/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/MediaStoreImageProvider.kt index 6f386f116..4c04b8907 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/MediaStoreImageProvider.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/model/provider/MediaStoreImageProvider.kt @@ -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")) } diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/utils/BmpWriter.kt b/android/app/src/main/kotlin/deckers/thibault/aves/utils/BmpWriter.kt index 1409eecfd..29599a028 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/utils/BmpWriter.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/utils/BmpWriter.kt @@ -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) diff --git a/android/build.gradle b/android/build.gradle index cf42cff6e..80a95abbc 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -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' } } diff --git a/lib/image_providers/uri_image_provider.dart b/lib/image_providers/uri_image_provider.dart index 80ea53f3d..823644af0 100644 --- a/lib/image_providers/uri_image_provider.dart +++ b/lib/image_providers/uri_image_provider.dart @@ -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 { final String uri, mimeType; diff --git a/lib/image_providers/uri_picture_provider.dart b/lib/image_providers/uri_picture_provider.dart index 8a13e7125..b50168c93 100644 --- a/lib/image_providers/uri_picture_provider.dart +++ b/lib/image_providers/uri_picture_provider.dart @@ -13,7 +13,7 @@ class UriPicture extends PictureProvider { final String uri, mimeType; @override - Future obtainKey(PictureConfiguration configuration) { + Future obtainKey(PictureConfiguration picture) { return SynchronousFuture(this); } diff --git a/lib/main.dart b/lib/main.dart index 470a5c629..af8efa9bb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -29,5 +29,5 @@ void main() { ); }).sendPort); - runApp(AvesApp()); + runApp(const AvesApp()); } diff --git a/lib/model/filters/location.dart b/lib/model/filters/location.dart index 4e78ac4d4..6b4793275 100644 --- a/lib/model/filters/location.dart +++ b/lib/model/filters/location.dart @@ -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, ); } diff --git a/lib/model/metadata.dart b/lib/model/metadata.dart index 2bb707e00..862d904d7 100644 --- a/lib/model/metadata.dart +++ b/lib/model/metadata.dart @@ -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; diff --git a/lib/model/settings/settings.dart b/lib/model/settings/settings.dart index 64cf880b2..18e9cb73b 100644 --- a/lib/model/settings/settings.dart +++ b/lib/model/settings/settings.dart @@ -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(); diff --git a/lib/services/app_shortcut_service.dart b/lib/services/app_shortcut_service.dart index c81d9a7f8..4ef9c5323 100644 --- a/lib/services/app_shortcut_service.dart +++ b/lib/services/app_shortcut_service.dart @@ -12,7 +12,7 @@ class AppShortcutService { // this ability will not change over the lifetime of the app static bool? _canPin; - static Future canPin() async { + static Future canPin() async { if (_canPin != null) { return SynchronousFuture(_canPin!); } diff --git a/lib/services/service_policy.dart b/lib/services/service_policy.dart index bc3e4321f..0406f4f29 100644 --- a/lib/services/service_policy.dart +++ b/lib/services/service_policy.dart @@ -26,7 +26,7 @@ class ServicePolicy { Object? key, }) { Completer completer; - _Task task; + _Task 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; + final task = toResume.item2 as _Task; _getQueue(priority)[key] = task; _pickNext(); return task.completer.future; diff --git a/lib/services/svg_metadata_service.dart b/lib/services/svg_metadata_service.dart index 3a282b883..365eeb6ec 100644 --- a/lib/services/svg_metadata_service.dart +++ b/lib/services/svg_metadata_service.dart @@ -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>(), + ..._textElements.map((name) => MapEntry(formatKey(name), root.getElement(name)?.text)).where((kv) => kv.value != null).cast>(), ]); final metadata = root.getElement(_metadataElement); diff --git a/lib/theme/icons.dart b/lib/theme/icons.dart index b914ce5f5..c65604bb6 100644 --- a/lib/theme/icons.dart +++ b/lib/theme/icons.dart @@ -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'; diff --git a/lib/utils/constants.dart b/lib/utils/constants.dart index 43daf682b..8d313e1d7 100644 --- a/lib/utils/constants.dart +++ b/lib/utils/constants.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', diff --git a/lib/utils/pedantic.dart b/lib/utils/pedantic.dart new file mode 100644 index 000000000..d98c609ed --- /dev/null +++ b/lib/utils/pedantic.dart @@ -0,0 +1,2 @@ +// cf https://github.com/google/pedantic/blob/master/lib/pedantic.dart +void unawaited(Future? future) {} diff --git a/lib/widgets/about/about_page.dart b/lib/widgets/about/about_page.dart index 31f2a3091..564d36509 100644 --- a/lib/widgets/about/about_page.dart +++ b/lib/widgets/about/about_page.dart @@ -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(), ], ), ), diff --git a/lib/widgets/about/app_ref.dart b/lib/widgets/about/app_ref.dart index 8d309ee5e..f995f0a7a 100644 --- a/lib/widgets/about/app_ref.dart +++ b/lib/widgets/about/app_ref.dart @@ -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(); } diff --git a/lib/widgets/about/credits.dart b/lib/widgets/about/credits.dart index ce081b1cf..ab8b366e7 100644 --- a/lib/widgets/about/credits.dart +++ b/lib/widgets/about/credits.dart @@ -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( diff --git a/lib/widgets/about/licenses.dart b/lib/widgets/about/licenses.dart index 55689796f..44cdd6384 100644 --- a/lib/widgets/about/licenses.dart +++ b/lib/widgets/about/licenses.dart @@ -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 { 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 { 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) { diff --git a/lib/widgets/about/news_badge.dart b/lib/widgets/about/news_badge.dart index 7ec8d6c1a..c0557a82e 100644 --- a/lib/widgets/about/news_badge.dart +++ b/lib/widgets/about/news_badge.dart @@ -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) { diff --git a/lib/widgets/about/update.dart b/lib/widgets/about/update.dart index 5b76768f4..fa25b9799 100644 --- a/lib/widgets/about/update.dart +++ b/lib/widgets/about/update.dart @@ -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(); } diff --git a/lib/widgets/aves_app.dart b/lib/widgets/aves_app.dart index df8d6b4ce..388d420c0 100644 --- a/lib/widgets/aves_app.dart +++ b/lib/widgets/aves_app.dart @@ -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 { darkTheme: Themes.darkTheme, themeMode: ThemeMode.dark, locale: settingsLocale, - localizationsDelegates: [ + localizationsDelegates: const [ ...AppLocalizations.localizationsDelegates, ], supportedLocales: AppLocalizations.supportedLocales, diff --git a/lib/widgets/collection/app_bar.dart b/lib/widgets/collection/app_bar.dart index f9d3e38cd..09089e7ca 100644 --- a/lib/widgets/collection/app_bar.dart +++ b/lib/widgets/collection/app_bar.dart @@ -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 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 with SingleTickerPr Future _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 diff --git a/lib/widgets/collection/collection_grid.dart b/lib/widgets/collection/collection_grid.dart index e53d4b09b..88c618791 100644 --- a/lib/widgets/collection/collection_grid.dart +++ b/lib/widgets/collection/collection_grid.dart @@ -324,8 +324,8 @@ class _CollectionScrollViewState extends State<_CollectionScrollView> { hasScrollBody: false, child: _buildEmptyCollectionPlaceholder(collection), ) - : SectionedListSliver(), - BottomPaddingSliver(), + : const SectionedListSliver(), + const BottomPaddingSliver(), ], ); } diff --git a/lib/widgets/collection/collection_page.dart b/lib/widgets/collection/collection_page.dart index 5bde8c65f..5cfb43a81 100644 --- a/lib/widgets/collection/collection_page.dart +++ b/lib/widgets/collection/collection_page.dart @@ -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 { ), ), ), - drawer: AppDrawer(), + drawer: const AppDrawer(), resizeToAvoidBottomInset: false, ), ); diff --git a/lib/widgets/collection/draggable_thumb_label.dart b/lib/widgets/collection/draggable_thumb_label.dart index d7776d9a2..370cc4d01 100644 --- a/lib/widgets/collection/draggable_thumb_label.dart +++ b/lib/widgets/collection/draggable_thumb_label.dart @@ -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) { diff --git a/lib/widgets/collection/entry_set_action_delegate.dart b/lib/widgets/collection/entry_set_action_delegate.dart index 57a51551c..4acfbbfdd 100644 --- a/lib/widgets/collection/entry_set_action_delegate.dart +++ b/lib/widgets/collection/entry_set_action_delegate.dart @@ -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); diff --git a/lib/widgets/collection/grid/section_layout.dart b/lib/widgets/collection/grid/section_layout.dart index 785ea1cf4..bc69a9961 100644 --- a/lib/widgets/collection/grid/section_layout.dart +++ b/lib/widgets/collection/grid/section_layout.dart @@ -9,6 +9,7 @@ class SectionedEntryListLayoutProvider extends SectionedListLayoutProvider _GridSelectionGestureDetectorState(); @@ -39,7 +40,7 @@ class _GridSelectionGestureDetectorState extends State widget.collection; - List get entries => collection.sortedEntries; + List get entries => collection.sortedEntries; ScrollController get scrollController => widget.scrollController; diff --git a/lib/widgets/collection/thumbnail/error.dart b/lib/widgets/collection/thumbnail/error.dart index 7345a4198..d55fcb99c 100644 --- a/lib/widgets/collection/thumbnail/error.dart +++ b/lib/widgets/collection/thumbnail/error.dart @@ -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(); diff --git a/lib/widgets/collection/thumbnail/theme.dart b/lib/widgets/collection/thumbnail/theme.dart index 12e92f90d..b3581d4b3 100644 --- a/lib/widgets/collection/thumbnail/theme.dart +++ b/lib/widgets/collection/thumbnail/theme.dart @@ -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) { diff --git a/lib/widgets/common/action_mixins/feedback.dart b/lib/widgets/common/action_mixins/feedback.dart index e045435fa..06c3ff7c6 100644 --- a/lib/widgets/common/action_mixins/feedback.dart +++ b/lib/widgets/common/action_mixins/feedback.dart @@ -50,10 +50,11 @@ class ReportOverlay extends StatefulWidget { final void Function(Set processed) onDone; const ReportOverlay({ + Key? key, required this.opStream, required this.itemCount, required this.onDone, - }); + }) : super(key: key); @override _ReportOverlayState createState() => _ReportOverlayState(); diff --git a/lib/widgets/common/app_bar_subtitle.dart b/lib/widgets/common/app_bar_subtitle.dart index abf2761a5..d65dcdc4f 100644 --- a/lib/widgets/common/app_bar_subtitle.dart +++ b/lib/widgets/common/app_bar_subtitle.dart @@ -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) { diff --git a/lib/widgets/common/app_bar_title.dart b/lib/widgets/common/app_bar_title.dart index 5b0c25330..57101d04b 100644 --- a/lib/widgets/common/app_bar_title.dart +++ b/lib/widgets/common/app_bar_title.dart @@ -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) { diff --git a/lib/widgets/common/aves_highlight.dart b/lib/widgets/common/aves_highlight.dart index 876604465..1ae123586 100644 --- a/lib/widgets/common/aves_highlight.dart +++ b/lib/widgets/common/aves_highlight.dart @@ -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 _convert(List nodes) { final spans = []; diff --git a/lib/widgets/common/basic/insets.dart b/lib/widgets/common/basic/insets.dart index 47ef0bdd2..af2f44867 100644 --- a/lib/widgets/common/basic/insets.dart +++ b/lib/widgets/common/basic/insets.dart @@ -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( @@ -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( diff --git a/lib/widgets/common/basic/multi_cross_fader.dart b/lib/widgets/common/basic/multi_cross_fader.dart index 5736bf622..ebf7a7e99 100644 --- a/lib/widgets/common/basic/multi_cross_fader.dart +++ b/lib/widgets/common/basic/multi_cross_fader.dart @@ -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(); diff --git a/lib/widgets/common/basic/query_bar.dart b/lib/widgets/common/basic/query_bar.dart index 2a35774b5..3100c1a5c 100644 --- a/lib/widgets/common/basic/query_bar.dart +++ b/lib/widgets/common/basic/query_bar.dart @@ -9,7 +9,10 @@ import 'package:flutter/widgets.dart'; class QueryBar extends StatefulWidget { final ValueNotifier filterNotifier; - const QueryBar({required this.filterNotifier}); + const QueryBar({ + Key? key, + required this.filterNotifier, + }) : super(key: key); @override _QueryBarState createState() => _QueryBarState(); diff --git a/lib/widgets/common/behaviour/double_back_pop.dart b/lib/widgets/common/behaviour/double_back_pop.dart index 8118bea01..6b198c293 100644 --- a/lib/widgets/common/behaviour/double_back_pop.dart +++ b/lib/widgets/common/behaviour/double_back_pop.dart @@ -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(); diff --git a/lib/widgets/common/fx/sweeper.dart b/lib/widgets/common/fx/sweeper.dart index 1c3c6851a..5be9447e7 100644 --- a/lib/widgets/common/fx/sweeper.dart +++ b/lib/widgets/common/fx/sweeper.dart @@ -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; diff --git a/lib/widgets/common/fx/transition_image.dart b/lib/widgets/common/fx/transition_image.dart index f75c65bab..01598fbe2 100644 --- a/lib/widgets/common/fx/transition_image.dart +++ b/lib/widgets/common/fx/transition_image.dart @@ -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(); diff --git a/lib/widgets/common/grid/draggable_thumb_label.dart b/lib/widgets/common/grid/draggable_thumb_label.dart index d82161d3a..6650405f8 100644 --- a/lib/widgets/common/grid/draggable_thumb_label.dart +++ b/lib/widgets/common/grid/draggable_thumb_label.dart @@ -9,9 +9,10 @@ class DraggableThumbLabel extends StatelessWidget { final List Function(BuildContext context, T item) lineBuilder; const DraggableThumbLabel({ + Key? key, required this.offsetY, required this.lineBuilder, - }); + }) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/widgets/common/grid/header.dart b/lib/widgets/common/grid/header.dart index ed4b1fd3d..b6205baf6 100644 --- a/lib/widgets/common/grid/header.dart +++ b/lib/widgets/common/grid/header.dart @@ -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, diff --git a/lib/widgets/common/grid/section_layout.dart b/lib/widgets/common/grid/section_layout.dart index fa4c8b25f..ed8ce5ccb 100644 --- a/lib/widgets/common/grid/section_layout.dart +++ b/lib/widgets/common/grid/section_layout.dart @@ -18,6 +18,7 @@ abstract class SectionedListLayoutProvider 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 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) { diff --git a/lib/widgets/common/grid/sliver.dart b/lib/widgets/common/grid/sliver.dart index b54afd3ae..e85987128 100644 --- a/lib/widgets/common/grid/sliver.dart +++ b/lib/widgets/common/grid/sliver.dart @@ -14,6 +14,8 @@ import 'package:provider/provider.dart'; // cf https://github.com/flutter/flutter/issues/49027 // adapted from `RenderSliverFixedExtentBoxAdaptor` class SectionedListSliver extends StatelessWidget { + const SectionedListSliver({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { final sectionLayouts = context.watch>().sectionLayouts; diff --git a/lib/widgets/common/identity/aves_expansion_tile.dart b/lib/widgets/common/identity/aves_expansion_tile.dart index 09f6352c9..f745c79a4 100644 --- a/lib/widgets/common/identity/aves_expansion_tile.dart +++ b/lib/widgets/common/identity/aves_expansion_tile.dart @@ -12,6 +12,7 @@ class AvesExpansionTile extends StatelessWidget { final List 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, diff --git a/lib/widgets/common/identity/aves_logo.dart b/lib/widgets/common/identity/aves_logo.dart index 89ded5caa..89abc6903 100644 --- a/lib/widgets/common/identity/aves_logo.dart +++ b/lib/widgets/common/identity/aves_logo.dart @@ -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) { diff --git a/lib/widgets/common/identity/empty.dart b/lib/widgets/common/identity/empty.dart index 27e5ac597..5e54ce377 100644 --- a/lib/widgets/common/identity/empty.dart +++ b/lib/widgets/common/identity/empty.dart @@ -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) { diff --git a/lib/widgets/common/identity/highlight_title.dart b/lib/widgets/common/identity/highlight_title.dart index 8d9c95a93..07ccd9b98 100644 --- a/lib/widgets/common/identity/highlight_title.dart +++ b/lib/widgets/common/identity/highlight_title.dart @@ -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; diff --git a/lib/widgets/common/magnifier/core/scale_gesture_recognizer.dart b/lib/widgets/common/magnifier/core/scale_gesture_recognizer.dart index 138efa424..54b229b94 100644 --- a/lib/widgets/common/magnifier/core/scale_gesture_recognizer.dart +++ b/lib/widgets/common/magnifier/core/scale_gesture_recognizer.dart @@ -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 diff --git a/lib/widgets/common/magnifier/pan/gesture_detector_scope.dart b/lib/widgets/common/magnifier/pan/gesture_detector_scope.dart index e135cf181..9763bc1f6 100644 --- a/lib/widgets/common/magnifier/pan/gesture_detector_scope.dart +++ b/lib/widgets/common/magnifier/pan/gesture_detector_scope.dart @@ -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(); diff --git a/lib/widgets/common/providers/highlight_info_provider.dart b/lib/widgets/common/providers/highlight_info_provider.dart index a1de6717a..22889f0cc 100644 --- a/lib/widgets/common/providers/highlight_info_provider.dart +++ b/lib/widgets/common/providers/highlight_info_provider.dart @@ -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) { diff --git a/lib/widgets/common/providers/media_query_data_provider.dart b/lib/widgets/common/providers/media_query_data_provider.dart index dc44699f9..302b6f8f4 100644 --- a/lib/widgets/common/providers/media_query_data_provider.dart +++ b/lib/widgets/common/providers/media_query_data_provider.dart @@ -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) { diff --git a/lib/widgets/common/providers/tile_extent_controller_provider.dart b/lib/widgets/common/providers/tile_extent_controller_provider.dart index 19701e48b..4bc322343 100644 --- a/lib/widgets/common/providers/tile_extent_controller_provider.dart +++ b/lib/widgets/common/providers/tile_extent_controller_provider.dart @@ -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) { diff --git a/lib/widgets/common/scaling.dart b/lib/widgets/common/scaling.dart index c6077383e..3dccaa5e0 100644 --- a/lib/widgets/common/scaling.dart +++ b/lib/widgets/common/scaling.dart @@ -24,12 +24,13 @@ class GridScaleGestureDetector 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(); @@ -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 { gradient: RadialGradient( center: FractionalOffset.fromOffsetAndSize(center, context.select((mq) => mq.size)), radius: 1, - colors: [ + colors: const [ Colors.black, Colors.black54, ], diff --git a/lib/widgets/debug/android_apps.dart b/lib/widgets/debug/android_apps.dart index fa39ddb39..eeaf09a44 100644 --- a/lib/widgets/debug/android_apps.dart +++ b/lib/widgets/debug/android_apps.dart @@ -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(); } diff --git a/lib/widgets/debug/android_dirs.dart b/lib/widgets/debug/android_dirs.dart index 98e49f0cc..ddf426495 100644 --- a/lib/widgets/debug/android_dirs.dart +++ b/lib/widgets/debug/android_dirs.dart @@ -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 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); }, ), ), diff --git a/lib/widgets/debug/android_env.dart b/lib/widgets/debug/android_env.dart index a7893c609..338e9c7a8 100644 --- a/lib/widgets/debug/android_env.dart +++ b/lib/widgets/debug/android_env.dart @@ -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 MapEntry(k.toString(), v?.toString() ?? 'null'))); - return InfoRowGroup(data); + return InfoRowGroup(info: data); }, ), ), diff --git a/lib/widgets/debug/app_debug_page.dart b/lib/widgets/debug/app_debug_page.dart index ce6a93b87..8ac9e89ea 100644 --- a/lib/widgets/debug/app_debug_page.dart +++ b/lib/widgets/debug/app_debug_page.dart @@ -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 createState() => _AppDebugPageState(); } @@ -42,14 +44,14 @@ class _AppDebugPageState extends State { 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 { _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 { 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}', diff --git a/lib/widgets/debug/cache.dart b/lib/widgets/debug/cache.dart index 8ab1cf38b..55f93711d 100644 --- a/lib/widgets/debug/cache.dart +++ b/lib/widgets/debug/cache.dart @@ -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(); } diff --git a/lib/widgets/debug/database.dart b/lib/widgets/debug/database.dart index ef7e25d89..2b9eca4fe 100644 --- a/lib/widgets/debug/database.dart +++ b/lib/widgets/debug/database.dart @@ -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(); } diff --git a/lib/widgets/debug/firebase.dart b/lib/widgets/debug/firebase.dart index c63291a74..c4c1fee0c 100644 --- a/lib/widgets/debug/firebase.dart +++ b/lib/widgets/debug/firebase.dart @@ -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({ - 'Firebase data collection enabled': '${Firebase.app().isAutomaticDataCollectionEnabled}', - 'Crashlytics collection enabled': '${FirebaseCrashlytics.instance.isCrashlyticsCollectionEnabled}', - }), + child: InfoRowGroup( + info: { + 'Firebase data collection enabled': '${Firebase.app().isAutomaticDataCollectionEnabled}', + 'Crashlytics collection enabled': '${FirebaseCrashlytics.instance.isCrashlyticsCollectionEnabled}', + }, + ), ) ], ); diff --git a/lib/widgets/debug/overlay.dart b/lib/widgets/debug/overlay.dart index 8fcae7b2c..66850d309 100644 --- a/lib/widgets/debug/overlay.dart +++ b/lib/widgets/debug/overlay.dart @@ -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( diff --git a/lib/widgets/debug/settings.dart b/lib/widgets/debug/settings.dart index def93f0c1..7281cb111 100644 --- a/lib/widgets/debug/settings.dart +++ b/lib/widgets/debug/settings.dart @@ -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( @@ -36,21 +38,23 @@ class DebugSettingsSection extends StatelessWidget { ), Padding( padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8), - child: InfoRowGroup({ - 'tileExtent - Collection': '${settings.getTileExtent(CollectionPage.routeName)}', - 'tileExtent - Albums': '${settings.getTileExtent(AlbumListPage.routeName)}', - 'tileExtent - Countries': '${settings.getTileExtent(CountryListPage.routeName)}', - 'tileExtent - Tags': '${settings.getTileExtent(TagListPage.routeName)}', - 'infoMapZoom': '${settings.infoMapZoom}', - 'viewerQuickActions': '${settings.viewerQuickActions}', - 'videoQuickActions': '${settings.videoQuickActions}', - 'pinnedFilters': toMultiline(settings.pinnedFilters), - 'hiddenFilters': toMultiline(settings.hiddenFilters), - 'searchHistory': toMultiline(settings.searchHistory), - 'lastVersionCheckDate': '${settings.lastVersionCheckDate}', - 'locale': '${settings.locale}', - 'systemLocale': '${WidgetsBinding.instance!.window.locale}', - }), + child: InfoRowGroup( + info: { + 'tileExtent - Collection': '${settings.getTileExtent(CollectionPage.routeName)}', + 'tileExtent - Albums': '${settings.getTileExtent(AlbumListPage.routeName)}', + 'tileExtent - Countries': '${settings.getTileExtent(CountryListPage.routeName)}', + 'tileExtent - Tags': '${settings.getTileExtent(TagListPage.routeName)}', + 'infoMapZoom': '${settings.infoMapZoom}', + 'viewerQuickActions': '${settings.viewerQuickActions}', + 'videoQuickActions': '${settings.videoQuickActions}', + 'pinnedFilters': toMultiline(settings.pinnedFilters), + 'hiddenFilters': toMultiline(settings.hiddenFilters), + 'searchHistory': toMultiline(settings.searchHistory), + 'lastVersionCheckDate': '${settings.lastVersionCheckDate}', + 'locale': '${settings.locale}', + 'systemLocale': '${WidgetsBinding.instance!.window.locale}', + }, + ), ), ], ); diff --git a/lib/widgets/debug/storage.dart b/lib/widgets/debug/storage.dart index d4b9ffb12..3b009fbdd 100644 --- a/lib/widgets/debug/storage.dart +++ b/lib/widgets/debug/storage.dart @@ -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 with Automati ), Padding( padding: const EdgeInsets.symmetric(horizontal: 8), - child: InfoRowGroup({ - 'description': '${v.getDescription(context)}', - 'isPrimary': '${v.isPrimary}', - 'isRemovable': '${v.isRemovable}', - 'state': '${v.state}', - if (freeSpace != null) 'freeSpace': formatFilesize(freeSpace), - }), + child: InfoRowGroup( + info: { + 'description': v.getDescription(context), + 'isPrimary': '${v.isPrimary}', + 'isRemovable': '${v.isRemovable}', + 'state': v.state, + if (freeSpace != null) 'freeSpace': formatFilesize(freeSpace), + }, + ), ), const Divider(), ]; diff --git a/lib/widgets/dialogs/add_shortcut_dialog.dart b/lib/widgets/dialogs/add_shortcut_dialog.dart index 82b9c1900..3806617d4 100644 --- a/lib/widgets/dialogs/add_shortcut_dialog.dart +++ b/lib/widgets/dialogs/add_shortcut_dialog.dart @@ -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 { MaterialPageRoute( settings: const RouteSettings(name: ItemPickDialog.routeName), builder: (context) => ItemPickDialog( - CollectionLens( + collection: CollectionLens( source: collection.source, filters: filters, ), diff --git a/lib/widgets/dialogs/aves_dialog.dart b/lib/widgets/dialogs/aves_dialog.dart index c47c4258a..57abc2199 100644 --- a/lib/widgets/dialogs/aves_dialog.dart +++ b/lib/widgets/dialogs/aves_dialog.dart @@ -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 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) { diff --git a/lib/widgets/dialogs/aves_selection_dialog.dart b/lib/widgets/dialogs/aves_selection_dialog.dart index c1323b2e0..9db644f29 100644 --- a/lib/widgets/dialogs/aves_selection_dialog.dart +++ b/lib/widgets/dialogs/aves_selection_dialog.dart @@ -13,11 +13,12 @@ class AvesSelectionDialog 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 createState() => _AvesSelectionDialogState(); diff --git a/lib/widgets/dialogs/cover_selection_dialog.dart b/lib/widgets/dialogs/cover_selection_dialog.dart index eefa7f90d..860f1c979 100644 --- a/lib/widgets/dialogs/cover_selection_dialog.dart +++ b/lib/widgets/dialogs/cover_selection_dialog.dart @@ -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 { MaterialPageRoute( settings: const RouteSettings(name: ItemPickDialog.routeName), builder: (context) => ItemPickDialog( - CollectionLens( + collection: CollectionLens( source: context.read(), filters: [filter], ), diff --git a/lib/widgets/dialogs/create_album_dialog.dart b/lib/widgets/dialogs/create_album_dialog.dart index c66a98d53..8aa6bf286 100644 --- a/lib/widgets/dialogs/create_album_dialog.dart +++ b/lib/widgets/dialogs/create_album_dialog.dart @@ -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(); } diff --git a/lib/widgets/dialogs/item_pick_dialog.dart b/lib/widgets/dialogs/item_pick_dialog.dart index 03cf7c8f0..f4cd6a1d7 100644 --- a/lib/widgets/dialogs/item_pick_dialog.dart +++ b/lib/widgets/dialogs/item_pick_dialog.dart @@ -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(); diff --git a/lib/widgets/dialogs/rename_album_dialog.dart b/lib/widgets/dialogs/rename_album_dialog.dart index 4e5080972..ed54f9874 100644 --- a/lib/widgets/dialogs/rename_album_dialog.dart +++ b/lib/widgets/dialogs/rename_album_dialog.dart @@ -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(); diff --git a/lib/widgets/dialogs/rename_entry_dialog.dart b/lib/widgets/dialogs/rename_entry_dialog.dart index 39c343e84..80b859ef8 100644 --- a/lib/widgets/dialogs/rename_entry_dialog.dart +++ b/lib/widgets/dialogs/rename_entry_dialog.dart @@ -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(); diff --git a/lib/widgets/dialogs/video_speed_dialog.dart b/lib/widgets/dialogs/video_speed_dialog.dart index 280234aa5..e1afe9109 100644 --- a/lib/widgets/dialogs/video_speed_dialog.dart +++ b/lib/widgets/dialogs/video_speed_dialog.dart @@ -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(); diff --git a/lib/widgets/dialogs/video_stream_selection_dialog.dart b/lib/widgets/dialogs/video_stream_selection_dialog.dart index cbe9dfb08..beab821c5 100644 --- a/lib/widgets/dialogs/video_stream_selection_dialog.dart +++ b/lib/widgets/dialogs/video_stream_selection_dialog.dart @@ -12,8 +12,9 @@ class VideoStreamSelectionDialog extends StatefulWidget { final Map streams; const VideoStreamSelectionDialog({ + Key? key, required this.streams, - }); + }) : super(key: key); @override _VideoStreamSelectionDialogState createState() => _VideoStreamSelectionDialogState(); diff --git a/lib/widgets/drawer/album_tile.dart b/lib/widgets/drawer/album_tile.dart index d9e1f5830..bcb41c34a 100644 --- a/lib/widgets/drawer/album_tile.dart +++ b/lib/widgets/drawer/album_tile.dart @@ -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) { diff --git a/lib/widgets/drawer/app_drawer.dart b/lib/widgets/drawer/app_drawer.dart index b7c6b80dc..65cb80d1b 100644 --- a/lib/widgets/drawer/app_drawer.dart +++ b/lib/widgets/drawer/app_drawer.dart @@ -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 { 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 { ), 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 { return Column( children: [ const Divider(), - ...specialAlbums.map((album) => AlbumTile(album)), + ...specialAlbums.map((album) => AlbumTile(album: album)), ], ); }); @@ -238,7 +240,7 @@ class _AppDrawerState extends State { 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 { 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 { 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 { title: 'Debug', topLevel: false, routeName: AppDebugPage.routeName, - pageBuilder: (_) => AppDebugPage(), + pageBuilder: (_) => const AppDebugPage(), ); } diff --git a/lib/widgets/drawer/collection_tile.dart b/lib/widgets/drawer/collection_tile.dart index 667f92d85..761c9c529 100644 --- a/lib/widgets/drawer/collection_tile.dart +++ b/lib/widgets/drawer/collection_tile.dart @@ -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( - source: context.read(), - filters: [filter], - )), + builder: (context) => CollectionPage( + collection: CollectionLens( + source: context.read(), + filters: [filter], + ), + ), ), (route) => false, ); diff --git a/lib/widgets/drawer/tile.dart b/lib/widgets/drawer/tile.dart index 5fce6f524..3b250e79d 100644 --- a/lib/widgets/drawer/tile.dart +++ b/lib/widgets/drawer/tile.dart @@ -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) { diff --git a/lib/widgets/filter_grids/album_pick.dart b/lib/widgets/filter_grids/album_pick.dart index 5f9b714c1..f69ad73cd 100644 --- a/lib/widgets/filter_grids/album_pick.dart +++ b/lib/widgets/filter_grids/album_pick.dart @@ -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( context: context, - builder: (context) => CreateAlbumDialog(), + builder: (context) => const CreateAlbumDialog(), ); if (newAlbum != null && newAlbum.isNotEmpty) { Navigator.pop(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); diff --git a/lib/widgets/filter_grids/albums_page.dart b/lib/widgets/filter_grids/albums_page.dart index 1fe283f34..3203844f2 100644 --- a/lib/widgets/filter_grids/albums_page.dart +++ b/lib/widgets/filter_grids/albums_page.dart @@ -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(); diff --git a/lib/widgets/filter_grids/common/chip_action_delegate.dart b/lib/widgets/filter_grids/common/chip_action_delegate.dart index 5b0cf1143..6e1766157 100644 --- a/lib/widgets/filter_grids/common/chip_action_delegate.dart +++ b/lib/widgets/filter_grids/common/chip_action_delegate.dart @@ -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( context: context, - builder: (context) => RenameAlbumDialog(album), + builder: (context) => RenameAlbumDialog(album: album), ); if (newName == null || newName.isEmpty) return; diff --git a/lib/widgets/filter_grids/common/draggable_thumb_label.dart b/lib/widgets/filter_grids/common/draggable_thumb_label.dart index 0967c385c..433c54867 100644 --- a/lib/widgets/filter_grids/common/draggable_thumb_label.dart +++ b/lib/widgets/filter_grids/common/draggable_thumb_label.dart @@ -11,9 +11,10 @@ class FilterDraggableThumbLabel extends StatelessWid final double offsetY; const FilterDraggableThumbLabel({ + Key? key, required this.sortFactor, required this.offsetY, - }); + }) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/widgets/filter_grids/common/filter_grid_page.dart b/lib/widgets/filter_grids/common/filter_grid_page.dart index 3ddc72ab8..539612342 100644 --- a/lib/widgets/filter_grids/common/filter_grid_page.dart +++ b/lib/widgets/filter_grids/common/filter_grid_page.dart @@ -91,7 +91,7 @@ class FilterGridPage extends StatelessWidget { ), ), ), - drawer: AppDrawer(), + drawer: const AppDrawer(), resizeToAvoidBottomInset: false, ), ); @@ -454,7 +454,7 @@ class _FilterScrollView extends StatelessWidget { ) : SectionedListSliver>(); }), - BottomPaddingSliver(), + const BottomPaddingSliver(), ], ); } diff --git a/lib/widgets/filter_grids/common/filter_nav_page.dart b/lib/widgets/filter_grids/common/filter_nav_page.dart index c5dbb7499..2fe5905e8 100644 --- a/lib/widgets/filter_grids/common/filter_nav_page.dart +++ b/lib/widgets/filter_grids/common/filter_nav_page.dart @@ -37,6 +37,7 @@ class FilterNavigationPage 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 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 extends StatelessWidget { context, MaterialPageRoute( settings: const RouteSettings(name: CollectionPage.routeName), - builder: (context) => CollectionPage(CollectionLens( - source: source, - filters: [filter], - )), + builder: (context) => CollectionPage( + collection: CollectionLens( + source: source, + filters: [filter], + ), + ), ), ), onLongPress: isMainMode ? _showMenu as OffsetFilterCallback : null, @@ -111,7 +114,7 @@ class FilterNavigationPage extends StatelessWidget { List _buildActions(BuildContext context) { return [ - CollectionSearchButton(source), + CollectionSearchButton(source: source), PopupMenuButton( key: const Key('appbar-menu-button'), itemBuilder: (context) { diff --git a/lib/widgets/filter_grids/common/section_layout.dart b/lib/widgets/filter_grids/common/section_layout.dart index ab9f1e091..c46571900 100644 --- a/lib/widgets/filter_grids/common/section_layout.dart +++ b/lib/widgets/filter_grids/common/section_layout.dart @@ -7,6 +7,7 @@ import 'package:flutter/material.dart'; class SectionedFilterListLayoutProvider extends SectionedListLayoutProvider> { const SectionedFilterListLayoutProvider({ + Key? key, required this.sections, required this.showHeaders, required double scrollableWidth, @@ -17,6 +18,7 @@ class SectionedFilterListLayoutProvider extends Sect required Duration tileAnimationDelay, required Widget child, }) : super( + key: key, scrollableWidth: scrollableWidth, columnCount: columnCount, spacing: spacing, diff --git a/lib/widgets/filter_grids/countries_page.dart b/lib/widgets/filter_grids/countries_page.dart index 84f81beb1..98039f9aa 100644 --- a/lib/widgets/filter_grids/countries_page.dart +++ b/lib/widgets/filter_grids/countries_page.dart @@ -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(); diff --git a/lib/widgets/filter_grids/tags_page.dart b/lib/widgets/filter_grids/tags_page.dart index f9b1f1768..8fe3328a9 100644 --- a/lib/widgets/filter_grids/tags_page.dart +++ b/lib/widgets/filter_grids/tags_page.dart @@ -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(); diff --git a/lib/widgets/home_page.dart b/lib/widgets/home_page.dart index fb8bdbffb..39bc3722e 100644 --- a/lib/widgets/home_page.dart +++ b/lib/widgets/home_page.dart @@ -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 { 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 { return DirectMaterialPageRoute( settings: const RouteSettings(name: CollectionPage.routeName), builder: (_) => CollectionPage( - CollectionLens( + collection: CollectionLens( source: source, filters: filters, ), diff --git a/lib/widgets/search/expandable_filter_row.dart b/lib/widgets/search/expandable_filter_row.dart index 28ae3a10c..10995787a 100644 --- a/lib/widgets/search/expandable_filter_row.dart +++ b/lib/widgets/search/expandable_filter_row.dart @@ -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; diff --git a/lib/widgets/search/search_button.dart b/lib/widgets/search/search_button.dart index 21f37df81..95edb3557 100644 --- a/lib/widgets/search/search_button.dart +++ b/lib/widgets/search/search_button.dart @@ -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) { diff --git a/lib/widgets/search/search_delegate.dart b/lib/widgets/search/search_delegate.dart index 254ffc014..fef50a63a 100644 --- a/lib/widgets/search/search_delegate.dart +++ b/lib/widgets/search/search_delegate.dart @@ -243,10 +243,12 @@ class CollectionSearchDelegate { context, MaterialPageRoute( settings: const RouteSettings(name: CollectionPage.routeName), - builder: (context) => CollectionPage(CollectionLens( - source: source, - filters: [filter], - )), + builder: (context) => CollectionPage( + collection: CollectionLens( + source: source, + filters: [filter], + ), + ), ), (route) => false, ); diff --git a/lib/widgets/search/search_page.dart b/lib/widgets/search/search_page.dart index 534e0858a..2d182a66d 100644 --- a/lib/widgets/search/search_page.dart +++ b/lib/widgets/search/search_page.dart @@ -12,9 +12,10 @@ class SearchPage extends StatefulWidget { final Animation animation; const SearchPage({ + Key? key, required this.delegate, required this.animation, - }); + }) : super(key: key); @override _SearchPageState createState() => _SearchPageState(); diff --git a/lib/widgets/settings/common/quick_actions/action_button.dart b/lib/widgets/settings/common/quick_actions/action_button.dart index 47c0f90d4..9e8c7f647 100644 --- a/lib/widgets/settings/common/quick_actions/action_button.dart +++ b/lib/widgets/settings/common/quick_actions/action_button.dart @@ -7,11 +7,12 @@ class ActionButton extends StatelessWidget { final bool enabled, showCaption; const ActionButton({ + Key? key, required this.text, required this.icon, this.enabled = true, this.showCaption = true, - }); + }) : super(key: key); static const padding = 8.0; diff --git a/lib/widgets/settings/common/quick_actions/action_panel.dart b/lib/widgets/settings/common/quick_actions/action_panel.dart index ba56c2d50..a1240dc17 100644 --- a/lib/widgets/settings/common/quick_actions/action_panel.dart +++ b/lib/widgets/settings/common/quick_actions/action_panel.dart @@ -6,9 +6,10 @@ class ActionPanel extends StatelessWidget { final Widget child; const ActionPanel({ + Key? key, this.highlight = false, required this.child, - }); + }) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/widgets/settings/common/quick_actions/available_actions.dart b/lib/widgets/settings/common/quick_actions/available_actions.dart index 602774c00..be1044939 100644 --- a/lib/widgets/settings/common/quick_actions/available_actions.dart +++ b/lib/widgets/settings/common/quick_actions/available_actions.dart @@ -14,6 +14,7 @@ class AvailableActionPanel extends StatelessWidget { final String Function(BuildContext context, T action) actionText; const AvailableActionPanel({ + Key? key, required this.allActions, required this.quickActions, required this.quickActionsChangeNotifier, @@ -23,7 +24,7 @@ class AvailableActionPanel extends StatelessWidget { required this.removeQuickAction, required this.actionIcon, required this.actionText, - }); + }) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/widgets/settings/common/quick_actions/editor_page.dart b/lib/widgets/settings/common/quick_actions/editor_page.dart index f36f22888..37058f902 100644 --- a/lib/widgets/settings/common/quick_actions/editor_page.dart +++ b/lib/widgets/settings/common/quick_actions/editor_page.dart @@ -24,6 +24,7 @@ class QuickActionEditorPage extends StatefulWidget { final void Function(List actions) save; const QuickActionEditorPage({ + Key? key, required this.title, required this.bannerText, required this.allAvailableActions, @@ -31,7 +32,7 @@ class QuickActionEditorPage extends StatefulWidget { required this.actionText, required this.load, required this.save, - }); + }) : super(key: key); @override _QuickActionEditorPageState createState() => _QuickActionEditorPageState(); @@ -131,7 +132,7 @@ class _QuickActionEditorPageState extends State extends StatelessWidget { final Widget? child; const QuickActionButton({ + Key? key, required this.placement, this.action, required this.panelHighlight, @@ -26,7 +27,7 @@ class QuickActionButton extends StatelessWidget { required this.onTargetLeave, this.draggableFeedbackBuilder, this.child, - }); + }) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/widgets/settings/language/language.dart b/lib/widgets/settings/language/language.dart index d9526106e..ab6f79186 100644 --- a/lib/widgets/settings/language/language.dart +++ b/lib/widgets/settings/language/language.dart @@ -36,7 +36,7 @@ class LanguageSection extends StatelessWidget { expandedNotifier: expandedNotifier, showHighlight: false, children: [ - LocaleTile(), + const LocaleTile(), ListTile( title: Text(context.l10n.settingsCoordinateFormatTile), subtitle: Text(currentCoordinateFormat.getName(context)), diff --git a/lib/widgets/settings/language/locale.dart b/lib/widgets/settings/language/locale.dart index a50768683..2ae5e4e0f 100644 --- a/lib/widgets/settings/language/locale.dart +++ b/lib/widgets/settings/language/locale.dart @@ -12,12 +12,14 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; class LocaleTile extends StatelessWidget { static const _systemLocaleOption = Locale('system'); + const LocaleTile({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { final current = settings.locale; return ListTile( title: Text(context.l10n.settingsLanguage), - subtitle: Text('${current == null ? context.l10n.settingsSystemDefault : _getLocaleName(current)}'), + subtitle: Text(current == null ? context.l10n.settingsSystemDefault : _getLocaleName(current)), onTap: () async { final value = await showDialog( context: context, diff --git a/lib/widgets/settings/privacy/access_grants.dart b/lib/widgets/settings/privacy/access_grants.dart index 23ae4a6dd..c6843bc7b 100644 --- a/lib/widgets/settings/privacy/access_grants.dart +++ b/lib/widgets/settings/privacy/access_grants.dart @@ -5,6 +5,8 @@ import 'package:aves/widgets/common/identity/empty.dart'; import 'package:flutter/material.dart'; class StorageAccessTile extends StatelessWidget { + const StorageAccessTile({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return ListTile( @@ -14,7 +16,7 @@ class StorageAccessTile extends StatelessWidget { context, MaterialPageRoute( settings: const RouteSettings(name: StorageAccessPage.routeName), - builder: (context) => StorageAccessPage(), + builder: (context) => const StorageAccessPage(), ), ); }, @@ -25,6 +27,8 @@ class StorageAccessTile extends StatelessWidget { class StorageAccessPage extends StatefulWidget { static const routeName = '/settings/storage_access'; + const StorageAccessPage({Key? key}) : super(key: key); + @override _StorageAccessPageState createState() => _StorageAccessPageState(); } diff --git a/lib/widgets/settings/privacy/hidden_filters.dart b/lib/widgets/settings/privacy/hidden_filters.dart index 0d7ab2768..4d4590506 100644 --- a/lib/widgets/settings/privacy/hidden_filters.dart +++ b/lib/widgets/settings/privacy/hidden_filters.dart @@ -9,6 +9,8 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class HiddenFilterTile extends StatelessWidget { + const HiddenFilterTile({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return ListTile( @@ -18,7 +20,7 @@ class HiddenFilterTile extends StatelessWidget { context, MaterialPageRoute( settings: const RouteSettings(name: HiddenFilterPage.routeName), - builder: (context) => HiddenFilterPage(), + builder: (context) => const HiddenFilterPage(), ), ); }, @@ -29,6 +31,8 @@ class HiddenFilterTile extends StatelessWidget { class HiddenFilterPage extends StatelessWidget { static const routeName = '/settings/hidden'; + const HiddenFilterPage({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( diff --git a/lib/widgets/settings/privacy/privacy.dart b/lib/widgets/settings/privacy/privacy.dart index 3babb19e4..713717b38 100644 --- a/lib/widgets/settings/privacy/privacy.dart +++ b/lib/widgets/settings/privacy/privacy.dart @@ -46,8 +46,8 @@ class PrivacySection extends StatelessWidget { }, title: Text(context.l10n.settingsSaveSearchHistory), ), - HiddenFilterTile(), - StorageAccessTile(), + const HiddenFilterTile(), + const StorageAccessTile(), ], ); } diff --git a/lib/widgets/settings/settings_page.dart b/lib/widgets/settings/settings_page.dart index 55177c2b6..aef10de24 100644 --- a/lib/widgets/settings/settings_page.dart +++ b/lib/widgets/settings/settings_page.dart @@ -13,6 +13,8 @@ import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; class SettingsPage extends StatefulWidget { static const routeName = '/settings'; + const SettingsPage({Key? key}) : super(key: key); + @override _SettingsPageState createState() => _SettingsPageState(); } diff --git a/lib/widgets/settings/video/subtitle_theme.dart b/lib/widgets/settings/video/subtitle_theme.dart index 1d5a3d776..072e14447 100644 --- a/lib/widgets/settings/video/subtitle_theme.dart +++ b/lib/widgets/settings/video/subtitle_theme.dart @@ -8,6 +8,8 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class SubtitleThemeTile extends StatelessWidget { + const SubtitleThemeTile({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return ListTile( @@ -17,7 +19,7 @@ class SubtitleThemeTile extends StatelessWidget { context, MaterialPageRoute( settings: const RouteSettings(name: SubtitleThemePage.routeName), - builder: (context) => SubtitleThemePage(), + builder: (context) => const SubtitleThemePage(), ), ); }, @@ -30,6 +32,8 @@ class SubtitleThemePage extends StatelessWidget { static const textAlignOptions = [TextAlign.left, TextAlign.center, TextAlign.right]; + const SubtitleThemePage({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return Scaffold( diff --git a/lib/widgets/settings/video/video.dart b/lib/widgets/settings/video/video.dart index eb81d51a8..4514d8ebb 100644 --- a/lib/widgets/settings/video/video.dart +++ b/lib/widgets/settings/video/video.dart @@ -39,7 +39,7 @@ class VideoSection extends StatelessWidget { onChanged: (v) => context.read().changeFilterVisibility(MimeFilter.video, v), title: Text(context.l10n.settingsVideoShowVideos), ), - VideoActionsTile(), + const VideoActionsTile(), SwitchListTile( value: currentEnableVideoHardwareAcceleration, onChanged: (v) => settings.enableVideoHardwareAcceleration = v, @@ -67,7 +67,7 @@ class VideoSection extends StatelessWidget { } }, ), - SubtitleThemeTile(), + const SubtitleThemeTile(), ]; return standalonePage diff --git a/lib/widgets/settings/video/video_actions_editor.dart b/lib/widgets/settings/video/video_actions_editor.dart index b0b5763c1..d0429ffa2 100644 --- a/lib/widgets/settings/video/video_actions_editor.dart +++ b/lib/widgets/settings/video/video_actions_editor.dart @@ -5,6 +5,8 @@ import 'package:aves/widgets/settings/common/quick_actions/editor_page.dart'; import 'package:flutter/material.dart'; class VideoActionsTile extends StatelessWidget { + const VideoActionsTile({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return ListTile( diff --git a/lib/widgets/settings/viewer/entry_background.dart b/lib/widgets/settings/viewer/entry_background.dart index 5f2c59ba6..acf78076c 100644 --- a/lib/widgets/settings/viewer/entry_background.dart +++ b/lib/widgets/settings/viewer/entry_background.dart @@ -9,9 +9,10 @@ class EntryBackgroundSelector extends StatefulWidget { final ValueSetter setter; const EntryBackgroundSelector({ + Key? key, required this.getter, required this.setter, - }); + }) : super(key: key); @override _EntryBackgroundSelectorState createState() => _EntryBackgroundSelectorState(); diff --git a/lib/widgets/settings/viewer/viewer.dart b/lib/widgets/settings/viewer/viewer.dart index cb03db693..1b1721439 100644 --- a/lib/widgets/settings/viewer/viewer.dart +++ b/lib/widgets/settings/viewer/viewer.dart @@ -35,7 +35,7 @@ class ViewerSection extends StatelessWidget { expandedNotifier: expandedNotifier, showHighlight: false, children: [ - ViewerActionsTile(), + const ViewerActionsTile(), SwitchListTile( value: currentShowOverlayMinimap, onChanged: (v) => settings.showOverlayMinimap = v, diff --git a/lib/widgets/settings/viewer/viewer_actions_editor.dart b/lib/widgets/settings/viewer/viewer_actions_editor.dart index 7793f661f..3ceeb3c16 100644 --- a/lib/widgets/settings/viewer/viewer_actions_editor.dart +++ b/lib/widgets/settings/viewer/viewer_actions_editor.dart @@ -5,6 +5,8 @@ import 'package:aves/widgets/settings/common/quick_actions/editor_page.dart'; import 'package:flutter/material.dart'; class ViewerActionsTile extends StatelessWidget { + const ViewerActionsTile({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return ListTile( diff --git a/lib/widgets/stats/filter_table.dart b/lib/widgets/stats/filter_table.dart index e5491e59a..36403ffb7 100644 --- a/lib/widgets/stats/filter_table.dart +++ b/lib/widgets/stats/filter_table.dart @@ -14,11 +14,12 @@ class FilterTable extends StatelessWidget { final FilterCallback onFilterSelection; const FilterTable({ + Key? key, required this.totalEntryCount, required this.entryCountMap, required this.filterBuilder, required this.onFilterSelection, - }); + }) : super(key: key); static const chipWidth = AvesFilterChip.maxChipWidth; static const countWidth = 32.0; @@ -80,9 +81,9 @@ class FilterTable extends StatelessWidget { ], ); }).toList(), - columnWidths: { - 0: const MaxColumnWidth(IntrinsicColumnWidth(), FixedColumnWidth(chipWidth)), - 2: const MaxColumnWidth(IntrinsicColumnWidth(), FixedColumnWidth(countWidth)), + columnWidths: const { + 0: MaxColumnWidth(IntrinsicColumnWidth(), FixedColumnWidth(chipWidth)), + 2: MaxColumnWidth(IntrinsicColumnWidth(), FixedColumnWidth(countWidth)), }, defaultVerticalAlignment: TableCellVerticalAlignment.middle, ); diff --git a/lib/widgets/stats/stats.dart b/lib/widgets/stats/stats.dart index d84808cd9..89869bf16 100644 --- a/lib/widgets/stats/stats.dart +++ b/lib/widgets/stats/stats.dart @@ -36,9 +36,10 @@ class StatsPage extends StatelessWidget { static const mimeDonutMinWidth = 124.0; StatsPage({ + Key? key, required this.source, this.parentCollection, - }) { + }) : super(key: key) { entries.forEach((entry) { if (entry.hasAddress) { final address = entry.addressDetails!; @@ -158,7 +159,7 @@ class StatsPage extends StatelessWidget { final availableWidth = constraints.maxWidth; final dim = max(minWidth, availableWidth / (availableWidth > 4 * minWidth ? 4 : (availableWidth > 2 * minWidth ? 2 : 1))); - final donut = Container( + final donut = SizedBox( width: dim, height: dim, child: Stack( @@ -272,10 +273,12 @@ class StatsPage extends StatelessWidget { context, MaterialPageRoute( settings: const RouteSettings(name: CollectionPage.routeName), - builder: (context) => CollectionPage(CollectionLens( - source: source, - filters: [filter], - )), + builder: (context) => CollectionPage( + collection: CollectionLens( + source: source, + filters: [filter], + ), + ), ), (route) => false, ); diff --git a/lib/widgets/viewer/debug/db.dart b/lib/widgets/viewer/debug/db.dart index a6aa3601d..a1a9161b8 100644 --- a/lib/widgets/viewer/debug/db.dart +++ b/lib/widgets/viewer/debug/db.dart @@ -8,7 +8,10 @@ import 'package:flutter/material.dart'; class DbTab extends StatefulWidget { final AvesEntry entry; - const DbTab({required this.entry}); + const DbTab({ + Key? key, + required this.entry, + }) : super(key: key); @override _DbTabState createState() => _DbTabState(); @@ -53,9 +56,11 @@ class _DbTabState extends State { children: [ Text('DB date:${data == null ? ' no row' : ''}'), if (data != null) - InfoRowGroup({ - 'dateMillis': '${data.dateMillis}', - }), + InfoRowGroup( + info: { + 'dateMillis': '${data.dateMillis}', + }, + ), ], ); }, @@ -72,19 +77,21 @@ class _DbTabState extends State { children: [ Text('DB entry:${data == null ? ' no row' : ''}'), if (data != null) - InfoRowGroup({ - 'uri': '${data.uri}', - 'path': '${data.path}', - 'sourceMimeType': '${data.sourceMimeType}', - 'width': '${data.width}', - 'height': '${data.height}', - 'sourceRotationDegrees': '${data.sourceRotationDegrees}', - 'sizeBytes': '${data.sizeBytes}', - 'sourceTitle': '${data.sourceTitle}', - 'dateModifiedSecs': '${data.dateModifiedSecs}', - 'sourceDateTakenMillis': '${data.sourceDateTakenMillis}', - 'durationMillis': '${data.durationMillis}', - }), + InfoRowGroup( + info: { + 'uri': data.uri, + 'path': data.path ?? '', + 'sourceMimeType': data.sourceMimeType, + 'width': '${data.width}', + 'height': '${data.height}', + 'sourceRotationDegrees': '${data.sourceRotationDegrees}', + 'sizeBytes': '${data.sizeBytes}', + 'sourceTitle': data.sourceTitle ?? '', + 'dateModifiedSecs': '${data.dateModifiedSecs}', + 'sourceDateTakenMillis': '${data.sourceDateTakenMillis}', + 'durationMillis': '${data.durationMillis}', + }, + ), ], ); }, @@ -101,17 +108,19 @@ class _DbTabState extends State { children: [ Text('DB metadata:${data == null ? ' no row' : ''}'), if (data != null) - InfoRowGroup({ - 'mimeType': '${data.mimeType}', - 'dateMillis': '${data.dateMillis}', - 'isAnimated': '${data.isAnimated}', - 'isFlipped': '${data.isFlipped}', - 'rotationDegrees': '${data.rotationDegrees}', - 'latitude': '${data.latitude}', - 'longitude': '${data.longitude}', - 'xmpSubjects': '${data.xmpSubjects}', - 'xmpTitleDescription': '${data.xmpTitleDescription}', - }), + InfoRowGroup( + info: { + 'mimeType': data.mimeType ?? '', + 'dateMillis': '${data.dateMillis}', + 'isAnimated': '${data.isAnimated}', + 'isFlipped': '${data.isFlipped}', + 'rotationDegrees': '${data.rotationDegrees}', + 'latitude': '${data.latitude}', + 'longitude': '${data.longitude}', + 'xmpSubjects': data.xmpSubjects ?? '', + 'xmpTitleDescription': data.xmpTitleDescription ?? '', + }, + ), ], ); }, @@ -128,12 +137,14 @@ class _DbTabState extends State { children: [ Text('DB address:${data == null ? ' no row' : ''}'), if (data != null) - InfoRowGroup({ - 'countryCode': '${data.countryCode}', - 'countryName': '${data.countryName}', - 'adminArea': '${data.adminArea}', - 'locality': '${data.locality}', - }), + InfoRowGroup( + info: { + 'countryCode': data.countryCode ?? '', + 'countryName': data.countryName ?? '', + 'adminArea': data.adminArea ?? '', + 'locality': data.locality ?? '', + }, + ), ], ); }, diff --git a/lib/widgets/viewer/debug/debug_page.dart b/lib/widgets/viewer/debug/debug_page.dart index fb6e927a1..d1a68c470 100644 --- a/lib/widgets/viewer/debug/debug_page.dart +++ b/lib/widgets/viewer/debug/debug_page.dart @@ -16,7 +16,10 @@ class ViewerDebugPage extends StatelessWidget { final AvesEntry entry; - const ViewerDebugPage({required this.entry}); + const ViewerDebugPage({ + Key? key, + required this.entry, + }) : super(key: key); @override Widget build(BuildContext context) { @@ -56,62 +59,74 @@ class ViewerDebugPage extends StatelessWidget { return ListView( padding: const EdgeInsets.all(16), children: [ - InfoRowGroup({ - 'uri': '${entry.uri}', - 'contentId': '${entry.contentId}', - 'path': '${entry.path}', - 'directory': '${entry.directory}', - 'filenameWithoutExtension': '${entry.filenameWithoutExtension}', - 'sourceTitle': '${entry.sourceTitle}', - 'sourceMimeType': '${entry.sourceMimeType}', - 'mimeType': '${entry.mimeType}', - }), + InfoRowGroup( + info: { + 'uri': entry.uri, + 'contentId': '${entry.contentId}', + 'path': entry.path ?? '', + 'directory': entry.directory ?? '', + 'filenameWithoutExtension': entry.filenameWithoutExtension ?? '', + 'sourceTitle': entry.sourceTitle ?? '', + 'sourceMimeType': entry.sourceMimeType, + 'mimeType': entry.mimeType, + }, + ), const Divider(), - InfoRowGroup({ - 'dateModifiedSecs': toDateValue(entry.dateModifiedSecs, factor: 1000), - 'sourceDateTakenMillis': toDateValue(entry.sourceDateTakenMillis), - 'bestDate': '${entry.bestDate}', - }), + InfoRowGroup( + info: { + 'dateModifiedSecs': toDateValue(entry.dateModifiedSecs, factor: 1000), + 'sourceDateTakenMillis': toDateValue(entry.sourceDateTakenMillis), + 'bestDate': '${entry.bestDate}', + }, + ), const Divider(), - InfoRowGroup({ - 'width': '${entry.width}', - 'height': '${entry.height}', - 'sourceRotationDegrees': '${entry.sourceRotationDegrees}', - 'rotationDegrees': '${entry.rotationDegrees}', - 'isRotated': '${entry.isRotated}', - 'isFlipped': '${entry.isFlipped}', - 'displayAspectRatio': '${entry.displayAspectRatio}', - 'displaySize': '${entry.displaySize}', - }), + InfoRowGroup( + info: { + 'width': '${entry.width}', + 'height': '${entry.height}', + 'sourceRotationDegrees': '${entry.sourceRotationDegrees}', + 'rotationDegrees': '${entry.rotationDegrees}', + 'isRotated': '${entry.isRotated}', + 'isFlipped': '${entry.isFlipped}', + 'displayAspectRatio': '${entry.displayAspectRatio}', + 'displaySize': '${entry.displaySize}', + }, + ), const Divider(), - InfoRowGroup({ - 'durationMillis': '${entry.durationMillis}', - 'durationText': '${entry.durationText}', - }), + InfoRowGroup( + info: { + 'durationMillis': '${entry.durationMillis}', + 'durationText': entry.durationText, + }, + ), const Divider(), - InfoRowGroup({ - 'sizeBytes': '${entry.sizeBytes}', - 'isFavourite': '${entry.isFavourite}', - 'isSvg': '${entry.isSvg}', - 'isPhoto': '${entry.isPhoto}', - 'isVideo': '${entry.isVideo}', - 'isCatalogued': '${entry.isCatalogued}', - 'isAnimated': '${entry.isAnimated}', - 'isGeotiff': '${entry.isGeotiff}', - 'is360': '${entry.is360}', - 'canEdit': '${entry.canEdit}', - 'canEditExif': '${entry.canEditExif}', - 'canRotateAndFlip': '${entry.canRotateAndFlip}', - 'xmpSubjects': '${entry.xmpSubjects}', - }), + InfoRowGroup( + info: { + 'sizeBytes': '${entry.sizeBytes}', + 'isFavourite': '${entry.isFavourite}', + 'isSvg': '${entry.isSvg}', + 'isPhoto': '${entry.isPhoto}', + 'isVideo': '${entry.isVideo}', + 'isCatalogued': '${entry.isCatalogued}', + 'isAnimated': '${entry.isAnimated}', + 'isGeotiff': '${entry.isGeotiff}', + 'is360': '${entry.is360}', + 'canEdit': '${entry.canEdit}', + 'canEditExif': '${entry.canEditExif}', + 'canRotateAndFlip': '${entry.canRotateAndFlip}', + 'xmpSubjects': '${entry.xmpSubjects}', + }, + ), const Divider(), - InfoRowGroup({ - 'hasGps': '${entry.hasGps}', - 'hasAddress': '${entry.hasAddress}', - 'hasFineAddress': '${entry.hasFineAddress}', - 'latLng': '${entry.latLng}', - 'geoUri': '${entry.geoUri}', - }), + InfoRowGroup( + info: { + 'hasGps': '${entry.hasGps}', + 'hasAddress': '${entry.hasAddress}', + 'hasFineAddress': '${entry.hasFineAddress}', + 'latLng': '${entry.latLng}', + 'geoUri': entry.geoUri ?? '', + }, + ), ], ); } diff --git a/lib/widgets/viewer/debug/metadata.dart b/lib/widgets/viewer/debug/metadata.dart index d0d55fd5b..198269ea1 100644 --- a/lib/widgets/viewer/debug/metadata.dart +++ b/lib/widgets/viewer/debug/metadata.dart @@ -12,7 +12,10 @@ import 'package:flutter/material.dart'; class MetadataTab extends StatefulWidget { final AvesEntry entry; - const MetadataTab({required this.entry}); + const MetadataTab({ + Key? key, + required this.entry, + }) : super(key: key); @override _MetadataTabState createState() => _MetadataTabState(); @@ -67,7 +70,7 @@ class _MetadataTabState extends State { Padding( padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8), child: InfoRowGroup( - data, + info: data, maxValueLength: Constants.infoGroupMaxValueLength, ), ) diff --git a/lib/widgets/viewer/entry_action_delegate.dart b/lib/widgets/viewer/entry_action_delegate.dart index 87c6075d6..0ef5305a7 100644 --- a/lib/widgets/viewer/entry_action_delegate.dart +++ b/lib/widgets/viewer/entry_action_delegate.dart @@ -13,6 +13,7 @@ import 'package:aves/services/android_app_service.dart'; import 'package:aves/services/image_op_events.dart'; import 'package:aves/services/services.dart'; import 'package:aves/theme/durations.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'; @@ -28,7 +29,6 @@ import 'package:aves/widgets/viewer/source_viewer_page.dart'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; -import 'package:pedantic/pedantic.dart'; import 'package:provider/provider.dart'; class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMixin { @@ -214,11 +214,9 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix context, MaterialPageRoute( settings: const RouteSettings(name: CollectionPage.routeName), - builder: (context) { - return CollectionPage( - targetCollection, - ); - }, + builder: (context) => CollectionPage( + collection: targetCollection, + ), ), (route) => false, )); @@ -252,7 +250,7 @@ class EntryActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix Future _showRenameDialog(BuildContext context, AvesEntry entry) async { final newName = await showDialog( context: context, - builder: (context) => RenameEntryDialog(entry), + builder: (context) => RenameEntryDialog(entry: entry), ); if (newName == null || newName.isEmpty) return; diff --git a/lib/widgets/viewer/entry_horizontal_pager.dart b/lib/widgets/viewer/entry_horizontal_pager.dart index d2f09ccff..62b4ca225 100644 --- a/lib/widgets/viewer/entry_horizontal_pager.dart +++ b/lib/widgets/viewer/entry_horizontal_pager.dart @@ -15,11 +15,12 @@ class MultiEntryScroller extends StatefulWidget { final void Function(String uri) onViewDisposed; const MultiEntryScroller({ + Key? key, required this.collection, required this.pageController, required this.onPageChanged, required this.onViewDisposed, - }); + }) : super(key: key); @override State createState() => _MultiEntryScrollerState(); @@ -33,7 +34,7 @@ class _MultiEntryScrollerState extends State with AutomaticK super.build(context); return MagnifierGestureDetectorScope( - axis: [Axis.horizontal, Axis.vertical], + axis: const [Axis.horizontal, Axis.vertical], child: PageView.builder( key: const Key('horizontal-pageview'), scrollDirection: Axis.horizontal, @@ -95,8 +96,9 @@ class SingleEntryScroller extends StatefulWidget { final AvesEntry entry; const SingleEntryScroller({ + Key? key, required this.entry, - }); + }) : super(key: key); @override State createState() => _SingleEntryScrollerState(); @@ -130,7 +132,7 @@ class _SingleEntryScrollerState extends State with Automati child ??= _buildViewer(); return MagnifierGestureDetectorScope( - axis: [Axis.vertical], + axis: const [Axis.vertical], child: child, ); } diff --git a/lib/widgets/viewer/entry_vertical_pager.dart b/lib/widgets/viewer/entry_vertical_pager.dart index 70fc8852e..211c17220 100644 --- a/lib/widgets/viewer/entry_vertical_pager.dart +++ b/lib/widgets/viewer/entry_vertical_pager.dart @@ -21,6 +21,7 @@ class ViewerVerticalPageView extends StatefulWidget { final void Function(String uri) onViewDisposed; const ViewerVerticalPageView({ + Key? key, required this.collection, required this.entryNotifier, required this.verticalPager, @@ -29,7 +30,7 @@ class ViewerVerticalPageView extends StatefulWidget { required this.onHorizontalPageChanged, required this.onImagePageRequested, required this.onViewDisposed, - }); + }) : super(key: key); @override _ViewerVerticalPageViewState createState() => _ViewerVerticalPageViewState(); diff --git a/lib/widgets/viewer/entry_viewer_stack.dart b/lib/widgets/viewer/entry_viewer_stack.dart index f00f6da16..91aa12c4f 100644 --- a/lib/widgets/viewer/entry_viewer_stack.dart +++ b/lib/widgets/viewer/entry_viewer_stack.dart @@ -210,7 +210,7 @@ class _EntryViewerStackState extends State with SingleTickerPr ), _buildTopOverlay(), _buildBottomOverlay(), - BottomGestureAreaProtector(), + const BottomGestureAreaProtector(), ], ), ), @@ -399,7 +399,7 @@ class _EntryViewerStackState extends State with SingleTickerPr settings: const RouteSettings(name: CollectionPage.routeName), builder: (context) { return CollectionPage( - CollectionLens( + collection: CollectionLens( source: baseCollection.source, filters: baseCollection.filters, groupFactor: baseCollection.groupFactor, diff --git a/lib/widgets/viewer/info/basic_section.dart b/lib/widgets/viewer/info/basic_section.dart index 8de74ef42..94a717100 100644 --- a/lib/widgets/viewer/info/basic_section.dart +++ b/lib/widgets/viewer/info/basic_section.dart @@ -53,15 +53,17 @@ class BasicSection extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - InfoRowGroup({ - l10n.viewerInfoLabelTitle: title, - l10n.viewerInfoLabelDate: dateText, - if (entry.isVideo) ..._buildVideoRows(context), - if (!entry.isSvg && entry.isSized) l10n.viewerInfoLabelResolution: rasterResolutionText, - l10n.viewerInfoLabelSize: entry.sizeBytes != null ? formatFilesize(entry.sizeBytes!) : infoUnknown, - l10n.viewerInfoLabelUri: uri, - if (path != null) l10n.viewerInfoLabelPath: path, - }), + InfoRowGroup( + info: { + l10n.viewerInfoLabelTitle: title, + l10n.viewerInfoLabelDate: dateText, + if (entry.isVideo) ..._buildVideoRows(context), + if (!entry.isSvg && entry.isSized) l10n.viewerInfoLabelResolution: rasterResolutionText, + l10n.viewerInfoLabelSize: entry.sizeBytes != null ? formatFilesize(entry.sizeBytes!) : infoUnknown, + l10n.viewerInfoLabelUri: uri, + if (path != null) l10n.viewerInfoLabelPath: path, + }, + ), OwnerProp( entry: entry, ), @@ -120,8 +122,9 @@ class OwnerProp extends StatefulWidget { final AvesEntry entry; const OwnerProp({ + Key? key, required this.entry, - }); + }) : super(key: key); @override _OwnerPropState createState() => _OwnerPropState(); diff --git a/lib/widgets/viewer/info/common.dart b/lib/widgets/viewer/info/common.dart index 2472d9610..7e2edd613 100644 --- a/lib/widgets/viewer/info/common.dart +++ b/lib/widgets/viewer/info/common.dart @@ -8,7 +8,10 @@ import 'package:flutter/rendering.dart'; class SectionRow extends StatelessWidget { final IconData icon; - const SectionRow(this.icon); + const SectionRow({ + Key? key, + required this.icon, + }) : super(key: key); @override Widget build(BuildContext context) { @@ -38,7 +41,7 @@ class SectionRow extends StatelessWidget { } class InfoRowGroup extends StatefulWidget { - final Map keyValues; + final Map info; final int maxValueLength; final Map? linkHandlers; @@ -49,11 +52,12 @@ class InfoRowGroup extends StatefulWidget { static final keyStyle = baseStyle.copyWith(color: Colors.white70, height: 2.0); static final linkStyle = baseStyle.copyWith(color: linkColor, decoration: TextDecoration.underline); - const InfoRowGroup( - this.keyValues, { + const InfoRowGroup({ + Key? key, + required this.info, this.maxValueLength = 0, this.linkHandlers, - }); + }) : super(key: key); @override _InfoRowGroupState createState() => _InfoRowGroupState(); @@ -62,7 +66,7 @@ class InfoRowGroup extends StatefulWidget { class _InfoRowGroupState extends State { final List _expandedKeys = []; - Map get keyValues => widget.keyValues; + Map get keyValues => widget.info; int get maxValueLength => widget.maxValueLength; @@ -74,7 +78,7 @@ class _InfoRowGroupState extends State { // compute the size of keys and space in order to align values final textScaleFactor = MediaQuery.textScaleFactorOf(context); - final keySizes = Map.fromEntries(keyValues.keys.map((key) => MapEntry(key, _getSpanWidth(TextSpan(text: '$key', style: InfoRowGroup.keyStyle), textScaleFactor)))); + final keySizes = Map.fromEntries(keyValues.keys.map((key) => MapEntry(key, _getSpanWidth(TextSpan(text: key, style: InfoRowGroup.keyStyle), textScaleFactor)))); final baseSpaceWidth = _getSpanWidth(TextSpan(text: '\u200A' * 100, style: InfoRowGroup.baseStyle), textScaleFactor); final lastKey = keyValues.keys.last; diff --git a/lib/widgets/viewer/info/info_app_bar.dart b/lib/widgets/viewer/info/info_app_bar.dart index 8e931288a..5bc3d7559 100644 --- a/lib/widgets/viewer/info/info_app_bar.dart +++ b/lib/widgets/viewer/info/info_app_bar.dart @@ -12,10 +12,11 @@ class InfoAppBar extends StatelessWidget { final VoidCallback onBackPressed; const InfoAppBar({ + Key? key, required this.entry, required this.metadataNotifier, required this.onBackPressed, - }); + }) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/widgets/viewer/info/info_page.dart b/lib/widgets/viewer/info/info_page.dart index 2bf631398..055b658cf 100644 --- a/lib/widgets/viewer/info/info_page.dart +++ b/lib/widgets/viewer/info/info_page.dart @@ -209,7 +209,7 @@ class _InfoPageContentState extends State<_InfoPageContent> { padding: horizontalPadding + const EdgeInsets.only(bottom: 8), sliver: metadataSliver, ), - BottomPaddingSliver(), + const BottomPaddingSliver(), ], ); } diff --git a/lib/widgets/viewer/info/location_section.dart b/lib/widgets/viewer/info/location_section.dart index 8084580bd..1a64ec9ff 100644 --- a/lib/widgets/viewer/info/location_section.dart +++ b/lib/widgets/viewer/info/location_section.dart @@ -106,7 +106,7 @@ class _LocationSectionState extends State with TickerProviderSt return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (widget.showTitle) const SectionRow(AIcons.location), + if (widget.showTitle) const SectionRow(icon: AIcons.location), FutureBuilder( future: availability.isConnected, builder: (context, snapshot) { @@ -221,10 +221,12 @@ class _AddressInfoGroupState extends State<_AddressInfoGroup> { final fullAddress = !snapshot.hasError && snapshot.connectionState == ConnectionState.done ? snapshot.data : null; final address = fullAddress ?? entry.shortAddress; final l10n = context.l10n; - return InfoRowGroup({ - l10n.viewerInfoLabelCoordinates: settings.coordinateFormat.format(entry.latLng!), - if (address.isNotEmpty) l10n.viewerInfoLabelAddress: address, - }); + return InfoRowGroup( + info: { + l10n.viewerInfoLabelCoordinates: settings.coordinateFormat.format(entry.latLng!), + if (address.isNotEmpty) l10n.viewerInfoLabelAddress: address, + }, + ); }, ); } diff --git a/lib/widgets/viewer/info/maps/common.dart b/lib/widgets/viewer/info/maps/common.dart index 696e09ddd..f7e45a122 100644 --- a/lib/widgets/viewer/info/maps/common.dart +++ b/lib/widgets/viewer/info/maps/common.dart @@ -21,7 +21,10 @@ class MapDecorator extends StatelessWidget { static const mapBackground = Color(0xFFDBD5D3); static const mapLoadingGrid = Color(0xFFC4BEBB); - const MapDecorator({this.child}); + const MapDecorator({ + Key? key, + this.child, + }) : super(key: key); @override Widget build(BuildContext context) { @@ -62,9 +65,10 @@ class MapButtonPanel extends StatelessWidget { static const double padding = 4; const MapButtonPanel({ + Key? key, required this.geoUri, required this.zoomBy, - }); + }) : super(key: key); @override Widget build(BuildContext context) { @@ -140,10 +144,11 @@ class MapOverlayButton extends StatelessWidget { final VoidCallback onPressed; const MapOverlayButton({ + Key? key, required this.icon, required this.tooltip, required this.onPressed, - }); + }) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/widgets/viewer/info/maps/leaflet_map.dart b/lib/widgets/viewer/info/maps/leaflet_map.dart index 8b47d6be5..aed8f9e05 100644 --- a/lib/widgets/viewer/info/maps/leaflet_map.dart +++ b/lib/widgets/viewer/info/maps/leaflet_map.dart @@ -98,11 +98,11 @@ class _EntryLeafletMapState extends State with TickerProviderSt Widget _buildMapLayer() { switch (widget.style) { case EntryMapStyle.osmHot: - return OSMHotLayer(); + return const OSMHotLayer(); case EntryMapStyle.stamenToner: - return StamenTonerLayer(); + return const StamenTonerLayer(); case EntryMapStyle.stamenWatercolor: - return StamenWatercolorLayer(); + return const StamenWatercolorLayer(); default: return const SizedBox.shrink(); } @@ -159,6 +159,8 @@ class _EntryLeafletMapState extends State with TickerProviderSt } class OSMHotLayer extends StatelessWidget { + const OSMHotLayer({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return TileLayerWidget( @@ -172,6 +174,8 @@ class OSMHotLayer extends StatelessWidget { } class StamenTonerLayer extends StatelessWidget { + const StamenTonerLayer({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return TileLayerWidget( @@ -185,6 +189,8 @@ class StamenTonerLayer extends StatelessWidget { } class StamenWatercolorLayer extends StatelessWidget { + const StamenWatercolorLayer({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return TileLayerWidget( diff --git a/lib/widgets/viewer/info/maps/marker.dart b/lib/widgets/viewer/info/maps/marker.dart index 3a1eb1b52..fe8a8f277 100644 --- a/lib/widgets/viewer/info/maps/marker.dart +++ b/lib/widgets/viewer/info/maps/marker.dart @@ -22,10 +22,11 @@ class ImageMarker extends StatelessWidget { static const innerBorderRadius = BorderRadius.all(Radius.circular(outerBorderRadiusDim - outerBorderWidth)); const ImageMarker({ + Key? key, required this.entry, required this.extent, this.pointerSize = Size.zero, - }); + }) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/widgets/viewer/info/maps/scale_layer.dart b/lib/widgets/viewer/info/maps/scale_layer.dart index ed6808507..30489bc8a 100644 --- a/lib/widgets/viewer/info/maps/scale_layer.dart +++ b/lib/widgets/viewer/info/maps/scale_layer.dart @@ -39,6 +39,8 @@ class ScaleLayerWidget extends StatelessWidget { class ScaleLayer extends StatelessWidget { final ScaleLayerOptions scaleLayerOpts; final MapState map; + + // ignore: prefer_void_to_null final Stream stream; final scale = [ 25000000, @@ -70,6 +72,7 @@ class ScaleLayer extends StatelessWidget { @override Widget build(BuildContext context) { + // ignore: prefer_void_to_null return StreamBuilder( stream: stream, builder: (context, snapshot) { @@ -104,9 +107,10 @@ class ScaleBar extends StatelessWidget { static const double barThickness = 1; const ScaleBar({ + Key? key, required this.distance, required this.width, - }); + }) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/widgets/viewer/info/metadata/metadata_dir_tile.dart b/lib/widgets/viewer/info/metadata/metadata_dir_tile.dart index 1e9aff201..476c43afa 100644 --- a/lib/widgets/viewer/info/metadata/metadata_dir_tile.dart +++ b/lib/widgets/viewer/info/metadata/metadata_dir_tile.dart @@ -8,6 +8,7 @@ import 'package:aves/services/services.dart'; import 'package:aves/services/svg_metadata_service.dart'; import 'package:aves/utils/color_utils.dart'; import 'package:aves/utils/constants.dart'; +import 'package:aves/utils/pedantic.dart'; import 'package:aves/widgets/common/action_mixins/feedback.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/identity/aves_expansion_tile.dart'; @@ -20,7 +21,6 @@ import 'package:aves/widgets/viewer/info/notifications.dart'; import 'package:aves/widgets/viewer/source_viewer_page.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:pedantic/pedantic.dart'; class MetadataDirTile extends StatelessWidget with FeedbackMixin { final AvesEntry entry; @@ -30,13 +30,14 @@ class MetadataDirTile extends StatelessWidget with FeedbackMixin { final bool initiallyExpanded, showThumbnails; const MetadataDirTile({ + Key? key, required this.entry, required this.title, required this.dir, this.expandedDirectoryNotifier, this.initiallyExpanded = false, this.showThumbnails = true, - }); + }) : super(key: key); @override Widget build(BuildContext context) { @@ -73,7 +74,7 @@ class MetadataDirTile extends StatelessWidget with FeedbackMixin { Padding( padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8), child: InfoRowGroup( - tags, + info: tags, maxValueLength: Constants.infoGroupMaxValueLength, linkHandlers: linkHandlers, ), diff --git a/lib/widgets/viewer/info/metadata/metadata_section.dart b/lib/widgets/viewer/info/metadata/metadata_section.dart index c4134dd5e..4a08f34ae 100644 --- a/lib/widgets/viewer/info/metadata/metadata_section.dart +++ b/lib/widgets/viewer/info/metadata/metadata_section.dart @@ -22,9 +22,10 @@ class MetadataSectionSliver extends StatefulWidget { final ValueNotifier> metadataNotifier; const MetadataSectionSliver({ + Key? key, required this.entry, required this.metadataNotifier, - }); + }) : super(key: key); @override State createState() => _MetadataSectionSliverState(); @@ -100,7 +101,7 @@ class _MetadataSectionSliverState extends State { ), ), children: [ - const SectionRow(AIcons.info), + const SectionRow(icon: AIcons.info), ...metadata.entries.map((kv) => MetadataDirTile( entry: entry, title: kv.key, @@ -262,9 +263,13 @@ class MetadataDirectory { static const mediaDirectory = 'Media'; // custom static const coverDirectory = 'Cover'; // custom - const MetadataDirectory(this.name, this.parent, SplayTreeMap allTags, {SplayTreeMap? tags, this.color}) - : allTags = allTags, - tags = tags ?? allTags; + const MetadataDirectory( + this.name, + this.parent, + this.allTags, { + SplayTreeMap? tags, + this.color, + }) : tags = tags ?? allTags; MetadataDirectory filterKeys(bool Function(String key) testKey) { final filteredTags = SplayTreeMap.of(Map.fromEntries(allTags.entries.where((kv) => testKey(kv.key)))); diff --git a/lib/widgets/viewer/info/metadata/xmp_namespaces.dart b/lib/widgets/viewer/info/metadata/xmp_namespaces.dart index 4856b63a6..7ed6ab364 100644 --- a/lib/widgets/viewer/info/metadata/xmp_namespaces.dart +++ b/lib/widgets/viewer/info/metadata/xmp_namespaces.dart @@ -70,7 +70,7 @@ class XmpNamespace { final content = [ if (props.isNotEmpty) InfoRowGroup( - Map.fromEntries(props.map((prop) => MapEntry(prop.displayKey, formatValue(prop)))), + info: Map.fromEntries(props.map((prop) => MapEntry(prop.displayKey, formatValue(prop)))), maxValueLength: Constants.infoGroupMaxValueLength, linkHandlers: linkifyValues(props), ), @@ -83,7 +83,7 @@ class XmpNamespace { Padding( padding: const EdgeInsets.only(top: 8), child: HighlightTitle( - displayTitle, + title: displayTitle, color: BrandColors.get(displayTitle), selectable: true, ), diff --git a/lib/widgets/viewer/info/metadata/xmp_structs.dart b/lib/widgets/viewer/info/metadata/xmp_structs.dart index aaff62184..f5ee2e936 100644 --- a/lib/widgets/viewer/info/metadata/xmp_structs.dart +++ b/lib/widgets/viewer/info/metadata/xmp_structs.dart @@ -15,10 +15,11 @@ class XmpStructArrayCard extends StatefulWidget { final Map Function(int index)? linkifier; XmpStructArrayCard({ + Key? key, required this.title, required Map> structByIndex, this.linkifier, - }) { + }) : super(key: key) { final length = structByIndex.keys.fold(0, max); structs.length = length; for (var i = 0; i < length; i++) { @@ -63,7 +64,7 @@ class _XmpStructArrayCardState extends State { children: [ Flexible( child: HighlightTitle( - '${widget.title} ${_index + 1}', + title: '${widget.title} ${_index + 1}', color: Colors.transparent, selectable: true, ), @@ -93,7 +94,7 @@ class _XmpStructArrayCardState extends State { // without clipping the text padding: const EdgeInsets.only(left: 8, right: 8, bottom: 8), child: InfoRowGroup( - structs[_index], + info: structs[_index], maxValueLength: Constants.infoGroupMaxValueLength, linkHandlers: widget.linkifier?.call(_index + 1), ), @@ -113,10 +114,11 @@ class XmpStructCard extends StatelessWidget { static const cardMargin = EdgeInsets.symmetric(vertical: 8, horizontal: 0); const XmpStructCard({ + Key? key, required this.title, required this.struct, this.linkifier, - }); + }) : super(key: key); @override Widget build(BuildContext context) { @@ -128,12 +130,12 @@ class XmpStructCard extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ HighlightTitle( - title, + title: title, color: Colors.transparent, selectable: true, ), InfoRowGroup( - struct, + info: struct, maxValueLength: Constants.infoGroupMaxValueLength, linkHandlers: linkifier?.call(), ), diff --git a/lib/widgets/viewer/info/metadata/xmp_tile.dart b/lib/widgets/viewer/info/metadata/xmp_tile.dart index 387d00531..7114adef2 100644 --- a/lib/widgets/viewer/info/metadata/xmp_tile.dart +++ b/lib/widgets/viewer/info/metadata/xmp_tile.dart @@ -14,11 +14,12 @@ class XmpDirTile extends StatefulWidget { final bool initiallyExpanded; const XmpDirTile({ + Key? key, required this.entry, required this.tags, required this.expandedNotifier, required this.initiallyExpanded, - }); + }) : super(key: key); @override _XmpDirTileState createState() => _XmpDirTileState(); diff --git a/lib/widgets/viewer/overlay/bottom/common.dart b/lib/widgets/viewer/overlay/bottom/common.dart index 47caa371a..3aa530f95 100644 --- a/lib/widgets/viewer/overlay/bottom/common.dart +++ b/lib/widgets/viewer/overlay/bottom/common.dart @@ -230,7 +230,7 @@ class _BottomOverlayContent extends AnimatedWidget { padding: const EdgeInsets.only(top: _interRowPadding), child: Row( children: [ - Container( + SizedBox( width: subRowWidth, child: _DateRow( entry: pageEntry, @@ -292,7 +292,7 @@ class _BottomOverlayContent extends AnimatedWidget { child: child, ), child: hasShootingDetails - ? Container( + ? SizedBox( width: subRowWidth, child: _ShootingRow(details!), ) diff --git a/lib/widgets/viewer/overlay/bottom/panorama.dart b/lib/widgets/viewer/overlay/bottom/panorama.dart index 861afbae2..8ee5bdecc 100644 --- a/lib/widgets/viewer/overlay/bottom/panorama.dart +++ b/lib/widgets/viewer/overlay/bottom/panorama.dart @@ -4,7 +4,7 @@ import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/viewer/overlay/common.dart'; import 'package:aves/widgets/viewer/panorama_page.dart'; import 'package:flutter/material.dart'; -import 'package:pedantic/pedantic.dart'; +import 'package:aves/utils/pedantic.dart'; class PanoramaOverlay extends StatelessWidget { final AvesEntry entry; diff --git a/lib/widgets/viewer/overlay/bottom/video.dart b/lib/widgets/viewer/overlay/bottom/video.dart index 6478e2e11..b12b9ca20 100644 --- a/lib/widgets/viewer/overlay/bottom/video.dart +++ b/lib/widgets/viewer/overlay/bottom/video.dart @@ -287,7 +287,7 @@ class _ButtonRow extends StatelessWidget { } PopupMenuEntry _buildPopupMenuItem(BuildContext context, VideoAction action) { - late final enabled; + late final bool enabled; switch (action) { case VideoAction.captureFrame: enabled = controller?.canCaptureFrameNotifier.value ?? false; diff --git a/lib/widgets/viewer/overlay/minimap.dart b/lib/widgets/viewer/overlay/minimap.dart index 42584db2d..3a30626ff 100644 --- a/lib/widgets/viewer/overlay/minimap.dart +++ b/lib/widgets/viewer/overlay/minimap.dart @@ -15,10 +15,11 @@ class Minimap extends StatelessWidget { static const defaultSize = Size(96, 96); const Minimap({ + Key? key, required this.entry, required this.viewStateNotifier, this.size = defaultSize, - }); + }) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/widgets/viewer/panorama_page.dart b/lib/widgets/viewer/panorama_page.dart index 8df109ade..9ba13d386 100644 --- a/lib/widgets/viewer/panorama_page.dart +++ b/lib/widgets/viewer/panorama_page.dart @@ -20,9 +20,10 @@ class PanoramaPage extends StatefulWidget { final PanoramaInfo info; const PanoramaPage({ + Key? key, required this.entry, required this.info, - }); + }) : super(key: key); @override _PanoramaPageState createState() => _PanoramaPageState(); @@ -112,7 +113,7 @@ class _PanoramaPageState extends State { ), ), ), - BottomGestureAreaProtector(), + const BottomGestureAreaProtector(), ], ), resizeToAvoidBottomInset: false, diff --git a/lib/widgets/viewer/printer.dart b/lib/widgets/viewer/printer.dart index ec640d9a3..e27f5bab2 100644 --- a/lib/widgets/viewer/printer.dart +++ b/lib/widgets/viewer/printer.dart @@ -4,11 +4,11 @@ import 'dart:convert'; import 'package:aves/model/entry.dart'; import 'package:aves/model/entry_images.dart'; import 'package:aves/services/services.dart'; +import 'package:aves/utils/pedantic.dart'; import 'package:aves/widgets/common/action_mixins/feedback.dart'; import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:flutter/widgets.dart'; import 'package:pdf/widgets.dart' as pdf; -import 'package:pedantic/pedantic.dart'; import 'package:printing/printing.dart'; class EntryPrinter with FeedbackMixin { diff --git a/lib/widgets/viewer/source_viewer_page.dart b/lib/widgets/viewer/source_viewer_page.dart index 17be3a598..b4caae6f6 100644 --- a/lib/widgets/viewer/source_viewer_page.dart +++ b/lib/widgets/viewer/source_viewer_page.dart @@ -9,8 +9,9 @@ class SourceViewerPage extends StatefulWidget { final Future Function() loader; const SourceViewerPage({ + Key? key, required this.loader, - }); + }) : super(key: key); @override _SourceViewerPageState createState() => _SourceViewerPageState(); @@ -40,7 +41,7 @@ class _SourceViewerPageState extends State { final source = snapshot.data!; final highlightView = AvesHighlightView( - source, + input: source, language: 'xml', theme: darculaTheme, padding: const EdgeInsets.all(8), diff --git a/lib/widgets/viewer/video_action_delegate.dart b/lib/widgets/viewer/video_action_delegate.dart index b892cf1d9..a6a5c99d2 100644 --- a/lib/widgets/viewer/video_action_delegate.dart +++ b/lib/widgets/viewer/video_action_delegate.dart @@ -7,6 +7,7 @@ import 'package:aves/model/source/collection_lens.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'; @@ -18,7 +19,6 @@ import 'package:aves/widgets/settings/video/video.dart'; import 'package:aves/widgets/viewer/video/controller.dart'; import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; -import 'package:pedantic/pedantic.dart'; import 'package:provider/provider.dart'; class VideoActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMixin { @@ -103,11 +103,9 @@ class VideoActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAwareMix context, MaterialPageRoute( settings: const RouteSettings(name: CollectionPage.routeName), - builder: (context) { - return CollectionPage( - targetCollection, - ); - }, + builder: (context) => CollectionPage( + collection: targetCollection, + ), ), (route) => false, )); diff --git a/lib/widgets/viewer/visual/error.dart b/lib/widgets/viewer/visual/error.dart index 9d72b010e..e233637e7 100644 --- a/lib/widgets/viewer/visual/error.dart +++ b/lib/widgets/viewer/visual/error.dart @@ -12,9 +12,10 @@ class ErrorView extends StatefulWidget { final VoidCallback onTap; const ErrorView({ + Key? key, required this.entry, required this.onTap, - }); + }) : super(key: key); @override _ErrorViewState createState() => _ErrorViewState(); diff --git a/lib/widgets/viewer/visual/raster.dart b/lib/widgets/viewer/visual/raster.dart index e246eaa4c..a4c1c97c3 100644 --- a/lib/widgets/viewer/visual/raster.dart +++ b/lib/widgets/viewer/visual/raster.dart @@ -20,10 +20,11 @@ class RasterImageView extends StatefulWidget { final ImageErrorWidgetBuilder errorBuilder; const RasterImageView({ + Key? key, required this.entry, required this.viewStateNotifier, required this.errorBuilder, - }); + }) : super(key: key); @override _RasterImageViewState createState() => _RasterImageViewState(); @@ -329,11 +330,12 @@ class RegionTile extends StatefulWidget { final int sampleSize; const RegionTile({ + Key? key, required this.entry, required this.tileRect, this.regionRect, required this.sampleSize, - }); + }) : super(key: key); @override _RegionTileState createState() => _RegionTileState(); diff --git a/lib/widgets/viewer/visual/subtitle/ass_parser.dart b/lib/widgets/viewer/visual/subtitle/ass_parser.dart index 5ab2bd893..bbb53cbbc 100644 --- a/lib/widgets/viewer/visual/subtitle/ass_parser.dart +++ b/lib/widgets/viewer/visual/subtitle/ass_parser.dart @@ -394,7 +394,7 @@ class AssParser { final match = alphaPattern.firstMatch(param); if (match != null) { final as = match.group(1); - final ai = int.tryParse('$as', radix: 16); + final ai = as != null ? int.tryParse(as, radix: 16) : null; if (ai != null) { return 0xFF - ai; } diff --git a/lib/widgets/viewer/visual/subtitle/subtitle.dart b/lib/widgets/viewer/visual/subtitle/subtitle.dart index 3c215c253..3dd359ac3 100644 --- a/lib/widgets/viewer/visual/subtitle/subtitle.dart +++ b/lib/widgets/viewer/visual/subtitle/subtitle.dart @@ -108,15 +108,13 @@ class VideoSubtitles extends StatelessWidget { text: span.text, style: style.copyWith( letterSpacing: letterSpacing != null ? letterSpacing * viewScale : null, - shadows: shadows != null - ? shadows - .map((v) => Shadow( - color: v.color, - offset: v.offset * viewScale, - blurRadius: v.blurRadius * viewScale, - )) - .toList() - : null, + shadows: shadows + ?.map((v) => Shadow( + color: v.color, + offset: v.offset * viewScale, + blurRadius: v.blurRadius * viewScale, + )) + .toList(), ), ); }).toList(); diff --git a/lib/widgets/viewer/visual/vector.dart b/lib/widgets/viewer/visual/vector.dart index da5cfa639..aa5489586 100644 --- a/lib/widgets/viewer/visual/vector.dart +++ b/lib/widgets/viewer/visual/vector.dart @@ -10,10 +10,11 @@ class VectorViewCheckeredBackground extends StatelessWidget { final Widget child; const VectorViewCheckeredBackground({ + Key? key, required this.displaySize, required this.viewStateNotifier, required this.child, - }); + }) : super(key: key); @override Widget build(BuildContext context) { diff --git a/lib/widgets/welcome_page.dart b/lib/widgets/welcome_page.dart index 249a235eb..b60953993 100644 --- a/lib/widgets/welcome_page.dart +++ b/lib/widgets/welcome_page.dart @@ -14,7 +14,7 @@ import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; class WelcomePage extends StatefulWidget { - const WelcomePage(); + const WelcomePage({Key? key}) : super(key: key); @override _WelcomePageState createState() => _WelcomePageState(); @@ -92,7 +92,7 @@ class _WelcomePageState extends State { ], ) ]), - const SizedBox(height: 16), + const SizedBox(height: 16), ]; } @@ -145,7 +145,7 @@ class _WelcomePageState extends State { crossAxisAlignment: CrossAxisAlignment.end, children: [ checkboxes, - const Spacer(), + const Spacer(), button, ], ), diff --git a/pubspec.lock b/pubspec.lock index 901ad32fc..1ec97be1d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -84,7 +84,7 @@ packages: name: cli_util url: "https://pub.dartlang.org" source: hosted - version: "0.3.0" + version: "0.3.1" clock: dependency: transitive description: @@ -105,7 +105,7 @@ packages: name: connectivity_plus url: "https://pub.dartlang.org" source: hosted - version: "1.0.3" + version: "1.0.4" connectivity_plus_linux: dependency: transitive description: @@ -147,7 +147,7 @@ packages: name: convert url: "https://pub.dartlang.org" source: hosted - version: "3.0.0" + version: "3.0.1" country_code: dependency: "direct main" description: @@ -323,6 +323,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.7.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" flutter_localizations: dependency: "direct main" description: flutter @@ -490,6 +497,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.8.0" + lints: + dependency: transitive + description: + name: lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" lists: dependency: transitive description: @@ -622,7 +636,7 @@ packages: name: package_info_plus_windows url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.0.2" palette_generator: dependency: "direct main" description: @@ -685,14 +699,14 @@ packages: name: pdf url: "https://pub.dartlang.org" source: hosted - version: "3.3.0" + version: "3.4.2" pedantic: - dependency: "direct main" + dependency: transitive description: name: pedantic url: "https://pub.dartlang.org" source: hosted - version: "1.11.0" + version: "1.11.1" percent_indicator: dependency: "direct main" description: @@ -755,7 +769,7 @@ packages: name: printing url: "https://pub.dartlang.org" source: hosted - version: "5.2.1" + version: "5.4.2" process: dependency: transitive description: @@ -790,7 +804,7 @@ packages: name: qr url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0" quiver: dependency: transitive description: @@ -1021,7 +1035,7 @@ packages: name: url_launcher url: "https://pub.dartlang.org" source: hosted - version: "6.0.6" + version: "6.0.7" url_launcher_linux: dependency: transitive description: @@ -1112,7 +1126,7 @@ packages: name: win32 url: "https://pub.dartlang.org" source: hosted - version: "2.1.5" + version: "2.2.4" wkt_parser: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index c1a3984c9..3508abbaa 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -50,7 +50,6 @@ dependencies: # TODO TLAD upgrade panorama when this is fixed: https://github.com/zesage/panorama/issues/25 (bug in v0.4.1) panorama: 0.4.0 pdf: - pedantic: percent_indicator: permission_handler: printing: @@ -70,6 +69,7 @@ dev_dependencies: sdk: flutter flutter_driver: sdk: flutter + flutter_lints: test: flutter: diff --git a/test/fake/metadata_db.dart b/test/fake/metadata_db.dart index 3c738bbce..e5a17d99c 100644 --- a/test/fake/metadata_db.dart +++ b/test/fake/metadata_db.dart @@ -9,19 +9,19 @@ import 'package:flutter_test/flutter_test.dart'; class FakeMetadataDb extends Fake implements MetadataDb { @override - Future init() => SynchronousFuture(true); + Future init() => SynchronousFuture(null); @override - Future removeIds(Set contentIds, {required bool metadataOnly}) => SynchronousFuture(true); + Future removeIds(Set contentIds, {required bool metadataOnly}) => SynchronousFuture(null); @override Future> loadEntries() => SynchronousFuture({}); @override - Future saveEntries(Iterable entries) => SynchronousFuture(true); + Future saveEntries(Iterable entries) => SynchronousFuture(null); @override - Future updateEntryId(int oldId, AvesEntry entry) => SynchronousFuture(true); + Future updateEntryId(int oldId, AvesEntry entry) => SynchronousFuture(null); @override Future> loadDates() => SynchronousFuture([]); @@ -30,38 +30,38 @@ class FakeMetadataDb extends Fake implements MetadataDb { Future> loadMetadataEntries() => SynchronousFuture([]); @override - Future saveMetadata(Set metadataEntries) => SynchronousFuture(true); + Future saveMetadata(Set metadataEntries) => SynchronousFuture(null); @override - Future updateMetadataId(int oldId, CatalogMetadata? metadata) => SynchronousFuture(true); + Future updateMetadataId(int oldId, CatalogMetadata? metadata) => SynchronousFuture(null); @override Future> loadAddresses() => SynchronousFuture([]); @override - Future updateAddressId(int oldId, AddressDetails? address) => SynchronousFuture(true); + Future updateAddressId(int oldId, AddressDetails? address) => SynchronousFuture(null); @override Future> loadFavourites() => SynchronousFuture({}); @override - Future addFavourites(Iterable rows) => SynchronousFuture(true); + Future addFavourites(Iterable rows) => SynchronousFuture(null); @override - Future updateFavouriteId(int oldId, FavouriteRow row) => SynchronousFuture(true); + Future updateFavouriteId(int oldId, FavouriteRow row) => SynchronousFuture(null); @override - Future removeFavourites(Iterable rows) => SynchronousFuture(true); + Future removeFavourites(Iterable rows) => SynchronousFuture(null); @override Future> loadCovers() => SynchronousFuture({}); @override - Future addCovers(Iterable rows) => SynchronousFuture(true); + Future addCovers(Iterable rows) => SynchronousFuture(null); @override - Future updateCoverEntryId(int oldId, CoverRow row) => SynchronousFuture(true); + Future updateCoverEntryId(int oldId, CoverRow row) => SynchronousFuture(null); @override - Future removeCovers(Set filters) => SynchronousFuture(true); + Future removeCovers(Set filters) => SynchronousFuture(null); } diff --git a/test/model/collection_source_test.dart b/test/model/collection_source_test.dart index 59275f209..9c69ec17d 100644 --- a/test/model/collection_source_test.dart +++ b/test/model/collection_source_test.dart @@ -252,7 +252,7 @@ void main() { FakeMediaStoreService.newImage('${FakeStorageService.primaryPath}Pictures/Cleanthes', '1'), FakeMediaStoreService.newImage('${FakeStorageService.primaryPath}Pictures/Chrysippus', '1'), FakeMediaStoreService.newImage('${FakeStorageService.removablePath}Pictures/Chrysippus', '1'), - FakeMediaStoreService.newImage('${FakeStorageService.primaryPath}', '1'), + FakeMediaStoreService.newImage(FakeStorageService.primaryPath, '1'), FakeMediaStoreService.newImage('${FakeStorageService.primaryPath}Pictures/Seneca', '1'), FakeMediaStoreService.newImage('${FakeStorageService.primaryPath}Seneca', '1'), FakeMediaStoreService.newImage('${FakeStorageService.removablePath}Pictures/Cicero', '1'), diff --git a/test/widget_test.dart b/test/widget_test.dart index df774cab7..9c67a3d79 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -3,6 +3,6 @@ import 'package:flutter_test/flutter_test.dart'; void main() { testWidgets('widget test', (tester) async { - await tester.pumpWidget(AvesApp()); + await tester.pumpWidget(const AvesApp()); }); } diff --git a/test_driver/app_test.dart b/test_driver/app_test.dart index 13f442cde..2a431fe1a 100644 --- a/test_driver/app_test.dart +++ b/test_driver/app_test.dart @@ -1,7 +1,8 @@ +// ignore_for_file: avoid_print import 'package:aves/model/source/enums.dart'; +import 'package:aves/utils/pedantic.dart'; import 'package:flutter_driver/flutter_driver.dart'; import 'package:path/path.dart' as p; -import 'package:pedantic/pedantic.dart'; import 'package:test/test.dart'; import 'constants.dart';