Giveaway improvements

This commit is contained in:
Ilya Laktyushin
2023-10-08 14:12:39 +04:00
parent d1f2b29370
commit 713336a13f
97 changed files with 3941 additions and 1182 deletions

View File

@@ -67,7 +67,8 @@ fragment half4 cameraBlobFragment(RasterizerData in[[stage_in]],
float t = AARadius / resolution.y;
float cAlpha = 1.0 - primaryParameters.y;
float cAlpha = min(1.0, 1.0 - primaryParameters.y);
float minColor = min(1.0, 1.0 + primaryParameters.y);
float bound = primaryParameters.x + 0.05;
if (abs(offset) > bound) {
cAlpha = mix(0.0, 1.0, min(1.0, (abs(offset) - bound) * 2.4));
@@ -75,5 +76,5 @@ fragment half4 cameraBlobFragment(RasterizerData in[[stage_in]],
float c = smoothstep(t, -t, map(uv, primaryParameters, primaryOffset, secondaryParameters, secondaryOffset));
return half4(c, max(cAlpha, 0.231), max(cAlpha, 0.188), c);
return half4(min(minColor, c), min(minColor, max(cAlpha, 0.231)), min(minColor, max(cAlpha, 0.188)), c);
}

View File

@@ -36,36 +36,47 @@ private struct CameraState: Equatable {
case holding
case handsFree
}
enum FlashTint {
case white
case yellow
case blue
}
let mode: CameraMode
let position: Camera.Position
let flashMode: Camera.FlashMode
let flashModeDidChange: Bool
let flashTint: FlashTint
let recording: Recording
let duration: Double
let isDualCameraEnabled: Bool
func updatedMode(_ mode: CameraMode) -> CameraState {
return CameraState(mode: mode, position: self.position, flashMode: self.flashMode, flashModeDidChange: self.flashModeDidChange, recording: self.recording, duration: self.duration, isDualCameraEnabled: self.isDualCameraEnabled)
return CameraState(mode: mode, position: self.position, flashMode: self.flashMode, flashModeDidChange: self.flashModeDidChange, flashTint: self.flashTint, recording: self.recording, duration: self.duration, isDualCameraEnabled: self.isDualCameraEnabled)
}
func updatedPosition(_ position: Camera.Position) -> CameraState {
return CameraState(mode: self.mode, position: position, flashMode: self.flashMode, flashModeDidChange: self.flashModeDidChange, recording: self.recording, duration: self.duration, isDualCameraEnabled: self.isDualCameraEnabled)
return CameraState(mode: self.mode, position: position, flashMode: self.flashMode, flashModeDidChange: self.flashModeDidChange, flashTint: self.flashTint, recording: self.recording, duration: self.duration, isDualCameraEnabled: self.isDualCameraEnabled)
}
func updatedFlashMode(_ flashMode: Camera.FlashMode) -> CameraState {
return CameraState(mode: self.mode, position: self.position, flashMode: flashMode, flashModeDidChange: self.flashMode != flashMode, recording: self.recording, duration: self.duration, isDualCameraEnabled: self.isDualCameraEnabled)
return CameraState(mode: self.mode, position: self.position, flashMode: flashMode, flashModeDidChange: self.flashMode != flashMode, flashTint: self.flashTint, recording: self.recording, duration: self.duration, isDualCameraEnabled: self.isDualCameraEnabled)
}
func updatedFlashTint(_ flashTint: FlashTint) -> CameraState {
return CameraState(mode: self.mode, position: self.position, flashMode: self.flashMode, flashModeDidChange: self.flashModeDidChange, flashTint: flashTint, recording: self.recording, duration: self.duration, isDualCameraEnabled: self.isDualCameraEnabled)
}
func updatedRecording(_ recording: Recording) -> CameraState {
return CameraState(mode: self.mode, position: self.position, flashMode: self.flashMode, flashModeDidChange: self.flashModeDidChange, recording: recording, duration: self.duration, isDualCameraEnabled: self.isDualCameraEnabled)
return CameraState(mode: self.mode, position: self.position, flashMode: self.flashMode, flashModeDidChange: self.flashModeDidChange, flashTint: self.flashTint, recording: recording, duration: self.duration, isDualCameraEnabled: self.isDualCameraEnabled)
}
func updatedDuration(_ duration: Double) -> CameraState {
return CameraState(mode: self.mode, position: self.position, flashMode: self.flashMode, flashModeDidChange: self.flashModeDidChange, recording: self.recording, duration: duration, isDualCameraEnabled: self.isDualCameraEnabled)
return CameraState(mode: self.mode, position: self.position, flashMode: self.flashMode, flashModeDidChange: self.flashModeDidChange, flashTint: self.flashTint, recording: self.recording, duration: duration, isDualCameraEnabled: self.isDualCameraEnabled)
}
func updatedIsDualCameraEnabled(_ isDualCameraEnabled: Bool) -> CameraState {
return CameraState(mode: self.mode, position: self.position, flashMode: self.flashMode, flashModeDidChange: self.flashModeDidChange, recording: self.recording, duration: self.duration, isDualCameraEnabled: isDualCameraEnabled)
return CameraState(mode: self.mode, position: self.position, flashMode: self.flashMode, flashModeDidChange: self.flashModeDidChange, flashTint: self.flashTint, recording: self.recording, duration: self.duration, isDualCameraEnabled: isDualCameraEnabled)
}
}
@@ -162,6 +173,7 @@ private final class CameraScreenComponent: CombinedComponent {
enum ImageKey: Hashable {
case cancel
case flip
case flashImage
}
private var cachedImages: [ImageKey: UIImage] = [:]
func image(_ key: ImageKey) -> UIImage {
@@ -171,9 +183,21 @@ private final class CameraScreenComponent: CombinedComponent {
var image: UIImage
switch key {
case .cancel:
image = UIImage(bundleImageName: "Camera/CloseIcon")!
image = UIImage(bundleImageName: "Camera/CloseIcon")!.withRenderingMode(.alwaysTemplate)
case .flip:
image = UIImage(bundleImageName: "Camera/FlipIcon")!
image = UIImage(bundleImageName: "Camera/FlipIcon")!.withRenderingMode(.alwaysTemplate)
case .flashImage:
image = generateImage(CGSize(width: 393.0, height: 852.0), rotatedContext: { size, context in
context.clear(CGRect(origin: .zero, size: size))
var locations: [CGFloat] = [0.0, 0.2, 0.6, 1.0]
let colors: [CGColor] = [UIColor(rgb: 0xffffff, alpha: 0.25).cgColor, UIColor(rgb: 0xffffff, alpha: 0.25).cgColor, UIColor(rgb: 0xffffff, alpha: 1.0).cgColor, UIColor(rgb: 0xffffff, alpha: 1.0).cgColor]
let colorSpace = CGColorSpaceCreateDeviceRGB()
let gradient = CGGradient(colorsSpace: colorSpace, colors: colors as CFArray, locations: &locations)!
let center = CGPoint(x: size.width / 2.0, y: size.height / 2.0 - 10.0)
context.drawRadialGradient(gradient, startCenter: center, startRadius: 0.0, endCenter: center, endRadius: size.width, options: .drawsAfterEndLocation)
})!.withRenderingMode(.alwaysTemplate)
}
cachedImages[key] = image
return image
@@ -589,7 +613,7 @@ private final class CameraScreenComponent: CombinedComponent {
static var body: Body {
let placeholder = Child(PlaceholderComponent.self)
let frontFlash = Child(Rectangle.self)
let frontFlash = Child(Image.self)
let cancelButton = Child(CameraButton.self)
let captureControls = Child(CaptureControlsComponent.self)
let zoomControl = Child(ZoomComponent.self)
@@ -689,19 +713,29 @@ private final class CameraScreenComponent: CombinedComponent {
// )
}
if case .none = component.cameraState.recording {
} else if case .front = component.cameraState.position {
var controlsTintColor: UIColor = .white
if case .front = component.cameraState.position, case .on = component.cameraState.flashMode {
let flashTintColor: UIColor
switch component.cameraState.flashTint {
case .white:
flashTintColor = .white
case .yellow:
flashTintColor = UIColor(rgb: 0xffed8c)
case .blue:
flashTintColor = UIColor(rgb: 0x8cdfff)
}
let frontFlash = frontFlash.update(
component: Rectangle(color: UIColor(white: 1.0, alpha: 0.6)),
availableSize: CGSize(width: availableSize.width, height: previewHeight),
component: Image(image: state.image(.flashImage), tintColor: flashTintColor),
availableSize: availableSize,
transition: .easeInOut(duration: 0.2)
)
context.add(frontFlash
.position(CGPoint(x: context.availableSize.width / 2.0, y: environment.safeInsets.top + previewHeight / 2.0))
.position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0))
.appear(.default(alpha: true))
.disappear(.default(alpha: true))
)
controlsTintColor = .black
}
let shutterState: ShutterButtonState
@@ -737,6 +771,7 @@ private final class CameraScreenComponent: CombinedComponent {
isTablet: isTablet,
hasAppeared: component.hasAppeared && hasAllRequiredAccess,
hasAccess: hasAllRequiredAccess,
tintColor: controlsTintColor,
shutterState: shutterState,
lastGalleryAsset: state.lastGalleryAsset,
tag: captureControlsTag,
@@ -823,6 +858,7 @@ private final class CameraScreenComponent: CombinedComponent {
component: AnyComponent(
Image(
image: state.image(.cancel),
tintColor: controlsTintColor,
size: CGSize(width: 40.0, height: 40.0)
)
)
@@ -867,7 +903,7 @@ private final class CameraScreenComponent: CombinedComponent {
range: nil,
waitForCompletion: false
),
colors: [:],
colors: ["__allcolors__": controlsTintColor],
size: CGSize(width: 40.0, height: 40.0)
)
)
@@ -878,7 +914,7 @@ private final class CameraScreenComponent: CombinedComponent {
component: AnyComponent(
BundleIconComponent(
name: "Camera/FlashOffIcon",
tintColor: nil
tintColor: controlsTintColor
)
)
)
@@ -909,7 +945,10 @@ private final class CameraScreenComponent: CombinedComponent {
content: AnyComponentWithIdentity(
id: "dual",
component: AnyComponent(
DualIconComponent(isSelected: component.cameraState.isDualCameraEnabled)
DualIconComponent(
isSelected: component.cameraState.isDualCameraEnabled,
tintColor: controlsTintColor
)
)
),
action: { [weak state] in
@@ -938,7 +977,8 @@ private final class CameraScreenComponent: CombinedComponent {
component: AnyComponent(
FlipButtonContentComponent(
action: animateFlipAction,
maskFrame: .zero
maskFrame: .zero,
tintColor: controlsTintColor
)
)
),
@@ -971,7 +1011,7 @@ private final class CameraScreenComponent: CombinedComponent {
let durationString = String(format: "%02d:%02d", (duration / 60) % 60, duration % 60)
let timeLabel = timeLabel.update(
component: MultilineTextComponent(
text: .plain(NSAttributedString(string: durationString, font: Font.with(size: 21.0, design: .camera), textColor: .white)),
text: .plain(NSAttributedString(string: durationString, font: Font.with(size: 21.0, design: .camera), textColor: controlsTintColor)),
horizontalAlignment: .center,
textShadowColor: UIColor(rgb: 0x000000, alpha: 0.2)
),
@@ -1021,7 +1061,10 @@ private final class CameraScreenComponent: CombinedComponent {
}
if let hintText {
let hintLabel = hintLabel.update(
component: HintLabelComponent(text: hintText),
component: HintLabelComponent(
text: hintText,
tintColor: controlsTintColor
),
availableSize: availableSize,
transition: .immediate
)
@@ -1045,6 +1088,7 @@ private final class CameraScreenComponent: CombinedComponent {
component: ModeComponent(
isTablet: isTablet,
strings: environment.strings,
tintColor: controlsTintColor,
availableModes: [.photo, .video],
currentMode: component.cameraState.mode,
updatedMode: { [weak state] mode in
@@ -1358,6 +1402,7 @@ public class CameraScreen: ViewController {
position: cameraFrontPosition ? .front : .back,
flashMode: .off,
flashModeDidChange: false,
flashTint: .white,
recording: .none,
duration: 0.0,
isDualCameraEnabled: isDualCameraEnabled
@@ -2820,17 +2865,23 @@ private final class DualIconComponent: Component {
typealias EnvironmentType = Empty
let isSelected: Bool
let tintColor: UIColor
init(
isSelected: Bool
isSelected: Bool,
tintColor: UIColor
) {
self.isSelected = isSelected
self.tintColor = tintColor
}
static func ==(lhs: DualIconComponent, rhs: DualIconComponent) -> Bool {
if lhs.isSelected != rhs.isSelected {
return false
}
if lhs.tintColor != rhs.tintColor {
return false
}
return true
}
@@ -2849,7 +2900,7 @@ private final class DualIconComponent: Component {
if let image = UIImage(bundleImageName: "Camera/DualIcon"), let cgImage = image.cgImage {
context.draw(cgImage, in: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - image.size.width) / 2.0), y: floorToScreenPixels((size.height - image.size.height) / 2.0) - 1.0), size: image.size))
}
})
})?.withRenderingMode(.alwaysTemplate)
let selectedImage = generateImage(CGSize(width: 36.0, height: 36.0), rotatedContext: { size, context in
context.clear(CGRect(origin: .zero, size: size))
@@ -2861,7 +2912,7 @@ private final class DualIconComponent: Component {
context.clip(to: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - image.size.width) / 2.0), y: floorToScreenPixels((size.height - image.size.height) / 2.0) - 1.0), size: image.size), mask: cgImage)
context.fill(CGRect(origin: .zero, size: size))
}
})
})?.withRenderingMode(.alwaysTemplate)
self.iconView.image = image
self.iconView.highlightedImage = selectedImage
@@ -2886,6 +2937,8 @@ private final class DualIconComponent: Component {
self.iconView.frame = CGRect(origin: .zero, size: size)
self.iconView.isHighlighted = component.isSelected
self.iconView.tintColor = component.tintColor
return size
}
}

View File

@@ -31,6 +31,7 @@ private extension SimpleShapeLayer {
private final class ShutterButtonContentComponent: Component {
let isTablet: Bool
let hasAppeared: Bool
let tintColor: UIColor
let shutterState: ShutterButtonState
let blobState: ShutterBlobView.BlobState
let highlightedAction: ActionSlot<Bool>
@@ -40,6 +41,7 @@ private final class ShutterButtonContentComponent: Component {
init(
isTablet: Bool,
hasAppeared: Bool,
tintColor: UIColor,
shutterState: ShutterButtonState,
blobState: ShutterBlobView.BlobState,
highlightedAction: ActionSlot<Bool>,
@@ -48,6 +50,7 @@ private final class ShutterButtonContentComponent: Component {
) {
self.isTablet = isTablet
self.hasAppeared = hasAppeared
self.tintColor = tintColor
self.shutterState = shutterState
self.blobState = blobState
self.highlightedAction = highlightedAction
@@ -62,6 +65,9 @@ private final class ShutterButtonContentComponent: Component {
if lhs.hasAppeared != rhs.hasAppeared {
return false
}
if lhs.tintColor != rhs.tintColor {
return false
}
if lhs.shutterState != rhs.shutterState {
return false
}
@@ -156,7 +162,7 @@ private final class ShutterButtonContentComponent: Component {
}
}
}
let innerColor: UIColor
let innerSize: CGSize
let ringSize: CGSize
@@ -164,7 +170,7 @@ private final class ShutterButtonContentComponent: Component {
var recordingProgress: Float?
switch component.shutterState {
case .generic, .disabled:
innerColor = .white
innerColor = component.tintColor
innerSize = CGSize(width: 60.0, height: 60.0)
ringSize = CGSize(width: 68.0, height: 68.0)
case .video:
@@ -188,7 +194,7 @@ private final class ShutterButtonContentComponent: Component {
}
self.ringLayer.fillColor = UIColor.clear.cgColor
self.ringLayer.strokeColor = UIColor.white.cgColor
self.ringLayer.strokeColor = component.tintColor.cgColor
self.ringLayer.lineWidth = ringWidth
let ringPath = CGPath(
ellipseIn: CGRect(
@@ -204,7 +210,7 @@ private final class ShutterButtonContentComponent: Component {
self.ringLayer.position = CGPoint(x: maximumShutterSize.width / 2.0, y: maximumShutterSize.height / 2.0)
if let blobView = self.blobView {
blobView.updateState(component.blobState, transition: transition)
blobView.updateState(component.blobState, tintColor: innerColor, transition: transition)
if component.isTablet {
blobView.bounds = CGRect(origin: .zero, size: CGSize(width: maximumShutterSize.width, height: 440.0))
} else {
@@ -247,14 +253,16 @@ private final class ShutterButtonContentComponent: Component {
final class FlipButtonContentComponent: Component {
private let action: ActionSlot<Void>
private let maskFrame: CGRect
private let tintColor: UIColor
init(action: ActionSlot<Void>, maskFrame: CGRect) {
init(action: ActionSlot<Void>, maskFrame: CGRect, tintColor: UIColor) {
self.action = action
self.maskFrame = maskFrame
self.tintColor = tintColor
}
static func ==(lhs: FlipButtonContentComponent, rhs: FlipButtonContentComponent) -> Bool {
return lhs.maskFrame == rhs.maskFrame
return lhs.maskFrame == rhs.maskFrame && lhs.tintColor == rhs.tintColor
}
final class View: UIView {
@@ -280,7 +288,7 @@ final class FlipButtonContentComponent: Component {
self.maskLayer.masksToBounds = true
self.maskLayer.cornerRadius = 16.0
self.icon.contents = UIImage(bundleImageName: "Camera/FlipIcon")?.cgImage
self.icon.contents = UIImage(bundleImageName: "Camera/FlipIcon")?.withRenderingMode(.alwaysTemplate).cgImage
self.darkIcon.contents = UIImage(bundleImageName: "Camera/FlipIcon")?.cgImage
self.darkIcon.layerTintColor = UIColor.black.cgColor
}
@@ -326,6 +334,8 @@ final class FlipButtonContentComponent: Component {
let size = CGSize(width: 48.0, height: 48.0)
self.icon.layerTintColor = component.tintColor.cgColor
self.icon.position = CGPoint(x: size.width / 2.0, y: size.height / 2.0)
self.icon.bounds = CGRect(origin: .zero, size: size)
@@ -350,13 +360,15 @@ final class FlipButtonContentComponent: Component {
final class LockContentComponent: Component {
private let maskFrame: CGRect
private let tintColor: UIColor
init(maskFrame: CGRect) {
init(maskFrame: CGRect, tintColor: UIColor) {
self.maskFrame = maskFrame
self.tintColor = tintColor
}
static func ==(lhs: LockContentComponent, rhs: LockContentComponent) -> Bool {
return lhs.maskFrame == rhs.maskFrame
return lhs.maskFrame == rhs.maskFrame && lhs.tintColor == rhs.tintColor
}
final class View: UIView {
@@ -383,7 +395,7 @@ final class LockContentComponent: Component {
self.maskLayer.masksToBounds = true
self.maskLayer.cornerRadius = 24.0
self.icon.contents = UIImage(bundleImageName: "Camera/LockIcon")?.cgImage
self.icon.contents = UIImage(bundleImageName: "Camera/LockIcon")?.withRenderingMode(.alwaysTemplate).cgImage
self.darkIcon.contents = UIImage(bundleImageName: "Camera/LockedIcon")?.cgImage
self.darkIcon.layerTintColor = UIColor.black.cgColor
}
@@ -397,6 +409,8 @@ final class LockContentComponent: Component {
let size = CGSize(width: 30.0, height: 30.0)
self.icon.layerTintColor = component.tintColor.cgColor
self.icon.position = CGPoint(x: size.width / 2.0, y: size.height / 2.0)
self.icon.bounds = CGRect(origin: .zero, size: size)
@@ -447,6 +461,7 @@ final class CaptureControlsComponent: Component {
let isTablet: Bool
let hasAppeared: Bool
let hasAccess: Bool
let tintColor: UIColor
let shutterState: ShutterButtonState
let lastGalleryAsset: PHAsset?
let tag: AnyObject?
@@ -465,6 +480,7 @@ final class CaptureControlsComponent: Component {
isTablet: Bool,
hasAppeared: Bool,
hasAccess: Bool,
tintColor: UIColor,
shutterState: ShutterButtonState,
lastGalleryAsset: PHAsset?,
tag: AnyObject?,
@@ -482,6 +498,7 @@ final class CaptureControlsComponent: Component {
self.isTablet = isTablet
self.hasAppeared = hasAppeared
self.hasAccess = hasAccess
self.tintColor = tintColor
self.shutterState = shutterState
self.lastGalleryAsset = lastGalleryAsset
self.tag = tag
@@ -507,6 +524,9 @@ final class CaptureControlsComponent: Component {
if lhs.hasAccess != rhs.hasAccess {
return false
}
if lhs.tintColor != rhs.tintColor {
return false
}
if lhs.shutterState != rhs.shutterState {
return false
}
@@ -578,8 +598,7 @@ final class CaptureControlsComponent: Component {
private let shutterHightlightedAction = ActionSlot<Bool>()
private let lockImage = UIImage(bundleImageName: "Camera/LockIcon")
private let zoomImage = UIImage(bundleImageName: "Camera/ZoomIcon")
private let zoomImage = UIImage(bundleImageName: "Camera/ZoomIcon")?.withRenderingMode(.alwaysTemplate)
private var didFlip = false
@@ -946,8 +965,10 @@ final class CaptureControlsComponent: Component {
transition.setBounds(view: galleryButtonView, bounds: CGRect(origin: .zero, size: galleryButtonFrame.size))
transition.setPosition(view: galleryButtonView, position: galleryButtonFrame.center)
let normalAlpha = component.tintColor.rgb == 0xffffff ? 1.0 : 0.6
transition.setScale(view: galleryButtonView, scale: isRecording || isTransitioning ? 0.1 : 1.0)
transition.setAlpha(view: galleryButtonView, alpha: isRecording || isTransitioning ? 0.0 : 1.0)
transition.setAlpha(view: galleryButtonView, alpha: isRecording || isTransitioning ? 0.0 : normalAlpha)
}
if !component.isTablet && component.hasAccess {
@@ -963,7 +984,8 @@ final class CaptureControlsComponent: Component {
component: AnyComponent(
FlipButtonContentComponent(
action: component.flipAnimationAction,
maskFrame: flipButtonMaskFrame
maskFrame: flipButtonMaskFrame,
tintColor: component.tintColor
)
)
),
@@ -1011,6 +1033,7 @@ final class CaptureControlsComponent: Component {
ShutterButtonContentComponent(
isTablet: component.isTablet,
hasAppeared: component.hasAppeared,
tintColor: component.tintColor,
shutterState: component.shutterState,
blobState: blobState,
highlightedAction: self.shutterHightlightedAction,
@@ -1072,6 +1095,7 @@ final class CaptureControlsComponent: Component {
component: AnyComponent(
Image(
image: self.zoomImage,
tintColor: component.tintColor,
size: hintIconSize
)
),
@@ -1117,7 +1141,8 @@ final class CaptureControlsComponent: Component {
id: "lock",
component: AnyComponent(
LockContentComponent(
maskFrame: lockMaskFrame
maskFrame: lockMaskFrame,
tintColor: component.tintColor
)
)
),

View File

@@ -21,6 +21,7 @@ private let buttonSize = CGSize(width: 55.0, height: 44.0)
final class ModeComponent: Component {
let isTablet: Bool
let strings: PresentationStrings
let tintColor: UIColor
let availableModes: [CameraMode]
let currentMode: CameraMode
let updatedMode: (CameraMode) -> Void
@@ -29,6 +30,7 @@ final class ModeComponent: Component {
init(
isTablet: Bool,
strings: PresentationStrings,
tintColor: UIColor,
availableModes: [CameraMode],
currentMode: CameraMode,
updatedMode: @escaping (CameraMode) -> Void,
@@ -36,6 +38,7 @@ final class ModeComponent: Component {
) {
self.isTablet = isTablet
self.strings = strings
self.tintColor = tintColor
self.availableModes = availableModes
self.currentMode = currentMode
self.updatedMode = updatedMode
@@ -49,6 +52,9 @@ final class ModeComponent: Component {
if lhs.strings !== rhs.strings {
return false
}
if lhs.tintColor != rhs.tintColor {
return false
}
if lhs.availableModes != rhs.availableModes {
return false
}
@@ -82,8 +88,17 @@ final class ModeComponent: Component {
self.pressed()
}
func update(value: String, selected: Bool) {
self.setAttributedTitle(NSAttributedString(string: value.uppercased(), font: Font.with(size: 14.0, design: .camera, weight: .semibold), textColor: selected ? UIColor(rgb: 0xf8d74a) : .white, paragraphAlignment: .center), for: .normal)
func update(value: String, selected: Bool, tintColor: UIColor) {
let accentColor: UIColor
let normalColor: UIColor
if tintColor.rgb == 0xffffff {
accentColor = UIColor(rgb: 0xf8d74a)
normalColor = .white
} else {
accentColor = tintColor
normalColor = tintColor.withAlphaComponent(0.5)
}
self.setAttributedTitle(NSAttributedString(string: value.uppercased(), font: Font.with(size: 14.0, design: .camera, weight: .semibold), textColor: selected ? accentColor : normalColor, paragraphAlignment: .center), for: .normal)
}
}
@@ -152,7 +167,7 @@ final class ModeComponent: Component {
updatedMode(mode)
}
itemView.update(value: mode.title(strings: component.strings), selected: mode == component.currentMode)
itemView.update(value: mode.title(strings: component.strings), selected: mode == component.currentMode, tintColor: component.tintColor)
itemView.bounds = CGRect(origin: .zero, size: itemFrame.size)
if isTablet {
@@ -199,17 +214,23 @@ final class ModeComponent: Component {
final class HintLabelComponent: Component {
let text: String
let tintColor: UIColor
init(
text: String
text: String,
tintColor: UIColor
) {
self.text = text
self.tintColor = tintColor
}
static func ==(lhs: HintLabelComponent, rhs: HintLabelComponent) -> Bool {
if lhs.text != rhs.text {
return false
}
if lhs.tintColor != rhs.tintColor {
return false
}
return true
}
@@ -247,7 +268,7 @@ final class HintLabelComponent: Component {
transition: .immediate,
component: AnyComponent(
MultilineTextComponent(
text: .plain(NSAttributedString(string: component.text.uppercased(), font: Font.with(size: 14.0, design: .camera, weight: .semibold), textColor: .white)),
text: .plain(NSAttributedString(string: component.text.uppercased(), font: Font.with(size: 14.0, design: .camera, weight: .semibold), textColor: component.tintColor)),
horizontalAlignment: .center
)
),

View File

@@ -64,7 +64,6 @@ private final class AnimatableProperty<T: Interpolatable> {
}
func tick(timestamp: Double) -> Bool {
guard let animation = self.animation, case let .curve(duration, curve) = animation.animation else {
return false
}
@@ -163,10 +162,14 @@ final class ShutterBlobView: UIView {
}
}
var primaryRedness: CGFloat {
func primaryRedness(tintColor: UIColor) -> CGFloat {
switch self {
case .generic:
return 0.0
if tintColor.rgb == 0x000000 {
return -1.0
} else {
return 0.0
}
default:
return 1.0
}
@@ -290,14 +293,14 @@ final class ShutterBlobView: UIView {
self.displayLink?.invalidate()
}
func updateState(_ state: BlobState, transition: Transition = .immediate) {
func updateState(_ state: BlobState, tintColor: UIColor, transition: Transition = .immediate) {
guard self.state != state else {
return
}
self.state = state
self.primarySize.update(value: state.primarySize, transition: transition)
self.primaryRedness.update(value: state.primaryRedness, transition: transition)
self.primaryRedness.update(value: state.primaryRedness(tintColor: tintColor), transition: transition)
self.primaryCornerRadius.update(value: state.primaryCornerRadius, transition: transition)
self.secondarySize.update(value: state.secondarySize, transition: transition)
self.secondaryRedness.update(value: state.secondaryRedness, transition: transition)
@@ -453,7 +456,6 @@ final class ShutterBlobView: UIView {
renderEncoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: 6, instanceCount: 1)
renderEncoder.endEncoding()
var storedDrawable: MetalImageLayer.Drawable? = drawable
commandBuffer.addCompletedHandler { _ in
DispatchQueue.main.async {