mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
Various fixes
This commit is contained in:
parent
92f2ff623b
commit
c8d483a2c7
15 changed files with 131 additions and 32 deletions
|
|
@ -10496,6 +10496,7 @@ Sorry for the inconvenience.";
|
|||
|
||||
"Premium.VoiceToText.Proceed" = "About Telegram Premium";
|
||||
"Premium.Wallpaper.Proceed" = "About Telegram Premium";
|
||||
"Premium.Colors.Proceed" = "About Telegram Premium";
|
||||
|
||||
"Notification.YouChangedWallpaperBoth" = "You set a new wallpaper for %@ and you.";
|
||||
|
||||
|
|
|
|||
|
|
@ -1003,6 +1003,7 @@ public enum PremiumIntroSource {
|
|||
case channelBoost(EnginePeer.Id)
|
||||
case nameColor
|
||||
case similarChannels
|
||||
case wallpapers
|
||||
}
|
||||
|
||||
public enum PremiumDemoSubject {
|
||||
|
|
|
|||
|
|
@ -1080,6 +1080,8 @@ private final class DemoSheetContent: CombinedComponent {
|
|||
buttonText = strings.Premium_VoiceToText_Proceed
|
||||
case .wallpapers:
|
||||
buttonText = strings.Premium_Wallpaper_Proceed
|
||||
case .colors:
|
||||
buttonText = strings.Premium_Colors_Proceed
|
||||
default:
|
||||
buttonText = strings.Common_OK
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,6 +245,12 @@ public enum PremiumSource: Equatable {
|
|||
} else {
|
||||
return false
|
||||
}
|
||||
case .wallpapers:
|
||||
if case .wallpapers = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -284,6 +290,7 @@ public enum PremiumSource: Equatable {
|
|||
case channelBoost(EnginePeer.Id)
|
||||
case nameColor
|
||||
case similarChannels
|
||||
case wallpapers
|
||||
|
||||
var identifier: String? {
|
||||
switch self {
|
||||
|
|
@ -361,6 +368,8 @@ public enum PremiumSource: Equatable {
|
|||
return "name_color"
|
||||
case .similarChannels:
|
||||
return "similar_channels"
|
||||
case .wallpapers:
|
||||
return "wallpapers"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -521,7 +521,7 @@ public class WallpaperGalleryController: ViewController {
|
|||
let context = strongSelf.context
|
||||
var replaceImpl: ((ViewController) -> Void)?
|
||||
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .wallpapers, action: {
|
||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .settings, forceDark: false, dismissed: nil)
|
||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .wallpapers, forceDark: false, dismissed: nil)
|
||||
replaceImpl?(controller)
|
||||
})
|
||||
replaceImpl = { [weak controller] c in
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import UIKit
|
|||
import Display
|
||||
import SwiftSignalKit
|
||||
import AsyncDisplayKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import TelegramPresentationData
|
||||
import TelegramUIPreferences
|
||||
|
|
@ -14,6 +15,7 @@ import AccountContext
|
|||
import PresentationDataUtils
|
||||
import AppBundle
|
||||
import GraphUI
|
||||
import StoryContainerScreen
|
||||
|
||||
private final class MessageStatsControllerArguments {
|
||||
let context: AccountContext
|
||||
|
|
@ -275,10 +277,14 @@ public func messageStatsController(context: AccountContext, updatedPresentationD
|
|||
let anyStatsContext: Any
|
||||
let dataSignal: Signal<PostStats?, NoError>
|
||||
var loadDetailedGraphImpl: ((StatsGraph, Int64) -> Signal<StatsGraph?, NoError>)?
|
||||
var openStoryImpl: ((EngineStoryItem, UIView) -> Void)?
|
||||
|
||||
var forwardsContext: StoryStatsPublicForwardsContext?
|
||||
let peerId: EnginePeer.Id
|
||||
var storyItem: EngineStoryItem?
|
||||
switch subject {
|
||||
case let .message(id):
|
||||
peerId = id.peerId
|
||||
let statsContext = MessageStatsContext(account: context.account, messageId: id)
|
||||
loadDetailedGraphImpl = { [weak statsContext] graph, x in
|
||||
return statsContext?.loadDetailedGraph(graph, x: x) ?? .single(nil)
|
||||
|
|
@ -303,7 +309,10 @@ public func messageStatsController(context: AccountContext, updatedPresentationD
|
|||
}
|
||||
messagesPromise.set(.single(nil) |> then(searchSignal))
|
||||
forwardsPromise.set(.single(nil))
|
||||
case let .story(peerId, id, _, _):
|
||||
case let .story(peerIdValue, id, item, _):
|
||||
peerId = peerIdValue
|
||||
storyItem = item
|
||||
|
||||
let statsContext = StoryStatsContext(account: context.account, peerId: peerId, storyId: id)
|
||||
loadDetailedGraphImpl = { [weak statsContext] graph, x in
|
||||
return statsContext?.loadDetailedGraph(graph, x: x) ?? .single(nil)
|
||||
|
|
@ -392,7 +401,11 @@ public func messageStatsController(context: AccountContext, updatedPresentationD
|
|||
storyViews = storyItem.views
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: nil, rightNavigationButton: iconNode.flatMap { ItemListNavigationButton(content: .node($0), style: .regular, enabled: true, action: { }) }, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: nil, rightNavigationButton: iconNode.flatMap { ItemListNavigationButton(content: .node($0), style: .regular, enabled: true, action: { [weak iconNode] in
|
||||
if let iconNode, let storyItem {
|
||||
openStoryImpl?(storyItem, iconNode.view)
|
||||
}
|
||||
}) }, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: messageStatsControllerEntries(data: data, storyViews: storyViews, messages: search?.0, forwards: forwards, presentationData: presentationData), style: .blocks, emptyStateItem: emptyStateItem, crossfadeState: previous == nil, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
|
|
@ -432,5 +445,65 @@ public func messageStatsController(context: AccountContext, updatedPresentationD
|
|||
}
|
||||
})
|
||||
}
|
||||
openStoryImpl = { [weak controller] story, sourceView in
|
||||
let storyContent = SingleStoryContentContextImpl(context: context, storyId: StoryId(peerId: peerId, id: story.id), storyItem: story, readGlobally: false)
|
||||
let _ = (storyContent.state
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).startStandalone(next: { [weak controller, weak sourceView] _ in
|
||||
guard let controller, let sourceView else {
|
||||
return
|
||||
}
|
||||
let transitionIn = StoryContainerScreen.TransitionIn(
|
||||
sourceView: sourceView,
|
||||
sourceRect: sourceView.bounds,
|
||||
sourceCornerRadius: sourceView.bounds.width * 0.5,
|
||||
sourceIsAvatar: false
|
||||
)
|
||||
|
||||
let storyContainerScreen = StoryContainerScreen(
|
||||
context: context,
|
||||
content: storyContent,
|
||||
transitionIn: transitionIn,
|
||||
transitionOut: { [weak sourceView] peerId, storyIdValue in
|
||||
if let sourceView {
|
||||
let destinationView = sourceView
|
||||
return StoryContainerScreen.TransitionOut(
|
||||
destinationView: destinationView,
|
||||
transitionView: StoryContainerScreen.TransitionView(
|
||||
makeView: { [weak destinationView] in
|
||||
let parentView = UIView()
|
||||
if let copyView = destinationView?.snapshotContentTree(unhide: true) {
|
||||
parentView.addSubview(copyView)
|
||||
}
|
||||
return parentView
|
||||
},
|
||||
updateView: { copyView, state, transition in
|
||||
guard let view = copyView.subviews.first else {
|
||||
return
|
||||
}
|
||||
let size = state.sourceSize.interpolate(to: state.destinationSize, amount: state.progress)
|
||||
transition.setPosition(view: view, position: CGPoint(x: size.width * 0.5, y: size.height * 0.5))
|
||||
transition.setScale(view: view, scale: size.width / state.destinationSize.width)
|
||||
},
|
||||
insertCloneTransitionView: nil
|
||||
),
|
||||
destinationRect: destinationView.bounds,
|
||||
destinationCornerRadius: destinationView.bounds.width * 0.5,
|
||||
destinationIsAvatar: false,
|
||||
completed: { [weak sourceView] in
|
||||
guard let sourceView else {
|
||||
return
|
||||
}
|
||||
sourceView.isHidden = false
|
||||
}
|
||||
)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
)
|
||||
controller.push(storyContainerScreen)
|
||||
})
|
||||
}
|
||||
return controller
|
||||
}
|
||||
|
|
|
|||
|
|
@ -339,8 +339,11 @@ public final class ChatMessageInteractiveFileNode: ASDisplayNode {
|
|||
return
|
||||
}
|
||||
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
if !context.isPremium, case .inProgress = self.audioTranscriptionState {
|
||||
return
|
||||
}
|
||||
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: arguments.context.currentAppConfiguration.with { $0 })
|
||||
|
||||
let transcriptionText = self.forcedAudioTranscriptionText ?? transcribedText(message: message)
|
||||
|
|
|
|||
|
|
@ -1622,8 +1622,11 @@ public class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||
return
|
||||
}
|
||||
|
||||
if !item.context.isPremium, case .inProgress = self.audioTranscriptionState {
|
||||
return
|
||||
}
|
||||
|
||||
let presentationData = item.context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: item.context.currentAppConfiguration.with { $0 })
|
||||
|
||||
let transcriptionText = transcribedText(message: item.message)
|
||||
|
|
|
|||
|
|
@ -4038,7 +4038,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate
|
|||
let subject: Signal<Subject?, NoError>
|
||||
let isEditingStory: Bool
|
||||
fileprivate let customTarget: EnginePeer.Id?
|
||||
fileprivate let forwardSource: (EnginePeer, EngineStoryItem)?
|
||||
let forwardSource: (EnginePeer, EngineStoryItem)?
|
||||
|
||||
fileprivate let initialCaption: NSAttributedString?
|
||||
fileprivate let initialPrivacy: EngineStoryPrivacy?
|
||||
|
|
|
|||
|
|
@ -201,6 +201,10 @@ final class MediaScrubberComponent: Component {
|
|||
component.trackTrimUpdated(0, startValue, endValue, updatedEnd, done)
|
||||
}
|
||||
}
|
||||
|
||||
let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(self.longPressed(_:)))
|
||||
longPressGesture.delegate = self
|
||||
self.addGestureRecognizer(longPressGesture)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
|
|
@ -265,6 +269,19 @@ final class MediaScrubberComponent: Component {
|
|||
}
|
||||
return firstTrack.offset
|
||||
}
|
||||
|
||||
@objc private func longPressed(_ gestureRecognizer: UILongPressGestureRecognizer) {
|
||||
guard let component = self.component, case .began = gestureRecognizer.state else {
|
||||
return
|
||||
}
|
||||
let point = gestureRecognizer.location(in: self)
|
||||
for (id, trackView) in self.trackViews {
|
||||
if trackView.frame.contains(point) {
|
||||
component.trackLongPressed(id, trackView.clippingView)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func handleCursorPan(_ gestureRecognizer: UIPanGestureRecognizer) {
|
||||
guard let component = self.component else {
|
||||
|
|
@ -387,12 +404,6 @@ final class MediaScrubberComponent: Component {
|
|||
self.selectedTrackId = id
|
||||
self.state?.updated(transition: .easeInOut(duration: 0.2))
|
||||
}
|
||||
trackView.onLongPress = { [weak self] id, sourceView in
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
}
|
||||
component.trackLongPressed(id, sourceView)
|
||||
}
|
||||
trackView.offsetUpdated = { [weak self] offset, apply in
|
||||
guard let self, let component = self.component else {
|
||||
return
|
||||
|
|
@ -617,7 +628,6 @@ private class TrackView: UIView, UIScrollViewDelegate, UIGestureRecognizerDelega
|
|||
fileprivate var videoOpaqueFrameLayers: [VideoFrameLayer] = []
|
||||
|
||||
var onSelection: (Int32) -> Void = { _ in }
|
||||
var onLongPress: (Int32, UIView) -> Void = { _, _ in }
|
||||
var offsetUpdated: (Double, Bool) -> Void = { _, _ in }
|
||||
var updated: (Transition) -> Void = { _ in }
|
||||
|
||||
|
|
@ -684,11 +694,7 @@ private class TrackView: UIView, UIScrollViewDelegate, UIGestureRecognizerDelega
|
|||
self.clippingView.addSubview(self.scrollView)
|
||||
self.scrollView.addSubview(self.containerView)
|
||||
self.backgroundView.addSubview(self.vibrancyView)
|
||||
|
||||
let longPressGesture = UILongPressGestureRecognizer(target: self, action: #selector(self.longPressed(_:)))
|
||||
longPressGesture.delegate = self
|
||||
self.addGestureRecognizer(longPressGesture)
|
||||
|
||||
|
||||
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
|
||||
self.addGestureRecognizer(tapGesture)
|
||||
|
||||
|
|
@ -699,13 +705,6 @@ private class TrackView: UIView, UIScrollViewDelegate, UIGestureRecognizerDelega
|
|||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
@objc private func longPressed(_ gestureRecognizer: UILongPressGestureRecognizer) {
|
||||
guard let (track, _, _) = self.params, case .began = gestureRecognizer.state else {
|
||||
return
|
||||
}
|
||||
self.onLongPress(track.id, self.clippingView)
|
||||
}
|
||||
|
||||
@objc private func handleTap(_ gestureRecognizer: UITapGestureRecognizer) {
|
||||
guard let (track, _, _) = self.params else {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -712,7 +712,14 @@ public func PeerNameColorScreen(
|
|||
elevatedLayout: false,
|
||||
action: { action in
|
||||
if case .info = action {
|
||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .nameColor, forceDark: false, dismissed: nil)
|
||||
var replaceImpl: ((ViewController) -> Void)?
|
||||
let controller = context.sharedContext.makePremiumDemoController(context: context, subject: .colors, action: {
|
||||
let controller = context.sharedContext.makePremiumIntroController(context: context, source: .settings, forceDark: false, dismissed: nil)
|
||||
replaceImpl?(controller)
|
||||
})
|
||||
replaceImpl = { [weak controller] c in
|
||||
controller?.replace(with: c)
|
||||
}
|
||||
pushImpl?(controller)
|
||||
}
|
||||
return true
|
||||
|
|
|
|||
BIN
submodules/TelegramUI/Resources/Animations/PremiumStar.tgs
Normal file
BIN
submodules/TelegramUI/Resources/Animations/PremiumStar.tgs
Normal file
Binary file not shown.
|
|
@ -2459,6 +2459,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
}, presentController: { [weak self] controller, arguments in
|
||||
self?.present(controller, in: .window(.root), with: arguments)
|
||||
}, presentControllerInCurrent: { [weak self] controller, arguments in
|
||||
if controller is UndoOverlayController {
|
||||
self?.dismissAllTooltips()
|
||||
}
|
||||
self?.present(controller, in: .current, with: arguments)
|
||||
}, navigationController: { [weak self] in
|
||||
return self?.navigationController as? NavigationController
|
||||
|
|
|
|||
|
|
@ -1783,6 +1783,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||
mappedSource = .nameColor
|
||||
case .similarChannels:
|
||||
mappedSource = .similarChannels
|
||||
case .wallpapers:
|
||||
mappedSource = .wallpapers
|
||||
}
|
||||
let controller = PremiumIntroScreen(context: context, source: mappedSource, forceDark: forceDark)
|
||||
controller.wasDismissed = dismissed
|
||||
|
|
|
|||
|
|
@ -963,7 +963,6 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
|||
self.avatarNode = nil
|
||||
self.iconNode = nil
|
||||
self.iconCheckNode = nil
|
||||
|
||||
self.animationNode = AnimationNode(animation: animation, colors: colors, scale: scale)
|
||||
self.animatedStickerNode = nil
|
||||
|
||||
|
|
@ -1007,12 +1006,9 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
|||
}
|
||||
case let .premiumPaywall(title, text, customUndoText, timeout, linkAction):
|
||||
self.avatarNode = nil
|
||||
self.iconNode = ASImageNode()
|
||||
self.iconNode?.displayWithoutProcessing = true
|
||||
self.iconNode?.displaysAsynchronously = false
|
||||
self.iconNode?.image = generateTintedImage(image: UIImage(bundleImageName: "Peer Info/PremiumIcon"), color: .white)
|
||||
self.iconNode = nil
|
||||
self.iconCheckNode = nil
|
||||
self.animationNode = nil
|
||||
self.animationNode = AnimationNode(animation: "PremiumStar", colors: [:], scale: 0.066)
|
||||
self.animatedStickerNode = nil
|
||||
|
||||
if let title = title, text.isEmpty {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue