Various tweaks (#381)

* Add the message delivery status to the plain timeline styler and display it outside of the main content

* Fix glitchy timeline scroll to bottom button

* Fixed bubbled reactions padding

* Simplified the emoji picker, double tapping a timeline item directly opens it now and added a context menu option. Linked it to rust side reaction sending

* Fix the sliding sync cold cache: treat invalidated rooms as filled

* Make splash screen view full screen

* Fix the offline indicator popping up when first setting up the network monitor

* Expose presentationDetents on the NavigationStackCoordinator and start using them for the EmojiPicker

* Fix link tint color

* Linked TimelineReactionsView reaction sending

* Remove now unused/unnecessary classes

* Add changelog

* Fix formatting issue
This commit is contained in:
Stefan Ceriu
2022-12-21 11:18:45 +02:00
committed by GitHub
parent 5b9d45e461
commit 71f1f044c7
33 changed files with 170 additions and 534 deletions
-70
View File
@@ -1,70 +0,0 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
struct Benchmark {
private static var trackingIdentifiers = [String: CFAbsoluteTime]()
public static var trackingEnabled = false
static func startTrackingForIdentifier(_ identifier: String, message: String? = nil) {
guard trackingEnabled else {
return
}
let startTime = CFAbsoluteTimeGetCurrent()
trackingIdentifiers[identifier] = startTime
if let message {
MXLog.verbose("⏰ \(message).")
}
}
static func logElapsedDurationForIdentifier(_ identifier: String, message: String? = nil) {
guard trackingEnabled else {
return
}
guard let start = trackingIdentifiers[identifier] else {
assertionFailure("⏰ Invalid tracking identifier")
return
}
let elapsedTime = CFAbsoluteTimeGetCurrent() - start
if let message {
MXLog.verbose("⏰ \(message). Elapsed time: \(elapsedTime.round(to: 4)) seconds.")
} else {
MXLog.verbose("⏰ Elapsed time: \(elapsedTime.round(to: 4)) seconds.")
}
}
static func endTrackingForIdentifier(_ identifier: String, message: String? = nil) {
guard trackingEnabled else {
return
}
logElapsedDurationForIdentifier(identifier, message: message)
trackingIdentifiers[identifier] = nil
}
}
private extension Double {
func round(to places: Int) -> Double {
let divisor = pow(10.0, Double(places))
return (self * divisor).rounded() / divisor
}
}
@@ -1,123 +0,0 @@
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
import UIKit
import Vision
enum ImageAnonymizerError: Error {
case noCgImageBased
}
enum ImageAnonymizer {
private static var allowedTextItems: [String] = [
"#",
"@",
"%",
"&",
"+",
"-",
"_",
"\"",
"?",
"*"
]
static func anonymizedImage(from image: UIImage,
confidenceLevel: Float = 0.5,
fillColor: UIColor = .red) async throws -> UIImage {
guard let cgImage = image.cgImage else {
throw ImageAnonymizerError.noCgImageBased
}
// create a handler with cgImage
let handler = VNImageRequestHandler(cgImage: cgImage, options: [:])
var observations: [VNDetectedObjectObservation] = []
// create a text request
let textRequest = VNRecognizeTextRequest { request, error in
guard let results = request.results as? [VNRecognizedTextObservation],
error == nil else {
return
}
observations.append(contentsOf: results)
}
textRequest.recognitionLevel = .accurate
textRequest.revision = VNRecognizeTextRequestRevision2
// create a face request
let faceRequest = VNDetectFaceRectanglesRequest { request, error in
guard let results = request.results as? [VNFaceObservation],
error == nil else {
return
}
observations.append(contentsOf: results)
}
// revision3 doesn't work!
faceRequest.revision = VNDetectFaceRectanglesRequestRevision2
#if targetEnvironment(simulator)
// Avoid `Could not create inference context` errors on Apple Silicon
// https://www.caseyliss.com/2022/6/20/feedback-is-broken-stop-trying-to-make-radar-happen
faceRequest.usesCPUOnly = true
#endif
// perform requests
try handler.perform([
textRequest,
faceRequest
])
return render(image: image,
confidenceLevel: confidenceLevel,
fillColor: fillColor,
observations: observations)
}
private static func render(image: UIImage,
confidenceLevel: Float,
fillColor: UIColor,
observations: [VNDetectedObjectObservation]) -> UIImage {
let size = image.size
let result = UIGraphicsImageRenderer(size: size).image { rendererContext in
// first draw self
image.draw(in: CGRect(origin: .zero, size: size))
// set fill color
fillColor.setFill()
for observation in observations {
guard observation.confidence >= confidenceLevel else {
// ensure observation's confidence level
continue
}
if let textObservation = observation as? VNRecognizedTextObservation,
let text = textObservation.topCandidates(1).first?.string {
if Double(text) != nil || Self.allowedTextItems.contains(text) {
continue
}
}
let box = observation.boundingBox
// boc is normalized (and in starts from the lower left corner)
// convert it to a rect in the image
let rect = CGRect(x: box.minX * size.width,
y: size.height - box.maxY * size.height,
width: box.width * size.width,
height: box.height * size.height)
rendererContext.fill(rect)
}
}
return result
}
}
+1 -1
View File
@@ -34,7 +34,7 @@ class NetworkMonitor {
init() {
queue = DispatchQueue(label: "io.element.elementx.networkmonitor")
pathMonitor = NWPathMonitor()
reachabilityPublisher = CurrentValueSubject<Bool, Never>(pathMonitor.currentPath.status == .satisfied)
reachabilityPublisher = CurrentValueSubject<Bool, Never>(true)
pathMonitor.pathUpdateHandler = { [weak self] path in
DispatchQueue.main.async {