mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Update localization
This commit is contained in:
parent
983e720453
commit
d23e67a62d
@ -10151,3 +10151,150 @@ Sorry for the inconvenience.";
|
|||||||
|
|
||||||
"Stats.Boosts.ShowMoreBoosts_1" = "Show %@ More Boost";
|
"Stats.Boosts.ShowMoreBoosts_1" = "Show %@ More Boost";
|
||||||
"Stats.Boosts.ShowMoreBoosts_any" = "Show %@ More Boosts";
|
"Stats.Boosts.ShowMoreBoosts_any" = "Show %@ More Boosts";
|
||||||
|
|
||||||
|
"ReassignBoost.Title" = "Reassign Boosts";
|
||||||
|
"ReassignBoost.Description" = "To boost **%1$@**, reassign a previous boost or gift **Telegram Premium** to a friend to get **%2$@** additional boosts.";
|
||||||
|
"ReassignBoost.ReassignBoosts" = "Reassign Boosts";
|
||||||
|
"ReassignBoost.AvailableIn" = "Available in %@";
|
||||||
|
"ReassignBoost.ExpiresOn" = "Boost expires on %@";
|
||||||
|
"ReassignBoost.WaitForCooldown" = "Wait until the boost is available or get **%1$@** more boosts by gifting a **Telegram Premium** subscription.";
|
||||||
|
|
||||||
|
"ReassignBoost.Success" = "Wait until the boost is available or get **%1$@** more boosts by gifting a **Telegram Premium** subscription.";
|
||||||
|
|
||||||
|
//"\(replacedBoosts) boosts are reassigned from \(inChannels) other channel."
|
||||||
|
|
||||||
|
"ChannelBoost.MoreBoosts.Title" = "More Boosts Needed";
|
||||||
|
"ChannelBoost.MoreBoosts.Text" = "To boost **%1$@** again, gift **Telegram Premium** to a friend and get **%2$@** additional boosts.";
|
||||||
|
|
||||||
|
"BoostGift.Title" = "Boosts via Gifts";
|
||||||
|
"BoostGift.Description" = "Get more boosts for your channel by gifting\nPremium to your subscribers.";
|
||||||
|
"BoostGift.PrepaidGiveawayTitle" = "PREPAID GIVEAWAY";
|
||||||
|
"BoostGift.PrepaidGiveawayCount_1" = "%@ Telegram Premium";
|
||||||
|
"BoostGift.PrepaidGiveawayCount_any" = "%@ Telegram Premium";
|
||||||
|
"BoostGift.PrepaidGiveawayMonths" = "%@-month subscriptions";
|
||||||
|
"BoostGift.CreateGiveaway" = "Create Giveaway";
|
||||||
|
"BoostGift.CreateGiveawayInfo" = "winners are chosen randomly";
|
||||||
|
"BoostGift.AwardSpecificUsers" = "Award Specific Users";
|
||||||
|
"BoostGift.SelectRecipients" = "select recipients";
|
||||||
|
"BoostGift.QuantityTitle" = "QUANTITY OF PRIZES";
|
||||||
|
"BoostGift.QuantityBoosts_1" = "%@ BOOST";
|
||||||
|
"BoostGift.QuantityBoosts_any" = "%@ BOOSTS";
|
||||||
|
"BoostGift.QuantityInfo" = "Choose how many Premium subscriptions to give away and boosts to receive.";
|
||||||
|
"BoostGift.ChannelsTitle" = "CHANNELS INCLUDED IN THE GIVEAWAY";
|
||||||
|
"BoostGift.AddChannel" = "Add Channel";
|
||||||
|
"BoostGift.ChannelsBoosts_1" = "this channel will receive %@ boost";
|
||||||
|
"BoostGift.ChannelsBoosts_any" = "this channel will receive %@ boosts";
|
||||||
|
"BoostGift.ChannelsInfo" = "Choose the channels users need to be subscribed to take part in the giveaway";
|
||||||
|
"BoostGift.UsersTitle" = "USERS ELIGIBLE FOR THE GIVEAWAY";
|
||||||
|
"BoostGift.FromCountries_1" = "from %@ country";
|
||||||
|
"BoostGift.FromCountries_any" = "from %@ countries";
|
||||||
|
"BoostGift.FromTwoCountries" = "from %1$@ and %2$@";
|
||||||
|
"BoostGift.FromOneCountry" = "from %1$@";
|
||||||
|
"BoostGift.FromAllCountries" = "from all countries";
|
||||||
|
"BoostGift.AllSubscribers" = "All subscribers";
|
||||||
|
"BoostGift.OnlyNewSubscribers" = "Only new subscribers";
|
||||||
|
"BoostGift.LimitSubscribersInfo" = "Choose if you want to limit the giveaway only to those who joined the channel after the giveaway started.";
|
||||||
|
"BoostGift.DateTitle" = "DATE WHEN GIVEAWAY ENDS";
|
||||||
|
"BoostGift.DateEnds" = "Ends";
|
||||||
|
"BoostGift.DateInfo" = "Choose when %1$@ of your channel will be randomly selected to receive Telegram Premium.";
|
||||||
|
"BoostGift.DateInfoSubscribers_1" = "%@ subscriber";
|
||||||
|
"BoostGift.DateInfoSubscribers_any" = "%@ subscribers";
|
||||||
|
"BoostGift.DurationTitle" = "DURATION OF PREMIUM SUBSCRIPTIONS";
|
||||||
|
"BoostGift.PremiumInfo" = "You can review the list of features and terms of use for Telegram Premium [here]().";
|
||||||
|
"BoostGift.GiftPremium" = "Gift Premium";
|
||||||
|
"BoostGift.StartGiveaway" = "Start Giveaway";
|
||||||
|
"BoostGift.ReduceQuantity.Title" = "Reduce Quantity";
|
||||||
|
"BoostGift.ReduceQuantity.Text" = "You can't acquire %1$@ %2$@-month subscriptions in the app. Do you want to reduce quantity to %3$@?";
|
||||||
|
"BoostGift.ReduceQuantity.Reduce" = "Reduce";
|
||||||
|
"BoostGift.GiveawayCreated.Title" = "Giveaway Created";
|
||||||
|
"BoostGift.GiveawayCreated.Text" = "Check your channel's [Statistics]() to see how this giveaway boosted your channel.";
|
||||||
|
"BoostGift.PremiumGifted.Title" = "Premium Subscriptions Gifted";
|
||||||
|
"BoostGift.PremiumGifted.Text" = "Check your channel's [Statistics]() to see how gifts boosted your channel.";
|
||||||
|
|
||||||
|
"BoostGift.Subscribers.Title" = "Gift Premium";
|
||||||
|
"BoostGift.Subscribers.Subtitle" = "select up to %@ subscribers";
|
||||||
|
"BoostGift.Subscribers.SectionTitle" = "SUBSCRIBERS";
|
||||||
|
"BoostGift.Subscribers.Joined" = "joined %@";
|
||||||
|
"BoostGift.Subscribers.Search" = "Search Subscribers";
|
||||||
|
"BoostGift.Subscribers.MaximumReached" = "You can select maximum %@ subscribers.";
|
||||||
|
"BoostGift.Subscribers.Save" = "Save Recipients";
|
||||||
|
|
||||||
|
"BoostGift.Channels.Title" = "Add Channels";
|
||||||
|
"BoostGift.Channels.Subtitle" = "select up to %@ channels";
|
||||||
|
"BoostGift.Channels.SectionTitle" = "CHANNELS";
|
||||||
|
"BoostGift.Channels.Search" = "Search Channels";
|
||||||
|
"BoostGift.Channels.MaximumReached" = "You can select maximum %@ channels.";
|
||||||
|
"BoostGift.Channels.PrivateChannel.Title" = "Channel is Private";
|
||||||
|
"BoostGift.Channels.PrivateChannel.Text" = "Are you sure you want to add a private channel? Users won't be able to join it without an invite link.";
|
||||||
|
"BoostGift.Channels.PrivateChannel.Add" = "Add";
|
||||||
|
"BoostGift.Channels.Save" = "Save Channels";
|
||||||
|
|
||||||
|
"Stats.Boosts.PrepaidGiveawaysTitle" = "PREPAID GIVEAWAYS";
|
||||||
|
"Stats.Boosts.PrepaidGiveawayCount_any" = "%@ Telegram Premium";
|
||||||
|
"Stats.Boosts.PrepaidGiveawayMonths" = "%@-month subscriptions";
|
||||||
|
"Stats.Boosts.PrepaidGiveawaysInfo" = "Select a giveaway you already paid for to set it up.";
|
||||||
|
"Stats.Boosts.ShortMonth" = "%@m";
|
||||||
|
"Stats.Boosts.Giveaway" = "Giveaway";
|
||||||
|
"Stats.Boosts.Gift" = "Gift";
|
||||||
|
"Stats.Boosts.TabBoosts_1" = "%@ Boost";
|
||||||
|
"Stats.Boosts.TabBoosts_any" = "%@ Boosts";
|
||||||
|
"Stats.Boosts.TabGifts_1" = "%@ Boost";
|
||||||
|
"Stats.Boosts.TabGifts_any" = "%@ Boosts";
|
||||||
|
"Stats.Boosts.ToBeDistributed" = "To Be Distributed";
|
||||||
|
"Stats.Boosts.Unclaimed" = "Unclaimed";
|
||||||
|
"Stats.Boosts.GetBoosts" = "Get Boosts via Gifts";
|
||||||
|
"Stats.Boosts.GetBoostsInfo" = "Get more boosts for your channel by gifting Premium to your subscribers.";
|
||||||
|
|
||||||
|
"Notification.PremiumPrize.Title" = "Congratulations!";
|
||||||
|
"Notification.PremiumPrize.UnclaimedText" = "You have an unclaimed prize from a giveaway by **%1$@**.\n\nThis prize is a **Telegram Premium** subscription for %2$@.";
|
||||||
|
"Notification.PremiumPrize.GiveawayText" = "You won a prize in a giveaway organized by **%1$@**.\n\nYour prize is a **Telegram Premium** subscription for %2$@.";
|
||||||
|
"Notification.PremiumPrize.GiftText" = "You've received a gift from **%1$@**.\n\nYour gift is a **Telegram Premium** subscription for %2$@.";
|
||||||
|
"Notification.PremiumPrize.Months_1" = "**%@** month";
|
||||||
|
"Notification.PremiumPrize.Months_any" = "**%@** months";
|
||||||
|
"Notification.PremiumPrize.View" = "Open Gift Link";
|
||||||
|
"Notification.PremiumPrize.Unclaimed" = "Unclaimed Prize";
|
||||||
|
|
||||||
|
"Story.SlideToSeek" = "Slide left or right to seek";
|
||||||
|
"Story.Guide.Title" = "Watching Stories";
|
||||||
|
"Story.Guide.Description" = "You can use these gestures to control playback.";
|
||||||
|
"Story.Guide.ForwardTitle" = "Go forward";
|
||||||
|
"Story.Guide.ForwardDescription" = "Tap the screen";
|
||||||
|
"Story.Guide.PauseTitle" = "Pause and Seek";
|
||||||
|
"Story.Guide.PauseDescription" = "Hold and move sideways";
|
||||||
|
"Story.Guide.BackTitle" = "Go back";
|
||||||
|
"Story.Guide.BackDescription" = "Tap the left edge";
|
||||||
|
"Story.Guide.MoveTitle" = "Move between stories";
|
||||||
|
"Story.Guide.MoveDescription" = "Swipe left or right";
|
||||||
|
"Story.Guide.Proceed" = "Tap to keep watching";
|
||||||
|
|
||||||
|
"Chat.Giveaway.Info.Title" = "About This Giveaway";
|
||||||
|
"Chat.Giveaway.Info.EndedTitle" = "Giveaway Ended";
|
||||||
|
|
||||||
|
"Chat.Giveaway.Info.AlmostOver" = "The giveaway is almost over.";
|
||||||
|
|
||||||
|
"Chat.Giveaway.Info.Subscriptions_1" = "**%@ Telegram Premium** subscription";
|
||||||
|
"Chat.Giveaway.Info.Subscriptions_any" = "**%@ Telegram Premium** subscriptions";
|
||||||
|
|
||||||
|
"Chat.Giveaway.Info.RandomUsers_1" = "**%@** random user";
|
||||||
|
"Chat.Giveaway.Info.RandomUsers_any" = "**%@** random user";
|
||||||
|
|
||||||
|
"Chat.Giveaway.Info.RandomSubscribers_1" = "**%@** random subscriber";
|
||||||
|
"Chat.Giveaway.Info.RandomSubscribers_any" = "**%@** random subscribers";
|
||||||
|
|
||||||
|
"Chat.Giveaway.Info.Months_1" = "**%@** month";
|
||||||
|
"Chat.Giveaway.Info.Months_any" = "**%@** months";
|
||||||
|
|
||||||
|
"Chat.Giveaway.Info.ActivatedLinks_1" = "%@ winner already used their gift link.";
|
||||||
|
"Chat.Giveaway.Info.ActivatedLinks_any" = "%@ of the winners already used their gift links.";
|
||||||
|
|
||||||
|
"Chat.Giveaway.Info.Refunded" = "The channel cancelled the prizes by reversing the payment for them.";
|
||||||
|
"Chat.Giveaway.Info.Won" = "You won a prize in this giveaway. %@";
|
||||||
|
"Chat.Giveaway.Info.DidntWin" = "You didn't win a prize in this giveaway.";
|
||||||
|
"Chat.Giveaway.Info.ViewPrize" = "View My Prize";
|
||||||
|
|
||||||
|
"Chat.Giveaway.Toast.NotAllowed" = "You can't participate in this giveaway.";
|
||||||
|
"Chat.Giveaway.Toast.Participating" = "You are participating in this giveaway.";
|
||||||
|
"Chat.Giveaway.Toast.NotQualified" = "You are not qualified for this giveaway yet.";
|
||||||
|
"Chat.Giveaway.Toast.AlmostOver" = "The giveaway is almost over.";
|
||||||
|
"Chat.Giveaway.Toast.Ended" = "The giveaway is ended.";
|
||||||
|
"Chat.Giveaway.Toast.LearnMore" = "Learn More";
|
||||||
|
@ -109,6 +109,7 @@ swift_library(
|
|||||||
"//submodules/CountrySelectionUI",
|
"//submodules/CountrySelectionUI",
|
||||||
"//submodules/TelegramUI/Components/Stories/PeerListItemComponent",
|
"//submodules/TelegramUI/Components/Stories/PeerListItemComponent",
|
||||||
"//submodules/InvisibleInkDustNode",
|
"//submodules/InvisibleInkDustNode",
|
||||||
|
"//submodules/AlertUI",
|
||||||
],
|
],
|
||||||
visibility = [
|
visibility = [
|
||||||
"//visibility:public",
|
"//visibility:public",
|
||||||
|
@ -377,8 +377,7 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
|
|||||||
case let .channelsHeader(_, text):
|
case let .channelsHeader(_, text):
|
||||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||||
case let .channel(_, _, peer, boosts, isRevealed):
|
case let .channel(_, _, peer, boosts, isRevealed):
|
||||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: PresentationDateTimeFormat(), nameDisplayOrder: presentationData.nameDisplayOrder, context: arguments.context, peer: peer, presence: nil, text: boosts.flatMap { .text("this channel will receive \($0) boosts", .secondary) } ?? .none, label: .none, editing: ItemListPeerItemEditing(editable: boosts == nil, editing: false, revealed: isRevealed), switchValue: nil, enabled: true, selectable: peer.id != arguments.context.account.peerId, sectionId: self.section, action: {
|
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: PresentationDateTimeFormat(), nameDisplayOrder: presentationData.nameDisplayOrder, context: arguments.context, peer: peer, presence: nil, text: boosts.flatMap { .text(presentationData.strings.BoostGift_ChannelsBoosts($0), .secondary) } ?? .none, label: .none, editing: ItemListPeerItemEditing(editable: boosts == nil, editing: false, revealed: isRevealed), switchValue: nil, enabled: true, selectable: peer.id != arguments.context.account.peerId, sectionId: self.section, action: {
|
||||||
// arguments.openPeer(peer)
|
|
||||||
}, setPeerIdWithRevealedOptions: { lhs, rhs in
|
}, setPeerIdWithRevealedOptions: { lhs, rhs in
|
||||||
arguments.setItemIdWithRevealedOptions(lhs, rhs)
|
arguments.setItemIdWithRevealedOptions(lhs, rhs)
|
||||||
}, removePeer: { id in
|
}, removePeer: { id in
|
||||||
@ -433,7 +432,7 @@ private enum CreateGiveawayEntry: ItemListNodeEntry {
|
|||||||
} else {
|
} else {
|
||||||
text = presentationData.strings.InviteLink_Create_TimeLimitExpiryDateNever
|
text = presentationData.strings.InviteLink_Create_TimeLimitExpiryDateNever
|
||||||
}
|
}
|
||||||
return ItemListDisclosureItem(presentationData: presentationData, title: "Ends", label: text, labelStyle: active ? .coloredText(theme.list.itemAccentColor) : .text, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: {
|
return ItemListDisclosureItem(presentationData: presentationData, title: presentationData.strings.BoostGift_DateEnds, label: text, labelStyle: active ? .coloredText(theme.list.itemAccentColor) : .text, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: {
|
||||||
arguments.dismissInput()
|
arguments.dismissInput()
|
||||||
var focus = false
|
var focus = false
|
||||||
arguments.updateState { state in
|
arguments.updateState { state in
|
||||||
@ -515,7 +514,7 @@ private func createGiveawayControllerEntries(
|
|||||||
|
|
||||||
switch subject {
|
switch subject {
|
||||||
case .generic:
|
case .generic:
|
||||||
entries.append(.createGiveaway(presentationData.theme, "Create Giveaway", "winners are chosen randomly", state.mode == .giveaway))
|
entries.append(.createGiveaway(presentationData.theme, presentationData.strings.BoostGift_CreateGiveaway, presentationData.strings.BoostGift_CreateGiveawayInfo, state.mode == .giveaway))
|
||||||
|
|
||||||
let recipientsText: String
|
let recipientsText: String
|
||||||
if !state.peers.isEmpty {
|
if !state.peers.isEmpty {
|
||||||
@ -533,22 +532,22 @@ private func createGiveawayControllerEntries(
|
|||||||
recipientsText = presentationData.strings.PremiumGift_LabelRecipients(Int32(peersCount))
|
recipientsText = presentationData.strings.PremiumGift_LabelRecipients(Int32(peersCount))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
recipientsText = "select recipients"
|
recipientsText = presentationData.strings.BoostGift_SelectRecipients
|
||||||
}
|
}
|
||||||
entries.append(.awardUsers(presentationData.theme, "Award Specific Users", recipientsText, state.mode == .gift))
|
entries.append(.awardUsers(presentationData.theme, presentationData.strings.BoostGift_AwardSpecificUsers, recipientsText, state.mode == .gift))
|
||||||
case let .prepaid(prepaidGiveaway):
|
case let .prepaid(prepaidGiveaway):
|
||||||
entries.append(.prepaidHeader(presentationData.theme, "PREPAID GIVEAWAY"))
|
entries.append(.prepaidHeader(presentationData.theme, presentationData.strings.BoostGift_PrepaidGiveawayTitle))
|
||||||
entries.append(.prepaid(presentationData.theme, "\(prepaidGiveaway.quantity) Telegram Premium", "\(prepaidGiveaway.months)-month subscriptions", prepaidGiveaway))
|
entries.append(.prepaid(presentationData.theme, presentationData.strings.BoostGift_PrepaidGiveawayCount(prepaidGiveaway.quantity), presentationData.strings.BoostGift_PrepaidGiveawayMonths("\(prepaidGiveaway.months)").string, prepaidGiveaway))
|
||||||
}
|
}
|
||||||
|
|
||||||
if case .giveaway = state.mode {
|
if case .giveaway = state.mode {
|
||||||
if case .generic = subject {
|
if case .generic = subject {
|
||||||
entries.append(.subscriptionsHeader(presentationData.theme, "QUANTITY OF PRIZES".uppercased(), "\(state.subscriptions * 4) BOOSTS"))
|
entries.append(.subscriptionsHeader(presentationData.theme, presentationData.strings.BoostGift_QuantityTitle.uppercased(), presentationData.strings.BoostGift_QuantityBoosts(state.subscriptions * 4)))
|
||||||
entries.append(.subscriptions(presentationData.theme, state.subscriptions))
|
entries.append(.subscriptions(presentationData.theme, state.subscriptions))
|
||||||
entries.append(.subscriptionsInfo(presentationData.theme, "Choose how many Premium subscriptions to give away and boosts to receive."))
|
entries.append(.subscriptionsInfo(presentationData.theme, presentationData.strings.BoostGift_QuantityInfo))
|
||||||
}
|
}
|
||||||
|
|
||||||
entries.append(.channelsHeader(presentationData.theme, "CHANNELS INCLUDED IN THE GIVEAWAY".uppercased()))
|
entries.append(.channelsHeader(presentationData.theme, presentationData.strings.BoostGift_ChannelsTitle.uppercased()))
|
||||||
var index: Int32 = 0
|
var index: Int32 = 0
|
||||||
let channels = [peerId] + state.channels
|
let channels = [peerId] + state.channels
|
||||||
for channelId in channels {
|
for channelId in channels {
|
||||||
@ -557,35 +556,44 @@ private func createGiveawayControllerEntries(
|
|||||||
}
|
}
|
||||||
index += 1
|
index += 1
|
||||||
}
|
}
|
||||||
entries.append(.channelAdd(presentationData.theme, "Add Channel"))
|
entries.append(.channelAdd(presentationData.theme, presentationData.strings.BoostGift_AddChannel))
|
||||||
entries.append(.channelsInfo(presentationData.theme, "Choose the channels users need to be subscribed to take part in the giveaway"))
|
entries.append(.channelsInfo(presentationData.theme, presentationData.strings.BoostGift_ChannelsInfo))
|
||||||
|
|
||||||
entries.append(.usersHeader(presentationData.theme, "USERS ELIGIBLE FOR THE GIVEAWAY".uppercased()))
|
entries.append(.usersHeader(presentationData.theme, presentationData.strings.BoostGift_UsersTitle.uppercased()))
|
||||||
|
|
||||||
let countriesText: String
|
let countriesText: String
|
||||||
if state.countries.count > 2 {
|
if state.countries.count > 2 {
|
||||||
countriesText = "from \(state.countries.count) countries"
|
countriesText = presentationData.strings.BoostGift_FromCountries(Int32(state.countries.count))
|
||||||
} else if !state.countries.isEmpty {
|
} else if !state.countries.isEmpty {
|
||||||
let allCountries = state.countries.map { locale.localizedString(forRegionCode: $0) ?? $0 }.joined(separator: " and ")
|
if state.countries.count == 2 {
|
||||||
countriesText = "from \(allCountries)"
|
let firstCountryCode = state.countries.first ?? ""
|
||||||
|
let secondCountryCode = state.countries.last ?? ""
|
||||||
|
let firstCountryName = locale.localizedString(forRegionCode: firstCountryCode) ?? firstCountryCode
|
||||||
|
let secondCountryName = locale.localizedString(forRegionCode: secondCountryCode) ?? secondCountryCode
|
||||||
|
countriesText = presentationData.strings.BoostGift_FromTwoCountries(firstCountryName, secondCountryName).string
|
||||||
|
} else {
|
||||||
|
let countryCode = state.countries.first ?? ""
|
||||||
|
let countryName = locale.localizedString(forRegionCode: countryCode) ?? countryCode
|
||||||
|
countriesText = presentationData.strings.BoostGift_FromOneCountry(countryName).string
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
countriesText = "from all countries"
|
countriesText = presentationData.strings.BoostGift_FromAllCountries
|
||||||
}
|
}
|
||||||
|
|
||||||
entries.append(.usersAll(presentationData.theme, "All subscribers", countriesText, !state.onlyNewEligible))
|
entries.append(.usersAll(presentationData.theme, presentationData.strings.BoostGift_AllSubscribers, countriesText, !state.onlyNewEligible))
|
||||||
entries.append(.usersNew(presentationData.theme, "Only new subscribers", countriesText, state.onlyNewEligible))
|
entries.append(.usersNew(presentationData.theme, presentationData.strings.BoostGift_OnlyNewSubscribers, countriesText, state.onlyNewEligible))
|
||||||
entries.append(.usersInfo(presentationData.theme, "Choose if you want to limit the giveaway only to those who joined the channel after the giveaway started."))
|
entries.append(.usersInfo(presentationData.theme, presentationData.strings.BoostGift_LimitSubscribersInfo))
|
||||||
|
|
||||||
entries.append(.timeHeader(presentationData.theme, "DATE WHEN GIVEAWAY ENDS".uppercased()))
|
entries.append(.timeHeader(presentationData.theme, presentationData.strings.BoostGift_DateTitle.uppercased()))
|
||||||
entries.append(.timeExpiryDate(presentationData.theme, presentationData.dateTimeFormat, state.time, state.pickingTimeLimit))
|
entries.append(.timeExpiryDate(presentationData.theme, presentationData.dateTimeFormat, state.time, state.pickingTimeLimit))
|
||||||
if state.pickingTimeLimit {
|
if state.pickingTimeLimit {
|
||||||
entries.append(.timeCustomPicker(presentationData.theme, presentationData.dateTimeFormat, state.time, minDate, maxDate))
|
entries.append(.timeCustomPicker(presentationData.theme, presentationData.dateTimeFormat, state.time, minDate, maxDate))
|
||||||
}
|
}
|
||||||
entries.append(.timeInfo(presentationData.theme, "Choose when \(state.subscriptions) subscribers of your channel will be randomly selected to receive Telegram Premium."))
|
entries.append(.timeInfo(presentationData.theme, presentationData.strings.BoostGift_DateInfo(presentationData.strings.BoostGift_DateInfoSubscribers(Int32(state.subscriptions))).string))
|
||||||
}
|
}
|
||||||
|
|
||||||
if case .generic = subject {
|
if case .generic = subject {
|
||||||
entries.append(.durationHeader(presentationData.theme, "DURATION OF PREMIUM SUBSCRIPTIONS".uppercased()))
|
entries.append(.durationHeader(presentationData.theme, presentationData.strings.BoostGift_DurationTitle.uppercased()))
|
||||||
|
|
||||||
let recipientCount: Int
|
let recipientCount: Int
|
||||||
switch state.mode {
|
switch state.mode {
|
||||||
@ -628,7 +636,7 @@ private func createGiveawayControllerEntries(
|
|||||||
i += 1
|
i += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
entries.append(.durationInfo(presentationData.theme, "You can review the list of features and terms of use for Telegram Premium [here]()."))
|
entries.append(.durationInfo(presentationData.theme, presentationData.strings.BoostGift_PremiumInfo))
|
||||||
}
|
}
|
||||||
|
|
||||||
return entries
|
return entries
|
||||||
@ -776,7 +784,7 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
|
|||||||
|
|
||||||
let (state, peersMap) = stateAndPeersMap
|
let (state, peersMap) = stateAndPeersMap
|
||||||
|
|
||||||
let headerItem = CreateGiveawayHeaderItem(theme: presentationData.theme, title: "Boosts via Gifts", text: "Get more boosts for your channel by gifting\nPremium to your subscribers.", cancel: {
|
let headerItem = CreateGiveawayHeaderItem(theme: presentationData.theme, strings: presentationData.strings, title: presentationData.strings.BoostGift_Title, text: presentationData.strings.BoostGift_Description, cancel: {
|
||||||
dismissImpl?()
|
dismissImpl?()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -787,7 +795,7 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
|
|||||||
case .gift:
|
case .gift:
|
||||||
badgeCount = Int32(state.peers.count)
|
badgeCount = Int32(state.peers.count)
|
||||||
}
|
}
|
||||||
let footerItem = CreateGiveawayFooterItem(theme: presentationData.theme, title: state.mode == .gift ? "Gift Premium" : "Start Giveaway", 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?()
|
||||||
})
|
})
|
||||||
let leftNavigationButton = ItemListNavigationButton(content: .none, style: .regular, enabled: false, action: {})
|
let leftNavigationButton = ItemListNavigationButton(content: .none, style: .regular, enabled: false, action: {})
|
||||||
@ -857,7 +865,7 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
|
|||||||
}
|
}
|
||||||
|
|
||||||
guard let selectedProduct else {
|
guard let selectedProduct else {
|
||||||
let alertController = textAlertController(context: context, title: "Reduce Quantity", text: "You can't acquire \(state.subscriptions) \(selectedMonths)-month subscriptions in the app. Do you want to reduce quantity to 25?", actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: "Reduce", action: {
|
let alertController = textAlertController(context: context, title: presentationData.strings.BoostGift_ReduceQuantity_Title, text: presentationData.strings.BoostGift_ReduceQuantity_Text("\(state.subscriptions)", "\(selectedMonths)", "\(25)").string, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: presentationData.strings.BoostGift_ReduceQuantity_Reduce, action: {
|
||||||
updateState { state in
|
updateState { state in
|
||||||
var updatedState = state
|
var updatedState = state
|
||||||
updatedState.subscriptions = 25
|
updatedState.subscriptions = 25
|
||||||
@ -915,11 +923,11 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
|
|||||||
let text: String
|
let text: String
|
||||||
switch state.mode {
|
switch state.mode {
|
||||||
case .giveaway:
|
case .giveaway:
|
||||||
title = "Giveaway Created"
|
title = presentationData.strings.BoostGift_GiveawayCreated_Title
|
||||||
text = "Check your channel's [Statistics]() to see how this giveaway boosted your channel."
|
text = presentationData.strings.BoostGift_GiveawayCreated_Text
|
||||||
case .gift:
|
case .gift:
|
||||||
title = "Premium Subscriptions Gifted"
|
title = presentationData.strings.BoostGift_PremiumGifted_Title
|
||||||
text = "Check your channel's [Statistics]() to see how gifts boosted your channel."
|
text = presentationData.strings.BoostGift_PremiumGifted_Text
|
||||||
}
|
}
|
||||||
|
|
||||||
let tooltipController = UndoOverlayController(presentationData: presentationData, content: .premiumPaywall(title: title, text: text, customUndoText: nil, timeout: nil, linkAction: { [weak navigationController] _ in
|
let tooltipController = UndoOverlayController(presentationData: presentationData, content: .premiumPaywall(title: title, text: text, customUndoText: nil, timeout: nil, linkAction: { [weak navigationController] _ in
|
||||||
@ -992,8 +1000,8 @@ public func createGiveawayController(context: AccountContext, updatedPresentatio
|
|||||||
controllers.removeLast(count)
|
controllers.removeLast(count)
|
||||||
navigationController.setViewControllers(controllers, animated: true)
|
navigationController.setViewControllers(controllers, animated: true)
|
||||||
|
|
||||||
let title = "Giveaway Created"
|
let title = presentationData.strings.BoostGift_GiveawayCreated_Title
|
||||||
let text = "Check your channel's [Statistics]() to see how this giveaway boosted your channel."
|
let text = presentationData.strings.BoostGift_GiveawayCreated_Text
|
||||||
|
|
||||||
let tooltipController = UndoOverlayController(presentationData: presentationData, content: .premiumPaywall(title: title, text: text, customUndoText: nil, timeout: nil, linkAction: { [weak navigationController] _ in
|
let tooltipController = UndoOverlayController(presentationData: presentationData, content: .premiumPaywall(title: title, text: text, customUndoText: nil, timeout: nil, linkAction: { [weak navigationController] _ in
|
||||||
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.StatsDatacenterId(id: peerId))
|
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.StatsDatacenterId(id: peerId))
|
||||||
|
@ -11,12 +11,14 @@ import ComponentFlow
|
|||||||
|
|
||||||
final class CreateGiveawayHeaderItem: ItemListControllerHeaderItem {
|
final class CreateGiveawayHeaderItem: ItemListControllerHeaderItem {
|
||||||
let theme: PresentationTheme
|
let theme: PresentationTheme
|
||||||
|
let strings: PresentationStrings
|
||||||
let title: String
|
let title: String
|
||||||
let text: String
|
let text: String
|
||||||
let cancel: () -> Void
|
let cancel: () -> Void
|
||||||
|
|
||||||
init(theme: PresentationTheme, title: String, text: String, cancel: @escaping () -> Void) {
|
init(theme: PresentationTheme, strings: PresentationStrings, title: String, text: String, cancel: @escaping () -> Void) {
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
|
self.strings = strings
|
||||||
self.title = title
|
self.title = title
|
||||||
self.text = text
|
self.text = text
|
||||||
self.cancel = cancel
|
self.cancel = cancel
|
||||||
@ -132,7 +134,7 @@ class CreateGiveawayHeaderItemNode: ItemListControllerHeaderItemNode {
|
|||||||
self.titleNode.attributedText = attributedTitle
|
self.titleNode.attributedText = attributedTitle
|
||||||
self.textNode.attributedText = attributedText
|
self.textNode.attributedText = attributedText
|
||||||
|
|
||||||
self.cancelNode.setAttributedTitle(NSAttributedString(string: "Cancel", font: Font.regular(17.0), textColor: self.item.theme.rootController.navigationBar.accentTextColor), for: .normal)
|
self.cancelNode.setAttributedTitle(NSAttributedString(string: self.item.strings.Common_Cancel, font: Font.regular(17.0), textColor: self.item.theme.rootController.navigationBar.accentTextColor), for: .normal)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func updateContentOffset(_ contentOffset: CGFloat, transition: ContainedViewLayoutTransition) {
|
override func updateContentOffset(_ contentOffset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
|
@ -4,12 +4,161 @@ import AsyncDisplayKit
|
|||||||
import Display
|
import Display
|
||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
import TelegramCore
|
import TelegramCore
|
||||||
import TelegramPresentationData
|
|
||||||
import TextFormat
|
|
||||||
import AccountContext
|
import AccountContext
|
||||||
import AlertUI
|
import TelegramStringFormatting
|
||||||
import PresentationDataUtils
|
import TelegramPresentationData
|
||||||
import Markdown
|
import Markdown
|
||||||
|
import AlertUI
|
||||||
|
|
||||||
|
public func giveawayInfoController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, message: EngineMessage, giveawayInfo: PremiumGiveawayInfo) -> ViewController? {
|
||||||
|
guard let giveaway = message.media.first(where: { $0 is TelegramMediaGiveaway }) as? TelegramMediaGiveaway else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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 = "The giveaway was sponsored by the admins of **\(peerName)**, who acquired **\(giveaway.quantity) Telegram Premium** subscriptions for **\(giveaway.months)** months for its followers."
|
||||||
|
} else {
|
||||||
|
intro = "The giveaway is sponsored by the admins of **\(peerName)**, who acquired **\(giveaway.quantity) Telegram Premium** subscriptions for **\(giveaway.months)** months for its followers."
|
||||||
|
}
|
||||||
|
|
||||||
|
let ending: String
|
||||||
|
if giveaway.flags.contains(.onlyNewSubscribers) {
|
||||||
|
if giveaway.channelPeerIds.count > 1 {
|
||||||
|
ending = "On **\(untilDate)**, Telegram will automatically select **\(giveaway.quantity)** random users that joined **\(peerName)** and **\(giveaway.channelPeerIds.count - 1)** other listed channels after **\(startDate)**."
|
||||||
|
} else {
|
||||||
|
ending = "On **\(untilDate)**, Telegram will automatically select **\(giveaway.quantity)** random users that joined **\(peerName)** after **\(startDate)**."
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if giveaway.channelPeerIds.count > 1 {
|
||||||
|
ending = "On **\(untilDate)**, Telegram will automatically select **\(giveaway.quantity)** random subscribers of **\(peerName)** and **\(giveaway.channelPeerIds.count - 1)** other listed channels."
|
||||||
|
} else {
|
||||||
|
ending = "On **\(untilDate)**, Telegram will automatically select **\(giveaway.quantity)** random subscribers of **\(peerName)**."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var participation: String
|
||||||
|
switch status {
|
||||||
|
case .notQualified:
|
||||||
|
if giveaway.channelPeerIds.count > 1 {
|
||||||
|
participation = "To take part in this giveaway please join the channel **\(peerName)** (**\(giveaway.channelPeerIds.count - 1)** other listed channels) before **\(untilDate)**."
|
||||||
|
} else {
|
||||||
|
participation = "To take part in this giveaway please join the channel **\(peerName)** before **\(untilDate)**."
|
||||||
|
}
|
||||||
|
case let .notAllowed(reason):
|
||||||
|
switch reason {
|
||||||
|
case let .joinedTooEarly(joinedOn):
|
||||||
|
let joinDate = stringForDate(timestamp: joinedOn, strings: presentationData.strings)
|
||||||
|
participation = "You are not eligible to participate in this giveaway, because you joined this channel on **\(joinDate)**, which is before the contest started."
|
||||||
|
case let .channelAdmin(adminId):
|
||||||
|
let _ = adminId
|
||||||
|
participation = "You are not eligible to participate in this giveaway, because you are an admin of participating channel (**\(peerName)**)."
|
||||||
|
case let .disallowedCountry(countryCode):
|
||||||
|
let _ = countryCode
|
||||||
|
participation = "You are not eligible to participate in this giveaway, because your country is not included in the terms of the giveaway."
|
||||||
|
}
|
||||||
|
case .participating:
|
||||||
|
if giveaway.channelPeerIds.count > 1 {
|
||||||
|
participation = "You are participating in this giveaway, because you have joined the channel **\(peerName)** (**\(giveaway.channelPeerIds.count - 1)** other listed channels)."
|
||||||
|
} else {
|
||||||
|
participation = "You are participating in this giveaway, because you have joined the channel **\(peerName)**."
|
||||||
|
}
|
||||||
|
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 = "The giveaway was sponsored by the admins of **\(peerName)**, who acquired **\(giveaway.quantity) Telegram Premium** subscriptions for **\(giveaway.months)** months for its followers."
|
||||||
|
|
||||||
|
var ending: String
|
||||||
|
if giveaway.flags.contains(.onlyNewSubscribers) {
|
||||||
|
if giveaway.channelPeerIds.count > 1 {
|
||||||
|
ending = "On **\(finishDate)**, Telegram automatically selected **\(giveaway.quantity)** random users that joined **\(peerName)** and other listed channels after **\(startDate)**."
|
||||||
|
} else {
|
||||||
|
ending = "On **\(finishDate)**, Telegram automatically selected **\(giveaway.quantity)** random users that joined **\(peerName)** after **\(startDate)**."
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if giveaway.channelPeerIds.count > 1 {
|
||||||
|
ending = "On **\(finishDate)**, Telegram automatically selected **\(giveaway.quantity)** random subscribers of **\(peerName)** and other listed channels."
|
||||||
|
} else {
|
||||||
|
ending = "On **\(finishDate)**, Telegram automatically selected **\(giveaway.quantity)** random subscribers of **\(peerName)**."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
let _ = slug
|
||||||
|
actions = [TextAlertAction(type: .defaultAction, title: presentationData.strings.Chat_Giveaway_Info_ViewPrize, action: {
|
||||||
|
dismissImpl?()
|
||||||
|
}), 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()
|
||||||
|
}
|
||||||
|
return alertController
|
||||||
|
}
|
||||||
|
|
||||||
private final class GiveawayInfoAlertContentNode: AlertContentNode {
|
private final class GiveawayInfoAlertContentNode: AlertContentNode {
|
||||||
private let title: String
|
private let title: String
|
||||||
@ -229,7 +378,7 @@ private final class GiveawayInfoAlertContentNode: AlertContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func giveawayInfoAlertController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, title: String, text: String, warning: String?, actions: [TextAlertAction]) -> AlertController {
|
private func giveawayInfoAlertController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, title: String, text: String, warning: String?, actions: [TextAlertAction]) -> AlertController {
|
||||||
let presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = updatedPresentationData?.initial ?? context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
|
||||||
let contentNode = GiveawayInfoAlertContentNode(theme: AlertControllerTheme(presentationData: presentationData), ptheme: presentationData.theme, title: title, text: text, warning: warning, actions: actions)
|
let contentNode = GiveawayInfoAlertContentNode(theme: AlertControllerTheme(presentationData: presentationData), ptheme: presentationData.theme, title: title, text: text, warning: warning, actions: actions)
|
@ -186,8 +186,8 @@ public func PremiumBoostScreen(
|
|||||||
let controller = textAlertController(
|
let controller = textAlertController(
|
||||||
sharedContext: context.sharedContext,
|
sharedContext: context.sharedContext,
|
||||||
updatedPresentationData: nil,
|
updatedPresentationData: nil,
|
||||||
title: "More Boosts Needed",
|
title: presentationData.strings.ChannelBoost_MoreBoosts_Title,
|
||||||
text: "To boost **\(peer.compactDisplayTitle)** again, gift **Telegram Premium** to a friend and get **\(premiumConfiguration.boostsPerGiftCount)** additional boosts.",
|
text: presentationData.strings.ChannelBoost_MoreBoosts_Text(peer.compactDisplayTitle, "\(premiumConfiguration.boostsPerGiftCount)").string,
|
||||||
actions: [
|
actions: [
|
||||||
TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})
|
TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})
|
||||||
],
|
],
|
||||||
|
@ -22,6 +22,7 @@ import TelegramStringFormatting
|
|||||||
import UndoUI
|
import UndoUI
|
||||||
import InvisibleInkDustNode
|
import InvisibleInkDustNode
|
||||||
|
|
||||||
|
//TODO:localize
|
||||||
private final class PremiumGiftCodeSheetContent: CombinedComponent {
|
private final class PremiumGiftCodeSheetContent: CombinedComponent {
|
||||||
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
||||||
|
|
||||||
|
@ -19,8 +19,6 @@ import PeerListItemComponent
|
|||||||
import TelegramStringFormatting
|
import TelegramStringFormatting
|
||||||
import AvatarNode
|
import AvatarNode
|
||||||
|
|
||||||
//TODO:localize
|
|
||||||
|
|
||||||
private final class ReplaceBoostScreenComponent: CombinedComponent {
|
private final class ReplaceBoostScreenComponent: CombinedComponent {
|
||||||
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
||||||
|
|
||||||
@ -172,7 +170,7 @@ private final class ReplaceBoostScreenComponent: CombinedComponent {
|
|||||||
if channelName.count > 48 {
|
if channelName.count > 48 {
|
||||||
channelName = "\(channelName.prefix(48))..."
|
channelName = "\(channelName.prefix(48))..."
|
||||||
}
|
}
|
||||||
let descriptionString = "To boost **\(channelName)**, reassign a previous boost or gift **Telegram Premium** to a friend to get **\(premiumConfiguration.boostsPerGiftCount)** additional boosts."
|
let descriptionString = strings.ReassignBoost_Description(channelName, "\(premiumConfiguration.boostsPerGiftCount)").string
|
||||||
|
|
||||||
let description = description.update(
|
let description = description.update(
|
||||||
component: MultilineTextComponent(
|
component: MultilineTextComponent(
|
||||||
@ -204,11 +202,11 @@ private final class ReplaceBoostScreenComponent: CombinedComponent {
|
|||||||
if let cooldownUntil = boost.cooldownUntil, cooldownUntil > state.currentTime {
|
if let cooldownUntil = boost.cooldownUntil, cooldownUntil > state.currentTime {
|
||||||
let duration = cooldownUntil - state.currentTime
|
let duration = cooldownUntil - state.currentTime
|
||||||
let durationValue = stringForDuration(duration, position: nil)
|
let durationValue = stringForDuration(duration, position: nil)
|
||||||
subtitle = "Available in \(durationValue)"
|
subtitle = strings.ReassignBoost_AvailableIn(durationValue).string
|
||||||
isEnabled = false
|
isEnabled = false
|
||||||
} else {
|
} else {
|
||||||
let expiresValue = stringForDate(timestamp: boost.expires, strings: strings)
|
let expiresValue = stringForDate(timestamp: boost.expires, strings: strings)
|
||||||
subtitle = "Boost expires on \(expiresValue)"
|
subtitle = strings.ReassignBoost_ExpiresOn(expiresValue).string
|
||||||
}
|
}
|
||||||
|
|
||||||
let accountContext = context.component.context
|
let accountContext = context.component.context
|
||||||
@ -245,7 +243,8 @@ private final class ReplaceBoostScreenComponent: CombinedComponent {
|
|||||||
selectedSlotsUpdated(state.selectedSlots)
|
selectedSlotsUpdated(state.selectedSlots)
|
||||||
} else {
|
} else {
|
||||||
let presentationData = accountContext.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = accountContext.sharedContext.currentPresentationData.with { $0 }
|
||||||
let undoController = UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: "Wait until the boost is available or get **3** more boosts by gifting a **Telegram Premium** subscription.", timeout: nil, customUndoText: nil), elevatedLayout: false, position: .top, action: { _ in return true })
|
|
||||||
|
let undoController = UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: strings.ReassignBoost_WaitForCooldown("\(premiumConfiguration.boostsPerGiftCount)").string, timeout: nil, customUndoText: nil), elevatedLayout: false, position: .top, action: { _ in return true })
|
||||||
presentController(undoController)
|
presentController(undoController)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -559,7 +558,7 @@ public class ReplaceBoostScreen: ViewController {
|
|||||||
let footerInsets = UIEdgeInsets(top: 0.0, left: layout.safeInsets.left, bottom: layout.intrinsicInsets.bottom, right: layout.safeInsets.right)
|
let footerInsets = UIEdgeInsets(top: 0.0, left: layout.safeInsets.left, bottom: layout.intrinsicInsets.bottom, right: layout.safeInsets.right)
|
||||||
|
|
||||||
transition.setFrame(view: self.footerView, frame: CGRect(origin: CGPoint(x: 0.0, y: -topInset), size: layout.size))
|
transition.setFrame(view: self.footerView, frame: CGRect(origin: CGPoint(x: 0.0, y: -topInset), size: layout.size))
|
||||||
self.footerHeight = self.footerView.update(size: layout.size, insets: footerInsets, theme: self.presentationData.theme, count: Int32(self.selectedSlots.count))
|
self.footerHeight = self.footerView.update(size: layout.size, insets: footerInsets, theme: self.presentationData.theme, strings: self.presentationData.strings, count: Int32(self.selectedSlots.count))
|
||||||
|
|
||||||
if !hadLayout {
|
if !hadLayout {
|
||||||
self.updateFooterAlpha()
|
self.updateFooterAlpha()
|
||||||
@ -838,9 +837,9 @@ public class ReplaceBoostScreen: ViewController {
|
|||||||
presentControllerImpl?(c)
|
presentControllerImpl?(c)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
self.title = "Reassign Boosts"
|
self.title = presentationData.strings.ReassignBoost_Title
|
||||||
|
|
||||||
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: presentationData.strings.Common_Close, style: .plain, target: self, action: #selector(self.cancelPressed))
|
self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: presentationData.strings.Common_Cancel, style: .plain, target: self, action: #selector(self.cancelPressed))
|
||||||
|
|
||||||
self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
||||||
|
|
||||||
@ -984,10 +983,10 @@ private final class FooterView: UIView {
|
|||||||
|
|
||||||
fileprivate var inProgress = false
|
fileprivate var inProgress = false
|
||||||
|
|
||||||
private var currentLayout: (CGSize, UIEdgeInsets, PresentationTheme, Int32)?
|
private var currentLayout: (CGSize, UIEdgeInsets, PresentationTheme, PresentationStrings, Int32)?
|
||||||
func update(size: CGSize, insets: UIEdgeInsets, theme: PresentationTheme, count: Int32) -> CGFloat {
|
func update(size: CGSize, insets: UIEdgeInsets, theme: PresentationTheme, strings: PresentationStrings, count: Int32) -> CGFloat {
|
||||||
let hadLayout = self.currentLayout != nil
|
let hadLayout = self.currentLayout != nil
|
||||||
self.currentLayout = (size, insets, theme, count)
|
self.currentLayout = (size, insets, theme, strings, count)
|
||||||
|
|
||||||
self.backgroundNode.updateColor(color: theme.rootController.tabBar.backgroundColor, transition: .immediate)
|
self.backgroundNode.updateColor(color: theme.rootController.tabBar.backgroundColor, transition: .immediate)
|
||||||
self.separatorView.backgroundColor = theme.rootController.tabBar.separatorColor
|
self.separatorView.backgroundColor = theme.rootController.tabBar.separatorColor
|
||||||
@ -1019,7 +1018,7 @@ private final class FooterView: UIView {
|
|||||||
content: AnyComponentWithIdentity(
|
content: AnyComponentWithIdentity(
|
||||||
id: AnyHashable(0),
|
id: AnyHashable(0),
|
||||||
component: AnyComponent(ButtonTextContentComponent(
|
component: AnyComponent(ButtonTextContentComponent(
|
||||||
text: "Reassign Boosts",
|
text: strings.ReassignBoost_ReassignBoosts,
|
||||||
badge: Int(count),
|
badge: Int(count),
|
||||||
textColor: theme.list.itemCheckColors.foregroundColor,
|
textColor: theme.list.itemCheckColors.foregroundColor,
|
||||||
badgeBackground: theme.list.itemCheckColors.foregroundColor,
|
badgeBackground: theme.list.itemCheckColors.foregroundColor,
|
||||||
@ -1036,8 +1035,8 @@ private final class FooterView: UIView {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
self.inProgress = true
|
self.inProgress = true
|
||||||
if let (size, insets, theme, count) = self.currentLayout {
|
if let (size, insets, theme, strings, count) = self.currentLayout {
|
||||||
let _ = self.update(size: size, insets: insets, theme: theme, count: count)
|
let _ = self.update(size: size, insets: insets, theme: theme, strings: strings, count: count)
|
||||||
}
|
}
|
||||||
self.action()
|
self.action()
|
||||||
}
|
}
|
||||||
|
@ -554,15 +554,15 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||||||
let expiresString: String
|
let expiresString: String
|
||||||
|
|
||||||
let durationMonths = Int32(round(Float(boost.expires - boost.date) / (86400.0 * 30.0)))
|
let durationMonths = Int32(round(Float(boost.expires - boost.date) / (86400.0 * 30.0)))
|
||||||
let durationString = "\(durationMonths)m"
|
let durationString = presentationData.strings.Stats_Boosts_ShortMonth("\(durationMonths)").string
|
||||||
|
|
||||||
let title: String
|
let title: String
|
||||||
let icon: GiftOptionItem.Icon
|
let icon: GiftOptionItem.Icon
|
||||||
var label: String?
|
var label: String?
|
||||||
if boost.flags.contains(.isGiveaway) {
|
if boost.flags.contains(.isGiveaway) {
|
||||||
label = "🏆 Giveaway"
|
label = "🏆 \(presentationData.strings.Stats_Boosts_Giveaway)"
|
||||||
} else if boost.flags.contains(.isGift) {
|
} else if boost.flags.contains(.isGift) {
|
||||||
label = "🎁 Gift"
|
label = "🎁 \(presentationData.strings.Stats_Boosts_Gift)"
|
||||||
}
|
}
|
||||||
|
|
||||||
let color: GiftOptionItem.Icon.Color
|
let color: GiftOptionItem.Icon.Color
|
||||||
@ -575,7 +575,7 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if boost.flags.contains(.isUnclaimed) {
|
if boost.flags.contains(.isUnclaimed) {
|
||||||
title = "Unclaimed"
|
title = presentationData.strings.Stats_Boosts_Unclaimed
|
||||||
icon = .image(color: color, name: "Premium/Unclaimed")
|
icon = .image(color: color, name: "Premium/Unclaimed")
|
||||||
expiresString = "\(durationString) • \(expiresValue)"
|
expiresString = "\(durationString) • \(expiresValue)"
|
||||||
} else if let peer = boost.peer {
|
} else if let peer = boost.peer {
|
||||||
@ -588,10 +588,10 @@ private enum StatsEntry: ItemListNodeEntry {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if boost.flags.contains(.isUnclaimed) {
|
if boost.flags.contains(.isUnclaimed) {
|
||||||
title = "Unclaimed"
|
title = presentationData.strings.Stats_Boosts_Unclaimed
|
||||||
icon = .image(color: color, name: "Premium/Unclaimed")
|
icon = .image(color: color, name: "Premium/Unclaimed")
|
||||||
} else if boost.flags.contains(.isGiveaway) {
|
} else if boost.flags.contains(.isGiveaway) {
|
||||||
title = "To be distributed"
|
title = presentationData.strings.Stats_Boosts_ToBeDistributed
|
||||||
icon = .image(color: color, name: "Premium/ToBeDistributed")
|
icon = .image(color: color, name: "Premium/ToBeDistributed")
|
||||||
} else {
|
} else {
|
||||||
title = "Unknown"
|
title = "Unknown"
|
||||||
@ -774,15 +774,14 @@ private func channelStatsControllerEntries(state: ChannelStatsControllerState, p
|
|||||||
entries.append(.boostOverviewTitle(presentationData.theme, presentationData.strings.Stats_Boosts_OverviewHeader))
|
entries.append(.boostOverviewTitle(presentationData.theme, presentationData.strings.Stats_Boosts_OverviewHeader))
|
||||||
entries.append(.boostOverview(presentationData.theme, boostData))
|
entries.append(.boostOverview(presentationData.theme, boostData))
|
||||||
|
|
||||||
//TODO:localize
|
|
||||||
if !boostData.prepaidGiveaways.isEmpty {
|
if !boostData.prepaidGiveaways.isEmpty {
|
||||||
entries.append(.boostPrepaidTitle(presentationData.theme, "PREPAID GIVEAWAYS"))
|
entries.append(.boostPrepaidTitle(presentationData.theme, presentationData.strings.Stats_Boosts_PrepaidGiveawaysTitle))
|
||||||
var i: Int32 = 0
|
var i: Int32 = 0
|
||||||
for giveaway in boostData.prepaidGiveaways {
|
for giveaway in boostData.prepaidGiveaways {
|
||||||
entries.append(.boostPrepaid(i, presentationData.theme, "\(giveaway.quantity) Telegram Premium", "\(giveaway.months)-month subscriptions", giveaway))
|
entries.append(.boostPrepaid(i, presentationData.theme, presentationData.strings.Stats_Boosts_PrepaidGiveawayCount(giveaway.quantity), presentationData.strings.Stats_Boosts_PrepaidGiveawayMonths("\(giveaway.months)").string, giveaway))
|
||||||
i += 1
|
i += 1
|
||||||
}
|
}
|
||||||
entries.append(.boostPrepaidInfo(presentationData.theme, "Select a giveaway you already paid for to set it up."))
|
entries.append(.boostPrepaidInfo(presentationData.theme, presentationData.strings.Stats_Boosts_PrepaidGiveawaysInfo))
|
||||||
}
|
}
|
||||||
|
|
||||||
let boostersTitle: String
|
let boostersTitle: String
|
||||||
@ -813,7 +812,7 @@ private func channelStatsControllerEntries(state: ChannelStatsControllerState, p
|
|||||||
}
|
}
|
||||||
|
|
||||||
if boostsCount > 0 && giftsCount > 0 && boostsCount != giftsCount {
|
if boostsCount > 0 && giftsCount > 0 && boostsCount != giftsCount {
|
||||||
entries.append(.boosterTabs(presentationData.theme, "\(boostsCount) Boosts", "\(giftsCount) Gifts", state.giftsSelected))
|
entries.append(.boosterTabs(presentationData.theme, presentationData.strings.Stats_Boosts_TabBoosts(boostsCount), presentationData.strings.Stats_Boosts_TabGifts(giftsCount), state.giftsSelected))
|
||||||
}
|
}
|
||||||
|
|
||||||
let selectedState: ChannelBoostersContext.State?
|
let selectedState: ChannelBoostersContext.State?
|
||||||
@ -853,8 +852,8 @@ private func channelStatsControllerEntries(state: ChannelStatsControllerState, p
|
|||||||
entries.append(.boostLinkInfo(presentationData.theme, presentationData.strings.Stats_Boosts_LinkInfo))
|
entries.append(.boostLinkInfo(presentationData.theme, presentationData.strings.Stats_Boosts_LinkInfo))
|
||||||
|
|
||||||
if giveawayAvailable {
|
if giveawayAvailable {
|
||||||
entries.append(.gifts(presentationData.theme, "Get Boosts via Gifts"))
|
entries.append(.gifts(presentationData.theme, presentationData.strings.Stats_Boosts_GetBoosts))
|
||||||
entries.append(.giftsInfo(presentationData.theme, "Get more boosts for your channel by gifting Premium to your subscribers."))
|
entries.append(.giftsInfo(presentationData.theme, presentationData.strings.Stats_Boosts_GetBoostsInfo))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,7 +189,6 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO:localize
|
|
||||||
override public func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, unboundSize: CGSize?, maxWidth: CGFloat, layout: (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
override public func asyncLayoutContent() -> (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize, _ avatarInset: CGFloat) -> (ChatMessageBubbleContentProperties, unboundSize: CGSize?, maxWidth: CGFloat, layout: (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool, ListViewItemApply?) -> Void))) {
|
||||||
let makeLabelLayout = TextNode.asyncLayout(self.labelNode)
|
let makeLabelLayout = TextNode.asyncLayout(self.labelNode)
|
||||||
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||||
@ -226,24 +225,24 @@ public class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
textSpacing += 13.0
|
textSpacing += 13.0
|
||||||
|
|
||||||
if unclaimed {
|
if unclaimed {
|
||||||
title = "Unclaimed Prize"
|
title = item.presentationData.strings.Notification_PremiumPrize_Unclaimed
|
||||||
} else {
|
} else {
|
||||||
title = "Congratulations!"
|
title = item.presentationData.strings.Notification_PremiumPrize_Title
|
||||||
}
|
}
|
||||||
var peerName = ""
|
var peerName = ""
|
||||||
if let channelId, let channel = item.message.peers[channelId] {
|
if let channelId, let channel = item.message.peers[channelId] {
|
||||||
peerName = EnginePeer(channel).compactDisplayTitle
|
peerName = EnginePeer(channel).compactDisplayTitle
|
||||||
}
|
}
|
||||||
if unclaimed {
|
if unclaimed {
|
||||||
text = "You have an unclaimed prize from a giveaway by **\(peerName)**.\n\nThis prize is a **Telegram Premium** subscription for **\(monthsValue)** months."
|
text = item.presentationData.strings.Notification_PremiumPrize_UnclaimedText(peerName, item.presentationData.strings.Notification_PremiumPrize_Months(monthsValue)).string
|
||||||
} else if fromGiveaway {
|
} else if fromGiveaway {
|
||||||
text = "You won a prize in a giveaway organized by **\(peerName)**.\n\nYour prize is a **Telegram Premium** subscription for **\(monthsValue)** months."
|
text = item.presentationData.strings.Notification_PremiumPrize_GiveawayText(peerName, item.presentationData.strings.Notification_PremiumPrize_Months(monthsValue)).string
|
||||||
} else {
|
} else {
|
||||||
text = "You've received a gift from **\(peerName)**.\n\nYour gift is a **Telegram Premium** subscription for **\(monthsValue)** months."
|
text = item.presentationData.strings.Notification_PremiumPrize_GiftText(peerName, item.presentationData.strings.Notification_PremiumPrize_Months(monthsValue)).string
|
||||||
}
|
}
|
||||||
|
|
||||||
months = monthsValue
|
months = monthsValue
|
||||||
buttonTitle = "Open Gift Link"
|
buttonTitle = item.presentationData.strings.Notification_PremiumPrize_View
|
||||||
hasServiceMessage = false
|
hasServiceMessage = false
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
|
@ -25,7 +25,6 @@ import TelegramUIPreferences
|
|||||||
import UndoUI
|
import UndoUI
|
||||||
import TelegramStringFormatting
|
import TelegramStringFormatting
|
||||||
|
|
||||||
//TODO:localize
|
|
||||||
final class ShareWithPeersScreenComponent: Component {
|
final class ShareWithPeersScreenComponent: Component {
|
||||||
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
typealias EnvironmentType = ViewControllerComponentContainer.Environment
|
||||||
|
|
||||||
@ -941,9 +940,9 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
sectionTitle = environment.strings.Story_Privacy_WhoCanViewHeader
|
sectionTitle = environment.strings.Story_Privacy_WhoCanViewHeader
|
||||||
} else if section.id == 1 {
|
} else if section.id == 1 {
|
||||||
if case .members = component.stateContext.subject {
|
if case .members = component.stateContext.subject {
|
||||||
sectionTitle = "SUBSCRIBERS"
|
sectionTitle = environment.strings.BoostGift_Subscribers_SectionTitle
|
||||||
} else if case .channels = component.stateContext.subject {
|
} else if case .channels = component.stateContext.subject {
|
||||||
sectionTitle = "CHANNELS"
|
sectionTitle = environment.strings.BoostGift_Channels_SectionTitle
|
||||||
} else {
|
} else {
|
||||||
sectionTitle = environment.strings.Story_Privacy_ContactsHeader
|
sectionTitle = environment.strings.Story_Privacy_ContactsHeader
|
||||||
}
|
}
|
||||||
@ -1390,7 +1389,7 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
} else {
|
} else {
|
||||||
if case .members = component.stateContext.subject {
|
if case .members = component.stateContext.subject {
|
||||||
if let invitedAt = stateValue.invitedAt[peer.id] {
|
if let invitedAt = stateValue.invitedAt[peer.id] {
|
||||||
subtitle = "joined \(stringForMediumDate(timestamp: invitedAt, strings: environment.strings, dateTimeFormat: environment.dateTimeFormat))"
|
subtitle = environment.strings.BoostGift_Subscribers_Joined(stringForMediumDate(timestamp: invitedAt, strings: environment.strings, dateTimeFormat: environment.dateTimeFormat)).string
|
||||||
} else {
|
} else {
|
||||||
subtitle = nil
|
subtitle = nil
|
||||||
}
|
}
|
||||||
@ -1445,7 +1444,7 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
self.hapticFeedback.error()
|
self.hapticFeedback.error()
|
||||||
|
|
||||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
controller.present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: "You can select maximum \(component.context.userLimits.maxGiveawayChannelsCount) channels.", timeout: nil, customUndoText: nil), elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in return false }), in: .current)
|
controller.present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: environment.strings.BoostGift_Channels_MaximumReached("\(component.context.userLimits.maxGiveawayChannelsCount)").string, timeout: nil, customUndoText: nil), elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in return false }), in: .current)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if case .channels = component.stateContext.subject {
|
if case .channels = component.stateContext.subject {
|
||||||
@ -1453,11 +1452,11 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
let alertController = textAlertController(
|
let alertController = textAlertController(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
forceTheme: environment.theme,
|
forceTheme: environment.theme,
|
||||||
title: "Channel is Private",
|
title: environment.strings.BoostGift_Channels_PrivateChannel_Title,
|
||||||
text: "Are you sure you want to add a private channel? Users won't be able to join it without an invite link.",
|
text: environment.strings.BoostGift_Channels_PrivateChannel_Text,
|
||||||
actions: [
|
actions: [
|
||||||
TextAlertAction(type: .genericAction, title: environment.strings.Common_Cancel, action: {}),
|
TextAlertAction(type: .genericAction, title: environment.strings.Common_Cancel, action: {}),
|
||||||
TextAlertAction(type: .defaultAction, title: "Add", action: {
|
TextAlertAction(type: .defaultAction, title: environment.strings.BoostGift_Channels_PrivateChannel_Add, action: {
|
||||||
togglePeer()
|
togglePeer()
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
@ -1475,7 +1474,7 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
self.hapticFeedback.error()
|
self.hapticFeedback.error()
|
||||||
|
|
||||||
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
let presentationData = component.context.sharedContext.currentPresentationData.with { $0 }
|
||||||
controller.present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: "You can select maximum 10 subscribers.", timeout: nil, customUndoText: nil), elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in return false }), in: .current)
|
controller.present(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: environment.strings.BoostGift_Subscribers_MaximumReached("\(10)").string, timeout: nil, customUndoText: nil), elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { _ in return false }), in: .current)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
togglePeer()
|
togglePeer()
|
||||||
@ -2018,9 +2017,9 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
let placeholder: String
|
let placeholder: String
|
||||||
switch component.stateContext.subject {
|
switch component.stateContext.subject {
|
||||||
case .members:
|
case .members:
|
||||||
placeholder = "Search Subscribers"
|
placeholder = environment.strings.BoostGift_Subscribers_Search
|
||||||
case .channels:
|
case .channels:
|
||||||
placeholder = "Search Channels"
|
placeholder = environment.strings.BoostGift_Channels_Search
|
||||||
case .chats:
|
case .chats:
|
||||||
placeholder = environment.strings.Story_Privacy_SearchChats
|
placeholder = environment.strings.Story_Privacy_SearchChats
|
||||||
default:
|
default:
|
||||||
@ -2367,13 +2366,13 @@ final class ShareWithPeersScreenComponent: Component {
|
|||||||
case .contactsSearch:
|
case .contactsSearch:
|
||||||
title = ""
|
title = ""
|
||||||
case .members:
|
case .members:
|
||||||
title = "Gift Premium"
|
title = environment.strings.BoostGift_Subscribers_Title
|
||||||
actionButtonTitle = "Save Recipients"
|
subtitle = environment.strings.BoostGift_Subscribers_Subtitle("\(10)").string
|
||||||
subtitle = "select up to 10 subscribers"
|
actionButtonTitle = environment.strings.BoostGift_Subscribers_Save
|
||||||
case .channels:
|
case .channels:
|
||||||
title = "Add Channels"
|
title = environment.strings.BoostGift_Channels_Title
|
||||||
actionButtonTitle = "Save Channels"
|
subtitle = environment.strings.BoostGift_Channels_Subtitle("\(component.context.userLimits.maxGiveawayChannelsCount)").string
|
||||||
subtitle = "select up to \(component.context.userLimits.maxGiveawayChannelsCount) channels"
|
actionButtonTitle = environment.strings.BoostGift_Channels_Save
|
||||||
}
|
}
|
||||||
|
|
||||||
let titleComponent: AnyComponent<Empty>
|
let titleComponent: AnyComponent<Empty>
|
||||||
|
@ -180,8 +180,6 @@ final class MediaNavigationStripComponent: Component {
|
|||||||
let itemHeight: CGFloat = 2.0
|
let itemHeight: CGFloat = 2.0
|
||||||
let minItemWidth: CGFloat = 2.0
|
let minItemWidth: CGFloat = 2.0
|
||||||
|
|
||||||
var size = CGSize(width: availableSize.width, height: itemHeight)
|
|
||||||
|
|
||||||
var didSetCompletion = false
|
var didSetCompletion = false
|
||||||
|
|
||||||
var validIndices: [Int] = []
|
var validIndices: [Int] = []
|
||||||
@ -223,7 +221,6 @@ final class MediaNavigationStripComponent: Component {
|
|||||||
var itemFrame = CGRect(origin: CGPoint(x: -globalOffset + CGFloat(i) * (itemWidth + spacing), y: 0.0), size: CGSize(width: itemWidth, height: itemHeight))
|
var itemFrame = CGRect(origin: CGPoint(x: -globalOffset + CGFloat(i) * (itemWidth + spacing), y: 0.0), size: CGSize(width: itemWidth, height: itemHeight))
|
||||||
if component.isSeeking {
|
if component.isSeeking {
|
||||||
itemFrame = CGRect(origin: .zero, size: CGSize(width: availableSize.width, height: 6.0))
|
itemFrame = CGRect(origin: .zero, size: CGSize(width: availableSize.width, height: 6.0))
|
||||||
size.height = itemFrame.height
|
|
||||||
}
|
}
|
||||||
if itemFrame.maxX < 0.0 || itemFrame.minX >= availableSize.width {
|
if itemFrame.maxX < 0.0 || itemFrame.minX >= availableSize.width {
|
||||||
continue
|
continue
|
||||||
|
@ -546,6 +546,14 @@ private final class StoryContainerScreenComponent: Component {
|
|||||||
}
|
}
|
||||||
self.initialSeekTimestamp = nil
|
self.initialSeekTimestamp = nil
|
||||||
self.previousSeekTime = nil
|
self.previousSeekTime = nil
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
guard let visibleItemView = itemSetComponentView.visibleItems[slice.item.storyItem.id]?.view.view as? StoryItemContentComponent.View else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
visibleItemView.seekEnded()
|
||||||
}
|
}
|
||||||
longPressRecognizer.shouldBegin = { [weak self] touch in
|
longPressRecognizer.shouldBegin = { [weak self] touch in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
|
@ -95,12 +95,13 @@ final class StoryInteractionGuideComponent: Component {
|
|||||||
self.component = component
|
self.component = component
|
||||||
self.state = state
|
self.state = state
|
||||||
|
|
||||||
|
let strings = component.strings
|
||||||
|
|
||||||
let sideInset: CGFloat = 48.0
|
let sideInset: CGFloat = 48.0
|
||||||
|
|
||||||
//TODO:localize
|
|
||||||
let titleSize = self.titleLabel.update(
|
let titleSize = self.titleLabel.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: "Watching Stories", font: Font.semibold(20.0), textColor: .white, paragraphAlignment: .center)))),
|
component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: strings.Story_Guide_Title, font: Font.semibold(20.0), textColor: .white, paragraphAlignment: .center)))),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: availableSize.height)
|
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: availableSize.height)
|
||||||
)
|
)
|
||||||
@ -114,7 +115,7 @@ final class StoryInteractionGuideComponent: Component {
|
|||||||
|
|
||||||
let textSize = self.descriptionLabel.update(
|
let textSize = self.descriptionLabel.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(BalancedTextComponent(text: .plain(NSAttributedString(string: "You can use these gestures to control playback.", font: Font.regular(15.0), textColor: UIColor(rgb: 0xffffff, alpha: 0.6), paragraphAlignment: .center)), maximumNumberOfLines: 0, lineSpacing: 0.2)),
|
component: AnyComponent(BalancedTextComponent(text: .plain(NSAttributedString(string: strings.Story_Guide_Description, font: Font.regular(15.0), textColor: UIColor(rgb: 0xffffff, alpha: 0.6), paragraphAlignment: .center)), maximumNumberOfLines: 0, lineSpacing: 0.2)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: availableSize.height)
|
containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: availableSize.height)
|
||||||
)
|
)
|
||||||
@ -132,8 +133,8 @@ final class StoryInteractionGuideComponent: Component {
|
|||||||
component: AnyComponent(
|
component: AnyComponent(
|
||||||
GuideItemComponent(
|
GuideItemComponent(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
title: "Go forward",
|
title: strings.Story_Guide_ForwardTitle,
|
||||||
text: "Tap the screen",
|
text: strings.Story_Guide_ForwardDescription,
|
||||||
animationName: "story_forward",
|
animationName: "story_forward",
|
||||||
isPlaying: self.currentIndex == 0,
|
isPlaying: self.currentIndex == 0,
|
||||||
playbackCompleted: { [weak self] in
|
playbackCompleted: { [weak self] in
|
||||||
@ -151,8 +152,8 @@ final class StoryInteractionGuideComponent: Component {
|
|||||||
component: AnyComponent(
|
component: AnyComponent(
|
||||||
GuideItemComponent(
|
GuideItemComponent(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
title: "Pause and Seek",
|
title: strings.Story_Guide_PauseTitle,
|
||||||
text: "Hold and move sideways",
|
text: strings.Story_Guide_PauseDescription,
|
||||||
animationName: "story_pause",
|
animationName: "story_pause",
|
||||||
isPlaying: self.currentIndex == 1,
|
isPlaying: self.currentIndex == 1,
|
||||||
playbackCompleted: { [weak self] in
|
playbackCompleted: { [weak self] in
|
||||||
@ -170,8 +171,8 @@ final class StoryInteractionGuideComponent: Component {
|
|||||||
component: AnyComponent(
|
component: AnyComponent(
|
||||||
GuideItemComponent(
|
GuideItemComponent(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
title: "Go back",
|
title: strings.Story_Guide_BackTitle,
|
||||||
text: "Tap the left edge",
|
text: strings.Story_Guide_BackDescription,
|
||||||
animationName: "story_back",
|
animationName: "story_back",
|
||||||
isPlaying: self.currentIndex == 2,
|
isPlaying: self.currentIndex == 2,
|
||||||
playbackCompleted: { [weak self] in
|
playbackCompleted: { [weak self] in
|
||||||
@ -189,8 +190,8 @@ final class StoryInteractionGuideComponent: Component {
|
|||||||
component: AnyComponent(
|
component: AnyComponent(
|
||||||
GuideItemComponent(
|
GuideItemComponent(
|
||||||
context: component.context,
|
context: component.context,
|
||||||
title: "Move between stories",
|
title: strings.Story_Guide_MoveTitle,
|
||||||
text: "Swipe left or right",
|
text: strings.Story_Guide_MoveDescription,
|
||||||
animationName: "story_move",
|
animationName: "story_move",
|
||||||
isPlaying: self.currentIndex == 3,
|
isPlaying: self.currentIndex == 3,
|
||||||
playbackCompleted: { [weak self] in
|
playbackCompleted: { [weak self] in
|
||||||
@ -222,7 +223,7 @@ final class StoryInteractionGuideComponent: Component {
|
|||||||
let buttonSize = self.proceedButton.update(
|
let buttonSize = self.proceedButton.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(Button(
|
component: AnyComponent(Button(
|
||||||
content: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: "Tap to keep watching", font: Font.semibold(17.0), textColor: .white, paragraphAlignment: .center)))),
|
content: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: strings.Story_Guide_Proceed, font: Font.semibold(17.0), textColor: .white, paragraphAlignment: .center)))),
|
||||||
action: { [weak self] in
|
action: { [weak self] in
|
||||||
self?.handleTap()
|
self?.handleTap()
|
||||||
}
|
}
|
||||||
|
@ -277,7 +277,9 @@ final class StoryItemContentComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.videoPlaybackStatus = status
|
self.videoPlaybackStatus = status
|
||||||
self.updateVideoPlaybackProgress()
|
if !self.isSeeking {
|
||||||
|
self.updateVideoPlaybackProgress()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -360,7 +362,9 @@ final class StoryItemContentComponent: Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if case .file = self.currentMessageMedia {
|
if case .file = self.currentMessageMedia {
|
||||||
self.updateVideoPlaybackProgress()
|
if !self.isSeeking {
|
||||||
|
self.updateVideoPlaybackProgress()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if !self.markedAsSeen {
|
if !self.markedAsSeen {
|
||||||
self.markedAsSeen = true
|
self.markedAsSeen = true
|
||||||
@ -536,6 +540,7 @@ final class StoryItemContentComponent: Component {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var isSeeking = false
|
||||||
func seekTo(_ timestamp: Double, apply: Bool) {
|
func seekTo(_ timestamp: Double, apply: Bool) {
|
||||||
guard let videoNode = self.videoNode else {
|
guard let videoNode = self.videoNode else {
|
||||||
return
|
return
|
||||||
@ -543,8 +548,13 @@ final class StoryItemContentComponent: Component {
|
|||||||
if apply {
|
if apply {
|
||||||
videoNode.seek(timestamp)
|
videoNode.seek(timestamp)
|
||||||
}
|
}
|
||||||
|
self.isSeeking = true
|
||||||
self.updateVideoPlaybackProgress(timestamp)
|
self.updateVideoPlaybackProgress(timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func seekEnded() {
|
||||||
|
self.isSeeking = false
|
||||||
|
}
|
||||||
|
|
||||||
func update(component: StoryItemContentComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<StoryContentItem.Environment>, transition: Transition) -> CGSize {
|
func update(component: StoryItemContentComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment<StoryContentItem.Environment>, transition: Transition) -> CGSize {
|
||||||
let previousItem = self.component?.item
|
let previousItem = self.component?.item
|
||||||
|
@ -4710,7 +4710,7 @@ public final class StoryItemSetContainerComponent: Component {
|
|||||||
|
|
||||||
let seekLabelSize = self.seekLabel.update(
|
let seekLabelSize = self.seekLabel.update(
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(Text(text: "Slide left or right to seek", font: Font.semibold(14.0), color: .white)),
|
component: AnyComponent(Text(text: component.strings.Story_SlideToSeek, font: Font.semibold(14.0), color: .white)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: availableSize
|
containerSize: availableSize
|
||||||
)
|
)
|
||||||
|
@ -4787,17 +4787,16 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
case let .ongoing(_, status):
|
case let .ongoing(_, status):
|
||||||
switch status {
|
switch status {
|
||||||
case .notAllowed:
|
case .notAllowed:
|
||||||
content = .info(title: nil, text: "You can't participate in this giveaway.", timeout: nil, customUndoText: "Learn More")
|
content = .info(title: nil, text: self.presentationData.strings.Chat_Giveaway_Toast_NotAllowed, timeout: nil, customUndoText: self.presentationData.strings.Chat_Giveaway_Toast_LearnMore)
|
||||||
case .participating:
|
case .participating:
|
||||||
content = .succeed(text: "You are participating in this giveaway.", timeout: nil, customUndoText: "Learn More")
|
content = .succeed(text: self.presentationData.strings.Chat_Giveaway_Toast_Participating, timeout: nil, customUndoText: self.presentationData.strings.Chat_Giveaway_Toast_LearnMore)
|
||||||
case .notQualified:
|
case .notQualified:
|
||||||
content = .info(title: nil, text: "You are not qualified for this giveaway yet.", timeout: nil, customUndoText: "Learn More")
|
content = .info(title: nil, text: self.presentationData.strings.Chat_Giveaway_Toast_NotQualified, timeout: nil, customUndoText: self.presentationData.strings.Chat_Giveaway_Toast_LearnMore)
|
||||||
case .almostOver:
|
case .almostOver:
|
||||||
content = .info(title: nil, text: "The giveaway is almost over.", timeout: nil, customUndoText: "Learn More")
|
content = .info(title: nil, text: self.presentationData.strings.Chat_Giveaway_Toast_AlmostOver, timeout: nil, customUndoText: self.presentationData.strings.Chat_Giveaway_Toast_LearnMore)
|
||||||
}
|
}
|
||||||
case let .finished(status, _, _, _, _):
|
case .finished:
|
||||||
let _ = status
|
content = .info(title: nil, text: self.presentationData.strings.Chat_Giveaway_Toast_Ended, timeout: nil, customUndoText: self.presentationData.strings.Chat_Giveaway_Toast_LearnMore)
|
||||||
content = .info(title: nil, text: "The giveaway is ended.", timeout: nil, customUndoText: "Learn More")
|
|
||||||
}
|
}
|
||||||
let controller = UndoOverlayController(presentationData: self.presentationData, content: content, elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { [weak self] action in
|
let controller = UndoOverlayController(presentationData: self.presentationData, content: content, elevatedLayout: false, position: .bottom, animateInAsReplacement: false, action: { [weak self] action in
|
||||||
if case .undo = action, let self {
|
if case .undo = action, let self {
|
||||||
@ -19563,150 +19562,11 @@ 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))
|
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Messages.Message(id: messageId))
|
||||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] message in
|
|> deliverOnMainQueue).startStandalone(next: { [weak self] message in
|
||||||
guard let self, let message, let giveaway = message.media.first(where: { $0 is TelegramMediaGiveaway }) as? TelegramMediaGiveaway else {
|
guard let self, let message else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var peerName = ""
|
if let controller = giveawayInfoController(context: self.context, updatedPresentationData: self.updatedPresentationData, message: message, giveawayInfo: giveawayInfo) {
|
||||||
if let peerId = giveaway.channelPeerIds.first, let peer = message.peers[peerId] {
|
self.present(controller, in: .window(.root))
|
||||||
peerName = EnginePeer(peer).compactDisplayTitle
|
|
||||||
}
|
|
||||||
|
|
||||||
let untilDate = stringForDate(timestamp: giveaway.untilDate, strings: self.presentationData.strings)
|
|
||||||
|
|
||||||
let title: String
|
|
||||||
let text: String
|
|
||||||
var warning: String?
|
|
||||||
|
|
||||||
var dismissImpl: (() -> Void)?
|
|
||||||
|
|
||||||
var actions: [TextAlertAction] = [TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_OK, action: {
|
|
||||||
dismissImpl?()
|
|
||||||
})]
|
|
||||||
|
|
||||||
switch giveawayInfo {
|
|
||||||
case let .ongoing(start, status):
|
|
||||||
let startDate = stringForDate(timestamp: start, strings: self.presentationData.strings)
|
|
||||||
|
|
||||||
title = "About This Giveaway"
|
|
||||||
|
|
||||||
let intro: String
|
|
||||||
if case .almostOver = status {
|
|
||||||
intro = "The giveaway was sponsored by the admins of **\(peerName)**, who acquired **\(giveaway.quantity) Telegram Premium** subscriptions for **\(giveaway.months)** months for its followers."
|
|
||||||
} else {
|
|
||||||
intro = "The giveaway is sponsored by the admins of **\(peerName)**, who acquired **\(giveaway.quantity) Telegram Premium** subscriptions for **\(giveaway.months)** months for its followers."
|
|
||||||
}
|
|
||||||
|
|
||||||
let ending: String
|
|
||||||
if giveaway.flags.contains(.onlyNewSubscribers) {
|
|
||||||
if giveaway.channelPeerIds.count > 1 {
|
|
||||||
ending = "On **\(untilDate)**, Telegram will automatically select **\(giveaway.quantity)** random users that joined **\(peerName)** and **\(giveaway.channelPeerIds.count - 1)** other listed channels after **\(startDate)**."
|
|
||||||
} else {
|
|
||||||
ending = "On **\(untilDate)**, Telegram will automatically select **\(giveaway.quantity)** random users that joined **\(peerName)** after **\(startDate)**."
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if giveaway.channelPeerIds.count > 1 {
|
|
||||||
ending = "On **\(untilDate)**, Telegram will automatically select **\(giveaway.quantity)** random subscribers of **\(peerName)** and **\(giveaway.channelPeerIds.count - 1)** other listed channels."
|
|
||||||
} else {
|
|
||||||
ending = "On **\(untilDate)**, Telegram will automatically select **\(giveaway.quantity)** random subscribers of **\(peerName)**."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var participation: String
|
|
||||||
switch status {
|
|
||||||
case .notQualified:
|
|
||||||
if giveaway.channelPeerIds.count > 1 {
|
|
||||||
participation = "To take part in this giveaway please join the channel **\(peerName)** (**\(giveaway.channelPeerIds.count - 1)** other listed channels) before **\(untilDate)**."
|
|
||||||
} else {
|
|
||||||
participation = "To take part in this giveaway please join the channel **\(peerName)** before **\(untilDate)**."
|
|
||||||
}
|
|
||||||
case let .notAllowed(reason):
|
|
||||||
switch reason {
|
|
||||||
case let .joinedTooEarly(joinedOn):
|
|
||||||
let joinDate = stringForDate(timestamp: joinedOn, strings: self.presentationData.strings)
|
|
||||||
participation = "You are not eligible to participate in this giveaway, because you joined this channel on **\(joinDate)**, which is before the contest started."
|
|
||||||
case let .channelAdmin(adminId):
|
|
||||||
let _ = adminId
|
|
||||||
participation = "You are not eligible to participate in this giveaway, because you are an admin of participating channel (**\(peerName)**)."
|
|
||||||
case let .disallowedCountry(countryCode):
|
|
||||||
let _ = countryCode
|
|
||||||
participation = "You are not eligible to participate in this giveaway, because your country is not included in the terms of the giveaway."
|
|
||||||
}
|
|
||||||
case .participating:
|
|
||||||
if giveaway.channelPeerIds.count > 1 {
|
|
||||||
participation = "You are participating in this giveaway, because you have joined the channel **\(peerName)** (**\(giveaway.channelPeerIds.count - 1)** other listed channels)."
|
|
||||||
} else {
|
|
||||||
participation = "You are participating in this giveaway, because you have joined the channel **\(peerName)**."
|
|
||||||
}
|
|
||||||
case .almostOver:
|
|
||||||
participation = "The giveaway is over, preparing results."
|
|
||||||
}
|
|
||||||
|
|
||||||
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: self.presentationData.strings)
|
|
||||||
let finishDate = stringForDate(timestamp: finish, strings: self.presentationData.strings)
|
|
||||||
title = "Giveaway Ended"
|
|
||||||
|
|
||||||
let intro = "The giveaway was sponsored by the admins of **\(peerName)**, who acquired **\(giveaway.quantity) Telegram Premium** subscriptions for **\(giveaway.months)** months for its followers."
|
|
||||||
|
|
||||||
var ending: String
|
|
||||||
if giveaway.flags.contains(.onlyNewSubscribers) {
|
|
||||||
if giveaway.channelPeerIds.count > 1 {
|
|
||||||
ending = "On **\(finishDate)**, Telegram automatically selected **\(giveaway.quantity)** random users that joined **\(peerName)** and other listed channels after **\(startDate)**."
|
|
||||||
} else {
|
|
||||||
ending = "On **\(finishDate)**, Telegram automatically selected **\(giveaway.quantity)** random users that joined **\(peerName)** after **\(startDate)**."
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if giveaway.channelPeerIds.count > 1 {
|
|
||||||
ending = "On **\(finishDate)**, Telegram automatically selected **\(giveaway.quantity)** random subscribers of **\(peerName)** and other listed channels."
|
|
||||||
} else {
|
|
||||||
ending = "On **\(finishDate)**, Telegram automatically selected **\(giveaway.quantity)** random subscribers of **\(peerName)**."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if activatedCount > 0 {
|
|
||||||
ending += " \(activatedCount) of the winners already used their gift links."
|
|
||||||
}
|
|
||||||
|
|
||||||
var result: String
|
|
||||||
switch status {
|
|
||||||
case .refunded:
|
|
||||||
result = ""
|
|
||||||
warning = "The channel cancelled the prizes by reversing the payment for them."
|
|
||||||
actions = [TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_Close, action: {
|
|
||||||
dismissImpl?()
|
|
||||||
})]
|
|
||||||
case .notWon:
|
|
||||||
result = "\n\nYou didn't win a prize in this giveaway."
|
|
||||||
case let .won(slug):
|
|
||||||
result = "\n\nYou won a prize in this giveaway. 🏆"
|
|
||||||
let _ = slug
|
|
||||||
actions = [TextAlertAction(type: .defaultAction, title: "View My Prize", action: {
|
|
||||||
dismissImpl?()
|
|
||||||
}), TextAlertAction(type: .genericAction, title: self.presentationData.strings.Common_Cancel, action: {
|
|
||||||
dismissImpl?()
|
|
||||||
})]
|
|
||||||
}
|
|
||||||
|
|
||||||
text = "\(intro)\n\n\(ending)\(result)"
|
|
||||||
}
|
|
||||||
|
|
||||||
let alertController = giveawayInfoAlertController(
|
|
||||||
context: self.context,
|
|
||||||
updatedPresentationData: self.updatedPresentationData,
|
|
||||||
title: title,
|
|
||||||
text: text,
|
|
||||||
warning: warning,
|
|
||||||
actions: actions
|
|
||||||
)
|
|
||||||
self.present(alertController, in: .window(.root))
|
|
||||||
|
|
||||||
dismissImpl = { [weak alertController] in
|
|
||||||
alertController?.dismissAnimated()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user