minor fixes
This commit is contained in:
parent
a71a30130b
commit
3ea5ddd753
7 changed files with 74 additions and 41 deletions
|
@ -77,29 +77,34 @@ class SearchSuggestionsProvider : MethodChannel.MethodCallHandler, ContentProvid
|
|||
val backgroundChannel = MethodChannel(messenger, BACKGROUND_CHANNEL)
|
||||
backgroundChannel.setMethodCallHandler(this)
|
||||
|
||||
return suspendCoroutine { cont ->
|
||||
GlobalScope.launch {
|
||||
FlutterUtils.runOnUiThread {
|
||||
backgroundChannel.invokeMethod("getSuggestions", hashMapOf(
|
||||
"query" to query,
|
||||
"locale" to Locale.getDefault().toString(),
|
||||
"use24hour" to DateFormat.is24HourFormat(context),
|
||||
), object : MethodChannel.Result {
|
||||
override fun success(result: Any?) {
|
||||
@Suppress("unchecked_cast")
|
||||
cont.resume(result as List<FieldMap>)
|
||||
}
|
||||
try {
|
||||
return suspendCoroutine { cont ->
|
||||
GlobalScope.launch {
|
||||
FlutterUtils.runOnUiThread {
|
||||
backgroundChannel.invokeMethod("getSuggestions", hashMapOf(
|
||||
"query" to query,
|
||||
"locale" to Locale.getDefault().toString(),
|
||||
"use24hour" to DateFormat.is24HourFormat(context),
|
||||
), object : MethodChannel.Result {
|
||||
override fun success(result: Any?) {
|
||||
@Suppress("unchecked_cast")
|
||||
cont.resume(result as List<FieldMap>)
|
||||
}
|
||||
|
||||
override fun error(errorCode: String, errorMessage: String?, errorDetails: Any?) {
|
||||
cont.resumeWithException(Exception("$errorCode: $errorMessage\n$errorDetails"))
|
||||
}
|
||||
override fun error(errorCode: String, errorMessage: String?, errorDetails: Any?) {
|
||||
cont.resumeWithException(Exception("$errorCode: $errorMessage\n$errorDetails"))
|
||||
}
|
||||
|
||||
override fun notImplemented() {
|
||||
cont.resumeWithException(NotImplementedError("getSuggestions"))
|
||||
}
|
||||
})
|
||||
override fun notImplemented() {
|
||||
cont.resumeWithException(NotImplementedError("getSuggestions"))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(LOG_TAG, "failed to get suggestions", e)
|
||||
return ArrayList()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -80,7 +80,6 @@ import kotlinx.coroutines.launch
|
|||
import java.nio.charset.Charset
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.text.ParseException
|
||||
import java.util.*
|
||||
import kotlin.math.roundToInt
|
||||
import kotlin.math.roundToLong
|
||||
|
||||
|
@ -412,19 +411,19 @@ class MetadataFetchHandler(private val context: Context) : MethodCallHandler {
|
|||
|
||||
// File type
|
||||
for (dir in metadata.getDirectoriesOfType(FileTypeDirectory::class.java)) {
|
||||
// * `metadata-extractor` sometimes detects the wrong MIME type (e.g. `pef` file as `tiff`, `mpeg` as `dvd`)
|
||||
// * `metadata-extractor` sometimes detects the wrong MIME type (e.g. `pef` file as `tiff`, `mpeg` as `dvd`, `avif` as `mov`)
|
||||
// * the content resolver / media store sometimes reports the wrong MIME type (e.g. `png` file as `jpeg`, `tiff` as `srw`)
|
||||
// * `context.getContentResolver().getType()` sometimes returns an incorrect value
|
||||
// * `MediaMetadataRetriever.setDataSource()` sometimes fails with `status = 0x80000000`
|
||||
// * file extension is unreliable
|
||||
// In the end, `metadata-extractor` is the most reliable, except for `tiff`/`dvd` (false positives, false negatives),
|
||||
// In the end, `metadata-extractor` is the most reliable, except for `tiff`/`dvd`/`mov` (false positives, false negatives),
|
||||
// in which case we trust the file extension
|
||||
// cf https://github.com/drewnoakes/metadata-extractor/issues/296
|
||||
if (path?.matches(TIFF_EXTENSION_PATTERN) == true) {
|
||||
metadataMap[KEY_MIME_TYPE] = MimeTypes.TIFF
|
||||
} else {
|
||||
dir.getSafeString(FileTypeDirectory.TAG_DETECTED_FILE_MIME_TYPE) {
|
||||
if (it != MimeTypes.TIFF && it != MimeTypes.DVD) {
|
||||
if (it != MimeTypes.TIFF && it != MimeTypes.DVD && it != MimeTypes.MOV) {
|
||||
metadataMap[KEY_MIME_TYPE] = it
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ class GSpherical(xmlBytes: ByteArray) {
|
|||
}
|
||||
}
|
||||
|
||||
fun describe(): Map<String, String?> = hashMapOf(
|
||||
fun describe(): Map<String, String> = hashMapOf(
|
||||
"Spherical" to spherical.toString(),
|
||||
"Stitched" to stitched.toString(),
|
||||
"Stitching Software" to stitchingSoftware,
|
||||
|
@ -79,7 +79,7 @@ class GSpherical(xmlBytes: ByteArray) {
|
|||
"Cropped Area Image Height Pixels" to croppedAreaImageHeightPixels?.toString(),
|
||||
"Cropped Area Left Pixels" to croppedAreaLeftPixels?.toString(),
|
||||
"Cropped Area Top Pixels" to croppedAreaTopPixels?.toString(),
|
||||
).filterValues { it != null }
|
||||
).filterValues { it != null }.mapValues { it.value as String }
|
||||
|
||||
companion object SphericalVideo {
|
||||
private val LOG_TAG = LogUtils.createTag<SphericalVideo>()
|
||||
|
|
|
@ -6,6 +6,7 @@ object MimeTypes {
|
|||
const val ANY = "*/*"
|
||||
|
||||
// generic raster
|
||||
private const val AVIF = "image/avif"
|
||||
const val BMP = "image/bmp"
|
||||
private const val DJVU = "image/vnd.djvu"
|
||||
const val GIF = "image/gif"
|
||||
|
@ -49,7 +50,7 @@ object MimeTypes {
|
|||
private const val AVI_VND = "video/vnd.avi"
|
||||
const val DVD = "video/dvd"
|
||||
private const val MKV = "video/x-matroska"
|
||||
private const val MOV = "video/quicktime"
|
||||
const val MOV = "video/quicktime"
|
||||
private const val MP2T = "video/mp2t"
|
||||
private const val MP2TS = "video/mp2ts"
|
||||
const val MP4 = "video/mp4"
|
||||
|
@ -72,7 +73,7 @@ object MimeTypes {
|
|||
// returns whether the specified MIME type represents
|
||||
// a raster image format that allows an alpha channel
|
||||
fun canHaveAlpha(mimeType: String?) = when (mimeType) {
|
||||
BMP, GIF, ICO, PNG, SVG, TIFF, WEBP -> true
|
||||
AVIF, BMP, GIF, ICO, PNG, SVG, TIFF, WEBP -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
|
@ -150,6 +151,7 @@ object MimeTypes {
|
|||
fun extensionFor(mimeType: String): String? = when (mimeType) {
|
||||
ARW -> ".arw"
|
||||
AVI, AVI_VND -> ".avi"
|
||||
AVIF -> ".avif"
|
||||
BMP -> ".bmp"
|
||||
CR2 -> ".cr2"
|
||||
CRW -> ".crw"
|
||||
|
|
|
@ -158,15 +158,35 @@ class _AvesAppState extends State<AvesApp> {
|
|||
);
|
||||
}
|
||||
|
||||
// setup before the first page is displayed. keep it short
|
||||
Future<void> _setup() async {
|
||||
final stopwatch = Stopwatch()..start();
|
||||
|
||||
// TODO TLAD [init] init settings/device w/o platform calls (first platform channel call takes ~800ms):
|
||||
// 1) use cached values if any,
|
||||
// 2a) call platform w/ delay if cached
|
||||
// 2b) call platform w/o delay if not cached
|
||||
// 3) cache platform call results across app restarts
|
||||
|
||||
await device.init();
|
||||
final isRotationLocked = await windowService.isRotationLocked();
|
||||
final areAnimationsRemoved = await AccessibilityService.areAnimationsRemoved();
|
||||
|
||||
// TODO TLAD [init] migrate settings away from `shared_preferences` to a platform-free solution
|
||||
await settings.init(
|
||||
monitorPlatformSettings: true,
|
||||
isRotationLocked: await windowService.isRotationLocked(),
|
||||
areAnimationsRemoved: await AccessibilityService.areAnimationsRemoved(),
|
||||
isRotationLocked: isRotationLocked,
|
||||
areAnimationsRemoved: areAnimationsRemoved,
|
||||
);
|
||||
await device.init();
|
||||
FijkLog.setLevel(FijkLogLevel.Warn);
|
||||
_monitorSettings();
|
||||
|
||||
FijkLog.setLevel(FijkLogLevel.Warn);
|
||||
unawaited(_setupErrorReporting());
|
||||
|
||||
debugPrint('App setup in ${stopwatch.elapsed.inMilliseconds}ms');
|
||||
}
|
||||
|
||||
void _monitorSettings() {
|
||||
// keep screen on
|
||||
settings.updateStream.where((key) => key == Settings.keepScreenOnKey).listen(
|
||||
(_) => settings.keepScreenOn.apply(),
|
||||
|
@ -183,8 +203,9 @@ class _AvesAppState extends State<AvesApp> {
|
|||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// error reporting
|
||||
Future<void> _setupErrorReporting() async {
|
||||
await reportService.init();
|
||||
settings.updateStream.where((key) => key == Settings.isErrorReportingAllowedKey).listen(
|
||||
(_) => reportService.setCollectionEnabled(settings.isErrorReportingAllowed),
|
||||
|
|
|
@ -44,7 +44,7 @@ class AvesDialog extends StatelessWidget {
|
|||
// and overflow feedback ignores the dialog shape,
|
||||
// so we restrict scrolling to the content instead
|
||||
content: _buildContent(context),
|
||||
contentPadding: scrollableContent != null ? EdgeInsets.zero : EdgeInsets.fromLTRB(horizontalContentPadding, 20, horizontalContentPadding, 0),
|
||||
contentPadding: scrollableContent != null ? EdgeInsets.zero : EdgeInsets.only(left: horizontalContentPadding, top: 20, right: horizontalContentPadding),
|
||||
actions: actions,
|
||||
actionsPadding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
shape: shape(context),
|
||||
|
|
|
@ -51,12 +51,14 @@ class _ExportEntryDialogState extends State<ExportEntryDialog> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = context.l10n;
|
||||
const contentHorizontalPadding = EdgeInsets.symmetric(horizontal: AvesDialog.defaultHorizontalContentPadding);
|
||||
|
||||
return AvesDialog(
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
scrollableContent: [
|
||||
const SizedBox(height: 16),
|
||||
Padding(
|
||||
padding: contentHorizontalPadding,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(l10n.exportEntryDialogFormat),
|
||||
|
@ -77,7 +79,10 @@ class _ExportEntryDialogState extends State<ExportEntryDialog> {
|
|||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
),
|
||||
Padding(
|
||||
padding: contentHorizontalPadding,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.baseline,
|
||||
textBaseline: TextBaseline.alphabetic,
|
||||
children: [
|
||||
|
@ -108,8 +113,9 @@ class _ExportEntryDialogState extends State<ExportEntryDialog> {
|
|||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
|
|
Loading…
Reference in a new issue