upgraded Flutter to stable v3.22.0
This commit is contained in:
parent
9a4657379b
commit
56762eea9c
82 changed files with 361 additions and 410 deletions
2
.flutter
2
.flutter
|
@ -1 +1 @@
|
|||
Subproject commit 54e66469a933b60ddf175f858f82eaeb97e48c8d
|
||||
Subproject commit 5dcb86f68f239346676ceb1ed1ea385bd215fba1
|
|
@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
## <a id="unreleased"></a>[Unreleased]
|
||||
|
||||
### Changed
|
||||
|
||||
- upgraded Flutter to stable v3.22.0
|
||||
|
||||
### Removed
|
||||
|
||||
- support for Android KitKat (API 19)
|
||||
|
||||
## <a id="v1.11.1"></a>[v1.11.1] - 2024-05-03
|
||||
|
||||
### Added
|
||||
|
|
|
@ -66,9 +66,6 @@ android {
|
|||
|
||||
defaultConfig {
|
||||
applicationId packageName
|
||||
// minSdk constraints:
|
||||
// - Flutter & other plugins: 19 (cf `flutter.minSdkVersion`)
|
||||
// - google_maps_flutter v2.1.1: 20
|
||||
minSdk flutter.minSdkVersion
|
||||
targetSdk 34
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
|
@ -201,7 +198,7 @@ dependencies {
|
|||
|
||||
implementation "androidx.appcompat:appcompat:1.6.1"
|
||||
implementation 'androidx.core:core-ktx:1.13.1'
|
||||
implementation 'androidx.lifecycle:lifecycle-process:2.7.0'
|
||||
implementation 'androidx.lifecycle:lifecycle-process:2.8.0'
|
||||
implementation 'androidx.media:media:1.7.0'
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
implementation 'androidx.security:security-crypto:1.1.0-alpha06'
|
||||
|
@ -229,7 +226,7 @@ dependencies {
|
|||
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.10.2'
|
||||
|
||||
kapt 'androidx.annotation:annotation:1.7.1'
|
||||
kapt 'androidx.annotation:annotation:1.8.0'
|
||||
ksp "com.github.bumptech.glide:ksp:$glide_version"
|
||||
|
||||
compileOnly rootProject.findProject(':streams_channel')
|
||||
|
|
|
@ -72,12 +72,10 @@
|
|||
-->
|
||||
|
||||
<!--
|
||||
allow install on API 19, despite the `minSdk` declared in dependencies:
|
||||
- the Security library is from API 21
|
||||
allow install on API 21, despite the `minSdk` declared in dependencies:
|
||||
- FFmpegKit for Flutter is from API 24 (when not LTS)
|
||||
- Google Maps is from API 20
|
||||
-->
|
||||
<uses-sdk tools:overrideLibrary="androidx.security, com.arthenica.ffmpegkit.flutter, io.flutter.plugins.googlemaps" />
|
||||
<uses-sdk tools:overrideLibrary="com.arthenica.ffmpegkit.flutter" />
|
||||
|
||||
<!-- from Android 11, we should define <queries> to make other apps visible to this app -->
|
||||
<queries>
|
||||
|
@ -321,8 +319,8 @@
|
|||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
<!-- as of Flutter v3.19.0 (stable),
|
||||
Impeller fails to render videos & platform views, has poor performance -->
|
||||
<!-- as of Flutter v3.22.0 (stable),
|
||||
Impeller fails to render videos (via `ffmpegkit`), and has random glitches -->
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.EnableImpeller"
|
||||
android:value="false" />
|
||||
|
|
|
@ -161,13 +161,12 @@ class AnalysisWorker(context: Context, parameters: WorkerParameters) : Coroutine
|
|||
applicationContext.getString(R.string.analysis_notification_action_stop),
|
||||
WorkManager.getInstance(applicationContext).createCancelPendingIntent(id)
|
||||
).build()
|
||||
val icon = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) R.drawable.ic_notification else R.mipmap.ic_launcher_round
|
||||
val contentTitle = title ?: applicationContext.getText(R.string.analysis_notification_default_title)
|
||||
val notification = NotificationCompat.Builder(applicationContext, NOTIFICATION_CHANNEL)
|
||||
.setContentTitle(contentTitle)
|
||||
.setTicker(contentTitle)
|
||||
.setContentText(message)
|
||||
.setSmallIcon(icon)
|
||||
.setSmallIcon(R.drawable.ic_notification)
|
||||
.setOngoing(true)
|
||||
.setContentIntent(openAppIntent)
|
||||
.addAction(stopAction)
|
||||
|
|
|
@ -4,8 +4,6 @@ import android.appwidget.AppWidgetManager
|
|||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import deckers.thibault.aves.model.FieldMap
|
||||
import deckers.thibault.aves.utils.FlutterUtils
|
||||
import deckers.thibault.aves.utils.FlutterUtils.enableSoftwareRendering
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
|
||||
|
@ -13,9 +11,6 @@ class HomeWidgetSettingsActivity : MainActivity() {
|
|||
private var appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID
|
||||
|
||||
public override fun onCreate(savedInstanceState: Bundle?) {
|
||||
if (FlutterUtils.isSoftwareRenderingRequired()) {
|
||||
intent.enableSoftwareRendering()
|
||||
}
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
// cancel if user does not complete widget setup
|
||||
|
|
|
@ -17,13 +17,37 @@ import androidx.core.content.pm.ShortcutManagerCompat
|
|||
import androidx.core.graphics.drawable.IconCompat
|
||||
import app.loup.streams_channel.StreamsChannel
|
||||
import deckers.thibault.aves.channel.AvesByteSendingMethodCodec
|
||||
import deckers.thibault.aves.channel.calls.*
|
||||
import deckers.thibault.aves.channel.calls.AccessibilityHandler
|
||||
import deckers.thibault.aves.channel.calls.AnalysisHandler
|
||||
import deckers.thibault.aves.channel.calls.AppAdapterHandler
|
||||
import deckers.thibault.aves.channel.calls.DebugHandler
|
||||
import deckers.thibault.aves.channel.calls.DeviceHandler
|
||||
import deckers.thibault.aves.channel.calls.EmbeddedDataHandler
|
||||
import deckers.thibault.aves.channel.calls.GeocodingHandler
|
||||
import deckers.thibault.aves.channel.calls.GlobalSearchHandler
|
||||
import deckers.thibault.aves.channel.calls.HomeWidgetHandler
|
||||
import deckers.thibault.aves.channel.calls.MediaEditHandler
|
||||
import deckers.thibault.aves.channel.calls.MediaFetchBytesHandler
|
||||
import deckers.thibault.aves.channel.calls.MediaFetchObjectHandler
|
||||
import deckers.thibault.aves.channel.calls.MediaSessionHandler
|
||||
import deckers.thibault.aves.channel.calls.MediaStoreHandler
|
||||
import deckers.thibault.aves.channel.calls.MetadataEditHandler
|
||||
import deckers.thibault.aves.channel.calls.MetadataFetchHandler
|
||||
import deckers.thibault.aves.channel.calls.SecurityHandler
|
||||
import deckers.thibault.aves.channel.calls.StorageHandler
|
||||
import deckers.thibault.aves.channel.calls.window.ActivityWindowHandler
|
||||
import deckers.thibault.aves.channel.calls.window.WindowHandler
|
||||
import deckers.thibault.aves.channel.streams.*
|
||||
import deckers.thibault.aves.channel.streams.ActivityResultStreamHandler
|
||||
import deckers.thibault.aves.channel.streams.AnalysisStreamHandler
|
||||
import deckers.thibault.aves.channel.streams.ErrorStreamHandler
|
||||
import deckers.thibault.aves.channel.streams.ImageByteStreamHandler
|
||||
import deckers.thibault.aves.channel.streams.ImageOpStreamHandler
|
||||
import deckers.thibault.aves.channel.streams.IntentStreamHandler
|
||||
import deckers.thibault.aves.channel.streams.MediaCommandStreamHandler
|
||||
import deckers.thibault.aves.channel.streams.MediaStoreChangeStreamHandler
|
||||
import deckers.thibault.aves.channel.streams.MediaStoreStreamHandler
|
||||
import deckers.thibault.aves.channel.streams.SettingsChangeStreamHandler
|
||||
import deckers.thibault.aves.model.FieldMap
|
||||
import deckers.thibault.aves.utils.FlutterUtils.enableSoftwareRendering
|
||||
import deckers.thibault.aves.utils.FlutterUtils.isSoftwareRenderingRequired
|
||||
import deckers.thibault.aves.utils.LogUtils
|
||||
import deckers.thibault.aves.utils.getParcelableExtraCompat
|
||||
import io.flutter.embedding.android.FlutterFragmentActivity
|
||||
|
@ -52,13 +76,6 @@ open class MainActivity : FlutterFragmentActivity() {
|
|||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
Log.i(LOG_TAG, "onCreate intent=$intent")
|
||||
|
||||
if (isSoftwareRenderingRequired()) {
|
||||
intent.enableSoftwareRendering()
|
||||
// running the app from Android Studio automatically adds to the intent the `start-paused` flag
|
||||
// so the IDE can connect to the app, but launching on KitKat emulators fails because of a timeout
|
||||
intent.removeExtra("start-paused")
|
||||
}
|
||||
|
||||
intent.extras?.takeUnless { it.isEmpty }?.let {
|
||||
Log.i(LOG_TAG, "onCreate intent extras=$it")
|
||||
}
|
||||
|
@ -168,11 +185,9 @@ open class MainActivity : FlutterFragmentActivity() {
|
|||
// as of Flutter v3.0.1, the window `viewInsets` and `viewPadding`
|
||||
// are incorrect on startup in some environments (e.g. API 29 emulator),
|
||||
// so we manually request to apply the insets to update the window metrics
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
window.decorView.requestApplyInsets()
|
||||
}, 100)
|
||||
}
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
window.decorView.requestApplyInsets()
|
||||
}, 100)
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
|
|
|
@ -34,7 +34,7 @@ class SearchSuggestionsProvider : ContentProvider() {
|
|||
val columns = arrayOf(
|
||||
SearchManager.SUGGEST_COLUMN_INTENT_DATA,
|
||||
SearchManager.SUGGEST_COLUMN_INTENT_EXTRA_DATA,
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) SearchManager.SUGGEST_COLUMN_CONTENT_TYPE else "mimeType",
|
||||
SearchManager.SUGGEST_COLUMN_CONTENT_TYPE,
|
||||
SearchManager.SUGGEST_COLUMN_TEXT_1,
|
||||
SearchManager.SUGGEST_COLUMN_TEXT_2,
|
||||
SearchManager.SUGGEST_COLUMN_ICON_1,
|
||||
|
|
|
@ -2,21 +2,26 @@ package deckers.thibault.aves
|
|||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import app.loup.streams_channel.StreamsChannel
|
||||
import deckers.thibault.aves.channel.AvesByteSendingMethodCodec
|
||||
import deckers.thibault.aves.channel.calls.*
|
||||
import deckers.thibault.aves.channel.calls.AccessibilityHandler
|
||||
import deckers.thibault.aves.channel.calls.DeviceHandler
|
||||
import deckers.thibault.aves.channel.calls.EmbeddedDataHandler
|
||||
import deckers.thibault.aves.channel.calls.MediaFetchBytesHandler
|
||||
import deckers.thibault.aves.channel.calls.MediaFetchObjectHandler
|
||||
import deckers.thibault.aves.channel.calls.MediaSessionHandler
|
||||
import deckers.thibault.aves.channel.calls.MetadataFetchHandler
|
||||
import deckers.thibault.aves.channel.calls.StorageHandler
|
||||
import deckers.thibault.aves.channel.calls.WallpaperHandler
|
||||
import deckers.thibault.aves.channel.calls.window.ActivityWindowHandler
|
||||
import deckers.thibault.aves.channel.calls.window.WindowHandler
|
||||
import deckers.thibault.aves.channel.streams.ImageByteStreamHandler
|
||||
import deckers.thibault.aves.channel.streams.MediaCommandStreamHandler
|
||||
import deckers.thibault.aves.model.FieldMap
|
||||
import deckers.thibault.aves.utils.FlutterUtils
|
||||
import deckers.thibault.aves.utils.FlutterUtils.enableSoftwareRendering
|
||||
import deckers.thibault.aves.utils.LogUtils
|
||||
import deckers.thibault.aves.utils.getParcelableExtraCompat
|
||||
import io.flutter.embedding.android.FlutterFragmentActivity
|
||||
|
@ -30,9 +35,6 @@ class WallpaperActivity : FlutterFragmentActivity() {
|
|||
private lateinit var mediaSessionHandler: MediaSessionHandler
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
if (FlutterUtils.isSoftwareRenderingRequired()) {
|
||||
intent.enableSoftwareRendering()
|
||||
}
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
Log.i(LOG_TAG, "onCreate intent=$intent")
|
||||
|
@ -83,11 +85,9 @@ class WallpaperActivity : FlutterFragmentActivity() {
|
|||
// as of Flutter v3.0.1, the window `viewInsets` and `viewPadding`
|
||||
// are incorrect on startup in some environments (e.g. API 29 emulator),
|
||||
// so we manually request to apply the insets to update the window metrics
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
window.decorView.requestApplyInsets()
|
||||
}, 100)
|
||||
}
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
window.decorView.requestApplyInsets()
|
||||
}, 100)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package deckers.thibault.aves.channel.calls
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.app.ComponentActivity
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.work.ExistingWorkPolicy
|
||||
import androidx.work.OneTimeWorkRequest
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
|
|
|
@ -79,15 +79,9 @@ class DebugHandler(private val context: Context) : MethodCallHandler {
|
|||
"obbDir" to context.obbDir,
|
||||
"externalCacheDir" to context.externalCacheDir,
|
||||
"externalFilesDir" to context.getExternalFilesDir(null),
|
||||
"codeCacheDir" to context.codeCacheDir,
|
||||
"noBackupFilesDir" to context.noBackupFilesDir,
|
||||
).apply {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
putAll(
|
||||
hashMapOf(
|
||||
"codeCacheDir" to context.codeCacheDir,
|
||||
"noBackupFilesDir" to context.noBackupFilesDir,
|
||||
)
|
||||
)
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
put("dataDir", context.dataDir)
|
||||
}
|
||||
|
@ -108,8 +102,6 @@ class DebugHandler(private val context: Context) : MethodCallHandler {
|
|||
}
|
||||
|
||||
private fun getCodecs(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
|
||||
val codecs = ArrayList<FieldMap>()
|
||||
|
||||
fun getFields(info: MediaCodecInfo): FieldMap {
|
||||
val fields: FieldMap = hashMapOf(
|
||||
"name" to info.name,
|
||||
|
@ -126,18 +118,7 @@ class DebugHandler(private val context: Context) : MethodCallHandler {
|
|||
return fields
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
codecs.addAll(MediaCodecList(MediaCodecList.REGULAR_CODECS).codecInfos.map(::getFields))
|
||||
} else {
|
||||
@Suppress("deprecation")
|
||||
val count = MediaCodecList.getCodecCount()
|
||||
for (i in 0 until count) {
|
||||
@Suppress("deprecation")
|
||||
val info = MediaCodecList.getCodecInfoAt(i)
|
||||
codecs.add(getFields(info))
|
||||
}
|
||||
}
|
||||
|
||||
val codecs = MediaCodecList(MediaCodecList.REGULAR_CODECS).codecInfos.map(::getFields).toList()
|
||||
result.success(codecs)
|
||||
}
|
||||
|
||||
|
|
|
@ -69,16 +69,11 @@ class DeviceHandler(private val context: Context) : MethodCallHandler {
|
|||
}
|
||||
|
||||
private fun getLocales(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
|
||||
fun toMap(locale: Locale): FieldMap {
|
||||
val fields: HashMap<String, Any?> = hashMapOf(
|
||||
"language" to locale.language,
|
||||
"country" to locale.country,
|
||||
)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
fields["script"] = locale.script
|
||||
}
|
||||
return fields
|
||||
}
|
||||
fun toMap(locale: Locale): FieldMap = hashMapOf(
|
||||
"language" to locale.language,
|
||||
"country" to locale.country,
|
||||
"script" to locale.script,
|
||||
)
|
||||
|
||||
val locales = ArrayList<FieldMap>()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
|
@ -106,11 +101,7 @@ class DeviceHandler(private val context: Context) : MethodCallHandler {
|
|||
}
|
||||
|
||||
private fun isSystemFilePickerEnabled(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
|
||||
val enabled = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).resolveActivity(context.packageManager) != null
|
||||
} else {
|
||||
false
|
||||
}
|
||||
val enabled = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).resolveActivity(context.packageManager) != null
|
||||
result.success(enabled)
|
||||
}
|
||||
|
||||
|
|
|
@ -47,9 +47,7 @@ class StorageHandler(private val context: Context) : MethodCallHandler {
|
|||
|
||||
private fun getDataUsage(@Suppress("unused_parameter") call: MethodCall, result: MethodChannel.Result) {
|
||||
var internalCache = getFolderSize(context.cacheDir)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
internalCache += getFolderSize(context.codeCacheDir)
|
||||
}
|
||||
internalCache += getFolderSize(context.codeCacheDir)
|
||||
val externalCache = context.externalCacheDirs.map(::getFolderSize).sum()
|
||||
|
||||
val dataDir = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) context.dataDir else File(context.applicationInfo.dataDir)
|
||||
|
@ -105,12 +103,7 @@ class StorageHandler(private val context: Context) : MethodCallHandler {
|
|||
val volumeFile = File(volumePath)
|
||||
try {
|
||||
val isPrimary = volumePath == primaryVolumePath
|
||||
val isRemovable = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Environment.isExternalStorageRemovable(volumeFile)
|
||||
} else {
|
||||
// random guess
|
||||
!isPrimary
|
||||
}
|
||||
val isRemovable = Environment.isExternalStorageRemovable(volumeFile)
|
||||
volumes.add(
|
||||
hashMapOf(
|
||||
"path" to volumePath,
|
||||
|
@ -202,11 +195,6 @@ class StorageHandler(private val context: Context) : MethodCallHandler {
|
|||
return
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
result.error("revokeDirectoryAccess-unsupported", "volume access is not allowed before Android Lollipop", null)
|
||||
return
|
||||
}
|
||||
|
||||
val success = PermissionManager.revokeDirectoryAccess(context, path)
|
||||
result.success(success)
|
||||
}
|
||||
|
|
|
@ -61,11 +61,6 @@ class ActivityResultStreamHandler(private val activity: Activity, arguments: Any
|
|||
return
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
error("requestDirectoryAccess-unsupported", "directory access is not allowed before Android Lollipop", null)
|
||||
return
|
||||
}
|
||||
|
||||
PermissionManager.requestDirectoryAccess(activity, ensureTrailingSeparator(path), {
|
||||
success(true)
|
||||
endOfStream()
|
||||
|
|
|
@ -4,14 +4,18 @@ import android.util.Log
|
|||
import androidx.exifinterface.media.ExifInterface
|
||||
import com.drew.lang.Rational
|
||||
import com.drew.metadata.Directory
|
||||
import com.drew.metadata.exif.*
|
||||
import com.drew.metadata.exif.ExifDirectoryBase
|
||||
import com.drew.metadata.exif.ExifIFD0Directory
|
||||
import com.drew.metadata.exif.ExifThumbnailDirectory
|
||||
import com.drew.metadata.exif.GpsDirectory
|
||||
import com.drew.metadata.exif.PanasonicRawIFD0Directory
|
||||
import com.drew.metadata.exif.makernotes.OlympusCameraSettingsMakernoteDirectory
|
||||
import com.drew.metadata.exif.makernotes.OlympusImageProcessingMakernoteDirectory
|
||||
import com.drew.metadata.exif.makernotes.OlympusMakernoteDirectory
|
||||
import deckers.thibault.aves.utils.LogUtils
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import java.util.Locale
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.floor
|
||||
import kotlin.math.roundToLong
|
||||
|
@ -22,7 +26,7 @@ object ExifInterfaceHelper {
|
|||
val GPS_DATE_FORMAT = SimpleDateFormat("yyyy:MM:dd", Locale.ROOT)
|
||||
val GPS_TIME_FORMAT = SimpleDateFormat("HH:mm:ss", Locale.ROOT)
|
||||
|
||||
private const val precisionErrorTolerance = 1e-10
|
||||
private const val PRECISION_ERROR_TOLERANCE = 1e-10
|
||||
|
||||
// ExifInterface always states it has the following attributes
|
||||
// and returns "0" instead of "null" when they are actually missing
|
||||
|
@ -220,7 +224,7 @@ object ExifInterfaceHelper {
|
|||
// initialize metadata-extractor directories that we will fill
|
||||
// by tags converted from the ExifInterface attributes
|
||||
// so that we can rely on metadata-extractor descriptions
|
||||
val dirs = DirType.values().associateWith { it.createDirectory() }
|
||||
val dirs = DirType.entries.associateWith { it.createDirectory() }
|
||||
|
||||
// exclude Exif directory when it only includes image size
|
||||
val isUselessExif = fun(it: Map<String, String>): Boolean {
|
||||
|
@ -308,7 +312,7 @@ object ExifInterfaceHelper {
|
|||
val numerator = 1L
|
||||
val f = numerator / d
|
||||
val denominator = f.roundToLong()
|
||||
if (abs(f - denominator) < precisionErrorTolerance) {
|
||||
if (abs(f - denominator) < PRECISION_ERROR_TOLERANCE) {
|
||||
return Rational(numerator, denominator)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ object Helper {
|
|||
private val PNG_RAW_PROFILE_PATTERN = Regex("^\\n(.*?)\\n\\s*(\\d+)\\n(.*)", RegexOption.DOT_MATCHES_ALL)
|
||||
|
||||
// providing the stream length is risky, as it may crash if it is incorrect
|
||||
private const val safeReadStreamLength = -1L
|
||||
private const val SAFE_READ_STREAM_LENGTH = -1L
|
||||
|
||||
fun readMimeType(input: InputStream): String? {
|
||||
val bufferedInputStream = if (input is BufferedInputStream) input else BufferedInputStream(input)
|
||||
|
@ -84,7 +84,7 @@ object Helper {
|
|||
FileType.Orf,
|
||||
FileType.Rw2 -> safeReadTiff(inputStream)
|
||||
|
||||
else -> ImageMetadataReader.readMetadata(inputStream, safeReadStreamLength, fileType)
|
||||
else -> ImageMetadataReader.readMetadata(inputStream, SAFE_READ_STREAM_LENGTH, fileType)
|
||||
}
|
||||
|
||||
metadata.addDirectory(FileTypeDirectory(fileType))
|
||||
|
@ -116,7 +116,7 @@ object Helper {
|
|||
|
||||
@Throws(IOException::class, TiffProcessingException::class)
|
||||
fun safeReadTiff(input: InputStream): com.drew.metadata.Metadata {
|
||||
val reader = RandomAccessStreamReader(input, RandomAccessStreamReader.DEFAULT_CHUNK_LENGTH, safeReadStreamLength)
|
||||
val reader = RandomAccessStreamReader(input, RandomAccessStreamReader.DEFAULT_CHUNK_LENGTH, SAFE_READ_STREAM_LENGTH)
|
||||
val metadata = com.drew.metadata.Metadata()
|
||||
val handler = SafeExifTiffHandler(metadata, null, 0)
|
||||
TiffReader().processTiff(reader, handler, 0)
|
||||
|
@ -294,9 +294,7 @@ object Helper {
|
|||
if (!modelTiePoints && !modelTransformation) return false
|
||||
|
||||
val modelPixelScale = this.containsTag(ExifGeoTiffTags.TAG_MODEL_PIXEL_SCALE)
|
||||
if ((modelTransformation && modelPixelScale) || (modelPixelScale && !modelTiePoints)) return false
|
||||
|
||||
return true
|
||||
return !((modelTransformation && modelPixelScale) || (modelPixelScale && !modelTiePoints))
|
||||
}
|
||||
|
||||
// TODO TLAD use `GeoTiffDirectory` from the Java version of `metadata-extractor` when available
|
||||
|
|
|
@ -31,6 +31,7 @@ import deckers.thibault.aves.utils.LogUtils
|
|||
import java.io.ByteArrayInputStream
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.util.Locale
|
||||
import java.util.zip.InflaterInputStream
|
||||
import java.util.zip.ZipException
|
||||
|
||||
|
@ -42,7 +43,7 @@ object SafePngMetadataReader {
|
|||
private val LOG_TAG = LogUtils.createTag<SafePngMetadataReader>()
|
||||
|
||||
// arbitrary size to detect chunks that may yield an OOM
|
||||
private const val chunkSizeDangerThreshold = SafeXmpReader.SEGMENT_TYPE_SIZE_DANGER_THRESHOLD
|
||||
private const val CHUNK_SIZE_DANGER_THRESHOLD = SafeXmpReader.SEGMENT_TYPE_SIZE_DANGER_THRESHOLD
|
||||
|
||||
private val latin1Encoding = Charsets.ISO_8859_1
|
||||
private val utf8Encoding = Charsets.UTF_8
|
||||
|
@ -85,7 +86,7 @@ object SafePngMetadataReader {
|
|||
val bytes = chunk.bytes
|
||||
|
||||
// TLAD insert start
|
||||
if (bytes.size > chunkSizeDangerThreshold) {
|
||||
if (bytes.size > CHUNK_SIZE_DANGER_THRESHOLD) {
|
||||
Log.w(LOG_TAG, "PNG chunk $chunkType is too large, with a size of ${bytes.size} B")
|
||||
return
|
||||
}
|
||||
|
@ -290,11 +291,12 @@ object SafePngMetadataReader {
|
|||
val second = reader.uInt8.toInt()
|
||||
val directory = PngDirectory(PngChunkType.tIME)
|
||||
if (DateUtil.isValidDate(year, month - 1, day) && DateUtil.isValidTime(hour, minute, second)) {
|
||||
val dateString = String.format("%04d:%02d:%02d %02d:%02d:%02d", year, month, day, hour, minute, second)
|
||||
val dateString = String.format(Locale.ROOT, "%04d:%02d:%02d %02d:%02d:%02d", year, month, day, hour, minute, second)
|
||||
directory.setString(PngDirectory.TAG_LAST_MODIFICATION_TIME, dateString)
|
||||
} else {
|
||||
directory.addError(
|
||||
String.format(
|
||||
Locale.ROOT,
|
||||
"PNG tIME data describes an invalid date/time: year=%d month=%d day=%d hour=%d minute=%d second=%d",
|
||||
year, month, day, hour, minute, second
|
||||
)
|
||||
|
|
|
@ -16,6 +16,7 @@ import com.drew.metadata.xmp.XmpDirectory
|
|||
import com.drew.metadata.xmp.XmpReader
|
||||
import deckers.thibault.aves.utils.LogUtils
|
||||
import java.io.IOException
|
||||
import java.util.Locale
|
||||
|
||||
class SafeXmpReader : XmpReader() {
|
||||
// adapted from `XmpReader` to detect and skip large extended XMP
|
||||
|
@ -133,7 +134,7 @@ class SafeXmpReader : XmpReader() {
|
|||
System.arraycopy(segmentBytes, totalOffset, extendedXMPBuffer, chunkOffset, segmentLength - totalOffset)
|
||||
} else {
|
||||
val directory = XmpDirectory()
|
||||
directory.addError(String.format("Inconsistent length for the Extended XMP buffer: %d instead of %d", fullLength, extendedXMPBuffer.size))
|
||||
directory.addError(String.format(Locale.ROOT, "Inconsistent length for the Extended XMP buffer: %d instead of %d", fullLength, extendedXMPBuffer.size))
|
||||
metadata.addDirectory(directory)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,6 @@ class MpfDirectory : Directory() {
|
|||
return _tagNameMap
|
||||
}
|
||||
|
||||
fun getNumberOfImages() = getInt(TAG_NUMBER_OF_IMAGES)
|
||||
|
||||
companion object {
|
||||
const val TAG_MPF_VERSION = 0xb000
|
||||
const val TAG_NUMBER_OF_IMAGES = 0xb001
|
||||
|
|
|
@ -15,7 +15,7 @@ class AvesEntry(map: FieldMap) {
|
|||
val trashed = map["trashed"] as Boolean
|
||||
val trashPath = map["trashPath"] as String?
|
||||
|
||||
val isRotated: Boolean
|
||||
private val isRotated: Boolean
|
||||
get() = rotationDegrees % 180 == 90
|
||||
|
||||
val displayWidth: Int
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package deckers.thibault.aves.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
|
@ -71,29 +69,4 @@ object FlutterUtils {
|
|||
r.run()
|
||||
}
|
||||
}
|
||||
|
||||
fun Intent.enableSoftwareRendering() {
|
||||
putExtra("enable-software-rendering", true)
|
||||
Log.i(LOG_TAG, "Enable software rendering")
|
||||
}
|
||||
|
||||
fun isSoftwareRenderingRequired() = Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT && isEmulator
|
||||
|
||||
private val isEmulator: Boolean
|
||||
get() = (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")
|
||||
|| Build.FINGERPRINT.startsWith("generic")
|
||||
|| Build.FINGERPRINT.startsWith("unknown")
|
||||
|| Build.HARDWARE.contains("goldfish")
|
||||
|| Build.HARDWARE.contains("ranchu")
|
||||
|| Build.MODEL.contains("google_sdk")
|
||||
|| Build.MODEL.contains("Emulator")
|
||||
|| Build.MODEL.contains("Android SDK built for x86")
|
||||
|| Build.MANUFACTURER.contains("Genymotion")
|
||||
|| Build.PRODUCT.contains("sdk_google")
|
||||
|| Build.PRODUCT.contains("google_sdk")
|
||||
|| Build.PRODUCT.contains("sdk")
|
||||
|| Build.PRODUCT.contains("sdk_x86")
|
||||
|| Build.PRODUCT.contains("vbox86p")
|
||||
|| Build.PRODUCT.contains("emulator")
|
||||
|| Build.PRODUCT.contains("simulator"))
|
||||
}
|
|
@ -28,7 +28,6 @@ object PermissionManager {
|
|||
Environment.DIRECTORY_PICTURES,
|
||||
)
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
suspend fun requestDirectoryAccess(activity: Activity, path: String, onGranted: (uri: Uri) -> Unit, onDenied: () -> Unit) {
|
||||
Log.i(LOG_TAG, "request user to select and grant access permission to path=$path")
|
||||
|
||||
|
@ -151,7 +150,6 @@ object PermissionManager {
|
|||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
fun revokeDirectoryAccess(context: Context, path: String): Boolean {
|
||||
return StorageUtils.convertDirPathToTreeDocumentUri(context, path)?.let {
|
||||
releaseUriPermission(context, it)
|
||||
|
@ -162,11 +160,9 @@ object PermissionManager {
|
|||
// returns paths matching directory URIs granted by the user
|
||||
fun getGrantedDirs(context: Context): Set<String> {
|
||||
val grantedDirs = HashSet<String>()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
for (uriPermission in context.contentResolver.persistedUriPermissions) {
|
||||
val dirPath = StorageUtils.convertTreeDocumentUriToDirPath(context, uriPermission.uri)
|
||||
dirPath?.let { grantedDirs.add(it) }
|
||||
}
|
||||
for (uriPermission in context.contentResolver.persistedUriPermissions) {
|
||||
val dirPath = StorageUtils.convertTreeDocumentUriToDirPath(context, uriPermission.uri)
|
||||
dirPath?.let { grantedDirs.add(it) }
|
||||
}
|
||||
return grantedDirs
|
||||
}
|
||||
|
@ -216,19 +212,6 @@ object PermissionManager {
|
|||
)
|
||||
})
|
||||
}
|
||||
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT
|
||||
|| Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT_WATCH
|
||||
) {
|
||||
// removable storage requires access permission, at the file level
|
||||
// without directory access, we consider the whole volume restricted
|
||||
val primaryVolume = StorageUtils.getPrimaryVolumePath(context)
|
||||
val nonPrimaryVolumes = StorageUtils.getVolumePaths(context).filter { it != primaryVolume }
|
||||
dirs.addAll(nonPrimaryVolumes.map {
|
||||
hashMapOf(
|
||||
"volumePath" to it,
|
||||
"relativeDir" to "",
|
||||
)
|
||||
})
|
||||
}
|
||||
return dirs
|
||||
}
|
||||
|
@ -236,7 +219,6 @@ object PermissionManager {
|
|||
// As of Android 11, `MediaStore.getDocumentUri` fails if any of the persisted
|
||||
// URI permissions we hold points to a folder that no longer exists,
|
||||
// so we should remove these obsolete URIs before proceeding.
|
||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
fun sanitizePersistedUriPermissions(context: Context) {
|
||||
try {
|
||||
for (uriPermission in context.contentResolver.persistedUriPermissions) {
|
||||
|
@ -252,7 +234,6 @@ object PermissionManager {
|
|||
}
|
||||
}
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private fun releaseUriPermission(context: Context, it: Uri) {
|
||||
val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
context.contentResolver.releasePersistableUriPermission(it, flags)
|
||||
|
|
|
@ -16,7 +16,6 @@ import android.provider.DocumentsContract
|
|||
import android.provider.MediaStore
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import androidx.annotation.RequiresApi
|
||||
import com.commonsware.cwac.document.DocumentFileCompat
|
||||
import deckers.thibault.aves.model.provider.ImageProvider
|
||||
import deckers.thibault.aves.utils.FileUtils.transferFrom
|
||||
|
@ -29,7 +28,7 @@ import java.io.FileInputStream
|
|||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.util.*
|
||||
import java.util.Locale
|
||||
import java.util.regex.Pattern
|
||||
|
||||
object StorageUtils {
|
||||
|
@ -381,7 +380,6 @@ object StorageUtils {
|
|||
// e.g.
|
||||
// /storage/emulated/0/ -> content://com.android.externalstorage.documents/tree/primary%3A
|
||||
// /storage/10F9-3F13/Pictures/ -> content://com.android.externalstorage.documents/tree/10F9-3F13%3APictures
|
||||
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
fun convertDirPathToTreeDocumentUri(context: Context, dirPath: String): Uri? {
|
||||
val uuid = getVolumeUuidForDocumentUri(context, dirPath)
|
||||
if (uuid != null) {
|
||||
|
@ -446,7 +444,7 @@ object StorageUtils {
|
|||
|
||||
fun getDocumentFile(context: Context, anyPath: String, mediaUri: Uri): DocumentFileCompat? {
|
||||
try {
|
||||
if (requireAccessPermission(context, anyPath) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (requireAccessPermission(context, anyPath)) {
|
||||
// need a document URI (not a media content URI) to open a `DocumentFile` output stream
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && isMediaStoreContentUri(mediaUri)) {
|
||||
// cleanest API to get it
|
||||
|
@ -485,7 +483,7 @@ object StorageUtils {
|
|||
fun createDirectoryDocIfAbsent(context: Context, dirPath: String): DocumentFileCompat? {
|
||||
try {
|
||||
val cleanDirPath = ensureTrailingSeparator(dirPath)
|
||||
return if (requireAccessPermission(context, cleanDirPath) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
return if (requireAccessPermission(context, cleanDirPath)) {
|
||||
val grantedDir = getGrantedDirForPath(context, cleanDirPath) ?: return null
|
||||
val rootTreeDocumentUri = convertDirPathToTreeDocumentUri(context, grantedDir) ?: return null
|
||||
var parentFile: DocumentFileCompat? = DocumentFileCompat.fromTreeUri(context, rootTreeDocumentUri) ?: return null
|
||||
|
|
|
@ -26,5 +26,5 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'androidx.annotation:annotation:1.7.1'
|
||||
implementation 'androidx.annotation:annotation:1.8.0'
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
import 'package:aves/widgets/aves_app.dart';
|
||||
import 'package:aves_utils/aves_utils.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -26,16 +25,21 @@ class Themes {
|
|||
}
|
||||
}
|
||||
|
||||
static Color _schemeCardLayer(ColorScheme colors) => ElevationOverlay.applySurfaceTint(colors.surface, colors.surfaceTint, 1);
|
||||
static bool _isDarkTheme(ColorScheme colors) => colors.brightness == Brightness.dark && colors.surface != Colors.black;
|
||||
|
||||
static Color firstLayerColor(BuildContext context) => _schemeFirstLayer(Theme.of(context).colorScheme);
|
||||
|
||||
static Color _schemeFirstLayer(ColorScheme colors) => _isDarkTheme(colors) ? colors.surfaceContainer : colors.surface;
|
||||
|
||||
static Color _schemeCardLayer(ColorScheme colors) => _isDarkTheme(colors) ? _schemeSecondLayer(colors) : colors.surfaceContainerLow;
|
||||
|
||||
static Color secondLayerColor(BuildContext context) => _schemeSecondLayer(Theme.of(context).colorScheme);
|
||||
|
||||
// `DialogTheme` M3 defaults use `6.0` elevation
|
||||
static Color _schemeSecondLayer(ColorScheme colors) => ElevationOverlay.applySurfaceTint(colors.surface, colors.surfaceTint, 6);
|
||||
static Color _schemeSecondLayer(ColorScheme colors) => _isDarkTheme(colors) ? colors.surfaceContainerHigh : colors.surfaceContainer;
|
||||
|
||||
static Color thirdLayerColor(BuildContext context) => _schemeThirdLayer(Theme.of(context).colorScheme);
|
||||
|
||||
static Color _schemeThirdLayer(ColorScheme colors) => ElevationOverlay.applySurfaceTint(colors.surface, colors.surfaceTint, 12);
|
||||
static Color _schemeThirdLayer(ColorScheme colors) => _isDarkTheme(colors) ? colors.surfaceContainerHighest : colors.surfaceContainerHigh;
|
||||
|
||||
static Color _unselectedWidgetColor(ColorScheme colors) => colors.onSurface.withOpacity(0.6);
|
||||
|
||||
|
@ -55,14 +59,15 @@ class Themes {
|
|||
colorScheme: colors,
|
||||
dividerColor: colors.outlineVariant,
|
||||
indicatorColor: colors.primary,
|
||||
scaffoldBackgroundColor: colors.background,
|
||||
scaffoldBackgroundColor: _schemeFirstLayer(colors),
|
||||
// TYPOGRAPHY & ICONOGRAPHY
|
||||
typography: _typography,
|
||||
// COMPONENT THEMES
|
||||
checkboxTheme: _checkboxTheme(colors),
|
||||
drawerTheme: _drawerTheme(colors),
|
||||
floatingActionButtonTheme: _floatingActionButtonTheme(colors),
|
||||
navigationRailTheme: NavigationRailThemeData(
|
||||
backgroundColor: colors.background,
|
||||
backgroundColor: _schemeFirstLayer(colors),
|
||||
selectedIconTheme: IconThemeData(color: colors.primary),
|
||||
unselectedIconTheme: IconThemeData(color: _unselectedWidgetColor(colors)),
|
||||
selectedLabelTextStyle: TextStyle(color: colors.primary),
|
||||
|
@ -78,16 +83,21 @@ class Themes {
|
|||
side: BorderSide(width: 2.0, color: _unselectedWidgetColor(colors)),
|
||||
);
|
||||
|
||||
static DrawerThemeData _drawerTheme(ColorScheme colors) => DrawerThemeData(
|
||||
backgroundColor: _schemeSecondLayer(colors),
|
||||
);
|
||||
|
||||
static const _listTileTheme = ListTileThemeData(
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 16),
|
||||
);
|
||||
|
||||
static PopupMenuThemeData _popupMenuTheme(ColorScheme colors, TextTheme textTheme) {
|
||||
return PopupMenuThemeData(
|
||||
labelTextStyle: MaterialStateProperty.resolveWith((states) {
|
||||
color: _schemeSecondLayer(colors),
|
||||
labelTextStyle: WidgetStateProperty.resolveWith((states) {
|
||||
// adapted from M3 defaults
|
||||
final TextStyle style = textTheme.labelLarge!;
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
if (states.contains(WidgetState.disabled)) {
|
||||
return style.apply(color: colors.onSurface.withOpacity(0.38));
|
||||
}
|
||||
return style.apply(color: colors.onSurface);
|
||||
|
@ -105,23 +115,23 @@ class Themes {
|
|||
|
||||
// adapted from M3 defaults
|
||||
static RadioThemeData _radioTheme(ColorScheme colors) => RadioThemeData(
|
||||
fillColor: MaterialStateProperty.resolveWith<Color>((states) {
|
||||
if (states.contains(MaterialState.selected)) {
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
fillColor: WidgetStateProperty.resolveWith<Color>((states) {
|
||||
if (states.contains(WidgetState.selected)) {
|
||||
if (states.contains(WidgetState.disabled)) {
|
||||
return colors.onSurface.withOpacity(0.38);
|
||||
}
|
||||
return colors.primary;
|
||||
}
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
if (states.contains(WidgetState.disabled)) {
|
||||
return colors.onSurface.withOpacity(0.38);
|
||||
}
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return colors.onSurface;
|
||||
}
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
if (states.contains(WidgetState.hovered)) {
|
||||
return colors.onSurface;
|
||||
}
|
||||
if (states.contains(MaterialState.focused)) {
|
||||
if (states.contains(WidgetState.focused)) {
|
||||
return colors.onSurface;
|
||||
}
|
||||
return _unselectedWidgetColor(colors);
|
||||
|
@ -166,13 +176,15 @@ class Themes {
|
|||
textTheme: textTheme,
|
||||
// COMPONENT THEMES
|
||||
appBarTheme: AppBarTheme(
|
||||
backgroundColor: _schemeFirstLayer(colors),
|
||||
// `foregroundColor` is used by icons
|
||||
foregroundColor: _lightActionIconColor,
|
||||
// `titleTextStyle.color` is used by text
|
||||
titleTextStyle: _titleTextStyle.copyWith(color: _lightTitleColor),
|
||||
systemOverlayStyle: deviceInitialized ? AvesApp.systemUIStyleForBrightness(colors.brightness, colors.background) : null,
|
||||
systemOverlayStyle: deviceInitialized ? AvesApp.systemUIStyleForBrightness(colors.brightness, _schemeFirstLayer(colors)) : null,
|
||||
),
|
||||
dialogTheme: DialogTheme(
|
||||
backgroundColor: _schemeSecondLayer(colors),
|
||||
titleTextStyle: _titleTextStyle.copyWith(color: _lightTitleColor),
|
||||
),
|
||||
listTileTheme: _listTileTheme.copyWith(
|
||||
|
@ -217,13 +229,15 @@ class Themes {
|
|||
textTheme: textTheme,
|
||||
// COMPONENT THEMES
|
||||
appBarTheme: AppBarTheme(
|
||||
backgroundColor: _schemeFirstLayer(colors),
|
||||
// `foregroundColor` is used by icons
|
||||
foregroundColor: _darkTitleColor,
|
||||
// `titleTextStyle.color` is used by text
|
||||
titleTextStyle: _titleTextStyle.copyWith(color: _darkTitleColor),
|
||||
systemOverlayStyle: deviceInitialized ? AvesApp.systemUIStyleForBrightness(colors.brightness, colors.background) : null,
|
||||
systemOverlayStyle: deviceInitialized ? AvesApp.systemUIStyleForBrightness(colors.brightness, _schemeFirstLayer(colors)) : null,
|
||||
),
|
||||
dialogTheme: DialogTheme(
|
||||
backgroundColor: _schemeSecondLayer(colors),
|
||||
titleTextStyle: _titleTextStyle.copyWith(color: _darkTitleColor),
|
||||
),
|
||||
listTileTheme: _listTileTheme,
|
||||
|
@ -251,13 +265,8 @@ class Themes {
|
|||
|
||||
static ThemeData blackTheme(Color accentColor, bool deviceInitialized) {
|
||||
final colors = _darkColorScheme(accentColor).copyWith(
|
||||
background: Colors.black,
|
||||
);
|
||||
final baseTheme = _baseDarkTheme(colors, deviceInitialized);
|
||||
return baseTheme.copyWith(
|
||||
appBarTheme: baseTheme.appBarTheme.copyWith(
|
||||
backgroundColor: colors.background,
|
||||
),
|
||||
surface: Colors.black,
|
||||
);
|
||||
return _baseDarkTheme(colors, deviceInitialized);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:aves/model/device.dart';
|
||||
import 'package:aves/theme/themes.dart';
|
||||
import 'package:aves/widgets/about/app_ref.dart';
|
||||
import 'package:aves/widgets/about/credits.dart';
|
||||
import 'package:aves/widgets/about/translators.dart';
|
||||
|
@ -192,7 +193,7 @@ class _ContentState extends State<_Content> {
|
|||
return Theme(
|
||||
data: theme.copyWith(
|
||||
listTileTheme: listTileTheme.copyWith(
|
||||
tileColor: theme.colorScheme.background,
|
||||
tileColor: Themes.firstLayerColor(context),
|
||||
),
|
||||
),
|
||||
child: const TvLicensePage(),
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'package:aves/app_flavor.dart';
|
|||
import 'package:aves/model/app/dependencies.dart';
|
||||
import 'package:aves/ref/brand_colors.dart';
|
||||
import 'package:aves/theme/colors.dart';
|
||||
import 'package:aves/theme/themes.dart';
|
||||
import 'package:aves/widgets/about/title.dart';
|
||||
import 'package:aves/widgets/common/basic/link_chip.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
|
@ -87,8 +88,8 @@ class _LicensesState extends State<Licenses> {
|
|||
MaterialPageRoute(
|
||||
builder: (context) => Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
// as of Flutter v3.7.8, `cardColor` is used as a background color by `LicensePage`
|
||||
cardColor: Theme.of(context).colorScheme.background,
|
||||
// as of Flutter v3.22.0, `cardColor` is used as a background color by `LicensePage`
|
||||
cardColor: Themes.firstLayerColor(context),
|
||||
),
|
||||
child: const LicensePage(),
|
||||
),
|
||||
|
|
|
@ -31,7 +31,7 @@ class AboutTranslators extends StatelessWidget {
|
|||
static Widget buildBody(BuildContext context) {
|
||||
return _RandomTextSpanHighlighter(
|
||||
spans: Contributors.translators.map((v) => v.name).toList(),
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:developer' show Flow, Timeline;
|
||||
|
||||
import 'package:aves/theme/themes.dart';
|
||||
import 'package:aves/widgets/common/basic/scaffold.dart';
|
||||
import 'package:aves/widgets/common/behaviour/intents.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
@ -77,7 +78,7 @@ class _TvLicensePageState extends State<TvLicensePage> {
|
|||
final isSelected = index == selectedIndex;
|
||||
final theme = Theme.of(context);
|
||||
return Ink(
|
||||
color: isSelected ? theme.highlightColor : theme.colorScheme.background,
|
||||
color: isSelected ? theme.highlightColor : Themes.firstLayerColor(context),
|
||||
child: ListTile(
|
||||
title: Text(packageName),
|
||||
subtitle: Text(MaterialLocalizations.of(context).licensesPackageDetailText(bindings.length)),
|
||||
|
@ -298,7 +299,7 @@ class _PackageLicensePageState extends State<_PackageLicensePage> {
|
|||
),
|
||||
body: Center(
|
||||
child: Material(
|
||||
color: theme.colorScheme.background,
|
||||
color: Themes.firstLayerColor(context),
|
||||
elevation: 4.0,
|
||||
child: Container(
|
||||
constraints: BoxConstraints.loose(const Size.fromWidth(600.0)),
|
||||
|
@ -328,7 +329,7 @@ class _PackageLicensePageState extends State<_PackageLicensePage> {
|
|||
SliverAppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
pinned: true,
|
||||
backgroundColor: theme.colorScheme.background,
|
||||
backgroundColor: Themes.firstLayerColor(context),
|
||||
title: _PackageLicensePageTitle(
|
||||
title: title,
|
||||
subtitle: subtitle,
|
||||
|
|
|
@ -96,12 +96,12 @@ class AvesApp extends StatefulWidget {
|
|||
State<AvesApp> createState() => _AvesAppState();
|
||||
|
||||
static void setSystemUIStyle(ThemeData theme) {
|
||||
final style = systemUIStyleForBrightness(theme.brightness, theme.colorScheme.background);
|
||||
final style = systemUIStyleForBrightness(theme.brightness, theme.colorScheme.surfaceContainer);
|
||||
SystemChrome.setSystemUIOverlayStyle(style);
|
||||
}
|
||||
|
||||
static SystemUiOverlayStyle systemUIStyleForBrightness(Brightness themeBrightness, Color backgroundColor) {
|
||||
final barBrightness = themeBrightness == Brightness.light ? Brightness.dark : Brightness.light;
|
||||
final barBrightness = themeBrightness == Brightness.dark ? Brightness.light : Brightness.dark;
|
||||
const statusBarColor = Colors.transparent;
|
||||
// as of Flutter v3.3.0-0.2.pre, setting `SystemUiOverlayStyle` (whether manually or automatically because of `AppBar`)
|
||||
// prevents the canvas from drawing behind the nav bar on Android <10 (API <29),
|
||||
|
|
|
@ -87,7 +87,7 @@ mixin FeedbackMixin {
|
|||
action: action != null
|
||||
? TextButton(
|
||||
style: ButtonStyle(
|
||||
foregroundColor: MaterialStateProperty.all(snackBarTheme.actionTextColor),
|
||||
foregroundColor: WidgetStateProperty.all(snackBarTheme.actionTextColor),
|
||||
),
|
||||
onPressed: () {
|
||||
notificationOverlayEntry?.dismiss();
|
||||
|
|
|
@ -132,12 +132,10 @@ class _OverlaySnackBarState extends State<OverlaySnackBar> {
|
|||
primary: colorScheme.onPrimary,
|
||||
secondary: buttonColor,
|
||||
surface: colorScheme.onSurface,
|
||||
background: defaults.backgroundColor!,
|
||||
error: colorScheme.onError,
|
||||
onPrimary: colorScheme.primary,
|
||||
onSecondary: colorScheme.secondary,
|
||||
onSurface: colorScheme.surface,
|
||||
onBackground: colorScheme.background,
|
||||
onError: colorScheme.error,
|
||||
brightness: brightness,
|
||||
),
|
||||
|
@ -363,17 +361,17 @@ class _SnackbarDefaultsM3 extends SnackBarThemeData {
|
|||
Color get backgroundColor => _colors.inverseSurface;
|
||||
|
||||
@override
|
||||
Color get actionTextColor => MaterialStateColor.resolveWith((states) {
|
||||
if (states.contains(MaterialState.disabled)) {
|
||||
Color get actionTextColor => WidgetStateColor.resolveWith((states) {
|
||||
if (states.contains(WidgetState.disabled)) {
|
||||
return _colors.inversePrimary;
|
||||
}
|
||||
if (states.contains(MaterialState.pressed)) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return _colors.inversePrimary;
|
||||
}
|
||||
if (states.contains(MaterialState.hovered)) {
|
||||
if (states.contains(WidgetState.hovered)) {
|
||||
return _colors.inversePrimary;
|
||||
}
|
||||
if (states.contains(MaterialState.focused)) {
|
||||
if (states.contains(WidgetState.focused)) {
|
||||
return _colors.inversePrimary;
|
||||
}
|
||||
return _colors.inversePrimary;
|
||||
|
|
|
@ -38,7 +38,7 @@ class MarkdownContainer extends StatelessWidget {
|
|||
child = Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
scrollbarTheme: ScrollbarThemeData(
|
||||
thumbVisibility: MaterialStateProperty.all(true),
|
||||
thumbVisibility: WidgetStateProperty.all(true),
|
||||
radius: const Radius.circular(16),
|
||||
crossAxisMargin: 6,
|
||||
mainAxisMargin: 16,
|
||||
|
|
|
@ -46,8 +46,8 @@ class _PopupMenuExpansionPanelState<T> extends State<PopupMenuExpansionPanel<T>>
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final style = PopupMenuTheme.of(context).labelTextStyle!.resolve(
|
||||
<MaterialState>{
|
||||
if (!widget.enabled) MaterialState.disabled,
|
||||
<WidgetState>{
|
||||
if (!widget.enabled) WidgetState.disabled,
|
||||
},
|
||||
)!;
|
||||
final animationDuration = context.select<DurationsData, Duration>((v) => v.expansionTileAnimation);
|
||||
|
|
|
@ -103,7 +103,7 @@ class _WheelSelectorState<T> extends State<WheelSelector<T>> {
|
|||
child: Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
scrollbarTheme: ScrollbarThemeData(
|
||||
thumbVisibility: MaterialStateProperty.all(false),
|
||||
thumbVisibility: WidgetStateProperty.all(false),
|
||||
),
|
||||
),
|
||||
child: ListWheelScrollView(
|
||||
|
|
|
@ -51,7 +51,7 @@ class MosaicScaleOverlay extends StatelessWidget {
|
|||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
_buildBar(extentMax, colorScheme.onBackground.withOpacity(.2)),
|
||||
_buildBar(extentMax, colorScheme.onSurface.withOpacity(.2)),
|
||||
_buildBar(scaledSize.width, colorScheme.primary),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:aves/model/settings/settings.dart';
|
||||
import 'package:aves/theme/durations.dart';
|
||||
import 'package:aves/theme/themes.dart';
|
||||
import 'package:aves/widgets/aves_app.dart';
|
||||
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
|
||||
import 'package:aves/widgets/common/basic/insets.dart';
|
||||
|
@ -227,7 +228,7 @@ class _AvesFloatingBarState extends State<AvesFloatingBar> with RouteAware {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final backgroundColor = theme.appBarTheme.backgroundColor ?? theme.colorScheme.surface;
|
||||
final backgroundColor = theme.appBarTheme.backgroundColor ?? Themes.firstLayerColor(context);
|
||||
return ValueListenableBuilder<bool>(
|
||||
valueListenable: _isBlurAllowedNotifier,
|
||||
builder: (context, isBlurAllowed, child) {
|
||||
|
|
|
@ -15,7 +15,7 @@ class AvesCaption extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final subtitleStyle = theme.textTheme.bodySmall!;
|
||||
final subtitleChangeShadowColor = theme.colorScheme.onBackground;
|
||||
final subtitleChangeShadowColor = theme.colorScheme.onSurface;
|
||||
return ChangeHighlightText(
|
||||
// provide key to refresh on theme brightness change
|
||||
key: ValueKey(subtitleChangeShadowColor),
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:aves/theme/durations.dart';
|
||||
import 'package:aves/theme/themes.dart';
|
||||
import 'package:aves/widgets/common/identity/highlight_title.dart';
|
||||
import 'package:expansion_tile_card/expansion_tile_card.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -56,7 +57,7 @@ class AvesExpansionTile extends StatelessWidget {
|
|||
expandable: enabled,
|
||||
initiallyExpanded: initiallyExpanded,
|
||||
finalPadding: const EdgeInsets.symmetric(vertical: 6.0),
|
||||
baseColor: theme.colorScheme.background,
|
||||
baseColor: Themes.firstLayerColor(context),
|
||||
expandedTextColor: colorScheme.onSurface,
|
||||
duration: animationDuration,
|
||||
shadowColor: theme.shadowColor,
|
||||
|
|
|
@ -12,6 +12,7 @@ import 'package:aves/model/settings/enums/accessibility_animations.dart';
|
|||
import 'package:aves/model/settings/settings.dart';
|
||||
import 'package:aves/theme/colors.dart';
|
||||
import 'package:aves/theme/icons.dart';
|
||||
import 'package:aves/theme/themes.dart';
|
||||
import 'package:aves/view/view.dart';
|
||||
import 'package:aves/widgets/collection/filter_bar.dart';
|
||||
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
|
||||
|
@ -48,6 +49,7 @@ class AvesFilterChip extends StatefulWidget {
|
|||
final CollectionFilter filter;
|
||||
final bool showText, showGenericIcon, useFilterColor;
|
||||
final AvesFilterDecoration? decoration;
|
||||
final Color? background;
|
||||
final String? banner;
|
||||
final Widget? leadingOverride, details;
|
||||
final double padding;
|
||||
|
@ -71,6 +73,7 @@ class AvesFilterChip extends StatefulWidget {
|
|||
this.showGenericIcon = true,
|
||||
this.useFilterColor = true,
|
||||
this.decoration,
|
||||
this.background,
|
||||
this.banner,
|
||||
this.leadingOverride,
|
||||
this.details,
|
||||
|
@ -233,7 +236,7 @@ class _AvesFilterChipState extends State<AvesFilterChip> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final decoration = widget.decoration;
|
||||
final chipBackground = Theme.of(context).colorScheme.background;
|
||||
final chipBackground = widget.background ?? Themes.firstLayerColor(context);
|
||||
|
||||
final onTap = widget.onTap != null
|
||||
? () {
|
||||
|
|
|
@ -16,13 +16,13 @@ class AvesOutlinedButton extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final style = ButtonStyle(
|
||||
side: MaterialStateProperty.resolveWith<BorderSide>((states) {
|
||||
side: WidgetStateProperty.resolveWith<BorderSide>((states) {
|
||||
return BorderSide(
|
||||
color: states.contains(MaterialState.disabled) ? theme.disabledColor : theme.colorScheme.primary,
|
||||
color: states.contains(WidgetState.disabled) ? theme.disabledColor : theme.colorScheme.primary,
|
||||
);
|
||||
}),
|
||||
foregroundColor: MaterialStateProperty.resolveWith<Color>((states) {
|
||||
return states.contains(MaterialState.disabled) ? theme.disabledColor : theme.colorScheme.onBackground;
|
||||
foregroundColor: WidgetStateProperty.resolveWith<Color>((states) {
|
||||
return states.contains(WidgetState.disabled) ? theme.disabledColor : theme.colorScheme.onSurface;
|
||||
}),
|
||||
);
|
||||
return icon != null
|
||||
|
|
|
@ -161,7 +161,7 @@ class OverlayTextButton extends StatelessWidget {
|
|||
});
|
||||
|
||||
static const _borderRadius = 123.0;
|
||||
static final _minSize = MaterialStateProperty.all<Size>(const Size(kMinInteractiveDimension, kMinInteractiveDimension));
|
||||
static final _minSize = WidgetStateProperty.all<Size>(const Size(kMinInteractiveDimension, kMinInteractiveDimension));
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -173,12 +173,12 @@ class OverlayTextButton extends StatelessWidget {
|
|||
child: OutlinedButton(
|
||||
onPressed: onPressed,
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStateProperty.all<Color>(Themes.overlayBackgroundColor(brightness: theme.brightness, blurred: blurred)),
|
||||
foregroundColor: MaterialStateProperty.all<Color>(theme.colorScheme.onSurface),
|
||||
overlayColor: theme.isDark ? MaterialStateProperty.all<Color>(Colors.white.withOpacity(0.12)) : null,
|
||||
backgroundColor: WidgetStateProperty.all<Color>(Themes.overlayBackgroundColor(brightness: theme.brightness, blurred: blurred)),
|
||||
foregroundColor: WidgetStateProperty.all<Color>(theme.colorScheme.onSurface),
|
||||
overlayColor: theme.isDark ? WidgetStateProperty.all<Color>(Colors.white.withOpacity(0.12)) : null,
|
||||
minimumSize: _minSize,
|
||||
side: MaterialStateProperty.all<BorderSide>(AvesBorder.curvedSide(context)),
|
||||
shape: MaterialStateProperty.all<OutlinedBorder>(const RoundedRectangleBorder(
|
||||
side: WidgetStateProperty.all<BorderSide>(AvesBorder.curvedSide(context)),
|
||||
shape: WidgetStateProperty.all<OutlinedBorder>(const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(_borderRadius)),
|
||||
)),
|
||||
),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
import 'package:aves/model/settings/settings.dart';
|
||||
import 'package:aves/theme/colors.dart';
|
||||
import 'package:aves/theme/themes.dart';
|
||||
import 'package:aves/widgets/common/basic/text/outlined.dart';
|
||||
import 'package:aves/widgets/common/extensions/theme.dart';
|
||||
import 'package:aves/widgets/common/fx/highlight_decoration.dart';
|
||||
|
@ -61,7 +62,7 @@ class HighlightTitle extends StatelessWidget {
|
|||
style: style,
|
||||
),
|
||||
],
|
||||
outlineColor: Theme.of(context).colorScheme.background,
|
||||
outlineColor: Themes.firstLayerColor(context),
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.fade,
|
||||
maxLines: 1,
|
||||
|
|
|
@ -60,49 +60,43 @@ class _OverlayCoordinateFilterChipState extends State<OverlayCoordinateFilterChi
|
|||
Widget build(BuildContext context) {
|
||||
final blurred = settings.enableBlurEffect;
|
||||
final theme = Theme.of(context);
|
||||
return Theme(
|
||||
data: theme.copyWith(
|
||||
colorScheme: theme.colorScheme.copyWith(
|
||||
background: Themes.overlayBackgroundColor(brightness: theme.brightness, blurred: blurred),
|
||||
return Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Selector<MapThemeData, Animation<double>>(
|
||||
selector: (context, v) => v.scale,
|
||||
builder: (context, scale, child) => SizeTransition(
|
||||
sizeFactor: scale,
|
||||
axisAlignment: 1,
|
||||
child: FadeTransition(
|
||||
opacity: scale,
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Selector<MapThemeData, Animation<double>>(
|
||||
selector: (context, v) => v.scale,
|
||||
builder: (context, scale, child) => SizeTransition(
|
||||
sizeFactor: scale,
|
||||
axisAlignment: 1,
|
||||
child: FadeTransition(
|
||||
opacity: scale,
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
child: ValueListenableBuilder<ZoomedBounds?>(
|
||||
valueListenable: _idleBoundsNotifier,
|
||||
builder: (context, bounds, child) {
|
||||
if (bounds == null) return const SizedBox();
|
||||
final filter = CoordinateFilter(
|
||||
bounds.sw,
|
||||
bounds.ne,
|
||||
// more stable format when bounds change
|
||||
minuteSecondPadding: true,
|
||||
);
|
||||
return Padding(
|
||||
padding: EdgeInsets.all(widget.padding),
|
||||
child: BlurredRRect.all(
|
||||
enabled: blurred,
|
||||
borderRadius: AvesFilterChip.defaultRadius,
|
||||
child: AvesFilterChip(
|
||||
filter: filter,
|
||||
useFilterColor: false,
|
||||
maxWidth: double.infinity,
|
||||
onTap: (filter) => FilterSelectedNotification(CoordinateFilter(bounds.sw, bounds.ne)).dispatch(context),
|
||||
),
|
||||
child: ValueListenableBuilder<ZoomedBounds?>(
|
||||
valueListenable: _idleBoundsNotifier,
|
||||
builder: (context, bounds, child) {
|
||||
if (bounds == null) return const SizedBox();
|
||||
final filter = CoordinateFilter(
|
||||
bounds.sw,
|
||||
bounds.ne,
|
||||
// more stable format when bounds change
|
||||
minuteSecondPadding: true,
|
||||
);
|
||||
return Padding(
|
||||
padding: EdgeInsets.all(widget.padding),
|
||||
child: BlurredRRect.all(
|
||||
enabled: blurred,
|
||||
borderRadius: AvesFilterChip.defaultRadius,
|
||||
child: AvesFilterChip(
|
||||
filter: filter,
|
||||
useFilterColor: false,
|
||||
background: Themes.overlayBackgroundColor(brightness: theme.brightness, blurred: blurred),
|
||||
maxWidth: double.infinity,
|
||||
onTap: (filter) => FilterSelectedNotification(CoordinateFilter(bounds.sw, bounds.ne)).dispatch(context),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -67,7 +67,7 @@ class _ErrorThumbnailState extends State<ErrorThumbnail> {
|
|||
}
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
color: Themes.firstLayerColor(context),
|
||||
width: extent,
|
||||
height: extent,
|
||||
child: child,
|
||||
|
|
|
@ -20,23 +20,39 @@ class _DebugColorSectionState extends State<DebugColorSection> with AutomaticKee
|
|||
('onPrimary', scheme.onPrimary),
|
||||
('primaryContainer', scheme.primaryContainer),
|
||||
('onPrimaryContainer', scheme.onPrimaryContainer),
|
||||
('primaryFixed', scheme.primaryFixed),
|
||||
('primaryFixedDim', scheme.primaryFixedDim),
|
||||
('onPrimaryFixed', scheme.onPrimaryFixed),
|
||||
('onPrimaryFixedVariant', scheme.onPrimaryFixedVariant),
|
||||
('secondary', scheme.secondary),
|
||||
('onSecondary', scheme.onSecondary),
|
||||
('secondaryContainer', scheme.secondaryContainer),
|
||||
('onSecondaryContainer', scheme.onSecondaryContainer),
|
||||
('secondaryFixed', scheme.secondaryFixed),
|
||||
('secondaryFixedDim', scheme.secondaryFixedDim),
|
||||
('onSecondaryFixed', scheme.onSecondaryFixed),
|
||||
('onSecondaryFixedVariant', scheme.onSecondaryFixedVariant),
|
||||
('tertiary', scheme.tertiary),
|
||||
('onTertiary', scheme.onTertiary),
|
||||
('tertiaryContainer', scheme.tertiaryContainer),
|
||||
('onTertiaryContainer', scheme.onTertiaryContainer),
|
||||
('tertiaryFixed', scheme.tertiaryFixed),
|
||||
('tertiaryFixedDim', scheme.tertiaryFixedDim),
|
||||
('onTertiaryFixed', scheme.onTertiaryFixed),
|
||||
('onTertiaryFixedVariant', scheme.onTertiaryFixedVariant),
|
||||
('error', scheme.error),
|
||||
('onError', scheme.onError),
|
||||
('errorContainer', scheme.errorContainer),
|
||||
('onErrorContainer', scheme.onErrorContainer),
|
||||
('background', scheme.background),
|
||||
('onBackground', scheme.onBackground),
|
||||
('surface', scheme.surface),
|
||||
('onSurface', scheme.onSurface),
|
||||
('surfaceVariant', scheme.surfaceVariant),
|
||||
('surfaceDim', scheme.surfaceDim),
|
||||
('surfaceBright', scheme.surfaceBright),
|
||||
('surfaceContainerLowest', scheme.surfaceContainerLowest),
|
||||
('surfaceContainerLow', scheme.surfaceContainerLow),
|
||||
('surfaceContainer', scheme.surfaceContainer),
|
||||
('surfaceContainerHigh', scheme.surfaceContainerHigh),
|
||||
('surfaceContainerHighest', scheme.surfaceContainerHighest),
|
||||
('onSurfaceVariant', scheme.onSurfaceVariant),
|
||||
('outline', scheme.outline),
|
||||
('outlineVariant', scheme.outlineVariant),
|
||||
|
|
|
@ -74,7 +74,7 @@ class AvesDialog extends StatelessWidget {
|
|||
child = Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
scrollbarTheme: ScrollbarThemeData(
|
||||
thumbVisibility: MaterialStateProperty.all(true),
|
||||
thumbVisibility: WidgetStateProperty.all(true),
|
||||
radius: const Radius.circular(16),
|
||||
crossAxisMargin: 4,
|
||||
// adapt margin when corner is around content itself, not outside for the title
|
||||
|
|
|
@ -99,7 +99,7 @@ class _ConvertEntryDialogState extends State<ConvertEntryDialog> {
|
|||
const contentHorizontalPadding = EdgeInsets.symmetric(horizontal: AvesDialog.defaultHorizontalContentPadding);
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final trailingStyle = TextStyle(color: colorScheme.onSurfaceVariant);
|
||||
final trailingChangeShadowColor = colorScheme.onBackground;
|
||||
final trailingChangeShadowColor = colorScheme.onSurface;
|
||||
|
||||
// used by the drop down to match input decoration
|
||||
final textFieldDecorationBorder = Border(
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'package:aves/model/settings/settings.dart';
|
|||
import 'package:aves/ref/brand_colors.dart';
|
||||
import 'package:aves/theme/colors.dart';
|
||||
import 'package:aves/theme/durations.dart';
|
||||
import 'package:aves/theme/themes.dart';
|
||||
import 'package:aves/view/view.dart';
|
||||
import 'package:aves/widgets/common/basic/text/outlined.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
|
@ -113,7 +114,7 @@ class _RemoveEntryMetadataDialogState extends State<RemoveEntryMetadataDialog> {
|
|||
),
|
||||
),
|
||||
],
|
||||
outlineColor: Theme.of(context).colorScheme.background,
|
||||
outlineColor: Themes.firstLayerColor(context),
|
||||
);
|
||||
if (context.select<Settings, bool>((v) => v.themeColorMode == AvesThemeColorMode.polychrome)) {
|
||||
final colors = context.watch<AvesColorsData>();
|
||||
|
|
|
@ -36,7 +36,7 @@ class _PatternDialogState extends State<PatternDialog> {
|
|||
child: PatternLock(
|
||||
relativePadding: .4,
|
||||
selectedColor: colorScheme.primary,
|
||||
notSelectedColor: colorScheme.onBackground,
|
||||
notSelectedColor: colorScheme.onSurface,
|
||||
pointRadius: 8,
|
||||
fillPoints: true,
|
||||
onInputComplete: (input) => _submit(input.join()),
|
||||
|
|
|
@ -50,8 +50,8 @@ class _PinDialogState extends State<PinDialog> {
|
|||
autoFocus: true,
|
||||
autoDismissKeyboard: !widget.needConfirmation || _confirming,
|
||||
pinTheme: PinTheme(
|
||||
activeColor: colorScheme.onBackground,
|
||||
inactiveColor: colorScheme.onBackground,
|
||||
activeColor: colorScheme.onSurface,
|
||||
inactiveColor: colorScheme.onSurface,
|
||||
selectedColor: colorScheme.primary,
|
||||
selectedFillColor: colorScheme.primary,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
|
|
|
@ -124,7 +124,7 @@ class _AppDrawerState extends State<AppDrawer> {
|
|||
final onPrimary = colorScheme.onPrimary;
|
||||
|
||||
final drawerButtonStyle = ButtonStyle(
|
||||
padding: MaterialStateProperty.all(const EdgeInsetsDirectional.only(start: 12, end: 16)),
|
||||
padding: WidgetStateProperty.all(const EdgeInsetsDirectional.only(start: 12, end: 16)),
|
||||
);
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
|
@ -163,9 +163,9 @@ class _AppDrawerState extends State<AppDrawer> {
|
|||
OutlinedButtonTheme(
|
||||
data: OutlinedButtonThemeData(
|
||||
style: ButtonStyle(
|
||||
foregroundColor: MaterialStateProperty.all<Color>(onPrimary),
|
||||
overlayColor: MaterialStateProperty.all<Color>(onPrimary.withOpacity(.12)),
|
||||
side: MaterialStateProperty.all<BorderSide>(BorderSide(width: 1, color: onPrimary.withOpacity(.24))),
|
||||
foregroundColor: WidgetStateProperty.all<Color>(onPrimary),
|
||||
overlayColor: WidgetStateProperty.all<Color>(onPrimary.withOpacity(.12)),
|
||||
side: WidgetStateProperty.all<BorderSide>(BorderSide(width: 1, color: onPrimary.withOpacity(.24))),
|
||||
),
|
||||
),
|
||||
child: Wrap(
|
||||
|
|
|
@ -275,7 +275,7 @@ class _QuickActionEditorBodyState<T extends Object> extends State<QuickActionEdi
|
|||
effect: WormEffect(
|
||||
dotWidth: 8,
|
||||
dotHeight: 8,
|
||||
dotColor: colorScheme.onBackground.withOpacity(.2),
|
||||
dotColor: colorScheme.onSurface.withOpacity(.2),
|
||||
activeDotColor: colorScheme.primary,
|
||||
),
|
||||
),
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:aves/theme/durations.dart';
|
||||
import 'package:aves/theme/styles.dart';
|
||||
import 'package:aves/theme/themes.dart';
|
||||
import 'package:aves/widgets/common/extensions/theme.dart';
|
||||
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
||||
import 'package:decorated_icon/decorated_icon.dart';
|
||||
|
@ -17,12 +18,10 @@ class SettingsTileLeading extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final colorScheme = theme.colorScheme;
|
||||
return AnimatedContainer(
|
||||
padding: const EdgeInsets.all(6),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.background,
|
||||
color: Themes.firstLayerColor(context),
|
||||
border: Border.fromBorderSide(BorderSide(
|
||||
color: color,
|
||||
width: AvesFilterChip.outlineWidth,
|
||||
|
@ -34,7 +33,7 @@ class SettingsTileLeading extends StatelessWidget {
|
|||
icon,
|
||||
size: 18,
|
||||
color: DefaultTextStyle.of(context).style.color,
|
||||
shadows: theme.isDark ? AStyles.embossShadows : null,
|
||||
shadows: Theme.of(context).isDark ? AStyles.embossShadows : null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -80,7 +80,6 @@ class _ContentState extends State<_Content> {
|
|||
valueListenable: _indexNotifier,
|
||||
builder: (context, selectedIndex, child) {
|
||||
final rail = NavigationRail(
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
extended: true,
|
||||
destinations: sections
|
||||
.map((section) => NavigationRailDestination(
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'package:aves/model/entry/entry.dart';
|
|||
import 'package:aves/model/entry/sort.dart';
|
||||
import 'package:aves/model/filters/date.dart';
|
||||
import 'package:aves/theme/durations.dart';
|
||||
import 'package:aves/theme/themes.dart';
|
||||
import 'package:aves/utils/time_utils.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
import 'package:aves/widgets/common/fx/transitions.dart';
|
||||
|
@ -196,11 +197,11 @@ class _HistogramState extends State<Histogram> with AutomaticKeepAliveClientMixi
|
|||
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
final accentColor = colorScheme.primary;
|
||||
final axisColor = charts.ColorUtil.fromDartColor(drawPoints ? colorScheme.onBackground : Colors.transparent);
|
||||
final measureLineColor = charts.ColorUtil.fromDartColor(drawPoints ? colorScheme.onBackground.withOpacity(.1) : Colors.transparent);
|
||||
final axisColor = charts.ColorUtil.fromDartColor(drawPoints ? colorScheme.onSurface : Colors.transparent);
|
||||
final measureLineColor = charts.ColorUtil.fromDartColor(drawPoints ? colorScheme.onSurface.withOpacity(.1) : Colors.transparent);
|
||||
final histogramLineColor = charts.ColorUtil.fromDartColor(drawLine ? accentColor : Colors.white);
|
||||
final histogramPointStrikeColor = charts.ColorUtil.fromDartColor(drawPoints ? colorScheme.onSurface : Colors.transparent);
|
||||
final histogramPointFillColor = charts.ColorUtil.fromDartColor(colorScheme.background);
|
||||
final histogramPointFillColor = charts.ColorUtil.fromDartColor(Themes.firstLayerColor(context));
|
||||
|
||||
final series = [
|
||||
if (drawLine || drawArea)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:aves/theme/styles.dart';
|
||||
import 'package:aves/theme/themes.dart';
|
||||
import 'package:aves/widgets/common/basic/text/outlined.dart';
|
||||
import 'package:aves/widgets/common/extensions/theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -15,17 +16,16 @@ class LinearPercentIndicatorText extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
return OutlinedText(
|
||||
textSpans: [
|
||||
TextSpan(
|
||||
text: percentFormat.format(percent),
|
||||
style: TextStyle(
|
||||
shadows: theme.isDark ? AStyles.embossShadows : null,
|
||||
shadows: Theme.of(context).isDark ? AStyles.embossShadows : null,
|
||||
),
|
||||
)
|
||||
],
|
||||
outlineColor: theme.colorScheme.background,
|
||||
outlineColor: Themes.firstLayerColor(context),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import 'package:aves/widgets/common/app_bar/sliver_app_bar_title.dart';
|
|||
import 'package:aves/widgets/common/basic/font_size_icon_theme.dart';
|
||||
import 'package:aves/widgets/common/basic/popup/menu_row.dart';
|
||||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
import 'package:aves/widgets/common/search/route.dart';
|
||||
import 'package:aves/widgets/viewer/action/entry_info_action_delegate.dart';
|
||||
import 'package:aves/widgets/viewer/info/info_search.dart';
|
||||
import 'package:aves/widgets/viewer/info/metadata/metadata_dir.dart';
|
||||
|
@ -112,14 +113,15 @@ class InfoAppBar extends StatelessWidget {
|
|||
|
||||
void _goToSearch(BuildContext context) {
|
||||
final isSelecting = context.read<Selection<AvesEntry>?>()?.isSelecting ?? false;
|
||||
showSearch(
|
||||
context: context,
|
||||
delegate: InfoSearchDelegate(
|
||||
searchFieldLabel: context.l10n.viewerInfoSearchFieldLabel,
|
||||
searchFieldStyle: Themes.searchFieldStyle(context),
|
||||
entry: entry,
|
||||
metadataNotifier: metadataNotifier,
|
||||
isSelecting: isSelecting,
|
||||
Navigator.maybeOf(context)?.push(
|
||||
SearchPageRoute(
|
||||
delegate: InfoSearchDelegate(
|
||||
searchFieldLabel: context.l10n.viewerInfoSearchFieldLabel,
|
||||
searchFieldStyle: Themes.searchFieldStyle(context),
|
||||
entry: entry,
|
||||
metadataNotifier: metadataNotifier,
|
||||
isSelecting: isSelecting,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -3,28 +3,30 @@ import 'package:aves/theme/icons.dart';
|
|||
import 'package:aves/widgets/common/extensions/build_context.dart';
|
||||
import 'package:aves/widgets/common/identity/empty.dart';
|
||||
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
|
||||
import 'package:aves/widgets/common/search/delegate.dart';
|
||||
import 'package:aves/widgets/viewer/info/embedded/embedded_data_opener.dart';
|
||||
import 'package:aves/widgets/viewer/info/metadata/metadata_dir.dart';
|
||||
import 'package:aves/widgets/viewer/info/metadata/metadata_dir_tile.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class InfoSearchDelegate extends SearchDelegate {
|
||||
class InfoSearchDelegate extends AvesSearchDelegate {
|
||||
final AvesEntry entry;
|
||||
final ValueNotifier<Map<String, MetadataDirectory>> metadataNotifier;
|
||||
final bool isSelecting;
|
||||
|
||||
Map<String, MetadataDirectory> get metadata => metadataNotifier.value;
|
||||
|
||||
static const pageRouteName = '/info/search';
|
||||
|
||||
InfoSearchDelegate({
|
||||
required String searchFieldLabel,
|
||||
required TextStyle searchFieldStyle,
|
||||
required super.searchFieldLabel,
|
||||
required super.searchFieldStyle,
|
||||
required this.entry,
|
||||
required this.metadataNotifier,
|
||||
required this.isSelecting,
|
||||
}) : super(
|
||||
searchFieldLabel: searchFieldLabel,
|
||||
searchFieldStyle: searchFieldStyle,
|
||||
routeName: pageRouteName,
|
||||
);
|
||||
|
||||
@override
|
||||
|
|
|
@ -64,7 +64,6 @@ class _TvMetadataPageState extends State<TvMetadataPage> {
|
|||
if (selectedDir == null) return const SizedBox();
|
||||
|
||||
final rail = NavigationRail(
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
extended: true,
|
||||
destinations: titles.mapIndexed((i, title) {
|
||||
final dir = metadata[titles[i]]!;
|
||||
|
|
|
@ -65,10 +65,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.12.0"
|
||||
nested:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -153,10 +153,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.12.0"
|
||||
mgrs_dart:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -58,10 +58,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.12.0"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
|
|
@ -48,6 +48,6 @@ android {
|
|||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdk 19
|
||||
minSdk 21
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,10 +50,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.12.0"
|
||||
plugin_platform_interface:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -50,10 +50,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.12.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -57,10 +57,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.12.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -131,26 +131,26 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa"
|
||||
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.0"
|
||||
version: "10.0.4"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0
|
||||
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
version: "3.0.3"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_testing
|
||||
sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47
|
||||
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
version: "3.0.1"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -179,10 +179,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.12.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -248,10 +248,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.1"
|
||||
version: "0.7.0"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -264,10 +264,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957
|
||||
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "13.0.0"
|
||||
version: "14.2.1"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -278,4 +278,4 @@ packages:
|
|||
version: "0.5.1"
|
||||
sdks:
|
||||
dart: ">=3.3.0 <4.0.0"
|
||||
flutter: ">=3.3.0"
|
||||
flutter: ">=3.18.0-18.0.pre.54"
|
||||
|
|
|
@ -48,6 +48,6 @@ android {
|
|||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdk 19
|
||||
minSdk 21
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,10 +50,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.12.0"
|
||||
plugin_platform_interface:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -160,10 +160,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.12.0"
|
||||
mgrs_dart:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -323,10 +323,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.12.0"
|
||||
mgrs_dart:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -464,10 +464,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb"
|
||||
sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.5.0"
|
||||
version: "5.5.1"
|
||||
win32_registry:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -485,5 +485,5 @@ packages:
|
|||
source: hosted
|
||||
version: "2.0.0"
|
||||
sdks:
|
||||
dart: ">=3.3.0 <4.0.0"
|
||||
dart: ">=3.4.0 <4.0.0"
|
||||
flutter: ">=3.19.0"
|
||||
|
|
|
@ -199,10 +199,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.12.0"
|
||||
mgrs_dart:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -167,10 +167,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.12.0"
|
||||
mgrs_dart:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -50,10 +50,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.12.0"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
|
|
@ -50,10 +50,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.12.0"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
|
|
@ -72,10 +72,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.12.0"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
|
|
@ -96,10 +96,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.12.0"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -88,10 +88,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.12.0"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
|
|
@ -212,10 +212,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.12.0"
|
||||
package_info_plus:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -433,10 +433,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb"
|
||||
sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.5.0"
|
||||
version: "5.5.1"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -446,5 +446,5 @@ packages:
|
|||
source: hosted
|
||||
version: "6.5.0"
|
||||
sdks:
|
||||
dart: ">=3.3.0 <4.0.0"
|
||||
dart: ">=3.4.0 <4.0.0"
|
||||
flutter: ">=3.19.0"
|
||||
|
|
66
pubspec.lock
66
pubspec.lock
|
@ -177,7 +177,7 @@ packages:
|
|||
description:
|
||||
path: charts_common
|
||||
ref: aves
|
||||
resolved-ref: "6c44dc05289c1a5dbf0b027dbba083669843072c"
|
||||
resolved-ref: ba7833d74e17ff497d3f4fb48f362d2dfdf3c6e3
|
||||
url: "https://github.com/deckerst/flutter_google_charts.git"
|
||||
source: git
|
||||
version: "0.12.0"
|
||||
|
@ -186,7 +186,7 @@ packages:
|
|||
description:
|
||||
path: charts_flutter
|
||||
ref: aves
|
||||
resolved-ref: "6c44dc05289c1a5dbf0b027dbba083669843072c"
|
||||
resolved-ref: ba7833d74e17ff497d3f4fb48f362d2dfdf3c6e3
|
||||
url: "https://github.com/deckerst/flutter_google_charts.git"
|
||||
source: git
|
||||
version: "0.12.0"
|
||||
|
@ -436,18 +436,18 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: flex_color_picker
|
||||
sha256: "5c846437069fb7afdd7ade6bf37e628a71d2ab0787095ddcb1253bf9345d5f3a"
|
||||
sha256: "31b27677d8d8400e4cff5edb3f189f606dd964d608779b6ae1b7ddad37ea48c6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.1"
|
||||
version: "3.5.0"
|
||||
flex_seed_scheme:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flex_seed_scheme
|
||||
sha256: "4cee2f1d07259f77e8b36f4ec5f35499d19e74e17c7dce5b819554914082bc01"
|
||||
sha256: fb66cdb8ca89084e79efcad2bc2d9deb144666875116f08cdd8d9f8238c8b3ab
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.0"
|
||||
version: "2.0.0"
|
||||
floating:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -511,7 +511,7 @@ packages:
|
|||
description:
|
||||
path: "."
|
||||
ref: HEAD
|
||||
resolved-ref: "2956bcff219761aa90a1c95ad2d90b0050ae208f"
|
||||
resolved-ref: f35b88327b98a1494426cf40ff7c30281cc7f937
|
||||
url: "https://github.com/deckerst/flutter_localization_nn.git"
|
||||
source: git
|
||||
version: "0.0.1"
|
||||
|
@ -566,10 +566,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: frontend_server_client
|
||||
sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612"
|
||||
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
version: "4.0.0"
|
||||
fuchsia_remote_debug_protocol:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
|
@ -715,10 +715,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: intl
|
||||
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
|
||||
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.18.1"
|
||||
version: "0.19.0"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -755,26 +755,26 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa"
|
||||
sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.0.0"
|
||||
version: "10.0.4"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_flutter_testing
|
||||
sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0
|
||||
sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
version: "3.0.3"
|
||||
leak_tracker_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker_testing
|
||||
sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47
|
||||
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.1"
|
||||
version: "3.0.1"
|
||||
lints:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -915,10 +915,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
|
||||
sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.12.0"
|
||||
mgrs_dart:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1093,10 +1093,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: pdf_widget_wrapper
|
||||
sha256: "9c3ca36e5000c9682d52bbdc486867ba7c5ee4403d1a5d6d03ed72157753377b"
|
||||
sha256: c930860d987213a3d58c7ec3b7ecf8085c3897f773e8dc23da9cae60a5d6d0f5
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
version: "1.0.4"
|
||||
percent_indicator:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -1531,26 +1531,26 @@ packages:
|
|||
dependency: "direct dev"
|
||||
description:
|
||||
name: test
|
||||
sha256: a1f7595805820fcc05e5c52e3a231aedd0b72972cb333e8c738a8b1239448b6f
|
||||
sha256: "7ee446762c2c50b3bd4ea96fe13ffac69919352bd3b4b17bac3f3465edc58073"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.24.9"
|
||||
version: "1.25.2"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||
sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.1"
|
||||
version: "0.7.0"
|
||||
test_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_core
|
||||
sha256: a757b14fc47507060a162cc2530d9a4a2f92f5100a952c7443b5cad5ef5b106a
|
||||
sha256: "2bc4b4ecddd75309300d8096f781c0e3280ca1ef85beda558d33fcbedc2eead4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.9"
|
||||
version: "0.6.0"
|
||||
transparent_image:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -1675,10 +1675,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957
|
||||
sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "13.0.0"
|
||||
version: "14.2.1"
|
||||
volume_controller:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -1747,10 +1747,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb"
|
||||
sha256: a79dbe579cb51ecd6d30b17e0cae4e0ea15e2c0e66f69ad4198f22a6789e94f4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.5.0"
|
||||
version: "5.5.1"
|
||||
win32_registry:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -1792,5 +1792,5 @@ packages:
|
|||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.3.0 <4.0.0"
|
||||
flutter: ">=3.19.6"
|
||||
dart: ">=3.4.0 <4.0.0"
|
||||
flutter: ">=3.22.0"
|
||||
|
|
|
@ -13,7 +13,7 @@ publish_to: none
|
|||
environment:
|
||||
# this project bundles Flutter SDK via `flutter_wrapper`
|
||||
# cf https://github.com/passsy/flutter_wrapper
|
||||
flutter: 3.19.6
|
||||
flutter: 3.22.0
|
||||
sdk: '>=3.3.0 <4.0.0'
|
||||
|
||||
# use `scripts/apply_flavor_{flavor}.sh` to set the right dependencies for the flavor
|
||||
|
|
Loading…
Reference in a new issue