mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
refactor, fix capacity handling
This commit is contained in:
@@ -30,20 +30,20 @@ class NativeByteBuffer(initialCapacity: Int) {
|
|||||||
var capacity = initialCapacity
|
var capacity = initialCapacity
|
||||||
var offset = 0
|
var offset = 0
|
||||||
|
|
||||||
fun ensureHeadroom(needed: Int = INITIAL_BUFFER_SIZE) {
|
inline fun ensureHeadroom() {
|
||||||
if (offset + needed > capacity) {
|
if (offset == capacity) {
|
||||||
capacity = (capacity * 2).coerceAtLeast(offset + needed)
|
capacity *= 2
|
||||||
pointer = NativeBuffer.realloc(pointer, capacity)
|
pointer = NativeBuffer.realloc(pointer, capacity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun wrapRemaining() = NativeBuffer.wrap(pointer + offset, capacity - offset)
|
inline fun wrapRemaining() = NativeBuffer.wrap(pointer + offset, capacity - offset)
|
||||||
|
|
||||||
fun advance(bytesRead: Int) {
|
inline fun advance(bytesRead: Int) {
|
||||||
offset += bytesRead
|
offset += bytesRead
|
||||||
}
|
}
|
||||||
|
|
||||||
fun free() {
|
inline fun free() {
|
||||||
if (pointer != 0L) {
|
if (pointer != 0L) {
|
||||||
NativeBuffer.free(pointer)
|
NativeBuffer.free(pointer)
|
||||||
pointer = 0L
|
pointer = 0L
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ private open class LocalImagesPigeonCodec : StandardMessageCodec() {
|
|||||||
|
|
||||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||||
interface LocalImageApi {
|
interface LocalImageApi {
|
||||||
fun requestImage(assetId: String, requestId: Long, width: Long, height: Long, isVideo: Boolean, callback: (Result<Map<String, Long>>) -> Unit)
|
fun requestImage(assetId: String, requestId: Long, width: Long, height: Long, isVideo: Boolean, callback: (Result<Map<String, Long>?>) -> Unit)
|
||||||
fun cancelRequest(requestId: Long)
|
fun cancelRequest(requestId: Long)
|
||||||
fun getThumbhash(thumbhash: String, callback: (Result<Map<String, Long>>) -> Unit)
|
fun getThumbhash(thumbhash: String, callback: (Result<Map<String, Long>>) -> Unit)
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ interface LocalImageApi {
|
|||||||
val widthArg = args[2] as Long
|
val widthArg = args[2] as Long
|
||||||
val heightArg = args[3] as Long
|
val heightArg = args[3] as Long
|
||||||
val isVideoArg = args[4] as Boolean
|
val isVideoArg = args[4] as Boolean
|
||||||
api.requestImage(assetIdArg, requestIdArg, widthArg, heightArg, isVideoArg) { result: Result<Map<String, Long>> ->
|
api.requestImage(assetIdArg, requestIdArg, widthArg, heightArg, isVideoArg) { result: Result<Map<String, Long>?> ->
|
||||||
val error = result.exceptionOrNull()
|
val error = result.exceptionOrNull()
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
reply.reply(LocalImagesPigeonUtils.wrapError(error))
|
reply.reply(LocalImagesPigeonUtils.wrapError(error))
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import java.util.concurrent.Future
|
|||||||
data class Request(
|
data class Request(
|
||||||
val taskFuture: Future<*>,
|
val taskFuture: Future<*>,
|
||||||
val cancellationSignal: CancellationSignal,
|
val cancellationSignal: CancellationSignal,
|
||||||
val callback: (Result<Map<String, Long>>) -> Unit
|
val callback: (Result<Map<String, Long>?>) -> Unit
|
||||||
)
|
)
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.Q)
|
@RequiresApi(Build.VERSION_CODES.Q)
|
||||||
@@ -71,7 +71,7 @@ class LocalImagesImpl(context: Context) : LocalImageApi {
|
|||||||
private val requestMap = ConcurrentHashMap<Long, Request>()
|
private val requestMap = ConcurrentHashMap<Long, Request>()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val CANCELLED = Result.success<Map<String, Long>>(mapOf())
|
val CANCELLED = Result.success<Map<String, Long>?>(null)
|
||||||
val OPTIONS = BitmapFactory.Options().apply { inPreferredConfig = Bitmap.Config.ARGB_8888 }
|
val OPTIONS = BitmapFactory.Options().apply { inPreferredConfig = Bitmap.Config.ARGB_8888 }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ class LocalImagesImpl(context: Context) : LocalImageApi {
|
|||||||
width: Long,
|
width: Long,
|
||||||
height: Long,
|
height: Long,
|
||||||
isVideo: Boolean,
|
isVideo: Boolean,
|
||||||
callback: (Result<Map<String, Long>>) -> Unit
|
callback: (Result<Map<String, Long>?>) -> Unit
|
||||||
) {
|
) {
|
||||||
val signal = CancellationSignal()
|
val signal = CancellationSignal()
|
||||||
val task = threadPool.submit {
|
val task = threadPool.submit {
|
||||||
@@ -138,7 +138,7 @@ class LocalImagesImpl(context: Context) : LocalImageApi {
|
|||||||
width: Long,
|
width: Long,
|
||||||
height: Long,
|
height: Long,
|
||||||
isVideo: Boolean,
|
isVideo: Boolean,
|
||||||
callback: (Result<Map<String, Long>>) -> Unit,
|
callback: (Result<Map<String, Long>?>) -> Unit,
|
||||||
signal: CancellationSignal
|
signal: CancellationSignal
|
||||||
) {
|
) {
|
||||||
signal.throwIfCanceled()
|
signal.throwIfCanceled()
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ private open class RemoteImagesPigeonCodec : StandardMessageCodec() {
|
|||||||
|
|
||||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||||
interface RemoteImageApi {
|
interface RemoteImageApi {
|
||||||
fun requestImage(url: String, headers: Map<String, String>, requestId: Long, callback: (Result<Map<String, Long>>) -> Unit)
|
fun requestImage(url: String, headers: Map<String, String>, requestId: Long, callback: (Result<Map<String, Long>?>) -> Unit)
|
||||||
fun cancelRequest(requestId: Long)
|
fun cancelRequest(requestId: Long)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -67,7 +67,7 @@ interface RemoteImageApi {
|
|||||||
val urlArg = args[0] as String
|
val urlArg = args[0] as String
|
||||||
val headersArg = args[1] as Map<String, String>
|
val headersArg = args[1] as Map<String, String>
|
||||||
val requestIdArg = args[2] as Long
|
val requestIdArg = args[2] as Long
|
||||||
api.requestImage(urlArg, headersArg, requestIdArg) { result: Result<Map<String, Long>> ->
|
api.requestImage(urlArg, headersArg, requestIdArg) { result: Result<Map<String, Long>?> ->
|
||||||
val error = result.exceptionOrNull()
|
val error = result.exceptionOrNull()
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
reply.reply(RemoteImagesPigeonUtils.wrapError(error))
|
reply.reply(RemoteImagesPigeonUtils.wrapError(error))
|
||||||
|
|||||||
@@ -46,14 +46,14 @@ class RemoteImagesImpl(context: Context) : RemoteImageApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val CANCELLED = Result.success<Map<String, Long>>(emptyMap())
|
val CANCELLED = Result.success<Map<String, Long>?>(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun requestImage(
|
override fun requestImage(
|
||||||
url: String,
|
url: String,
|
||||||
headers: Map<String, String>,
|
headers: Map<String, String>,
|
||||||
requestId: Long,
|
requestId: Long,
|
||||||
callback: (Result<Map<String, Long>>) -> Unit
|
callback: (Result<Map<String, Long>?>) -> Unit
|
||||||
) {
|
) {
|
||||||
val signal = CancellationSignal()
|
val signal = CancellationSignal()
|
||||||
requestMap[requestId] = RemoteRequest(signal)
|
requestMap[requestId] = RemoteRequest(signal)
|
||||||
@@ -167,7 +167,7 @@ private class CronetImageFetcher(context: Context, cacheDir: File) : ImageFetche
|
|||||||
.enableBrotli(true)
|
.enableBrotli(true)
|
||||||
.setStoragePath(storageDir.absolutePath)
|
.setStoragePath(storageDir.absolutePath)
|
||||||
.setUserAgent(USER_AGENT)
|
.setUserAgent(USER_AGENT)
|
||||||
.enableHttpCache(CronetEngine.Builder.HTTP_CACHE_DISK, CACHE_SIZE_BYTES)
|
// .enableHttpCache(CronetEngine.Builder.HTTP_CACHE_DISK, CACHE_SIZE_BYTES)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@ private class CronetImageFetcher(context: Context, cacheDir: File) : ImageFetche
|
|||||||
val requestBuilder = engine.newUrlRequestBuilder(url, callback, executor)
|
val requestBuilder = engine.newUrlRequestBuilder(url, callback, executor)
|
||||||
headers.forEach { (key, value) -> requestBuilder.addHeader(key, value) }
|
headers.forEach { (key, value) -> requestBuilder.addHeader(key, value) }
|
||||||
val request = requestBuilder.build()
|
val request = requestBuilder.build()
|
||||||
signal.setOnCancelListener { request.cancel() }
|
signal.setOnCancelListener(request::cancel)
|
||||||
request.start()
|
request.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,6 +222,7 @@ private class CronetImageFetcher(context: Context, cacheDir: File) : ImageFetche
|
|||||||
private val onFailure: (Exception) -> Unit,
|
private val onFailure: (Exception) -> Unit,
|
||||||
private val onComplete: () -> Unit,
|
private val onComplete: () -> Unit,
|
||||||
) : UrlRequest.Callback() {
|
) : UrlRequest.Callback() {
|
||||||
|
private var contentLength: Int = 0
|
||||||
private var buffer: NativeByteBuffer? = null
|
private var buffer: NativeByteBuffer? = null
|
||||||
private var httpError: IOException? = null
|
private var httpError: IOException? = null
|
||||||
|
|
||||||
@@ -235,9 +236,9 @@ private class CronetImageFetcher(context: Context, cacheDir: File) : ImageFetche
|
|||||||
return request.cancel()
|
return request.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pre-size from Content-Length when available, otherwise use reasonable default
|
contentLength = info.allHeaders["content-length"]?.firstOrNull()?.toIntOrNull() ?: 0
|
||||||
val capacity = info.allHeaders["content-length"]?.firstOrNull()?.toIntOrNull()
|
// Cronet wants the buffer to always have free space, so increment by 1
|
||||||
?.takeIf { it > 0 } ?: INITIAL_BUFFER_SIZE
|
val capacity = if (contentLength > 0) contentLength + 1 else INITIAL_BUFFER_SIZE
|
||||||
buffer = NativeByteBuffer(capacity)
|
buffer = NativeByteBuffer(capacity)
|
||||||
request.read(buffer!!.wrapRemaining())
|
request.read(buffer!!.wrapRemaining())
|
||||||
}
|
}
|
||||||
@@ -248,7 +249,7 @@ private class CronetImageFetcher(context: Context, cacheDir: File) : ImageFetche
|
|||||||
byteBuffer: ByteBuffer
|
byteBuffer: ByteBuffer
|
||||||
) {
|
) {
|
||||||
buffer!!.apply {
|
buffer!!.apply {
|
||||||
advance(byteBuffer.remaining())
|
advance(byteBuffer.position())
|
||||||
ensureHeadroom()
|
ensureHeadroom()
|
||||||
}
|
}
|
||||||
request.read(buffer!!.wrapRemaining())
|
request.read(buffer!!.wrapRemaining())
|
||||||
@@ -303,7 +304,7 @@ private class OkHttpImageFetcher private constructor(
|
|||||||
}
|
}
|
||||||
.dispatcher(Dispatcher().apply { maxRequestsPerHost = MAX_REQUESTS_PER_HOST })
|
.dispatcher(Dispatcher().apply { maxRequestsPerHost = MAX_REQUESTS_PER_HOST })
|
||||||
.connectionPool(connectionPool)
|
.connectionPool(connectionPool)
|
||||||
.cache(Cache(File(dir, "thumbnails"), CACHE_SIZE_BYTES))
|
// .cache(Cache(File(dir, "thumbnails"), CACHE_SIZE_BYTES))
|
||||||
|
|
||||||
if (sslSocketFactory != null && trustManager != null) {
|
if (sslSocketFactory != null && trustManager != null) {
|
||||||
builder.sslSocketFactory(sslSocketFactory, trustManager)
|
builder.sslSocketFactory(sslSocketFactory, trustManager)
|
||||||
@@ -345,8 +346,7 @@ private class OkHttpImageFetcher private constructor(
|
|||||||
) {
|
) {
|
||||||
synchronized(stateLock) {
|
synchronized(stateLock) {
|
||||||
if (draining) {
|
if (draining) {
|
||||||
onFailure(IllegalStateException("Client is draining"))
|
return onFailure(IllegalStateException("Client is draining"))
|
||||||
return
|
|
||||||
}
|
}
|
||||||
activeCount++
|
activeCount++
|
||||||
}
|
}
|
||||||
@@ -354,7 +354,7 @@ private class OkHttpImageFetcher private constructor(
|
|||||||
val requestBuilder = Request.Builder().url(url)
|
val requestBuilder = Request.Builder().url(url)
|
||||||
headers.forEach { (key, value) -> requestBuilder.addHeader(key, value) }
|
headers.forEach { (key, value) -> requestBuilder.addHeader(key, value) }
|
||||||
val call = client.newCall(requestBuilder.build())
|
val call = client.newCall(requestBuilder.build())
|
||||||
signal.setOnCancelListener { call.cancel() }
|
signal.setOnCancelListener(call::cancel)
|
||||||
|
|
||||||
call.enqueue(object : Callback {
|
call.enqueue(object : Callback {
|
||||||
override fun onFailure(call: Call, e: IOException) {
|
override fun onFailure(call: Call, e: IOException) {
|
||||||
@@ -363,45 +363,38 @@ private class OkHttpImageFetcher private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onResponse(call: Call, response: Response) {
|
override fun onResponse(call: Call, response: Response) {
|
||||||
try {
|
response.use {
|
||||||
response.use {
|
if (!response.isSuccessful) {
|
||||||
if (call.isCanceled()) {
|
return onFailure(IOException("HTTP ${response.code}: ${response.message}")).also { onComplete() }
|
||||||
return onFailure(OperationCanceledException())
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!response.isSuccessful) {
|
val body = response.body
|
||||||
return onFailure(IOException("HTTP ${response.code}: ${response.message}"))
|
?: return onFailure(IOException("Empty response body")).also { onComplete() }
|
||||||
}
|
|
||||||
|
|
||||||
val body = response.body ?: return onFailure(IOException("Empty response body"))
|
if (call.isCanceled()) {
|
||||||
|
onFailure(OperationCanceledException())
|
||||||
val contentLength = body.contentLength()
|
return onComplete()
|
||||||
val capacity = if (contentLength > 0 && contentLength <= Int.MAX_VALUE) {
|
}
|
||||||
contentLength.toInt()
|
|
||||||
} else {
|
|
||||||
INITIAL_BUFFER_SIZE
|
|
||||||
}
|
|
||||||
val buffer = NativeByteBuffer(capacity)
|
|
||||||
|
|
||||||
|
val contentLength = body.contentLength().toInt()
|
||||||
|
val capacity = if (contentLength > 0) contentLength + 1 else INITIAL_BUFFER_SIZE
|
||||||
|
val buffer = NativeByteBuffer(capacity)
|
||||||
|
body.source().use { source ->
|
||||||
try {
|
try {
|
||||||
body.source().use { source ->
|
while (true) {
|
||||||
while (true) {
|
if (call.isCanceled()) throw OperationCanceledException()
|
||||||
signal.throwIfCanceled()
|
val bytesRead = source.read(buffer.wrapRemaining())
|
||||||
buffer.ensureHeadroom()
|
if (bytesRead == -1) break
|
||||||
val bytesRead = source.read(buffer.wrapRemaining())
|
buffer.ensureHeadroom()
|
||||||
if (bytesRead == -1) break
|
buffer.advance(bytesRead)
|
||||||
buffer.advance(bytesRead)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onSuccess(buffer)
|
onSuccess(buffer)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
buffer.free()
|
buffer.free()
|
||||||
onFailure(e)
|
onFailure(e)
|
||||||
}
|
}
|
||||||
|
onComplete()
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
onComplete()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class LocalImagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
|
|||||||
|
|
||||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||||
protocol LocalImageApi {
|
protocol LocalImageApi {
|
||||||
func requestImage(assetId: String, requestId: Int64, width: Int64, height: Int64, isVideo: Bool, completion: @escaping (Result<[String: Int64], Error>) -> Void)
|
func requestImage(assetId: String, requestId: Int64, width: Int64, height: Int64, isVideo: Bool, completion: @escaping (Result<[String: Int64]?, Error>) -> Void)
|
||||||
func cancelRequest(requestId: Int64) throws
|
func cancelRequest(requestId: Int64) throws
|
||||||
func getThumbhash(thumbhash: String, completion: @escaping (Result<[String: Int64], Error>) -> Void)
|
func getThumbhash(thumbhash: String, completion: @escaping (Result<[String: Int64], Error>) -> Void)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class LocalImageApiImpl: LocalImageApi {
|
|||||||
renderingIntent: .defaultIntent
|
renderingIntent: .defaultIntent
|
||||||
)!
|
)!
|
||||||
private static var requests = [Int64: LocalImageRequest]()
|
private static var requests = [Int64: LocalImageRequest]()
|
||||||
private static let cancelledResult = Result<[String: Int64], any Error>.success([:])
|
private static let cancelledResult = Result<[String: Int64]?, any Error>.success(nil)
|
||||||
private static let concurrencySemaphore = DispatchSemaphore(value: ProcessInfo.processInfo.activeProcessorCount * 2)
|
private static let concurrencySemaphore = DispatchSemaphore(value: ProcessInfo.processInfo.activeProcessorCount * 2)
|
||||||
private static let assetCache = {
|
private static let assetCache = {
|
||||||
let assetCache = NSCache<NSString, PHAsset>()
|
let assetCache = NSCache<NSString, PHAsset>()
|
||||||
@@ -62,7 +62,7 @@ class LocalImageApiImpl: LocalImageApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func requestImage(assetId: String, requestId: Int64, width: Int64, height: Int64, isVideo: Bool, completion: @escaping (Result<[String: Int64], any Error>) -> Void) {
|
func requestImage(assetId: String, requestId: Int64, width: Int64, height: Int64, isVideo: Bool, completion: @escaping (Result<[String: Int64]?, any Error>) -> Void) {
|
||||||
let request = LocalImageRequest(callback: completion)
|
let request = LocalImageRequest(callback: completion)
|
||||||
let item = DispatchWorkItem {
|
let item = DispatchWorkItem {
|
||||||
if request.isCancelled {
|
if request.isCancelled {
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class RemoteImagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable
|
|||||||
|
|
||||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||||
protocol RemoteImageApi {
|
protocol RemoteImageApi {
|
||||||
func requestImage(url: String, headers: [String: String], requestId: Int64, completion: @escaping (Result<[String: Int64], Error>) -> Void)
|
func requestImage(url: String, headers: [String: String], requestId: Int64, completion: @escaping (Result<[String: Int64]?, Error>) -> Void)
|
||||||
func cancelRequest(requestId: Int64) throws
|
func cancelRequest(requestId: Int64) throws
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,13 +16,16 @@ class LocalImageRequest extends ImageRequest {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Map<String, int> info = await localImageApi.requestImage(
|
final info = await localImageApi.requestImage(
|
||||||
localId,
|
localId,
|
||||||
requestId: requestId,
|
requestId: requestId,
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
isVideo: assetType == AssetType.video,
|
isVideo: assetType == AssetType.video,
|
||||||
);
|
);
|
||||||
|
if (info == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
final frame = await _fromDecodedPlatformImage(info["pointer"]!, info["width"]!, info["height"]!, info["rowBytes"]!);
|
final frame = await _fromDecodedPlatformImage(info["pointer"]!, info["width"]!, info["height"]!, info["rowBytes"]!);
|
||||||
return frame == null ? null : ImageInfo(image: frame.image, scale: scale);
|
return frame == null ? null : ImageInfo(image: frame.image, scale: scale);
|
||||||
|
|||||||
@@ -12,8 +12,13 @@ class RemoteImageRequest extends ImageRequest {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final Map<String, int> info = await remoteImageApi.requestImage(uri, headers: headers, requestId: requestId);
|
final info = await remoteImageApi.requestImage(uri, headers: headers, requestId: requestId);
|
||||||
final frame = await _fromEncodedPlatformImage(info["pointer"]!, info["length"]!);
|
final frame = switch (info) {
|
||||||
|
{'pointer': int pointer, 'length': int length} => await _fromEncodedPlatformImage(pointer, length),
|
||||||
|
{'pointer': int pointer, 'width': int width, 'height': int height, 'rowBytes': int rowBytes} =>
|
||||||
|
await _fromDecodedPlatformImage(pointer, width, height, rowBytes),
|
||||||
|
_ => null,
|
||||||
|
};
|
||||||
return frame == null ? null : ImageInfo(image: frame.image, scale: scale);
|
return frame == null ? null : ImageInfo(image: frame.image, scale: scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-7
@@ -49,7 +49,7 @@ class LocalImageApi {
|
|||||||
|
|
||||||
final String pigeonVar_messageChannelSuffix;
|
final String pigeonVar_messageChannelSuffix;
|
||||||
|
|
||||||
Future<Map<String, int>> requestImage(
|
Future<Map<String, int>?> requestImage(
|
||||||
String assetId, {
|
String assetId, {
|
||||||
required int requestId,
|
required int requestId,
|
||||||
required int width,
|
required int width,
|
||||||
@@ -79,13 +79,8 @@ class LocalImageApi {
|
|||||||
message: pigeonVar_replyList[1] as String?,
|
message: pigeonVar_replyList[1] as String?,
|
||||||
details: pigeonVar_replyList[2],
|
details: pigeonVar_replyList[2],
|
||||||
);
|
);
|
||||||
} else if (pigeonVar_replyList[0] == null) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: 'null-error',
|
|
||||||
message: 'Host platform returned null value for non-null return value.',
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
return (pigeonVar_replyList[0] as Map<Object?, Object?>?)!.cast<String, int>();
|
return (pigeonVar_replyList[0] as Map<Object?, Object?>?)?.cast<String, int>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-7
@@ -49,7 +49,7 @@ class RemoteImageApi {
|
|||||||
|
|
||||||
final String pigeonVar_messageChannelSuffix;
|
final String pigeonVar_messageChannelSuffix;
|
||||||
|
|
||||||
Future<Map<String, int>> requestImage(
|
Future<Map<String, int>?> requestImage(
|
||||||
String url, {
|
String url, {
|
||||||
required Map<String, String> headers,
|
required Map<String, String> headers,
|
||||||
required int requestId,
|
required int requestId,
|
||||||
@@ -71,13 +71,8 @@ class RemoteImageApi {
|
|||||||
message: pigeonVar_replyList[1] as String?,
|
message: pigeonVar_replyList[1] as String?,
|
||||||
details: pigeonVar_replyList[2],
|
details: pigeonVar_replyList[2],
|
||||||
);
|
);
|
||||||
} else if (pigeonVar_replyList[0] == null) {
|
|
||||||
throw PlatformException(
|
|
||||||
code: 'null-error',
|
|
||||||
message: 'Host platform returned null value for non-null return value.',
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
return (pigeonVar_replyList[0] as Map<Object?, Object?>?)!.cast<String, int>();
|
return (pigeonVar_replyList[0] as Map<Object?, Object?>?)?.cast<String, int>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import 'package:pigeon/pigeon.dart';
|
|||||||
@HostApi()
|
@HostApi()
|
||||||
abstract class LocalImageApi {
|
abstract class LocalImageApi {
|
||||||
@async
|
@async
|
||||||
Map<String, int> requestImage(
|
Map<String, int>? requestImage(
|
||||||
String assetId, {
|
String assetId, {
|
||||||
required int requestId,
|
required int requestId,
|
||||||
required int width,
|
required int width,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import 'package:pigeon/pigeon.dart';
|
|||||||
@HostApi()
|
@HostApi()
|
||||||
abstract class RemoteImageApi {
|
abstract class RemoteImageApi {
|
||||||
@async
|
@async
|
||||||
Map<String, int> requestImage(
|
Map<String, int>? requestImage(
|
||||||
String url, {
|
String url, {
|
||||||
required Map<String, String> headers,
|
required Map<String, String> headers,
|
||||||
required int requestId,
|
required int requestId,
|
||||||
|
|||||||
Reference in New Issue
Block a user