mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 06:35:51 +00:00
Various improvements
This commit is contained in:
@@ -59,7 +59,7 @@ class ChatSlowmodeItem: ListViewItem, ItemListItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private let allowedValues: [Int32] = [0, 10, 30, 60, 300, 900, 3600]
|
private let allowedValues: [Int32] = [0, 5, 10, 30, 60, 300, 900, 3600]
|
||||||
|
|
||||||
class ChatSlowmodeItemNode: ListViewItemNode {
|
class ChatSlowmodeItemNode: ListViewItemNode {
|
||||||
private let backgroundNode: ASDisplayNode
|
private let backgroundNode: ASDisplayNode
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ private enum UsernameSetupEntry: ItemListNodeEntry {
|
|||||||
case publicLinkInfo(PresentationTheme, String)
|
case publicLinkInfo(PresentationTheme, String)
|
||||||
|
|
||||||
case additionalLinkHeader(PresentationTheme, String)
|
case additionalLinkHeader(PresentationTheme, String)
|
||||||
case additionalLink(PresentationTheme, TelegramPeerUsername, Int32)
|
case additionalLink(PresentationTheme, TelegramPeerUsername, Int32, Bool)
|
||||||
case additionalLinkInfo(PresentationTheme, String)
|
case additionalLinkInfo(PresentationTheme, String)
|
||||||
|
|
||||||
var section: ItemListSectionId {
|
var section: ItemListSectionId {
|
||||||
@@ -84,7 +84,7 @@ private enum UsernameSetupEntry: ItemListNodeEntry {
|
|||||||
return .index(3)
|
return .index(3)
|
||||||
case .additionalLinkHeader:
|
case .additionalLinkHeader:
|
||||||
return .index(4)
|
return .index(4)
|
||||||
case let .additionalLink(_, username, _):
|
case let .additionalLink(_, username, _, _):
|
||||||
return .username(username.username)
|
return .username(username.username)
|
||||||
case .additionalLinkInfo:
|
case .additionalLinkInfo:
|
||||||
return .index(5)
|
return .index(5)
|
||||||
@@ -123,8 +123,8 @@ private enum UsernameSetupEntry: ItemListNodeEntry {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
case let .additionalLink(lhsTheme, lhsAddressName, lhsIndex):
|
case let .additionalLink(lhsTheme, lhsAddressName, lhsIndex, lhsCanToggleIsActive):
|
||||||
if case let .additionalLink(rhsTheme, rhsAddressName, rhsIndex) = rhs, lhsTheme === rhsTheme, lhsAddressName == rhsAddressName, lhsIndex == rhsIndex {
|
if case let .additionalLink(rhsTheme, rhsAddressName, rhsIndex, rhsCanToggleIsActive) = rhs, lhsTheme === rhsTheme, lhsAddressName == rhsAddressName, lhsIndex == rhsIndex, lhsCanToggleIsActive == rhsCanToggleIsActive {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
@@ -175,9 +175,9 @@ private enum UsernameSetupEntry: ItemListNodeEntry {
|
|||||||
default:
|
default:
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
case let .additionalLink(_, _, lhsIndex):
|
case let .additionalLink(_, _, lhsIndex, _):
|
||||||
switch rhs {
|
switch rhs {
|
||||||
case let .additionalLink(_, _, rhsIndex):
|
case let .additionalLink(_, _, rhsIndex, _):
|
||||||
return lhsIndex < rhsIndex
|
return lhsIndex < rhsIndex
|
||||||
case .publicLinkHeader, .editablePublicLink, .publicLinkStatus, .publicLinkInfo, .additionalLinkHeader:
|
case .publicLinkHeader, .editablePublicLink, .publicLinkStatus, .publicLinkInfo, .additionalLinkHeader:
|
||||||
return false
|
return false
|
||||||
@@ -232,9 +232,9 @@ private enum UsernameSetupEntry: ItemListNodeEntry {
|
|||||||
}, sectionId: self.section)
|
}, sectionId: self.section)
|
||||||
case let .additionalLinkHeader(_, text):
|
case let .additionalLinkHeader(_, text):
|
||||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||||
case let .additionalLink(_, link, _):
|
case let .additionalLink(_, link, _, canToggleIsActive):
|
||||||
return AdditionalLinkItem(presentationData: presentationData, username: link, sectionId: self.section, style: .blocks, tapAction: {
|
return AdditionalLinkItem(presentationData: presentationData, username: link, sectionId: self.section, style: .blocks, tapAction: {
|
||||||
if !link.flags.contains(.isEditable) {
|
if canToggleIsActive {
|
||||||
if link.isActive {
|
if link.isActive {
|
||||||
arguments.deactivateLink(link.username)
|
arguments.deactivateLink(link.username)
|
||||||
} else {
|
} else {
|
||||||
@@ -348,8 +348,12 @@ private func usernameSetupControllerEntries(presentationData: PresentationData,
|
|||||||
entries.append(.publicLinkStatus(presentationData.theme, currentUsername, status, statusText, currentUsername))
|
entries.append(.publicLinkStatus(presentationData.theme, currentUsername, status, statusText, currentUsername))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isBot = false
|
||||||
|
|
||||||
let otherUsernames = peer.usernames.filter { !$0.flags.contains(.isEditable) }
|
let otherUsernames = peer.usernames.filter { !$0.flags.contains(.isEditable) }
|
||||||
if case .bot = mode {
|
if case .bot = mode {
|
||||||
|
isBot = true
|
||||||
|
|
||||||
var infoText = presentationData.strings.Username_BotLinkHint
|
var infoText = presentationData.strings.Username_BotLinkHint
|
||||||
if otherUsernames.isEmpty {
|
if otherUsernames.isEmpty {
|
||||||
infoText = presentationData.strings.Username_BotLinkHintExtended
|
infoText = presentationData.strings.Username_BotLinkHintExtended
|
||||||
@@ -384,7 +388,11 @@ private func usernameSetupControllerEntries(presentationData: PresentationData,
|
|||||||
}
|
}
|
||||||
var i: Int32 = 0
|
var i: Int32 = 0
|
||||||
for username in usernames {
|
for username in usernames {
|
||||||
entries.append(.additionalLink(presentationData.theme, username, i))
|
var canToggleIsActive = false
|
||||||
|
if !username.flags.contains(.isEditable) || isBot {
|
||||||
|
canToggleIsActive = true
|
||||||
|
}
|
||||||
|
entries.append(.additionalLink(presentationData.theme, username, i, canToggleIsActive))
|
||||||
i += 1
|
i += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -613,7 +621,7 @@ public func usernameSetupController(context: AccountContext, mode: UsernameSetup
|
|||||||
|
|
||||||
controller.setReorderEntry({ (fromIndex: Int, toIndex: Int, entries: [UsernameSetupEntry]) -> Signal<Bool, NoError> in
|
controller.setReorderEntry({ (fromIndex: Int, toIndex: Int, entries: [UsernameSetupEntry]) -> Signal<Bool, NoError> in
|
||||||
let fromEntry = entries[fromIndex]
|
let fromEntry = entries[fromIndex]
|
||||||
guard case let .additionalLink(_, fromUsername, _) = fromEntry else {
|
guard case let .additionalLink(_, fromUsername, _, _) = fromEntry else {
|
||||||
return .single(false)
|
return .single(false)
|
||||||
}
|
}
|
||||||
var referenceId: String?
|
var referenceId: String?
|
||||||
@@ -626,7 +634,7 @@ public func usernameSetupController(context: AccountContext, mode: UsernameSetup
|
|||||||
var i = 0
|
var i = 0
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
switch entry {
|
switch entry {
|
||||||
case let .additionalLink(_, link, _):
|
case let .additionalLink(_, link, _, _):
|
||||||
currentUsernames.append(link.username)
|
currentUsernames.append(link.username)
|
||||||
if !link.isActive && maxIndex == nil {
|
if !link.isActive && maxIndex == nil {
|
||||||
maxIndex = max(0, i - 1)
|
maxIndex = max(0, i - 1)
|
||||||
@@ -639,7 +647,7 @@ public func usernameSetupController(context: AccountContext, mode: UsernameSetup
|
|||||||
|
|
||||||
if toIndex < entries.count {
|
if toIndex < entries.count {
|
||||||
switch entries[toIndex] {
|
switch entries[toIndex] {
|
||||||
case let .additionalLink(_, toUsername, _):
|
case let .additionalLink(_, toUsername, _, _):
|
||||||
if toUsername.isActive {
|
if toUsername.isActive {
|
||||||
referenceId = toUsername.username
|
referenceId = toUsername.username
|
||||||
} else {
|
} else {
|
||||||
@@ -716,7 +724,7 @@ public func usernameSetupController(context: AccountContext, mode: UsernameSetup
|
|||||||
var currentUsernames: [TelegramPeerUsername] = []
|
var currentUsernames: [TelegramPeerUsername] = []
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
switch entry {
|
switch entry {
|
||||||
case let .additionalLink(_, username, _):
|
case let .additionalLink(_, username, _, _):
|
||||||
currentUsernames.append(username)
|
currentUsernames.append(username)
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -142,10 +142,11 @@ final class VideoChatActionButtonComponent: Component {
|
|||||||
|
|
||||||
let alphaTransition: ComponentTransition = transition.animation.isImmediate ? .immediate : .easeInOut(duration: 0.2)
|
let alphaTransition: ComponentTransition = transition.animation.isImmediate ? .immediate : .easeInOut(duration: 0.2)
|
||||||
|
|
||||||
let genericBackgroundColor = UIColor(rgb: 0x1b1d22)
|
let genericBackgroundColor = UIColor(rgb: 0x2d2f38)
|
||||||
|
|
||||||
let titleText: String
|
let titleText: String
|
||||||
let backgroundColor: UIColor
|
let backgroundColor: UIColor
|
||||||
|
var tintColorKind: GlassBackgroundView.TintColor.Kind = .panel
|
||||||
let iconDiameter: CGFloat
|
let iconDiameter: CGFloat
|
||||||
var isEnabled: Bool = true
|
var isEnabled: Bool = true
|
||||||
switch component.content {
|
switch component.content {
|
||||||
@@ -208,6 +209,7 @@ final class VideoChatActionButtonComponent: Component {
|
|||||||
case .leave:
|
case .leave:
|
||||||
titleText = component.strings.VoiceChat_Leave
|
titleText = component.strings.VoiceChat_Leave
|
||||||
backgroundColor = UIColor(rgb: 0x330d0b)
|
backgroundColor = UIColor(rgb: 0x330d0b)
|
||||||
|
tintColorKind = .custom
|
||||||
iconDiameter = 22.0
|
iconDiameter = 22.0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,7 +284,7 @@ final class VideoChatActionButtonComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.background.update(size: size, cornerRadius: size.width * 0.5, isDark: true, tintColor: .init(kind: .custom, color: backgroundColor), transition: tintTransition)
|
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))
|
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: floor((size.width - titleSize.width) * 0.5), y: size.height + 8.0), size: titleSize)
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ private func blurredAvatarImage(_ dataImage: UIImage) -> UIImage? {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private let activityBorderImage: UIImage = {
|
private let activityBorderImage: UIImage = {
|
||||||
return generateStretchableFilledCircleImage(diameter: 20.0, color: nil, strokeColor: .white, strokeWidth: 2.0)!.withRenderingMode(.alwaysTemplate)
|
return generateStretchableFilledCircleImage(diameter: 32.0, color: nil, strokeColor: .white, strokeWidth: 2.0)!.withRenderingMode(.alwaysTemplate)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
final class VideoChatParticipantVideoComponent: Component {
|
final class VideoChatParticipantVideoComponent: Component {
|
||||||
@@ -227,7 +227,7 @@ final class VideoChatParticipantVideoComponent: Component {
|
|||||||
self.pinchContainerNode.contentNode.view.addSubview(self.backgroundGradientView)
|
self.pinchContainerNode.contentNode.view.addSubview(self.backgroundGradientView)
|
||||||
|
|
||||||
//TODO:release optimize
|
//TODO:release optimize
|
||||||
self.pinchContainerNode.contentNode.view.layer.cornerRadius = 10.0
|
self.pinchContainerNode.contentNode.view.layer.cornerRadius = 16.0
|
||||||
self.pinchContainerNode.contentNode.view.clipsToBounds = true
|
self.pinchContainerNode.contentNode.view.clipsToBounds = true
|
||||||
|
|
||||||
self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))))
|
self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))))
|
||||||
@@ -680,7 +680,7 @@ final class VideoChatParticipantVideoComponent: Component {
|
|||||||
|
|
||||||
if videoDescription != nil && self.videoSpec == nil && !isEffectivelyPaused {
|
if videoDescription != nil && self.videoSpec == nil && !isEffectivelyPaused {
|
||||||
if self.loadingEffectView == nil {
|
if self.loadingEffectView == nil {
|
||||||
let loadingEffectView = VideoChatVideoLoadingEffectView(effectAlpha: 0.1, borderAlpha: 0.2, cornerRadius: 10.0, duration: 1.0)
|
let loadingEffectView = VideoChatVideoLoadingEffectView(effectAlpha: 0.1, borderAlpha: 0.2, cornerRadius: 16.0, duration: 1.0)
|
||||||
self.loadingEffectView = loadingEffectView
|
self.loadingEffectView = loadingEffectView
|
||||||
loadingEffectView.alpha = 0.0
|
loadingEffectView.alpha = 0.0
|
||||||
loadingEffectView.isUserInteractionEnabled = false
|
loadingEffectView.isUserInteractionEnabled = false
|
||||||
|
|||||||
@@ -485,6 +485,14 @@ final class VideoChatScreenComponent: Component {
|
|||||||
if gestureRecognizer is UIPanGestureRecognizer {
|
if gestureRecognizer is UIPanGestureRecognizer {
|
||||||
if let otherGestureRecognizer = otherGestureRecognizer as? UIPanGestureRecognizer {
|
if let otherGestureRecognizer = otherGestureRecognizer as? UIPanGestureRecognizer {
|
||||||
if otherGestureRecognizer.view is UIScrollView {
|
if otherGestureRecognizer.view is UIScrollView {
|
||||||
|
if let view = otherGestureRecognizer.view {
|
||||||
|
if let inputView = self.inputMediaNode?.view, view.isDescendant(of: inputView) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if let reactionView = self.reactionContextNode?.view, view.isDescendant(of: reactionView) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if let participantsView = self.participants.view as? VideoChatParticipantsComponent.View {
|
if let participantsView = self.participants.view as? VideoChatParticipantsComponent.View {
|
||||||
@@ -2195,7 +2203,7 @@ final class VideoChatScreenComponent: Component {
|
|||||||
|
|
||||||
let landscapeControlsWidth: CGFloat = 104.0
|
let landscapeControlsWidth: CGFloat = 104.0
|
||||||
var landscapeControlsOffsetX: CGFloat = 0.0
|
var landscapeControlsOffsetX: CGFloat = 0.0
|
||||||
//let landscapeControlsSpacing: CGFloat = 30.0
|
let landscapeControlsSpacing: CGFloat = 30.0
|
||||||
|
|
||||||
var leftInset: CGFloat = max(environment.safeInsets.left, 16.0)
|
var leftInset: CGFloat = max(environment.safeInsets.left, 16.0)
|
||||||
|
|
||||||
@@ -2222,6 +2230,8 @@ final class VideoChatScreenComponent: Component {
|
|||||||
let navigationButtonDiameter: CGFloat = 40.0
|
let navigationButtonDiameter: CGFloat = 40.0
|
||||||
let navigationButtonInset: CGFloat = 4.0
|
let navigationButtonInset: CGFloat = 4.0
|
||||||
|
|
||||||
|
let panelColor = UIColor(rgb: 0x1f1f27)
|
||||||
|
|
||||||
let navigationLeftButtonSize = self.navigationLeftButton.update(
|
let navigationLeftButtonSize = self.navigationLeftButton.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(PlainButtonComponent(
|
component: AnyComponent(PlainButtonComponent(
|
||||||
@@ -2232,7 +2242,7 @@ final class VideoChatScreenComponent: Component {
|
|||||||
color: .white
|
color: .white
|
||||||
)),
|
)),
|
||||||
background: AnyComponent(
|
background: AnyComponent(
|
||||||
GlassBackgroundComponent(size: CGSize(width: navigationButtonDiameter, height: navigationButtonDiameter), tintColor: .init(kind: .custom, color: UIColor(rgb: 0x101014)))
|
GlassBackgroundComponent(size: CGSize(width: navigationButtonDiameter, height: navigationButtonDiameter), isDark: false, tintColor: .init(kind: .panel, color: panelColor))
|
||||||
),
|
),
|
||||||
effectAlignment: .center,
|
effectAlignment: .center,
|
||||||
minSize: CGSize(width: navigationButtonDiameter, height: navigationButtonDiameter),
|
minSize: CGSize(width: navigationButtonDiameter, height: navigationButtonDiameter),
|
||||||
@@ -2254,7 +2264,7 @@ final class VideoChatScreenComponent: Component {
|
|||||||
image: closeButtonImage(dark: false)
|
image: closeButtonImage(dark: false)
|
||||||
)),
|
)),
|
||||||
background: AnyComponent(
|
background: AnyComponent(
|
||||||
GlassBackgroundComponent(size: CGSize(width: navigationButtonDiameter, height: navigationButtonDiameter), tintColor: .init(kind: .custom, color: UIColor(rgb: 0x101014)))
|
GlassBackgroundComponent(size: CGSize(width: navigationButtonDiameter, height: navigationButtonDiameter), isDark: false, tintColor: .init(kind: .panel, color: panelColor))
|
||||||
),
|
),
|
||||||
effectAlignment: .center,
|
effectAlignment: .center,
|
||||||
minSize: CGSize(width: navigationButtonDiameter, height: navigationButtonDiameter),
|
minSize: CGSize(width: navigationButtonDiameter, height: navigationButtonDiameter),
|
||||||
@@ -2646,24 +2656,28 @@ final class VideoChatScreenComponent: Component {
|
|||||||
|
|
||||||
//TODO:release
|
//TODO:release
|
||||||
let actionButtonSize = CGSize(width: actionButtonDiameter, height: actionButtonDiameter)
|
let actionButtonSize = CGSize(width: actionButtonDiameter, height: actionButtonDiameter)
|
||||||
let firstActionButtonFrame = CGRect(origin: CGPoint(x: microphoneButtonFrame.minX - actionMicrophoneButtonSpacing - actionButtonDiameter, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: actionButtonSize)
|
var firstActionButtonFrame = CGRect(origin: CGPoint(x: microphoneButtonFrame.minX - actionMicrophoneButtonSpacing - actionButtonDiameter, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: actionButtonSize)
|
||||||
let secondActionButtonFrame = CGRect(origin: CGPoint(x: firstActionButtonFrame.minX + 80.0, 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)
|
||||||
|
|
||||||
let fourthActionButtonFrame = CGRect(origin: CGPoint(x: microphoneButtonFrame.maxX + actionMicrophoneButtonSpacing, 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)
|
||||||
let thirdActionButtonFrame = CGRect(origin: CGPoint(x: fourthActionButtonFrame.minX - 80.0, 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)
|
||||||
|
|
||||||
let _ = firstActionButtonFrame
|
|
||||||
|
|
||||||
// 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 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 rightActionButtonFrame = CGRect(origin: CGPoint(x: microphoneButtonFrame.maxX + actionMicrophoneButtonSpacing, y: microphoneButtonFrame.minY + floor((microphoneButtonFrame.height - actionButtonDiameter) * 0.5)), size: CGSize(width: actionButtonDiameter, height: actionButtonDiameter))
|
||||||
|
|
||||||
// if buttonsOnTheSide {
|
if buttonsOnTheSide {
|
||||||
// leftActionButtonFrame.origin.x = microphoneButtonFrame.minX
|
secondActionButtonFrame.origin.x = microphoneButtonFrame.minX
|
||||||
// leftActionButtonFrame.origin.y = microphoneButtonFrame.minY - landscapeControlsSpacing - actionButtonDiameter
|
secondActionButtonFrame.origin.y = microphoneButtonFrame.minY - landscapeControlsSpacing - actionButtonDiameter
|
||||||
//
|
|
||||||
// rightActionButtonFrame.origin.x = microphoneButtonFrame.minX
|
firstActionButtonFrame.origin.x = microphoneButtonFrame.minX
|
||||||
// rightActionButtonFrame.origin.y = microphoneButtonFrame.maxY + landscapeControlsSpacing
|
firstActionButtonFrame.origin.y = secondActionButtonFrame.minY - landscapeControlsSpacing - actionButtonDiameter
|
||||||
// }
|
|
||||||
|
thirdActionButtonFrame.origin.x = microphoneButtonFrame.minX
|
||||||
|
thirdActionButtonFrame.origin.y = microphoneButtonFrame.maxY + landscapeControlsSpacing
|
||||||
|
|
||||||
|
fourthActionButtonFrame.origin.x = microphoneButtonFrame.minX
|
||||||
|
fourthActionButtonFrame.origin.y = thirdActionButtonFrame.maxY + landscapeControlsSpacing
|
||||||
|
}
|
||||||
|
|
||||||
let participantsSize = availableSize
|
let participantsSize = availableSize
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ swift_library(
|
|||||||
"//submodules/ActivityIndicator",
|
"//submodules/ActivityIndicator",
|
||||||
"//submodules/ShimmerEffect",
|
"//submodules/ShimmerEffect",
|
||||||
"//submodules/Components/BundleIconComponent",
|
"//submodules/Components/BundleIconComponent",
|
||||||
|
"//submodules/TelegramUI/Components/GlassBackgroundComponent",
|
||||||
|
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import AnimatedTextComponent
|
|||||||
import ActivityIndicator
|
import ActivityIndicator
|
||||||
import BundleIconComponent
|
import BundleIconComponent
|
||||||
import ShimmerEffect
|
import ShimmerEffect
|
||||||
|
import GlassBackgroundComponent
|
||||||
|
|
||||||
public final class ButtonBadgeComponent: Component {
|
public final class ButtonBadgeComponent: Component {
|
||||||
let fillColor: UIColor
|
let fillColor: UIColor
|
||||||
@@ -338,6 +339,12 @@ public final class ButtonTextContentComponent: Component {
|
|||||||
|
|
||||||
public final class ButtonComponent: Component {
|
public final class ButtonComponent: Component {
|
||||||
public struct Background: Equatable {
|
public struct Background: Equatable {
|
||||||
|
public enum Style {
|
||||||
|
case glass
|
||||||
|
case legacy
|
||||||
|
}
|
||||||
|
|
||||||
|
public var style: Style
|
||||||
public var color: UIColor
|
public var color: UIColor
|
||||||
public var foreground: UIColor
|
public var foreground: UIColor
|
||||||
public var pressedColor: UIColor
|
public var pressedColor: UIColor
|
||||||
@@ -345,12 +352,14 @@ public final class ButtonComponent: Component {
|
|||||||
public var isShimmering: Bool
|
public var isShimmering: Bool
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
|
style: Style = .legacy,
|
||||||
color: UIColor,
|
color: UIColor,
|
||||||
foreground: UIColor,
|
foreground: UIColor,
|
||||||
pressedColor: UIColor,
|
pressedColor: UIColor,
|
||||||
cornerRadius: CGFloat = 10.0,
|
cornerRadius: CGFloat = 10.0,
|
||||||
isShimmering: Bool = false
|
isShimmering: Bool = false
|
||||||
) {
|
) {
|
||||||
|
self.style = style
|
||||||
self.color = color
|
self.color = color
|
||||||
self.foreground = foreground
|
self.foreground = foreground
|
||||||
self.pressedColor = pressedColor
|
self.pressedColor = pressedColor
|
||||||
@@ -360,6 +369,7 @@ public final class ButtonComponent: Component {
|
|||||||
|
|
||||||
public func withIsShimmering(_ isShimmering: Bool) -> Background {
|
public func withIsShimmering(_ isShimmering: Bool) -> Background {
|
||||||
return Background(
|
return Background(
|
||||||
|
style: self.style,
|
||||||
color: self.color,
|
color: self.color,
|
||||||
foreground: self.foreground,
|
foreground: self.foreground,
|
||||||
pressedColor: self.pressedColor,
|
pressedColor: self.pressedColor,
|
||||||
@@ -431,6 +441,7 @@ public final class ButtonComponent: Component {
|
|||||||
private weak var componentState: EmptyComponentState?
|
private weak var componentState: EmptyComponentState?
|
||||||
|
|
||||||
private var shimmeringView: ButtonShimmeringView?
|
private var shimmeringView: ButtonShimmeringView?
|
||||||
|
private var chromeView: UIImageView?
|
||||||
private var contentItem: ContentItem?
|
private var contentItem: ContentItem?
|
||||||
|
|
||||||
private var activityIndicator: ActivityIndicator?
|
private var activityIndicator: ActivityIndicator?
|
||||||
@@ -475,7 +486,12 @@ public final class ButtonComponent: Component {
|
|||||||
self.isEnabled = (component.isEnabled || component.allowActionWhenDisabled) && !component.displaysProgress
|
self.isEnabled = (component.isEnabled || component.allowActionWhenDisabled) && !component.displaysProgress
|
||||||
|
|
||||||
transition.setBackgroundColor(view: self, color: component.background.color)
|
transition.setBackgroundColor(view: self, color: component.background.color)
|
||||||
transition.setCornerRadius(layer: self.layer, cornerRadius: component.background.cornerRadius)
|
|
||||||
|
var cornerRadius: CGFloat = component.background.cornerRadius
|
||||||
|
if case .glass = component.background.style, component.background.cornerRadius == 10.0 {
|
||||||
|
cornerRadius = availableSize.height * 0.5
|
||||||
|
}
|
||||||
|
transition.setCornerRadius(layer: self.layer, cornerRadius: cornerRadius)
|
||||||
|
|
||||||
var contentAlpha: CGFloat = 1.0
|
var contentAlpha: CGFloat = 1.0
|
||||||
if component.displaysProgress {
|
if component.displaysProgress {
|
||||||
@@ -581,6 +597,33 @@ public final class ButtonComponent: Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if component.background.style == .glass {
|
||||||
|
let chromeView: UIImageView
|
||||||
|
var chromeTransition = transition
|
||||||
|
if let current = self.chromeView {
|
||||||
|
chromeView = current
|
||||||
|
} else {
|
||||||
|
chromeTransition = .immediate
|
||||||
|
chromeView = UIImageView()
|
||||||
|
self.chromeView = chromeView
|
||||||
|
if let shimmeringView = self.shimmeringView {
|
||||||
|
self.insertSubview(chromeView, aboveSubview: shimmeringView)
|
||||||
|
} else {
|
||||||
|
self.insertSubview(chromeView, at: 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
chromeView.layer.compositingFilter = "overlayBlendMode"
|
||||||
|
chromeView.alpha = 0.8
|
||||||
|
chromeView.image = GlassBackgroundView.generateForegroundImage(size: CGSize(width: 26.0 * 2.0, height: 26.0 * 2.0), isDark: component.background.color.lightness < 0.4, fillColor: .clear)
|
||||||
|
}
|
||||||
|
chromeTransition.setFrame(view: chromeView, frame: CGRect(origin: .zero, size: availableSize))
|
||||||
|
} 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 availableSize
|
return availableSize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -834,7 +834,8 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
|||||||
file: arguments.parentMessage.associatedMedia[MediaId(
|
file: arguments.parentMessage.associatedMedia[MediaId(
|
||||||
namespace: Namespaces.Media.CloudFile,
|
namespace: Namespaces.Media.CloudFile,
|
||||||
id: backgroundEmojiId
|
id: backgroundEmojiId
|
||||||
)] as? TelegramMediaFile
|
)] as? TelegramMediaFile,
|
||||||
|
emptyCorner: giftEmojiFileId != nil
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
var isTransparent: Bool = false
|
var isTransparent: Bool = false
|
||||||
@@ -898,16 +899,19 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let giftEmojiFileId {
|
if let giftEmojiFileId {
|
||||||
let giftLayerSize = CGSize(width: 20.0, height: 20.0)
|
let giftLayerSize = CGSize(width: 18.0, height: 18.0)
|
||||||
let giftLayerFrame = CGRect(origin: CGPoint(x: textFrame.minX - 16.0, y: 5.0), size: giftLayerSize)
|
let giftLayerFrame = CGRect(origin: CGPoint(x: realSize.width - giftLayerSize.width - 4.0, y: 3.0), size: giftLayerSize)
|
||||||
|
|
||||||
let giftEmojiLayer: InlineStickerItemLayer
|
let giftEmojiLayer: InlineStickerItemLayer
|
||||||
if let current = node.giftEmojiLayer {
|
if let current = node.giftEmojiLayer, current.file?.fileId.id == giftEmojiFileId {
|
||||||
giftEmojiLayer = current
|
giftEmojiLayer = current
|
||||||
|
|
||||||
animation.animator.updateFrame(layer: giftEmojiLayer, frame: giftLayerFrame, completion: nil)
|
animation.animator.updateFrame(layer: giftEmojiLayer, frame: giftLayerFrame, completion: nil)
|
||||||
} else {
|
} else {
|
||||||
giftEmojiLayer = InlineStickerItemLayer(context: arguments.context, userLocation: .other, attemptSynchronousLoad: true, emoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: giftEmojiFileId, file: nil, custom: nil, enableAnimation: true), file: nil, cache: arguments.context.animationCache, renderer: arguments.context.animationRenderer, unique: false, placeholderColor: placeholderColor, pointSize: giftLayerSize, dynamicColor: nil, loopCount: 2)
|
if let giftEmojiLayer = node.giftEmojiLayer {
|
||||||
|
node.giftEmojiLayer = nil
|
||||||
|
giftEmojiLayer.removeFromSuperlayer()
|
||||||
|
}
|
||||||
|
giftEmojiLayer = InlineStickerItemLayer(context: arguments.context, userLocation: .other, attemptSynchronousLoad: true, emoji: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: giftEmojiFileId, file: nil, custom: nil, enableAnimation: true), file: nil, cache: arguments.context.animationCache, renderer: arguments.context.animationRenderer, unique: false, placeholderColor: placeholderColor, pointSize: CGSize(width: giftLayerSize.width * 2.0, height: giftLayerSize.height * 2.0), dynamicColor: nil, loopCount: 2)
|
||||||
node.giftEmojiLayer = giftEmojiLayer
|
node.giftEmojiLayer = giftEmojiLayer
|
||||||
node.contentNode.layer.addSublayer(giftEmojiLayer)
|
node.contentNode.layer.addSublayer(giftEmojiLayer)
|
||||||
|
|
||||||
|
|||||||
@@ -426,11 +426,13 @@ public final class MessageInlineBlockBackgroundView: UIView {
|
|||||||
public let context: AccountContext
|
public let context: AccountContext
|
||||||
public let fileId: Int64
|
public let fileId: Int64
|
||||||
public let file: TelegramMediaFile?
|
public let file: TelegramMediaFile?
|
||||||
|
public let emptyCorner: Bool
|
||||||
|
|
||||||
public init(context: AccountContext, fileId: Int64, file: TelegramMediaFile?) {
|
public init(context: AccountContext, fileId: Int64, file: TelegramMediaFile?, emptyCorner: Bool = false) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.fileId = fileId
|
self.fileId = fileId
|
||||||
self.file = file
|
self.file = file
|
||||||
|
self.emptyCorner = emptyCorner
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func ==(lhs: Pattern, rhs: Pattern) -> Bool {
|
public static func ==(lhs: Pattern, rhs: Pattern) -> Bool {
|
||||||
@@ -446,7 +448,9 @@ public final class MessageInlineBlockBackgroundView: UIView {
|
|||||||
if lhs.file?.fileId != rhs.file?.fileId {
|
if lhs.file?.fileId != rhs.file?.fileId {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.emptyCorner != rhs.emptyCorner {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -771,7 +775,12 @@ public final class MessageInlineBlockBackgroundView: UIView {
|
|||||||
patternContentLayer.frame = CGRect(origin: CGPoint(x: patternOrigin.x - placement.position.x / 3.0 - itemSize.width * 0.5, y: patternOrigin.y + placement.position.y / 3.0 - itemSize.height * 0.5), size: itemSize)
|
patternContentLayer.frame = CGRect(origin: CGPoint(x: patternOrigin.x - placement.position.x / 3.0 - itemSize.width * 0.5, y: patternOrigin.y + placement.position.y / 3.0 - itemSize.height * 0.5), size: itemSize)
|
||||||
var alphaFraction = abs(placement.position.x / 3.0) / min(500.0, size.width)
|
var alphaFraction = abs(placement.position.x / 3.0) / min(500.0, size.width)
|
||||||
alphaFraction = min(1.0, max(0.0, alphaFraction))
|
alphaFraction = min(1.0, max(0.0, alphaFraction))
|
||||||
patternContentLayer.opacity = 0.3 * Float(1.0 - alphaFraction) * Float(patternAlpha)
|
|
||||||
|
if maxIndex == 1 && params.pattern?.emptyCorner == true {
|
||||||
|
patternContentLayer.opacity = 0.0
|
||||||
|
} else {
|
||||||
|
patternContentLayer.opacity = 0.3 * Float(1.0 - alphaFraction) * Float(patternAlpha)
|
||||||
|
}
|
||||||
|
|
||||||
maxIndex += 1
|
maxIndex += 1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -784,10 +784,12 @@ public extension GlassBackgroundView {
|
|||||||
|
|
||||||
public final class GlassBackgroundComponent: Component {
|
public final class GlassBackgroundComponent: Component {
|
||||||
private let size: CGSize
|
private let size: CGSize
|
||||||
|
private let isDark: Bool
|
||||||
private let tintColor: GlassBackgroundView.TintColor
|
private let tintColor: GlassBackgroundView.TintColor
|
||||||
|
|
||||||
public init(size: CGSize, tintColor: GlassBackgroundView.TintColor) {
|
public init(size: CGSize, isDark: Bool, tintColor: GlassBackgroundView.TintColor) {
|
||||||
self.size = size
|
self.size = size
|
||||||
|
self.isDark = isDark
|
||||||
self.tintColor = tintColor
|
self.tintColor = tintColor
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -795,6 +797,9 @@ public final class GlassBackgroundComponent: Component {
|
|||||||
if lhs.size != rhs.size {
|
if lhs.size != rhs.size {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.isDark != rhs.isDark {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhs.tintColor != rhs.tintColor {
|
if lhs.tintColor != rhs.tintColor {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -803,7 +808,7 @@ public final class GlassBackgroundComponent: Component {
|
|||||||
|
|
||||||
public final class View: GlassBackgroundView {
|
public final class View: GlassBackgroundView {
|
||||||
func update(component: GlassBackgroundComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
func update(component: GlassBackgroundComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||||
self.update(size: component.size, cornerRadius: component.size.height / 2.0, isDark: true, tintColor: component.tintColor, transition: transition)
|
self.update(size: component.size, cornerRadius: component.size.height / 2.0, isDark: component.isDark, tintColor: component.tintColor, transition: transition)
|
||||||
self.frame = CGRect(origin: .zero, size: component.size)
|
self.frame = CGRect(origin: .zero, size: component.size)
|
||||||
|
|
||||||
return component.size
|
return component.size
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ import SwitchNode
|
|||||||
import CheckNode
|
import CheckNode
|
||||||
|
|
||||||
public final class ListActionItemComponent: Component {
|
public final class ListActionItemComponent: Component {
|
||||||
|
public enum Style {
|
||||||
|
case glass
|
||||||
|
case legacy
|
||||||
|
}
|
||||||
|
|
||||||
public enum ToggleStyle {
|
public enum ToggleStyle {
|
||||||
case regular
|
case regular
|
||||||
case icons
|
case icons
|
||||||
@@ -133,6 +138,7 @@ public final class ListActionItemComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public let theme: PresentationTheme
|
public let theme: PresentationTheme
|
||||||
|
public let style: Style
|
||||||
public let background: AnyComponent<Empty>?
|
public let background: AnyComponent<Empty>?
|
||||||
public let title: AnyComponent<Empty>
|
public let title: AnyComponent<Empty>
|
||||||
public let titleAlignment: Alignment
|
public let titleAlignment: Alignment
|
||||||
@@ -146,6 +152,7 @@ public final class ListActionItemComponent: Component {
|
|||||||
|
|
||||||
public init(
|
public init(
|
||||||
theme: PresentationTheme,
|
theme: PresentationTheme,
|
||||||
|
style: Style = .legacy,
|
||||||
background: AnyComponent<Empty>? = nil,
|
background: AnyComponent<Empty>? = nil,
|
||||||
title: AnyComponent<Empty>,
|
title: AnyComponent<Empty>,
|
||||||
titleAlignment: Alignment = .default,
|
titleAlignment: Alignment = .default,
|
||||||
@@ -158,6 +165,7 @@ public final class ListActionItemComponent: Component {
|
|||||||
updateIsHighlighted: ((UIView, Bool) -> Void)? = nil
|
updateIsHighlighted: ((UIView, Bool) -> Void)? = nil
|
||||||
) {
|
) {
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
|
self.style = style
|
||||||
self.background = background
|
self.background = background
|
||||||
self.title = title
|
self.title = title
|
||||||
self.titleAlignment = titleAlignment
|
self.titleAlignment = titleAlignment
|
||||||
@@ -174,6 +182,9 @@ public final class ListActionItemComponent: Component {
|
|||||||
if lhs.theme !== rhs.theme {
|
if lhs.theme !== rhs.theme {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.style != rhs.style {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhs.background != rhs.background {
|
if lhs.background != rhs.background {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -391,8 +402,19 @@ public final class ListActionItemComponent: Component {
|
|||||||
contentRightInset = customAccessorySizeValue.width + customAccessory.insets.left + customAccessory.insets.right
|
contentRightInset = customAccessorySizeValue.width + customAccessory.insets.left + customAccessory.insets.right
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var contentInsets = component.contentInsets
|
||||||
|
switch component.style {
|
||||||
|
case .glass:
|
||||||
|
if contentInsets.top == 12.0 && contentInsets.bottom == 12.0 {
|
||||||
|
contentInsets.top = 16.0
|
||||||
|
contentInsets.bottom = 16.0
|
||||||
|
}
|
||||||
|
case .legacy:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
var contentHeight: CGFloat = 0.0
|
var contentHeight: CGFloat = 0.0
|
||||||
contentHeight += component.contentInsets.top
|
contentHeight += contentInsets.top
|
||||||
|
|
||||||
if let leftIcon = component.leftIcon {
|
if let leftIcon = component.leftIcon {
|
||||||
switch leftIcon {
|
switch leftIcon {
|
||||||
@@ -414,11 +436,10 @@ public final class ListActionItemComponent: Component {
|
|||||||
contentLeftInset = floor((availableSize.width - titleSize.width) / 2.0)
|
contentLeftInset = floor((availableSize.width - titleSize.width) / 2.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let titleY = contentHeight
|
let titleY = contentHeight
|
||||||
contentHeight += titleSize.height
|
contentHeight += titleSize.height
|
||||||
|
|
||||||
contentHeight += component.contentInsets.bottom
|
contentHeight += contentInsets.bottom
|
||||||
|
|
||||||
if let iconValue = component.icon {
|
if let iconValue = component.icon {
|
||||||
if previousComponent?.icon?.component.id != iconValue.component.id, let icon = self.icon {
|
if previousComponent?.icon?.component.id != iconValue.component.id, let icon = self.icon {
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public final class ListSectionContentView: UIView {
|
|||||||
|
|
||||||
public final class Configuration {
|
public final class Configuration {
|
||||||
public let theme: PresentationTheme
|
public let theme: PresentationTheme
|
||||||
|
public let style: ListSectionComponent.Style
|
||||||
public let isModal: Bool
|
public let isModal: Bool
|
||||||
public let displaySeparators: Bool
|
public let displaySeparators: Bool
|
||||||
public let extendsItemHighlightToSection: Bool
|
public let extendsItemHighlightToSection: Bool
|
||||||
@@ -48,12 +49,14 @@ public final class ListSectionContentView: UIView {
|
|||||||
|
|
||||||
public init(
|
public init(
|
||||||
theme: PresentationTheme,
|
theme: PresentationTheme,
|
||||||
|
style: ListSectionComponent.Style = .legacy,
|
||||||
isModal: Bool = false,
|
isModal: Bool = false,
|
||||||
displaySeparators: Bool,
|
displaySeparators: Bool,
|
||||||
extendsItemHighlightToSection: Bool,
|
extendsItemHighlightToSection: Bool,
|
||||||
background: ListSectionComponent.Background
|
background: ListSectionComponent.Background
|
||||||
) {
|
) {
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
|
self.style = style
|
||||||
self.isModal = isModal
|
self.isModal = isModal
|
||||||
self.displaySeparators = displaySeparators
|
self.displaySeparators = displaySeparators
|
||||||
self.extendsItemHighlightToSection = extendsItemHighlightToSection
|
self.extendsItemHighlightToSection = extendsItemHighlightToSection
|
||||||
@@ -152,6 +155,14 @@ public final class ListSectionContentView: UIView {
|
|||||||
}
|
}
|
||||||
self.externalContentBackgroundView.updateColor(color: backgroundColor, transition: transition)
|
self.externalContentBackgroundView.updateColor(color: backgroundColor, transition: transition)
|
||||||
|
|
||||||
|
let cornerRadius: CGFloat
|
||||||
|
switch configuration.style {
|
||||||
|
case .glass:
|
||||||
|
cornerRadius = 26.0
|
||||||
|
case .legacy:
|
||||||
|
cornerRadius = 11.0
|
||||||
|
}
|
||||||
|
|
||||||
var innerContentHeight: CGFloat = 0.0
|
var innerContentHeight: CGFloat = 0.0
|
||||||
var validItemIds: [AnyHashable] = []
|
var validItemIds: [AnyHashable] = []
|
||||||
for index in 0 ..< readyItems.count {
|
for index in 0 ..< readyItems.count {
|
||||||
@@ -264,18 +275,18 @@ public final class ListSectionContentView: UIView {
|
|||||||
|
|
||||||
let backgroundFrame: CGRect
|
let backgroundFrame: CGRect
|
||||||
var backgroundAlpha: CGFloat = 1.0
|
var backgroundAlpha: CGFloat = 1.0
|
||||||
var contentCornerRadius: CGFloat = 11.0
|
var contentCornerRadius: CGFloat = cornerRadius
|
||||||
switch configuration.background {
|
switch configuration.background {
|
||||||
case let .none(clipped):
|
case let .none(clipped):
|
||||||
backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: size)
|
backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: size)
|
||||||
backgroundAlpha = 0.0
|
backgroundAlpha = 0.0
|
||||||
self.externalContentBackgroundView.update(size: backgroundFrame.size, corners: DynamicCornerRadiusView.Corners(minXMinY: 11.0, maxXMinY: 11.0, minXMaxY: 11.0, maxXMaxY: 11.0), transition: transition)
|
self.externalContentBackgroundView.update(size: backgroundFrame.size, corners: DynamicCornerRadiusView.Corners(minXMinY: cornerRadius, maxXMinY: cornerRadius, minXMaxY: cornerRadius, maxXMaxY: cornerRadius), transition: transition)
|
||||||
if !clipped {
|
if !clipped {
|
||||||
contentCornerRadius = 0.0
|
contentCornerRadius = 0.0
|
||||||
}
|
}
|
||||||
case .all:
|
case .all:
|
||||||
backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: size)
|
backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: size)
|
||||||
self.externalContentBackgroundView.update(size: backgroundFrame.size, corners: DynamicCornerRadiusView.Corners(minXMinY: 11.0, maxXMinY: 11.0, minXMaxY: 11.0, maxXMaxY: 11.0), transition: transition)
|
self.externalContentBackgroundView.update(size: backgroundFrame.size, corners: DynamicCornerRadiusView.Corners(minXMinY: cornerRadius, maxXMinY: cornerRadius, minXMaxY: cornerRadius, maxXMaxY: cornerRadius), transition: transition)
|
||||||
case let .range(from, corners):
|
case let .range(from, corners):
|
||||||
if let itemView = self.itemViews[from], itemView.frame.minY < size.height {
|
if let itemView = self.itemViews[from], itemView.frame.minY < size.height {
|
||||||
backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: itemView.frame.minY), size: CGSize(width: size.width, height: size.height - itemView.frame.minY))
|
backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: itemView.frame.minY), size: CGSize(width: size.width, height: size.height - itemView.frame.minY))
|
||||||
@@ -306,7 +317,13 @@ public final class ListSectionComponent: Component {
|
|||||||
case range(from: AnyHashable, corners: DynamicCornerRadiusView.Corners)
|
case range(from: AnyHashable, corners: DynamicCornerRadiusView.Corners)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum Style {
|
||||||
|
case glass
|
||||||
|
case legacy
|
||||||
|
}
|
||||||
|
|
||||||
public let theme: PresentationTheme
|
public let theme: PresentationTheme
|
||||||
|
public let style: Style
|
||||||
public let background: Background
|
public let background: Background
|
||||||
public let header: AnyComponent<Empty>?
|
public let header: AnyComponent<Empty>?
|
||||||
public let footer: AnyComponent<Empty>?
|
public let footer: AnyComponent<Empty>?
|
||||||
@@ -317,6 +334,7 @@ public final class ListSectionComponent: Component {
|
|||||||
|
|
||||||
public init(
|
public init(
|
||||||
theme: PresentationTheme,
|
theme: PresentationTheme,
|
||||||
|
style: Style = .legacy,
|
||||||
background: Background = .all,
|
background: Background = .all,
|
||||||
header: AnyComponent<Empty>?,
|
header: AnyComponent<Empty>?,
|
||||||
footer: AnyComponent<Empty>?,
|
footer: AnyComponent<Empty>?,
|
||||||
@@ -326,6 +344,7 @@ public final class ListSectionComponent: Component {
|
|||||||
extendsItemHighlightToSection: Bool = false
|
extendsItemHighlightToSection: Bool = false
|
||||||
) {
|
) {
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
|
self.style = style
|
||||||
self.background = background
|
self.background = background
|
||||||
self.header = header
|
self.header = header
|
||||||
self.footer = footer
|
self.footer = footer
|
||||||
@@ -339,6 +358,9 @@ public final class ListSectionComponent: Component {
|
|||||||
if lhs.theme !== rhs.theme {
|
if lhs.theme !== rhs.theme {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
if lhs.style != rhs.style {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if lhs.background != rhs.background {
|
if lhs.background != rhs.background {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -464,6 +486,7 @@ public final class ListSectionComponent: Component {
|
|||||||
let contentResult = self.contentView.update(
|
let contentResult = self.contentView.update(
|
||||||
configuration: ListSectionContentView.Configuration(
|
configuration: ListSectionContentView.Configuration(
|
||||||
theme: component.theme,
|
theme: component.theme,
|
||||||
|
style: component.style,
|
||||||
isModal: component.isModal,
|
isModal: component.isModal,
|
||||||
displaySeparators: component.displaySeparators,
|
displaySeparators: component.displaySeparators,
|
||||||
extendsItemHighlightToSection: component.extendsItemHighlightToSection,
|
extendsItemHighlightToSection: component.extendsItemHighlightToSection,
|
||||||
@@ -638,6 +661,7 @@ public final class ListSubSectionComponent: Component {
|
|||||||
let contentResult = self.contentView.update(
|
let contentResult = self.contentView.update(
|
||||||
configuration: ListSectionContentView.Configuration(
|
configuration: ListSectionContentView.Configuration(
|
||||||
theme: component.theme,
|
theme: component.theme,
|
||||||
|
style: .legacy,
|
||||||
isModal: component.isModal,
|
isModal: component.isModal,
|
||||||
displaySeparators: component.displaySeparators,
|
displaySeparators: component.displaySeparators,
|
||||||
extendsItemHighlightToSection: false,
|
extendsItemHighlightToSection: false,
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ swift_library(
|
|||||||
"//submodules/TelegramUI/Components/EmojiActionIconComponent",
|
"//submodules/TelegramUI/Components/EmojiActionIconComponent",
|
||||||
"//submodules/TelegramUI/Components/TabSelectorComponent",
|
"//submodules/TelegramUI/Components/TabSelectorComponent",
|
||||||
"//submodules/TelegramUI/Components/PlainButtonComponent",
|
"//submodules/TelegramUI/Components/PlainButtonComponent",
|
||||||
|
"//submodules/TextFormat",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ import PeerNameColorItem
|
|||||||
import EmojiActionIconComponent
|
import EmojiActionIconComponent
|
||||||
import TabSelectorComponent
|
import TabSelectorComponent
|
||||||
import WallpaperResources
|
import WallpaperResources
|
||||||
|
import EdgeEffect
|
||||||
|
import TextFormat
|
||||||
|
|
||||||
private let giftListTag = GenericComponentViewTag()
|
private let giftListTag = GenericComponentViewTag()
|
||||||
|
|
||||||
@@ -143,8 +145,7 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
private let topOverscrollLayer = SimpleLayer()
|
private let topOverscrollLayer = SimpleLayer()
|
||||||
private let scrollView: ScrollView
|
private let scrollView: ScrollView
|
||||||
private let actionButton = ComponentView<Empty>()
|
private let actionButton = ComponentView<Empty>()
|
||||||
private let bottomPanelBackgroundView: BlurredBackgroundView
|
private let edgeEffectView: EdgeEffectView
|
||||||
private let bottomPanelSeparator: SimpleLayer
|
|
||||||
|
|
||||||
private let backButton = PeerInfoHeaderNavigationButton()
|
private let backButton = PeerInfoHeaderNavigationButton()
|
||||||
|
|
||||||
@@ -155,12 +156,13 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
private var currentSection: Section = .profile
|
private var currentSection: Section = .profile
|
||||||
|
|
||||||
private let previewSection = ComponentView<Empty>()
|
private let profilePreview = ComponentView<Empty>()
|
||||||
private let boostSection = ComponentView<Empty>()
|
private let profileColorSection = ComponentView<Empty>()
|
||||||
private let bannerSection = ComponentView<Empty>()
|
private let profileResetColorSection = ComponentView<Empty>()
|
||||||
private let replySection = ComponentView<Empty>()
|
|
||||||
private let resetColorSection = ComponentView<Empty>()
|
|
||||||
private let profileGiftsSection = ComponentView<Empty>()
|
private let profileGiftsSection = ComponentView<Empty>()
|
||||||
|
|
||||||
|
private let namePreview = ComponentView<Empty>()
|
||||||
|
private let nameColorSection = ComponentView<Empty>()
|
||||||
private let nameGiftsSection = ComponentView<Empty>()
|
private let nameGiftsSection = ComponentView<Empty>()
|
||||||
|
|
||||||
private var isUpdating: Bool = false
|
private var isUpdating: Bool = false
|
||||||
@@ -195,6 +197,8 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
|
|
||||||
private weak var emojiStatusSelectionController: ViewController?
|
private weak var emojiStatusSelectionController: ViewController?
|
||||||
|
|
||||||
|
private var cachedChevronImage: (UIImage, PresentationTheme)?
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
self.scrollView = ScrollView()
|
self.scrollView = ScrollView()
|
||||||
self.scrollView.showsVerticalScrollIndicator = false
|
self.scrollView.showsVerticalScrollIndicator = false
|
||||||
@@ -208,8 +212,7 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
self.scrollView.alwaysBounceVertical = true
|
self.scrollView.alwaysBounceVertical = true
|
||||||
|
|
||||||
self.bottomPanelBackgroundView = BlurredBackgroundView(color: .clear, enableBlur: true)
|
self.edgeEffectView = EdgeEffectView()
|
||||||
self.bottomPanelSeparator = SimpleLayer()
|
|
||||||
|
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
@@ -218,8 +221,7 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
|
|
||||||
self.scrollView.layer.addSublayer(self.topOverscrollLayer)
|
self.scrollView.layer.addSublayer(self.topOverscrollLayer)
|
||||||
|
|
||||||
self.addSubview(self.bottomPanelBackgroundView)
|
self.addSubview(self.edgeEffectView)
|
||||||
self.layer.addSublayer(self.bottomPanelSeparator)
|
|
||||||
|
|
||||||
self.backButton.action = { [weak self] _, _ in
|
self.backButton.action = { [weak self] _, _ in
|
||||||
if let self, let controller = self.environment?.controller() {
|
if let self, let controller = self.environment?.controller() {
|
||||||
@@ -297,16 +299,10 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
if self.scrolledUp != scrolledUp {
|
if self.scrolledUp != scrolledUp {
|
||||||
self.scrolledUp = scrolledUp
|
self.scrolledUp = scrolledUp
|
||||||
if !self.isUpdating {
|
if !self.isUpdating {
|
||||||
self.state?.updated()
|
self.state?.updated(transition: .easeInOut(duration: 0.3))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let bottomNavigationAlphaDistance: CGFloat = 16.0
|
|
||||||
let bottomNavigationAlpha: CGFloat = max(0.0, min(1.0, (self.scrollView.contentSize.height - self.scrollView.bounds.maxY) / bottomNavigationAlphaDistance))
|
|
||||||
|
|
||||||
transition.setAlpha(view: self.bottomPanelBackgroundView, alpha: bottomNavigationAlpha)
|
|
||||||
transition.setAlpha(layer: self.bottomPanelSeparator, alpha: bottomNavigationAlpha)
|
|
||||||
|
|
||||||
switch self.currentSection {
|
switch self.currentSection {
|
||||||
case .profile:
|
case .profile:
|
||||||
if let giftListView = self.profileGiftsSection.findTaggedView(tag: giftListTag) as? GiftListItemComponent.View {
|
if let giftListView = self.profileGiftsSection.findTaggedView(tag: giftListTag) as? GiftListItemComponent.View {
|
||||||
@@ -600,6 +596,9 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
switch subject {
|
switch subject {
|
||||||
case .reply:
|
case .reply:
|
||||||
|
if case .collectible = resolvedState.nameColor {
|
||||||
|
self.updatedPeerNameColor = .preset(.blue)
|
||||||
|
}
|
||||||
if let result {
|
if let result {
|
||||||
self.updatedPeerNameEmoji = result.fileId.id
|
self.updatedPeerNameEmoji = result.fileId.id
|
||||||
} else {
|
} else {
|
||||||
@@ -681,6 +680,10 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
self.backgroundColor = environment.theme.list.blocksBackgroundColor
|
self.backgroundColor = environment.theme.list.blocksBackgroundColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.cachedChevronImage == nil || self.cachedChevronImage?.1 !== environment.theme {
|
||||||
|
self.cachedChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Item List/InlineTextRightArrow"), color: environment.theme.list.itemAccentColor)!, environment.theme)
|
||||||
|
}
|
||||||
|
|
||||||
if self.contentsDataDisposable == nil {
|
if self.contentsDataDisposable == nil {
|
||||||
self.contentsDataDisposable = (ContentsData.get(context: component.context)
|
self.contentsDataDisposable = (ContentsData.get(context: component.context)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] contentsData in
|
|> deliverOnMainQueue).start(next: { [weak self] contentsData in
|
||||||
@@ -804,7 +807,7 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
if let intValue = value.base as? Int32 {
|
if let intValue = value.base as? Int32 {
|
||||||
self.currentSection = Section(rawValue: intValue) ?? .profile
|
self.currentSection = Section(rawValue: intValue) ?? .profile
|
||||||
self.state?.updated(transition: .immediate)
|
self.state?.updated(transition: .easeInOut(duration: 0.3))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -829,14 +832,20 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
|
|
||||||
var contentHeight: CGFloat = 0.0
|
var contentHeight: CGFloat = 0.0
|
||||||
|
|
||||||
let sectionTransition = transition
|
let itemCornerRadius: CGFloat = 26.0
|
||||||
|
|
||||||
let itemCornerRadius: CGFloat = 10.0
|
|
||||||
|
|
||||||
switch self.currentSection {
|
switch self.currentSection {
|
||||||
case .profile:
|
case .profile:
|
||||||
if let replySectionView = self.replySection.view, replySectionView.superview != nil {
|
var transition = transition
|
||||||
replySectionView.removeFromSuperview()
|
if self.profilePreview.view == nil {
|
||||||
|
transition = .immediate
|
||||||
|
}
|
||||||
|
|
||||||
|
if let namePreviewView = self.namePreview.view, namePreviewView.superview != nil {
|
||||||
|
namePreviewView.removeFromSuperview()
|
||||||
|
}
|
||||||
|
if let nameColorSectionView = self.nameColorSection.view, nameColorSectionView.superview != nil {
|
||||||
|
nameColorSectionView.removeFromSuperview()
|
||||||
}
|
}
|
||||||
if let nameGiftsSectionView = self.nameGiftsSection.view, nameGiftsSectionView.superview != nil {
|
if let nameGiftsSectionView = self.nameGiftsSection.view, nameGiftsSectionView.superview != nil {
|
||||||
nameGiftsSectionView.removeFromSuperview()
|
nameGiftsSectionView.removeFromSuperview()
|
||||||
@@ -850,46 +859,35 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
hasHeaderColor = true
|
hasHeaderColor = true
|
||||||
}
|
}
|
||||||
|
|
||||||
let previewSectionSize = self.previewSection.update(
|
let profilePreviewSize = self.profilePreview.update(
|
||||||
transition: sectionTransition,
|
transition: transition,
|
||||||
component: AnyComponent(ListSectionComponent(
|
component: AnyComponent(TopBottomCornersComponent(topCornerRadius: itemCornerRadius, bottomCornerRadius: !self.scrolledUp ? itemCornerRadius : 0.0, component: AnyComponent(ListItemComponentAdaptor(
|
||||||
theme: environment.theme,
|
itemGenerator: PeerNameColorProfilePreviewItem(
|
||||||
background: .none(clipped: false),
|
context: component.context,
|
||||||
header: nil,
|
theme: environment.theme,
|
||||||
footer: nil,
|
componentTheme: environment.theme,
|
||||||
items: [
|
strings: environment.strings,
|
||||||
AnyComponentWithIdentity(id: 0, component: AnyComponent(ListItemComponentAdaptor(
|
topInset: 0.0,
|
||||||
itemGenerator: PeerNameColorProfilePreviewItem(
|
sectionId: 0,
|
||||||
context: component.context,
|
peer: peer,
|
||||||
theme: environment.theme,
|
subtitleString: environment.strings.Presence_online,
|
||||||
componentTheme: environment.theme,
|
files: self.cachedIconFiles,
|
||||||
strings: environment.strings,
|
nameDisplayOrder: presentationData.nameDisplayOrder,
|
||||||
topInset: 0.0,
|
showBackground: false
|
||||||
sectionId: 0,
|
),
|
||||||
peer: peer,
|
params: ListViewItemLayoutParams(width: availableSize.width - sideInset * 2.0, leftInset: 0.0, rightInset: 0.0, availableHeight: 10000.0, isStandalone: true)
|
||||||
subtitleString: environment.strings.Presence_online,
|
)))),
|
||||||
files: self.cachedIconFiles,
|
|
||||||
nameDisplayOrder: presentationData.nameDisplayOrder,
|
|
||||||
showBackground: false
|
|
||||||
),
|
|
||||||
params: ListViewItemLayoutParams(width: availableSize.width - sideInset * 2.0, leftInset: 0.0, rightInset: 0.0, availableHeight: 10000.0, isStandalone: true)
|
|
||||||
))),
|
|
||||||
],
|
|
||||||
displaySeparators: false,
|
|
||||||
extendsItemHighlightToSection: true
|
|
||||||
)),
|
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 1000.0)
|
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 1000.0)
|
||||||
)
|
)
|
||||||
let previewSectionFrame = CGRect(origin: CGPoint(x: sideInset, y: environment.navigationHeight + 12.0), size: previewSectionSize)
|
let profilePreviewFrame = CGRect(origin: CGPoint(x: sideInset, y: environment.navigationHeight + 12.0), size: profilePreviewSize)
|
||||||
if let previewSectionView = self.previewSection.view {
|
if let profilePreviewView = self.profilePreview.view {
|
||||||
if previewSectionView.superview == nil {
|
if profilePreviewView.superview == nil {
|
||||||
self.addSubview(previewSectionView)
|
self.addSubview(profilePreviewView)
|
||||||
}
|
}
|
||||||
sectionTransition.setFrame(view: previewSectionView, frame: previewSectionFrame)
|
transition.setFrame(view: profilePreviewView, frame: profilePreviewFrame)
|
||||||
}
|
}
|
||||||
contentHeight += previewSectionSize.height
|
contentHeight += profilePreviewSize.height - 18.0
|
||||||
contentHeight += environment.navigationHeight + 12.0
|
|
||||||
|
|
||||||
var profileLogoContents: [AnyComponentWithIdentity<Empty>] = []
|
var profileLogoContents: [AnyComponentWithIdentity<Empty>] = []
|
||||||
profileLogoContents.append(AnyComponentWithIdentity(id: 0, component: AnyComponent(MultilineTextComponent(
|
profileLogoContents.append(AnyComponentWithIdentity(id: 0, component: AnyComponent(MultilineTextComponent(
|
||||||
@@ -900,15 +898,50 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
)),
|
)),
|
||||||
maximumNumberOfLines: 0
|
maximumNumberOfLines: 0
|
||||||
))))
|
))))
|
||||||
let bannerSectionSize = self.bannerSection.update(
|
|
||||||
transition: sectionTransition,
|
//TODO:localize
|
||||||
|
let footerAttributes = MarkdownAttributes(
|
||||||
|
body: MarkdownAttributeSet(font: Font.regular(13.0), textColor: environment.theme.list.freeTextColor),
|
||||||
|
bold: MarkdownAttributeSet(font: Font.semibold(13.0), textColor: environment.theme.list.freeTextColor),
|
||||||
|
link: MarkdownAttributeSet(font: Font.regular(13.0), textColor: environment.theme.list.itemAccentColor),
|
||||||
|
linkAttribute: { contents in
|
||||||
|
return (TelegramTextAttributes.URL, contents)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
let previewFooterText = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString("You can also change color of your name and customize replies to you. [Change >]()", attributes: footerAttributes))
|
||||||
|
if let range = previewFooterText.string.range(of: ">"), let chevronImage = self.cachedChevronImage?.0 {
|
||||||
|
previewFooterText.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: previewFooterText.string))
|
||||||
|
}
|
||||||
|
|
||||||
|
let profileColorSectionSize = self.profileColorSection.update(
|
||||||
|
transition: transition,
|
||||||
component: AnyComponent(ListSectionComponent(
|
component: AnyComponent(ListSectionComponent(
|
||||||
theme: environment.theme,
|
theme: environment.theme,
|
||||||
background: .range(from: 1, corners: DynamicCornerRadiusView.Corners(minXMinY: !hasHeaderColor ? itemCornerRadius : 0.0, maxXMinY: !hasHeaderColor ? itemCornerRadius : 0.0, minXMaxY: itemCornerRadius, maxXMaxY: itemCornerRadius)),
|
style: .glass,
|
||||||
|
background: .range(from: 0, corners: DynamicCornerRadiusView.Corners(minXMinY: !hasHeaderColor ? itemCornerRadius : 0.0, maxXMinY: !hasHeaderColor ? itemCornerRadius : 0.0, minXMaxY: itemCornerRadius, maxXMaxY: itemCornerRadius)),
|
||||||
header: nil,
|
header: nil,
|
||||||
footer: nil,
|
footer: AnyComponent(MultilineTextComponent(
|
||||||
|
text: .plain(previewFooterText),
|
||||||
|
maximumNumberOfLines: 0,
|
||||||
|
highlightColor: environment.theme.list.itemAccentColor.withAlphaComponent(0.1),
|
||||||
|
highlightInset: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: -8.0),
|
||||||
|
highlightAction: { attributes in
|
||||||
|
if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] {
|
||||||
|
return NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tapAction: { [weak self] _, _ in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.currentSection = .name
|
||||||
|
self.state?.updated(transition: .easeInOut(duration: 0.3))
|
||||||
|
}
|
||||||
|
)),
|
||||||
items: [
|
items: [
|
||||||
AnyComponentWithIdentity(id: 1, component: AnyComponent(ListItemComponentAdaptor(
|
AnyComponentWithIdentity(id: 0, component: AnyComponent(ListItemComponentAdaptor(
|
||||||
itemGenerator: PeerNameColorItem(
|
itemGenerator: PeerNameColorItem(
|
||||||
theme: environment.theme,
|
theme: environment.theme,
|
||||||
colors: component.context.peerNameColors,
|
colors: component.context.peerNameColors,
|
||||||
@@ -928,8 +961,9 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
),
|
),
|
||||||
params: listItemParams
|
params: listItemParams
|
||||||
))),
|
))),
|
||||||
AnyComponentWithIdentity(id: 2, component: AnyComponent(ListActionItemComponent(
|
AnyComponentWithIdentity(id: 1, component: AnyComponent(ListActionItemComponent(
|
||||||
theme: environment.theme,
|
theme: environment.theme,
|
||||||
|
style: .glass,
|
||||||
title: AnyComponent(HStack(profileLogoContents, spacing: 6.0)),
|
title: AnyComponent(HStack(profileLogoContents, spacing: 6.0)),
|
||||||
icon: ListActionItemComponent.Icon(component: AnyComponentWithIdentity(id: 0, component: AnyComponent(EmojiActionIconComponent(
|
icon: ListActionItemComponent.Icon(component: AnyComponentWithIdentity(id: 0, component: AnyComponent(EmojiActionIconComponent(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
@@ -956,25 +990,27 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 1000.0)
|
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 1000.0)
|
||||||
)
|
)
|
||||||
let bannerSectionFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: bannerSectionSize)
|
let profileColorSectionFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: profileColorSectionSize)
|
||||||
if let bannerSectionView = self.bannerSection.view {
|
if let profileColorSectionView = self.profileColorSection.view {
|
||||||
if bannerSectionView.superview == nil {
|
if profileColorSectionView.superview == nil {
|
||||||
self.scrollView.addSubview(bannerSectionView)
|
self.scrollView.addSubview(profileColorSectionView)
|
||||||
}
|
}
|
||||||
sectionTransition.setFrame(view: bannerSectionView, frame: bannerSectionFrame)
|
transition.setFrame(view: profileColorSectionView, frame: profileColorSectionFrame)
|
||||||
}
|
}
|
||||||
contentHeight += bannerSectionSize.height
|
contentHeight += profileColorSectionSize.height
|
||||||
contentHeight += sectionSpacing
|
contentHeight += sectionSpacing
|
||||||
|
|
||||||
let resetColorSectionSize = self.resetColorSection.update(
|
let profileResetColorSectionSize = self.profileResetColorSection.update(
|
||||||
transition: sectionTransition,
|
transition: transition,
|
||||||
component: AnyComponent(ListSectionComponent(
|
component: AnyComponent(ListSectionComponent(
|
||||||
theme: environment.theme,
|
theme: environment.theme,
|
||||||
|
style: .glass,
|
||||||
header: nil,
|
header: nil,
|
||||||
footer: nil,
|
footer: nil,
|
||||||
items: [
|
items: [
|
||||||
AnyComponentWithIdentity(id: 0, component: AnyComponent(ListActionItemComponent(
|
AnyComponentWithIdentity(id: 0, component: AnyComponent(ListActionItemComponent(
|
||||||
theme: environment.theme,
|
theme: environment.theme,
|
||||||
|
style: .glass,
|
||||||
title: AnyComponent(MultilineTextComponent(
|
title: AnyComponent(MultilineTextComponent(
|
||||||
text: .plain(NSAttributedString(
|
text: .plain(NSAttributedString(
|
||||||
string: environment.strings.Channel_Appearance_ResetProfileColor,
|
string: environment.strings.Channel_Appearance_ResetProfileColor,
|
||||||
@@ -1011,18 +1047,18 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
displayResetProfileColor = true
|
displayResetProfileColor = true
|
||||||
}
|
}
|
||||||
|
|
||||||
let resetColorSectionFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: resetColorSectionSize)
|
let profileResetColorSectionFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: profileResetColorSectionSize)
|
||||||
if let resetColorSectionView = self.resetColorSection.view {
|
if let profileResetColorSectionView = self.profileResetColorSection.view {
|
||||||
if resetColorSectionView.superview == nil {
|
if profileResetColorSectionView.superview == nil {
|
||||||
self.scrollView.addSubview(resetColorSectionView)
|
self.scrollView.addSubview(profileResetColorSectionView)
|
||||||
}
|
}
|
||||||
sectionTransition.setPosition(view: resetColorSectionView, position: resetColorSectionFrame.center)
|
transition.setPosition(view: profileResetColorSectionView, position: profileResetColorSectionFrame.center)
|
||||||
sectionTransition.setBounds(view: resetColorSectionView, bounds: CGRect(origin: CGPoint(), size: resetColorSectionFrame.size))
|
transition.setBounds(view: profileResetColorSectionView, bounds: CGRect(origin: CGPoint(), size: profileResetColorSectionFrame.size))
|
||||||
sectionTransition.setScale(view: resetColorSectionView, scale: displayResetProfileColor ? 1.0 : 0.001)
|
transition.setScale(view: profileResetColorSectionView, scale: displayResetProfileColor ? 1.0 : 0.001)
|
||||||
sectionTransition.setAlpha(view: resetColorSectionView, alpha: displayResetProfileColor ? 1.0 : 0.0)
|
transition.setAlpha(view: profileResetColorSectionView, alpha: displayResetProfileColor ? 1.0 : 0.0)
|
||||||
}
|
}
|
||||||
if displayResetProfileColor {
|
if displayResetProfileColor {
|
||||||
contentHeight += resetColorSectionSize.height
|
contentHeight += profileResetColorSectionSize.height
|
||||||
contentHeight += sectionSpacing
|
contentHeight += sectionSpacing
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1032,9 +1068,10 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
selectedGiftId = id
|
selectedGiftId = id
|
||||||
}
|
}
|
||||||
let giftsSectionSize = self.profileGiftsSection.update(
|
let giftsSectionSize = self.profileGiftsSection.update(
|
||||||
transition: sectionTransition,
|
transition: transition,
|
||||||
component: AnyComponent(ListSectionComponent(
|
component: AnyComponent(ListSectionComponent(
|
||||||
theme: environment.theme,
|
theme: environment.theme,
|
||||||
|
style: .glass,
|
||||||
header: AnyComponent(MultilineTextComponent(
|
header: AnyComponent(MultilineTextComponent(
|
||||||
text: .plain(NSAttributedString(
|
text: .plain(NSAttributedString(
|
||||||
string: environment.strings.NameColor_GiftTitle,
|
string: environment.strings.NameColor_GiftTitle,
|
||||||
@@ -1106,19 +1143,24 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
if giftsSectionView.superview == nil {
|
if giftsSectionView.superview == nil {
|
||||||
self.scrollView.addSubview(giftsSectionView)
|
self.scrollView.addSubview(giftsSectionView)
|
||||||
}
|
}
|
||||||
sectionTransition.setFrame(view: giftsSectionView, frame: giftsSectionFrame)
|
transition.setFrame(view: giftsSectionView, frame: giftsSectionFrame)
|
||||||
}
|
}
|
||||||
contentHeight += giftsSectionSize.height
|
contentHeight += giftsSectionSize.height
|
||||||
contentHeight += sectionSpacing
|
contentHeight += sectionSpacing
|
||||||
}
|
}
|
||||||
case .name:
|
case .name:
|
||||||
if let previewSectionView = self.previewSection.view, previewSectionView.superview != nil {
|
var transition = transition
|
||||||
previewSectionView.removeFromSuperview()
|
if self.namePreview.view == nil {
|
||||||
|
transition = .immediate
|
||||||
}
|
}
|
||||||
if let bannerSectionView = self.bannerSection.view, bannerSectionView.superview != nil {
|
|
||||||
bannerSectionView.removeFromSuperview()
|
if let profilePreviewView = self.profilePreview.view, profilePreviewView.superview != nil {
|
||||||
|
profilePreviewView.removeFromSuperview()
|
||||||
}
|
}
|
||||||
if let resetColorSectionView = self.resetColorSection.view, resetColorSectionView.superview != nil {
|
if let profileColorSectionView = self.profileColorSection.view, profileColorSectionView.superview != nil {
|
||||||
|
profileColorSectionView.removeFromSuperview()
|
||||||
|
}
|
||||||
|
if let resetColorSectionView = self.profileResetColorSection.view, resetColorSectionView.superview != nil {
|
||||||
resetColorSectionView.removeFromSuperview()
|
resetColorSectionView.removeFromSuperview()
|
||||||
}
|
}
|
||||||
if let profileGiftsSectionView = self.profileGiftsSection.view, profileGiftsSectionView.superview != nil {
|
if let profileGiftsSectionView = self.profileGiftsSection.view, profileGiftsSectionView.superview != nil {
|
||||||
@@ -1165,10 +1207,42 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
replyColor = collectibleColor.mainColor(dark: environment.theme.overallDarkAppearance)
|
replyColor = collectibleColor.mainColor(dark: environment.theme.overallDarkAppearance)
|
||||||
}
|
}
|
||||||
|
|
||||||
let replySectionSize = self.replySection.update(
|
let namePreviewSize = self.namePreview.update(
|
||||||
transition: sectionTransition,
|
transition: transition,
|
||||||
|
component: AnyComponent(TopBottomCornersComponent(topCornerRadius: itemCornerRadius, bottomCornerRadius: !self.scrolledUp ? itemCornerRadius : 0.0, component: AnyComponent(ListItemComponentAdaptor(
|
||||||
|
itemGenerator: PeerNameColorChatPreviewItem(
|
||||||
|
context: component.context,
|
||||||
|
theme: chatPreviewTheme,
|
||||||
|
componentTheme: chatPreviewTheme,
|
||||||
|
strings: environment.strings,
|
||||||
|
sectionId: 0,
|
||||||
|
fontSize: presentationData.chatFontSize,
|
||||||
|
chatBubbleCorners: presentationData.chatBubbleCorners,
|
||||||
|
wallpaper: chatPreviewWallpaper,
|
||||||
|
dateTimeFormat: environment.dateTimeFormat,
|
||||||
|
nameDisplayOrder: presentationData.nameDisplayOrder,
|
||||||
|
messageItems: [messageItem]
|
||||||
|
),
|
||||||
|
params: ListViewItemLayoutParams(width: availableSize.width - sideInset * 2.0, leftInset: 0.0, rightInset: 0.0, availableHeight: 10000.0, isStandalone: true)
|
||||||
|
)))),
|
||||||
|
environment: {},
|
||||||
|
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 1000.0)
|
||||||
|
)
|
||||||
|
let namePreviewFrame = CGRect(origin: CGPoint(x: sideInset, y: environment.navigationHeight + 12.0), size: namePreviewSize)
|
||||||
|
if let namePreviewView = self.namePreview.view {
|
||||||
|
if namePreviewView.superview == nil {
|
||||||
|
self.addSubview(namePreviewView)
|
||||||
|
}
|
||||||
|
transition.setFrame(view: namePreviewView, frame: namePreviewFrame)
|
||||||
|
}
|
||||||
|
contentHeight += namePreviewSize.height - 18.0
|
||||||
|
|
||||||
|
let nameColorSectionSize = self.nameColorSection.update(
|
||||||
|
transition: transition,
|
||||||
component: AnyComponent(ListSectionComponent(
|
component: AnyComponent(ListSectionComponent(
|
||||||
theme: environment.theme,
|
theme: environment.theme,
|
||||||
|
style: .glass,
|
||||||
|
background: .range(from: 0, corners: DynamicCornerRadiusView.Corners(minXMinY: 0.0, maxXMinY: 0.0, minXMaxY: itemCornerRadius, maxXMaxY: itemCornerRadius)),
|
||||||
header: nil,
|
header: nil,
|
||||||
footer: AnyComponent(MultilineTextComponent(
|
footer: AnyComponent(MultilineTextComponent(
|
||||||
text: .plain(NSAttributedString(
|
text: .plain(NSAttributedString(
|
||||||
@@ -1180,31 +1254,18 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
)),
|
)),
|
||||||
items: [
|
items: [
|
||||||
AnyComponentWithIdentity(id: 0, component: AnyComponent(ListItemComponentAdaptor(
|
AnyComponentWithIdentity(id: 0, component: AnyComponent(ListItemComponentAdaptor(
|
||||||
itemGenerator: PeerNameColorChatPreviewItem(
|
|
||||||
context: component.context,
|
|
||||||
theme: chatPreviewTheme,
|
|
||||||
componentTheme: chatPreviewTheme,
|
|
||||||
strings: environment.strings,
|
|
||||||
sectionId: 0,
|
|
||||||
fontSize: presentationData.chatFontSize,
|
|
||||||
chatBubbleCorners: presentationData.chatBubbleCorners,
|
|
||||||
wallpaper: chatPreviewWallpaper,
|
|
||||||
dateTimeFormat: environment.dateTimeFormat,
|
|
||||||
nameDisplayOrder: presentationData.nameDisplayOrder,
|
|
||||||
messageItems: [messageItem]
|
|
||||||
),
|
|
||||||
params: listItemParams
|
|
||||||
))),
|
|
||||||
AnyComponentWithIdentity(id: 1, component: AnyComponent(ListItemComponentAdaptor(
|
|
||||||
itemGenerator: PeerNameColorItem(
|
itemGenerator: PeerNameColorItem(
|
||||||
theme: environment.theme,
|
theme: environment.theme,
|
||||||
colors: component.context.peerNameColors,
|
colors: component.context.peerNameColors,
|
||||||
mode: .name,
|
mode: .name,
|
||||||
currentColor: resolvedState.nameColor.nameColor,
|
currentColor: resolvedState.nameColor.nameColor,
|
||||||
updated: { [weak self] value in
|
updated: { [weak self] value in
|
||||||
guard let self, let value else {
|
guard let self, let resolvedState = self.resolveState(), let value else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if case .collectible = resolvedState.nameColor {
|
||||||
|
self.updatedPeerNameEmoji = .some(nil)
|
||||||
|
}
|
||||||
self.updatedPeerNameColor = .preset(value)
|
self.updatedPeerNameColor = .preset(value)
|
||||||
self.state?.updated(transition: .spring(duration: 0.4))
|
self.state?.updated(transition: .spring(duration: 0.4))
|
||||||
},
|
},
|
||||||
@@ -1212,8 +1273,9 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
),
|
),
|
||||||
params: listItemParams
|
params: listItemParams
|
||||||
))),
|
))),
|
||||||
AnyComponentWithIdentity(id: 2, component: AnyComponent(ListActionItemComponent(
|
AnyComponentWithIdentity(id: 1, component: AnyComponent(ListActionItemComponent(
|
||||||
theme: environment.theme,
|
theme: environment.theme,
|
||||||
|
style: .glass,
|
||||||
title: AnyComponent(HStack(replyLogoContents, spacing: 6.0)),
|
title: AnyComponent(HStack(replyLogoContents, spacing: 6.0)),
|
||||||
icon: ListActionItemComponent.Icon(component: AnyComponentWithIdentity(id: 0, component: AnyComponent(EmojiActionIconComponent(
|
icon: ListActionItemComponent.Icon(component: AnyComponentWithIdentity(id: 0, component: AnyComponent(EmojiActionIconComponent(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
@@ -1236,14 +1298,14 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 1000.0)
|
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 1000.0)
|
||||||
)
|
)
|
||||||
let replySectionFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: replySectionSize)
|
let nameColorSectionFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: nameColorSectionSize)
|
||||||
if let replySectionView = self.replySection.view {
|
if let nameColorSectionView = self.nameColorSection.view {
|
||||||
if replySectionView.superview == nil {
|
if nameColorSectionView.superview == nil {
|
||||||
self.scrollView.addSubview(replySectionView)
|
self.scrollView.addSubview(nameColorSectionView)
|
||||||
}
|
}
|
||||||
sectionTransition.setFrame(view: replySectionView, frame: replySectionFrame)
|
transition.setFrame(view: nameColorSectionView, frame: nameColorSectionFrame)
|
||||||
}
|
}
|
||||||
contentHeight += replySectionSize.height
|
contentHeight += nameColorSectionSize.height
|
||||||
contentHeight += sectionSpacing
|
contentHeight += sectionSpacing
|
||||||
|
|
||||||
if !self.starGifts.isEmpty {
|
if !self.starGifts.isEmpty {
|
||||||
@@ -1252,9 +1314,10 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
selectedGiftId = collectibleColor.collectibleId
|
selectedGiftId = collectibleColor.collectibleId
|
||||||
}
|
}
|
||||||
let giftsSectionSize = self.nameGiftsSection.update(
|
let giftsSectionSize = self.nameGiftsSection.update(
|
||||||
transition: sectionTransition,
|
transition: transition,
|
||||||
component: AnyComponent(ListSectionComponent(
|
component: AnyComponent(ListSectionComponent(
|
||||||
theme: environment.theme,
|
theme: environment.theme,
|
||||||
|
style: .glass,
|
||||||
header: AnyComponent(MultilineTextComponent(
|
header: AnyComponent(MultilineTextComponent(
|
||||||
text: .plain(NSAttributedString(
|
text: .plain(NSAttributedString(
|
||||||
string: environment.strings.NameColor_GiftTitle,
|
string: environment.strings.NameColor_GiftTitle,
|
||||||
@@ -1284,6 +1347,7 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.updatedPeerNameColor = .collectible(peerColor)
|
self.updatedPeerNameColor = .collectible(peerColor)
|
||||||
|
self.updatedPeerNameEmoji = peerColor.backgroundEmojiId
|
||||||
self.state?.updated(transition: .spring(duration: 0.4))
|
self.state?.updated(transition: .spring(duration: 0.4))
|
||||||
},
|
},
|
||||||
tag: giftListTag
|
tag: giftListTag
|
||||||
@@ -1300,7 +1364,7 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
if giftsSectionView.superview == nil {
|
if giftsSectionView.superview == nil {
|
||||||
self.scrollView.addSubview(giftsSectionView)
|
self.scrollView.addSubview(giftsSectionView)
|
||||||
}
|
}
|
||||||
sectionTransition.setFrame(view: giftsSectionView, frame: giftsSectionFrame)
|
transition.setFrame(view: giftsSectionView, frame: giftsSectionFrame)
|
||||||
}
|
}
|
||||||
contentHeight += giftsSectionSize.height
|
contentHeight += giftsSectionSize.height
|
||||||
contentHeight += sectionSpacing
|
contentHeight += sectionSpacing
|
||||||
@@ -1309,10 +1373,12 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
|
|
||||||
contentHeight += bottomContentInset
|
contentHeight += bottomContentInset
|
||||||
|
|
||||||
var buttonTitle = environment.strings.Channel_Appearance_ApplyButton
|
//TODO:localize
|
||||||
if let emojiStatus = resolvedState.emojiStatus, case .starGift = emojiStatus.content, resolvedState.changes.contains(.emojiStatus) {
|
let buttonSideInset: CGFloat = 36.0
|
||||||
buttonTitle = environment.strings.NameColor_WearCollectible
|
let buttonTitle = "Apply Style" // environment.strings.Channel_Appearance_ApplyButton
|
||||||
}
|
// if let emojiStatus = resolvedState.emojiStatus, case .starGift = emojiStatus.content, resolvedState.changes.contains(.emojiStatus) {
|
||||||
|
// buttonTitle = environment.strings.NameColor_WearCollectible
|
||||||
|
// }
|
||||||
|
|
||||||
var buttonContents: [AnyComponentWithIdentity<Empty>] = []
|
var buttonContents: [AnyComponentWithIdentity<Empty>] = []
|
||||||
buttonContents.append(AnyComponentWithIdentity(id: AnyHashable(buttonTitle), component: AnyComponent(
|
buttonContents.append(AnyComponentWithIdentity(id: AnyHashable(buttonTitle), component: AnyComponent(
|
||||||
@@ -1323,6 +1389,7 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
transition: transition,
|
transition: transition,
|
||||||
component: AnyComponent(ButtonComponent(
|
component: AnyComponent(ButtonComponent(
|
||||||
background: ButtonComponent.Background(
|
background: ButtonComponent.Background(
|
||||||
|
style: .glass,
|
||||||
color: environment.theme.list.itemCheckColors.fillColor,
|
color: environment.theme.list.itemCheckColors.fillColor,
|
||||||
foreground: environment.theme.list.itemCheckColors.foregroundColor,
|
foreground: environment.theme.list.itemCheckColors.foregroundColor,
|
||||||
pressedColor: environment.theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.8)
|
pressedColor: environment.theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.8)
|
||||||
@@ -1341,7 +1408,7 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 50.0)
|
containerSize: CGSize(width: availableSize.width - buttonSideInset * 2.0, height: 52.0)
|
||||||
)
|
)
|
||||||
contentHeight += buttonSize.height
|
contentHeight += buttonSize.height
|
||||||
|
|
||||||
@@ -1350,7 +1417,7 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
|
|
||||||
let buttonY = availableSize.height - bottomInset - environment.safeInsets.bottom - buttonSize.height
|
let buttonY = availableSize.height - bottomInset - environment.safeInsets.bottom - buttonSize.height
|
||||||
|
|
||||||
let buttonFrame = CGRect(origin: CGPoint(x: sideInset, y: buttonY), size: buttonSize)
|
let buttonFrame = CGRect(origin: CGPoint(x: buttonSideInset, y: buttonY), size: buttonSize)
|
||||||
if let buttonView = self.actionButton.view {
|
if let buttonView = self.actionButton.view {
|
||||||
if buttonView.superview == nil {
|
if buttonView.superview == nil {
|
||||||
self.addSubview(buttonView)
|
self.addSubview(buttonView)
|
||||||
@@ -1359,26 +1426,24 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
transition.setAlpha(view: buttonView, alpha: 1.0)
|
transition.setAlpha(view: buttonView, alpha: 1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
let bottomPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: buttonY - 8.0), size: CGSize(width: availableSize.width, height: availableSize.height - buttonY + 8.0))
|
let edgeEffectHeight: CGFloat = availableSize.height - buttonY + 8.0
|
||||||
transition.setFrame(view: self.bottomPanelBackgroundView, frame: bottomPanelFrame)
|
let edgeEffectFrame = CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - edgeEffectHeight), size: CGSize(width: availableSize.width, height: edgeEffectHeight))
|
||||||
self.bottomPanelBackgroundView.updateColor(color: environment.theme.rootController.navigationBar.blurredBackgroundColor, transition: .immediate)
|
transition.setFrame(view: self.edgeEffectView, frame: edgeEffectFrame)
|
||||||
self.bottomPanelBackgroundView.update(size: bottomPanelFrame.size, transition: transition.containedViewLayoutTransition)
|
self.edgeEffectView.update(content: environment.theme.list.blocksBackgroundColor, isInverted: false, rect: edgeEffectFrame, edge: .bottom, edgeSize: edgeEffectFrame.height, containerSize: availableSize, transition: transition)
|
||||||
|
|
||||||
self.bottomPanelSeparator.backgroundColor = environment.theme.rootController.navigationBar.separatorColor.cgColor
|
|
||||||
transition.setFrame(layer: self.bottomPanelSeparator, frame: CGRect(origin: CGPoint(x: bottomPanelFrame.minX, y: bottomPanelFrame.minY), size: CGSize(width: bottomPanelFrame.width, height: UIScreenPixel)))
|
|
||||||
|
|
||||||
let previousBounds = self.scrollView.bounds
|
let previousBounds = self.scrollView.bounds
|
||||||
let contentSize = CGSize(width: availableSize.width, height: contentHeight)
|
let contentSize = CGSize(width: availableSize.width, height: contentHeight)
|
||||||
if self.scrollView.frame != CGRect(origin: CGPoint(), size: availableSize) {
|
let scrollViewFrame = CGRect(origin: CGPoint(x: 0.0, y: environment.navigationHeight + 30.0), size: CGSize(width: availableSize.width, height: availableSize.height - environment.navigationHeight - 30.0))
|
||||||
self.scrollView.frame = CGRect(origin: CGPoint(), size: availableSize)
|
if self.scrollView.frame != scrollViewFrame {
|
||||||
|
self.scrollView.frame = scrollViewFrame
|
||||||
}
|
}
|
||||||
if self.scrollView.contentSize != contentSize {
|
if self.scrollView.contentSize != contentSize {
|
||||||
self.scrollView.contentSize = contentSize
|
self.scrollView.contentSize = contentSize
|
||||||
}
|
}
|
||||||
let scrollInsets = UIEdgeInsets(top: environment.navigationHeight, left: 0.0, bottom: availableSize.height - bottomPanelFrame.minY, right: 0.0)
|
// let scrollInsets = UIEdgeInsets(top: 0.0, left: 0.0, bottom: availableSize.height - bottomPanelFrame.minY, right: 0.0)
|
||||||
if self.scrollView.verticalScrollIndicatorInsets != scrollInsets {
|
// if self.scrollView.verticalScrollIndicatorInsets != scrollInsets {
|
||||||
self.scrollView.verticalScrollIndicatorInsets = scrollInsets
|
// self.scrollView.verticalScrollIndicatorInsets = scrollInsets
|
||||||
}
|
// }
|
||||||
|
|
||||||
if !previousBounds.isEmpty, !transition.animation.isImmediate {
|
if !previousBounds.isEmpty, !transition.animation.isImmediate {
|
||||||
let bounds = self.scrollView.bounds
|
let bounds = self.scrollView.bounds
|
||||||
@@ -1388,7 +1453,8 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.topOverscrollLayer.frame = CGRect(origin: CGPoint(x: 0.0, y: -3000.0), size: CGSize(width: availableSize.width, height: 3000.0))
|
self.topOverscrollLayer.backgroundColor = environment.theme.list.itemBlocksBackgroundColor.cgColor
|
||||||
|
self.topOverscrollLayer.frame = CGRect(origin: CGPoint(x: sideInset, y: -1000.0), size: CGSize(width: availableSize.width - sideInset * 2.0, height: 1315.0))
|
||||||
|
|
||||||
self.updateScrolling(transition: transition)
|
self.updateScrolling(transition: transition)
|
||||||
|
|
||||||
@@ -1397,7 +1463,7 @@ final class UserAppearanceScreenComponent: Component {
|
|||||||
size: availableSize,
|
size: availableSize,
|
||||||
metrics: environment.metrics,
|
metrics: environment.metrics,
|
||||||
deviceMetrics: environment.deviceMetrics,
|
deviceMetrics: environment.deviceMetrics,
|
||||||
intrinsicInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: bottomPanelFrame.height, right: 0.0),
|
intrinsicInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: edgeEffectHeight, right: 0.0),
|
||||||
safeInsets: UIEdgeInsets(top: 0.0, left: environment.safeInsets.left, bottom: 0.0, right: environment.safeInsets.right),
|
safeInsets: UIEdgeInsets(top: 0.0, left: environment.safeInsets.left, bottom: 0.0, right: environment.safeInsets.right),
|
||||||
additionalInsets: .zero,
|
additionalInsets: .zero,
|
||||||
statusBarHeight: environment.statusBarHeight,
|
statusBarHeight: environment.statusBarHeight,
|
||||||
@@ -1494,3 +1560,79 @@ private extension PeerColor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
final class TopBottomCornersComponent: Component {
|
||||||
|
private let topCornerRadius: CGFloat
|
||||||
|
private let bottomCornerRadius: CGFloat
|
||||||
|
private let component: AnyComponent<Empty>
|
||||||
|
|
||||||
|
public init(
|
||||||
|
topCornerRadius: CGFloat,
|
||||||
|
bottomCornerRadius: CGFloat,
|
||||||
|
component: AnyComponent<Empty>
|
||||||
|
) {
|
||||||
|
self.topCornerRadius = topCornerRadius
|
||||||
|
self.bottomCornerRadius = bottomCornerRadius
|
||||||
|
self.component = component
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func == (lhs: TopBottomCornersComponent, rhs: TopBottomCornersComponent) -> Bool {
|
||||||
|
if lhs.topCornerRadius != rhs.topCornerRadius {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.bottomCornerRadius != rhs.bottomCornerRadius {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.component != rhs.component {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class View: UIView {
|
||||||
|
private let containerView: UIView
|
||||||
|
private let hostView: ComponentHostView<Empty>
|
||||||
|
|
||||||
|
public override init(frame: CGRect) {
|
||||||
|
self.containerView = UIView()
|
||||||
|
self.hostView = ComponentHostView<Empty>()
|
||||||
|
|
||||||
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
self.clipsToBounds = true
|
||||||
|
self.containerView.clipsToBounds = true
|
||||||
|
|
||||||
|
self.addSubview(self.containerView)
|
||||||
|
self.containerView.addSubview(self.hostView)
|
||||||
|
}
|
||||||
|
|
||||||
|
public required init?(coder: NSCoder) {
|
||||||
|
preconditionFailure()
|
||||||
|
}
|
||||||
|
|
||||||
|
func update(component: TopBottomCornersComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<Empty>, transition: ComponentTransition) -> CGSize {
|
||||||
|
|
||||||
|
let size = self.hostView.update(
|
||||||
|
transition: transition,
|
||||||
|
component: component.component,
|
||||||
|
environment: {},
|
||||||
|
containerSize: availableSize
|
||||||
|
)
|
||||||
|
|
||||||
|
transition.setCornerRadius(layer: self.containerView.layer, cornerRadius: component.topCornerRadius)
|
||||||
|
transition.setCornerRadius(layer: self.layer, cornerRadius: component.bottomCornerRadius)
|
||||||
|
transition.setFrame(view: self.containerView, frame: CGRect(origin: .zero, size: CGSize(width: availableSize.width, height: availableSize.height + component.bottomCornerRadius)))
|
||||||
|
|
||||||
|
return size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public func makeView() -> View {
|
||||||
|
return View()
|
||||||
|
}
|
||||||
|
|
||||||
|
public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment<EnvironmentType>, transition: ComponentTransition) -> CGSize {
|
||||||
|
return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -590,6 +590,7 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
|
|||||||
let flipButtonBackground = flipButtonBackground.update(
|
let flipButtonBackground = flipButtonBackground.update(
|
||||||
component: GlassBackgroundComponent(
|
component: GlassBackgroundComponent(
|
||||||
size: CGSize(width: 40.0, height: 40.0),
|
size: CGSize(width: 40.0, height: 40.0),
|
||||||
|
isDark: true,
|
||||||
tintColor: .init(kind: .panel, color: environment.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7))
|
tintColor: .init(kind: .panel, color: environment.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7))
|
||||||
),
|
),
|
||||||
availableSize: CGSize(width: 40.0, height: 40.0),
|
availableSize: CGSize(width: 40.0, height: 40.0),
|
||||||
@@ -691,6 +692,7 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
|
|||||||
let flashButtonBackground = flashButtonBackground.update(
|
let flashButtonBackground = flashButtonBackground.update(
|
||||||
component: GlassBackgroundComponent(
|
component: GlassBackgroundComponent(
|
||||||
size: CGSize(width: 40.0, height: 40.0),
|
size: CGSize(width: 40.0, height: 40.0),
|
||||||
|
isDark: true,
|
||||||
tintColor: .init(kind: .panel, color: environment.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7))
|
tintColor: .init(kind: .panel, color: environment.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7))
|
||||||
),
|
),
|
||||||
availableSize: CGSize(width: 40.0, height: 40.0),
|
availableSize: CGSize(width: 40.0, height: 40.0),
|
||||||
@@ -764,6 +766,7 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
|
|||||||
id: "background",
|
id: "background",
|
||||||
component: AnyComponent(GlassBackgroundComponent(
|
component: AnyComponent(GlassBackgroundComponent(
|
||||||
size: CGSize(width: 40.0, height: 40.0),
|
size: CGSize(width: 40.0, height: 40.0),
|
||||||
|
isDark: true,
|
||||||
tintColor: .init(kind: .panel, color: environment.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7))
|
tintColor: .init(kind: .panel, color: environment.theme.chat.inputPanel.inputBackgroundColor.withMultipliedAlpha(0.7))
|
||||||
))
|
))
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user