mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-04 21:41:45 +00:00
Merge commit '7b5f9a89b2d88fc75f7e7941c9114624574f40a3'
This commit is contained in:
commit
64ab80da02
@ -973,7 +973,7 @@ public protocol MediaEditorScreenResult {
|
|||||||
|
|
||||||
public protocol TelegramRootControllerInterface: NavigationController {
|
public protocol TelegramRootControllerInterface: NavigationController {
|
||||||
@discardableResult
|
@discardableResult
|
||||||
func openStoryCamera(customTarget: Stories.PendingTarget?, transitionIn: StoryCameraTransitionIn?, transitionedIn: @escaping () -> Void, transitionOut: @escaping (Stories.PendingTarget?, Bool) -> StoryCameraTransitionOut?) -> StoryCameraTransitionInCoordinator?
|
func openStoryCamera(customTarget: Stories.PendingTarget?, resumeLiveStream: Bool, transitionIn: StoryCameraTransitionIn?, transitionedIn: @escaping () -> Void, transitionOut: @escaping (Stories.PendingTarget?, Bool) -> StoryCameraTransitionOut?) -> StoryCameraTransitionInCoordinator?
|
||||||
func proceedWithStoryUpload(target: Stories.PendingTarget, results: [MediaEditorScreenResult], existingMedia: EngineMedia?, forwardInfo: Stories.PendingForwardInfo?, externalState: MediaEditorTransitionOutExternalState, commit: @escaping (@escaping () -> Void) -> Void)
|
func proceedWithStoryUpload(target: Stories.PendingTarget, results: [MediaEditorScreenResult], existingMedia: EngineMedia?, forwardInfo: Stories.PendingForwardInfo?, externalState: MediaEditorTransitionOutExternalState, commit: @escaping (@escaping () -> Void) -> Void)
|
||||||
|
|
||||||
func getContactsController() -> ViewController?
|
func getContactsController() -> ViewController?
|
||||||
|
|||||||
@ -2909,6 +2909,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
var premiumNeeded = false
|
var premiumNeeded = false
|
||||||
var hasActiveCall = false
|
var hasActiveCall = false
|
||||||
var hasActiveGroupCall = false
|
var hasActiveGroupCall = false
|
||||||
|
var hasLiveStream = false
|
||||||
|
|
||||||
|
if let componentView = self.chatListHeaderView(), let storyPeerListView = componentView.storyPeerListView(), storyPeerListView.isLiveStreaming {
|
||||||
|
hasLiveStream = true
|
||||||
|
}
|
||||||
|
|
||||||
let storiesCountLimit = self.context.userLimits.maxExpiringStoriesCount
|
let storiesCountLimit = self.context.userLimits.maxExpiringStoriesCount
|
||||||
var storiesCount = 0
|
var storiesCount = 0
|
||||||
@ -2938,7 +2943,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if reachedCountLimit {
|
if !hasLiveStream && reachedCountLimit {
|
||||||
let context = self.context
|
let context = self.context
|
||||||
var replaceImpl: ((ViewController) -> Void)?
|
var replaceImpl: ((ViewController) -> Void)?
|
||||||
let controller = PremiumLimitScreen(context: context, subject: .expiringStories, count: Int32(storiesCount), action: {
|
let controller = PremiumLimitScreen(context: context, subject: .expiringStories, count: Int32(storiesCount), action: {
|
||||||
@ -2955,7 +2960,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if premiumNeeded || hasActiveCall || hasActiveGroupCall {
|
if !hasLiveStream && (premiumNeeded || hasActiveCall || hasActiveGroupCall) {
|
||||||
if let storyCameraTooltip = self.storyCameraTooltip {
|
if let storyCameraTooltip = self.storyCameraTooltip {
|
||||||
self.storyCameraTooltip = nil
|
self.storyCameraTooltip = nil
|
||||||
storyCameraTooltip.dismiss()
|
storyCameraTooltip.dismiss()
|
||||||
@ -3042,7 +3047,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let rootController = self.context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface {
|
if let rootController = self.context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface {
|
||||||
let coordinator = rootController.openStoryCamera(customTarget: nil, transitionIn: cameraTransitionIn, transitionedIn: {}, transitionOut: self.storyCameraTransitionOut())
|
let coordinator = rootController.openStoryCamera(customTarget: nil, resumeLiveStream: hasLiveStream, transitionIn: cameraTransitionIn, transitionedIn: {}, transitionOut: self.storyCameraTransitionOut())
|
||||||
coordinator?.animateIn()
|
coordinator?.animateIn()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6420,7 +6425,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
if let current = self.storyCameraTransitionInCoordinator {
|
if let current = self.storyCameraTransitionInCoordinator {
|
||||||
coordinator = current
|
coordinator = current
|
||||||
} else {
|
} else {
|
||||||
coordinator = rootController.openStoryCamera(customTarget: nil, transitionIn: nil, transitionedIn: {}, transitionOut: { [weak self] target, _ in
|
coordinator = rootController.openStoryCamera(customTarget: nil, resumeLiveStream: false, transitionIn: nil, transitionedIn: {}, transitionOut: { [weak self] target, _ in
|
||||||
guard let self, let target else {
|
guard let self, let target else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -155,6 +155,19 @@ final class CameraLiveStreamComponent: Component {
|
|||||||
self.storyContentState = state
|
self.storyContentState = state
|
||||||
self.state?.updated()
|
self.state?.updated()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
self.inputMediaNodeDataPromise.set(
|
||||||
|
ChatEntityKeyboardInputNode.inputData(
|
||||||
|
context: component.context,
|
||||||
|
chatPeerId: nil,
|
||||||
|
areCustomEmojiEnabled: true,
|
||||||
|
hasTrending: true,
|
||||||
|
hasSearch: true,
|
||||||
|
hideBackground: true,
|
||||||
|
maskEdge: .clip,
|
||||||
|
sendGif: nil
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let storyContentState = self.storyContentState, let slice = storyContentState.slice {
|
if let storyContentState = self.storyContentState, let slice = storyContentState.slice {
|
||||||
|
|||||||
@ -374,6 +374,11 @@ private final class CameraScreenComponent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let controller = getController() {
|
if let controller = getController() {
|
||||||
|
if controller.resumeLiveStream {
|
||||||
|
controller.updateCameraState({ $0.updatedMode(.live).updatedIsWaitingForStream(true) }, update: false, transition: .immediate)
|
||||||
|
self.startLiveStream(rtmp: false)
|
||||||
|
}
|
||||||
|
|
||||||
if let customTarget = controller.customTarget {
|
if let customTarget = controller.customTarget {
|
||||||
self.sendAsPeerId = customTarget
|
self.sendAsPeerId = customTarget
|
||||||
self.isCustomTarget = true
|
self.isCustomTarget = true
|
||||||
@ -1080,6 +1085,7 @@ private final class CameraScreenComponent: CombinedComponent {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var storyListContext: PeerExpiringStoryListContext?
|
||||||
func startLiveStream(rtmp: Bool) {
|
func startLiveStream(rtmp: Bool) {
|
||||||
guard let controller = self.getController() else {
|
guard let controller = self.getController() else {
|
||||||
return
|
return
|
||||||
@ -1117,41 +1123,36 @@ private final class CameraScreenComponent: CombinedComponent {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// let _ = (self.context.engine.messages.storySubscriptions(isHidden: false)
|
let _ = (self.context.engine.messages.storySubscriptions(isHidden: false)
|
||||||
// |> take(1)
|
|> take(1)
|
||||||
// |> deliverOnMainQueue).start(next: { [weak self, weak controller] subscriptions in
|
|> deliverOnMainQueue).start(next: { [weak self, weak controller] subscriptions in
|
||||||
// guard let self else {
|
guard let self else {
|
||||||
// return
|
return
|
||||||
// }
|
}
|
||||||
// if subscriptions.accountItem?.hasLiveItems == true {
|
if subscriptions.accountItem?.hasLiveItems == true {
|
||||||
// let storyList = PeerExpiringStoryListContext(account: self.context.account, peerId: peerId)
|
let storyList = PeerExpiringStoryListContext(account: self.context.account, peerId: peerId)
|
||||||
// let _ = (storyList.state
|
self.storyListContext = storyList
|
||||||
// |> filter { !$0.isLoading }
|
let _ = (storyList.state
|
||||||
// |> take(1)
|
|> filter { !$0.isLoading }
|
||||||
// |> deliverOnMainQueue).start(next: { [weak self, weak controller] state in
|
|> take(1)
|
||||||
// guard let self else {
|
|> deliverOnMainQueue).start(next: { [weak self, weak controller] state in
|
||||||
// return
|
guard let self else {
|
||||||
// }
|
return
|
||||||
// for item in state.items.reversed() {
|
}
|
||||||
// let _ = (self.context.engine.messages.getStory(peerId: peerId, id: item.id)
|
for item in state.items.reversed() {
|
||||||
// |> deliverOnMainQueue).start(next: { [weak self, weak controller] item in
|
if case let .item(item) = item, case .liveStream = item.media {
|
||||||
// guard let self, let item else {
|
self.liveStreamStory = item
|
||||||
// return
|
controller?.updateCameraState({ $0.updatedIsStreaming(true) }, transition: .spring(duration: 0.4))
|
||||||
// }
|
self.updated(transition: .immediate)
|
||||||
// if case .liveStream = item.media {
|
return
|
||||||
// self.liveStreamStory = item
|
}
|
||||||
// controller?.updateCameraState({ $0.updatedIsStreaming(true) }, transition: .spring(duration: 0.4))
|
}
|
||||||
// self.updated(transition: .immediate)
|
startNewLiveStream()
|
||||||
// return
|
})
|
||||||
// }
|
} else {
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// startNewStream()
|
|
||||||
// })
|
|
||||||
// } else {
|
|
||||||
startNewLiveStream()
|
startNewLiveStream()
|
||||||
// }
|
}
|
||||||
// })
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func endLiveStream() {
|
func endLiveStream() {
|
||||||
@ -2815,7 +2816,7 @@ public class CameraScreenImpl: ViewController, CameraScreen {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let code = filteredCodes.first, !self.cameraState.isCollageEnabled && self.cameraState.recording == CameraState.Recording.none {
|
if let code = filteredCodes.first, !self.cameraState.isCollageEnabled && self.cameraState.recording == CameraState.Recording.none && self.cameraState.mode != .live {
|
||||||
self.controller?.updateFocusedCode(code)
|
self.controller?.updateFocusedCode(code)
|
||||||
} else {
|
} else {
|
||||||
self.controller?.updateFocusedCode(nil)
|
self.controller?.updateFocusedCode(nil)
|
||||||
@ -3915,6 +3916,7 @@ public class CameraScreenImpl: ViewController, CameraScreen {
|
|||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
fileprivate let mode: Mode
|
fileprivate let mode: Mode
|
||||||
fileprivate let customTarget: EnginePeer.Id?
|
fileprivate let customTarget: EnginePeer.Id?
|
||||||
|
fileprivate let resumeLiveStream: Bool
|
||||||
fileprivate let holder: CameraHolder?
|
fileprivate let holder: CameraHolder?
|
||||||
fileprivate let transitionIn: TransitionIn?
|
fileprivate let transitionIn: TransitionIn?
|
||||||
fileprivate let transitionOut: (Bool) -> TransitionOut?
|
fileprivate let transitionOut: (Bool) -> TransitionOut?
|
||||||
@ -3972,15 +3974,18 @@ public class CameraScreenImpl: ViewController, CameraScreen {
|
|||||||
|
|
||||||
public var isEmbedded = false
|
public var isEmbedded = false
|
||||||
|
|
||||||
fileprivate func updateCameraState(_ f: (CameraState) -> CameraState, transition: ComponentTransition) {
|
fileprivate func updateCameraState(_ f: (CameraState) -> CameraState, update: Bool = true, transition: ComponentTransition) {
|
||||||
self.node.cameraState = f(self.node.cameraState)
|
self.node.cameraState = f(self.node.cameraState)
|
||||||
self.node.requestUpdateLayout(transition: transition)
|
if update {
|
||||||
|
self.node.requestUpdateLayout(transition: transition)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
customTarget: EnginePeer.Id? = nil,
|
customTarget: EnginePeer.Id? = nil,
|
||||||
|
resumeLiveStream: Bool = false,
|
||||||
holder: CameraHolder? = nil,
|
holder: CameraHolder? = nil,
|
||||||
transitionIn: TransitionIn?,
|
transitionIn: TransitionIn?,
|
||||||
transitionOut: @escaping (Bool) -> TransitionOut?,
|
transitionOut: @escaping (Bool) -> TransitionOut?,
|
||||||
@ -3989,6 +3994,7 @@ public class CameraScreenImpl: ViewController, CameraScreen {
|
|||||||
self.context = context
|
self.context = context
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.customTarget = customTarget
|
self.customTarget = customTarget
|
||||||
|
self.resumeLiveStream = resumeLiveStream
|
||||||
self.holder = holder
|
self.holder = holder
|
||||||
self.transitionIn = transitionIn
|
self.transitionIn = transitionIn
|
||||||
self.transitionOut = transitionOut
|
self.transitionOut = transitionOut
|
||||||
@ -4030,7 +4036,7 @@ public class CameraScreenImpl: ViewController, CameraScreen {
|
|||||||
super.displayNodeDidLoad()
|
super.displayNodeDidLoad()
|
||||||
|
|
||||||
self.node.didAppear = { [weak self] in
|
self.node.didAppear = { [weak self] in
|
||||||
guard let self else {
|
guard let self, !self.resumeLiveStream else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.postingAvailabilityDisposable = (self.postingAvailabilityPromise.get()
|
self.postingAvailabilityDisposable = (self.postingAvailabilityPromise.get()
|
||||||
|
|||||||
@ -634,7 +634,7 @@ public final class GiftItemComponent: Component {
|
|||||||
if case let .starGift(gift, _) = component.subject, gift.flags.contains(.isAuction) {
|
if case let .starGift(gift, _) = component.subject, gift.flags.contains(.isAuction) {
|
||||||
buttonColor = component.theme.overallDarkAppearance ? UIColor(rgb: 0xffc337) : UIColor(rgb: 0xd3720a)
|
buttonColor = component.theme.overallDarkAppearance ? UIColor(rgb: 0xffc337) : UIColor(rgb: 0xd3720a)
|
||||||
//todo:localize
|
//todo:localize
|
||||||
price = "Place a Bid"
|
price = "Join"
|
||||||
} else {
|
} else {
|
||||||
if priceValue.contains("#") {
|
if priceValue.contains("#") {
|
||||||
buttonColor = component.theme.overallDarkAppearance ? UIColor(rgb: 0xffc337) : UIColor(rgb: 0xd3720a)
|
buttonColor = component.theme.overallDarkAppearance ? UIColor(rgb: 0xffc337) : UIColor(rgb: 0xd3720a)
|
||||||
|
|||||||
@ -10646,7 +10646,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let rootController = self.context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface {
|
if let rootController = self.context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface {
|
||||||
let coordinator = rootController.openStoryCamera(customTarget: self.peerId == self.context.account.peerId ? nil : .peer(self.peerId), transitionIn: cameraTransitionIn, transitionedIn: {}, transitionOut: self.storyCameraTransitionOut())
|
let coordinator = rootController.openStoryCamera(customTarget: self.peerId == self.context.account.peerId ? nil : .peer(self.peerId), resumeLiveStream: false, transitionIn: cameraTransitionIn, transitionedIn: {}, transitionOut: self.storyCameraTransitionOut())
|
||||||
coordinator?.animateIn()
|
coordinator?.animateIn()
|
||||||
}
|
}
|
||||||
case .channelBoostRequired:
|
case .channelBoostRequired:
|
||||||
|
|||||||
@ -310,7 +310,7 @@ final class PeerInfoStoryGridScreenComponent: Component {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if let rootController = component.context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface {
|
if let rootController = component.context.sharedContext.mainWindow?.viewController as? TelegramRootControllerInterface {
|
||||||
let coordinator = rootController.openStoryCamera(customTarget: nil, transitionIn: nil, transitionedIn: {}, transitionOut: { _, _ in return nil })
|
let coordinator = rootController.openStoryCamera(customTarget: nil, resumeLiveStream: false, transitionIn: nil, transitionedIn: {}, transitionOut: { _, _ in return nil })
|
||||||
coordinator?.animateIn()
|
coordinator?.animateIn()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1147,13 +1147,21 @@ final class StoryItemContentComponent: Component {
|
|||||||
if self.liveCallStatsDisposable == nil {
|
if self.liveCallStatsDisposable == nil {
|
||||||
self.liveCallStatsDisposable = (mediaStreamCall.members
|
self.liveCallStatsDisposable = (mediaStreamCall.members
|
||||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] members in
|
|> deliverOnMainQueue).startStandalone(next: { [weak self] members in
|
||||||
guard let self, let environment = self.environment else {
|
guard let self, let component = self.component, let environment = self.environment else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//TODO:localize
|
//TODO:localize
|
||||||
let subtitle: String
|
let subtitle: String
|
||||||
if let members {
|
if let members {
|
||||||
subtitle = "\(max(1, members.totalCount)) watching"
|
var totalCount = members.totalCount
|
||||||
|
if component.isEmbeddedInCamera {
|
||||||
|
totalCount -= 1
|
||||||
|
}
|
||||||
|
if totalCount == 0 && component.isEmbeddedInCamera {
|
||||||
|
subtitle = "no viewers"
|
||||||
|
} else {
|
||||||
|
subtitle = "\(max(1, totalCount)) watching"
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
subtitle = "loading..."
|
subtitle = "loading..."
|
||||||
}
|
}
|
||||||
|
|||||||
@ -533,6 +533,18 @@ public final class StoryPeerListComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public var isLiveStreaming: Bool {
|
||||||
|
guard let component = self.component else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for itemSet in self.sortedItems {
|
||||||
|
if itemSet.peer.id == component.context.account.peerId, itemSet.hasLiveItems {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
public func transitionViewForItem(peerId: EnginePeer.Id) -> (UIView, StoryContainerScreen.TransitionView)? {
|
public func transitionViewForItem(peerId: EnginePeer.Id) -> (UIView, StoryContainerScreen.TransitionView)? {
|
||||||
if self.collapsedButton.isUserInteractionEnabled {
|
if self.collapsedButton.isUserInteractionEnabled {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -301,7 +301,7 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
|||||||
}
|
}
|
||||||
|
|
||||||
@discardableResult
|
@discardableResult
|
||||||
public func openStoryCamera(customTarget: Stories.PendingTarget?, transitionIn: StoryCameraTransitionIn?, transitionedIn: @escaping () -> Void, transitionOut: @escaping (Stories.PendingTarget?, Bool) -> StoryCameraTransitionOut?) -> StoryCameraTransitionInCoordinator? {
|
public func openStoryCamera(customTarget: Stories.PendingTarget?, resumeLiveStream: Bool, transitionIn: StoryCameraTransitionIn?, transitionedIn: @escaping () -> Void, transitionOut: @escaping (Stories.PendingTarget?, Bool) -> StoryCameraTransitionOut?) -> StoryCameraTransitionInCoordinator? {
|
||||||
guard let controller = self.viewControllers.last as? ViewController else {
|
guard let controller = self.viewControllers.last as? ViewController else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -335,6 +335,7 @@ public final class TelegramRootController: NavigationController, TelegramRootCon
|
|||||||
context: context,
|
context: context,
|
||||||
mode: .story,
|
mode: .story,
|
||||||
customTarget: mediaEditorCustomTarget,
|
customTarget: mediaEditorCustomTarget,
|
||||||
|
resumeLiveStream: resumeLiveStream,
|
||||||
transitionIn: transitionIn.flatMap {
|
transitionIn: transitionIn.flatMap {
|
||||||
if let sourceView = $0.sourceView {
|
if let sourceView = $0.sourceView {
|
||||||
return CameraScreenImpl.TransitionIn(
|
return CameraScreenImpl.TransitionIn(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user