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