Various fixes

This commit is contained in:
Ilya Laktyushin 2024-09-26 15:18:34 +04:00
parent a30ab38ce4
commit 072c6bc3c4
11 changed files with 170 additions and 59 deletions

View File

@ -979,6 +979,7 @@ public protocol SharedAccountContext: AnyObject {
func makeStarsGiftController(context: AccountContext, birthdays: [EnginePeer.Id: TelegramBirthday]?, completion: @escaping (([EnginePeer.Id]) -> Void)) -> ViewController
func makePremiumGiftController(context: AccountContext, source: PremiumGiftSource, completion: (([EnginePeer.Id]) -> Void)?) -> ViewController
func makeGiftOptionsController(context: AccountContext, peerId: EnginePeer.Id, premiumOptions: [CachedPremiumGiftOption]) -> ViewController
func makePremiumPrivacyControllerController(context: AccountContext, subject: PremiumPrivacySubject, peerId: EnginePeer.Id) -> ViewController
func makePremiumBoostLevelsController(context: AccountContext, peerId: EnginePeer.Id, subject: BoostSubject, boostStatus: ChannelBoostStatus, myBoostStatus: MyBoostStatus, forceDark: Bool, openStats: (() -> Void)?) -> ViewController

View File

@ -136,6 +136,7 @@ public struct Namespaces {
public static let cachedRevenueStats: Int8 = 39
public static let recommendedApps: Int8 = 40
public static let starsReactionDefaultToPrivate: Int8 = 41
public static let cachedPremiumGiftCodeOptions: Int8 = 42
}
public struct UnorderedItemList {

View File

@ -148,6 +148,79 @@ func _internal_getPremiumGiveawayInfo(account: Account, peerId: EnginePeer.Id, m
}
}
public final class CachedPremiumGiftCodeOptions: Codable {
public let options: [PremiumGiftCodeOption]
public init(options: [PremiumGiftCodeOption]) {
self.options = options
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: StringCodingKey.self)
self.options = try container.decode([PremiumGiftCodeOption].self, forKey: "t")
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: StringCodingKey.self)
try container.encode(self.options, forKey: "t")
}
}
func _internal_premiumGiftCodeOptions(account: Account, peerId: EnginePeer.Id?, onlyCached: Bool = false) -> Signal<[PremiumGiftCodeOption], NoError> {
let cached = account.postbox.transaction { transaction -> Signal<[PremiumGiftCodeOption], NoError> in
if let entry = transaction.retrieveItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPremiumGiftCodeOptions, key: ValueBoxKey(length: 0)))?.get(CachedPremiumGiftCodeOptions.self) {
return .single(entry.options)
}
return .single([])
} |> switchToLatest
var flags: Int32 = 0
if let _ = peerId {
flags |= 1 << 0
}
let remote = account.postbox.transaction { transaction -> Peer? in
if let peerId = peerId {
return transaction.getPeer(peerId)
}
return nil
}
|> mapToSignal { peer in
let inputPeer = peer.flatMap(apiInputPeer)
return account.network.request(Api.functions.payments.getPremiumGiftCodeOptions(flags: flags, boostPeer: inputPeer))
|> map(Optional.init)
|> `catch` { _ -> Signal<[Api.PremiumGiftCodeOption]?, NoError> in
return .single(nil)
}
|> mapToSignal { results -> Signal<[PremiumGiftCodeOption], NoError> in
let options = results?.map { PremiumGiftCodeOption(apiGiftCodeOption: $0) } ?? []
return account.postbox.transaction { transaction -> [PremiumGiftCodeOption] in
if peerId == nil {
if let entry = CodableEntry(CachedPremiumGiftCodeOptions(options: options)) {
transaction.putItemCacheEntry(id: ItemCacheEntryId(collectionId: Namespaces.CachedItemCollection.cachedPremiumGiftCodeOptions, key: ValueBoxKey(length: 0)), entry: entry)
}
}
return options
}
}
}
if peerId == nil {
return cached
|> mapToSignal { cached in
if onlyCached && !cached.isEmpty {
return .single(cached)
} else {
return .single(cached)
|> then(remote)
}
}
} else {
return remote
}
}
func _internal_premiumGiftCodeOptions(account: Account, peerId: EnginePeer.Id?) -> Signal<[PremiumGiftCodeOption], NoError> {
var flags: Int32 = 0
if let _ = peerId {

View File

@ -54,8 +54,8 @@ public extension TelegramEngine {
return _internal_applyPremiumGiftCode(account: self.account, slug: slug)
}
public func premiumGiftCodeOptions(peerId: EnginePeer.Id?) -> Signal<[PremiumGiftCodeOption], NoError> {
return _internal_premiumGiftCodeOptions(account: self.account, peerId: peerId)
public func premiumGiftCodeOptions(peerId: EnginePeer.Id?, onlyCached: Bool = false) -> Signal<[PremiumGiftCodeOption], NoError> {
return _internal_premiumGiftCodeOptions(account: self.account, peerId: peerId, onlyCached: onlyCached)
}
public func premiumGiveawayInfo(peerId: EnginePeer.Id, messageId: EngineMessage.Id) -> Signal<PremiumGiveawayInfo?, NoError> {

View File

@ -5683,7 +5683,13 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
@objc private func nameButtonPressed() {
if let item = self.item, let peer = item.message.author {
let messageReference = MessageReference(item.message)
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
if peer.id.isVerificationCodes, let forwardAuthor = item.content.firstMessage.forwardInfo?.author {
if let channel = forwardAuthor as? TelegramChannel, case .broadcast = channel.info {
item.controllerInteraction.openPeer(EnginePeer(channel), .chat(textInputState: nil, subject: nil, peekData: nil), messageReference, .default)
} else {
item.controllerInteraction.openPeer(EnginePeer(forwardAuthor), .info(nil), messageReference, .default)
}
} else if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
item.controllerInteraction.openPeer(EnginePeer(peer), .chat(textInputState: nil, subject: nil, peekData: nil), messageReference, .default)
} else {
item.controllerInteraction.openPeer(EnginePeer(peer), .info(nil), messageReference, .groupParticipant(storyStats: nil, avatarHeaderNode: nil))

View File

@ -438,6 +438,8 @@ final class GiftSetupScreenComponent: Component {
contentHeight += environment.navigationHeight
contentHeight += 26.0
let giftConfiguration = GiftConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 })
var introSectionItems: [AnyComponentWithIdentity<Empty>] = []
introSectionItems.append(AnyComponentWithIdentity(id: introSectionItems.count, component: AnyComponent(Rectangle(color: .clear, height: 346.0, tag: self.introPlaceholderTag))))
@ -451,10 +453,10 @@ final class GiftSetupScreenComponent: Component {
return ListMultilineTextFieldItemComponent.ResetText(value: $0)
},
placeholder: "Enter Message",
autocapitalizationType: .none,
autocorrectionType: .no,
autocapitalizationType: .sentences,
autocorrectionType: .yes,
returnKeyType: .done,
characterLimit: 255,
characterLimit: Int(giftConfiguration.maxCaptionLength),
displayCharacterLimit: true,
emptyLineHandling: .notAllowed,
formatMenuAvailability: .available([.bold, .italic, .underline, .strikethrough, .spoiler]),
@ -1062,3 +1064,27 @@ public final class GiftSetupScreen: ViewControllerComponentContainer {
super.containerLayoutUpdated(layout, transition: transition)
}
}
private struct GiftConfiguration {
static var defaultValue: GiftConfiguration {
return GiftConfiguration(maxCaptionLength: 255)
}
let maxCaptionLength: Int32
fileprivate init(maxCaptionLength: Int32) {
self.maxCaptionLength = maxCaptionLength
}
static func with(appConfiguration: AppConfiguration) -> GiftConfiguration {
if let data = appConfiguration.data {
var maxCaptionLength: Int32?
if let value = data["stargifts_message_length_max"] as? Double {
maxCaptionLength = Int32(value)
}
return GiftConfiguration(maxCaptionLength: maxCaptionLength ?? GiftConfiguration.defaultValue.maxCaptionLength)
} else {
return .defaultValue
}
}
}

View File

@ -135,7 +135,6 @@ private final class GiftViewSheetContent: CombinedComponent {
return { context in
let environment = context.environment[ViewControllerComponentContainer.Environment.self].value
let controller = environment.controller
let component = context.component
let theme = environment.theme
@ -294,17 +293,12 @@ private final class GiftViewSheetContent: CombinedComponent {
)
),
action: {
// if "".isEmpty {
// component.openPeer(peer)
// Queue.mainQueue().after(1.0, {
// component.cancel(false)
// })
// } else {
if let controller = controller() as? GiftViewScreen, let navigationController = controller.navigationController, let chatController = navigationController.viewControllers.first(where: { $0 is ChatController }) as? ChatController {
chatController.playShakeAnimation()
}
component.cancel(true)
// }
if "".isEmpty {
component.openPeer(peer)
Queue.mainQueue().after(1.0, {
component.cancel(false)
})
}
}
)
)
@ -798,12 +792,17 @@ public class GiftViewScreen: ViewControllerComponentContainer {
self.dismissAnimated()
let title: String = added ? "Gift Saved to Profile" : "Gift Removed from Profile"
var text = added ? "The gift is now displayed in [your profile]()." : "The gift is no longer displayed in [your profile]()."
if let _ = updateSavedToProfile {
text = text.replacingOccurrences(of: "]()", with: "").replacingOccurrences(of: "[", with: "")
}
if let navigationController {
Queue.mainQueue().after(0.5) {
if let lastController = navigationController.viewControllers.last as? ViewController {
let resultController = UndoOverlayController(
presentationData: presentationData,
content: .sticker(context: context, file: arguments.gift.file, loop: false, title: added ? "Gift Saved to Profile" : "Gift Removed from Profile", text: added ? "The gift is now displayed in [your profile]()." : "The gift is no longer displayed in [your profile]().", undoText: nil, customAction: nil),
content: .sticker(context: context, file: arguments.gift.file, loop: false, title: title, text: text, undoText: nil, customAction: nil),
elevatedLayout: lastController is ChatController,
action: { [weak navigationController] action in
if case .info = action, let navigationController {
@ -854,11 +853,11 @@ public class GiftViewScreen: ViewControllerComponentContainer {
self?.dismissAnimated()
if let navigationController {
if let starsContext = context.starsContext {
navigationController.pushViewController(context.sharedContext.makeStarsTransactionsScreen(context: context, starsContext: starsContext), animated: true)
}
Queue.mainQueue().after(0.5) {
if let starsContext = context.starsContext {
navigationController.pushViewController(context.sharedContext.makeStarsTransactionsScreen(context: context, starsContext: starsContext), animated: true)
}
if let lastController = navigationController.viewControllers.last as? ViewController {
let resultController = UndoOverlayController(
presentationData: presentationData,

View File

@ -413,7 +413,7 @@ public final class ListMultilineTextFieldItemComponent: Component {
environment: {},
containerSize: CGSize(width: 100.0, height: 100.0)
)
let textLimitLabelFrame = CGRect(origin: CGPoint(x: availableSize.width - textLimitLabelSize.width - rightInset, y: verticalInset + 2.0), size: textLimitLabelSize)
let textLimitLabelFrame = CGRect(origin: CGPoint(x: availableSize.width - textLimitLabelSize.width - leftInset + 5.0, y: verticalInset + 2.0), size: textLimitLabelSize)
if let textLimitLabelView = textLimitLabel.view {
if textLimitLabelView.superview == nil {
textLimitLabelView.isUserInteractionEnabled = false

View File

@ -384,6 +384,7 @@ final class PeerInfoScreenData {
let starsRevenueStatsContext: StarsRevenueStatsContext?
let revenueStatsState: RevenueStats?
let profileGiftsContext: ProfileGiftsContext?
let premiumGiftOptions: [PremiumGiftCodeOption]
let _isContact: Bool
var forceIsContact: Bool = false
@ -430,7 +431,8 @@ final class PeerInfoScreenData {
starsRevenueStatsState: StarsRevenueStats?,
starsRevenueStatsContext: StarsRevenueStatsContext?,
revenueStatsState: RevenueStats?,
profileGiftsContext: ProfileGiftsContext?
profileGiftsContext: ProfileGiftsContext?,
premiumGiftOptions: [PremiumGiftCodeOption]
) {
self.peer = peer
self.chatPeer = chatPeer
@ -466,6 +468,7 @@ final class PeerInfoScreenData {
self.starsRevenueStatsContext = starsRevenueStatsContext
self.revenueStatsState = revenueStatsState
self.profileGiftsContext = profileGiftsContext
self.premiumGiftOptions = premiumGiftOptions
}
}
@ -959,7 +962,8 @@ func peerInfoScreenSettingsData(context: AccountContext, peerId: EnginePeer.Id,
starsRevenueStatsState: nil,
starsRevenueStatsContext: nil,
revenueStatsState: nil,
profileGiftsContext: nil
profileGiftsContext: nil,
premiumGiftOptions: []
)
}
}
@ -1005,7 +1009,8 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
starsRevenueStatsState: nil,
starsRevenueStatsContext: nil,
revenueStatsState: nil,
profileGiftsContext: nil
profileGiftsContext: nil,
premiumGiftOptions: []
))
case let .user(userPeerId, secretChatId, kind):
let groupsInCommon: GroupsInCommonContext?
@ -1017,11 +1022,17 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
groupsInCommon = nil
}
let premiumGiftOptions: Signal<[PremiumGiftCodeOption], NoError>
let profileGiftsContext: ProfileGiftsContext?
if case .user = kind {
profileGiftsContext = ProfileGiftsContext(account: context.account, peerId: userPeerId)
premiumGiftOptions = .single([])
|> then(
context.engine.payments.premiumGiftCodeOptions(peerId: nil, onlyCached: true)
)
} else {
profileGiftsContext = nil
premiumGiftOptions = .single([])
}
enum StatusInputData: Equatable {
@ -1275,9 +1286,10 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
hasBotPreviewItems,
peerInfoPersonalChannel(context: context, peerId: peerId, isSettings: false),
privacySettings,
starsRevenueContextAndState
starsRevenueContextAndState,
premiumGiftOptions
)
|> map { peerView, availablePanes, globalNotificationSettings, encryptionKeyFingerprint, status, hasStories, hasStoryArchive, accountIsPremium, savedMessagesPeer, hasSavedMessagesChats, hasSavedMessages, hasSavedMessageTags, hasBotPreviewItems, personalChannel, privacySettings, starsRevenueContextAndState -> PeerInfoScreenData in
|> map { peerView, availablePanes, globalNotificationSettings, encryptionKeyFingerprint, status, hasStories, hasStoryArchive, accountIsPremium, savedMessagesPeer, hasSavedMessagesChats, hasSavedMessages, hasSavedMessageTags, hasBotPreviewItems, personalChannel, privacySettings, starsRevenueContextAndState, premiumGiftOptions -> PeerInfoScreenData in
var availablePanes = availablePanes
if isMyProfile {
availablePanes?.insert(.stories, at: 0)
@ -1394,7 +1406,8 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
starsRevenueStatsState: starsRevenueContextAndState.1,
starsRevenueStatsContext: starsRevenueContextAndState.0,
revenueStatsState: nil,
profileGiftsContext: profileGiftsContext
profileGiftsContext: profileGiftsContext,
premiumGiftOptions: premiumGiftOptions
)
}
case .channel:
@ -1604,7 +1617,8 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
starsRevenueStatsState: starsRevenueContextAndState.1,
starsRevenueStatsContext: starsRevenueContextAndState.0,
revenueStatsState: revenueContextAndState.1,
profileGiftsContext: nil
profileGiftsContext: nil,
premiumGiftOptions: []
)
}
case let .group(groupId):
@ -1905,7 +1919,8 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
starsRevenueStatsState: nil,
starsRevenueStatsContext: nil,
revenueStatsState: nil,
profileGiftsContext: nil
profileGiftsContext: nil,
premiumGiftOptions: []
))
}
}

View File

@ -9816,35 +9816,16 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}
private func openPremiumGift() {
guard let cachedData = self.data?.cachedData as? CachedUserData else {
guard let premiumGiftOptions = self.data?.premiumGiftOptions else {
return
}
var pushControllerImpl: ((ViewController) -> Void)?
let controller = PremiumGiftScreen(context: self.context, peerIds: [self.peerId], options: cachedData.premiumGiftOptions, source: .profile, pushController: { c in
pushControllerImpl?(c)
}, completion: { [weak self] in
if let strongSelf = self, let navigationController = strongSelf.controller?.navigationController as? NavigationController {
var controllers = navigationController.viewControllers
controllers = controllers.filter { !($0 is PeerInfoScreen) && !($0 is PremiumGiftScreen) }
var foundController = false
for controller in controllers.reversed() {
if let chatController = controller as? ChatController, case .peer(id: strongSelf.peerId) = chatController.chatLocation {
chatController.hintPlayNextOutgoingGift()
foundController = true
break
}
}
if !foundController {
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .peer(id: strongSelf.peerId), subject: nil, botStart: nil, mode: .standard(.default), params: nil)
chatController.hintPlayNextOutgoingGift()
controllers.append(chatController)
}
navigationController.setViewControllers(controllers, animated: true)
}
})
pushControllerImpl = { [weak controller] c in
controller?.push(c)
}
let premiumOptions = premiumGiftOptions.filter { $0.users == 1 }.map { CachedPremiumGiftOption(months: $0.months, currency: $0.currency, amount: $0.amount, botUrl: "", storeProductId: $0.storeProductId) }
let controller = self.context.sharedContext.makeGiftOptionsController(
context: self.context,
peerId: self.peerId,
premiumOptions: premiumOptions
)
self.controller?.push(controller)
}

View File

@ -2405,6 +2405,15 @@ public final class SharedAccountContextImpl: SharedAccountContext {
return controller
}
public func makeGiftOptionsController(context: AccountContext, peerId: EnginePeer.Id, premiumOptions: [CachedPremiumGiftOption]) -> ViewController {
guard let starsContext = context.starsContext else {
fatalError()
}
let controller = GiftOptionsScreen(context: context, starsContext: starsContext, peerId: peerId, premiumOptions: premiumOptions)
controller.navigationPresentation = .modal
return controller
}
public func makePremiumPrivacyControllerController(context: AccountContext, subject: PremiumPrivacySubject, peerId: EnginePeer.Id) -> ViewController {
let mappedSubject: PremiumPrivacyScreen.Subject
let introSource: PremiumIntroSource