mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Add story stealth mode shortcut in chat list
This commit is contained in:
parent
28b48c1758
commit
891fed3189
@ -12134,3 +12134,6 @@ Sorry for the inconvenience.";
|
|||||||
"Channel.AdminLogFilter.Section.Messages" = "Messages";
|
"Channel.AdminLogFilter.Section.Messages" = "Messages";
|
||||||
|
|
||||||
"Premium.Gift.ContactSelection.AddBirthday" = "Add Your Birthday";
|
"Premium.Gift.ContactSelection.AddBirthday" = "Add Your Birthday";
|
||||||
|
|
||||||
|
|
||||||
|
"Story.StealthMode.EnableAndOpenAction" = "Enable and Open the Story";
|
||||||
|
@ -1012,7 +1012,7 @@ public protocol SharedAccountContext: AnyObject {
|
|||||||
func makeChatQrCodeScreen(context: AccountContext, peer: Peer, threadId: Int64?, temporary: Bool) -> ViewController
|
func makeChatQrCodeScreen(context: AccountContext, peer: Peer, threadId: Int64?, temporary: Bool) -> ViewController
|
||||||
|
|
||||||
func makePremiumIntroController(context: AccountContext, source: PremiumIntroSource, forceDark: Bool, dismissed: (() -> Void)?) -> ViewController
|
func makePremiumIntroController(context: AccountContext, source: PremiumIntroSource, forceDark: Bool, dismissed: (() -> Void)?) -> ViewController
|
||||||
func makePremiumDemoController(context: AccountContext, subject: PremiumDemoSubject, action: @escaping () -> Void) -> ViewController
|
func makePremiumDemoController(context: AccountContext, subject: PremiumDemoSubject, forceDark: Bool, action: @escaping () -> Void, dismissed: (() -> Void)?) -> ViewController
|
||||||
func makePremiumLimitController(context: AccountContext, subject: PremiumLimitSubject, count: Int32, forceDark: Bool, cancel: @escaping () -> Void, action: @escaping () -> Bool) -> ViewController
|
func makePremiumLimitController(context: AccountContext, subject: PremiumLimitSubject, count: Int32, forceDark: Bool, cancel: @escaping () -> Void, action: @escaping () -> Bool) -> ViewController
|
||||||
func makePremiumGiftController(context: AccountContext, source: PremiumGiftSource, completion: (() -> Void)?) -> ViewController
|
func makePremiumGiftController(context: AccountContext, source: PremiumGiftSource, completion: (() -> Void)?) -> ViewController
|
||||||
func makePremiumPrivacyControllerController(context: AccountContext, subject: PremiumPrivacySubject, peerId: EnginePeer.Id) -> ViewController
|
func makePremiumPrivacyControllerController(context: AccountContext, subject: PremiumPrivacySubject, peerId: EnginePeer.Id) -> ViewController
|
||||||
|
@ -72,6 +72,7 @@ public enum PremiumDemoSubject {
|
|||||||
case lastSeen
|
case lastSeen
|
||||||
case messagePrivacy
|
case messagePrivacy
|
||||||
case folderTags
|
case folderTags
|
||||||
|
case business
|
||||||
|
|
||||||
case businessLocation
|
case businessLocation
|
||||||
case businessHours
|
case businessHours
|
||||||
|
@ -103,6 +103,7 @@ swift_library(
|
|||||||
"//submodules/TelegramUI/Components/Settings/PeerNameColorItem",
|
"//submodules/TelegramUI/Components/Settings/PeerNameColorItem",
|
||||||
"//submodules/TelegramUI/Components/Settings/BirthdayPickerScreen",
|
"//submodules/TelegramUI/Components/Settings/BirthdayPickerScreen",
|
||||||
"//submodules/Components/MultilineTextComponent",
|
"//submodules/Components/MultilineTextComponent",
|
||||||
|
"//submodules/TelegramUI/Components/Stories/StoryStealthModeSheetScreen",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
@ -210,6 +210,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
|
|
||||||
private var sharedOpenStoryProgressDisposable = MetaDisposable()
|
private var sharedOpenStoryProgressDisposable = MetaDisposable()
|
||||||
|
|
||||||
|
var currentTooltipUpdateTimer: Foundation.Timer?
|
||||||
|
|
||||||
private var fullScreenEffectView: RippleEffectView?
|
private var fullScreenEffectView: RippleEffectView?
|
||||||
|
|
||||||
public override func updateNavigationCustomData(_ data: Any?, progress: CGFloat, transition: ContainedViewLayoutTransition) {
|
public override func updateNavigationCustomData(_ data: Any?, progress: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
@ -3082,20 +3084,29 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
|
|
||||||
// items.append(.action(ContextMenuActionItem(text: presentationData.strings.StoryFeed_ViewAnonymously, icon: { theme in
|
items.append(.action(ContextMenuActionItem(text: presentationData.strings.StoryFeed_ViewAnonymously, icon: { theme in
|
||||||
// return generateTintedImage(image: UIImage(bundleImageName: self.context.isPremium ? "Chat/Context Menu/Eye" : "Chat/Context Menu/EyeLocked"), color: theme.contextMenu.primaryColor)
|
return generateTintedImage(image: UIImage(bundleImageName: self.context.isPremium ? "Chat/Context Menu/Eye" : "Chat/Context Menu/EyeLocked"), color: theme.contextMenu.primaryColor)
|
||||||
// }, action: { [weak self] _, a in
|
}, action: { [weak self] _, a in
|
||||||
// a(.default)
|
a(.default)
|
||||||
//
|
|
||||||
// guard let self else {
|
guard let self else {
|
||||||
// return
|
return
|
||||||
// }
|
}
|
||||||
// if self.context.isPremium {
|
if self.context.isPremium {
|
||||||
//// self.sendMessageContext.requestStealthMode(view: self)
|
self.requestStealthMode(openStory: { [weak self] presentTooltip in
|
||||||
// } else {
|
guard let self else {
|
||||||
//// self.presentStealthModeUpgradeScreen()
|
return
|
||||||
// }
|
}
|
||||||
// })))
|
self.openStories(peerId: peer.id, completion: { storyController in
|
||||||
|
presentTooltip(storyController)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
self.presentStealthModeUpgrade(action: { [weak self] in
|
||||||
|
self?.presentUpgradeStoriesScreen()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})))
|
||||||
|
|
||||||
let hideText: String
|
let hideText: String
|
||||||
if self.location == .chatList(groupId: .archive) {
|
if self.location == .chatList(groupId: .archive) {
|
||||||
@ -3985,6 +3996,10 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func openStories(peerId: EnginePeer.Id) {
|
public func openStories(peerId: EnginePeer.Id) {
|
||||||
|
self.openStories(peerId: peerId, completion: { _ in })
|
||||||
|
}
|
||||||
|
|
||||||
|
public func openStories(peerId: EnginePeer.Id, completion: @escaping (StoryContainerScreen) -> Void = { _ in }) {
|
||||||
if let navigationBarView = self.chatListDisplayNode.navigationBarView.view as? ChatListNavigationBar.View {
|
if let navigationBarView = self.chatListDisplayNode.navigationBarView.view as? ChatListNavigationBar.View {
|
||||||
if navigationBarView.storiesUnlocked {
|
if navigationBarView.storiesUnlocked {
|
||||||
self.shouldFixStorySubscriptionOrder = true
|
self.shouldFixStorySubscriptionOrder = true
|
||||||
@ -4087,7 +4102,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||||||
self.sharedOpenStoryProgressDisposable.set(nil)
|
self.sharedOpenStoryProgressDisposable.set(nil)
|
||||||
componentView.storyPeerListView()?.setLoadingItem(peerId: peerId, signal: signal)
|
componentView.storyPeerListView()?.setLoadingItem(peerId: peerId, signal: signal)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
completion: completion
|
||||||
)
|
)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -0,0 +1,162 @@
|
|||||||
|
import Foundation
|
||||||
|
import Display
|
||||||
|
import SwiftSignalKit
|
||||||
|
import TelegramCore
|
||||||
|
import TelegramPresentationData
|
||||||
|
import AccountContext
|
||||||
|
import StoryContainerScreen
|
||||||
|
import StoryStealthModeSheetScreen
|
||||||
|
import UndoUI
|
||||||
|
|
||||||
|
extension ChatListControllerImpl {
|
||||||
|
func requestStealthMode(openStory: @escaping (@escaping (StoryContainerScreen) -> Void) -> Void) {
|
||||||
|
let context = self.context
|
||||||
|
|
||||||
|
let _ = (context.engine.data.get(
|
||||||
|
TelegramEngine.EngineData.Item.Configuration.StoryConfigurationState(),
|
||||||
|
TelegramEngine.EngineData.Item.Configuration.App()
|
||||||
|
)
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak self] config, appConfig in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let timestamp = Int32(Date().timeIntervalSince1970)
|
||||||
|
if let activeUntilTimestamp = config.stealthModeState.actualizedNow().activeUntilTimestamp, activeUntilTimestamp > timestamp {
|
||||||
|
let remainingActiveSeconds = activeUntilTimestamp - timestamp
|
||||||
|
|
||||||
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }.withUpdated(theme: defaultDarkPresentationTheme)
|
||||||
|
let text = presentationData.strings.Story_ToastStealthModeActiveText(timeIntervalString(strings: presentationData.strings, value: remainingActiveSeconds)).string
|
||||||
|
let tooltipScreen = UndoOverlayController(
|
||||||
|
presentationData: presentationData,
|
||||||
|
content: .actionSucceeded(title: presentationData.strings.Story_ToastStealthModeActiveTitle, text: text, cancel: "", destructive: false),
|
||||||
|
elevatedLayout: false,
|
||||||
|
animateInAsReplacement: false,
|
||||||
|
action: { _ in
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
tooltipScreen.tag = "no_auto_dismiss"
|
||||||
|
weak var tooltipScreenValue: UndoOverlayController? = tooltipScreen
|
||||||
|
self.currentTooltipUpdateTimer?.invalidate()
|
||||||
|
self.currentTooltipUpdateTimer = Foundation.Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { [weak self] _ in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let tooltipScreenValue else {
|
||||||
|
self.currentTooltipUpdateTimer?.invalidate()
|
||||||
|
self.currentTooltipUpdateTimer = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let timestamp = Int32(Date().timeIntervalSince1970)
|
||||||
|
let remainingActiveSeconds = max(1, activeUntilTimestamp - timestamp)
|
||||||
|
|
||||||
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }.withUpdated(theme: defaultDarkPresentationTheme)
|
||||||
|
let text = presentationData.strings.Story_ToastStealthModeActiveText(timeIntervalString(strings: presentationData.strings, value: remainingActiveSeconds)).string
|
||||||
|
tooltipScreenValue.content = .actionSucceeded(title: presentationData.strings.Story_ToastStealthModeActiveTitle, text: text, cancel: "", destructive: false)
|
||||||
|
})
|
||||||
|
|
||||||
|
openStory({ storyController in
|
||||||
|
storyController.presentExternalTooltip(tooltipScreen)
|
||||||
|
})
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let pastPeriod: Int32
|
||||||
|
let futurePeriod: Int32
|
||||||
|
if let data = appConfig.data, let futurePeriodF = data["stories_stealth_future_period"] as? Double, let pastPeriodF = data["stories_stealth_past_period"] as? Double {
|
||||||
|
futurePeriod = Int32(futurePeriodF)
|
||||||
|
pastPeriod = Int32(pastPeriodF)
|
||||||
|
} else {
|
||||||
|
pastPeriod = 5 * 60
|
||||||
|
futurePeriod = 25 * 60
|
||||||
|
}
|
||||||
|
|
||||||
|
let sheet = StoryStealthModeSheetScreen(
|
||||||
|
context: context,
|
||||||
|
mode: .control(external: true, cooldownUntilTimestamp: config.stealthModeState.actualizedNow().cooldownUntilTimestamp),
|
||||||
|
forceDark: false,
|
||||||
|
backwardDuration: pastPeriod,
|
||||||
|
forwardDuration: futurePeriod,
|
||||||
|
buttonAction: {
|
||||||
|
let _ = (context.engine.messages.enableStoryStealthMode()
|
||||||
|
|> deliverOnMainQueue).start(completed: {
|
||||||
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }.withUpdated(theme: defaultDarkPresentationTheme)
|
||||||
|
let text = presentationData.strings.Story_ToastStealthModeActivatedText(timeIntervalString(strings: presentationData.strings, value: pastPeriod), timeIntervalString(strings: presentationData.strings, value: futurePeriod)).string
|
||||||
|
let tooltipScreen = UndoOverlayController(
|
||||||
|
presentationData: presentationData,
|
||||||
|
content: .actionSucceeded(title: presentationData.strings.Story_ToastStealthModeActivatedTitle, text: text, cancel: "", destructive: false),
|
||||||
|
elevatedLayout: false,
|
||||||
|
animateInAsReplacement: false,
|
||||||
|
action: { _ in
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
openStory({ storyController in
|
||||||
|
storyController.presentExternalTooltip(tooltipScreen)
|
||||||
|
})
|
||||||
|
|
||||||
|
HapticFeedback().success()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.push(sheet)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func presentStealthModeUpgrade(action: @escaping () -> Void) {
|
||||||
|
let context = self.context
|
||||||
|
let _ = (context.engine.data.get(
|
||||||
|
TelegramEngine.EngineData.Item.Configuration.StoryConfigurationState(),
|
||||||
|
TelegramEngine.EngineData.Item.Configuration.App()
|
||||||
|
)
|
||||||
|
|> deliverOnMainQueue).start(next: { [weak self] config, appConfig in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let pastPeriod: Int32
|
||||||
|
let futurePeriod: Int32
|
||||||
|
if let data = appConfig.data, let futurePeriodF = data["stories_stealth_future_period"] as? Double, let pastPeriodF = data["stories_stealth_past_period"] as? Double {
|
||||||
|
futurePeriod = Int32(futurePeriodF)
|
||||||
|
pastPeriod = Int32(pastPeriodF)
|
||||||
|
} else {
|
||||||
|
pastPeriod = 5 * 60
|
||||||
|
futurePeriod = 25 * 60
|
||||||
|
}
|
||||||
|
|
||||||
|
let sheet = StoryStealthModeSheetScreen(
|
||||||
|
context: context,
|
||||||
|
mode: .upgrade,
|
||||||
|
forceDark: false,
|
||||||
|
backwardDuration: pastPeriod,
|
||||||
|
forwardDuration: futurePeriod,
|
||||||
|
buttonAction: {
|
||||||
|
action()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.push(sheet)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func presentUpgradeStoriesScreen() {
|
||||||
|
let context = self.context
|
||||||
|
var replaceImpl: ((ViewController) -> Void)?
|
||||||
|
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .stories, forceDark: false, action: {
|
||||||
|
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .storiesStealthMode, forceDark: false, dismissed: nil)
|
||||||
|
replaceImpl?(controller)
|
||||||
|
}, dismissed: nil)
|
||||||
|
replaceImpl = { [weak self, weak controller] c in
|
||||||
|
controller?.dismiss(animated: true, completion: {
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.push(c)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
self.push(controller)
|
||||||
|
}
|
||||||
|
}
|
@ -1579,10 +1579,10 @@ func chatListFilterPresetController(context: AccountContext, currentPreset initi
|
|||||||
},
|
},
|
||||||
openTagColorPremium: {
|
openTagColorPremium: {
|
||||||
var replaceImpl: ((ViewController) -> Void)?
|
var replaceImpl: ((ViewController) -> Void)?
|
||||||
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .folderTags, action: {
|
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .folderTags, forceDark: false, action: {
|
||||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .folderTags, forceDark: false, dismissed: nil)
|
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .folderTags, forceDark: false, dismissed: nil)
|
||||||
replaceImpl?(controller)
|
replaceImpl?(controller)
|
||||||
})
|
}, dismissed: nil)
|
||||||
replaceImpl = { [weak controller] c in
|
replaceImpl = { [weak controller] c in
|
||||||
controller?.replace(with: c)
|
controller?.replace(with: c)
|
||||||
}
|
}
|
||||||
|
@ -559,10 +559,10 @@ public func chatListFilterPresetListController(context: AccountContext, mode: Ch
|
|||||||
context.engine.peers.updateChatListFiltersDisplayTags(isEnabled: value)
|
context.engine.peers.updateChatListFiltersDisplayTags(isEnabled: value)
|
||||||
}, updateDisplayTagsLocked: {
|
}, updateDisplayTagsLocked: {
|
||||||
var replaceImpl: ((ViewController) -> Void)?
|
var replaceImpl: ((ViewController) -> Void)?
|
||||||
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .folderTags, action: {
|
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .folderTags, forceDark: false, action: {
|
||||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .folderTags, forceDark: false, dismissed: nil)
|
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .folderTags, forceDark: false, dismissed: nil)
|
||||||
replaceImpl?(controller)
|
replaceImpl?(controller)
|
||||||
})
|
}, dismissed: nil)
|
||||||
replaceImpl = { [weak controller] c in
|
replaceImpl = { [weak controller] c in
|
||||||
controller?.replace(with: c)
|
controller?.replace(with: c)
|
||||||
}
|
}
|
||||||
|
@ -1425,6 +1425,71 @@ public class PremiumDemoScreen: ViewControllerComponentContainer {
|
|||||||
case businessChatBots
|
case businessChatBots
|
||||||
case businessIntro
|
case businessIntro
|
||||||
case businessLinks
|
case businessLinks
|
||||||
|
|
||||||
|
public var perk: PremiumPerk {
|
||||||
|
switch self {
|
||||||
|
case .doubleLimits:
|
||||||
|
return .doubleLimits
|
||||||
|
case .moreUpload:
|
||||||
|
return .moreUpload
|
||||||
|
case .fasterDownload:
|
||||||
|
return .fasterDownload
|
||||||
|
case .voiceToText:
|
||||||
|
return .voiceToText
|
||||||
|
case .noAds:
|
||||||
|
return .noAds
|
||||||
|
case .uniqueReactions:
|
||||||
|
return .uniqueReactions
|
||||||
|
case .premiumStickers:
|
||||||
|
return .premiumStickers
|
||||||
|
case .advancedChatManagement:
|
||||||
|
return .advancedChatManagement
|
||||||
|
case .profileBadge:
|
||||||
|
return .profileBadge
|
||||||
|
case .animatedUserpics:
|
||||||
|
return .animatedUserpics
|
||||||
|
case .appIcons:
|
||||||
|
return .appIcons
|
||||||
|
case .animatedEmoji:
|
||||||
|
return .animatedEmoji
|
||||||
|
case .emojiStatus:
|
||||||
|
return .emojiStatus
|
||||||
|
case .translation:
|
||||||
|
return .translation
|
||||||
|
case .stories:
|
||||||
|
return .stories
|
||||||
|
case .colors:
|
||||||
|
return .colors
|
||||||
|
case .wallpapers:
|
||||||
|
return .wallpapers
|
||||||
|
case .messageTags:
|
||||||
|
return .messageTags
|
||||||
|
case .lastSeen:
|
||||||
|
return .lastSeen
|
||||||
|
case .messagePrivacy:
|
||||||
|
return .messagePrivacy
|
||||||
|
case .business:
|
||||||
|
return .business
|
||||||
|
case .folderTags:
|
||||||
|
return .folderTags
|
||||||
|
case .businessLocation:
|
||||||
|
return .businessLocation
|
||||||
|
case .businessHours:
|
||||||
|
return .businessHours
|
||||||
|
case .businessGreetingMessage:
|
||||||
|
return .businessGreetingMessage
|
||||||
|
case .businessQuickReplies:
|
||||||
|
return .businessQuickReplies
|
||||||
|
case .businessAwayMessage:
|
||||||
|
return .businessAwayMessage
|
||||||
|
case .businessChatBots:
|
||||||
|
return .businessChatBots
|
||||||
|
case .businessIntro:
|
||||||
|
return .businessIntro
|
||||||
|
case .businessLinks:
|
||||||
|
return .businessLinks
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Source: Equatable {
|
public enum Source: Equatable {
|
||||||
|
@ -369,7 +369,7 @@ private final class RecentActionsSettingsSheetComponent: Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateScrolling(transition: Transition) {
|
private func updateScrolling(isFirstTime: Bool = false, transition: Transition) {
|
||||||
guard let environment = self.environment, let controller = environment.controller(), let itemLayout = self.itemLayout else {
|
guard let environment = self.environment, let controller = environment.controller(), let itemLayout = self.itemLayout else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -389,16 +389,23 @@ private final class RecentActionsSettingsSheetComponent: Component {
|
|||||||
var topOffsetFraction = topOffset / topOffsetDistance
|
var topOffsetFraction = topOffset / topOffsetDistance
|
||||||
topOffsetFraction = max(0.0, min(1.0, topOffsetFraction))
|
topOffsetFraction = max(0.0, min(1.0, topOffsetFraction))
|
||||||
|
|
||||||
|
let modalStyleOverlayTransition: ContainedViewLayoutTransition
|
||||||
|
if isFirstTime {
|
||||||
|
modalStyleOverlayTransition = .animated(duration: 0.4, curve: .spring)
|
||||||
|
} else {
|
||||||
|
modalStyleOverlayTransition = transition.containedViewLayoutTransition
|
||||||
|
}
|
||||||
|
|
||||||
let transitionFactor: CGFloat = 1.0 - topOffsetFraction
|
let transitionFactor: CGFloat = 1.0 - topOffsetFraction
|
||||||
if self.isUpdating {
|
if self.isUpdating {
|
||||||
DispatchQueue.main.async { [weak controller] in
|
DispatchQueue.main.async { [weak controller] in
|
||||||
guard let controller else {
|
guard let controller else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
controller.updateModalStyleOverlayTransitionFactor(transitionFactor, transition: transition.containedViewLayoutTransition)
|
controller.updateModalStyleOverlayTransitionFactor(transitionFactor, transition: modalStyleOverlayTransition)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
controller.updateModalStyleOverlayTransitionFactor(transitionFactor, transition: transition.containedViewLayoutTransition)
|
controller.updateModalStyleOverlayTransitionFactor(transitionFactor, transition: modalStyleOverlayTransition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,8 +450,10 @@ private final class RecentActionsSettingsSheetComponent: Component {
|
|||||||
let resetScrolling = self.scrollView.bounds.width != availableSize.width
|
let resetScrolling = self.scrollView.bounds.width != availableSize.width
|
||||||
|
|
||||||
let sideInset: CGFloat = 16.0 + environment.safeInsets.left
|
let sideInset: CGFloat = 16.0 + environment.safeInsets.left
|
||||||
|
|
||||||
|
var isFirstTime = false
|
||||||
if self.component == nil {
|
if self.component == nil {
|
||||||
|
isFirstTime = true
|
||||||
self.selectedMembersActions = Set(MembersActionType.actionTypesFromFlags(component.initialValue.events))
|
self.selectedMembersActions = Set(MembersActionType.actionTypesFromFlags(component.initialValue.events))
|
||||||
self.selectedSettingsActions = Set(SettingsActionType.actionTypesFromFlags(component.initialValue.events))
|
self.selectedSettingsActions = Set(SettingsActionType.actionTypesFromFlags(component.initialValue.events))
|
||||||
self.selectedMessagesActions = Set(MessagesActionType.actionTypesFromFlags(component.initialValue.events))
|
self.selectedMessagesActions = Set(MessagesActionType.actionTypesFromFlags(component.initialValue.events))
|
||||||
@ -924,7 +933,7 @@ private final class RecentActionsSettingsSheetComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.ignoreScrolling = false
|
self.ignoreScrolling = false
|
||||||
self.updateScrolling(transition: transition)
|
self.updateScrolling(isFirstTime: isFirstTime, transition: transition)
|
||||||
|
|
||||||
return availableSize
|
return availableSize
|
||||||
}
|
}
|
||||||
|
@ -625,10 +625,10 @@ public final class AdsReportScreen: ViewControllerComponentContainer {
|
|||||||
})
|
})
|
||||||
case .premiumRequired:
|
case .premiumRequired:
|
||||||
var replaceImpl: ((ViewController) -> Void)?
|
var replaceImpl: ((ViewController) -> Void)?
|
||||||
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .noAds, action: {
|
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .noAds, forceDark: false, action: {
|
||||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .ads, forceDark: false, dismissed: nil)
|
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .ads, forceDark: false, dismissed: nil)
|
||||||
replaceImpl?(controller)
|
replaceImpl?(controller)
|
||||||
})
|
}, dismissed: nil)
|
||||||
replaceImpl = { [weak controller] c in
|
replaceImpl = { [weak controller] c in
|
||||||
controller?.replace(with: c)
|
controller?.replace(with: c)
|
||||||
}
|
}
|
||||||
|
@ -370,10 +370,10 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode {
|
|||||||
let tipController = UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_voiceToText", scale: 0.065, colors: [:], title: nil, text: presentationData.strings.Message_AudioTranscription_SubscribeToPremium, customUndoText: presentationData.strings.Message_AudioTranscription_SubscribeToPremiumAction, timeout: nil), elevatedLayout: false, position: .top, animateInAsReplacement: false, action: { action in
|
let tipController = UndoOverlayController(presentationData: presentationData, content: .universal(animation: "anim_voiceToText", scale: 0.065, colors: [:], title: nil, text: presentationData.strings.Message_AudioTranscription_SubscribeToPremium, customUndoText: presentationData.strings.Message_AudioTranscription_SubscribeToPremiumAction, timeout: nil), elevatedLayout: false, position: .top, animateInAsReplacement: false, action: { action in
|
||||||
if case .undo = action {
|
if case .undo = action {
|
||||||
var replaceImpl: ((ViewController) -> Void)?
|
var replaceImpl: ((ViewController) -> Void)?
|
||||||
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .voiceToText, action: {
|
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .voiceToText, forceDark: false, action: {
|
||||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .settings, forceDark: false, dismissed: nil)
|
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .settings, forceDark: false, dismissed: nil)
|
||||||
replaceImpl?(controller)
|
replaceImpl?(controller)
|
||||||
})
|
}, dismissed: nil)
|
||||||
replaceImpl = { [weak controller] c in
|
replaceImpl = { [weak controller] c in
|
||||||
controller?.replace(with: c)
|
controller?.replace(with: c)
|
||||||
}
|
}
|
||||||
@ -537,10 +537,10 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode {
|
|||||||
let tipController = UndoOverlayController(presentationData: presentationData, content: .universal(animation: "Transcribe", scale: 0.06, colors: [:], title: nil, text: text, customUndoText: nil, timeout: timeout), elevatedLayout: false, position: .top, animateInAsReplacement: false, action: { action in
|
let tipController = UndoOverlayController(presentationData: presentationData, content: .universal(animation: "Transcribe", scale: 0.06, colors: [:], title: nil, text: text, customUndoText: nil, timeout: timeout), elevatedLayout: false, position: .top, animateInAsReplacement: false, action: { action in
|
||||||
if case .info = action {
|
if case .info = action {
|
||||||
var replaceImpl: ((ViewController) -> Void)?
|
var replaceImpl: ((ViewController) -> Void)?
|
||||||
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .voiceToText, action: {
|
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .voiceToText, forceDark: false, action: {
|
||||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .settings, forceDark: false, dismissed: nil)
|
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .settings, forceDark: false, dismissed: nil)
|
||||||
replaceImpl?(controller)
|
replaceImpl?(controller)
|
||||||
})
|
}, dismissed: nil)
|
||||||
replaceImpl = { [weak controller] c in
|
replaceImpl = { [weak controller] c in
|
||||||
controller?.replace(with: c)
|
controller?.replace(with: c)
|
||||||
}
|
}
|
||||||
|
@ -1829,10 +1829,10 @@ public class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
if case .undo = action {
|
if case .undo = action {
|
||||||
let context = item.context
|
let context = item.context
|
||||||
var replaceImpl: ((ViewController) -> Void)?
|
var replaceImpl: ((ViewController) -> Void)?
|
||||||
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .voiceToText, action: {
|
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .voiceToText, forceDark: false, action: {
|
||||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .settings, forceDark: false, dismissed: nil)
|
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .settings, forceDark: false, dismissed: nil)
|
||||||
replaceImpl?(controller)
|
replaceImpl?(controller)
|
||||||
})
|
}, dismissed: nil)
|
||||||
replaceImpl = { [weak controller] c in
|
replaceImpl = { [weak controller] c in
|
||||||
controller?.replace(with: c)
|
controller?.replace(with: c)
|
||||||
}
|
}
|
||||||
@ -1941,10 +1941,10 @@ public class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
let tipController = UndoOverlayController(presentationData: presentationData, content: .universal(animation: "Transcribe", scale: 0.06, colors: [:], title: nil, text: text, customUndoText: nil, timeout: timeout), elevatedLayout: false, position: .top, animateInAsReplacement: false, action: { action in
|
let tipController = UndoOverlayController(presentationData: presentationData, content: .universal(animation: "Transcribe", scale: 0.06, colors: [:], title: nil, text: text, customUndoText: nil, timeout: timeout), elevatedLayout: false, position: .top, animateInAsReplacement: false, action: { action in
|
||||||
if case .info = action {
|
if case .info = action {
|
||||||
var replaceImpl: ((ViewController) -> Void)?
|
var replaceImpl: ((ViewController) -> Void)?
|
||||||
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .voiceToText, action: {
|
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .voiceToText, forceDark: false, action: {
|
||||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .settings, forceDark: false, dismissed: nil)
|
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .settings, forceDark: false, dismissed: nil)
|
||||||
replaceImpl?(controller)
|
replaceImpl?(controller)
|
||||||
})
|
}, dismissed: nil)
|
||||||
replaceImpl = { [weak controller] c in
|
replaceImpl = { [weak controller] c in
|
||||||
controller?.replace(with: c)
|
controller?.replace(with: c)
|
||||||
}
|
}
|
||||||
|
@ -2244,7 +2244,7 @@ struct ChatRecentActionsEntry: Comparable, Identifiable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private let deletedMessagesDisplayedLimit = 5
|
private let deletedMessagesDisplayedLimit = 4
|
||||||
|
|
||||||
func chatRecentActionsEntries(entries: [ChannelAdminEventLogEntry], presentationData: ChatPresentationData, expandedDeletedMessages: Set<EngineMessage.Id>) -> [ChatRecentActionsEntry] {
|
func chatRecentActionsEntries(entries: [ChannelAdminEventLogEntry], presentationData: ChatPresentationData, expandedDeletedMessages: Set<EngineMessage.Id>) -> [ChatRecentActionsEntry] {
|
||||||
var result: [ChatRecentActionsEntry] = []
|
var result: [ChatRecentActionsEntry] = []
|
||||||
@ -2252,7 +2252,7 @@ func chatRecentActionsEntries(entries: [ChannelAdminEventLogEntry], presentation
|
|||||||
|
|
||||||
func appendCurrentDeleteEntries() {
|
func appendCurrentDeleteEntries() {
|
||||||
if !deleteMessageEntries.isEmpty, let lastEntry = deleteMessageEntries.last, let lastMessageId = lastEntry.event.action.messageId {
|
if !deleteMessageEntries.isEmpty, let lastEntry = deleteMessageEntries.last, let lastMessageId = lastEntry.event.action.messageId {
|
||||||
let isExpandable = deleteMessageEntries.count > deletedMessagesDisplayedLimit
|
let isExpandable = deleteMessageEntries.count >= deletedMessagesDisplayedLimit
|
||||||
let isExpanded = expandedDeletedMessages.contains(lastMessageId) || !isExpandable
|
let isExpanded = expandedDeletedMessages.contains(lastMessageId) || !isExpandable
|
||||||
let isGroup = deleteMessageEntries.count > 1
|
let isGroup = deleteMessageEntries.count > 1
|
||||||
|
|
||||||
|
@ -726,10 +726,10 @@ public func PeerNameColorScreen(
|
|||||||
action: { action in
|
action: { action in
|
||||||
if case .info = action {
|
if case .info = action {
|
||||||
var replaceImpl: ((ViewController) -> Void)?
|
var replaceImpl: ((ViewController) -> Void)?
|
||||||
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .colors, action: {
|
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .colors, forceDark: false, action: {
|
||||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .settings, forceDark: false, dismissed: nil)
|
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .settings, forceDark: false, dismissed: nil)
|
||||||
replaceImpl?(controller)
|
replaceImpl?(controller)
|
||||||
})
|
}, dismissed: nil)
|
||||||
replaceImpl = { [weak controller] c in
|
replaceImpl = { [weak controller] c in
|
||||||
controller?.replace(with: c)
|
controller?.replace(with: c)
|
||||||
}
|
}
|
||||||
|
@ -527,10 +527,10 @@ public class WallpaperGalleryController: ViewController {
|
|||||||
if forBoth && !strongSelf.context.isPremium {
|
if forBoth && !strongSelf.context.isPremium {
|
||||||
let context = strongSelf.context
|
let context = strongSelf.context
|
||||||
var replaceImpl: ((ViewController) -> Void)?
|
var replaceImpl: ((ViewController) -> Void)?
|
||||||
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .wallpapers, action: {
|
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .wallpapers, forceDark: false, action: {
|
||||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .wallpapers, forceDark: false, dismissed: nil)
|
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .wallpapers, forceDark: false, dismissed: nil)
|
||||||
replaceImpl?(controller)
|
replaceImpl?(controller)
|
||||||
})
|
}, dismissed: nil)
|
||||||
replaceImpl = { [weak controller] c in
|
replaceImpl = { [weak controller] c in
|
||||||
controller?.replace(with: c)
|
controller?.replace(with: c)
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,8 @@ public extension StoryContainerScreen {
|
|||||||
transitionIn: @escaping () -> StoryContainerScreen.TransitionIn?,
|
transitionIn: @escaping () -> StoryContainerScreen.TransitionIn?,
|
||||||
transitionOut: @escaping (EnginePeer.Id) -> StoryContainerScreen.TransitionOut?,
|
transitionOut: @escaping (EnginePeer.Id) -> StoryContainerScreen.TransitionOut?,
|
||||||
setFocusedItem: @escaping (Signal<StoryId?, NoError>) -> Void,
|
setFocusedItem: @escaping (Signal<StoryId?, NoError>) -> Void,
|
||||||
setProgress: @escaping (Signal<Never, NoError>) -> Void
|
setProgress: @escaping (Signal<Never, NoError>) -> Void,
|
||||||
|
completion: @escaping (StoryContainerScreen) -> Void = { _ in }
|
||||||
) {
|
) {
|
||||||
let storyContent = StoryContentContextImpl(context: context, isHidden: isHidden, focusedPeerId: peerId, singlePeer: singlePeer, fixedOrder: initialOrder)
|
let storyContent = StoryContentContextImpl(context: context, isHidden: isHidden, focusedPeerId: peerId, singlePeer: singlePeer, fixedOrder: initialOrder)
|
||||||
let signal = storyContent.state
|
let signal = storyContent.state
|
||||||
@ -211,6 +212,7 @@ public extension StoryContainerScreen {
|
|||||||
)
|
)
|
||||||
setFocusedItem(storyContainerScreen.focusedItem)
|
setFocusedItem(storyContainerScreen.focusedItem)
|
||||||
parentController?.push(storyContainerScreen)
|
parentController?.push(storyContainerScreen)
|
||||||
|
completion(storyContainerScreen)
|
||||||
}
|
}
|
||||||
|> ignoreValues
|
|> ignoreValues
|
||||||
|
|
||||||
|
@ -1223,6 +1223,16 @@ private final class StoryContainerScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func presentExternalTooltip(_ tooltipScreen: UndoOverlayController) {
|
||||||
|
guard let stateValue = self.stateValue, let slice = stateValue.slice, let itemSetView = self.visibleItemSetViews[slice.peer.id], let itemSetComponentView = itemSetView.view.view as? StoryItemSetContainerComponent.View else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
itemSetComponentView.sendMessageContext.tooltipScreen = tooltipScreen
|
||||||
|
itemSetComponentView.updateIsProgressPaused()
|
||||||
|
|
||||||
|
self.environment?.controller()?.present(tooltipScreen, in: .current)
|
||||||
|
}
|
||||||
|
|
||||||
func update(component: StoryContainerScreenComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<ViewControllerComponentContainer.Environment>, transition: Transition) -> CGSize {
|
func update(component: StoryContainerScreenComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<ViewControllerComponentContainer.Environment>, transition: Transition) -> CGSize {
|
||||||
if self.didAnimateOut {
|
if self.didAnimateOut {
|
||||||
return availableSize
|
return availableSize
|
||||||
@ -2057,6 +2067,12 @@ public class StoryContainerScreen: ViewControllerComponentContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func presentExternalTooltip(_ tooltipScreen: UndoOverlayController) {
|
||||||
|
if let componentView = self.node.hostView.componentView as? StoryContainerScreenComponent.View {
|
||||||
|
componentView.presentExternalTooltip(tooltipScreen)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func dismissWithoutTransitionOut() {
|
func dismissWithoutTransitionOut() {
|
||||||
self.focusedItemPromise.set(.single(nil))
|
self.focusedItemPromise.set(.single(nil))
|
||||||
|
|
||||||
|
@ -5757,22 +5757,27 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private func presentStoriesUpgradeScreen(source: PremiumSource) {
|
private func presentStoriesUpgradeScreen(source: PremiumIntroSource) {
|
||||||
guard let component = self.component else {
|
guard let component = self.component else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let context = component.context
|
let context = component.context
|
||||||
var replaceImpl: ((ViewController) -> Void)?
|
var replaceImpl: ((ViewController) -> Void)?
|
||||||
let controller = PremiumLimitsListScreen(context: context, subject: .stories, source: .other, order: [.stories], buttonText: component.strings.Story_PremiumUpgradeStoriesButton, isPremium: false, forceDark: true)
|
var dismissedImpl: (() -> Void)?
|
||||||
controller.action = { [weak self] in
|
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .stories, forceDark: true, action: { [weak self] in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let controller = PremiumIntroScreen(context: context, source: source, forceDark: true)
|
var dismissedImpl: (() -> Void)?
|
||||||
|
let controller = context.sharedContext.makePremiumIntroController(context: context, source: source, forceDark: true, dismissed: {
|
||||||
|
dismissedImpl?()
|
||||||
|
})
|
||||||
self.sendMessageContext.actionSheet = controller
|
self.sendMessageContext.actionSheet = controller
|
||||||
controller.wasDismissed = { [weak self, weak controller]in
|
replaceImpl?(controller)
|
||||||
|
|
||||||
|
dismissedImpl = { [weak self, weak controller] in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -5782,10 +5787,10 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
}
|
}
|
||||||
self.updateIsProgressPaused()
|
self.updateIsProgressPaused()
|
||||||
}
|
}
|
||||||
|
}, dismissed: {
|
||||||
replaceImpl?(controller)
|
dismissedImpl?()
|
||||||
}
|
})
|
||||||
controller.disposed = { [weak self, weak controller] in
|
dismissedImpl = { [weak self, weak controller] in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -3186,7 +3186,8 @@ final class StoryItemSetContainerSendMessage {
|
|||||||
|
|
||||||
let sheet = StoryStealthModeSheetScreen(
|
let sheet = StoryStealthModeSheetScreen(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
mode: .control(cooldownUntilTimestamp: config.stealthModeState.actualizedNow().cooldownUntilTimestamp),
|
mode: .control(external: false, cooldownUntilTimestamp: config.stealthModeState.actualizedNow().cooldownUntilTimestamp),
|
||||||
|
forceDark: true,
|
||||||
backwardDuration: pastPeriod,
|
backwardDuration: pastPeriod,
|
||||||
forwardDuration: futurePeriod,
|
forwardDuration: futurePeriod,
|
||||||
buttonAction: { [weak self, weak view] in
|
buttonAction: { [weak self, weak view] in
|
||||||
@ -3261,6 +3262,7 @@ final class StoryItemSetContainerSendMessage {
|
|||||||
let sheet = StoryStealthModeSheetScreen(
|
let sheet = StoryStealthModeSheetScreen(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
mode: .upgrade,
|
mode: .upgrade,
|
||||||
|
forceDark: true,
|
||||||
backwardDuration: pastPeriod,
|
backwardDuration: pastPeriod,
|
||||||
forwardDuration: futurePeriod,
|
forwardDuration: futurePeriod,
|
||||||
buttonAction: {
|
buttonAction: {
|
||||||
|
@ -100,7 +100,7 @@ private final class StoryStealthModeSheetContentComponent: Component {
|
|||||||
self.state = state
|
self.state = state
|
||||||
|
|
||||||
var remainingCooldownSeconds: Int32 = 0
|
var remainingCooldownSeconds: Int32 = 0
|
||||||
if case let .control(cooldownUntilTimestamp) = component.mode {
|
if case let .control(_, cooldownUntilTimestamp) = component.mode {
|
||||||
if let cooldownUntilTimestamp {
|
if let cooldownUntilTimestamp {
|
||||||
remainingCooldownSeconds = cooldownUntilTimestamp - Int32(Date().timeIntervalSince1970)
|
remainingCooldownSeconds = cooldownUntilTimestamp - Int32(Date().timeIntervalSince1970)
|
||||||
remainingCooldownSeconds = max(0, remainingCooldownSeconds)
|
remainingCooldownSeconds = max(0, remainingCooldownSeconds)
|
||||||
@ -243,9 +243,9 @@ private final class StoryStealthModeSheetContentComponent: Component {
|
|||||||
let buttonText: String
|
let buttonText: String
|
||||||
let content: AnyComponentWithIdentity<Empty>
|
let content: AnyComponentWithIdentity<Empty>
|
||||||
switch component.mode {
|
switch component.mode {
|
||||||
case .control:
|
case let .control(external, _):
|
||||||
if remainingCooldownSeconds <= 0 {
|
if remainingCooldownSeconds <= 0 {
|
||||||
buttonText = environment.strings.Story_StealthMode_EnableAction
|
buttonText = external ? environment.strings.Story_StealthMode_EnableAndOpenAction : environment.strings.Story_StealthMode_EnableAction
|
||||||
} else {
|
} else {
|
||||||
buttonText = environment.strings.Story_StealthMode_CooldownAction(stringForDuration(remainingCooldownSeconds)).string
|
buttonText = environment.strings.Story_StealthMode_CooldownAction(stringForDuration(remainingCooldownSeconds)).string
|
||||||
}
|
}
|
||||||
@ -283,7 +283,7 @@ private final class StoryStealthModeSheetContentComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch component.mode {
|
switch component.mode {
|
||||||
case let .control(cooldownUntilTimestamp):
|
case let .control(_, cooldownUntilTimestamp):
|
||||||
var remainingCooldownSeconds: Int32 = 0
|
var remainingCooldownSeconds: Int32 = 0
|
||||||
if let cooldownUntilTimestamp {
|
if let cooldownUntilTimestamp {
|
||||||
remainingCooldownSeconds = cooldownUntilTimestamp - Int32(Date().timeIntervalSince1970)
|
remainingCooldownSeconds = cooldownUntilTimestamp - Int32(Date().timeIntervalSince1970)
|
||||||
@ -468,13 +468,14 @@ private final class StoryStealthModeSheetScreenComponent: Component {
|
|||||||
|
|
||||||
public class StoryStealthModeSheetScreen: ViewControllerComponentContainer {
|
public class StoryStealthModeSheetScreen: ViewControllerComponentContainer {
|
||||||
public enum Mode: Equatable {
|
public enum Mode: Equatable {
|
||||||
case control(cooldownUntilTimestamp: Int32?)
|
case control(external: Bool, cooldownUntilTimestamp: Int32?)
|
||||||
case upgrade
|
case upgrade
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
context: AccountContext,
|
context: AccountContext,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
|
forceDark: Bool,
|
||||||
backwardDuration: Int32,
|
backwardDuration: Int32,
|
||||||
forwardDuration: Int32,
|
forwardDuration: Int32,
|
||||||
buttonAction: (() -> Void)? = nil
|
buttonAction: (() -> Void)? = nil
|
||||||
@ -485,7 +486,7 @@ public class StoryStealthModeSheetScreen: ViewControllerComponentContainer {
|
|||||||
backwardDuration: backwardDuration,
|
backwardDuration: backwardDuration,
|
||||||
forwardDuration: forwardDuration,
|
forwardDuration: forwardDuration,
|
||||||
buttonAction: buttonAction
|
buttonAction: buttonAction
|
||||||
), navigationBarAppearance: .none, theme: .dark)
|
), navigationBarAppearance: .none, theme: forceDark ? .dark : .default)
|
||||||
|
|
||||||
self.statusBar.statusBarStyle = .Ignore
|
self.statusBar.statusBarStyle = .Ignore
|
||||||
self.navigationPresentation = .flatModal
|
self.navigationPresentation = .flatModal
|
||||||
|
@ -11930,10 +11930,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
case .info:
|
case .info:
|
||||||
let context = self.context
|
let context = self.context
|
||||||
var replaceImpl: ((ViewController) -> Void)?
|
var replaceImpl: ((ViewController) -> Void)?
|
||||||
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .fasterDownload, action: {
|
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .fasterDownload, forceDark: false, action: {
|
||||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .fasterDownload, forceDark: false, dismissed: nil)
|
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .fasterDownload, forceDark: false, dismissed: nil)
|
||||||
replaceImpl?(controller)
|
replaceImpl?(controller)
|
||||||
})
|
}, dismissed: nil)
|
||||||
replaceImpl = { [weak controller] c in
|
replaceImpl = { [weak controller] c in
|
||||||
controller?.replace(with: c)
|
controller?.replace(with: c)
|
||||||
}
|
}
|
||||||
|
@ -591,10 +591,10 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
|||||||
}, iconSource: nil, action: { c, _ in
|
}, iconSource: nil, action: { c, _ in
|
||||||
c.dismiss(completion: {
|
c.dismiss(completion: {
|
||||||
var replaceImpl: ((ViewController) -> Void)?
|
var replaceImpl: ((ViewController) -> Void)?
|
||||||
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .noAds, action: {
|
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .noAds, forceDark: false, action: {
|
||||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .ads, forceDark: false, dismissed: nil)
|
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .ads, forceDark: false, dismissed: nil)
|
||||||
replaceImpl?(controller)
|
replaceImpl?(controller)
|
||||||
})
|
}, dismissed: nil)
|
||||||
replaceImpl = { [weak controller] c in
|
replaceImpl = { [weak controller] c in
|
||||||
controller?.replace(with: c)
|
controller?.replace(with: c)
|
||||||
}
|
}
|
||||||
@ -1088,10 +1088,10 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
|||||||
}, action: { _, f in
|
}, action: { _, f in
|
||||||
let context = context
|
let context = context
|
||||||
var replaceImpl: ((ViewController) -> Void)?
|
var replaceImpl: ((ViewController) -> Void)?
|
||||||
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .fasterDownload, action: {
|
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .fasterDownload, forceDark: false, action: {
|
||||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .fasterDownload, forceDark: false, dismissed: nil)
|
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .fasterDownload, forceDark: false, dismissed: nil)
|
||||||
replaceImpl?(controller)
|
replaceImpl?(controller)
|
||||||
})
|
}, dismissed: nil)
|
||||||
replaceImpl = { [weak controller] c in
|
replaceImpl = { [weak controller] c in
|
||||||
controller?.replace(with: c)
|
controller?.replace(with: c)
|
||||||
}
|
}
|
||||||
|
@ -2062,7 +2062,9 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
return controller
|
return controller
|
||||||
}
|
}
|
||||||
|
|
||||||
public func makePremiumDemoController(context: AccountContext, subject: PremiumDemoSubject, action: @escaping () -> Void) -> ViewController {
|
public func makePremiumDemoController(context: AccountContext, subject: PremiumDemoSubject, forceDark: Bool, action: @escaping () -> Void, dismissed: (() -> Void)?) -> ViewController {
|
||||||
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
var buttonText: String = presentationData.strings.Common_OK
|
||||||
let mappedSubject: PremiumDemoScreen.Subject
|
let mappedSubject: PremiumDemoScreen.Subject
|
||||||
switch subject {
|
switch subject {
|
||||||
case .doubleLimits:
|
case .doubleLimits:
|
||||||
@ -2095,6 +2097,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
mappedSubject = .translation
|
mappedSubject = .translation
|
||||||
case .stories:
|
case .stories:
|
||||||
mappedSubject = .stories
|
mappedSubject = .stories
|
||||||
|
buttonText = presentationData.strings.Story_PremiumUpgradeStoriesButton
|
||||||
case .colors:
|
case .colors:
|
||||||
mappedSubject = .colors
|
mappedSubject = .colors
|
||||||
case .wallpapers:
|
case .wallpapers:
|
||||||
@ -2107,10 +2110,24 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
mappedSubject = .messagePrivacy
|
mappedSubject = .messagePrivacy
|
||||||
case .folderTags:
|
case .folderTags:
|
||||||
mappedSubject = .folderTags
|
mappedSubject = .folderTags
|
||||||
|
case .business:
|
||||||
|
mappedSubject = .business
|
||||||
|
buttonText = presentationData.strings.Chat_EmptyStateIntroFooterPremiumActionButton
|
||||||
default:
|
default:
|
||||||
mappedSubject = .doubleLimits
|
mappedSubject = .doubleLimits
|
||||||
}
|
}
|
||||||
return PremiumDemoScreen(context: context, subject: mappedSubject, action: action)
|
|
||||||
|
switch mappedSubject {
|
||||||
|
case .stories, .business, .doubleLimits:
|
||||||
|
let controller = PremiumLimitsListScreen(context: context, subject: mappedSubject, source: .other, order: [mappedSubject.perk], buttonText: buttonText, isPremium: false, forceDark: forceDark)
|
||||||
|
controller.action = action
|
||||||
|
if let dismissed {
|
||||||
|
controller.disposed = dismissed
|
||||||
|
}
|
||||||
|
return controller
|
||||||
|
default:
|
||||||
|
return PremiumDemoScreen(context: context, subject: mappedSubject, action: action)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func makePremiumLimitController(context: AccountContext, subject: PremiumLimitSubject, count: Int32, forceDark: Bool, cancel: @escaping () -> Void, action: @escaping () -> Bool) -> ViewController {
|
public func makePremiumLimitController(context: AccountContext, subject: PremiumLimitSubject, count: Int32, forceDark: Bool, cancel: @escaping () -> Void, action: @escaping () -> Bool) -> ViewController {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user