diff --git a/submodules/ReactionSelectionNode/Sources/ReactionContextBackgroundNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionContextBackgroundNode.swift index 0fda32b42e..bec620d3b2 100644 --- a/submodules/ReactionSelectionNode/Sources/ReactionContextBackgroundNode.swift +++ b/submodules/ReactionSelectionNode/Sources/ReactionContextBackgroundNode.swift @@ -237,7 +237,7 @@ final class ReactionContextBackgroundNode: ASDisplayNode { var glassBackgroundFrame = contentBounds.insetBy(dx: 10.0, dy: 10.0) glassBackgroundFrame.size.height -= 8.0 transition.updateFrame(view: glassBackgroundView, frame: glassBackgroundFrame, beginWithCurrentState: true) - glassBackgroundView.update(size: glassBackgroundFrame.size, cornerRadius: 23.0, isDark: true, tintColor: .init(kind: .panel, color: UIColor(rgb: 0x1f1f27)), transition: ComponentTransition(transition)) + glassBackgroundView.update(size: glassBackgroundFrame.size, cornerRadius: 23.0, isDark: true, tintColor: .init(kind: .panel, color: UIColor(rgb: 0x4d4f5c, alpha: 0.6)), transition: ComponentTransition(transition)) transition.updateFrame(view: self.backgroundTintView, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: contentBounds.width, height: contentBounds.height)).insetBy(dx: -10.0, dy: -10.0)) } else { diff --git a/submodules/TelegramCallsUI/Sources/Components/MessageItemComponent.swift b/submodules/TelegramCallsUI/Sources/Components/MessageItemComponent.swift index 2e87d6d599..8dfcd81362 100644 --- a/submodules/TelegramCallsUI/Sources/Components/MessageItemComponent.swift +++ b/submodules/TelegramCallsUI/Sources/Components/MessageItemComponent.swift @@ -106,8 +106,8 @@ final class MessageItemComponent: Component { transition.setPosition(view: textSnapshotView, position: CGPoint(x: textSnapshotView.center.x + 71.0, y: textSnapshotView.center.y)) let initialSize = self.background.frame.size - self.background.update(size: globalFrame.size, cornerRadius: cornerRadius, isDark: true, tintColor: .init(kind: .panel, color: UIColor(rgb: 0x1f1f27)), transition: .immediate) - self.background.update(size: initialSize, cornerRadius: 18.0, isDark: true, tintColor: .init(kind: .panel, color: UIColor(rgb: 0x1f1f27)), transition: transition) + self.background.update(size: globalFrame.size, cornerRadius: cornerRadius, isDark: true, tintColor: .init(kind: .panel, color: UIColor(rgb: 0x4d4f5c, alpha: 0.6)), transition: .immediate) + self.background.update(size: initialSize, cornerRadius: 18.0, isDark: true, tintColor: .init(kind: .panel, color: UIColor(rgb: 0x4d4f5c, alpha: 0.6)), transition: transition) let deltaX = (globalFrame.width - self.container.frame.width) / 2.0 let deltaY = (globalFrame.height - self.container.frame.height) / 2.0 @@ -179,8 +179,12 @@ final class MessageItemComponent: Component { transition.setFrame(view: self.avatarNode.view, frame: avatarFrame) } + var peerName = component.peer.compactDisplayTitle + if peerName.count > 40 { + peerName = "\(peerName.prefix(40))…" + } let attributedText = stringWithAppliedEntities(component.text, entities: component.entities, baseColor: textColor, linkColor: linkColor, baseFont: textFont, linkFont: textFont, boldFont: boldTextFont, italicFont: textFont, boldItalicFont: boldTextFont, fixedFont: textFont, blockQuoteFont: textFont, message: nil).mutableCopy() as! NSMutableAttributedString - attributedText.insert(NSAttributedString(string: component.peer.compactDisplayTitle + " ", font: boldTextFont, textColor: textColor), at: 0) + attributedText.insert(NSAttributedString(string: peerName + " ", font: boldTextFont, textColor: textColor), at: 0) let textSize = self.text.update( transition: transition, @@ -209,7 +213,7 @@ final class MessageItemComponent: Component { transition.setFrame(view: self.container, frame: CGRect(origin: CGPoint(), size: size)) - self.background.update(size: size, cornerRadius: cornerRadius, isDark: true, tintColor: .init(kind: .panel, color: UIColor(rgb: 0x1f1f27)), transition: transition) + self.background.update(size: size, cornerRadius: cornerRadius, isDark: true, tintColor: .init(kind: .panel, color: UIColor(rgb: 0x4d4f5c, alpha: 0.6)), transition: transition) transition.setFrame(view: self.background, frame: CGRect(origin: CGPoint(), size: size)) if isFirstTime, let availableReactions = component.availableReactions, let textView = self.text.view { @@ -227,7 +231,7 @@ final class MessageItemComponent: Component { return } - let emojiTargetView = UIView(frame: CGRect(origin: CGPoint(x: textView.frame.width - 44.0, y: 0.0), size: CGSize(width: 44.0, height: 44.0))) + let emojiTargetView = UIView(frame: CGRect(origin: CGPoint(x: textView.frame.width - 32.0, y: -17.0), size: CGSize(width: 44.0, height: 44.0))) emojiTargetView.isUserInteractionEnabled = false textView.addSubview(emojiTargetView) diff --git a/submodules/TelegramCallsUI/Sources/Components/MessageListComponent.swift b/submodules/TelegramCallsUI/Sources/Components/MessageListComponent.swift index a45c6391b6..3dcd378652 100644 --- a/submodules/TelegramCallsUI/Sources/Components/MessageListComponent.swift +++ b/submodules/TelegramCallsUI/Sources/Components/MessageListComponent.swift @@ -71,10 +71,9 @@ final class MessageListComponent: Component { private var component: MessageListComponent? private weak var state: EmptyComponentState? - private var isUpdating: Bool = false + private var isUpdating = false private var nextSendActionTransition: MessageListComponent.SendActionTransition? - private var itemViews: [AnyHashable: ComponentView] = [:] private let topInset: CGFloat = 8.0 diff --git a/submodules/TelegramCallsUI/Sources/VideoChatActionButtonComponent.swift b/submodules/TelegramCallsUI/Sources/VideoChatActionButtonComponent.swift index a8014d2037..70a6b73c63 100644 --- a/submodules/TelegramCallsUI/Sources/VideoChatActionButtonComponent.swift +++ b/submodules/TelegramCallsUI/Sources/VideoChatActionButtonComponent.swift @@ -142,7 +142,8 @@ final class VideoChatActionButtonComponent: Component { let alphaTransition: ComponentTransition = transition.animation.isImmediate ? .immediate : .easeInOut(duration: 0.2) - let genericBackgroundColor = UIColor(rgb: 0x2d2f38) + let genericBackgroundColor = UIColor(rgb: 0x2d2f38, alpha: 0.6) + let blueColor = UIColor(rgb: 0x21477d) let titleText: String let backgroundColor: UIColor @@ -168,7 +169,7 @@ final class VideoChatActionButtonComponent: Component { case .connecting: backgroundColor = genericBackgroundColor case .muted: - backgroundColor = !isActive ? genericBackgroundColor : UIColor(rgb: 0x027FFF) + backgroundColor = !isActive ? genericBackgroundColor : blueColor case .unmuted: backgroundColor = !isActive ? genericBackgroundColor : UIColor(rgb: 0x34C659) case .raiseHand, .scheduled: @@ -181,7 +182,10 @@ final class VideoChatActionButtonComponent: Component { case .connecting: backgroundColor = genericBackgroundColor case .muted: - backgroundColor = !isActive ? genericBackgroundColor : UIColor(rgb: 0x027FFF) + backgroundColor = !isActive ? genericBackgroundColor : blueColor + if isActive { + tintColorKind = .custom + } case .unmuted: backgroundColor = !isActive ? genericBackgroundColor : UIColor(rgb: 0x34C659) case .raiseHand, .scheduled: @@ -189,18 +193,19 @@ final class VideoChatActionButtonComponent: Component { } iconDiameter = 58.0 case .rotateCamera: - titleText = "" + //TODO:localize + titleText = "rotate" switch component.microphoneState { case .connecting: backgroundColor = genericBackgroundColor case .muted: - backgroundColor = UIColor(rgb: 0x027FFF) + backgroundColor = blueColor case .unmuted: backgroundColor = UIColor(rgb: 0x34C659) case .raiseHand, .scheduled: backgroundColor = UIColor(rgb: 0x3252EF) } - iconDiameter = 60.0 + iconDiameter = 44.0 case .message: //TODO:localize titleText = "message" @@ -264,7 +269,9 @@ final class VideoChatActionButtonComponent: Component { let titleSize = self.title.update( transition: .immediate, component: AnyComponent(MultilineTextComponent( - text: .plain(NSAttributedString(string: titleText, font: Font.regular(13.0), textColor: .white)) + text: .plain(NSAttributedString(string: titleText, font: Font.regular(13.0), textColor: .white)), + horizontalAlignment: .center, + maximumNumberOfLines: 2 )), environment: {}, containerSize: CGSize(width: 90.0, height: 100.0) @@ -287,7 +294,7 @@ final class VideoChatActionButtonComponent: Component { self.background.update(size: size, cornerRadius: size.width * 0.5, isDark: true, tintColor: .init(kind: tintColorKind, color: backgroundColor), transition: tintTransition) transition.setFrame(view: self.background, frame: CGRect(origin: CGPoint(), size: size)) - let titleFrame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) * 0.5), y: size.height + 8.0), size: titleSize) + let titleFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - titleSize.width) * 0.5), y: size.height + 5.0), size: titleSize) if let titleView = self.title.view { if titleView.superview == nil { self.addSubview(titleView) diff --git a/submodules/TelegramCallsUI/Sources/VideoChatEncryptionKeyComponent.swift b/submodules/TelegramCallsUI/Sources/VideoChatEncryptionKeyComponent.swift index edea3aeb9b..769b3e0073 100644 --- a/submodules/TelegramCallsUI/Sources/VideoChatEncryptionKeyComponent.swift +++ b/submodules/TelegramCallsUI/Sources/VideoChatEncryptionKeyComponent.swift @@ -8,6 +8,7 @@ import TelegramPresentationData import CallsEmoji import ImageBlur import HierarchyTrackingLayer +import GlassBackgroundComponent private final class EmojiContainerView: UIView { private let maskImageView: UIImageView? @@ -686,14 +687,11 @@ final class VideoChatEncryptionKeyComponent: Component { } let backgroundSize = component.isExpanded ? expandedSize : collapsedSize - let backgroundCornerRadius: CGFloat = component.isExpanded ? 10.0 : collapsedSize.height * 0.5 + let backgroundCornerRadius: CGFloat = component.isExpanded ? 26.0 : collapsedSize.height * 0.5 let _ = self.background.update( transition: transition, - component: AnyComponent(FilledRoundedRectangleComponent( - color: component.theme.list.itemBlocksBackgroundColor, - cornerRadius: .value(backgroundCornerRadius), smoothCorners: false - )), + component: AnyComponent(GlassBackgroundComponent(size: backgroundSize, cornerRadius: backgroundCornerRadius, isDark: true, tintColor: .init(kind: .panel, color: UIColor(rgb: 0x1f1f27)))), environment: {}, containerSize: backgroundSize ) diff --git a/submodules/TelegramCallsUI/Sources/VideoChatMicButtonComponent.swift b/submodules/TelegramCallsUI/Sources/VideoChatMicButtonComponent.swift index 86399fe9ae..5bb2f993f5 100644 --- a/submodules/TelegramCallsUI/Sources/VideoChatMicButtonComponent.swift +++ b/submodules/TelegramCallsUI/Sources/VideoChatMicButtonComponent.swift @@ -11,6 +11,9 @@ import MetalEngine import SwiftSignalKit import AccountContext import RadialStatusNode +import GlassBackgroundComponent + +private let blueColor = UIColor(rgb: 0x55b3f8) private final class BlobView: UIView { let blobsLayer: CallBlobsLayer @@ -192,6 +195,7 @@ final class VideoChatMicButtonComponent: Component { let strings: PresentationStrings let content: Content let isCollapsed: Bool + let isCompact: Bool let updateUnmutedStateIsPushToTalk: (Bool?) -> Void let raiseHand: () -> Void let scheduleAction: () -> Void @@ -201,6 +205,7 @@ final class VideoChatMicButtonComponent: Component { strings: PresentationStrings, content: Content, isCollapsed: Bool, + isCompact: Bool, updateUnmutedStateIsPushToTalk: @escaping (Bool?) -> Void, raiseHand: @escaping () -> Void, scheduleAction: @escaping () -> Void @@ -209,6 +214,7 @@ final class VideoChatMicButtonComponent: Component { self.strings = strings self.content = content self.isCollapsed = isCollapsed + self.isCompact = isCompact self.updateUnmutedStateIsPushToTalk = updateUnmutedStateIsPushToTalk self.raiseHand = raiseHand self.scheduleAction = scheduleAction @@ -224,6 +230,9 @@ final class VideoChatMicButtonComponent: Component { if lhs.isCollapsed != rhs.isCollapsed { return false } + if lhs.isCompact != rhs.isCompact { + return false + } return true } @@ -238,6 +247,8 @@ final class VideoChatMicButtonComponent: Component { private var glowView: GlowView? private var blobView: BlobView? + private var chromeView: UIImageView? + private var component: VideoChatMicButtonComponent? private var isUpdating: Bool = false @@ -340,7 +351,7 @@ final class VideoChatMicButtonComponent: Component { let alphaTransition: ComponentTransition = transition.animation.isImmediate ? .immediate : .easeInOut(duration: 0.2) - let titleText: String + var titleText: String var subtitleText: String? var isEnabled = true switch component.content { @@ -377,10 +388,14 @@ final class VideoChatMicButtonComponent: Component { } self.isEnabled = isEnabled + if component.isCompact { + titleText = titleText.lowercased() + } + let titleSize = self.title.update( transition: .immediate, component: AnyComponent(MultilineTextComponent( - text: .plain(NSAttributedString(string: titleText, font: Font.regular(15.0), textColor: .white)) + text: .plain(NSAttributedString(string: titleText, font: Font.regular(13.0), textColor: .white)) )), environment: {}, containerSize: CGSize(width: 180.0, height: 100.0) @@ -402,7 +417,7 @@ final class VideoChatMicButtonComponent: Component { progressIndicator = RadialStatusNode(backgroundNodeColor: .clear) self.progressIndicator = progressIndicator } - progressIndicator.transitionToState(.progress(color: UIColor(rgb: 0x0080FF), lineWidth: 3.0, value: nil, cancelEnabled: false, animateRotation: true)) + progressIndicator.transitionToState(.progress(color: blueColor, lineWidth: 3.0, value: nil, cancelEnabled: false, animateRotation: true)) let progressIndicatorView = progressIndicator.view if progressIndicatorView.superview == nil { @@ -447,7 +462,7 @@ final class VideoChatMicButtonComponent: Component { if case .muted(forced: true) = component.content { colors = [UIColor(rgb: 0x3252EF), UIColor(rgb: 0xC64688)] } else if case .muted(forced: false) = component.content { - colors = [UIColor(rgb: 0x0080FF), UIColor(rgb: 0x00A1FE)] + colors = [blueColor, UIColor(rgb: 0x55adfe)] } else if case .raiseHand = component.content { colors = [UIColor(rgb: 0x3252EF), UIColor(rgb: 0xC64688)] } else if case .scheduled = component.content { @@ -503,6 +518,9 @@ final class VideoChatMicButtonComponent: Component { } var titleFrame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) * 0.5), y: size.height + 16.0), size: titleSize) + if component.isCompact { + titleFrame.origin.y -= 11.0 + } if subtitleText != nil { titleFrame.origin.y -= 5.0 } @@ -545,7 +563,7 @@ final class VideoChatMicButtonComponent: Component { } subtitleTransition.setPosition(view: subtitleView, position: subtitleFrame.center) subtitleView.bounds = CGRect(origin: CGPoint(), size: subtitleFrame.size) - alphaTransition.setAlpha(view: subtitleView, alpha: component.isCollapsed ? 0.0 : 1.0) + alphaTransition.setAlpha(view: subtitleView, alpha: component.isCollapsed || component.isCompact ? 0.0 : 1.0) } } else if let subtitle = self.subtitle { self.subtitle = nil @@ -566,7 +584,7 @@ final class VideoChatMicButtonComponent: Component { transition.setPosition(view: self.icon.view, position: iconFrame.center) transition.setBounds(view: self.icon.view, bounds: CGRect(origin: CGPoint(), size: iconFrame.size)) - transition.setScale(view: self.icon.view, scale: component.isCollapsed ? ((iconSize.width - 32.0) / iconSize.width) : 1.0) + transition.setScale(view: self.icon.view, scale: component.isCollapsed || component.isCompact ? ((iconSize.width - 34.0) / iconSize.width) : 1.0) switch component.content { case .connecting: @@ -622,7 +640,7 @@ final class VideoChatMicButtonComponent: Component { if case .muted(forced: true) = component.content { blobsColor = UIColor(rgb: 0x914BAD) } else if case .muted(forced: false) = component.content { - blobsColor = UIColor(rgb: 0x0086FF) + blobsColor = UIColor(rgb: 0x397cd8) } else if case .raiseHand = component.content { blobsColor = UIColor(rgb: 0x914BAD) } else if case .scheduled = component.content { @@ -665,7 +683,7 @@ final class VideoChatMicButtonComponent: Component { glowView = GlowView(frame: CGRect()) glowView.isUserInteractionEnabled = false self.glowView = glowView - self.insertSubview(glowView, aboveSubview: blobView) + //self.insertSubview(glowView, aboveSubview: blobView) transition.animateScale(view: glowView, from: 0.001, to: 1.0) glowView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) @@ -675,7 +693,7 @@ final class VideoChatMicButtonComponent: Component { if case .muted(forced: true) = component.content { glowColor = UIColor(rgb: 0x3252EF) } else if case .muted(forced: false) = component.content { - glowColor = UIColor(rgb: 0x0086FF) + glowColor = blueColor } else if case .raiseHand = component.content { glowColor = UIColor(rgb: 0x3252EF) } else if case .scheduled = component.content { @@ -706,6 +724,29 @@ final class VideoChatMicButtonComponent: Component { } } + if component.isCompact { + let chromeView: UIImageView + var chromeTransition = transition + if let current = self.chromeView { + chromeView = current + } else { + chromeTransition = .immediate + chromeView = UIImageView() + self.chromeView = chromeView + self.addSubview(chromeView) + + chromeView.layer.compositingFilter = "overlayBlendMode" + chromeView.alpha = 0.8 + chromeView.image = GlassBackgroundView.generateForegroundImage(size: size, isDark: false, fillColor: .clear) + } + chromeTransition.setFrame(view: chromeView, frame: CGRect(origin: .zero, size: size)) + } else if let chromeView = self.chromeView { + self.chromeView = nil + chromeView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false, completion: { _ in + chromeView.removeFromSuperview() + }) + } + return size } } diff --git a/submodules/TelegramCallsUI/Sources/VideoChatParticipantsComponent.swift b/submodules/TelegramCallsUI/Sources/VideoChatParticipantsComponent.swift index 564a15f75b..fd2f7495f8 100644 --- a/submodules/TelegramCallsUI/Sources/VideoChatParticipantsComponent.swift +++ b/submodules/TelegramCallsUI/Sources/VideoChatParticipantsComponent.swift @@ -2034,7 +2034,7 @@ final class VideoChatParticipantsComponent: Component { } else { let step: CGFloat = CGFloat(i - firstStep) / CGFloat(numSteps - firstStep - 1) let value: CGFloat = 1.0 - Display.bezierPoint(0.42, 0.0, 0.58, 1.0, step) - return UIColor(white: 0.0, alpha: baseGradientAlpha * value) + return UIColor(white: 0.0, alpha: baseGradientAlpha * value).multipliedWith(.red) } } let locations = (0 ..< numSteps).map { i -> CGFloat in diff --git a/submodules/TelegramCallsUI/Sources/VideoChatScreen.swift b/submodules/TelegramCallsUI/Sources/VideoChatScreen.swift index 8343007c16..3d596cb823 100644 --- a/submodules/TelegramCallsUI/Sources/VideoChatScreen.swift +++ b/submodules/TelegramCallsUI/Sources/VideoChatScreen.swift @@ -492,6 +492,9 @@ final class VideoChatScreenComponent: Component { if let reactionView = self.reactionContextNode?.view, view.isDescendant(of: reactionView) { return false } + if let messageListView = self.messagesList.view, view.isDescendant(of: messageListView) { + return false + } } return true } @@ -2243,7 +2246,7 @@ final class VideoChatScreenComponent: Component { size: CGSize(width: 34.0, height: 34.0) )), background: AnyComponent( - GlassBackgroundComponent(size: CGSize(width: navigationButtonDiameter, height: navigationButtonDiameter), isDark: false, tintColor: .init(kind: .panel, color: panelColor)) + GlassBackgroundComponent(size: CGSize(width: navigationButtonDiameter, height: navigationButtonDiameter), cornerRadius: navigationButtonDiameter * 0.5, isDark: true, tintColor: .init(kind: .panel, color: panelColor)) ), effectAlignment: .center, minSize: CGSize(width: navigationButtonDiameter, height: navigationButtonDiameter), @@ -2266,7 +2269,7 @@ final class VideoChatScreenComponent: Component { contentMode: .center )), background: AnyComponent( - GlassBackgroundComponent(size: CGSize(width: navigationButtonDiameter, height: navigationButtonDiameter), isDark: false, tintColor: .init(kind: .panel, color: panelColor)) + GlassBackgroundComponent(size: CGSize(width: navigationButtonDiameter, height: navigationButtonDiameter), cornerRadius: navigationButtonDiameter * 0.5, isDark: true, tintColor: .init(kind: .panel, color: panelColor)) ), effectAlignment: .center, minSize: CGSize(width: navigationButtonDiameter, height: navigationButtonDiameter), @@ -2313,6 +2316,7 @@ final class VideoChatScreenComponent: Component { navigationSidebarButton = ComponentView() self.navigationSidebarButton = navigationSidebarButton } + let navigationSidebarButtonSize = navigationSidebarButton.update( transition: .immediate, component: AnyComponent(PlainButtonComponent( @@ -2320,11 +2324,7 @@ final class VideoChatScreenComponent: Component { name: "Call/PanelIcon", tintColor: .white )), - background: AnyComponent(FilledRoundedRectangleComponent( - color: UIColor(white: 1.0, alpha: 0.1), - cornerRadius: .value(navigationButtonDiameter * 0.5), - smoothCorners: false - )), + background: AnyComponent(GlassBackgroundComponent(size: CGSize(width: navigationButtonDiameter + 10.0, height: navigationButtonDiameter), cornerRadius: navigationButtonDiameter * 0.5, isDark: true, tintColor: .init(kind: .panel, color: panelColor))), effectAlignment: .center, minSize: CGSize(width: navigationButtonDiameter + 10.0, height: navigationButtonDiameter), action: { [weak self] in @@ -2454,16 +2454,19 @@ final class VideoChatScreenComponent: Component { } let areButtonsCollapsed: Bool + let areButtonsActuallyCollapsed: Bool let mainColumnWidth: CGFloat let mainColumnSideInset: CGFloat if isTwoColumnLayout { - areButtonsCollapsed = false + areButtonsCollapsed = true + areButtonsActuallyCollapsed = false mainColumnWidth = min(isLandscape ? 340.0 : 320.0, availableSize.width - leftInset - rightInset - 340.0) mainColumnSideInset = 0.0 } else { areButtonsCollapsed = true //self.expandedParticipantsVideoState != nil + areButtonsActuallyCollapsed = self.expandedParticipantsVideoState != nil if availableSize.width > maxSingleColumnWidth { mainColumnWidth = 420.0 @@ -2553,51 +2556,24 @@ final class VideoChatScreenComponent: Component { let actionButtonDiameter: CGFloat = 56.0 let expandedMicrophoneButtonDiameter: CGFloat = actionButtonDiameter - var collapsedMicrophoneButtonDiameter: CGFloat = 116.0 + let collapsedMicrophoneButtonDiameter: CGFloat = actionButtonDiameter // 116.0 - let maxActionMicrophoneButtonSpacing: CGFloat = 38.0 - let minActionMicrophoneButtonSpacing: CGFloat = 20.0 - - if actionButtonDiameter * 2.0 + collapsedMicrophoneButtonDiameter + maxActionMicrophoneButtonSpacing * 2.0 > mainColumnWidth { - collapsedMicrophoneButtonDiameter = mainColumnWidth - (actionButtonDiameter * 2.0 + minActionMicrophoneButtonSpacing * 2.0) - collapsedMicrophoneButtonDiameter = max(actionButtonDiameter, collapsedMicrophoneButtonDiameter) - } - - let microphoneButtonDiameter: CGFloat - if buttonsOnTheSide { - microphoneButtonDiameter = actionButtonDiameter - } else if isTwoColumnLayout { - microphoneButtonDiameter = collapsedMicrophoneButtonDiameter + let buttonsWidth: CGFloat = actionButtonDiameter * 5.0 + let remainingButtonsSpace: CGFloat + if isTwoColumnLayout { + remainingButtonsSpace = mainColumnWidth - buttonsWidth } else { - if areButtonsCollapsed { - microphoneButtonDiameter = expandedMicrophoneButtonDiameter - } else { - microphoneButtonDiameter = self.expandedParticipantsVideoState == nil ? collapsedMicrophoneButtonDiameter : expandedMicrophoneButtonDiameter - } - } - let _ = microphoneButtonDiameter - //let buttonsSideInset: CGFloat = 26.0 - - //let buttonsWidth: CGFloat = actionButtonDiameter * 2.0 + microphoneButtonDiameter - //let remainingButtonsSpace: CGFloat = availableSize.width - buttonsSideInset * 2.0 - buttonsWidth - - let effectiveMaxActionMicrophoneButtonSpacing: CGFloat - if areButtonsCollapsed { - effectiveMaxActionMicrophoneButtonSpacing = 101.0 - } else { - effectiveMaxActionMicrophoneButtonSpacing = maxActionMicrophoneButtonSpacing + remainingButtonsSpace = availableSize.width - 16.0 * 2.0 - buttonsWidth } - //TODO:release - //let actionMicrophoneButtonSpacing = min(effectiveMaxActionMicrophoneButtonSpacing, floor(remainingButtonsSpace * 0.5)) - let actionMicrophoneButtonSpacing = effectiveMaxActionMicrophoneButtonSpacing + let actionMicrophoneButtonSpacing = min(25.0, floor(remainingButtonsSpace * 0.25)) var collapsedMicrophoneButtonFrame: CGRect = CGRect(origin: CGPoint(x: floor((availableSize.width - collapsedMicrophoneButtonDiameter) * 0.5), y: availableSize.height - 48.0 - environment.safeInsets.bottom - collapsedMicrophoneButtonDiameter), size: CGSize(width: collapsedMicrophoneButtonDiameter, height: collapsedMicrophoneButtonDiameter)) if self.isAnimatedOutFromPrivateCall { collapsedMicrophoneButtonFrame.origin.y = availableSize.height + 48.0 } - var expandedMicrophoneButtonFrame: CGRect = CGRect(origin: CGPoint(x: floor((availableSize.width - expandedMicrophoneButtonDiameter) * 0.5), y: availableSize.height - environment.safeInsets.bottom - expandedMicrophoneButtonDiameter - 12.0), size: CGSize(width: expandedMicrophoneButtonDiameter, height: expandedMicrophoneButtonDiameter)) + var expandedMicrophoneButtonFrame: CGRect = CGRect(origin: CGPoint(x: floor((availableSize.width - expandedMicrophoneButtonDiameter) * 0.5), y: availableSize.height - environment.safeInsets.bottom - expandedMicrophoneButtonDiameter - 40.0), size: CGSize(width: expandedMicrophoneButtonDiameter, height: expandedMicrophoneButtonDiameter)) var isMainColumnHidden = false if isTwoColumnLayout { @@ -2656,16 +2632,12 @@ final class VideoChatScreenComponent: Component { expandedParticipantsClippingY = expandedMicrophoneButtonFrame.minY - 24.0 } - //TODO:release let actionButtonSize = CGSize(width: actionButtonDiameter, height: actionButtonDiameter) - var firstActionButtonFrame = CGRect(origin: CGPoint(x: microphoneButtonFrame.minX - actionMicrophoneButtonSpacing - actionButtonDiameter, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: actionButtonSize) - var secondActionButtonFrame = CGRect(origin: CGPoint(x: firstActionButtonFrame.minX + 80.0, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: actionButtonSize) + var firstActionButtonFrame = CGRect(origin: CGPoint(x: microphoneButtonFrame.minX - (actionButtonDiameter + actionMicrophoneButtonSpacing) * 2.0, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: actionButtonSize) + var secondActionButtonFrame = CGRect(origin: CGPoint(x: firstActionButtonFrame.minX + actionMicrophoneButtonSpacing + actionButtonDiameter, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: actionButtonSize) - var fourthActionButtonFrame = CGRect(origin: CGPoint(x: microphoneButtonFrame.maxX + actionMicrophoneButtonSpacing, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: actionButtonSize) - var thirdActionButtonFrame = CGRect(origin: CGPoint(x: fourthActionButtonFrame.minX - 80.0, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: actionButtonSize) - -// var leftActionButtonFrame = CGRect(origin: CGPoint(x: microphoneButtonFrame.minX - actionMicrophoneButtonSpacing - actionButtonDiameter, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: CGSize(width: actionButtonDiameter, height: actionButtonDiameter)) -// var rightActionButtonFrame = CGRect(origin: CGPoint(x: microphoneButtonFrame.maxX + actionMicrophoneButtonSpacing, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: CGSize(width: actionButtonDiameter, height: actionButtonDiameter)) + var fourthActionButtonFrame = CGRect(origin: CGPoint(x: microphoneButtonFrame.maxX + 2.0 * actionMicrophoneButtonSpacing + actionButtonDiameter, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: actionButtonSize) + var thirdActionButtonFrame = CGRect(origin: CGPoint(x: microphoneButtonFrame.maxX + actionMicrophoneButtonSpacing, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: actionButtonSize) if buttonsOnTheSide { secondActionButtonFrame.origin.x = microphoneButtonFrame.minX @@ -2686,7 +2658,7 @@ final class VideoChatScreenComponent: Component { let columnSpacing: CGFloat = 14.0 let participantsLayout: VideoChatParticipantsComponent.Layout if isTwoColumnLayout { - let mainColumnInsets: UIEdgeInsets = UIEdgeInsets(top: navigationHeight, left: mainColumnSideInset, bottom: availableSize.height - collapsedParticipantsClippingY, right: mainColumnSideInset) + let mainColumnInsets: UIEdgeInsets = UIEdgeInsets(top: navigationHeight + 10.0, left: mainColumnSideInset, bottom: availableSize.height - collapsedParticipantsClippingY, right: mainColumnSideInset) let videoColumnWidth: CGFloat = max(10.0, availableSize.width - leftInset - rightInset - mainColumnWidth - columnSpacing) participantsLayout = VideoChatParticipantsComponent.Layout( leftInset: leftInset, @@ -3013,7 +2985,8 @@ final class VideoChatScreenComponent: Component { call: call, strings: environment.strings, content: micButtonContent, - isCollapsed: areButtonsCollapsed || buttonsOnTheSide, + isCollapsed: areButtonsActuallyCollapsed || buttonsOnTheSide, + isCompact: true, updateUnmutedStateIsPushToTalk: { [weak self] unmutedStateIsPushToTalk in guard let self, let currentCall = self.currentCall else { return @@ -3136,53 +3109,6 @@ final class VideoChatScreenComponent: Component { } } - var displayVideoControlButton = true - if areButtonsCollapsed || buttonsOnTheSide { - displayVideoControlButton = false - } else if let expandedParticipantsVideoState = self.expandedParticipantsVideoState, !expandedParticipantsVideoState.isUIHidden { - displayVideoControlButton = false - } - if case .audio = videoControlButtonContent { - if let (availableOutputs, _) = self.audioOutputState { - if availableOutputs.count <= 1 { - displayVideoControlButton = false - } - } else { - displayVideoControlButton = false - } - } - if videoControlButtonContent == videoButtonContent { - displayVideoControlButton = false - } - - let videoControlButtonSize = self.videoControlButton.update( - transition: transition, - component: AnyComponent(PlainButtonComponent( - content: AnyComponent(VideoChatActionButtonComponent( - strings: environment.strings, - content: videoControlButtonContent, - microphoneState: actionButtonMicrophoneState, - isCollapsed: true - )), - effectAlignment: .center, - action: { [weak self] in - guard let self else { - return - } - if let state = self.callState, state.isMyVideoActive { - if case let .group(groupCall) = self.currentCall { - groupCall.switchVideoCamera() - } - } else { - self.onAudioRoutePressed() - } - }, - animateAlpha: false - )), - environment: {}, - containerSize: CGSize(width: 32.0, height: 32.0) - ) - let _ = self.videoButton.update( transition: transition, component: AnyComponent(PlainButtonComponent( @@ -3190,7 +3116,7 @@ final class VideoChatScreenComponent: Component { strings: environment.strings, content: videoButtonContent, microphoneState: actionButtonMicrophoneState, - isCollapsed: areButtonsCollapsed || buttonsOnTheSide + isCollapsed: areButtonsActuallyCollapsed || buttonsOnTheSide )), effectAlignment: .center, action: { [weak self] in @@ -3209,32 +3135,12 @@ final class VideoChatScreenComponent: Component { containerSize: CGSize(width: actionButtonDiameter, height: actionButtonDiameter) ) - let videoControlButtonSpacing: CGFloat = 8.0 - - let videoButtonFrame = secondActionButtonFrame -// if displayVideoControlButton { -// let totalVideoButtonsHeight = actionButtonDiameter + videoControlButtonSpacing + videoControlButtonSize.height -// videoButtonFrame.origin.y = videoButtonFrame.minY + floor((videoButtonFrame.height - totalVideoButtonsHeight) / 2.0) + videoControlButtonSpacing + videoControlButtonSize.height -// } - - let videoControlButtonFrame = CGRect(origin: CGPoint(x: videoButtonFrame.minX + floor((videoButtonFrame.width - videoControlButtonSize.width) / 2.0), y: videoButtonFrame.minY - videoControlButtonSpacing - videoControlButtonSize.height), size: videoControlButtonSize) - - if let videoControlButtonView = self.videoControlButton.view { - if videoControlButtonView.superview == nil { - self.containerView.addSubview(videoControlButtonView) - } - transition.setPosition(view: videoControlButtonView, position: videoControlButtonFrame.center) - transition.setBounds(view: videoControlButtonView, bounds: CGRect(origin: CGPoint(), size: videoControlButtonFrame.size)) - alphaTransition.setAlpha(view: videoControlButtonView, alpha: displayVideoControlButton ? 1.0 : 0.0) - transition.setScale(view: videoControlButtonView, scale: displayVideoControlButton ? 1.0 : 0.001) - } - if let videoButtonView = self.videoButton.view { if videoButtonView.superview == nil { self.containerView.addSubview(videoButtonView) } - transition.setPosition(view: videoButtonView, position: videoButtonFrame.center) - transition.setBounds(view: videoButtonView, bounds: CGRect(origin: CGPoint(), size: videoButtonFrame.size)) + transition.setPosition(view: videoButtonView, position: secondActionButtonFrame.center) + transition.setBounds(view: videoButtonView, bounds: CGRect(origin: CGPoint(), size: secondActionButtonFrame.size)) } let _ = self.speakerButton.update( @@ -3242,13 +3148,22 @@ final class VideoChatScreenComponent: Component { component: AnyComponent(PlainButtonComponent( content: AnyComponent(VideoChatActionButtonComponent( strings: environment.strings, - content: .audio(audio: .speaker, isEnabled: false), + content: videoControlButtonContent, microphoneState: actionButtonMicrophoneState, - isCollapsed: areButtonsCollapsed || buttonsOnTheSide + isCollapsed: areButtonsActuallyCollapsed || buttonsOnTheSide )), effectAlignment: .center, action: { [weak self] in - let _ = self + guard let self else { + return + } + if let state = self.callState, state.isMyVideoActive { + if case let .group(groupCall) = self.currentCall { + groupCall.switchVideoCamera() + } + } else { + self.onAudioRoutePressed() + } }, animateAlpha: false )), @@ -3270,7 +3185,7 @@ final class VideoChatScreenComponent: Component { strings: environment.strings, content: .message, microphoneState: actionButtonMicrophoneState, - isCollapsed: areButtonsCollapsed || buttonsOnTheSide + isCollapsed: areButtonsActuallyCollapsed || buttonsOnTheSide )), effectAlignment: .center, action: { [weak self] in @@ -3299,7 +3214,7 @@ final class VideoChatScreenComponent: Component { strings: environment.strings, content: .leave, microphoneState: actionButtonMicrophoneState, - isCollapsed: areButtonsCollapsed || buttonsOnTheSide + isCollapsed: areButtonsActuallyCollapsed || buttonsOnTheSide )), effectAlignment: .center, action: { [weak self] in @@ -3324,14 +3239,9 @@ final class VideoChatScreenComponent: Component { var inputPanelBottomInset: CGFloat = 0.0 var inputPanelSize: CGSize = .zero if self.inputPanelIsActive { - var inputPanelAvailableWidth = availableSize.width + let inputPanelAvailableWidth = availableSize.width var inputPanelAvailableHeight = 103.0 - if case .regular = environment.metrics.widthClass { - if (self.inputPanelExternalState.isEditing || self.inputPanelExternalState.hasText) { - inputPanelAvailableWidth += 200.0 - } - } - + let keyboardWasHidden = self.inputPanelExternalState.isKeyboardHidden if environment.inputHeight > 0.0 || self.currentInputMode == .emoji || keyboardWasHidden { inputPanelAvailableHeight = 200.0 @@ -3552,7 +3462,7 @@ final class VideoChatScreenComponent: Component { inputPanelBottomInset = inputHeight - environment.safeInsets.bottom } else { if self.inputPanelExternalState.isEditing { - inputPanelBottomInset = 70.0 + inputPanelBottomInset = availableSize.height - microphoneButtonFrame.minY } else { inputPanelBottomInset = -inputPanelSize.height - environment.safeInsets.bottom } @@ -3564,18 +3474,46 @@ final class VideoChatScreenComponent: Component { } transition.setFrame(view: inputPanelView, frame: inputPanelFrame) } - } else if let inputPanelView = self.inputPanel.view { + } else { self.inputPanelExternalState.isEditing = false - var inputPanelFrame = inputPanelView.frame - inputPanelFrame.origin.y = availableSize.height - transition.setFrame(view: inputPanelView, frame: inputPanelFrame) + if let inputPanelView = self.inputPanel.view { + var inputPanelFrame = inputPanelView.frame + inputPanelFrame.origin.y = availableSize.height + transition.setFrame(view: inputPanelView, frame: inputPanelFrame) + } + + if let inputMediaNode = self.inputMediaNode { + self.inputMediaNode = nil + + let keyboardWasHidden = self.inputPanelExternalState.isKeyboardHidden + var dismissingInputHeight = environment.inputHeight + if self.currentInputMode == .emoji || (dismissingInputHeight.isZero && keyboardWasHidden) { + dismissingInputHeight = max(environment.inputHeight, environment.deviceMetrics.standardInputHeight(inLandscape: false)) + } + + if let animationHint = transition.userData(TextFieldComponent.AnimationHint.self), case .textFocusChanged = animationHint.kind { + dismissingInputHeight = 0.0 + } + + var targetFrame = inputMediaNode.frame + if dismissingInputHeight > 0.0 { + targetFrame.origin.y = availableSize.height - dismissingInputHeight + } else { + targetFrame.origin.y = availableSize.height + } + transition.setFrame(view: inputMediaNode.view, frame: targetFrame, completion: { [weak inputMediaNode] _ in + if let inputMediaNode { + Queue.mainQueue().after(0.2) { + inputMediaNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak inputMediaNode] _ in + inputMediaNode?.view.removeFromSuperview() + }) + } + } + }) + } } - - - - var reactionsInset = 0.0 var effectiveDisplayReactions = false if self.inputPanelExternalState.isEditing && !self.inputPanelExternalState.hasText { @@ -3586,9 +3524,9 @@ final class VideoChatScreenComponent: Component { effectiveDisplayReactions = true } - let reactionsAnchorRect: CGRect = CGRect(origin: CGPoint(x: availableSize.width - 44.0, y: availableSize.height - inputPanelBottomInset - inputPanelSize.height - 33.0), size: CGSize(width: 44.0, height: 44.0)) + let reactionsAnchorRect: CGRect = CGRect(origin: CGPoint(x: availableSize.width - 44.0, y: availableSize.height - inputPanelBottomInset - inputPanelSize.height - 18.0), size: CGSize(width: 44.0, height: 44.0)) if let reactionItems = self.reactionItems, effectiveDisplayReactions { - reactionsInset += 63.0 + reactionsInset += 48.0 let reactionContextNode: ReactionContextNode var reactionContextNodeTransition = transition @@ -3647,31 +3585,11 @@ final class VideoChatScreenComponent: Component { self.state?.updated(transition: ComponentTransition(transition)) } ) - reactionContextNode.displayTail = false //self.displayLikeReactions - reactionContextNode.forceTailToRight = true //self.displayLikeReactions + reactionContextNode.displayTail = false + reactionContextNode.forceTailToRight = true reactionContextNode.forceDark = true self.reactionContextNode = reactionContextNode -// if let tempReactionsGesture = self.tempReactionsGesture { -// tempReactionsGesture.externalUpdated = { [weak self] view, point in -// guard let self, let view, let reactionContextNode = self.reactionContextNode else { -// return -// } -// let presentationPoint = view.convert(point, to: reactionContextNode.view) -// reactionContextNode.highlightGestureMoved(location: presentationPoint, hover: false) -// } -// tempReactionsGesture.externalEnded = { [weak self] viewAndPoint in -// guard let self, let viewAndPoint, let reactionContextNode = self.reactionContextNode else { -// return -// } -// let _ = viewAndPoint -// /*let (view, point) = viewAndPoint -// let presentationPoint = view.convert(point, to: reactionContextNode.view) -// let _ = presentationPoint*/ -// reactionContextNode.highlightGestureFinished(performAction: true) -// } -// } - reactionContextNode.reactionSelected = { [weak self, weak reactionContextNode] updateReaction, _ in guard let self, let reactionContextNode else { return @@ -3685,7 +3603,7 @@ final class VideoChatScreenComponent: Component { } let targetSize = CGSize(width: 24.0, height: 24.0) - let targetView = UIView(frame: CGRect(origin: CGPoint(x: 230.0, y: self.bounds.height - targetSize.height - 133.0), size: targetSize)) //UIView(frame: CGRect(origin: CGPoint(x: floor((self.bounds.width - targetSize.width) * 0.5), y: floor((self.bounds.height - targetSize.height) * 0.5)), size: targetSize)) + let targetView = UIView(frame: CGRect(origin: CGPoint(x: 230.0, y: self.bounds.height - targetSize.height - 133.0), size: targetSize)) targetView.isUserInteractionEnabled = false self.addSubview(targetView) @@ -3787,18 +3705,12 @@ final class VideoChatScreenComponent: Component { self.containerView.addSubview(reactionContextNode.view) } -// if reactionContextNode.isAnimatingOutToReaction { -// if !reactionContextNode.isAnimatingOut { -// reactionContextNode.animateOut(to: reactionsAnchorRect, animatingOutToReaction: true) -// } -// } else { - reactionContextNodeTransition.setFrame(view: reactionContextNode.view, frame: CGRect(origin: CGPoint(), size: availableSize)) - reactionContextNode.updateLayout(size: availableSize, insets: UIEdgeInsets(), anchorRect: reactionsAnchorRect, centerAligned: true, isCoveredByInput: false, isAnimatingOut: false, transition: reactionContextNodeTransition.containedViewLayoutTransition) - - if animateReactionsIn { - reactionContextNode.animateIn(from: reactionsAnchorRect) - } -// } + reactionContextNodeTransition.setFrame(view: reactionContextNode.view, frame: CGRect(origin: CGPoint(), size: availableSize)) + reactionContextNode.updateLayout(size: availableSize, insets: UIEdgeInsets(), anchorRect: reactionsAnchorRect, centerAligned: true, isCoveredByInput: false, isAnimatingOut: false, transition: reactionContextNodeTransition.containedViewLayoutTransition) + + if animateReactionsIn { + reactionContextNode.animateIn(from: reactionsAnchorRect) + } } else { if let reactionContextNode = self.reactionContextNode { if let disappearingReactionContextNode = self.disappearingReactionContextNode { @@ -3819,7 +3731,7 @@ final class VideoChatScreenComponent: Component { reactionContextNode.updateLayout(size: availableSize, insets: UIEdgeInsets(), anchorRect: reactionsAnchorRect, centerAligned: reactionContextNode.centerAligned, isCoveredByInput: false, isAnimatingOut: false, transition: transition.containedViewLayoutTransition) } } - + var sendActionTransition: MessageListComponent.SendActionTransition? if let next = self.nextSendMessageTransition { @@ -3845,6 +3757,8 @@ final class VideoChatScreenComponent: Component { ) } } + + let messagesBottomInset: CGFloat = max(inputPanelBottomInset + inputPanelSize.height + 31.0, availableSize.height - microphoneButtonFrame.minY + 16.0) + reactionsInset let messagesListSize = self.messagesList.update( transition: transition, component: AnyComponent(MessageListComponent( @@ -3854,10 +3768,8 @@ final class VideoChatScreenComponent: Component { sendActionTransition: sendActionTransition )), environment: {}, - containerSize: availableSize + containerSize: CGSize(width: availableSize.width, height: availableSize.height - messagesBottomInset) ) - let messagesBottomInset: CGFloat = max(inputPanelBottomInset + inputPanelSize.height + 31.0, 118.0) + reactionsInset - let messagesListFrame = CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - messagesListSize.height - messagesBottomInset), size: messagesListSize) if let messagesListView = self.messagesList.view { if messagesListView.superview == nil { diff --git a/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift b/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift index 8ce886de03..e3dd5550db 100644 --- a/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift +++ b/submodules/TelegramUI/Components/Gifts/GiftOptionsScreen/Sources/GiftOptionsScreen.swift @@ -1140,7 +1140,7 @@ final class GiftOptionsScreenComponent: Component { premiumDescriptionRawString = strings.Gift_Options_Premium_Text(peerName).string isPremiumDescription = true } - if !isPremiumDescription && self.starsFilter == .resale { + if !isPremiumDescription && self.starsFilter == .resale && component.peerId != component.context.account.peerId { premiumDescriptionRawString = strings.Gift_Options_Collectibles_Text } diff --git a/submodules/TelegramUI/Components/GlassBackgroundComponent/Sources/GlassBackgroundComponent.swift b/submodules/TelegramUI/Components/GlassBackgroundComponent/Sources/GlassBackgroundComponent.swift index 7408ebb792..d54d328edd 100644 --- a/submodules/TelegramUI/Components/GlassBackgroundComponent/Sources/GlassBackgroundComponent.swift +++ b/submodules/TelegramUI/Components/GlassBackgroundComponent/Sources/GlassBackgroundComponent.swift @@ -263,8 +263,9 @@ public class GlassBackgroundView: UIView { private let backgroundNode: NavigationBackgroundNode? private let nativeView: UIVisualEffectView? - private let foregroundView: UIImageView? + private var foregroundView: UIImageView? private let shadowView: UIImageView? + private var antiGlareView: UIImageView? private let maskContainerView: UIView public let maskContentView: UIView @@ -356,6 +357,11 @@ public class GlassBackgroundView: UIView { let shadowInset: CGFloat = 32.0 + var useAntiGlare = false + if #available(iOS 26.0, *), isDark { + useAntiGlare = true + } + let params = Params(cornerRadius: cornerRadius, isDark: isDark, tintColor: tintColor) if self.params != params { self.params = params @@ -375,9 +381,25 @@ public class GlassBackgroundView: UIView { })?.stretchableImage(withLeftCapWidth: Int(shadowInset + cornerRadius), topCapHeight: Int(shadowInset + cornerRadius)) } + if useAntiGlare { + if self.antiGlareView == nil { + let antiGlareView = UIImageView() + self.antiGlareView = antiGlareView + self.addSubview(antiGlareView) + } + } else if let antiGlareView = self.antiGlareView { + self.antiGlareView = nil + antiGlareView.removeFromSuperview() + } + if let foregroundView = self.foregroundView { foregroundView.image = GlassBackgroundView.generateLegacyGlassImage(size: CGSize(width: cornerRadius * 2.0, height: cornerRadius * 2.0), inset: shadowInset, isDark: isDark, fillColor: tintColor.color) } else { + if let antiGlareView = self.antiGlareView { + antiGlareView.image = GlassBackgroundView.generateAntiglareImage(size: CGSize(width: cornerRadius * 2.0, height: cornerRadius * 2.0), color: tintColor.color.withAlphaComponent(1.0)) + antiGlareView.layer.compositingFilter = "overlayBlendMode" + } + if let nativeView { if #available(iOS 26.0, *) { let glassEffect = UIGlassEffect(style: .clear) @@ -400,6 +422,9 @@ public class GlassBackgroundView: UIView { if let foregroundView = self.foregroundView { transition.setFrame(view: foregroundView, frame: CGRect(origin: CGPoint(), size: size).insetBy(dx: -shadowInset, dy: -shadowInset)) } + if let antiGlareView = self.antiGlareView { + transition.setFrame(view: antiGlareView, frame: CGRect(origin: CGPoint(), size: size)) + } if let shadowView = self.shadowView { transition.setFrame(view: shadowView, frame: CGRect(origin: CGPoint(), size: size).insetBy(dx: -shadowInset, dy: -shadowInset)) } @@ -701,6 +726,22 @@ public extension GlassBackgroundView { })!.stretchableImage(withLeftCapWidth: Int(size.width * 0.5), topCapHeight: Int(size.height * 0.5)) } + static func generateAntiglareImage(size: CGSize, color: UIColor) -> UIImage { + var size = size + if size == .zero { + size = CGSize(width: 1.0, height: 1.0) + } + + return generateImage(size, rotatedContext: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + + let lineWidth: CGFloat = 1.0 + context.addEllipse(in: CGRect(origin: CGPoint(), size: size).insetBy(dx: lineWidth * 0.5, dy: lineWidth * 0.5)) + context.setStrokeColor(color.cgColor) + context.strokePath() + })!.stretchableImage(withLeftCapWidth: Int(size.width * 0.5), topCapHeight: Int(size.height * 0.5)) + } + static func generateForegroundImage(size: CGSize, isDark: Bool, fillColor: UIColor) -> UIImage { var size = size if size == .zero { @@ -784,11 +825,13 @@ public extension GlassBackgroundView { public final class GlassBackgroundComponent: Component { private let size: CGSize + private let cornerRadius: CGFloat private let isDark: Bool private let tintColor: GlassBackgroundView.TintColor - public init(size: CGSize, isDark: Bool, tintColor: GlassBackgroundView.TintColor) { + public init(size: CGSize, cornerRadius: CGFloat, isDark: Bool, tintColor: GlassBackgroundView.TintColor) { self.size = size + self.cornerRadius = cornerRadius self.isDark = isDark self.tintColor = tintColor } @@ -797,6 +840,9 @@ public final class GlassBackgroundComponent: Component { if lhs.size != rhs.size { return false } + if lhs.cornerRadius != rhs.cornerRadius { + return false + } if lhs.isDark != rhs.isDark { return false } @@ -808,7 +854,7 @@ public final class GlassBackgroundComponent: Component { public final class View: GlassBackgroundView { func update(component: GlassBackgroundComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: ComponentTransition) -> CGSize { - self.update(size: component.size, cornerRadius: component.size.height / 2.0, isDark: component.isDark, tintColor: component.tintColor, transition: transition) + self.update(size: component.size, cornerRadius: component.cornerRadius, isDark: component.isDark, tintColor: component.tintColor, transition: transition) self.frame = CGRect(origin: .zero, size: component.size) return component.size diff --git a/submodules/TelegramUI/Components/MessageInputActionButtonComponent/Sources/MessageInputActionButtonComponent.swift b/submodules/TelegramUI/Components/MessageInputActionButtonComponent/Sources/MessageInputActionButtonComponent.swift index 6ecb348167..f360dbcdea 100644 --- a/submodules/TelegramUI/Components/MessageInputActionButtonComponent/Sources/MessageInputActionButtonComponent.swift +++ b/submodules/TelegramUI/Components/MessageInputActionButtonComponent/Sources/MessageInputActionButtonComponent.swift @@ -529,12 +529,14 @@ public final class MessageInputActionButtonComponent: Component { self.backgroundView = backgroundView } - var tintColor = UIColor(rgb: 0x1f1f27) + var tintColor = UIColor(rgb: 0x4d4f5c, alpha: 0.6) + var tintKind: GlassBackgroundView.TintColor.Kind = .panel if case .send = component.mode { - tintColor = UIColor(rgb: 0x0187ee) + tintColor = UIColor(rgb: 0x029dff) + tintKind = .custom } let buttonSize = CGSize(width: 40.0, height: 40.0) - backgroundView.update(size: buttonSize, cornerRadius: buttonSize.height / 2.0, isDark: true, tintColor: .init(kind: .custom, color: tintColor), transition: transition) + backgroundView.update(size: buttonSize, cornerRadius: buttonSize.height / 2.0, isDark: false, tintColor: .init(kind: tintKind, color: tintColor), transition: transition) backgroundView.frame = CGRect(origin: .zero, size: buttonSize) } diff --git a/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MessageInputPanelComponent.swift b/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MessageInputPanelComponent.swift index dc7165399e..871f6a0075 100644 --- a/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MessageInputPanelComponent.swift +++ b/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MessageInputPanelComponent.swift @@ -873,6 +873,7 @@ public final class MessageInputPanelComponent: Component { }, isOneLineWhenUnfocused: component.style == .media, formatMenuAvailability: component.isFormattingLocked ? .locked : .available(TextFieldComponent.FormatMenuAvailability.Action.all), + returnKeyType: component.style == .glass ? .done : .default, lockedFormatAction: { component.presentTextFormattingTooltip?() }, @@ -1076,7 +1077,7 @@ public final class MessageInputPanelComponent: Component { self.fieldBackgroundTint.isHidden = true } if let fieldGlassBackgroundView = self.fieldGlassBackgroundView { - fieldGlassBackgroundView.update(size: fieldBackgroundFrame.size, cornerRadius: baseFieldHeight * 0.5, isDark: true, tintColor: .init(kind: .panel, color: UIColor(rgb: 0x1f1f27)), transition: transition) + fieldGlassBackgroundView.update(size: fieldBackgroundFrame.size, cornerRadius: baseFieldHeight * 0.5, isDark: true, tintColor: .init(kind: .panel, color: UIColor(rgb: 0x4d4f5c, alpha: 0.6)), transition: transition) transition.setFrame(view: fieldGlassBackgroundView, frame: fieldBackgroundFrame) } default: diff --git a/submodules/TelegramUI/Components/VideoMessageCameraScreen/Sources/VideoMessageCameraScreen.swift b/submodules/TelegramUI/Components/VideoMessageCameraScreen/Sources/VideoMessageCameraScreen.swift index 02d2bea010..e63036546a 100644 --- a/submodules/TelegramUI/Components/VideoMessageCameraScreen/Sources/VideoMessageCameraScreen.swift +++ b/submodules/TelegramUI/Components/VideoMessageCameraScreen/Sources/VideoMessageCameraScreen.swift @@ -590,6 +590,7 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent { let flipButtonBackground = flipButtonBackground.update( component: GlassBackgroundComponent( size: CGSize(width: 40.0, height: 40.0), + cornerRadius: 20.0, isDark: true, tintColor: .init(kind: .panel, color: environment.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7)) ), @@ -692,6 +693,7 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent { let flashButtonBackground = flashButtonBackground.update( component: GlassBackgroundComponent( size: CGSize(width: 40.0, height: 40.0), + cornerRadius: 20.0, isDark: true, tintColor: .init(kind: .panel, color: environment.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7)) ), @@ -766,6 +768,7 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent { id: "background", component: AnyComponent(GlassBackgroundComponent( size: CGSize(width: 40.0, height: 40.0), + cornerRadius: 20.0, isDark: true, tintColor: .init(kind: .panel, color: environment.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7)) ))