diff --git a/Nextcloud.xcodeproj/project.pbxproj b/Nextcloud.xcodeproj/project.pbxproj index f7ad38bf23..f996034b5e 100644 --- a/Nextcloud.xcodeproj/project.pbxproj +++ b/Nextcloud.xcodeproj/project.pbxproj @@ -5775,7 +5775,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 6; + CURRENT_PROJECT_VERSION = 7; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = NKUJUXUJ3B; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -5841,7 +5841,7 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 6; + CURRENT_PROJECT_VERSION = 7; DEVELOPMENT_TEAM = NKUJUXUJ3B; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; diff --git a/iOSClient/Menu/NCContextMenuMain.swift b/iOSClient/Menu/NCContextMenuMain.swift index 9359a89ce8..053651b338 100644 --- a/iOSClient/Menu/NCContextMenuMain.swift +++ b/iOSClient/Menu/NCContextMenuMain.swift @@ -498,19 +498,18 @@ class NCContextMenuMain: NSObject { if shouldShowMenu { let deferredElement = UIDeferredMenuElement { completion in Task { - var iconImage = UIImage() + var iconImage = UIImage(systemName: "exclamationmark.triangle.fill") if let iconUrl = item.icon { - if let image = await NCUtility().convertSVGtoPNGWriteToUserData( - serverUrl: metadata.urlBase + iconUrl, - rewrite: false, - account: metadata.account - ).image { - let image = image.rasterResized(to: CGSize(width: 20, height: 20)) - iconImage = image.withTintColor( - NCBrandColor.shared.iconImageColor, - renderingMode: .alwaysOriginal - ) + let results = await NextcloudKit.shared.downloadContentAsync(serverUrl: metadata.urlBase + iconUrl, account: metadata.account) + if results.error == .success, let data = results.responseData?.data, + let image = try? await NCSVGRenderer().renderSVGToUIImage( + svgData: data, + size: CGSize(width: UIScreen.main.scale * 20, + height: UIScreen.main.scale * 20), + tintColor: NCBrandColor.shared.iconImageColor, + trimTransparentPixels: false) { + iconImage = image } } diff --git a/iOSClient/Utility/NCSVGRenderer.swift b/iOSClient/Utility/NCSVGRenderer.swift index 0568ff892b..6fced16ac0 100644 --- a/iOSClient/Utility/NCSVGRenderer.swift +++ b/iOSClient/Utility/NCSVGRenderer.swift @@ -34,6 +34,7 @@ final class NCSVGRenderer: NSObject, WKNavigationDelegate { svgData: Data?, size: CGSize = CGSize(width: 256, height: 256), backgroundColor: UIColor = .clear, + tintColor: UIColor? = nil, trimTransparentPixels: Bool = true, alphaThreshold: UInt8 = 0 ) async throws -> UIImage? { @@ -54,7 +55,7 @@ final class NCSVGRenderer: NSObject, WKNavigationDelegate { self.webView = webView // Inline the SVG into the DOM to avoid rasterization path. - let html = makeHTML(svgData: svgData, canvasPointSize: targetPointSize, backgroundColor: backgroundColor) + let html = makeHTML(svgData: svgData, canvasPointSize: targetPointSize, backgroundColor: backgroundColor, tintColor: tintColor) try await loadHTMLAsync(webView: webView, html: html) try await waitForInlineSVGReady(webView: webView) @@ -95,67 +96,86 @@ final class NCSVGRenderer: NSObject, WKNavigationDelegate { return webView } - private func makeHTML(svgData: Data, canvasPointSize: CGSize, backgroundColor: UIColor) -> String { + private func makeHTML( + svgData: Data, + canvasPointSize: CGSize, + backgroundColor: UIColor, + tintColor: UIColor? + ) -> String { + let w = Int(canvasPointSize.width.rounded(.down)) let h = Int(canvasPointSize.height.rounded(.down)) - // Base64 payload is decoded in JS and inserted as inline SVG markup. let base64 = svgData.base64EncodedString() - let cssBackground = (backgroundColor == .clear) ? "transparent" : backgroundColor.toCSSColor() + + let cssBackground: String = (backgroundColor == .clear) + ? "transparent" + : backgroundColor.toCSSColor() + + // Non-optional CSS tint (inherit if nil) + let cssTint: String = tintColor.map { $0.toCSSColor() } ?? "inherit" + + // Apply fill only when tintColor is provided + let svgFillRule: String = tintColor != nil + ? "#container svg { fill: currentColor; }" + : "" return """ - - - - - - + + +
+ - - - """ + svg.setAttribute('preserveAspectRatio', 'xMidYMid meet'); + } + })(); + + + + """ } private func loadHTMLAsync(webView: WKWebView, html: String) async throws {