Voice Chat UI fixes

This commit is contained in:
Ilya Laktyushin 2020-12-14 19:37:37 +04:00
parent ae2bf3b908
commit 85a74c2ff2
10 changed files with 145 additions and 94 deletions

View File

@ -7,6 +7,7 @@ public protocol ChatListController: ViewController {
var context: AccountContext { get } var context: AccountContext { get }
var lockViewFrame: CGRect? { get } var lockViewFrame: CGRect? { get }
var isSearchActive: Bool { get }
func activateSearch() func activateSearch()
func deactivateSearch(animated: Bool) func deactivateSearch(animated: Bool)
func activateCompose() func activateCompose()

View File

@ -84,9 +84,13 @@ public final class VoiceBlobView: UIView, TGModernConversationInputMicButtonDeco
} }
public func setColor(_ color: UIColor) { public func setColor(_ color: UIColor) {
smallBlob.setColor(color) self.setColor(color, animated: false)
mediumBlob.setColor(color.withAlphaComponent(0.3)) }
bigBlob.setColor(color.withAlphaComponent(0.15))
public func setColor(_ color: UIColor, animated: Bool) {
smallBlob.setColor(color, animated: animated)
mediumBlob.setColor(color.withAlphaComponent(0.3), animated: animated)
bigBlob.setColor(color.withAlphaComponent(0.15), animated: animated)
} }
public func updateLevel(_ level: CGFloat) { public func updateLevel(_ level: CGFloat) {
@ -250,8 +254,12 @@ final class BlobView: UIView {
fatalError("init(coder:) has not been implemented") fatalError("init(coder:) has not been implemented")
} }
func setColor(_ color: UIColor) { func setColor(_ color: UIColor, animated: Bool) {
let previousColor = shapeLayer.fillColor
shapeLayer.fillColor = color.cgColor shapeLayer.fillColor = color.cgColor
if animated, let previousColor = previousColor {
shapeLayer.animate(from: previousColor, to: color.cgColor, keyPath: "fillColor", timingFunction: CAMediaTimingFunctionName.linear.rawValue, duration: 0.3)
}
} }
func updateSpeedLevel(to newSpeedLevel: CGFloat) { func updateSpeedLevel(to newSpeedLevel: CGFloat) {

View File

@ -1678,6 +1678,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
self.present(actionSheet, in: .window(.root)) self.present(actionSheet, in: .window(.root))
} }
public private(set) var isSearchActive: Bool = false
public func activateSearch() { public func activateSearch() {
if self.displayNavigationBar { if self.displayNavigationBar {
let _ = (combineLatest(self.chatListDisplayNode.containerNode.currentItemNode.contentsReady |> take(1), self.context.account.postbox.tailChatListView(groupId: .root, count: 16, summaryComponents: ChatListEntrySummaryComponents(tagSummary: nil, actionsSummary: nil)) |> take(1)) let _ = (combineLatest(self.chatListDisplayNode.containerNode.currentItemNode.contentsReady |> take(1), self.context.account.postbox.tailChatListView(groupId: .root, count: 16, summaryComponents: ChatListEntrySummaryComponents(tagSummary: nil, actionsSummary: nil)) |> take(1))
@ -1729,18 +1730,14 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
(strongSelf.parent as? TabBarController)?.updateIsTabBarHidden(true, transition: .animated(duration: 0.4, curve: .spring)) (strongSelf.parent as? TabBarController)?.updateIsTabBarHidden(true, transition: .animated(duration: 0.4, curve: .spring))
}) })
self.isSearchActive = true
if let navigationController = self.navigationController as? NavigationController { if let navigationController = self.navigationController as? NavigationController {
var voiceChatOverlayController: VoiceChatOverlayController?
for controller in navigationController.globalOverlayControllers { for controller in navigationController.globalOverlayControllers {
if let controller = controller as? VoiceChatOverlayController { if let controller = controller as? VoiceChatOverlayController {
voiceChatOverlayController = controller controller.updateVisibility()
break break
} }
} }
if let controller = voiceChatOverlayController {
controller.update(hidden: true, slide: true, animated: true)
}
} }
} }
} }
@ -1785,18 +1782,14 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
} }
} }
self.isSearchActive = false
if let navigationController = self.navigationController as? NavigationController { if let navigationController = self.navigationController as? NavigationController {
var voiceChatOverlayController: VoiceChatOverlayController?
for controller in navigationController.globalOverlayControllers { for controller in navigationController.globalOverlayControllers {
if let controller = controller as? VoiceChatOverlayController { if let controller = controller as? VoiceChatOverlayController {
voiceChatOverlayController = controller controller.updateVisibility()
break break
} }
} }
if let controller = voiceChatOverlayController {
controller.update(hidden: false, slide: true, animated: true)
}
} }
} }
} }

