mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-05 11:58:32 +00:00
Move synchronous image upload preparation off the main actor (#6323)
* Move synchronous image upload preparation off the main actor Signed-off-by: Ivan Magda <imagda15@gmail.com> * Make media preparation cooperative with cancellation Replace the dispatch queue with concurrent copy, image and video-thumbnail functions. Return sendable upload metadata directly, bound each batch to two preparations and discard unfinished results when cancellation occurs. Keep file metadata reads synchronous and prevent the preview from sending a result after its preparation task has been cancelled. Replace unrelated tests with cancellation and batch-order coverage requested during review. * Update MediaUploadingPreprocessor.swift * Run media preparation in a nonisolated preprocessor Make MediaUploadingPreprocessor a nonisolated struct whose copy, image processing and video thumbnail run in @concurrent instance methods, instead of a main-actor type with static helpers and an extra setting parameter. Check cancellation with plain early returns between the slow steps, name the batch limit, stop logging cancelled video exports as errors, and restore develop's structure and doc comments where they were changed without need. Replace the tests that didn't reach the new code with tests for cleanup on failure, on batch failure and on cancellation, and make the preview test set up its blocking mock before the view model starts processing. * Apply review suggestions to media preparation Docs: - Drop the doc comment on maximumConcurrentProcessingCount, the name says it. - Move the cleanup note into the main description of both processMedia functions, so the Returns lines match develop again. Tests: - Rename the test helper to copyResourceToTemporaryDirectory(_:). --------- Signed-off-by: Ivan Magda <imagda15@gmail.com> Co-authored-by: Ivan Magda <imagda15@gmail.com>
This commit is contained in:
@@ -22,9 +22,9 @@
|
||||
|
||||
// swiftlint:disable all
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
|
||||
extension UIImage {
|
||||
nonisolated extension UIImage {
|
||||
public func blurHash(numberOfComponents components: (Int, Int)) -> String? {
|
||||
let pixelWidth = Int(round(size.width * scale))
|
||||
let pixelHeight = Int(round(size.height * scale))
|
||||
@@ -116,14 +116,14 @@ extension UIImage {
|
||||
}
|
||||
}
|
||||
|
||||
private func encodeDC(_ value: (Float, Float, Float)) -> Int {
|
||||
private nonisolated func encodeDC(_ value: (Float, Float, Float)) -> Int {
|
||||
let roundedR = linearTosRGB(value.0)
|
||||
let roundedG = linearTosRGB(value.1)
|
||||
let roundedB = linearTosRGB(value.2)
|
||||
return (roundedR << 16) + (roundedG << 8) + roundedB
|
||||
}
|
||||
|
||||
private func encodeAC(_ value: (Float, Float, Float), maximumValue: Float) -> Int {
|
||||
private nonisolated func encodeAC(_ value: (Float, Float, Float), maximumValue: Float) -> Int {
|
||||
let quantR = Int(max(0, min(18, floor(signPow(value.0 / maximumValue, 0.5) * 9 + 9.5))))
|
||||
let quantG = Int(max(0, min(18, floor(signPow(value.1 / maximumValue, 0.5) * 9 + 9.5))))
|
||||
let quantB = Int(max(0, min(18, floor(signPow(value.2 / maximumValue, 0.5) * 9 + 9.5))))
|
||||
@@ -131,11 +131,11 @@ private func encodeAC(_ value: (Float, Float, Float), maximumValue: Float) -> In
|
||||
return quantR * 19 * 19 + quantG * 19 + quantB
|
||||
}
|
||||
|
||||
private func signPow(_ value: Float, _ exp: Float) -> Float {
|
||||
private nonisolated func signPow(_ value: Float, _ exp: Float) -> Float {
|
||||
copysign(pow(abs(value), exp), value)
|
||||
}
|
||||
|
||||
private func linearTosRGB(_ value: Float) -> Int {
|
||||
private nonisolated func linearTosRGB(_ value: Float) -> Int {
|
||||
let v = max(0, min(1, value))
|
||||
if v <= 0.0031308 {
|
||||
return Int(v * 12.92 * 255 + 0.5)
|
||||
@@ -144,7 +144,7 @@ private func linearTosRGB(_ value: Float) -> Int {
|
||||
}
|
||||
}
|
||||
|
||||
private func sRGBToLinear<Type: BinaryInteger>(_ value: Type) -> Float {
|
||||
private nonisolated func sRGBToLinear<Type: BinaryInteger>(_ value: Type) -> Float {
|
||||
let v = Float(Int64(value)) / 255
|
||||
if v <= 0.04045 {
|
||||
return v / 12.92
|
||||
@@ -153,9 +153,9 @@ private func sRGBToLinear<Type: BinaryInteger>(_ value: Type) -> Float {
|
||||
}
|
||||
}
|
||||
|
||||
private let encodeCharacters: [String] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~".map { String($0) }
|
||||
private nonisolated let encodeCharacters: [String] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~".map { String($0) }
|
||||
|
||||
extension BinaryInteger {
|
||||
nonisolated extension BinaryInteger {
|
||||
func encode83(length: Int) -> String {
|
||||
var result = ""
|
||||
for i in 1...length {
|
||||
@@ -166,7 +166,7 @@ extension BinaryInteger {
|
||||
}
|
||||
}
|
||||
|
||||
private func pow(_ base: Int, _ exponent: Int) -> Int {
|
||||
private nonisolated func pow(_ base: Int, _ exponent: Int) -> Int {
|
||||
(0..<exponent).reduce(1) { value, _ in value * base }
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user