From 0d591796b7bfa0afdbe3b8c3bb294ea7e1dc8ec2 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 28 Apr 2021 03:41:32 +0400 Subject: [PATCH] Video Chats Improvements --- .../Sources/CallController.swift | 4 +- .../Sources/CallControllerButton.swift | 3 ++ .../Sources/VoiceChatController.swift | 44 ++++++------------ .../Sources/VoiceChatParticipantItem.swift | 10 ++-- .../Contents.json | 21 +++++++++ .../airpods-b515@3x.png | Bin 0 -> 4642 bytes .../ChatInterfaceStateContextMenus.swift | 2 +- .../Sources/PeerInfo/PeerInfoData.swift | 10 ++-- .../UrlHandling/Sources/UrlHandling.swift | 8 ++-- 9 files changed, 59 insertions(+), 43 deletions(-) create mode 100644 submodules/TelegramUI/Images.xcassets/Call/CallAirpodsMaxButton.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Call/CallAirpodsMaxButton.imageset/airpods-b515@3x.png diff --git a/submodules/TelegramCallsUI/Sources/CallController.swift b/submodules/TelegramCallsUI/Sources/CallController.swift index 64281e9645..6f47d375ab 100644 --- a/submodules/TelegramCallsUI/Sources/CallController.swift +++ b/submodules/TelegramCallsUI/Sources/CallController.swift @@ -187,7 +187,9 @@ public final class CallController: ViewController { if port.type == .bluetooth { var image = UIImage(bundleImageName: "Call/CallBluetoothButton") let portName = port.name.lowercased() - if portName.contains("airpods pro") { + if portName.contains("airpods max") { + image = UIImage(bundleImageName: "Call/CallAirpodsMaxButton") + } else if portName.contains("airpods pro") { image = UIImage(bundleImageName: "Call/CallAirpodsProButton") } else if portName.contains("airpods") { image = UIImage(bundleImageName: "Call/CallAirpodsButton") diff --git a/submodules/TelegramCallsUI/Sources/CallControllerButton.swift b/submodules/TelegramCallsUI/Sources/CallControllerButton.swift index 2f80b15fc1..28bdc66a40 100644 --- a/submodules/TelegramCallsUI/Sources/CallControllerButton.swift +++ b/submodules/TelegramCallsUI/Sources/CallControllerButton.swift @@ -37,6 +37,7 @@ final class CallControllerButtonItemNode: HighlightTrackingButtonNode { case speaker case airpods case airpodsPro + case airpodsMax case headphones case accept case end @@ -232,6 +233,8 @@ final class CallControllerButtonItemNode: HighlightTrackingButtonNode { image = generateTintedImage(image: UIImage(bundleImageName: "Call/CallAirpodsButton"), color: imageColor) case .airpodsPro: image = generateTintedImage(image: UIImage(bundleImageName: "Call/CallAirpodsProButton"), color: imageColor) + case .airpodsMax: + image = generateTintedImage(image: UIImage(bundleImageName: "Call/CallAirpodsMaxButton"), color: imageColor) case .headphones: image = generateTintedImage(image: UIImage(bundleImageName: "Call/CallHeadphonesButton"), color: imageColor) case .accept: diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift index ed38917dec..5619b8498e 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatController.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatController.swift @@ -953,6 +953,8 @@ public final class VoiceChatController: ViewController { self.actionButton = VoiceChatActionButton() if self.isScheduling { + self.cameraButton.alpha = 0.0 + self.cameraButton.isUserInteractionEnabled = false self.audioButton.alpha = 0.0 self.audioButton.isUserInteractionEnabled = false self.leaveButton.alpha = 0.0 @@ -2111,7 +2113,7 @@ public final class VoiceChatController: ViewController { strongSelf.updateFloatingHeaderOffset(offset: strongSelf.currentContentOffset ?? 0.0, transition: .animated(duration: 0.3, curve: .easeInOut)) } } - if false, let (peerId, _) = minimalVisiblePeerid { + if let (peerId, _) = minimalVisiblePeerid { var index = 0 for item in strongSelf.currentEntries { if case let .peer(entry) = item, entry.peer.id == peerId { @@ -2159,7 +2161,7 @@ public final class VoiceChatController: ViewController { strongSelf.updateFloatingHeaderOffset(offset: strongSelf.currentContentOffset ?? 0.0, transition: .animated(duration: 0.3, curve: .easeInOut)) } } - if false, let (peerId, _) = minimalVisiblePeerid { + if let (peerId, _) = minimalVisiblePeerid { var index = 0 for item in strongSelf.currentEntries { if case let .peer(entry) = item, entry.peer.id == peerId { @@ -2249,7 +2251,6 @@ public final class VoiceChatController: ViewController { } let avatarSize = CGSize(width: 28.0, height: 28.0) - return combineLatest(self.displayAsPeersPromise.get(), self.context.account.postbox.loadedPeerWithId(self.call.peerId), self.inviteLinksPromise.get()) |> take(1) |> deliverOnMainQueue @@ -2411,8 +2412,6 @@ public final class VoiceChatController: ViewController { strongSelf.controller?.present(alertController, in: .window(.root)) }))) } - - return items } } @@ -2601,18 +2600,15 @@ public final class VoiceChatController: ViewController { let minute = components.minute ?? 0 components.minute = 0 let roundedToHourDate = calendar.date(from: components)! - components.hour = 0 + let roundedToMidnightDate = calendar.date(from: components)! - let nextTwoHourDate = calendar.date(byAdding: .hour, value: minute > 30 ? 4 : 3, to: roundedToHourDate) - let maxDate = calendar.date(byAdding: .day, value: 8, to: roundedToMidnightDate) - + if let date = calendar.date(byAdding: .day, value: 365, to: currentDate) { self.pickerView?.maximumDate = date } - if let next1MinDate = next1MinDate, let nextTwoHourDate = nextTwoHourDate { self.pickerView?.minimumDate = next1MinDate self.pickerView?.maximumDate = maxDate @@ -3140,8 +3136,7 @@ public final class VoiceChatController: ViewController { guard availableOutputs.count >= 2 else { return } - let hasMute = false - + if availableOutputs.count == 2 { for output in availableOutputs { if output != currentOutput { @@ -3153,9 +3148,6 @@ public final class VoiceChatController: ViewController { let actionSheet = ActionSheetController(presentationData: self.presentationData.withUpdated(theme: self.darkTheme)) var items: [ActionSheetItem] = [] for output in availableOutputs { - if hasMute, case .builtin = output { - continue - } let title: String var icon: UIImage? switch output { @@ -3171,7 +3163,9 @@ public final class VoiceChatController: ViewController { if port.type == .bluetooth { var image = UIImage(bundleImageName: "Call/CallBluetoothButton") let portName = port.name.lowercased() - if portName.contains("airpods pro") { + if portName.contains("airpods max") { + image = UIImage(bundleImageName: "Call/CallAirpodsMaxButton") + } else if portName.contains("airpods pro") { image = UIImage(bundleImageName: "Call/CallAirpodsProButton") } else if portName.contains("airpods") { image = UIImage(bundleImageName: "Call/CallAirpodsButton") @@ -3204,18 +3198,6 @@ public final class VoiceChatController: ViewController { }) self.controller?.present(controller, in: .window(.root)) } - return; - let controller = voiceChatCameraPreviewController(sharedContext: self.context.sharedContext, account: self.context.account, forceTheme: self.darkTheme, title: self.presentationData.strings.VoiceChat_VideoPreviewTitle, text: self.presentationData.strings.VoiceChat_VideoPreviewDescription, apply: { [weak self] in - guard let strongSelf = self else { - return - } - if strongSelf.call.isVideo { - strongSelf.call.disableVideo() - } else { - strongSelf.call.requestVideo() - } - }) - self.controller?.present(controller, in: .window(.root)) } @objc private func switchCameraPressed() { @@ -3682,6 +3664,8 @@ public final class VoiceChatController: ViewController { size.width = floor(min(size.width, size.height) * 0.5) } + let isScheduled = self.isScheduling || self.callState?.scheduleTimestamp != nil + var previousIsLandscape = false if let previousLayout = previousLayout, case .compact = previousLayout.metrics.widthClass, previousLayout.size.width > previousLayout.size.height { previousIsLandscape = true @@ -3855,7 +3839,7 @@ public final class VoiceChatController: ViewController { let forthButtonFrame: CGRect let leftButtonFrame: CGRect - if self.mainVideoContainerNode == nil { + if self.mainVideoContainerNode == nil || isScheduled { leftButtonFrame = CGRect(origin: CGPoint(x: sideButtonOrigin, y: floor((self.effectiveBottomAreaHeight - sideButtonSize.height) / 2.0)), size: sideButtonSize) } else { leftButtonFrame = CGRect(origin: CGPoint(x: sideButtonOrigin, y: floor((self.effectiveBottomAreaHeight - sideButtonSize.height - upperButtonDistance - cameraButtonSize.height) / 2.0) + upperButtonDistance + cameraButtonSize.height), size: sideButtonSize) @@ -4106,6 +4090,8 @@ public final class VoiceChatController: ViewController { if let callState = self.callState { if callState.scheduleTimestamp != nil && self.listNode.alpha > 0.0 { self.timerNode.isHidden = false + self.cameraButton.alpha = 0.0 + self.cameraButton.isUserInteractionEnabled = false self.listNode.alpha = 0.0 self.listNode.isUserInteractionEnabled = false self.backgroundNode.backgroundColor = panelBackgroundColor diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatParticipantItem.swift b/submodules/TelegramCallsUI/Sources/VoiceChatParticipantItem.swift index 3366dd3ce6..b4ea1ad777 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatParticipantItem.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatParticipantItem.swift @@ -905,7 +905,7 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode { titleColor = UIColor(rgb: 0xffffff, alpha: 0.65) } else if case .tile = item.style { switch item.text { - case let .text(_, textColor): + case let .text(_, _, textColor): switch textColor { case .generic: titleColor = item.presentationData.theme.list.itemPrimaryTextColor @@ -977,7 +977,7 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode { } else { statusAttributedString = NSAttributedString(string: item.presentationData.strings.LastSeen_Offline, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor) } - case let .text(text, textColor): + case let .text(text, textIcon, textColor): var textColorValue: UIColor switch textColor { case .generic: @@ -999,7 +999,7 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode { break } - if let expandedText = item.expandedText, case let .text(text, textColor) = expandedText { + if let expandedText = item.expandedText, case let .text(text, _, textColor) = expandedText { let textColorValue: UIColor switch textColor { case .generic: @@ -1086,9 +1086,9 @@ class VoiceChatParticipantItemNode: ItemListRevealOptionsItemNode { var animateStatusTransitionFromUp: Bool? if let currentItem = currentItem { - if case .presence = currentItem.text, case let .text(_, newColor) = item.text { + if case .presence = currentItem.text, case let .text(_, _, newColor) = item.text { animateStatusTransitionFromUp = newColor == .constructive - } else if case let .text(_, currentColor) = currentItem.text, case let .text(_, newColor) = item.text, currentColor != newColor { + } else if case let .text(_, _, currentColor) = currentItem.text, case let .text(_, _, newColor) = item.text, currentColor != newColor { animateStatusTransitionFromUp = newColor == .constructive } else if case .text = currentItem.text, case .presence = item.text { animateStatusTransitionFromUp = false diff --git a/submodules/TelegramUI/Images.xcassets/Call/CallAirpodsMaxButton.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Call/CallAirpodsMaxButton.imageset/Contents.json new file mode 100644 index 0000000000..360b4f2588 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Call/CallAirpodsMaxButton.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "airpods-b515@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Call/CallAirpodsMaxButton.imageset/airpods-b515@3x.png b/submodules/TelegramUI/Images.xcassets/Call/CallAirpodsMaxButton.imageset/airpods-b515@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..cf735b34c9a9ae76a30865d2438810cf7d869ac2 GIT binary patch literal 4642 zcmX|^WmFX0*TshhN$HNEq?@682uYEY9J-X290`dT5DAeIWGImiham-28mXa?E*Vm! z`^Epe)^peToxSf_XWjc{e>rd?11-`Aj1K?+0I80)hVi|M-lIT>dtVd!4}fT=7eouWMj?P-nFP#0{9ku)*AzF~<&mrP=;sAg}Y>7F6^}A`>j-@_8T5ai@ z+EiziD1bOnB663b38upyMd5&ty{eW#Q)$I4!_S}a%$g=j?n$EAc25<#M;T(mK}fi= z{R1vV#a`IKS^M>V(A|>a?|J`W#or&pa3c3L-)aEWumB+r&62>>_ey+| zaDos+D+64W=jZf&*j*P6O6Th#zBudyw>cmDstqxB=M=%=40NZw5P{YHrVs%88W#Hp zUv6Vr0OPymrai%C4Y)45bf3NfNmQ`xdI8A*KU)Q1dzJ`|ALgO4!9&I9cbUBfVJ%_k zwUP@j}jXbu*tJ%!Z?SBrUE~g_-b>B?@Q^@5PGDrY24sXP160!vj)&#^;ISn-Q$( zmHUkDl-ry(4Xci-O9)%Zia|mi#-@8j^dU6Gp>CG&=j$P8Iw@zUu zs^jhI_jC6voMUwe$q>yY^_A&r#Y6XLG<0++!L{GJ`si!#GrL>Fgz9U@8iO4Y=Csf+ z+hxGA%0C~XaZ(a|0Bq~88U766IgAo*so=*TRATF~2-d%8#?v-^r^RaSs@36$Cs{9- zDMol^DRC8~`{Gb)4-#0WnB#KC_h2FkT#a=3UHjwpFG_Not)zNbCbr0|U>jtJNIUFN zVhlEnCz@~T{XilRMPms~2$SYycQyCpDQ(dZ=agRyP5;R6_zr-0@#jT|examoI_ZtgZ zV=&$fVZ!VMucdpYPo+h`wo6e^=ET8+{0z{YkCkvhxiVfE454@6) zSIdUXe`7%u4-okKtlKhRBs?`F)34P%vyMO)isJFF%m8oa*n3-~t zt(*Ay;NRR-Bp)ZYnS}B%XEPDfY{vO$kX~5t6-FSZjS-a;KaKkbO(s<<)82)rFNvE@ zMsxN#nUW|wGL0o~X_Iiuy&6>~;nt-50XZmO=6%bdsk&RS{$0qIJeRb>iW#vcI8RK@ z+O?ekGC4AN(*2rUih{g5dw}s`%wYLe%TQ}yEqFTRhSX)) z1@h<38=QX8`f)@cwp$W)^>ZQ%zn**iGBjYvum_@D8%Bj2iKKO#=jd^c9+CM`!Lq&YZRvL%Pa zUr3Zjl#UX+$L>)s20QCT`K0M8I?HPrD_PB=%yt>4qD~xY ze1X-;;VFK}Jh2iO&i7j6zChu?5f_NT9_Jz(!nmEn>t z%SC=fW(GtDyq^Gvf~SC1sfzt8>m>DA){m=!2Rv-NcHGK9aAy|*C!-kkh7bc~x@CbA;}ZlE=917H`6T_dvCXk^ zcT!{pvUHAd?sQIY&wZ|Y&U7vwDdK*%?Y1Se6|?0Nu(@rrBZ--xz)Vk0pNuAr4~^Rt zwpyLFy=Y|B8BrC{OD;A4)Tn=eTvUhZEtx56v%HnES=+Y)Q*SJSbN;HE@l9S++O*lk2!F7yZlbh?+H_Y-Rf85Dy%21~Zd81cx39S`wqLTZHJ|^s zj_IA4OLx|k*a5vQ$wP&u{m`utjga(E$*}8v%x?clC)@CxnI)0M

n&G3H&n zuy?63eOrArsi0X}FX7g=3v?S)QoP%GlH789q3XwmV#8wStWEe<*JpSI&thUjGEFZl z9LIOJ$<+63jb+WXCn8ft4`%q;;GBDmvyQ7yN=Ml}6un znUx$vI*vD#`hQ{@;BxxpygwX12w$7~kM7!H z;E|2xW$$-n?2t39^U)ydtA~f(AN`&+Bd<4scVMgbt`6!~A-;z*-8*z070agAM*W{F z%fnk^TG!)i6xyGiOWT;-*`h*ZeVcJ6PGrSSAy}3MeVkL+& zc@c8d@Mp)$iW4P0Av0m}ob!di%<16i#9ozrmi)HIkcWWh-8|poY@LAbbhcc6OUuG$ zYv!Kn*`w3r-MspG*Y*A5J+^S6}wWM{+p zuO@zEV1$AU4dtLWdf&4XU5iFOUMXE)jaOApQT@gqW>Gu{YR3?4l4}VE+qtc$ z1zgSMMa$y^{r-^%?S|%EnUeoxo4EEo?l=t$4r1OR+4H*M!<4p?Hh0Kg&h4=iwonEic|*t^>AZHk_|H&2b3kY z6ce^2=sqZPsvAwwBQr37tBK2KY~`1{MkFq@Ak`3IF7AyeAj{*21l*6oqeuPI?9J=K zi#B-)2aWS*Z6il*OJC0x3C?_%qV9@u6yKyk^7NJdqzVlP{#~zL+~Z@q?vmbt;ZzlE z?$gm|-c|jS$#;4QP6|qYgsMzS$q|=seG@A{xkj3K4T*1{U7G@e%|b+aXuLz{k$s{| z0WBl-KF?n6n|0S;4Ev-|KF#$RuK0BE;HX#|ZAh&vP+nS`5@MF~X4-*GVy{snL1Ju> zlFnijY4K4_cNVWM!GTTp{a+^(SDGAjAsj86H(_`zQA){eP|_9{%vM|a*35!urS~fC zT}mNvgB1$O+WCRfHnsgcqRPo{YP!Am;(HsRv`A~f*AH`P^#vngsSeEiH?c6f6*GnJ z=CaI`{;sroH*dnwyg6d5cpy}_xBsneW3hLoIZN%vy7-*LrwN^SVQxeB*=odAt@p9M0pWRoirUezMYNbnrGj)P(kdDseUr}j1tAolQPugK2_|;Qx0CoRo`bF#6Q=0@~^HZzF=n+%8A?F6lAGwcSKr`!s4d=7oAv4sf`NVPjP&IG#8lOgX zK>kp)HtpDcp|N{!;V53{F7aCYjaO)2qFX1pM4a8pmiaOk60EiS*lAFCzM4poI0Ssd zqF800rqZ4B0|9mye{>pR@;Tq+Gi&2YYG17Om#s>5%0QsN1b0KS8`Z!AS0d9|;Z=^r z2WcD}QybT=IGu_;PgW`9;%Ne8edx@bB8j&j!{jTeKM~GNa|r1P=_P)xzDrks7Hg*9 z1M{r20HasaEZ*-+Ns+rXG{Ly^XMSX4y|LJZ1)wxmh9}Y{(=LyKMWp2juC5PcRXDy2 z6;32BcmIZH#c8MN>jcK1Iv=OGQSKTadnmCskQ_z?cR{3S!3CAC%8Fck z)c3gqm?RmTqSeTICwX78vP=ZnFaG36q$=o{y>YJ9I!p~&2#jaVZz|*R(QrA)td8#X z-5+!<_K5#hu^}kgrZ4r=A*+Xvb`+iBCbsZY9eS5^?R_WkC&+x6nC#2>EN;?M`uo%X Nbif80)oS+9{|AHDxLyDN literal 0 HcmV?d00001 diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift index 66b1a1a16e..2daa5baa46 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateContextMenus.swift @@ -1219,7 +1219,7 @@ func chatAvailableMessageActionsImpl(postbox: Postbox, accountPeerId: PeerId, me if canDeleteGlobally { optionsMap[id]!.insert(.deleteGlobally) } - if user.botInfo != nil && !user.id.isReplies && !isAction { + if user.botInfo != nil && message.flags.contains(.Incoming) && !user.id.isReplies && !isAction { optionsMap[id]!.insert(.report) } } else if let _ = peer as? TelegramSecretChat { diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift index 0e4be25a38..06a7d7a2e2 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoData.swift @@ -876,7 +876,9 @@ func availableActionsForMemberOfPeer(accountPeerId: PeerId, peer: Peer?, member: } else if member.id != accountPeerId { if let channel = peer as? TelegramChannel { if channel.flags.contains(.isCreator) { - result.insert(.restrict) + if !channel.flags.contains(.isGigagroup) { + result.insert(.restrict) + } result.insert(.promote) } else { switch member { @@ -887,13 +889,15 @@ func availableActionsForMemberOfPeer(accountPeerId: PeerId, peer: Peer?, member: case let .member(member): if let adminInfo = member.adminInfo { if adminInfo.promotedBy == accountPeerId { - result.insert(.restrict) + if !channel.flags.contains(.isGigagroup) { + result.insert(.restrict) + } if channel.hasPermission(.addAdmins) { result.insert(.promote) } } } else { - if channel.hasPermission(.banMembers) { + if channel.hasPermission(.banMembers) && !channel.flags.contains(.isGigagroup) { result.insert(.restrict) } if channel.hasPermission(.addAdmins) { diff --git a/submodules/UrlHandling/Sources/UrlHandling.swift b/submodules/UrlHandling/Sources/UrlHandling.swift index a3d111b8f5..671fedd79e 100644 --- a/submodules/UrlHandling/Sources/UrlHandling.swift +++ b/submodules/UrlHandling/Sources/UrlHandling.swift @@ -265,7 +265,7 @@ public func parseInternalUrl(query: String) -> ParsedInternalUrl? { } else { return nil } - } else if let value = Int(pathComponents[1]) { + } else if let value = Int32(pathComponents[1]) { var threadId: Int32? var commentId: Int32? if let queryItems = components.queryItems { @@ -286,11 +286,11 @@ public func parseInternalUrl(query: String) -> ParsedInternalUrl? { } } if let threadId = threadId { - return .peerName(peerName, .replyThread(threadId, Int32(value))) + return .peerName(peerName, .replyThread(threadId, value)) } else if let commentId = commentId { - return .peerName(peerName, .replyThread(Int32(value), commentId)) + return .peerName(peerName, .replyThread(value, commentId)) } else { - return .peerName(peerName, .channelMessage(Int32(value))) + return .peerName(peerName, .channelMessage(value)) } } else { return nil