mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 01:20:12 +00:00
Notifications (#275)
This commit is contained in:
@@ -18,26 +18,26 @@ import Kingfisher
|
||||
import UIKit
|
||||
|
||||
struct MediaProvider: MediaProviderProtocol {
|
||||
private let clientProxy: ClientProxyProtocol
|
||||
private let mediaProxy: MediaProxyProtocol
|
||||
private let imageCache: Kingfisher.ImageCache
|
||||
private let fileCache: FileCache
|
||||
private let backgroundTaskService: BackgroundTaskServiceProtocol
|
||||
private let backgroundTaskService: BackgroundTaskServiceProtocol?
|
||||
|
||||
init(clientProxy: ClientProxyProtocol,
|
||||
init(mediaProxy: MediaProxyProtocol,
|
||||
imageCache: Kingfisher.ImageCache,
|
||||
fileCache: FileCache,
|
||||
backgroundTaskService: BackgroundTaskServiceProtocol) {
|
||||
self.clientProxy = clientProxy
|
||||
backgroundTaskService: BackgroundTaskServiceProtocol?) {
|
||||
self.mediaProxy = mediaProxy
|
||||
self.imageCache = imageCache
|
||||
self.fileCache = fileCache
|
||||
self.backgroundTaskService = backgroundTaskService
|
||||
}
|
||||
|
||||
func imageFromSource(_ source: MediaSource?, avatarSize: AvatarSize?) -> UIImage? {
|
||||
func imageFromSource(_ source: MediaSourceProxy?, avatarSize: AvatarSize?) -> UIImage? {
|
||||
guard let source else {
|
||||
return nil
|
||||
}
|
||||
let cacheKey = cacheKeyForURLString(source.underlyingSource.url(), avatarSize: avatarSize)
|
||||
let cacheKey = cacheKeyForURLString(source.url, avatarSize: avatarSize)
|
||||
return imageCache.retrieveImageInMemoryCache(forKey: cacheKey, options: nil)
|
||||
}
|
||||
|
||||
@@ -46,19 +46,19 @@ struct MediaProvider: MediaProviderProtocol {
|
||||
return nil
|
||||
}
|
||||
|
||||
return imageFromSource(MediaSource(source: clientProxy.mediaSourceForURLString(urlString)), avatarSize: avatarSize)
|
||||
return imageFromSource(.init(urlString: urlString), avatarSize: avatarSize)
|
||||
}
|
||||
|
||||
func loadImageFromURLString(_ urlString: String, avatarSize: AvatarSize?) async -> Result<UIImage, MediaProviderError> {
|
||||
await loadImageFromSource(MediaSource(source: clientProxy.mediaSourceForURLString(urlString)), avatarSize: avatarSize)
|
||||
await loadImageFromSource(.init(urlString: urlString), avatarSize: avatarSize)
|
||||
}
|
||||
|
||||
func loadImageFromSource(_ source: MediaSource, avatarSize: AvatarSize?) async -> Result<UIImage, MediaProviderError> {
|
||||
func loadImageFromSource(_ source: MediaSourceProxy, avatarSize: AvatarSize?) async -> Result<UIImage, MediaProviderError> {
|
||||
if let image = imageFromSource(source, avatarSize: avatarSize) {
|
||||
return .success(image)
|
||||
}
|
||||
|
||||
let loadImageBgTask = await backgroundTaskService.startBackgroundTask(withName: "LoadImage: \(source.url.hashValue)")
|
||||
let loadImageBgTask = await backgroundTaskService?.startBackgroundTask(withName: "LoadImage: \(source.url.hashValue)")
|
||||
defer {
|
||||
loadImageBgTask?.stop()
|
||||
}
|
||||
@@ -73,9 +73,9 @@ struct MediaProvider: MediaProviderProtocol {
|
||||
do {
|
||||
let imageData: Data
|
||||
if let avatarSize {
|
||||
imageData = try await clientProxy.loadMediaThumbnailForSource(source.underlyingSource, width: UInt(avatarSize.scaledValue), height: UInt(avatarSize.scaledValue))
|
||||
imageData = try await mediaProxy.loadMediaThumbnailForSource(source, width: UInt(avatarSize.scaledValue), height: UInt(avatarSize.scaledValue))
|
||||
} else {
|
||||
imageData = try await clientProxy.loadMediaContentForSource(source.underlyingSource)
|
||||
imageData = try await mediaProxy.loadMediaContentForSource(source)
|
||||
}
|
||||
|
||||
guard let image = UIImage(data: imageData) else {
|
||||
@@ -92,20 +92,20 @@ struct MediaProvider: MediaProviderProtocol {
|
||||
}
|
||||
}
|
||||
|
||||
func fileFromSource(_ source: MediaSource?, fileExtension: String) -> URL? {
|
||||
func fileFromSource(_ source: MediaSourceProxy?, fileExtension: String) -> URL? {
|
||||
guard let source else {
|
||||
return nil
|
||||
}
|
||||
let cacheKey = fileCacheKeyForURLString(source.underlyingSource.url())
|
||||
let cacheKey = fileCacheKeyForURLString(source.url)
|
||||
return fileCache.file(forKey: cacheKey, fileExtension: fileExtension)
|
||||
}
|
||||
|
||||
@discardableResult func loadFileFromSource(_ source: MediaSource, fileExtension: String) async -> Result<URL, MediaProviderError> {
|
||||
@discardableResult func loadFileFromSource(_ source: MediaSourceProxy, fileExtension: String) async -> Result<URL, MediaProviderError> {
|
||||
if let url = fileFromSource(source, fileExtension: fileExtension) {
|
||||
return .success(url)
|
||||
}
|
||||
|
||||
let loadFileBgTask = await backgroundTaskService.startBackgroundTask(withName: "LoadFile: \(source.url.hashValue)")
|
||||
let loadFileBgTask = await backgroundTaskService?.startBackgroundTask(withName: "LoadFile: \(source.url.hashValue)")
|
||||
defer {
|
||||
loadFileBgTask?.stop()
|
||||
}
|
||||
@@ -113,7 +113,7 @@ struct MediaProvider: MediaProviderProtocol {
|
||||
let cacheKey = fileCacheKeyForURLString(source.url)
|
||||
|
||||
do {
|
||||
let data = try await clientProxy.loadMediaContentForSource(source.underlyingSource)
|
||||
let data = try await mediaProxy.loadMediaContentForSource(source)
|
||||
|
||||
let url = try fileCache.store(data, with: fileExtension, forKey: cacheKey)
|
||||
return .success(url)
|
||||
@@ -128,12 +128,12 @@ struct MediaProvider: MediaProviderProtocol {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fileFromSource(MediaSource(source: clientProxy.mediaSourceForURLString(urlString)),
|
||||
return fileFromSource(MediaSourceProxy(urlString: urlString),
|
||||
fileExtension: fileExtension)
|
||||
}
|
||||
|
||||
func loadFileFromURLString(_ urlString: String, fileExtension: String) async -> Result<URL, MediaProviderError> {
|
||||
await loadFileFromSource(MediaSource(source: clientProxy.mediaSourceForURLString(urlString)),
|
||||
await loadFileFromSource(MediaSourceProxy(urlString: urlString),
|
||||
fileExtension: fileExtension)
|
||||
}
|
||||
|
||||
|
||||
@@ -24,17 +24,17 @@ enum MediaProviderError: Error {
|
||||
}
|
||||
|
||||
protocol MediaProviderProtocol {
|
||||
func imageFromSource(_ source: MediaSource?, avatarSize: AvatarSize?) -> UIImage?
|
||||
func imageFromSource(_ source: MediaSourceProxy?, avatarSize: AvatarSize?) -> UIImage?
|
||||
|
||||
@discardableResult func loadImageFromSource(_ source: MediaSource, avatarSize: AvatarSize?) async -> Result<UIImage, MediaProviderError>
|
||||
@discardableResult func loadImageFromSource(_ source: MediaSourceProxy, avatarSize: AvatarSize?) async -> Result<UIImage, MediaProviderError>
|
||||
|
||||
func imageFromURLString(_ urlString: String?, avatarSize: AvatarSize?) -> UIImage?
|
||||
|
||||
@discardableResult func loadImageFromURLString(_ urlString: String, avatarSize: AvatarSize?) async -> Result<UIImage, MediaProviderError>
|
||||
|
||||
func fileFromSource(_ source: MediaSource?, fileExtension: String) -> URL?
|
||||
func fileFromSource(_ source: MediaSourceProxy?, fileExtension: String) -> URL?
|
||||
|
||||
@discardableResult func loadFileFromSource(_ source: MediaSource, fileExtension: String) async -> Result<URL, MediaProviderError>
|
||||
@discardableResult func loadFileFromSource(_ source: MediaSourceProxy, fileExtension: String) async -> Result<URL, MediaProviderError>
|
||||
|
||||
func fileFromURLString(_ urlString: String?, fileExtension: String) -> URL?
|
||||
|
||||
@@ -42,11 +42,11 @@ protocol MediaProviderProtocol {
|
||||
}
|
||||
|
||||
extension MediaProviderProtocol {
|
||||
func imageFromSource(_ source: MediaSource?) -> UIImage? {
|
||||
func imageFromSource(_ source: MediaSourceProxy?) -> UIImage? {
|
||||
imageFromSource(source, avatarSize: nil)
|
||||
}
|
||||
|
||||
@discardableResult func loadImageFromSource(_ source: MediaSource) async -> Result<UIImage, MediaProviderError> {
|
||||
@discardableResult func loadImageFromSource(_ source: MediaSourceProxy) async -> Result<UIImage, MediaProviderError> {
|
||||
await loadImageFromSource(source, avatarSize: nil)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// 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 Combine
|
||||
import Foundation
|
||||
import MatrixRustSDK
|
||||
import UIKit
|
||||
|
||||
class MediaProxy: MediaProxyProtocol {
|
||||
private let client: ClientProtocol
|
||||
private let clientQueue: DispatchQueue
|
||||
|
||||
init(client: ClientProtocol,
|
||||
clientQueue: DispatchQueue = .global()) {
|
||||
self.client = client
|
||||
self.clientQueue = clientQueue
|
||||
}
|
||||
|
||||
func mediaSourceForURLString(_ urlString: String) -> MediaSourceProxy {
|
||||
.init(urlString: urlString)
|
||||
}
|
||||
|
||||
func loadMediaContentForSource(_ source: MediaSourceProxy) async throws -> Data {
|
||||
try await Task.dispatch(on: clientQueue) {
|
||||
let bytes = try self.client.getMediaContent(source: source.underlyingSource)
|
||||
return Data(bytes: bytes, count: bytes.count)
|
||||
}
|
||||
}
|
||||
|
||||
func loadMediaThumbnailForSource(_ source: MediaSourceProxy, width: UInt, height: UInt) async throws -> Data {
|
||||
try await Task.dispatch(on: clientQueue) {
|
||||
let bytes = try self.client.getMediaThumbnail(source: source.underlyingSource, width: UInt64(width), height: UInt64(height))
|
||||
return Data(bytes: bytes, count: bytes.count)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// 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
|
||||
|
||||
protocol MediaProxyProtocol {
|
||||
func mediaSourceForURLString(_ urlString: String) -> MediaSourceProxy
|
||||
|
||||
func loadMediaContentForSource(_ source: MediaSourceProxy) async throws -> Data
|
||||
|
||||
func loadMediaThumbnailForSource(_ source: MediaSourceProxy, width: UInt, height: UInt) async throws -> Data
|
||||
}
|
||||
+12
-12
@@ -17,24 +17,24 @@
|
||||
import Foundation
|
||||
import MatrixRustSDK
|
||||
|
||||
struct MediaSource: Equatable {
|
||||
let underlyingSource: MatrixRustSDK.MediaSource
|
||||
struct MediaSourceProxy: Equatable {
|
||||
let underlyingSource: MediaSource
|
||||
|
||||
init(source: MediaSource) {
|
||||
underlyingSource = source
|
||||
}
|
||||
|
||||
init(urlString: String) {
|
||||
underlyingSource = mediaSourceFromUrl(url: urlString)
|
||||
}
|
||||
|
||||
var url: String {
|
||||
underlyingSource.url()
|
||||
}
|
||||
|
||||
init(source: MatrixRustSDK.MediaSource) {
|
||||
underlyingSource = source
|
||||
}
|
||||
|
||||
init(urlString: String) {
|
||||
underlyingSource = MatrixRustSDK.mediaSourceFromUrl(url: urlString)
|
||||
}
|
||||
|
||||
// MARK: - Equatable
|
||||
|
||||
static func == (lhs: MediaSource, rhs: MediaSource) -> Bool {
|
||||
lhs.underlyingSource.url() == rhs.underlyingSource.url()
|
||||
static func == (lhs: MediaSourceProxy, rhs: MediaSourceProxy) -> Bool {
|
||||
lhs.url == rhs.url
|
||||
}
|
||||
}
|
||||
@@ -18,11 +18,11 @@ import Foundation
|
||||
import UIKit
|
||||
|
||||
struct MockMediaProvider: MediaProviderProtocol {
|
||||
func imageFromSource(_ source: MediaSource?, avatarSize: AvatarSize?) -> UIImage? {
|
||||
func imageFromSource(_ source: MediaSourceProxy?, avatarSize: AvatarSize?) -> UIImage? {
|
||||
nil
|
||||
}
|
||||
|
||||
func loadImageFromSource(_ source: MediaSource, avatarSize: AvatarSize?) async -> Result<UIImage, MediaProviderError> {
|
||||
func loadImageFromSource(_ source: MediaSourceProxy, avatarSize: AvatarSize?) async -> Result<UIImage, MediaProviderError> {
|
||||
.failure(.failedRetrievingImage)
|
||||
}
|
||||
|
||||
@@ -50,11 +50,11 @@ struct MockMediaProvider: MediaProviderProtocol {
|
||||
return .success(image)
|
||||
}
|
||||
|
||||
func fileFromSource(_ source: MediaSource?, fileExtension: String) -> URL? {
|
||||
func fileFromSource(_ source: MediaSourceProxy?, fileExtension: String) -> URL? {
|
||||
nil
|
||||
}
|
||||
|
||||
@discardableResult func loadFileFromSource(_ source: MediaSource, fileExtension: String) async -> Result<URL, MediaProviderError> {
|
||||
@discardableResult func loadFileFromSource(_ source: MediaSourceProxy, fileExtension: String) async -> Result<URL, MediaProviderError> {
|
||||
.failure(.failedRetrievingFile)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user