View File

@ -611,10 +611,7 @@ open class NavigationController: UINavigationController, ContainableController,
} }
} }
} }
layout.additionalInsets.left = max(layout.intrinsicInsets.left, additionalSideInsets.left)
layout.additionalInsets.right = max(layout.intrinsicInsets.right, additionalSideInsets.right)
if self.currentTopVisibleOverlayContainerStatusBar !== topVisibleOverlayContainerWithStatusBar { if self.currentTopVisibleOverlayContainerStatusBar !== topVisibleOverlayContainerWithStatusBar {
animateStatusBarStyleTransition = true animateStatusBarStyleTransition = true
self.currentTopVisibleOverlayContainerStatusBar = topVisibleOverlayContainerWithStatusBar self.currentTopVisibleOverlayContainerStatusBar = topVisibleOverlayContainerWithStatusBar
@ -722,6 +719,9 @@ open class NavigationController: UINavigationController, ContainableController,
} }
} }
layout.additionalInsets.left = max(layout.intrinsicInsets.left, additionalSideInsets.left)
layout.additionalInsets.right = max(layout.intrinsicInsets.right, additionalSideInsets.right)
switch navigationLayout.root { switch navigationLayout.root {
case let .flat(controllers): case let .flat(controllers):
if let rootContainer = self.rootContainer { if let rootContainer = self.rootContainer {

View File

@ -94,7 +94,7 @@ final class NavigationSplitContainer: ASDisplayNode {
transition.updateFrame(node: self.detailContainer, frame: CGRect(origin: CGPoint(x: masterWidth, y: 0.0), size: CGSize(width: detailWidth, height: layout.size.height))) transition.updateFrame(node: self.detailContainer, frame: CGRect(origin: CGPoint(x: masterWidth, y: 0.0), size: CGSize(width: detailWidth, height: layout.size.height)))
transition.updateFrame(node: self.separator, frame: CGRect(origin: CGPoint(x: masterWidth, y: 0.0), size: CGSize(width: UIScreenPixel, height: layout.size.height))) transition.updateFrame(node: self.separator, frame: CGRect(origin: CGPoint(x: masterWidth, y: 0.0), size: CGSize(width: UIScreenPixel, height: layout.size.height)))
self.masterContainer.update(layout: ContainerViewLayout(size: CGSize(width: masterWidth, height: layout.size.height), metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: layout.intrinsicInsets, safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), canBeClosed: false, controllers: masterControllers, transition: transition) self.masterContainer.update(layout: ContainerViewLayout(size: CGSize(width: masterWidth, height: layout.size.height), metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: layout.intrinsicInsets, safeInsets: layout.safeInsets, additionalInsets: UIEdgeInsets(), statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), canBeClosed: false, controllers: masterControllers, transition: transition)
self.detailContainer.update(layout: ContainerViewLayout(size: CGSize(width: detailWidth, height: layout.size.height), metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: layout.intrinsicInsets, safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), canBeClosed: true, controllers: detailControllers, transition: transition) self.detailContainer.update(layout: ContainerViewLayout(size: CGSize(width: detailWidth, height: layout.size.height), metrics: layout.metrics, deviceMetrics: layout.deviceMetrics, intrinsicInsets: layout.intrinsicInsets, safeInsets: layout.safeInsets, additionalInsets: layout.additionalInsets, statusBarHeight: layout.statusBarHeight, inputHeight: layout.inputHeight, inputHeightIsInteractivellyChanging: layout.inputHeightIsInteractivellyChanging, inVoiceOver: layout.inVoiceOver), canBeClosed: true, controllers: detailControllers, transition: transition)
var controllersUpdated = false var controllersUpdated = false

View File

@ -278,7 +278,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
var audioLevels: [(PeerId, Float, Bool)] = [] var audioLevels: [(PeerId, Float, Bool)] = []
for (peerId, level, hasVoice) in levels { for (peerId, level, hasVoice) in levels {
if level > 0.1 { if level > 0.001 {
audioLevels.append((peerId, level, hasVoice)) audioLevels.append((peerId, level, hasVoice))
} }
} }

View File

@ -1291,7 +1291,13 @@ public final class VoiceChatController: ViewController {
let listTopInset = layoutTopInset + topPanelHeight let listTopInset = layoutTopInset + topPanelHeight
let bottomAreaHeight: CGFloat = 268.0 let bottomAreaHeight: CGFloat = 268.0
let bottomPanelHeight = bottomAreaHeight + layout.intrinsicInsets.bottom let bottomPanelHeight = bottomAreaHeight + layout.intrinsicInsets.bottom
let listSize = CGSize(width: layout.size.width, height: layout.size.height - listTopInset - bottomPanelHeight)
var size = layout.size
if case .regular = layout.metrics.widthClass {
size.width = floor(min(size.width, size.height) * 0.5)
}
let listSize = CGSize(width: size.width, height: layout.size.height - listTopInset - bottomPanelHeight)
let topInset: CGFloat let topInset: CGFloat
if let (panInitialTopInset, panOffset) = self.panGestureArguments { if let (panInitialTopInset, panOffset) = self.panGestureArguments {
if self.isExpanded { if self.isExpanded {
@ -1312,12 +1318,12 @@ public final class VoiceChatController: ViewController {
let rawPanelOffset = offset + listTopInset - topPanelHeight let rawPanelOffset = offset + listTopInset - topPanelHeight
let panelOffset = max(layoutTopInset, rawPanelOffset) let panelOffset = max(layoutTopInset, rawPanelOffset)
let topPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: panelOffset), size: CGSize(width: layout.size.width, height: topPanelHeight)) let topPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: panelOffset), size: CGSize(width: size.width, height: topPanelHeight))
let backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: topPanelFrame.maxY), size: CGSize(width: layout.size.width, height: layout.size.height)) let backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: topPanelFrame.maxY), size: CGSize(width: size.width, height: layout.size.height))
let sideInset: CGFloat = 16.0 let sideInset: CGFloat = 16.0
let leftBorderFrame = CGRect(origin: CGPoint(x: 0.0, y: topPanelFrame.maxY - 16.0), size: CGSize(width: sideInset, height: layout.size.height)) let leftBorderFrame = CGRect(origin: CGPoint(x: 0.0, y: topPanelFrame.maxY - 16.0), size: CGSize(width: sideInset, height: layout.size.height))
let rightBorderFrame = CGRect(origin: CGPoint(x: layout.size.width - sideInset, y: topPanelFrame.maxY - 16.0), size: CGSize(width: sideInset, height: layout.size.height)) let rightBorderFrame = CGRect(origin: CGPoint(x: size.width - sideInset, y: topPanelFrame.maxY - 16.0), size: CGSize(width: sideInset, height: layout.size.height))
let previousTopPanelFrame = self.topPanelNode.frame let previousTopPanelFrame = self.topPanelNode.frame
let previousBackgroundFrame = self.backgroundNode.frame let previousBackgroundFrame = self.backgroundNode.frame
@ -1343,7 +1349,7 @@ public final class VoiceChatController: ViewController {
} else { } else {
completion?() completion?()
} }
self.topPanelBackgroundNode.frame = CGRect(x: 0.0, y: topPanelHeight - 24.0, width: layout.size.width, height: 24.0) self.topPanelBackgroundNode.frame = CGRect(x: 0.0, y: topPanelHeight - 24.0, width: size.width, height: 24.0)
var bottomEdge: CGFloat = 0.0 var bottomEdge: CGFloat = 0.0
self.listNode.forEachItemNode { itemNode in self.listNode.forEachItemNode { itemNode in
@ -1364,11 +1370,11 @@ public final class VoiceChatController: ViewController {
bottomOffset = bottomEdge - listMaxY bottomOffset = bottomEdge - listMaxY
} }
let bottomCornersFrame = CGRect(origin: CGPoint(x: sideInset, y: -50.0 + bottomOffset), size: CGSize(width: layout.size.width - sideInset * 2.0, height: 50.0)) let bottomCornersFrame = CGRect(origin: CGPoint(x: sideInset, y: -50.0 + bottomOffset), size: CGSize(width: size.width - sideInset * 2.0, height: 50.0))
let previousBottomCornersFrame = self.bottomCornersNode.frame let previousBottomCornersFrame = self.bottomCornersNode.frame
if !bottomCornersFrame.equalTo(previousBottomCornersFrame) { if !bottomCornersFrame.equalTo(previousBottomCornersFrame) {
self.bottomCornersNode.frame = bottomCornersFrame self.bottomCornersNode.frame = bottomCornersFrame
self.bottomPanelBackgroundNode.frame = CGRect(x: 0.0, y: bottomOffset, width: layout.size.width, height: 2000.0) self.bottomPanelBackgroundNode.frame = CGRect(x: 0.0, y: bottomOffset, width: size.width, height: 2000.0)
let positionDelta = CGPoint(x: 0.0, y: previousBottomCornersFrame.minY - bottomCornersFrame.minY) let positionDelta = CGPoint(x: 0.0, y: previousBottomCornersFrame.minY - bottomCornersFrame.minY)
transition.animatePositionAdditive(node: self.bottomCornersNode, offset: positionDelta) transition.animatePositionAdditive(node: self.bottomCornersNode, offset: positionDelta)
@ -1385,6 +1391,11 @@ public final class VoiceChatController: ViewController {
self.controller?.statusBar.statusBarStyle = isFullscreen ? .White : .Ignore self.controller?.statusBar.statusBarStyle = isFullscreen ? .White : .Ignore
var size = layout.size
if case .regular = layout.metrics.widthClass {
size.width = floor(min(size.width, size.height) * 0.5)
}
let topPanelHeight: CGFloat = 63.0 let topPanelHeight: CGFloat = 63.0
let topEdgeFrame: CGRect let topEdgeFrame: CGRect
if isFullscreen { if isFullscreen {
@ -1394,9 +1405,9 @@ public final class VoiceChatController: ViewController {
} else { } else {
offset = 44.0 offset = 44.0
} }
topEdgeFrame = CGRect(x: 0.0, y: -offset, width: layout.size.width, height: topPanelHeight + offset) topEdgeFrame = CGRect(x: 0.0, y: -offset, width: size.width, height: topPanelHeight + offset)
} else { } else {
topEdgeFrame = CGRect(x: 0.0, y: 0.0, width: layout.size.width, height: topPanelHeight) topEdgeFrame = CGRect(x: 0.0, y: 0.0, width: size.width, height: topPanelHeight)
} }
let transition: ContainedViewLayoutTransition = .animated(duration: 0.3, curve: .linear) let transition: ContainedViewLayoutTransition = .animated(duration: 0.3, curve: .linear)
@ -1451,7 +1462,12 @@ public final class VoiceChatController: ViewController {
} }
} }
self.titleNode.update(size: CGSize(width: layout.size.width, height: 44.0), title: title, subtitle: self.currentSubtitle, transition: transition) var size = layout.size
if case .regular = layout.metrics.widthClass {
size.width = floor(min(size.width, size.height) * 0.5)
}
self.titleNode.update(size: CGSize(width: size.width, height: 44.0), title: title, subtitle: self.currentSubtitle, transition: transition)
} }
private func updateButtons(transition: ContainedViewLayoutTransition) { private func updateButtons(transition: ContainedViewLayoutTransition) {
@ -1522,14 +1538,19 @@ public final class VoiceChatController: ViewController {
let isFirstTime = self.validLayout == nil let isFirstTime = self.validLayout == nil
self.validLayout = (layout, navigationHeight) self.validLayout = (layout, navigationHeight)
var size = layout.size
if case .regular = layout.metrics.widthClass {
size.width = floor(min(size.width, size.height) * 0.5)
}
self.updateTitle(transition: transition) self.updateTitle(transition: transition)
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 10.0), size: CGSize(width: layout.size.width, height: 44.0))) transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: 0.0, y: 10.0), size: CGSize(width: size.width, height: 44.0)))
transition.updateFrame(node: self.optionsButton, frame: CGRect(origin: CGPoint(x: 20.0, y: 18.0), size: CGSize(width: 28.0, height: 28.0))) transition.updateFrame(node: self.optionsButton, frame: CGRect(origin: CGPoint(x: 20.0, y: 18.0), size: CGSize(width: 28.0, height: 28.0)))
transition.updateFrame(node: self.closeButton, frame: CGRect(origin: CGPoint(x: layout.size.width - 20.0 - 28.0, y: 18.0), size: CGSize(width: 28.0, height: 28.0))) transition.updateFrame(node: self.closeButton, frame: CGRect(origin: CGPoint(x: size.width - 20.0 - 28.0, y: 18.0), size: CGSize(width: 28.0, height: 28.0)))
transition.updateFrame(node: self.dimNode, frame: CGRect(origin: CGPoint(), size: layout.size)) transition.updateFrame(node: self.dimNode, frame: CGRect(origin: CGPoint(), size: layout.size))
transition.updateFrame(node: self.contentContainer, frame: CGRect(origin: CGPoint(), size: layout.size)) transition.updateFrame(node: self.contentContainer, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - size.width) / 2.0), y: 0.0), size: size))
let bottomAreaHeight: CGFloat = 268.0 let bottomAreaHeight: CGFloat = 268.0
let layoutTopInset: CGFloat = max(layout.statusBarHeight ?? 0.0, layout.safeInsets.top) let layoutTopInset: CGFloat = max(layout.statusBarHeight ?? 0.0, layout.safeInsets.top)
@ -1550,16 +1571,16 @@ public final class VoiceChatController: ViewController {
} else { } else {
offset = 44.0 offset = 44.0
} }
topEdgeFrame = CGRect(x: 0.0, y: -offset, width: layout.size.width, height: topPanelHeight + offset) topEdgeFrame = CGRect(x: 0.0, y: -offset, width: size.width, height: topPanelHeight + offset)
} else { } else {
topEdgeFrame = CGRect(x: 0.0, y: 0.0, width: layout.size.width, height: topPanelHeight) topEdgeFrame = CGRect(x: 0.0, y: 0.0, width: size.width, height: topPanelHeight)
} }
transition.updateFrame(node: self.topPanelEdgeNode, frame: topEdgeFrame) transition.updateFrame(node: self.topPanelEdgeNode, frame: topEdgeFrame)
} }
let bottomPanelHeight = bottomAreaHeight + layout.intrinsicInsets.bottom let bottomPanelHeight = bottomAreaHeight + layout.intrinsicInsets.bottom
let listTopInset = layoutTopInset + topPanelHeight let listTopInset = layoutTopInset + topPanelHeight
let listSize = CGSize(width: layout.size.width, height: layout.size.height - listTopInset - bottomPanelHeight) let listSize = CGSize(width: size.width, height: layout.size.height - listTopInset - bottomPanelHeight)
let topInset: CGFloat let topInset: CGFloat
if let (panInitialTopInset, panOffset) = self.panGestureArguments { if let (panInitialTopInset, panOffset) = self.panGestureArguments {
@ -1583,15 +1604,15 @@ public final class VoiceChatController: ViewController {
self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: nil, updateSizeAndInsets: updateSizeAndInsets, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: nil, updateSizeAndInsets: updateSizeAndInsets, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
transition.updateFrame(node: self.topCornersNode, frame: CGRect(origin: CGPoint(x: sideInset, y: 63.0), size: CGSize(width: layout.size.width - sideInset * 2.0, height: 50.0))) transition.updateFrame(node: self.topCornersNode, frame: CGRect(origin: CGPoint(x: sideInset, y: 63.0), size: CGSize(width: size.width - sideInset * 2.0, height: 50.0)))
let bottomPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - bottomPanelHeight), size: CGSize(width: layout.size.width, height: bottomPanelHeight)) let bottomPanelFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - bottomPanelHeight), size: CGSize(width: size.width, height: bottomPanelHeight))
transition.updateFrame(node: self.bottomPanelNode, frame: bottomPanelFrame) transition.updateFrame(node: self.bottomPanelNode, frame: bottomPanelFrame)
let sideButtonSize = CGSize(width: 60.0, height: 60.0) let sideButtonSize = CGSize(width: 60.0, height: 60.0)
let centralButtonSize = CGSize(width: 440.0, height: 440.0) let centralButtonSize = CGSize(width: 440.0, height: 440.0)
let actionButtonFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - centralButtonSize.width) / 2.0), y: floorToScreenPixels((bottomAreaHeight - centralButtonSize.height) / 2.0)), size: centralButtonSize) let actionButtonFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - centralButtonSize.width) / 2.0), y: floorToScreenPixels((bottomAreaHeight - centralButtonSize.height) / 2.0)), size: centralButtonSize)
let actionButtonState: VoiceChatActionButton.State let actionButtonState: VoiceChatActionButton.State
let actionButtonTitle: String let actionButtonTitle: String
@ -1632,7 +1653,7 @@ public final class VoiceChatController: ViewController {
} }
self.actionButton.isDisabled = !actionButtonEnabled self.actionButton.isDisabled = !actionButtonEnabled
self.actionButton.update(size: centralButtonSize, buttonSize: CGSize(width: 144.0, height: 144.0), state: actionButtonState, title: actionButtonTitle, subtitle: actionButtonSubtitle, dark: self.isFullscreen, small: layout.size.width < 330.0, animated: true) self.actionButton.update(size: centralButtonSize, buttonSize: CGSize(width: 144.0, height: 144.0), state: actionButtonState, title: actionButtonTitle, subtitle: actionButtonSubtitle, dark: self.isFullscreen, small: size.width < 330.0, animated: true)
if self.actionButton.supernode === self.bottomPanelNode { if self.actionButton.supernode === self.bottomPanelNode {
transition.updateFrame(node: self.actionButton, frame: actionButtonFrame) transition.updateFrame(node: self.actionButton, frame: actionButtonFrame)
@ -1641,12 +1662,12 @@ public final class VoiceChatController: ViewController {
self.updateButtons(transition: transition) self.updateButtons(transition: transition)
let sideButtonMinimalInset: CGFloat = 16.0 let sideButtonMinimalInset: CGFloat = 16.0
let sideButtonOffset = min(36.0, floor((((layout.size.width - 144.0) / 2.0) - sideButtonSize.width) / 2.0)) let sideButtonOffset = min(36.0, floor((((size.width - 144.0) / 2.0) - sideButtonSize.width) / 2.0))
let sideButtonOrigin = max(sideButtonMinimalInset, floor((layout.size.width - 144.0) / 2.0) - sideButtonOffset - sideButtonSize.width) let sideButtonOrigin = max(sideButtonMinimalInset, floor((size.width - 144.0) / 2.0) - sideButtonOffset - sideButtonSize.width)
if self.audioOutputNode.supernode === self.bottomPanelNode { if self.audioOutputNode.supernode === self.bottomPanelNode {
transition.updateFrame(node: self.audioOutputNode, frame: CGRect(origin: CGPoint(x: sideButtonOrigin, y: floor((bottomAreaHeight - sideButtonSize.height) / 2.0)), size: sideButtonSize)) transition.updateFrame(node: self.audioOutputNode, frame: CGRect(origin: CGPoint(x: sideButtonOrigin, y: floor((bottomAreaHeight - sideButtonSize.height) / 2.0)), size: sideButtonSize))
transition.updateFrame(node: self.leaveNode, frame: CGRect(origin: CGPoint(x: layout.size.width - sideButtonOrigin - sideButtonSize.width, y: floor((bottomAreaHeight - sideButtonSize.height) / 2.0)), size: sideButtonSize)) transition.updateFrame(node: self.leaveNode, frame: CGRect(origin: CGPoint(x: size.width - sideButtonOrigin - sideButtonSize.width, y: floor((bottomAreaHeight - sideButtonSize.height) / 2.0)), size: sideButtonSize))
} }
if isFirstTime { if isFirstTime {
while !self.enqueuedTransitions.isEmpty { while !self.enqueuedTransitions.isEmpty {
@ -1757,9 +1778,14 @@ public final class VoiceChatController: ViewController {
insets.left = layout.safeInsets.left + sideInset insets.left = layout.safeInsets.left + sideInset
insets.right = layout.safeInsets.right + sideInset insets.right = layout.safeInsets.right + sideInset
var size = layout.size
if case .regular = layout.metrics.widthClass {
size.width = floor(min(size.width, size.height) * 0.5)
}
let bottomPanelHeight = bottomAreaHeight + layout.intrinsicInsets.bottom let bottomPanelHeight = bottomAreaHeight + layout.intrinsicInsets.bottom
let listTopInset = layoutTopInset + 63.0 let listTopInset = layoutTopInset + 63.0
let listSize = CGSize(width: layout.size.width, height: layout.size.height - listTopInset - bottomPanelHeight) let listSize = CGSize(width: size.width, height: layout.size.height - listTopInset - bottomPanelHeight)
self.topInset = max(0.0, max(listSize.height - itemsHeight, listSize.height - 46.0 - floor(56.0 * 3.5))) self.topInset = max(0.0, max(listSize.height - itemsHeight, listSize.height - 46.0 - floor(56.0 * 3.5)))
@ -2224,6 +2250,7 @@ public final class VoiceChatController: ViewController {
if count == 2 || navigationController.viewControllers[count - 2] is ChatController { if count == 2 || navigationController.viewControllers[count - 2] is ChatController {
if case .active(.cantSpeak) = self.controllerNode.actionButton.stateValue { if case .active(.cantSpeak) = self.controllerNode.actionButton.stateValue {
} else if let chatController = navigationController.viewControllers[count - 2] as? ChatController, chatController.isSendButtonVisible { } else if let chatController = navigationController.viewControllers[count - 2] as? ChatController, chatController.isSendButtonVisible {
} else if let tabBarController = navigationController.viewControllers[count - 2] as? TabBarController, let chatListController = tabBarController.controllers[tabBarController.selectedIndex] as? ChatListController, chatListController.isSearchActive {
} else { } else {
self.detachActionButton() self.detachActionButton()
} }

View File

@ -292,11 +292,15 @@ public final class VoiceChatOverlayController: ViewController {
} }
private var disposable: Disposable? private var disposable: Disposable?
private weak var parentNavigationController: NavigationController?
private var currentParams: ([UIViewController], [UIViewController], VoiceChatActionButton.State)?
init(actionButton: VoiceChatActionButton, audioOutputNode: CallControllerButtonItemNode, leaveNode: CallControllerButtonItemNode, navigationController: NavigationController?) { init(actionButton: VoiceChatActionButton, audioOutputNode: CallControllerButtonItemNode, leaveNode: CallControllerButtonItemNode, navigationController: NavigationController?) {
self.actionButton = actionButton self.actionButton = actionButton
self.audioOutputNode = audioOutputNode self.audioOutputNode = audioOutputNode
self.leaveNode = leaveNode self.leaveNode = leaveNode
self.parentNavigationController = navigationController
super.init(navigationBarPresentationData: nil) super.init(navigationBarPresentationData: nil)
@ -314,51 +318,8 @@ public final class VoiceChatOverlayController: ViewController {
self.disposable = (combineLatest(queue: Queue.mainQueue(), controllers, overlayControllers, actionButton.state)).start(next: { [weak self] controllers, overlayControllers, state in self.disposable = (combineLatest(queue: Queue.mainQueue(), controllers, overlayControllers, actionButton.state)).start(next: { [weak self] controllers, overlayControllers, state in
if let strongSelf = self { if let strongSelf = self {
var hasVoiceChatController = false strongSelf.currentParams = (controllers, overlayControllers, state)
var overlayControllersCount = 0 strongSelf.updateVisibility()
for controller in controllers {
if controller is VoiceChatController {
hasVoiceChatController = true
}
}
for controller in overlayControllers {
if controller is TooltipController || controller is TooltipScreen || controller is AlertController {
} else {
overlayControllersCount += 1
}
}
var slide = true
var hidden = true
var animated = true
if controllers.count == 1 || controllers.last is ChatController {
if let chatController = controllers.last as? ChatController, chatController.isSendButtonVisible {
slide = false
animated = false
} else {
hidden = false
}
}
if overlayControllersCount > 0 {
hidden = true
}
if case .active(.cantSpeak) = state {
hidden = true
}
if hasVoiceChatController {
hidden = false
animated = false
}
strongSelf.controllerNode.update(hidden: hidden, slide: slide, animated: animated)
let previousInsets = strongSelf.additionalSideInsets
strongSelf.additionalSideInsets = hidden ? UIEdgeInsets() : UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 75.0)
if previousInsets != strongSelf.additionalSideInsets {
navigationController.requestLayout(transition: .animated(duration: 0.3, curve: .easeInOut))
}
} }
}) })
} }
@ -387,7 +348,64 @@ public final class VoiceChatOverlayController: ViewController {
self.controllerNode.animateOut(reclaim: reclaim, completion: completion) self.controllerNode.animateOut(reclaim: reclaim, completion: completion)
} }
public func updateVisibility() {
guard let (controllers, overlayControllers, state) = self.currentParams else {
return
}
var hasVoiceChatController = false
var overlayControllersCount = 0
for controller in controllers {
if controller is VoiceChatController {
hasVoiceChatController = true
}
}
for controller in overlayControllers {
if controller is TooltipController || controller is TooltipScreen || controller is AlertController {
} else {
overlayControllersCount += 1
}
}
var slide = true
var hidden = true
var animated = true
if controllers.count == 1 || controllers.last is ChatController {
if let chatController = controllers.last as? ChatController, chatController.isSendButtonVisible {
slide = false
} else {
hidden = false
}
}
if let tabBarController = controllers.last as? TabBarController {
if let chatListController = tabBarController.controllers[tabBarController.selectedIndex] as? ChatListController, chatListController.isSearchActive {
hidden = true
}
}
if overlayControllersCount > 0 {
hidden = true
}
if case .active(.cantSpeak) = state {
hidden = true
}
if hasVoiceChatController {
hidden = false
animated = false
}
self.controllerNode.update(hidden: hidden, slide: slide, animated: animated)
let previousInsets = self.additionalSideInsets
self.additionalSideInsets = hidden ? UIEdgeInsets() : UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 75.0)
if previousInsets != self.additionalSideInsets {
self.parentNavigationController?.requestLayout(transition: .animated(duration: 0.3, curve: .easeInOut))
}
}
private let hiddenPromise = ValuePromise<Bool>()
public func update(hidden: Bool, slide: Bool, animated: Bool) { public func update(hidden: Bool, slide: Bool, animated: Bool) {
self.hiddenPromise.set(hidden)
self.controllerNode.update(hidden: hidden, slide: slide, animated: animated) self.controllerNode.update(hidden: hidden, slide: slide, animated: animated)
} }

View File

@ -334,6 +334,7 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
titleAttributedString = NSAttributedString(string: channel.title, font: currentBoldFont, textColor: titleColor) titleAttributedString = NSAttributedString(string: channel.title, font: currentBoldFont, textColor: titleColor)
} }
var wavesColor = UIColor(rgb: 0x34c759)
switch item.text { switch item.text {
case .presence: case .presence:
if let user = item.peer as? TelegramUser, let botInfo = user.botInfo { if let user = item.peer as? TelegramUser, let botInfo = user.botInfo {
@ -358,6 +359,7 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
textColorValue = item.presentationData.theme.list.itemSecondaryTextColor textColorValue = item.presentationData.theme.list.itemSecondaryTextColor
case .accent: case .accent:
textColorValue = item.presentationData.theme.list.itemAccentColor textColorValue = item.presentationData.theme.list.itemAccentColor
wavesColor = textColorValue
case .constructive: case .constructive:
textColorValue = UIColor(rgb: 0x34c759) textColorValue = UIColor(rgb: 0x34c759)
} }
@ -561,7 +563,7 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
playbackMaskLayer.path = maskPath.cgPath playbackMaskLayer.path = maskPath.cgPath
audioLevelView.layer.mask = playbackMaskLayer audioLevelView.layer.mask = playbackMaskLayer
audioLevelView.setColor(UIColor(rgb: 0x34c759)) audioLevelView.setColor(wavesColor)
strongSelf.audioLevelView = audioLevelView strongSelf.audioLevelView = audioLevelView
strongSelf.offsetContainerNode.view.insertSubview(audioLevelView, at: 0) strongSelf.offsetContainerNode.view.insertSubview(audioLevelView, at: 0)
} }
@ -574,10 +576,12 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode {
if value > 0.0 { if value > 0.0 {
audioLevelView.startAnimating() audioLevelView.startAnimating()
avatarScale = 1.03 + level * 0.13 avatarScale = 1.03 + level * 0.13
audioLevelView.setColor(wavesColor, animated: true)
} else { } else {
audioLevelView.stopAnimating(duration: 0.5) audioLevelView.stopAnimating(duration: 0.5)
avatarScale = 1.0 avatarScale = 1.0
} }
print(value)
let transition: ContainedViewLayoutTransition = .animated(duration: 0.15, curve: .easeInOut) let transition: ContainedViewLayoutTransition = .animated(duration: 0.15, curve: .easeInOut)
transition.updateTransformScale(node: strongSelf.avatarNode, scale: avatarScale, beginWithCurrentState: true) transition.updateTransformScale(node: strongSelf.avatarNode, scale: avatarScale, beginWithCurrentState: true)

View File

@ -7083,7 +7083,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
if let controller = voiceChatOverlayController { if let controller = voiceChatOverlayController {
controller.update(hidden: self.isSendButtonVisible, slide: false, animated: true) controller.updateVisibility()
} }
} }
} }