mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-04 05:26:48 +00:00
Merge commit 'b70c7b2868b04cca4d86dc568a7c97f5ce02d466'
This commit is contained in:
commit
4e01a117db
@ -791,9 +791,9 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
|
|||||||
let badgeCount: Int32
|
let badgeCount: Int32
|
||||||
switch state.mode {
|
switch state.mode {
|
||||||
case .giveaway:
|
case .giveaway:
|
||||||
badgeCount = state.subscriptions
|
badgeCount = state.subscriptions * 4
|
||||||
case .gift:
|
case .gift:
|
||||||
badgeCount = Int32(state.peers.count)
|
badgeCount = Int32(state.peers.count) * 4
|
||||||
}
|
}
|
||||||
let footerItem = CreateGiveawayFooterItem(theme: presentationData.theme, title: state.mode == .gift ? presentationData.strings.BoostGift_GiftPremium : presentationData.strings.BoostGift_StartGiveaway, badgeCount: badgeCount, isLoading: state.updating, action: {
|
let footerItem = CreateGiveawayFooterItem(theme: presentationData.theme, title: state.mode == .gift ? presentationData.strings.BoostGift_GiftPremium : presentationData.strings.BoostGift_StartGiveaway, badgeCount: badgeCount, isLoading: state.updating, action: {
|
||||||
buyActionImpl?()
|
buyActionImpl?()
|
||||||
|
|||||||
@ -303,7 +303,10 @@ class GiftOptionItemNode: ItemListRevealOptionsItemNode {
|
|||||||
|
|
||||||
let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: labelAttributedString, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: .greatestFiniteMagnitude)))
|
let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: labelAttributedString, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width, height: .greatestFiniteMagnitude)))
|
||||||
|
|
||||||
let textConstrainedWidth = params.width - leftInset - 8.0 - editingOffset - rightInset - labelLayout.size.width - avatarInset
|
var textConstrainedWidth = params.width - leftInset - 8.0 - editingOffset - rightInset - labelLayout.size.width - avatarInset
|
||||||
|
if let label = item.label, case .semitransparent = label {
|
||||||
|
textConstrainedWidth -= 54.0
|
||||||
|
}
|
||||||
|
|
||||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleAttributedString, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: textConstrainedWidth, height: .greatestFiniteMagnitude)))
|
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleAttributedString, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: textConstrainedWidth, height: .greatestFiniteMagnitude)))
|
||||||
let (statusLayout, statusApply) = makeStatusLayout(TextNodeLayoutArguments(attributedString: statusAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: textConstrainedWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
let (statusLayout, statusApply) = makeStatusLayout(TextNodeLayoutArguments(attributedString: statusAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: textConstrainedWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
|||||||
@ -10,157 +10,182 @@ import TelegramPresentationData
|
|||||||
import Markdown
|
import Markdown
|
||||||
import AlertUI
|
import AlertUI
|
||||||
|
|
||||||
public func giveawayInfoController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, message: EngineMessage, giveawayInfo: PremiumGiveawayInfo, openLink: @escaping (String) -> Void) -> ViewController? {
|
public func presentGiveawayInfoController(
|
||||||
guard let giveaway = message.media.first(where: { $0 is TelegramMediaGiveaway }) as? TelegramMediaGiveaway else {
|
context: AccountContext,
|
||||||
return nil
|
updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil,
|
||||||
|
messageId: EngineMessage.Id,
|
||||||
|
giveawayInfo: PremiumGiveawayInfo,
|
||||||
|
present: @escaping (ViewController) -> Void,
|
||||||
|
openLink: @escaping (String) -> Void
|
||||||
|
) {
|
||||||
|
var peerIds: [EnginePeer.Id] = [context.account.peerId]
|
||||||
|
if case let .ongoing(_, status) = giveawayInfo, case let .notAllowed(reason) = status, case let .channelAdmin(adminId) = reason {
|
||||||
|
peerIds.append(adminId)
|
||||||
}
|
}
|
||||||
|
|
||||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
let _ = (context.engine.data.get(
|
||||||
|
TelegramEngine.EngineData.Item.Messages.Message(id: messageId),
|
||||||
var peerName = ""
|
EngineDataMap(peerIds.map(TelegramEngine.EngineData.Item.Peer.Peer.init))
|
||||||
if let peerId = giveaway.channelPeerIds.first, let peer = message.peers[peerId] {
|
|
||||||
peerName = EnginePeer(peer).compactDisplayTitle
|
|
||||||
}
|
|
||||||
|
|
||||||
let untilDate = stringForDate(timestamp: giveaway.untilDate, strings: presentationData.strings)
|
|
||||||
|
|
||||||
let title: String
|
|
||||||
let text: String
|
|
||||||
var warning: String?
|
|
||||||
|
|
||||||
var dismissImpl: (() -> Void)?
|
|
||||||
|
|
||||||
var actions: [TextAlertAction] = [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {
|
|
||||||
dismissImpl?()
|
|
||||||
})]
|
|
||||||
|
|
||||||
switch giveawayInfo {
|
|
||||||
case let .ongoing(start, status):
|
|
||||||
let startDate = stringForDate(timestamp: start, strings: presentationData.strings)
|
|
||||||
|
|
||||||
title = presentationData.strings.Chat_Giveaway_Info_Title
|
|
||||||
|
|
||||||
let intro: String
|
|
||||||
if case .almostOver = status {
|
|
||||||
intro = presentationData.strings.Chat_Giveaway_Info_EndedIntro(peerName, presentationData.strings.Chat_Giveaway_Info_Subscriptions(giveaway.quantity), presentationData.strings.Chat_Giveaway_Info_Months(giveaway.months)).string
|
|
||||||
} else {
|
|
||||||
intro = presentationData.strings.Chat_Giveaway_Info_OngoingIntro(peerName, presentationData.strings.Chat_Giveaway_Info_Subscriptions(giveaway.quantity), presentationData.strings.Chat_Giveaway_Info_Months(giveaway.months)).string
|
|
||||||
}
|
|
||||||
|
|
||||||
let ending: String
|
|
||||||
if giveaway.flags.contains(.onlyNewSubscribers) {
|
|
||||||
let randomUsers = presentationData.strings.Chat_Giveaway_Info_RandomUsers(giveaway.quantity)
|
|
||||||
if giveaway.channelPeerIds.count > 1 {
|
|
||||||
ending = presentationData.strings.Chat_Giveaway_Info_OngoingNewMany(untilDate, randomUsers, peerName, presentationData.strings.Chat_Giveaway_Info_OtherChannels(Int32(giveaway.channelPeerIds.count - 1)), startDate).string
|
|
||||||
} else {
|
|
||||||
ending = presentationData.strings.Chat_Giveaway_Info_OngoingNew(untilDate, randomUsers, peerName, startDate).string
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let randomSubscribers = presentationData.strings.Chat_Giveaway_Info_RandomSubscribers(giveaway.quantity)
|
|
||||||
if giveaway.channelPeerIds.count > 1 {
|
|
||||||
ending = presentationData.strings.Chat_Giveaway_Info_OngoingMany(untilDate, randomSubscribers, peerName, presentationData.strings.Chat_Giveaway_Info_OtherChannels(Int32(giveaway.channelPeerIds.count - 1))).string
|
|
||||||
} else {
|
|
||||||
ending = presentationData.strings.Chat_Giveaway_Info_Ongoing(untilDate, randomSubscribers, peerName).string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var participation: String
|
|
||||||
switch status {
|
|
||||||
case .notQualified:
|
|
||||||
if giveaway.channelPeerIds.count > 1 {
|
|
||||||
participation = presentationData.strings.Chat_Giveaway_Info_NotQualifiedMany(peerName, presentationData.strings.Chat_Giveaway_Info_OtherChannels(Int32(giveaway.channelPeerIds.count - 1)), untilDate).string
|
|
||||||
} else {
|
|
||||||
participation = presentationData.strings.Chat_Giveaway_Info_NotQualified(peerName, untilDate).string
|
|
||||||
}
|
|
||||||
case let .notAllowed(reason):
|
|
||||||
switch reason {
|
|
||||||
case let .joinedTooEarly(joinedOn):
|
|
||||||
let joinDate = stringForDate(timestamp: joinedOn, strings: presentationData.strings)
|
|
||||||
participation = presentationData.strings.Chat_Giveaway_Info_NotAllowedJoinedEarly(joinDate).string
|
|
||||||
case let .channelAdmin(adminId):
|
|
||||||
let _ = adminId
|
|
||||||
participation = presentationData.strings.Chat_Giveaway_Info_NotAllowedAdmin(peerName).string
|
|
||||||
case .disallowedCountry:
|
|
||||||
participation = presentationData.strings.Chat_Giveaway_Info_NotAllowedCountry
|
|
||||||
}
|
|
||||||
case .participating:
|
|
||||||
if giveaway.channelPeerIds.count > 1 {
|
|
||||||
participation = presentationData.strings.Chat_Giveaway_Info_ParticipatingMany(peerName, presentationData.strings.Chat_Giveaway_Info_OtherChannels(Int32(giveaway.channelPeerIds.count - 1))).string
|
|
||||||
} else {
|
|
||||||
participation = presentationData.strings.Chat_Giveaway_Info_Participating(peerName).string
|
|
||||||
}
|
|
||||||
case .almostOver:
|
|
||||||
participation = presentationData.strings.Chat_Giveaway_Info_AlmostOver
|
|
||||||
}
|
|
||||||
|
|
||||||
if !participation.isEmpty {
|
|
||||||
participation = "\n\n\(participation)"
|
|
||||||
}
|
|
||||||
|
|
||||||
text = "\(intro)\n\n\(ending)\(participation)"
|
|
||||||
case let .finished(status, start, finish, _, activatedCount):
|
|
||||||
let startDate = stringForDate(timestamp: start, strings: presentationData.strings)
|
|
||||||
let finishDate = stringForDate(timestamp: finish, strings: presentationData.strings)
|
|
||||||
title = presentationData.strings.Chat_Giveaway_Info_EndedTitle
|
|
||||||
|
|
||||||
let intro = presentationData.strings.Chat_Giveaway_Info_EndedIntro(peerName, presentationData.strings.Chat_Giveaway_Info_Subscriptions(giveaway.quantity), presentationData.strings.Chat_Giveaway_Info_Months(giveaway.months)).string
|
|
||||||
|
|
||||||
var ending: String
|
|
||||||
if giveaway.flags.contains(.onlyNewSubscribers) {
|
|
||||||
let randomUsers = presentationData.strings.Chat_Giveaway_Info_RandomUsers(giveaway.quantity)
|
|
||||||
if giveaway.channelPeerIds.count > 1 {
|
|
||||||
ending = presentationData.strings.Chat_Giveaway_Info_EndedNewMany(finishDate, randomUsers, peerName, startDate).string
|
|
||||||
} else {
|
|
||||||
ending = presentationData.strings.Chat_Giveaway_Info_EndedNew(finishDate, randomUsers, peerName, startDate).string
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let randomSubscribers = presentationData.strings.Chat_Giveaway_Info_RandomSubscribers(giveaway.quantity)
|
|
||||||
if giveaway.channelPeerIds.count > 1 {
|
|
||||||
ending = presentationData.strings.Chat_Giveaway_Info_EndedMany(finishDate, randomSubscribers, peerName).string
|
|
||||||
} else {
|
|
||||||
ending = presentationData.strings.Chat_Giveaway_Info_Ended(finishDate, randomSubscribers, peerName).string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if activatedCount > 0 {
|
|
||||||
ending += " " + presentationData.strings.Chat_Giveaway_Info_ActivatedLinks(activatedCount)
|
|
||||||
}
|
|
||||||
|
|
||||||
var result: String
|
|
||||||
switch status {
|
|
||||||
case .refunded:
|
|
||||||
result = ""
|
|
||||||
warning = presentationData.strings.Chat_Giveaway_Info_Refunded
|
|
||||||
actions = [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Close, action: {
|
|
||||||
dismissImpl?()
|
|
||||||
})]
|
|
||||||
case .notWon:
|
|
||||||
result = "\n\n" + presentationData.strings.Chat_Giveaway_Info_DidntWin
|
|
||||||
case let .won(slug):
|
|
||||||
result = "\n\n" + presentationData.strings.Chat_Giveaway_Info_Won("🏆").string
|
|
||||||
actions = [TextAlertAction(type: .defaultAction, title: presentationData.strings.Chat_Giveaway_Info_ViewPrize, action: {
|
|
||||||
dismissImpl?()
|
|
||||||
openLink(slug)
|
|
||||||
}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
|
|
||||||
dismissImpl?()
|
|
||||||
})]
|
|
||||||
}
|
|
||||||
|
|
||||||
text = "\(intro)\n\n\(ending)\(result)"
|
|
||||||
}
|
|
||||||
|
|
||||||
let alertController = giveawayInfoAlertController(
|
|
||||||
context: context,
|
|
||||||
updatedPresentationData: updatedPresentationData,
|
|
||||||
title: title,
|
|
||||||
text: text,
|
|
||||||
warning: warning,
|
|
||||||
actions: actions
|
|
||||||
)
|
)
|
||||||
dismissImpl = { [weak alertController] in
|
|> deliverOnMainQueue).startStandalone(next: { message, peerMap in
|
||||||
alertController?.dismissAnimated()
|
guard let message else {
|
||||||
}
|
return
|
||||||
return alertController
|
}
|
||||||
|
guard let giveaway = message.media.first(where: { $0 is TelegramMediaGiveaway }) as? TelegramMediaGiveaway else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
|
||||||
|
var peerName = ""
|
||||||
|
if let peerId = giveaway.channelPeerIds.first, let peer = message.peers[peerId] {
|
||||||
|
peerName = EnginePeer(peer).compactDisplayTitle
|
||||||
|
}
|
||||||
|
|
||||||
|
let timeZone = TimeZone.current
|
||||||
|
let untilDate = stringForDate(timestamp: giveaway.untilDate, timeZone: timeZone, strings: presentationData.strings)
|
||||||
|
|
||||||
|
let title: String
|
||||||
|
let text: String
|
||||||
|
var warning: String?
|
||||||
|
|
||||||
|
var dismissImpl: (() -> Void)?
|
||||||
|
|
||||||
|
var actions: [TextAlertAction] = [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {
|
||||||
|
dismissImpl?()
|
||||||
|
})]
|
||||||
|
|
||||||
|
switch giveawayInfo {
|
||||||
|
case let .ongoing(start, status):
|
||||||
|
let startDate = stringForDate(timestamp: start, timeZone: timeZone, strings: presentationData.strings)
|
||||||
|
|
||||||
|
title = presentationData.strings.Chat_Giveaway_Info_Title
|
||||||
|
|
||||||
|
let intro: String
|
||||||
|
if case .almostOver = status {
|
||||||
|
intro = presentationData.strings.Chat_Giveaway_Info_EndedIntro(peerName, presentationData.strings.Chat_Giveaway_Info_Subscriptions(giveaway.quantity), presentationData.strings.Chat_Giveaway_Info_Months(giveaway.months)).string
|
||||||
|
} else {
|
||||||
|
intro = presentationData.strings.Chat_Giveaway_Info_OngoingIntro(peerName, presentationData.strings.Chat_Giveaway_Info_Subscriptions(giveaway.quantity), presentationData.strings.Chat_Giveaway_Info_Months(giveaway.months)).string
|
||||||
|
}
|
||||||
|
|
||||||
|
let ending: String
|
||||||
|
if giveaway.flags.contains(.onlyNewSubscribers) {
|
||||||
|
let randomUsers = presentationData.strings.Chat_Giveaway_Info_RandomUsers(giveaway.quantity)
|
||||||
|
if giveaway.channelPeerIds.count > 1 {
|
||||||
|
ending = presentationData.strings.Chat_Giveaway_Info_OngoingNewMany(untilDate, randomUsers, peerName, presentationData.strings.Chat_Giveaway_Info_OtherChannels(Int32(giveaway.channelPeerIds.count - 1)), startDate).string
|
||||||
|
} else {
|
||||||
|
ending = presentationData.strings.Chat_Giveaway_Info_OngoingNew(untilDate, randomUsers, peerName, startDate).string
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let randomSubscribers = presentationData.strings.Chat_Giveaway_Info_RandomSubscribers(giveaway.quantity)
|
||||||
|
if giveaway.channelPeerIds.count > 1 {
|
||||||
|
ending = presentationData.strings.Chat_Giveaway_Info_OngoingMany(untilDate, randomSubscribers, peerName, presentationData.strings.Chat_Giveaway_Info_OtherChannels(Int32(giveaway.channelPeerIds.count - 1))).string
|
||||||
|
} else {
|
||||||
|
ending = presentationData.strings.Chat_Giveaway_Info_Ongoing(untilDate, randomSubscribers, peerName).string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var participation: String
|
||||||
|
switch status {
|
||||||
|
case .notQualified:
|
||||||
|
if giveaway.channelPeerIds.count > 1 {
|
||||||
|
participation = presentationData.strings.Chat_Giveaway_Info_NotQualifiedMany(peerName, presentationData.strings.Chat_Giveaway_Info_OtherChannels(Int32(giveaway.channelPeerIds.count - 1)), untilDate).string
|
||||||
|
} else {
|
||||||
|
participation = presentationData.strings.Chat_Giveaway_Info_NotQualified(peerName, untilDate).string
|
||||||
|
}
|
||||||
|
case let .notAllowed(reason):
|
||||||
|
switch reason {
|
||||||
|
case let .joinedTooEarly(joinedOn):
|
||||||
|
let joinDate = stringForDate(timestamp: joinedOn, strings: presentationData.strings)
|
||||||
|
participation = presentationData.strings.Chat_Giveaway_Info_NotAllowedJoinedEarly(joinDate).string
|
||||||
|
case let .channelAdmin(adminId):
|
||||||
|
var channelName = peerName
|
||||||
|
if let maybePeer = peerMap[adminId], let peer = maybePeer {
|
||||||
|
channelName = peer.compactDisplayTitle
|
||||||
|
}
|
||||||
|
participation = presentationData.strings.Chat_Giveaway_Info_NotAllowedAdmin(channelName).string
|
||||||
|
case .disallowedCountry:
|
||||||
|
participation = presentationData.strings.Chat_Giveaway_Info_NotAllowedCountry
|
||||||
|
}
|
||||||
|
case .participating:
|
||||||
|
if giveaway.channelPeerIds.count > 1 {
|
||||||
|
participation = presentationData.strings.Chat_Giveaway_Info_ParticipatingMany(peerName, presentationData.strings.Chat_Giveaway_Info_OtherChannels(Int32(giveaway.channelPeerIds.count - 1))).string
|
||||||
|
} else {
|
||||||
|
participation = presentationData.strings.Chat_Giveaway_Info_Participating(peerName).string
|
||||||
|
}
|
||||||
|
case .almostOver:
|
||||||
|
participation = presentationData.strings.Chat_Giveaway_Info_AlmostOver
|
||||||
|
}
|
||||||
|
|
||||||
|
if !participation.isEmpty {
|
||||||
|
participation = "\n\n\(participation)"
|
||||||
|
}
|
||||||
|
|
||||||
|
text = "\(intro)\n\n\(ending)\(participation)"
|
||||||
|
case let .finished(status, start, finish, _, activatedCount):
|
||||||
|
let startDate = stringForDate(timestamp: start, timeZone: timeZone, strings: presentationData.strings)
|
||||||
|
let finishDate = stringForDate(timestamp: finish, timeZone: timeZone, strings: presentationData.strings)
|
||||||
|
title = presentationData.strings.Chat_Giveaway_Info_EndedTitle
|
||||||
|
|
||||||
|
let intro = presentationData.strings.Chat_Giveaway_Info_EndedIntro(peerName, presentationData.strings.Chat_Giveaway_Info_Subscriptions(giveaway.quantity), presentationData.strings.Chat_Giveaway_Info_Months(giveaway.months)).string
|
||||||
|
|
||||||
|
var ending: String
|
||||||
|
if giveaway.flags.contains(.onlyNewSubscribers) {
|
||||||
|
let randomUsers = presentationData.strings.Chat_Giveaway_Info_RandomUsers(giveaway.quantity)
|
||||||
|
if giveaway.channelPeerIds.count > 1 {
|
||||||
|
ending = presentationData.strings.Chat_Giveaway_Info_EndedNewMany(finishDate, randomUsers, peerName, startDate).string
|
||||||
|
} else {
|
||||||
|
ending = presentationData.strings.Chat_Giveaway_Info_EndedNew(finishDate, randomUsers, peerName, startDate).string
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let randomSubscribers = presentationData.strings.Chat_Giveaway_Info_RandomSubscribers(giveaway.quantity)
|
||||||
|
if giveaway.channelPeerIds.count > 1 {
|
||||||
|
ending = presentationData.strings.Chat_Giveaway_Info_EndedMany(finishDate, randomSubscribers, peerName).string
|
||||||
|
} else {
|
||||||
|
ending = presentationData.strings.Chat_Giveaway_Info_Ended(finishDate, randomSubscribers, peerName).string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if activatedCount > 0 {
|
||||||
|
ending += " " + presentationData.strings.Chat_Giveaway_Info_ActivatedLinks(activatedCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
var result: String
|
||||||
|
switch status {
|
||||||
|
case .refunded:
|
||||||
|
result = ""
|
||||||
|
warning = presentationData.strings.Chat_Giveaway_Info_Refunded
|
||||||
|
actions = [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Close, action: {
|
||||||
|
dismissImpl?()
|
||||||
|
})]
|
||||||
|
case .notWon:
|
||||||
|
result = "\n\n" + presentationData.strings.Chat_Giveaway_Info_DidntWin
|
||||||
|
case let .won(slug):
|
||||||
|
result = "\n\n" + presentationData.strings.Chat_Giveaway_Info_Won("🏆").string
|
||||||
|
actions = [TextAlertAction(type: .defaultAction, title: presentationData.strings.Chat_Giveaway_Info_ViewPrize, action: {
|
||||||
|
dismissImpl?()
|
||||||
|
openLink(slug)
|
||||||
|
}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
|
||||||
|
dismissImpl?()
|
||||||
|
})]
|
||||||
|
}
|
||||||
|
|
||||||
|
text = "\(intro)\n\n\(ending)\(result)"
|
||||||
|
}
|
||||||
|
|
||||||
|
let alertController = giveawayInfoAlertController(
|
||||||
|
context: context,
|
||||||
|
updatedPresentationData: updatedPresentationData,
|
||||||
|
title: title,
|
||||||
|
text: text,
|
||||||
|
warning: warning,
|
||||||
|
actions: actions
|
||||||
|
)
|
||||||
|
dismissImpl = { [weak alertController] in
|
||||||
|
alertController?.dismissAnimated()
|
||||||
|
}
|
||||||
|
present(alertController)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private final class GiveawayInfoAlertContentNode: AlertContentNode {
|
private final class GiveawayInfoAlertContentNode: AlertContentNode {
|
||||||
|
|||||||
@ -666,6 +666,7 @@ private final class DemoSheetContent: CombinedComponent {
|
|||||||
let background = Child(GradientBackgroundComponent.self)
|
let background = Child(GradientBackgroundComponent.self)
|
||||||
let pager = Child(DemoPagerComponent.self)
|
let pager = Child(DemoPagerComponent.self)
|
||||||
let button = Child(SolidRoundedButtonComponent.self)
|
let button = Child(SolidRoundedButtonComponent.self)
|
||||||
|
let measureText = Child(MultilineTextComponent.self)
|
||||||
|
|
||||||
return { context in
|
return { context in
|
||||||
let environment = context.environment[ViewControllerComponentContainer.Environment.self].value
|
let environment = context.environment[ViewControllerComponentContainer.Environment.self].value
|
||||||
@ -1003,44 +1004,108 @@ private final class DemoSheetContent: CombinedComponent {
|
|||||||
.cornerRadius(15.0)
|
.cornerRadius(15.0)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var measuredTextHeight: CGFloat?
|
||||||
|
|
||||||
let buttonText: String
|
let buttonText: String
|
||||||
var buttonAnimationName: String?
|
var buttonAnimationName: String?
|
||||||
if state.isPremium == true {
|
if state.isPremium == true {
|
||||||
buttonText = strings.Common_OK
|
buttonText = strings.Common_OK
|
||||||
} else {
|
} else {
|
||||||
switch component.source {
|
switch component.source {
|
||||||
case let .intro(price):
|
case let .intro(price):
|
||||||
buttonText = strings.Premium_SubscribeFor(price ?? "–").string
|
buttonText = strings.Premium_SubscribeFor(price ?? "–").string
|
||||||
case let .gift(price):
|
case let .gift(price):
|
||||||
buttonText = strings.Premium_Gift_GiftSubscription(price ?? "–").string
|
buttonText = strings.Premium_Gift_GiftSubscription(price ?? "–").string
|
||||||
case .other:
|
case .other:
|
||||||
switch component.subject {
|
var text: String
|
||||||
case .fasterDownload:
|
switch component.subject {
|
||||||
buttonText = strings.Premium_FasterSpeed_Proceed
|
case .fasterDownload:
|
||||||
case .advancedChatManagement:
|
buttonText = strings.Premium_FasterSpeed_Proceed
|
||||||
buttonText = strings.Premium_ChatManagement_Proceed
|
case .advancedChatManagement:
|
||||||
case .uniqueReactions:
|
buttonText = strings.Premium_ChatManagement_Proceed
|
||||||
buttonText = strings.Premium_Reactions_Proceed
|
case .uniqueReactions:
|
||||||
buttonAnimationName = "premium_unlock"
|
buttonText = strings.Premium_Reactions_Proceed
|
||||||
case .premiumStickers:
|
buttonAnimationName = "premium_unlock"
|
||||||
buttonText = strings.Premium_Stickers_Proceed
|
case .premiumStickers:
|
||||||
buttonAnimationName = "premium_unlock"
|
buttonText = strings.Premium_Stickers_Proceed
|
||||||
case .appIcons:
|
buttonAnimationName = "premium_unlock"
|
||||||
buttonText = strings.Premium_AppIcons_Proceed
|
case .appIcons:
|
||||||
buttonAnimationName = "premium_unlock"
|
buttonText = strings.Premium_AppIcons_Proceed
|
||||||
case .noAds:
|
buttonAnimationName = "premium_unlock"
|
||||||
buttonText = strings.Premium_NoAds_Proceed
|
case .noAds:
|
||||||
case .animatedEmoji:
|
buttonText = strings.Premium_NoAds_Proceed
|
||||||
buttonText = strings.Premium_AnimatedEmoji_Proceed
|
case .animatedEmoji:
|
||||||
buttonAnimationName = "premium_unlock"
|
buttonText = strings.Premium_AnimatedEmoji_Proceed
|
||||||
case .translation:
|
buttonAnimationName = "premium_unlock"
|
||||||
buttonText = strings.Premium_Translation_Proceed
|
case .translation:
|
||||||
case .stories:
|
buttonText = strings.Premium_Translation_Proceed
|
||||||
buttonText = strings.Common_OK
|
case .stories:
|
||||||
buttonAnimationName = "premium_unlock"
|
buttonText = strings.Common_OK
|
||||||
default:
|
buttonAnimationName = "premium_unlock"
|
||||||
buttonText = strings.Common_OK
|
default:
|
||||||
|
buttonText = strings.Common_OK
|
||||||
|
}
|
||||||
|
|
||||||
|
switch component.subject {
|
||||||
|
case .moreUpload:
|
||||||
|
text = strings.Premium_UploadSizeInfo
|
||||||
|
case .fasterDownload:
|
||||||
|
text = strings.Premium_FasterSpeedStandaloneInfo
|
||||||
|
case .voiceToText:
|
||||||
|
text = strings.Premium_VoiceToTextStandaloneInfo
|
||||||
|
case .noAds:
|
||||||
|
text = strings.Premium_NoAdsStandaloneInfo
|
||||||
|
case .uniqueReactions:
|
||||||
|
text = strings.Premium_InfiniteReactionsInfo
|
||||||
|
case .premiumStickers:
|
||||||
|
text = strings.Premium_StickersInfo
|
||||||
|
case .emojiStatus:
|
||||||
|
text = strings.Premium_EmojiStatusInfo
|
||||||
|
case .advancedChatManagement:
|
||||||
|
text = strings.Premium_ChatManagementStandaloneInfo
|
||||||
|
case .profileBadge:
|
||||||
|
text = strings.Premium_BadgeInfo
|
||||||
|
case .animatedUserpics:
|
||||||
|
text = strings.Premium_AvatarInfo
|
||||||
|
case .appIcons:
|
||||||
|
text = strings.Premium_AppIconStandaloneInfo
|
||||||
|
case .animatedEmoji:
|
||||||
|
text = strings.Premium_AnimatedEmojiStandaloneInfo
|
||||||
|
case .translation:
|
||||||
|
text = strings.Premium_TranslationStandaloneInfo
|
||||||
|
case .doubleLimits:
|
||||||
|
text = ""
|
||||||
|
case .stories:
|
||||||
|
text = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
let textSideInset: CGFloat = 24.0
|
||||||
|
|
||||||
|
let textColor = UIColor.black
|
||||||
|
let textFont = Font.regular(17.0)
|
||||||
|
let boldTextFont = Font.semibold(17.0)
|
||||||
|
let markdownAttributes = MarkdownAttributes(
|
||||||
|
body: MarkdownAttributeSet(font: textFont, textColor: textColor),
|
||||||
|
bold: MarkdownAttributeSet(font: boldTextFont, textColor: textColor),
|
||||||
|
link: MarkdownAttributeSet(font: textFont, textColor: textColor),
|
||||||
|
linkAttribute: { _ in
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
let measureText = measureText.update(
|
||||||
|
component: MultilineTextComponent(
|
||||||
|
text: .markdown(text: text, attributes: markdownAttributes),
|
||||||
|
horizontalAlignment: .center,
|
||||||
|
maximumNumberOfLines: 0,
|
||||||
|
lineSpacing: 0.0
|
||||||
|
),
|
||||||
|
availableSize: CGSize(width: context.availableSize.width - textSideInset * 2.0, height: context.availableSize.height),
|
||||||
|
transition: .immediate
|
||||||
|
)
|
||||||
|
context.add(measureText
|
||||||
|
.position(CGPoint(x: 0.0, y: 1000.0))
|
||||||
|
)
|
||||||
|
measuredTextHeight = measureText.size.height
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1079,12 +1144,17 @@ private final class DemoSheetContent: CombinedComponent {
|
|||||||
transition: context.transition
|
transition: context.transition
|
||||||
)
|
)
|
||||||
|
|
||||||
var contentHeight: CGFloat = context.availableSize.width + 146.0
|
var contentHeight: CGFloat = context.availableSize.width
|
||||||
if case .other = component.source {
|
if let measuredTextHeight {
|
||||||
contentHeight -= 40.0
|
contentHeight += measuredTextHeight + 66.0
|
||||||
|
} else {
|
||||||
|
contentHeight += 146.0
|
||||||
|
if case .other = component.source {
|
||||||
|
contentHeight -= 40.0
|
||||||
|
|
||||||
if [.advancedChatManagement, .fasterDownload].contains(component.subject) {
|
if [.advancedChatManagement, .fasterDownload].contains(component.subject) {
|
||||||
contentHeight += 20.0
|
contentHeight += 20.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1166,6 +1236,7 @@ private final class DemoSheetComponent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
)),
|
)),
|
||||||
backgroundColor: .color(environment.theme.actionSheet.opaqueItemBackgroundColor),
|
backgroundColor: .color(environment.theme.actionSheet.opaqueItemBackgroundColor),
|
||||||
|
followContentSizeChanges: context.component.source == .other,
|
||||||
animateOut: animateOut
|
animateOut: animateOut
|
||||||
),
|
),
|
||||||
environment: {
|
environment: {
|
||||||
|
|||||||
@ -817,7 +817,7 @@ public class PremiumLimitsListScreen: ViewController {
|
|||||||
additionalInset = 20.0
|
additionalInset = 20.0
|
||||||
}
|
}
|
||||||
|
|
||||||
return layout.size.height - layout.size.width - 178.0 - panelHeight + additionalInset
|
return layout.size.height - layout.size.width - 181.0 - panelHeight + additionalInset
|
||||||
} else {
|
} else {
|
||||||
return 210.0
|
return 210.0
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1077,7 +1077,7 @@ public func channelStatsController(context: AccountContext, updatedPresentationD
|
|||||||
}
|
}
|
||||||
controller.visibleBottomContentOffsetChanged = { offset in
|
controller.visibleBottomContentOffsetChanged = { offset in
|
||||||
let state = stateValue.with { $0 }
|
let state = stateValue.with { $0 }
|
||||||
if case let .known(value) = offset, value < 100.0, case .boosts = state.section, state.boostersExpanded {
|
if case let .known(value) = offset, value < 510.0, case .boosts = state.section, state.boostersExpanded {
|
||||||
boostsContext.loadMore()
|
boostsContext.loadMore()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -117,11 +117,11 @@ public func stringForFullDate(timestamp: Int32, strings: PresentationStrings, da
|
|||||||
return monthFormat(dayString, yearString, timeString).string
|
return monthFormat(dayString, yearString, timeString).string
|
||||||
}
|
}
|
||||||
|
|
||||||
public func stringForDate(timestamp: Int32, strings: PresentationStrings) -> String {
|
public func stringForDate(timestamp: Int32, timeZone: TimeZone? = TimeZone(secondsFromGMT: 0), strings: PresentationStrings) -> String {
|
||||||
let formatter = DateFormatter()
|
let formatter = DateFormatter()
|
||||||
formatter.timeStyle = .none
|
formatter.timeStyle = .none
|
||||||
formatter.dateStyle = .medium
|
formatter.dateStyle = .medium
|
||||||
formatter.timeZone = TimeZone(secondsFromGMT: 0)
|
formatter.timeZone = timeZone
|
||||||
formatter.locale = localeWithStrings(strings)
|
formatter.locale = localeWithStrings(strings)
|
||||||
return formatter.string(from: Date(timeIntervalSince1970: Double(timestamp)))
|
return formatter.string(from: Date(timeIntervalSince1970: Double(timestamp)))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -184,6 +184,7 @@ private struct PeerNameColorScreenState: Equatable {
|
|||||||
var updatedNameColor: PeerNameColor?
|
var updatedNameColor: PeerNameColor?
|
||||||
var updatedBackgroundEmojiId: Int64?
|
var updatedBackgroundEmojiId: Int64?
|
||||||
var inProgress: Bool = false
|
var inProgress: Bool = false
|
||||||
|
var needsBoosts: Bool = false
|
||||||
}
|
}
|
||||||
|
|
||||||
private func peerNameColorScreenEntries(
|
private func peerNameColorScreenEntries(
|
||||||
@ -253,7 +254,11 @@ private func peerNameColorScreenEntries(
|
|||||||
colors: nameColors,
|
colors: nameColors,
|
||||||
currentColor: nameColor
|
currentColor: nameColor
|
||||||
))
|
))
|
||||||
entries.append(.colorDescription(presentationData.strings.NameColor_ChatPreview_Description_Account))
|
if case .channel = peer {
|
||||||
|
entries.append(.colorDescription(presentationData.strings.NameColor_ChatPreview_Description_Channel))
|
||||||
|
} else {
|
||||||
|
entries.append(.colorDescription(presentationData.strings.NameColor_ChatPreview_Description_Account))
|
||||||
|
}
|
||||||
|
|
||||||
if let emojiContent {
|
if let emojiContent {
|
||||||
entries.append(.backgroundEmojiHeader(presentationData.strings.NameColor_BackgroundEmoji_Title, backgroundEmojiId != nil ? presentationData.strings.NameColor_BackgroundEmoji_Remove : nil))
|
entries.append(.backgroundEmojiHeader(presentationData.strings.NameColor_BackgroundEmoji_Title, backgroundEmojiId != nil ? presentationData.strings.NameColor_BackgroundEmoji_Remove : nil))
|
||||||
@ -530,6 +535,7 @@ public func PeerNameColorScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let controller = ItemListController(context: context, state: signal)
|
let controller = ItemListController(context: context, state: signal)
|
||||||
|
controller.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
||||||
presentImpl = { [weak controller] c in
|
presentImpl = { [weak controller] c in
|
||||||
guard let controller else {
|
guard let controller else {
|
||||||
return
|
return
|
||||||
@ -561,6 +567,10 @@ public func PeerNameColorScreen(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
let state = stateValue.with({ $0 })
|
let state = stateValue.with({ $0 })
|
||||||
|
if case .channel = subject, state.needsBoosts {
|
||||||
|
f()
|
||||||
|
return true
|
||||||
|
}
|
||||||
var hasChanges = false
|
var hasChanges = false
|
||||||
if state.updatedNameColor != nil || state.updatedBackgroundEmojiId != nil {
|
if state.updatedNameColor != nil || state.updatedBackgroundEmojiId != nil {
|
||||||
hasChanges = true
|
hasChanges = true
|
||||||
@ -624,6 +634,12 @@ public func PeerNameColorScreen(
|
|||||||
|> deliverOnMainQueue).startStandalone(next: {
|
|> deliverOnMainQueue).startStandalone(next: {
|
||||||
}, error: { error in
|
}, error: { error in
|
||||||
if case .channelBoostRequired = error {
|
if case .channelBoostRequired = error {
|
||||||
|
updateState { state in
|
||||||
|
var updatedState = state
|
||||||
|
updatedState.needsBoosts = true
|
||||||
|
return updatedState
|
||||||
|
}
|
||||||
|
|
||||||
let _ = combineLatest(
|
let _ = combineLatest(
|
||||||
queue: Queue.mainQueue(),
|
queue: Queue.mainQueue(),
|
||||||
context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)),
|
context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)),
|
||||||
|
|||||||
@ -19177,19 +19177,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
|
|
||||||
func displayGiveawayStatusInfo(messageId: EngineMessage.Id, giveawayInfo: PremiumGiveawayInfo) {
|
func displayGiveawayStatusInfo(messageId: EngineMessage.Id, giveawayInfo: PremiumGiveawayInfo) {
|
||||||
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|
presentGiveawayInfoController(context: self.context, updatedPresentationData: self.updatedPresentationData, messageId: messageId, giveawayInfo: giveawayInfo, present: { [weak self] c in
|
||||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] message in
|
guard let self else {
|
||||||
guard let self, let message else {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if let controller = giveawayInfoController(context: self.context, updatedPresentationData: self.updatedPresentationData, message: message, giveawayInfo: giveawayInfo, openLink: { [weak self] slug in
|
self.present(c, in: .window(.root))
|
||||||
guard let self else {
|
}, openLink: { [weak self] slug in
|
||||||
return
|
guard let self else {
|
||||||
}
|
return
|
||||||
self.openResolved(result: .premiumGiftCode(slug: slug), sourceMessageId: messageId)
|
|
||||||
}) {
|
|
||||||
self.present(controller, in: .window(.root))
|
|
||||||
}
|
}
|
||||||
|
self.openResolved(result: .premiumGiftCode(slug: slug), sourceMessageId: messageId)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -913,6 +913,9 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
|
|||||||
openPeer: { peer in
|
openPeer: { peer in
|
||||||
if peer.id != context.account.peerId {
|
if peer.id != context.account.peerId {
|
||||||
openPeer(peer, .chat(textInputState: nil, subject: nil, peekData: nil))
|
openPeer(peer, .chat(textInputState: nil, subject: nil, peekData: nil))
|
||||||
|
if case let .chat(peerId, _) = urlContext, peerId == peer.id {
|
||||||
|
dismissImpl?()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openMessage: { messageId in
|
openMessage: { messageId in
|
||||||
@ -922,6 +925,9 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
openPeer(peer, .chat(textInputState: nil, subject: .message(id: .id(messageId), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil), peekData: nil))
|
openPeer(peer, .chat(textInputState: nil, subject: .message(id: .id(messageId), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: nil), peekData: nil))
|
||||||
|
if case let .chat(peerId, _) = urlContext, peerId == messageId.peerId {
|
||||||
|
dismissImpl?()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
shareLink: { link in
|
shareLink: { link in
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"app": "10.2.1",
|
"app": "10.2.2",
|
||||||
"bazel": "6.4.0",
|
"bazel": "6.4.0",
|
||||||
"xcode": "15.0"
|
"xcode": "15.0"
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user