mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Voice chat UI fixes
This commit is contained in:
parent
42834133f8
commit
1e10a74871
@ -5988,7 +5988,7 @@ Sorry for the inconvenience.";
|
||||
|
||||
"CHAT_VOICECHAT_START" = "%1$@ has started voice chat in the group %2$@";
|
||||
"CHAT_VOICECHAT_INVITE" = "%1$@ has invited %3$@ in the group %2$@";
|
||||
"CHAT_VOICECHAT_INVITE_YOU" = "%1$@ has invited you to voice chat in the group %1$@";
|
||||
"CHAT_VOICECHAT_INVITE_YOU" = "%1$@ has invited you to voice chat in the group %2$@";
|
||||
|
||||
"Call.VoiceChatInProgressTitle" = "Voice Chat in Progress";
|
||||
"Call.VoiceChatInProgressMessageCall" = "Leave voice chat in %1$@ and start a call with %2$@?";
|
||||
|
@ -1361,7 +1361,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
animateOnline = true
|
||||
} else if let channel = renderedPeer.peer as? TelegramChannel {
|
||||
onlineIsVoiceChat = true
|
||||
if channel.flags.contains(.hasVoiceChat) && item.interaction.searchTextHighightState == nil {
|
||||
if channel.flags.contains(.hasActiveVoiceChat) && item.interaction.searchTextHighightState == nil {
|
||||
online = true
|
||||
}
|
||||
animateOnline = true
|
||||
|
@ -140,6 +140,7 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
|
||||
var inCallNavigate: (() -> Void)?
|
||||
private var inCallStatusBar: StatusBar?
|
||||
private var updateInCallStatusBarState: CallStatusBarNode?
|
||||
private var globalScrollToTopNode: ScrollToTopNode?
|
||||
private var rootContainer: RootContainer?
|
||||
private var rootModalFrame: NavigationModalFrame?
|
||||
@ -406,6 +407,11 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
inCallStatusBar.callStatusBarNode?.frame = inCallStatusBarFrame
|
||||
layout.statusBarHeight = inCallStatusBarFrame.height
|
||||
inCallStatusBar.frame = inCallStatusBarFrame
|
||||
|
||||
if let forceInCallStatusBar = self.updateInCallStatusBarState {
|
||||
self.updateInCallStatusBarState = nil
|
||||
inCallStatusBar.updateState(statusBar: nil, withSafeInsets: !layout.safeInsets.top.isZero, inCallNode: forceInCallStatusBar, animated: false)
|
||||
}
|
||||
}
|
||||
|
||||
if let globalOverlayContainerParent = self.globalOverlayContainerParent {
|
||||
@ -1409,6 +1415,8 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
if let layout = self.validLayout {
|
||||
inCallStatusBar.updateState(statusBar: nil, withSafeInsets: !layout.safeInsets.top.isZero, inCallNode: forceInCallStatusBar, animated: false)
|
||||
self.containerLayoutUpdated(layout, transition: transition)
|
||||
} else {
|
||||
self.updateInCallStatusBarState = forceInCallStatusBar
|
||||
}
|
||||
} else if let inCallStatusBar = self.inCallStatusBar {
|
||||
self.inCallStatusBar = nil
|
||||
|
@ -333,8 +333,7 @@ final class NavigationModalContainer: ASDisplayNode, UIScrollViewDelegate, UIGes
|
||||
let containerLayout: ContainerViewLayout
|
||||
let containerFrame: CGRect
|
||||
let containerScale: CGFloat
|
||||
switch layout.metrics.widthClass {
|
||||
case .compact:
|
||||
if layout.metrics.widthClass == .compact || self.isFlat {
|
||||
self.panRecognizer?.isEnabled = true
|
||||
self.container.clipsToBounds = true
|
||||
if self.isFlat {
|
||||
@ -387,7 +386,7 @@ final class NavigationModalContainer: ASDisplayNode, UIScrollViewDelegate, UIGes
|
||||
let scaledTopInset: CGFloat = topInset * (1.0 - coveredByModalTransition) + maxScaledTopInset * coveredByModalTransition
|
||||
containerFrame = unscaledFrame.offsetBy(dx: 0.0, dy: scaledTopInset - (unscaledFrame.midY - containerScale * unscaledFrame.height / 2.0))
|
||||
}
|
||||
case .regular:
|
||||
} else {
|
||||
self.panRecognizer?.isEnabled = false
|
||||
if self.isFlat {
|
||||
self.dim.backgroundColor = .clear
|
||||
|
@ -142,6 +142,7 @@ public struct TelegramChannelFlags: OptionSet {
|
||||
public static let isScam = TelegramChannelFlags(rawValue: 1 << 2)
|
||||
public static let hasGeo = TelegramChannelFlags(rawValue: 1 << 3)
|
||||
public static let hasVoiceChat = TelegramChannelFlags(rawValue: 1 << 4)
|
||||
public static let hasActiveVoiceChat = TelegramChannelFlags(rawValue: 1 << 5)
|
||||
}
|
||||
|
||||
public final class TelegramChannel: Peer {
|
||||
@ -298,4 +299,8 @@ public final class TelegramChannel: Peer {
|
||||
public func withUpdatedDefaultBannedRights(_ defaultBannedRights: TelegramChatBannedRights?) -> TelegramChannel {
|
||||
return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: self.flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: defaultBannedRights)
|
||||
}
|
||||
|
||||
public func withUpdatedFlags(_ flags: TelegramChannelFlags) -> TelegramChannel {
|
||||
return TelegramChannel(id: self.id, accessHash: self.accessHash, title: self.title, username: self.username, photo: self.photo, creationDate: self.creationDate, version: self.version, participationStatus: self.participationStatus, info: self.info, flags: flags, restrictionInfo: self.restrictionInfo, adminRights: self.adminRights, bannedRights: self.bannedRights, defaultBannedRights: self.defaultBannedRights)
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ swift_library(
|
||||
"//submodules/AlertUI:AlertUI",
|
||||
"//submodules/DirectionalPanGesture:DirectionalPanGesture",
|
||||
"//submodules/PeerInfoUI:PeerInfoUI",
|
||||
"//submodules/DeviceProximity:DeviceProximity",
|
||||
],
|
||||
visibility = [
|
||||
"//visibility:public",
|
||||
|
@ -404,7 +404,7 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
|
||||
}
|
||||
|
||||
if let (size, leftInset, rightInset) = self.validLayout {
|
||||
self.updateLayout(size: size, leftInset: leftInset, rightInset: rightInset, transition: .immediate)
|
||||
self.updateLayout(size: size, leftInset: leftInset, rightInset: rightInset, transition: .animated(duration: 0.2, curve: .easeInOut))
|
||||
}
|
||||
|
||||
if updateAudioLevels {
|
||||
@ -448,6 +448,8 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
|
||||
public func updateLayout(size: CGSize, leftInset: CGFloat, rightInset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
self.validLayout = (size, leftInset, rightInset)
|
||||
|
||||
let staticTransition: ContainedViewLayoutTransition = .immediate
|
||||
|
||||
let panelHeight = size.height
|
||||
|
||||
transition.updateFrame(node: self.contentNode, frame: CGRect(origin: CGPoint(), size: size))
|
||||
@ -462,17 +464,17 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
|
||||
let joinButtonTitleSize = self.joinButtonTitleNode.updateLayout(CGSize(width: 150.0, height: .greatestFiniteMagnitude))
|
||||
let joinButtonSize = CGSize(width: joinButtonTitleSize.width + 20.0, height: 28.0)
|
||||
let joinButtonFrame = CGRect(origin: CGPoint(x: size.width - rightInset - 7.0 - joinButtonSize.width, y: floor((panelHeight - joinButtonSize.height) / 2.0)), size: joinButtonSize)
|
||||
transition.updateFrame(node: self.joinButton, frame: joinButtonFrame)
|
||||
transition.updateFrame(node: self.joinButtonBackgroundNode, frame: CGRect(origin: CGPoint(), size: joinButtonFrame.size))
|
||||
transition.updateFrame(node: self.joinButtonTitleNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((joinButtonFrame.width - joinButtonTitleSize.width) / 2.0), y: floorToScreenPixels((joinButtonFrame.height - joinButtonTitleSize.height) / 2.0)), size: joinButtonTitleSize))
|
||||
staticTransition.updateFrame(node: self.joinButton, frame: joinButtonFrame)
|
||||
staticTransition.updateFrame(node: self.joinButtonBackgroundNode, frame: CGRect(origin: CGPoint(), size: joinButtonFrame.size))
|
||||
staticTransition.updateFrame(node: self.joinButtonTitleNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((joinButtonFrame.width - joinButtonTitleSize.width) / 2.0), y: floorToScreenPixels((joinButtonFrame.height - joinButtonTitleSize.height) / 2.0)), size: joinButtonTitleSize))
|
||||
|
||||
let micButtonSize = CGSize(width: 36.0, height: 36.0)
|
||||
let micButtonFrame = CGRect(origin: CGPoint(x: size.width - rightInset - 7.0 - micButtonSize.width, y: floor((panelHeight - micButtonSize.height) / 2.0)), size: micButtonSize)
|
||||
transition.updateFrame(node: self.micButton, frame: micButtonFrame)
|
||||
transition.updateFrame(node: self.micButtonBackgroundNode, frame: CGRect(origin: CGPoint(), size: micButtonFrame.size))
|
||||
staticTransition.updateFrame(node: self.micButton, frame: micButtonFrame)
|
||||
staticTransition.updateFrame(node: self.micButtonBackgroundNode, frame: CGRect(origin: CGPoint(), size: micButtonFrame.size))
|
||||
|
||||
let animationSize = CGSize(width: 36.0, height: 36.0)
|
||||
transition.updateFrame(node: self.micButtonForegroundNode, frame: CGRect(origin: CGPoint(x: floor((micButtonFrame.width - animationSize.width) / 2.0), y: floor((micButtonFrame.height - animationSize.height) / 2.0)), size: animationSize))
|
||||
staticTransition.updateFrame(node: self.micButtonForegroundNode, frame: CGRect(origin: CGPoint(x: floor((micButtonFrame.width - animationSize.width) / 2.0), y: floor((micButtonFrame.height - animationSize.height) / 2.0)), size: animationSize))
|
||||
|
||||
var isMuted = true
|
||||
if let _ = self.callState?.muteState {
|
||||
@ -498,11 +500,11 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
|
||||
let textSize = self.textNode.updateLayout(CGSize(width: size.width, height: .greatestFiniteMagnitude))
|
||||
|
||||
let titleFrame = CGRect(origin: CGPoint(x: leftInset + 16.0, y: 9.0), size: titleSize)
|
||||
transition.updateFrame(node: self.titleNode, frame: titleFrame)
|
||||
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: leftInset + 16.0, y: titleFrame.maxY + 1.0), size: textSize))
|
||||
staticTransition.updateFrame(node: self.titleNode, frame: titleFrame)
|
||||
staticTransition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: leftInset + 16.0, y: titleFrame.maxY + 1.0), size: textSize))
|
||||
|
||||
if let image = self.muteIconNode.image {
|
||||
transition.updateFrame(node: self.muteIconNode, frame: CGRect(origin: CGPoint(x: titleFrame.maxX + 4.0, y: titleFrame.minY + 5.0), size: image.size))
|
||||
staticTransition.updateFrame(node: self.muteIconNode, frame: CGRect(origin: CGPoint(x: titleFrame.maxX + 4.0, y: titleFrame.minY + 5.0), size: image.size))
|
||||
}
|
||||
self.muteIconNode.isHidden = self.currentData?.groupCall != nil
|
||||
self.joinButton.isHidden = self.currentData?.groupCall != nil
|
||||
|
@ -14,6 +14,7 @@ import TelegramPresentationData
|
||||
import DeviceAccess
|
||||
import UniversalMediaPlayer
|
||||
import AccountContext
|
||||
import DeviceProximity
|
||||
|
||||
public final class AccountGroupCallContextImpl: AccountGroupCallContext {
|
||||
public final class Proxy {
|
||||
@ -427,6 +428,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
|
||||
public weak var sourcePanel: ASDisplayNode?
|
||||
|
||||
private var proximityManagerIndex: Int?
|
||||
|
||||
init(
|
||||
accountContext: AccountContext,
|
||||
audioSession: ManagedAudioSession,
|
||||
@ -651,6 +654,10 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
|
||||
self.myAudioLevelTimer?.invalidate()
|
||||
self.typingDisposable.dispose()
|
||||
|
||||
if let proximityManagerIndex = self.proximityManagerIndex {
|
||||
DeviceProximityManager.shared().remove(proximityManagerIndex)
|
||||
}
|
||||
}
|
||||
|
||||
private func updateSessionState(internalState: InternalState, audioSessionControl: ManagedAudioSessionControl?) {
|
||||
@ -663,6 +670,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
if let audioSessionControl = audioSessionControl, previousControl == nil {
|
||||
audioSessionControl.setOutputMode(.custom(self.currentAudioOutputValue))
|
||||
audioSessionControl.setup(synchronous: true)
|
||||
|
||||
self.setCurrentAudioOutput(.speaker)
|
||||
}
|
||||
|
||||
self.audioSessionShouldBeActive.set(true)
|
||||
@ -1033,6 +1042,26 @@ public final class PresentationGroupCallImpl: PresentationGroupCall {
|
||||
}
|
||||
self.currentAudioOutputValue = output
|
||||
|
||||
var shouldMonitorProximity = false
|
||||
switch output {
|
||||
case .builtin:
|
||||
shouldMonitorProximity = true
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if shouldMonitorProximity {
|
||||
if self.proximityManagerIndex == nil {
|
||||
self.proximityManagerIndex = DeviceProximityManager.shared().add { _ in
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if let proximityManagerIndex = self.proximityManagerIndex {
|
||||
self.proximityManagerIndex = nil
|
||||
DeviceProximityManager.shared().remove(proximityManagerIndex)
|
||||
}
|
||||
}
|
||||
|
||||
self.audioOutputStatePromise.set(.single((self.audioOutputStateValue.0, output))
|
||||
|> then(
|
||||
.single(self.audioOutputStateValue)
|
||||
|
@ -100,6 +100,9 @@ func parseTelegramGroupOrChannel(chat: Api.Chat) -> Peer? {
|
||||
if (flags & Int32(1 << 23)) != 0 {
|
||||
channelFlags.insert(.hasVoiceChat)
|
||||
}
|
||||
if (flags & Int32(1 << 24)) != 0 {
|
||||
channelFlags.insert(.hasActiveVoiceChat)
|
||||
}
|
||||
|
||||
let restrictionInfo: PeerAccessRestrictionInfo?
|
||||
if let restrictionReason = restrictionReason {
|
||||
|
@ -440,6 +440,15 @@ public func stopGroupCall(account: Account, peerId: PeerId, callId: Int64, acces
|
||||
return cachedData
|
||||
}
|
||||
})
|
||||
if var peer = transaction.getPeer(peerId) as? TelegramChannel {
|
||||
var flags = peer.flags
|
||||
flags.remove(.hasVoiceChat)
|
||||
flags.remove(.hasActiveVoiceChat)
|
||||
peer = peer.withUpdatedFlags(flags)
|
||||
updatePeers(transaction: transaction, peers: [peer], update: { _, updated in
|
||||
return updated
|
||||
})
|
||||
}
|
||||
|
||||
account.stateManager.addUpdates(result)
|
||||
}
|
||||
|
@ -729,6 +729,8 @@ final class AuthorizedApplicationContext {
|
||||
}
|
||||
}))
|
||||
})
|
||||
|
||||
self.rootController.setForceInCallStatusBar((self.context.sharedContext as! SharedAccountContextImpl).currentCallStatusBarNode)
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
@ -94,7 +94,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
||||
private var callDisposable: Disposable?
|
||||
private var callStateDisposable: Disposable?
|
||||
|
||||
private var currentCallStatusBarNode: CallStatusBarNodeImpl?
|
||||
private(set) var currentCallStatusBarNode: CallStatusBarNodeImpl?
|
||||
|
||||
private var groupCallDisposable: Disposable?
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user