From ccb08cd241d3e8eb60bc5a3d861fad9b92dbefb9 Mon Sep 17 00:00:00 2001 From: Rusyn Mykyta Date: Sat, 1 Jun 2024 21:34:44 +0300 Subject: [PATCH 1/2] activity color for iOS --- ios/FasterImageViewManager.swift | 66 +++++++++++++++++++++++++++++++- src/index.tsx | 3 ++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/ios/FasterImageViewManager.swift b/ios/FasterImageViewManager.swift index 783ed62..a8dee30 100644 --- a/ios/FasterImageViewManager.swift +++ b/ios/FasterImageViewManager.swift @@ -28,6 +28,7 @@ struct ImageOptions: Decodable { let thumbhash: String? let resizeMode: String? let showActivityIndicator: Bool? + let activityColor: String? let transitionDuration: Double? let cachePolicy: String? let failureImage: String? @@ -120,6 +121,9 @@ final class FasterImageView: UIView { self.thumbhash = thumbhash } resizeMode = options.resizeMode ?? "contain" + if let activityColor = options.activityColor { + self.activityColor = UIColor(hex: activityColor) + } if let showActivityIndicator = options.showActivityIndicator { self.showActivityIndicator = showActivityIndicator } @@ -231,10 +235,16 @@ final class FasterImageView: UIView { var showActivityIndicator = false { didSet { - lazyImageView.placeholderView = UIActivityIndicatorView() + let activity = UIActivityIndicatorView() + if self.activityColor != nil { + activity.color = self.activityColor + } + lazyImageView.placeholderView = activity } } + var activityColor: UIColor? + var resizeMode = "contain" { didSet { let mode = ResizeMode(rawValue: resizeMode) @@ -365,3 +375,57 @@ fileprivate extension FasterImageView { } } + +fileprivate extension UIColor { + convenience init?(hex: String) { + if !hex.starts(with: "#") { + return nil + } + + let input = hex + .replacingOccurrences(of: "#", with: "") + .uppercased() + var alpha: CGFloat = 1.0 + var red: CGFloat = 0 + var blue: CGFloat = 0 + var green: CGFloat = 0 + + switch (input.count) { + case 3 /* #RGB */: + red = Self.colorComponent(from: input, start: 0, length: 1) + green = Self.colorComponent(from: input, start: 1, length: 1) + blue = Self.colorComponent(from: input, start: 2, length: 1) + break + case 4 /* #ARGB */: + alpha = Self.colorComponent(from: input, start: 0, length: 1) + red = Self.colorComponent(from: input, start: 1, length: 1) + green = Self.colorComponent(from: input, start: 2, length: 1) + blue = Self.colorComponent(from: input, start: 3, length: 1) + break + case 6 /* #RRGGBB */: + red = Self.colorComponent(from: input, start: 0, length: 2) + green = Self.colorComponent(from: input, start: 2, length: 2) + blue = Self.colorComponent(from: input, start: 4, length: 2) + break + case 8 /* #AARRGGBB */: + alpha = Self.colorComponent(from: input, start: 0, length: 2) + red = Self.colorComponent(from: input, start: 2, length: 2) + green = Self.colorComponent(from: input, start: 4, length: 2) + blue = Self.colorComponent(from: input, start: 6, length: 2) + break + default: + return nil + } + self.init(red: red, green: green, blue: blue, alpha: alpha) + } + + static func colorComponent(from: String, start: Int, length: Int) -> CGFloat { + let substring = (from as NSString) + .substring(with: NSRange(location: start, length: length)) + let fullHex = length == 2 ? substring : "\(substring)\(substring)" + var hexComponent: UInt64 = 0 + Scanner(string: fullHex) + .scanHexInt64(&hexComponent) + return CGFloat(Double(hexComponent) / 255.0) + } +} diff --git a/src/index.tsx b/src/index.tsx index 48de6c2..7fa5f13 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -3,6 +3,7 @@ import { requireNativeComponent, NativeModules, Platform, + ColorValue, } from 'react-native'; export type IOSImageResizeMode = @@ -34,6 +35,7 @@ export type AndroidImageResizeMode = * @property {string} [thumbhash] - Thumbhash of the image (base64 encoded) (iOS only) * @property {('cover' | 'contain' | 'center' | 'fill')} [resizeMode] - Resize mode of the image * @property {boolean} [showActivityIndicator] - Show activity indicator while loading, overrides placeholder. Defaults to false (iOS only) + * @property {ColorValue} [activityColor] - Activity indicator color. Changed default activity indicator color if specified. Defaults to undefined (iOS only) * @property {number} [transitionDuration] - Duration of the transition animation in seconds, defaults to 0.75 * @property {string} [failureImage] - Image to show when the image fails to load, pass blurhash, thumbhash or base64 encoded image * @property {boolean} [progressiveLoadingEnabled] - Enable progressive loading, defaults to false @@ -58,6 +60,7 @@ export type ImageOptions = { borderBottomLeftRadius?: number; borderBottomRightRadius?: number; showActivityIndicator?: boolean; + activityColor?: ColorValue; transitionDuration?: number; cachePolicy?: 'memory' | 'discWithCacheControl' | 'discNoCacheControl'; failureImage?: string; From ff7af44ab8eb71fcef8aec0723a6c9076c69f0e1 Mon Sep 17 00:00:00 2001 From: Mykyta Rusyn Date: Sat, 1 Jun 2024 23:15:27 +0300 Subject: [PATCH 2/2] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f6c4965..b257063 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,8 @@ await clearCache(); | resizeMode | string | contain | The resize mode of the image | | thumbhash | string | | The thumbhash of the image as a base64 encoded string to show while loading (Android not tested) | | blurhash | string | | The blurhash of the image to show while loading (iOS only) | -| showActivityIndicator | boolean | false (iOS only) | Whether to show the UIActivityIndicatorView indicator when the image is loading | +| showActivityIndicator | boolean | false (iOS only) | Whether to show the UIActivityIndicatorView indicator when the image is loading +| activityColor | ColorValue | undefined (iOS only) | Activity indicator color. Changed default activity indicator color. Only hex supported | | base64Placeholder | string | | The base64 encoded placeholder image to show while the image is loading | | cachePolicy | string | memory | The cache policy of the image | | transitionDuration | number | 0.75 (iOS) Android (100) | The transition duration of the image |