Files
GLEGram-iOS/submodules/PremiumUI/Sources/GiveawayInfoController.swift
T
Leeksov 4647310322 GLEGram 12.5 — Initial public release
Based on Swiftgram 12.5 (Telegram iOS 12.5).
All GLEGram features ported and organized in GLEGram/ folder.

Features: Ghost Mode, Saved Deleted Messages, Content Protection Bypass,
Font Replacement, Fake Profile, Chat Export, Plugin System, and more.

See CHANGELOG_12.5.md for full details.
2026-04-06 09:48:12 +03:00

384 lines
18 KiB
Swift

import Foundation
import UIKit
import AsyncDisplayKit
import Display
import SwiftSignalKit
import TelegramCore
import AccountContext
import TelegramStringFormatting
import TextFormat
import TelegramPresentationData
import ComponentFlow
import AlertComponent
public func presentGiveawayInfoController(
context: AccountContext,
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),
EngineDataMap(peerIds.map(TelegramEngine.EngineData.Item.Peer.Peer.init))
)
|> deliverOnMainQueue).startStandalone(next: { message, peerMap in
guard let message else {
return
}
let giveaway = message.media.first(where: { $0 is TelegramMediaGiveaway }) as? TelegramMediaGiveaway
let giveawayResults = message.media.first(where: { $0 is TelegramMediaGiveawayResults }) as? TelegramMediaGiveawayResults
var quantity: Int32 = 0
if let giveaway {
quantity = giveaway.quantity
} else if let giveawayResults {
quantity = giveawayResults.winnersCount + giveawayResults.unclaimedCount
}
var months: Int32 = 0
var stars: Int64 = 0
if let giveaway {
switch giveaway.prize {
case let .premium(monthsValue):
months = monthsValue
case let .stars(amount):
stars = amount
}
} else if let giveawayResults {
switch giveawayResults.prize {
case let .premium(monthsValue):
months = monthsValue
case let .stars(amount):
stars = amount
}
}
var prizeDescription: String?
if let giveaway {
prizeDescription = giveaway.prizeDescription
} else if let giveawayResults {
prizeDescription = giveawayResults.prizeDescription
}
var untilDateValue: Int32 = 0
if let giveaway {
untilDateValue = giveaway.untilDate
} else if let giveawayResults {
untilDateValue = giveawayResults.untilDate
}
var onlyNewSubscribers = false
if let giveaway, giveaway.flags.contains(.onlyNewSubscribers) {
onlyNewSubscribers = true
} else if let giveawayResults, giveawayResults.flags.contains(.onlyNewSubscribers) {
onlyNewSubscribers = true
}
var author = message.forwardInfo?.author ?? message.author?._asPeer()
if author is TelegramChannel {
} else {
if let peer = message.forwardInfo?.source ?? message.peers[message.id.peerId] {
author = peer
}
}
var isGroup = false
if let channel = author as? TelegramChannel, case .group = channel.info {
isGroup = true
}
var peerName = ""
if let author {
peerName = EnginePeer(author).compactDisplayTitle
}
var groupsAndChannels = false
var channelsCount: Int32 = 1
if let giveaway {
channelsCount = Int32(giveaway.channelPeerIds.count)
var channelCount = 0
var groupCount = 0
for peerId in giveaway.channelPeerIds {
if let peer = message.peers[peerId] as? TelegramChannel {
switch peer.info {
case .broadcast:
channelCount += 1
case .group:
groupCount += 1
}
}
}
if groupCount > 0 && channelCount > 0 {
groupsAndChannels = true
}
} else if let giveawayResults {
channelsCount = 1 + giveawayResults.additionalChannelsCount
}
let timeZone = TimeZone.current
let untilDate = stringForDate(timestamp: untilDateValue, timeZone: timeZone, strings: presentationData.strings)
let title: String
var text: String
var warning: String?
var actions: [AlertScreen.Action] = [
.init(title: presentationData.strings.Common_OK, type: .default)
]
var additionalPrizes = ""
if let prizeDescription, !prizeDescription.isEmpty {
additionalPrizes = "\n\n" + presentationData.strings.Chat_Giveaway_Info_AdditionalPrizes(peerName, "\(quantity) \(prizeDescription)").string
}
switch giveawayInfo {
case let .ongoing(start, status):
let startDate = presentationData.strings.Chat_Giveaway_Info_FullDate(
stringForMessageTimestamp(timestamp: start, dateTimeFormat: presentationData.dateTimeFormat),
stringForDate(timestamp: start, timeZone: timeZone, strings: presentationData.strings)
).string.trimmingCharacters(in: CharacterSet(charactersIn: "*"))
title = presentationData.strings.Chat_Giveaway_Info_Title
let intro: String
if stars > 0 {
let starsString = presentationData.strings.Chat_Giveaway_Info_Stars_Stars(Int32(clamping: stars))
if case .almostOver = status {
if isGroup {
intro = presentationData.strings.Chat_Giveaway_Info_Stars_Group_EndedIntro(peerName, starsString).string
} else {
intro = presentationData.strings.Chat_Giveaway_Info_Stars_EndedIntro(peerName, starsString).string
}
} else {
if isGroup {
intro = presentationData.strings.Chat_Giveaway_Info_Stars_Group_OngoingIntro(peerName, starsString).string
} else {
intro = presentationData.strings.Chat_Giveaway_Info_Stars_OngoingIntro(peerName, starsString).string
}
}
} else {
let subscriptionsString = presentationData.strings.Chat_Giveaway_Info_Subscriptions(quantity)
let monthsString = presentationData.strings.Chat_Giveaway_Info_Months(months)
if case .almostOver = status {
if isGroup {
intro = presentationData.strings.Chat_Giveaway_Info_Group_EndedIntro(peerName, subscriptionsString, monthsString).string
} else {
intro = presentationData.strings.Chat_Giveaway_Info_EndedIntro(peerName, subscriptionsString, monthsString).string
}
} else {
if isGroup {
intro = presentationData.strings.Chat_Giveaway_Info_Group_OngoingIntro(peerName, subscriptionsString, monthsString).string
} else {
intro = presentationData.strings.Chat_Giveaway_Info_OngoingIntro(peerName, subscriptionsString, monthsString).string
}
}
}
var otherText: String = ""
if channelsCount > 1 {
if isGroup {
if groupsAndChannels {
if channelsCount == 2 {
otherText = presentationData.strings.Chat_Giveaway_Info_OtherChannels(Int32(channelsCount - 1))
} else {
otherText = presentationData.strings.Chat_Giveaway_Info_OtherGroupsAndChannels(Int32(channelsCount - 1))
}
} else {
otherText = presentationData.strings.Chat_Giveaway_Info_OtherGroups(Int32(channelsCount - 1))
}
} else {
if groupsAndChannels {
if channelsCount == 2 {
otherText = presentationData.strings.Chat_Giveaway_Info_OtherGroups(Int32(channelsCount - 1))
} else {
otherText = presentationData.strings.Chat_Giveaway_Info_OtherChannelsAndGroups(Int32(channelsCount - 1))
}
} else {
otherText = presentationData.strings.Chat_Giveaway_Info_OtherChannels(Int32(channelsCount - 1))
}
}
}
let ending: String
if onlyNewSubscribers {
let randomUsers = presentationData.strings.Chat_Giveaway_Info_RandomUsers(quantity)
if channelsCount > 1 {
ending = presentationData.strings.Chat_Giveaway_Info_OngoingNewMany(untilDate, randomUsers, peerName, otherText, startDate).string
} else {
ending = presentationData.strings.Chat_Giveaway_Info_OngoingNew(untilDate, randomUsers, peerName, startDate).string
}
} else {
let randomSubscribers = isGroup ? presentationData.strings.Chat_Giveaway_Info_Group_RandomMembers(quantity) : presentationData.strings.Chat_Giveaway_Info_RandomSubscribers(quantity)
if channelsCount > 1 {
ending = presentationData.strings.Chat_Giveaway_Info_OngoingMany(untilDate, randomSubscribers, peerName, otherText).string
} else {
ending = presentationData.strings.Chat_Giveaway_Info_Ongoing(untilDate, randomSubscribers, peerName).string
}
}
var participation: String
switch status {
case .notQualified:
if channelsCount > 1 {
participation = presentationData.strings.Chat_Giveaway_Info_NotQualifiedMany(peerName, otherText, 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
var isGroup = false
if let maybePeer = peerMap[adminId], let peer = maybePeer {
channelName = peer.compactDisplayTitle
if case let .channel(channel) = peer, case .group = channel.info {
isGroup = true
}
}
participation = isGroup ? presentationData.strings.Chat_Giveaway_Info_NotAllowedAdminGroup(channelName).string : presentationData.strings.Chat_Giveaway_Info_NotAllowedAdmin(channelName).string
case .disallowedCountry:
participation = presentationData.strings.Chat_Giveaway_Info_NotAllowedCountry
}
case .participating:
if channelsCount > 1 {
participation = presentationData.strings.Chat_Giveaway_Info_ParticipatingMany(peerName, otherText).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)\(additionalPrizes)\n\n\(ending)\(participation)"
case let .finished(status, start, finish, _, activatedCount):
let startDate = presentationData.strings.Chat_Giveaway_Info_FullDate(
stringForMessageTimestamp(timestamp: start, dateTimeFormat: presentationData.dateTimeFormat),
stringForDate(timestamp: start, timeZone: timeZone, strings: presentationData.strings)
).string.trimmingCharacters(in: CharacterSet(charactersIn: "*"))
let finishDate = stringForDate(timestamp: finish, timeZone: timeZone, strings: presentationData.strings)
title = presentationData.strings.Chat_Giveaway_Info_EndedTitle
let intro: String
if stars > 0 {
let starsString = presentationData.strings.Chat_Giveaway_Info_Stars_Stars(Int32(clamping: stars))
if isGroup {
intro = presentationData.strings.Chat_Giveaway_Info_Stars_Group_EndedIntro(peerName, starsString).string
} else {
intro = presentationData.strings.Chat_Giveaway_Info_Stars_EndedIntro(peerName, starsString).string
}
} else {
let subscriptionsString = presentationData.strings.Chat_Giveaway_Info_Subscriptions(quantity)
let monthsString = presentationData.strings.Chat_Giveaway_Info_Months(months)
if isGroup {
intro = presentationData.strings.Chat_Giveaway_Info_Group_EndedIntro(peerName, subscriptionsString, monthsString).string
} else {
intro = presentationData.strings.Chat_Giveaway_Info_EndedIntro(peerName, subscriptionsString, monthsString).string
}
}
var ending: String
if onlyNewSubscribers {
let randomUsers = presentationData.strings.Chat_Giveaway_Info_RandomUsers(quantity)
if channelsCount > 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 = isGroup ? presentationData.strings.Chat_Giveaway_Info_Group_RandomMembers(quantity) : presentationData.strings.Chat_Giveaway_Info_RandomSubscribers(quantity)
if channelsCount > 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 let activatedCount, 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
case .notWon:
result = "**\(presentationData.strings.Chat_Giveaway_Info_DidntWin)**\n\n"
case let .wonPremium(slug):
result = "**\(presentationData.strings.Chat_Giveaway_Info_Won("").string)**\n\n"
actions = [
.init(title: presentationData.strings.Chat_Giveaway_Info_ViewPrize, type: .default, action: {
openLink(slug)
}),
.init(title: presentationData.strings.Common_Cancel)
]
case let .wonStars(stars):
let _ = stars
result = "**\(presentationData.strings.Chat_Giveaway_Info_Won("").string)**\n\n"
actions = [
.init(title: presentationData.strings.Chat_Giveaway_Info_ViewPrize, type: .default, action: {
openLink("")
}),
.init(title: presentationData.strings.Common_Cancel)
]
}
text = "\(result)\(intro)\(additionalPrizes)\n\n\(ending)"
}
var content: [AnyComponentWithIdentity<AlertComponentEnvironment>] = []
content.append(AnyComponentWithIdentity(
id: "title",
component: AnyComponent(
AlertTitleComponent(title: title)
)
))
content.append(AnyComponentWithIdentity(
id: "text",
component: AnyComponent(
AlertTextComponent(content: .plain(text))
)
))
if let warning {
content.append(AnyComponentWithIdentity(
id: "warning",
component: AnyComponent(
AlertTextComponent(content: .plain(warning), color: .destructive, style: .background(.bold))
)
))
}
var effectiveUpdatedPresentationData: (PresentationData, Signal<PresentationData, NoError>)
if let updatedPresentationData {
effectiveUpdatedPresentationData = updatedPresentationData
} else {
effectiveUpdatedPresentationData = (presentationData, context.sharedContext.presentationData)
}
let alertController = AlertScreen(
configuration: AlertScreen.Configuration(actionAlignment: .vertical),
content: content,
actions: actions,
updatedPresentationData: effectiveUpdatedPresentationData
)
present(alertController)
})
}