mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 01:10:09 +00:00
Various improvements
This commit is contained in:
parent
b2b1b954f0
commit
097eacdc34
@ -12230,10 +12230,22 @@ Sorry for the inconvenience.";
|
|||||||
"Stars.Intro.Title" = "Telegram Stars";
|
"Stars.Intro.Title" = "Telegram Stars";
|
||||||
"Stars.Intro.Description" = "Buy Stars to unlock content and services in miniapps on Telegram.";
|
"Stars.Intro.Description" = "Buy Stars to unlock content and services in miniapps on Telegram.";
|
||||||
"Stars.Intro.Balance" = "Balance";
|
"Stars.Intro.Balance" = "Balance";
|
||||||
|
"Stars.Intro.YourBalance" = "your balance";
|
||||||
|
"Stars.Intro.Buy" = "Buy More Stars";
|
||||||
"Stars.Intro.AllTransactions" = "All Transactions";
|
"Stars.Intro.AllTransactions" = "All Transactions";
|
||||||
"Stars.Intro.Incoming" = "Incoming";
|
"Stars.Intro.Incoming" = "Incoming";
|
||||||
"Stars.Intro.Outgoing" = "Outgoing";
|
"Stars.Intro.Outgoing" = "Outgoing";
|
||||||
|
|
||||||
|
"Stars.Intro.Transaction.AppleTopUp.Title" = "Stars Top-Up";
|
||||||
|
"Stars.Intro.Transaction.AppleTopUp.Subtitle" = "via App Store";
|
||||||
|
"Stars.Intro.Transaction.GoogleTopUp.Title" = "Stars Top-Up";
|
||||||
|
"Stars.Intro.Transaction.GoogleTopUp.Subtitle" = "via Play Market";
|
||||||
|
"Stars.Intro.Transaction.PremiumBotTopUp.Title" = "Stars Top-Up";
|
||||||
|
"Stars.Intro.Transaction.PremiumBotTopUp.Subtitle" = "via Premium Bot";
|
||||||
|
"Stars.Intro.Transaction.FragmentTopUp.Title" = "Stars Top-Up";
|
||||||
|
"Stars.Intro.Transaction.FragmentTopUp.Subtitle" = "via Fragment";
|
||||||
|
"Stars.Intro.Transaction.Unsupported.Title" = "Unsupported";
|
||||||
|
|
||||||
"Stars.Purchase.GetStars" = "Get Stars";
|
"Stars.Purchase.GetStars" = "Get Stars";
|
||||||
"Stars.Purchase.GetStarsInfo" = "Choose how many Stars you would like to buy.";
|
"Stars.Purchase.GetStarsInfo" = "Choose how many Stars you would like to buy.";
|
||||||
|
|
||||||
@ -12249,6 +12261,7 @@ Sorry for the inconvenience.";
|
|||||||
"Stars.Purchase.Info" = "By proceeding and purchasing Stars, you agree with [Terms and Conditions]().";
|
"Stars.Purchase.Info" = "By proceeding and purchasing Stars, you agree with [Terms and Conditions]().";
|
||||||
"Stars.Purchase.Terms_URL" = "https://telegram.org/tos";
|
"Stars.Purchase.Terms_URL" = "https://telegram.org/tos";
|
||||||
|
|
||||||
|
"Stars.Transaction.Via" = "Via";
|
||||||
"Stars.Transaction.To" = "To";
|
"Stars.Transaction.To" = "To";
|
||||||
"Stars.Transaction.Id" = "Transaction ID";
|
"Stars.Transaction.Id" = "Transaction ID";
|
||||||
"Stars.Transaction.Date" = "Date";
|
"Stars.Transaction.Date" = "Date";
|
||||||
@ -12256,6 +12269,16 @@ Sorry for the inconvenience.";
|
|||||||
"Stars.Transaction.Terms_URL" = "https://telegram.org/tos";
|
"Stars.Transaction.Terms_URL" = "https://telegram.org/tos";
|
||||||
"Stars.Transaction.CopiedId" = "Transaction ID copied to clipboard.";
|
"Stars.Transaction.CopiedId" = "Transaction ID copied to clipboard.";
|
||||||
|
|
||||||
|
"Stars.Transaction.AppleTopUp.Title" = "Stars Top-Up";
|
||||||
|
"Stars.Transaction.AppleTopUp.Subtitle" = "App Store";
|
||||||
|
"Stars.Transaction.GoogleTopUp.Title" = "Stars Top-Up";
|
||||||
|
"Stars.Transaction.GoogleTopUp.Subtitle" = "Play Market";
|
||||||
|
"Stars.Transaction.PremiumBotTopUp.Title" = "Stars Top-Up";
|
||||||
|
"Stars.Transaction.PremiumBotTopUp.Subtitle" = "Premium Bot";
|
||||||
|
"Stars.Transaction.FragmentTopUp.Title" = "Stars Top-Up";
|
||||||
|
"Stars.Transaction.FragmentTopUp.Subtitle" = "Fragment";
|
||||||
|
"Stars.Transaction.Unsupported.Title" = "Unsupported";
|
||||||
|
|
||||||
"Stars.Transfer.Title" = "Confirm Your Purchase";
|
"Stars.Transfer.Title" = "Confirm Your Purchase";
|
||||||
"Stars.Transfer.Info" = "Do you want to buy **%1$@** in **%2$@** for **%3$@**?";
|
"Stars.Transfer.Info" = "Do you want to buy **%1$@** in **%2$@** for **%3$@**?";
|
||||||
"Stars.Transfer.Info.Stars_1" = "%@ Star";
|
"Stars.Transfer.Info.Stars_1" = "%@ Star";
|
||||||
|
|||||||
@ -13,6 +13,7 @@ swift_library(
|
|||||||
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
|
"//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit",
|
||||||
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
|
"//submodules/AsyncDisplayKit:AsyncDisplayKit",
|
||||||
"//submodules/Display:Display",
|
"//submodules/Display:Display",
|
||||||
|
"//submodules/Postbox:Postbox",
|
||||||
"//submodules/TelegramCore:TelegramCore",
|
"//submodules/TelegramCore:TelegramCore",
|
||||||
"//submodules/TelegramPresentationData:TelegramPresentationData",
|
"//submodules/TelegramPresentationData:TelegramPresentationData",
|
||||||
"//submodules/PeerPresenceStatusManager:PeerPresenceStatusManager",
|
"//submodules/PeerPresenceStatusManager:PeerPresenceStatusManager",
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import Foundation
|
|||||||
import UIKit
|
import UIKit
|
||||||
import Display
|
import Display
|
||||||
import AsyncDisplayKit
|
import AsyncDisplayKit
|
||||||
|
import Postbox
|
||||||
import TelegramCore
|
import TelegramCore
|
||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
import TelegramPresentationData
|
import TelegramPresentationData
|
||||||
@ -60,7 +61,7 @@ public enum ItemListAvatarAndNameInfoItemName: Equatable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func composedDisplayTitle(context: AccountContext, strings: PresentationStrings) -> String {
|
public func composedDisplayTitle(context: AccountContext?, strings: PresentationStrings) -> String {
|
||||||
switch self {
|
switch self {
|
||||||
case let .personName(firstName, lastName, phone):
|
case let .personName(firstName, lastName, phone):
|
||||||
if !firstName.isEmpty {
|
if !firstName.isEmpty {
|
||||||
@ -72,7 +73,11 @@ public enum ItemListAvatarAndNameInfoItemName: Equatable {
|
|||||||
} else if !lastName.isEmpty {
|
} else if !lastName.isEmpty {
|
||||||
return lastName
|
return lastName
|
||||||
} else if !phone.isEmpty {
|
} else if !phone.isEmpty {
|
||||||
return formatPhoneNumber(context: context, number: "+\(phone)")
|
if let context {
|
||||||
|
return formatPhoneNumber(context: context, number: "+\(phone)")
|
||||||
|
} else {
|
||||||
|
return "+\(phone)"
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return strings.User_DeletedAccount
|
return strings.User_DeletedAccount
|
||||||
}
|
}
|
||||||
@ -127,7 +132,18 @@ public enum ItemListAvatarAndNameInfoItemMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class ItemListAvatarAndNameInfoItem: ListViewItem, ItemListItem {
|
public class ItemListAvatarAndNameInfoItem: ListViewItem, ItemListItem {
|
||||||
let accountContext: AccountContext
|
public enum ItemContext {
|
||||||
|
case accountContext(AccountContext)
|
||||||
|
case other(accountPeerId: EnginePeer.Id, postbox: Postbox, network: Network)
|
||||||
|
|
||||||
|
var accountContext: AccountContext? {
|
||||||
|
if case let .accountContext(accountContext) = self {
|
||||||
|
return accountContext
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let itemContext: ItemContext
|
||||||
let presentationData: ItemListPresentationData
|
let presentationData: ItemListPresentationData
|
||||||
let dateTimeFormat: PresentationDateTimeFormat
|
let dateTimeFormat: PresentationDateTimeFormat
|
||||||
let mode: ItemListAvatarAndNameInfoItemMode
|
let mode: ItemListAvatarAndNameInfoItemMode
|
||||||
@ -150,8 +166,8 @@ public class ItemListAvatarAndNameInfoItem: ListViewItem, ItemListItem {
|
|||||||
|
|
||||||
public let selectable: Bool
|
public let selectable: Bool
|
||||||
|
|
||||||
public init(accountContext: AccountContext, presentationData: ItemListPresentationData, dateTimeFormat: PresentationDateTimeFormat, mode: ItemListAvatarAndNameInfoItemMode, peer: EnginePeer?, presence: EnginePeer.Presence?, label: String? = nil, memberCount: Int?, state: ItemListAvatarAndNameInfoItemState, sectionId: ItemListSectionId, style: ItemListAvatarAndNameInfoItemStyle, editingNameUpdated: @escaping (ItemListAvatarAndNameInfoItemName) -> Void, editingNameCompleted: @escaping () -> Void = {}, avatarTapped: @escaping () -> Void, context: ItemListAvatarAndNameInfoItemContext? = nil, updatingImage: ItemListAvatarAndNameInfoItemUpdatingAvatar? = nil, call: (() -> Void)? = nil, action: (() -> Void)? = nil, longTapAction: (() -> Void)? = nil, tag: ItemListItemTag? = nil) {
|
public init(itemContext: ItemContext, presentationData: ItemListPresentationData, dateTimeFormat: PresentationDateTimeFormat, mode: ItemListAvatarAndNameInfoItemMode, peer: EnginePeer?, presence: EnginePeer.Presence?, label: String? = nil, memberCount: Int?, state: ItemListAvatarAndNameInfoItemState, sectionId: ItemListSectionId, style: ItemListAvatarAndNameInfoItemStyle, editingNameUpdated: @escaping (ItemListAvatarAndNameInfoItemName) -> Void, editingNameCompleted: @escaping () -> Void = {}, avatarTapped: @escaping () -> Void, context: ItemListAvatarAndNameInfoItemContext? = nil, updatingImage: ItemListAvatarAndNameInfoItemUpdatingAvatar? = nil, call: (() -> Void)? = nil, action: (() -> Void)? = nil, longTapAction: (() -> Void)? = nil, tag: ItemListItemTag? = nil) {
|
||||||
self.accountContext = accountContext
|
self.itemContext = itemContext
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
self.dateTimeFormat = dateTimeFormat
|
self.dateTimeFormat = dateTimeFormat
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
@ -358,7 +374,12 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
|||||||
updatedTheme = item.presentationData.theme
|
updatedTheme = item.presentationData.theme
|
||||||
}
|
}
|
||||||
|
|
||||||
let premiumConfiguration = PremiumConfiguration.with(appConfiguration: item.accountContext.currentAppConfiguration.with { $0 })
|
let premiumConfiguration: PremiumConfiguration
|
||||||
|
if case let .accountContext(context) = item.itemContext {
|
||||||
|
premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 })
|
||||||
|
} else {
|
||||||
|
premiumConfiguration = .defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
var credibilityIconImage: UIImage?
|
var credibilityIconImage: UIImage?
|
||||||
var credibilityIconOffset: CGFloat = 4.0
|
var credibilityIconOffset: CGFloat = 4.0
|
||||||
@ -395,7 +416,7 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
|||||||
nameMaximumNumberOfLines = 2
|
nameMaximumNumberOfLines = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
let (nameNodeLayout, nameNodeApply) = layoutNameNode(TextNodeLayoutArguments(attributedString: NSAttributedString(string: displayTitle.composedDisplayTitle(context: item.accountContext, strings: item.presentationData.strings), font: nameFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: nameMaximumNumberOfLines, truncationType: .end, constrainedSize: CGSize(width: baseWidth - 20 - 94.0 - (item.call != nil ? 36.0 : 0.0) - additionalTitleInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
let (nameNodeLayout, nameNodeApply) = layoutNameNode(TextNodeLayoutArguments(attributedString: NSAttributedString(string: displayTitle.composedDisplayTitle(context: item.itemContext.accountContext, strings: item.presentationData.strings), font: nameFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: nameMaximumNumberOfLines, truncationType: .end, constrainedSize: CGSize(width: baseWidth - 20 - 94.0 - (item.call != nil ? 36.0 : 0.0) - additionalTitleInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||||
|
|
||||||
var statusText: String = ""
|
var statusText: String = ""
|
||||||
let statusColor: UIColor
|
let statusColor: UIColor
|
||||||
@ -404,7 +425,11 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
|||||||
switch item.mode {
|
switch item.mode {
|
||||||
case .settings:
|
case .settings:
|
||||||
if let phone = peer.phone, !phone.isEmpty {
|
if let phone = peer.phone, !phone.isEmpty {
|
||||||
statusText += formatPhoneNumber(context: item.accountContext, number: phone)
|
if let accountContext = item.itemContext.accountContext {
|
||||||
|
statusText += formatPhoneNumber(context: accountContext, number: phone)
|
||||||
|
} else {
|
||||||
|
statusText += formatPhoneNumber(phone)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let username = peer.addressName, !username.isEmpty {
|
if let username = peer.addressName, !username.isEmpty {
|
||||||
if !statusText.isEmpty {
|
if !statusText.isEmpty {
|
||||||
@ -669,7 +694,13 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
|||||||
overrideImage = .deletedIcon
|
overrideImage = .deletedIcon
|
||||||
}
|
}
|
||||||
|
|
||||||
strongSelf.avatarNode.setPeer(context: item.accountContext, theme: item.presentationData.theme, peer: peer, overrideImage: overrideImage, emptyColor: ignoreEmpty ? nil : item.presentationData.theme.list.mediaPlaceholderColor, synchronousLoad: synchronousLoads)
|
switch item.itemContext {
|
||||||
|
case let .accountContext(context):
|
||||||
|
strongSelf.avatarNode.setPeer(context: context, theme: item.presentationData.theme, peer: peer, overrideImage: overrideImage, emptyColor: ignoreEmpty ? nil : item.presentationData.theme.list.mediaPlaceholderColor, synchronousLoad: synchronousLoads)
|
||||||
|
case let .other(accountPeerId, postbox, network):
|
||||||
|
strongSelf.avatarNode.setPeer(accountPeerId: accountPeerId, postbox: postbox, network: network, contentSettings: .default, theme: item.presentationData.theme, peer: peer, authorOfMessage: nil, overrideImage: overrideImage, emptyColor: ignoreEmpty ? nil : item.presentationData.theme.list.mediaPlaceholderColor, synchronousLoad: synchronousLoads)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let avatarFrame = CGRect(origin: CGPoint(x: params.leftInset + 15.0, y: floor((layout.contentSize.height - 66.0) / 2.0)), size: CGSize(width: 66.0, height: 66.0))
|
let avatarFrame = CGRect(origin: CGPoint(x: params.leftInset + 15.0, y: floor((layout.contentSize.height - 66.0) / 2.0)), size: CGSize(width: 66.0, height: 66.0))
|
||||||
|
|||||||
@ -346,7 +346,7 @@ private enum ChannelAdminEntry: ItemListNodeEntry {
|
|||||||
let arguments = arguments as! ChannelAdminControllerArguments
|
let arguments = arguments as! ChannelAdminControllerArguments
|
||||||
switch self {
|
switch self {
|
||||||
case let .info(_, _, dateTimeFormat, peer, presence):
|
case let .info(_, _, dateTimeFormat, peer, presence):
|
||||||
return ItemListAvatarAndNameInfoItem(accountContext: arguments.context, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .generic, peer: peer, presence: presence, memberCount: nil, state: ItemListAvatarAndNameInfoItemState(), sectionId: self.section, style: .blocks(withTopInset: true, withExtendedBottomInset: false), editingNameUpdated: { _ in
|
return ItemListAvatarAndNameInfoItem(itemContext: .accountContext(arguments.context), presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .generic, peer: peer, presence: presence, memberCount: nil, state: ItemListAvatarAndNameInfoItemState(), sectionId: self.section, style: .blocks(withTopInset: true, withExtendedBottomInset: false), editingNameUpdated: { _ in
|
||||||
}, avatarTapped: {
|
}, avatarTapped: {
|
||||||
})
|
})
|
||||||
case let .rankTitle(_, text, count, limit):
|
case let .rankTitle(_, text, count, limit):
|
||||||
|
|||||||
@ -215,7 +215,7 @@ private enum ChannelBannedMemberEntry: ItemListNodeEntry {
|
|||||||
let arguments = arguments as! ChannelBannedMemberControllerArguments
|
let arguments = arguments as! ChannelBannedMemberControllerArguments
|
||||||
switch self {
|
switch self {
|
||||||
case let .info(_, _, dateTimeFormat, peer, presence):
|
case let .info(_, _, dateTimeFormat, peer, presence):
|
||||||
return ItemListAvatarAndNameInfoItem(accountContext: arguments.context, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .generic, peer: peer, presence: presence, memberCount: nil, state: ItemListAvatarAndNameInfoItemState(), sectionId: self.section, style: .blocks(withTopInset: true, withExtendedBottomInset: false), editingNameUpdated: { _ in
|
return ItemListAvatarAndNameInfoItem(itemContext: .accountContext(arguments.context), presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .generic, peer: peer, presence: presence, memberCount: nil, state: ItemListAvatarAndNameInfoItemState(), sectionId: self.section, style: .blocks(withTopInset: true, withExtendedBottomInset: false), editingNameUpdated: { _ in
|
||||||
}, avatarTapped: {
|
}, avatarTapped: {
|
||||||
})
|
})
|
||||||
case let .rightsHeader(_, text):
|
case let .rightsHeader(_, text):
|
||||||
|
|||||||
@ -35,7 +35,7 @@ private enum DeviceContactInfoAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final class DeviceContactInfoControllerArguments {
|
private final class DeviceContactInfoControllerArguments {
|
||||||
let accountContext: AccountContext?
|
let context: ShareControllerAccountContext
|
||||||
let isPlain: Bool
|
let isPlain: Bool
|
||||||
let updateEditingName: (ItemListAvatarAndNameInfoItemName) -> Void
|
let updateEditingName: (ItemListAvatarAndNameInfoItemName) -> Void
|
||||||
let updatePhone: (Int64, String) -> Void
|
let updatePhone: (Int64, String) -> Void
|
||||||
@ -52,8 +52,8 @@ private final class DeviceContactInfoControllerArguments {
|
|||||||
let updateShareViaException: (Bool) -> Void
|
let updateShareViaException: (Bool) -> Void
|
||||||
let openAvatar: (EnginePeer) -> Void
|
let openAvatar: (EnginePeer) -> Void
|
||||||
|
|
||||||
init(accountContext: AccountContext?, isPlain: Bool, updateEditingName: @escaping (ItemListAvatarAndNameInfoItemName) -> Void, updatePhone: @escaping (Int64, String) -> Void, updatePhoneLabel: @escaping (Int64, String) -> Void, deletePhone: @escaping (Int64) -> Void, setPhoneIdWithRevealedOptions: @escaping (Int64?, Int64?) -> Void, addPhoneNumber: @escaping () -> Void, performAction: @escaping (DeviceContactInfoAction) -> Void, toggleSelection: @escaping (DeviceContactInfoDataId) -> Void, callPhone: @escaping (String) -> Void, openUrl: @escaping (String) -> Void, openAddress: @escaping (DeviceContactAddressData) -> Void, displayCopyContextMenu: @escaping (DeviceContactInfoEntryTag, String) -> Void, updateShareViaException: @escaping (Bool) -> Void, openAvatar: @escaping (EnginePeer) -> Void) {
|
init(context: ShareControllerAccountContext, isPlain: Bool, updateEditingName: @escaping (ItemListAvatarAndNameInfoItemName) -> Void, updatePhone: @escaping (Int64, String) -> Void, updatePhoneLabel: @escaping (Int64, String) -> Void, deletePhone: @escaping (Int64) -> Void, setPhoneIdWithRevealedOptions: @escaping (Int64?, Int64?) -> Void, addPhoneNumber: @escaping () -> Void, performAction: @escaping (DeviceContactInfoAction) -> Void, toggleSelection: @escaping (DeviceContactInfoDataId) -> Void, callPhone: @escaping (String) -> Void, openUrl: @escaping (String) -> Void, openAddress: @escaping (DeviceContactAddressData) -> Void, displayCopyContextMenu: @escaping (DeviceContactInfoEntryTag, String) -> Void, updateShareViaException: @escaping (Bool) -> Void, openAvatar: @escaping (EnginePeer) -> Void) {
|
||||||
self.accountContext = accountContext
|
self.context = context
|
||||||
self.isPlain = isPlain
|
self.isPlain = isPlain
|
||||||
self.updateEditingName = updateEditingName
|
self.updateEditingName = updateEditingName
|
||||||
self.updatePhone = updatePhone
|
self.updatePhone = updatePhone
|
||||||
@ -406,10 +406,13 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
|
|||||||
let arguments = arguments as! DeviceContactInfoControllerArguments
|
let arguments = arguments as! DeviceContactInfoControllerArguments
|
||||||
switch self {
|
switch self {
|
||||||
case let .info(_, _, _, dateTimeFormat, peer, state, jobSummary, _, hiddenAvatar):
|
case let .info(_, _, _, dateTimeFormat, peer, state, jobSummary, _, hiddenAvatar):
|
||||||
guard let accountContext = arguments.accountContext else {
|
let itemContext: ItemListAvatarAndNameInfoItem.ItemContext
|
||||||
fatalError()
|
if let context = arguments.context as? ShareControllerAppAccountContext {
|
||||||
|
itemContext = .accountContext(context.context)
|
||||||
|
} else {
|
||||||
|
itemContext = .other(accountPeerId: arguments.context.accountPeerId, postbox: arguments.context.stateManager.postbox, network: arguments.context.stateManager.network)
|
||||||
}
|
}
|
||||||
return ItemListAvatarAndNameInfoItem(accountContext: accountContext, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .contact, peer: peer, presence: nil, label: jobSummary, memberCount: nil, state: state, sectionId: self.section, style: arguments.isPlain ? .plain : .blocks(withTopInset: false, withExtendedBottomInset: true), editingNameUpdated: { editingName in
|
return ItemListAvatarAndNameInfoItem(itemContext: itemContext, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .contact, peer: peer, presence: nil, label: jobSummary, memberCount: nil, state: state, sectionId: self.section, style: arguments.isPlain ? .plain : .blocks(withTopInset: false, withExtendedBottomInset: true), editingNameUpdated: { editingName in
|
||||||
arguments.updateEditingName(editingName)
|
arguments.updateEditingName(editingName)
|
||||||
}, avatarTapped: {
|
}, avatarTapped: {
|
||||||
if peer.smallProfileImage != nil {
|
if peer.smallProfileImage != nil {
|
||||||
@ -945,13 +948,7 @@ public func deviceContactInfoController(context: ShareControllerAccountContext,
|
|||||||
shareViaException = shareViaExceptionValue
|
shareViaException = shareViaExceptionValue
|
||||||
}
|
}
|
||||||
|
|
||||||
let accountContext: AccountContext?
|
let arguments = DeviceContactInfoControllerArguments(context: context, isPlain: !isShare, updateEditingName: { editingName in
|
||||||
if let context = context as? ShareControllerAppAccountContext {
|
|
||||||
accountContext = context.context
|
|
||||||
} else {
|
|
||||||
accountContext = nil
|
|
||||||
}
|
|
||||||
let arguments = DeviceContactInfoControllerArguments(accountContext: accountContext, isPlain: !isShare, updateEditingName: { editingName in
|
|
||||||
updateState { state in
|
updateState { state in
|
||||||
var state = state
|
var state = state
|
||||||
if let _ = state.editingState {
|
if let _ = state.editingState {
|
||||||
|
|||||||
@ -35,8 +35,9 @@ private final class DataAndStorageControllerArguments {
|
|||||||
let openBrowserSelection: () -> Void
|
let openBrowserSelection: () -> Void
|
||||||
let openIntents: () -> Void
|
let openIntents: () -> Void
|
||||||
let toggleEnableSensitiveContent: (Bool) -> Void
|
let toggleEnableSensitiveContent: (Bool) -> Void
|
||||||
|
let presentSensitiveContentConfirmation: () -> Void
|
||||||
|
|
||||||
init(openStorageUsage: @escaping () -> Void, openNetworkUsage: @escaping () -> Void, openProxy: @escaping () -> Void, openAutomaticDownloadConnectionType: @escaping (AutomaticDownloadConnectionType) -> Void, resetAutomaticDownload: @escaping () -> Void, toggleVoiceUseLessData: @escaping (Bool) -> Void, openSaveIncoming: @escaping (AutomaticSaveIncomingPeerType) -> Void, toggleSaveEditedPhotos: @escaping (Bool) -> Void, togglePauseMusicOnRecording: @escaping (Bool) -> Void, toggleRaiseToListen: @escaping (Bool) -> Void, toggleDownloadInBackground: @escaping (Bool) -> Void, openBrowserSelection: @escaping () -> Void, openIntents: @escaping () -> Void, toggleEnableSensitiveContent: @escaping (Bool) -> Void) {
|
init(openStorageUsage: @escaping () -> Void, openNetworkUsage: @escaping () -> Void, openProxy: @escaping () -> Void, openAutomaticDownloadConnectionType: @escaping (AutomaticDownloadConnectionType) -> Void, resetAutomaticDownload: @escaping () -> Void, toggleVoiceUseLessData: @escaping (Bool) -> Void, openSaveIncoming: @escaping (AutomaticSaveIncomingPeerType) -> Void, toggleSaveEditedPhotos: @escaping (Bool) -> Void, togglePauseMusicOnRecording: @escaping (Bool) -> Void, toggleRaiseToListen: @escaping (Bool) -> Void, toggleDownloadInBackground: @escaping (Bool) -> Void, openBrowserSelection: @escaping () -> Void, openIntents: @escaping () -> Void, toggleEnableSensitiveContent: @escaping (Bool) -> Void, presentSensitiveContentConfirmation: @escaping () -> Void) {
|
||||||
self.openStorageUsage = openStorageUsage
|
self.openStorageUsage = openStorageUsage
|
||||||
self.openNetworkUsage = openNetworkUsage
|
self.openNetworkUsage = openNetworkUsage
|
||||||
self.openProxy = openProxy
|
self.openProxy = openProxy
|
||||||
@ -51,6 +52,7 @@ private final class DataAndStorageControllerArguments {
|
|||||||
self.openBrowserSelection = openBrowserSelection
|
self.openBrowserSelection = openBrowserSelection
|
||||||
self.openIntents = openIntents
|
self.openIntents = openIntents
|
||||||
self.toggleEnableSensitiveContent = toggleEnableSensitiveContent
|
self.toggleEnableSensitiveContent = toggleEnableSensitiveContent
|
||||||
|
self.presentSensitiveContentConfirmation = presentSensitiveContentConfirmation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +112,7 @@ private enum DataAndStorageEntry: ItemListNodeEntry {
|
|||||||
case connectionHeader(PresentationTheme, String)
|
case connectionHeader(PresentationTheme, String)
|
||||||
case connectionProxy(PresentationTheme, String, String)
|
case connectionProxy(PresentationTheme, String, String)
|
||||||
case enableSensitiveContent(String, Bool)
|
case enableSensitiveContent(String, Bool)
|
||||||
|
case enableSensitiveContentInfo(String)
|
||||||
|
|
||||||
var section: ItemListSectionId {
|
var section: ItemListSectionId {
|
||||||
switch self {
|
switch self {
|
||||||
@ -127,7 +130,7 @@ private enum DataAndStorageEntry: ItemListNodeEntry {
|
|||||||
return DataAndStorageSection.other.rawValue
|
return DataAndStorageSection.other.rawValue
|
||||||
case .connectionHeader, .connectionProxy:
|
case .connectionHeader, .connectionProxy:
|
||||||
return DataAndStorageSection.connection.rawValue
|
return DataAndStorageSection.connection.rawValue
|
||||||
case .enableSensitiveContent:
|
case .enableSensitiveContent, .enableSensitiveContentInfo:
|
||||||
return DataAndStorageSection.enableSensitiveContent.rawValue
|
return DataAndStorageSection.enableSensitiveContent.rawValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -174,12 +177,14 @@ private enum DataAndStorageEntry: ItemListNodeEntry {
|
|||||||
return 34
|
return 34
|
||||||
case .raiseToListenInfo:
|
case .raiseToListenInfo:
|
||||||
return 35
|
return 35
|
||||||
case .connectionHeader:
|
|
||||||
return 36
|
|
||||||
case .connectionProxy:
|
|
||||||
return 37
|
|
||||||
case .enableSensitiveContent:
|
case .enableSensitiveContent:
|
||||||
|
return 36
|
||||||
|
case .enableSensitiveContentInfo:
|
||||||
|
return 37
|
||||||
|
case .connectionHeader:
|
||||||
return 38
|
return 38
|
||||||
|
case .connectionProxy:
|
||||||
|
return 39
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,6 +328,12 @@ private enum DataAndStorageEntry: ItemListNodeEntry {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
case let .enableSensitiveContentInfo(text):
|
||||||
|
if case .enableSensitiveContentInfo(text) = rhs {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -421,9 +432,15 @@ private enum DataAndStorageEntry: ItemListNodeEntry {
|
|||||||
arguments.openProxy()
|
arguments.openProxy()
|
||||||
})
|
})
|
||||||
case let .enableSensitiveContent(text, value):
|
case let .enableSensitiveContent(text, value):
|
||||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enableInteractiveChanges: value, sectionId: self.section, style: .blocks, updated: { updatedValue in
|
||||||
arguments.toggleEnableSensitiveContent(value)
|
if value {
|
||||||
|
arguments.toggleEnableSensitiveContent(updatedValue)
|
||||||
|
} else {
|
||||||
|
arguments.presentSensitiveContentConfirmation()
|
||||||
|
}
|
||||||
}, tag: nil)
|
}, tag: nil)
|
||||||
|
case let .enableSensitiveContentInfo(text):
|
||||||
|
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -627,6 +644,14 @@ private func dataAndStorageControllerEntries(state: DataAndStorageControllerStat
|
|||||||
entries.append(.raiseToListen(presentationData.theme, presentationData.strings.Settings_RaiseToListen, data.mediaInputSettings.enableRaiseToSpeak))
|
entries.append(.raiseToListen(presentationData.theme, presentationData.strings.Settings_RaiseToListen, data.mediaInputSettings.enableRaiseToSpeak))
|
||||||
entries.append(.raiseToListenInfo(presentationData.theme, presentationData.strings.Settings_RaiseToListenInfo))
|
entries.append(.raiseToListenInfo(presentationData.theme, presentationData.strings.Settings_RaiseToListenInfo))
|
||||||
|
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
if let contentSettingsConfiguration = contentSettingsConfiguration { //, contentSettingsConfiguration.canAdjustSensitiveContent {
|
||||||
|
entries.append(.enableSensitiveContent("Show 18+ Content", contentSettingsConfiguration.sensitiveContentEnabled))
|
||||||
|
entries.append(.enableSensitiveContentInfo("Do not hide media that contain content suitable only for adults."))
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
let proxyValue: String
|
let proxyValue: String
|
||||||
if let proxySettings = data.proxySettings, let activeServer = proxySettings.activeServer, proxySettings.enabled {
|
if let proxySettings = data.proxySettings, let activeServer = proxySettings.activeServer, proxySettings.enabled {
|
||||||
switch activeServer.connection {
|
switch activeServer.connection {
|
||||||
@ -640,13 +665,7 @@ private func dataAndStorageControllerEntries(state: DataAndStorageControllerStat
|
|||||||
}
|
}
|
||||||
entries.append(.connectionHeader(presentationData.theme, presentationData.strings.ChatSettings_ConnectionType_Title.uppercased()))
|
entries.append(.connectionHeader(presentationData.theme, presentationData.strings.ChatSettings_ConnectionType_Title.uppercased()))
|
||||||
entries.append(.connectionProxy(presentationData.theme, presentationData.strings.SocksProxySetup_Title, proxyValue))
|
entries.append(.connectionProxy(presentationData.theme, presentationData.strings.SocksProxySetup_Title, proxyValue))
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
if let contentSettingsConfiguration = contentSettingsConfiguration, contentSettingsConfiguration.canAdjustSensitiveContent {
|
|
||||||
entries.append(.enableSensitiveContent("Display Sensitive Content", contentSettingsConfiguration.sensitiveContentEnabled))
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return entries
|
return entries
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -779,6 +798,8 @@ public func dataAndStorageController(context: AccountContext, focusOnItemTag: Da
|
|||||||
return DataAndStorageData(automaticMediaDownloadSettings: automaticMediaDownloadSettings, autodownloadSettings: autodownloadSettings, generatedMediaStoreSettings: generatedMediaStoreSettings, mediaInputSettings: mediaInputSettings, voiceCallSettings: voiceCallSettings, proxySettings: proxySettings)
|
return DataAndStorageData(automaticMediaDownloadSettings: automaticMediaDownloadSettings, autodownloadSettings: autodownloadSettings, generatedMediaStoreSettings: generatedMediaStoreSettings, mediaInputSettings: mediaInputSettings, voiceCallSettings: voiceCallSettings, proxySettings: proxySettings)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
var enableSensitiveContentImpl: (() -> Void)?
|
||||||
|
|
||||||
let arguments = DataAndStorageControllerArguments(openStorageUsage: {
|
let arguments = DataAndStorageControllerArguments(openStorageUsage: {
|
||||||
pushControllerImpl?(StorageUsageScreen(context: context, makeStorageUsageExceptionsScreen: { category in
|
pushControllerImpl?(StorageUsageScreen(context: context, makeStorageUsageExceptionsScreen: { category in
|
||||||
return storageUsageExceptionsScreen(context: context, category: category)
|
return storageUsageExceptionsScreen(context: context, category: category)
|
||||||
@ -882,8 +903,22 @@ public func dataAndStorageController(context: AccountContext, focusOnItemTag: Da
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
updateSensitiveContentDisposable.set(updateRemoteContentSettingsConfiguration(postbox: context.account.postbox, network: context.account.network, sensitiveContentEnabled: value).start())
|
updateSensitiveContentDisposable.set(updateRemoteContentSettingsConfiguration(postbox: context.account.postbox, network: context.account.network, sensitiveContentEnabled: value).start())
|
||||||
|
}, presentSensitiveContentConfirmation: {
|
||||||
|
let controller = textAlertController(context: context, title: "18+ Content", text: "Confirm that you are over 18 years old and update your settings to see potentially explicit and sensitive content.", actions: [
|
||||||
|
TextAlertAction(type: .genericAction, title: "Cancel", action: {
|
||||||
|
|
||||||
|
}),
|
||||||
|
TextAlertAction(type: .defaultAction, title: "Confirm", action: {
|
||||||
|
enableSensitiveContentImpl?()
|
||||||
|
})
|
||||||
|
])
|
||||||
|
presentControllerImpl?(controller, nil)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
enableSensitiveContentImpl = {
|
||||||
|
arguments.toggleEnableSensitiveContent(true)
|
||||||
|
}
|
||||||
|
|
||||||
let preferencesKey: PostboxViewKey = .preferences(keys: Set([ApplicationSpecificPreferencesKeys.mediaAutoSaveSettings]))
|
let preferencesKey: PostboxViewKey = .preferences(keys: Set([ApplicationSpecificPreferencesKeys.mediaAutoSaveSettings]))
|
||||||
let preferences = context.account.postbox.combinedView(keys: [preferencesKey])
|
let preferences = context.account.postbox.combinedView(keys: [preferencesKey])
|
||||||
|> map { views -> MediaAutoSaveSettings in
|
|> map { views -> MediaAutoSaveSettings in
|
||||||
|
|||||||
@ -167,7 +167,7 @@ private enum SaveIncomingMediaEntry: ItemListNodeEntry {
|
|||||||
switch self {
|
switch self {
|
||||||
case let .peer(peer, presence):
|
case let .peer(peer, presence):
|
||||||
return ItemListAvatarAndNameInfoItem(
|
return ItemListAvatarAndNameInfoItem(
|
||||||
accountContext: arguments.context,
|
itemContext: .accountContext(arguments.context),
|
||||||
presentationData: presentationData,
|
presentationData: presentationData,
|
||||||
dateTimeFormat: PresentationDateTimeFormat(),
|
dateTimeFormat: PresentationDateTimeFormat(),
|
||||||
mode: .generic,
|
mode: .generic,
|
||||||
|
|||||||
@ -72,10 +72,10 @@ struct InternalStarsStatus {
|
|||||||
let nextOffset: String?
|
let nextOffset: String?
|
||||||
}
|
}
|
||||||
|
|
||||||
func _internal_requestStarsState(account: Account, peerId: EnginePeer.Id, offset: String?) -> Signal<InternalStarsStatus?, NoError> {
|
func _internal_requestStarsState(account: Account, peerId: EnginePeer.Id, offset: String?) -> Signal<InternalStarsStatus, NoError> {
|
||||||
return account.postbox.transaction { transaction -> Peer? in
|
return account.postbox.transaction { transaction -> Peer? in
|
||||||
return transaction.getPeer(peerId)
|
return transaction.getPeer(peerId)
|
||||||
} |> mapToSignal { peer -> Signal<InternalStarsStatus?, NoError> in
|
} |> mapToSignal { peer -> Signal<InternalStarsStatus, NoError> in
|
||||||
guard let peer, let inputPeer = apiInputPeer(peer) else {
|
guard let peer, let inputPeer = apiInputPeer(peer) else {
|
||||||
return .never()
|
return .never()
|
||||||
}
|
}
|
||||||
@ -88,15 +88,9 @@ func _internal_requestStarsState(account: Account, peerId: EnginePeer.Id, offset
|
|||||||
}
|
}
|
||||||
|
|
||||||
return signal
|
return signal
|
||||||
|> map(Optional.init)
|
|> retryRequest
|
||||||
|> `catch` { _ -> Signal<Api.payments.StarsStatus?, NoError> in
|
|> mapToSignal { result -> Signal<InternalStarsStatus, NoError> in
|
||||||
return .single(nil)
|
return account.postbox.transaction { transaction -> InternalStarsStatus in
|
||||||
}
|
|
||||||
|> mapToSignal { result -> Signal<InternalStarsStatus?, NoError> in
|
|
||||||
guard let result else {
|
|
||||||
return .single(nil)
|
|
||||||
}
|
|
||||||
return account.postbox.transaction { transaction -> InternalStarsStatus? in
|
|
||||||
switch result {
|
switch result {
|
||||||
case let .starsStatus(_, balance, history, nextOffset, chats, users):
|
case let .starsStatus(_, balance, history, nextOffset, chats, users):
|
||||||
let peers = AccumulatedPeers(chats: chats, users: users)
|
let peers = AccumulatedPeers(chats: chats, users: users)
|
||||||
@ -168,14 +162,10 @@ private final class StarsContextImpl {
|
|||||||
self.disposable.set((_internal_requestStarsState(account: self.account, peerId: self.peerId, offset: nil)
|
self.disposable.set((_internal_requestStarsState(account: self.account, peerId: self.peerId, offset: nil)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] status in
|
|> deliverOnMainQueue).start(next: { [weak self] status in
|
||||||
if let self {
|
if let self {
|
||||||
if let status {
|
self._state = StarsContext.State(balance: status.balance, transactions: status.transactions, canLoadMore: status.nextOffset != nil, isLoading: false)
|
||||||
self._state = StarsContext.State(balance: status.balance, transactions: status.transactions, canLoadMore: status.nextOffset != nil, isLoading: false)
|
self.nextOffset = status.nextOffset
|
||||||
self.nextOffset = status.nextOffset
|
|
||||||
|
self.loadMore()
|
||||||
self.loadMore()
|
|
||||||
} else {
|
|
||||||
self._state = nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -202,12 +192,8 @@ private final class StarsContextImpl {
|
|||||||
self.disposable.set((_internal_requestStarsState(account: self.account, peerId: self.peerId, offset: nextOffset)
|
self.disposable.set((_internal_requestStarsState(account: self.account, peerId: self.peerId, offset: nextOffset)
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] status in
|
|> deliverOnMainQueue).start(next: { [weak self] status in
|
||||||
if let self {
|
if let self {
|
||||||
if let status {
|
self._state = StarsContext.State(balance: status.balance, transactions: currentState.transactions + status.transactions, canLoadMore: status.nextOffset != nil, isLoading: false)
|
||||||
self._state = StarsContext.State(balance: status.balance, transactions: currentState.transactions + status.transactions, canLoadMore: status.nextOffset != nil, isLoading: false)
|
self.nextOffset = status.nextOffset
|
||||||
self.nextOffset = status.nextOffset
|
|
||||||
} else {
|
|
||||||
self.nextOffset = nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -73,17 +73,7 @@ public extension TelegramEngine {
|
|||||||
public func peerStarsContext(peerId: EnginePeer.Id) -> StarsContext {
|
public func peerStarsContext(peerId: EnginePeer.Id) -> StarsContext {
|
||||||
return StarsContext(account: self.account, peerId: peerId)
|
return StarsContext(account: self.account, peerId: peerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func peerStarsState(peerId: EnginePeer.Id) -> Signal<StarsContext.State?, NoError> {
|
|
||||||
return _internal_requestStarsState(account: self.account, peerId: peerId, offset: nil)
|
|
||||||
|> map { state -> StarsContext.State? in
|
|
||||||
guard let state else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return StarsContext.State(balance: state.balance, transactions: state.transactions, canLoadMore: false, isLoading: false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public func sendStarsPaymentForm(formId: Int64, source: BotPaymentInvoiceSource) -> Signal<SendBotPaymentResult, SendBotPaymentFormError> {
|
public func sendStarsPaymentForm(formId: Int64, source: BotPaymentInvoiceSource) -> Signal<SendBotPaymentResult, SendBotPaymentFormError> {
|
||||||
return _internal_sendStarsPaymentForm(account: self.account, formId: formId, source: source)
|
return _internal_sendStarsPaymentForm(account: self.account, formId: formId, source: source)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -847,8 +847,8 @@ private let starImage: UIImage? = {
|
|||||||
generateImage(CGSize(width: 32.0, height: 32.0), contextGenerator: { size, context in
|
generateImage(CGSize(width: 32.0, height: 32.0), contextGenerator: { size, context in
|
||||||
context.clear(CGRect(origin: .zero, size: size))
|
context.clear(CGRect(origin: .zero, size: size))
|
||||||
|
|
||||||
if let image = generateTintedImage(image: UIImage(bundleImageName: "Premium/Stars/Star"), color: .white), let cgImage = image.cgImage {
|
if let image = generateTintedImage(image: UIImage(bundleImageName: "Item List/PremiumIcon"), color: .white), let cgImage = image.cgImage {
|
||||||
context.draw(cgImage, in: CGRect(origin: .zero, size: size).insetBy(dx: 2.0, dy: 2.0), byTiling: false)
|
context.draw(cgImage, in: CGRect(origin: .zero, size: size).insetBy(dx: 4.0, dy: 4.0), byTiling: false)
|
||||||
}
|
}
|
||||||
})?.withRenderingMode(.alwaysTemplate)
|
})?.withRenderingMode(.alwaysTemplate)
|
||||||
}()
|
}()
|
||||||
|
|||||||
@ -317,7 +317,7 @@ public class ShareRootControllerImpl {
|
|||||||
presentationDataPromise.set(.single(presentationData))
|
presentationDataPromise.set(.single(presentationData))
|
||||||
|
|
||||||
var immediatePeerId: PeerId?
|
var immediatePeerId: PeerId?
|
||||||
if #available(iOS 13.2, *), let sendMessageIntent = self.getExtensionContext()?.intent as? INSendMessageIntent {
|
if !"".isEmpty, #available(iOS 13.2, *), let sendMessageIntent = self.getExtensionContext()?.intent as? INSendMessageIntent {
|
||||||
if let contact = sendMessageIntent.recipients?.first, let handle = contact.customIdentifier, handle.hasPrefix("tg") {
|
if let contact = sendMessageIntent.recipients?.first, let handle = contact.customIdentifier, handle.hasPrefix("tg") {
|
||||||
let string = handle.suffix(from: handle.index(handle.startIndex, offsetBy: 2))
|
let string = handle.suffix(from: handle.index(handle.startIndex, offsetBy: 2))
|
||||||
if let peerId = Int64(string) {
|
if let peerId = Int64(string) {
|
||||||
|
|||||||
@ -1059,13 +1059,13 @@ func generateStarsIcon(count: Int) -> UIImage {
|
|||||||
|
|
||||||
var originX = floorToScreenPixels((size.width - totalWidth) / 2.0)
|
var originX = floorToScreenPixels((size.width - totalWidth) / 2.0)
|
||||||
|
|
||||||
let mainImage = UIImage(bundleImageName: "Premium/Stars/Star")
|
let mainImage = UIImage(bundleImageName: "Premium/Stars/StarLarge")
|
||||||
if let cgImage = mainImage?.cgImage, let partCGImage = partImage.cgImage {
|
if let cgImage = mainImage?.cgImage, let partCGImage = partImage.cgImage {
|
||||||
context.draw(cgImage, in: CGRect(origin: CGPoint(x: originX, y: 0.0), size: imageSize), byTiling: false)
|
context.draw(cgImage, in: CGRect(origin: CGPoint(x: originX, y: 0.0), size: imageSize), byTiling: false)
|
||||||
originX += spacing
|
originX += spacing + UIScreenPixel
|
||||||
|
|
||||||
for _ in 0 ..< count - 1 {
|
for _ in 0 ..< count - 1 {
|
||||||
context.draw(partCGImage, in: CGRect(origin: CGPoint(x: originX, y: UIScreenPixel), size: imageSize), byTiling: false)
|
context.draw(partCGImage, in: CGRect(origin: CGPoint(x: originX, y: -UIScreenPixel), size: imageSize).insetBy(dx: -1.0 + UIScreenPixel, dy: -1.0 + UIScreenPixel), byTiling: false)
|
||||||
originX += spacing
|
originX += spacing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,7 +52,7 @@ final class StarsBalanceComponent: Component {
|
|||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
self.icon.image = UIImage(bundleImageName: "Premium/Stars/StarLarge")
|
self.icon.image = UIImage(bundleImageName: "Premium/Stars/BalanceStar")
|
||||||
|
|
||||||
self.addSubview(self.icon)
|
self.addSubview(self.icon)
|
||||||
}
|
}
|
||||||
@ -107,7 +107,7 @@ final class StarsBalanceComponent: Component {
|
|||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(
|
component: AnyComponent(
|
||||||
MultilineTextComponent(
|
MultilineTextComponent(
|
||||||
text: .plain(NSAttributedString(string: "your balance", font: Font.regular(17.0), textColor: component.theme.list.itemSecondaryTextColor)),
|
text: .plain(NSAttributedString(string: component.strings.Stars_Intro_YourBalance, font: Font.regular(17.0), textColor: component.theme.list.itemSecondaryTextColor)),
|
||||||
horizontalAlignment: .center
|
horizontalAlignment: .center
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@ -126,7 +126,7 @@ final class StarsBalanceComponent: Component {
|
|||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(
|
component: AnyComponent(
|
||||||
SolidRoundedButtonComponent(
|
SolidRoundedButtonComponent(
|
||||||
title: "Buy More Stars",
|
title: component.strings.Stars_Intro_Buy,
|
||||||
theme: SolidRoundedButtonComponent.Theme(theme: component.theme),
|
theme: SolidRoundedButtonComponent.Theme(theme: component.theme),
|
||||||
height: 50.0,
|
height: 50.0,
|
||||||
cornerRadius: 11.0,
|
cornerRadius: 11.0,
|
||||||
|
|||||||
@ -118,7 +118,9 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
let closeButton = Child(Button.self)
|
let closeButton = Child(Button.self)
|
||||||
let title = Child(MultilineTextComponent.self)
|
let title = Child(MultilineTextComponent.self)
|
||||||
let star = Child(GiftAvatarComponent.self)
|
let star = Child(GiftAvatarComponent.self)
|
||||||
let description = Child(BalancedTextComponent.self)
|
let amount = Child(BalancedTextComponent.self)
|
||||||
|
let amountStar = Child(BundleIconComponent.self)
|
||||||
|
let description = Child(MultilineTextComponent.self)
|
||||||
let table = Child(TableComponent.self)
|
let table = Child(TableComponent.self)
|
||||||
let additional = Child(BalancedTextComponent.self)
|
let additional = Child(BalancedTextComponent.self)
|
||||||
let button = Child(SolidRoundedButtonComponent.self)
|
let button = Child(SolidRoundedButtonComponent.self)
|
||||||
@ -157,6 +159,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
)
|
)
|
||||||
|
|
||||||
let titleText: String
|
let titleText: String
|
||||||
|
let amountText: String
|
||||||
let descriptionText: String
|
let descriptionText: String
|
||||||
let additionalText: String
|
let additionalText: String
|
||||||
let buttonText: String
|
let buttonText: String
|
||||||
@ -164,6 +167,7 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
let count: Int64
|
let count: Int64
|
||||||
let transactionId: String?
|
let transactionId: String?
|
||||||
let date: Int32
|
let date: Int32
|
||||||
|
let via: String?
|
||||||
let toPeer: EnginePeer?
|
let toPeer: EnginePeer?
|
||||||
let photo: TelegramMediaWebFile?
|
let photo: TelegramMediaWebFile?
|
||||||
|
|
||||||
@ -173,17 +177,24 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
switch transaction.peer {
|
switch transaction.peer {
|
||||||
case let .peer(peer):
|
case let .peer(peer):
|
||||||
titleText = transaction.title ?? peer.compactDisplayTitle
|
titleText = transaction.title ?? peer.compactDisplayTitle
|
||||||
|
via = nil
|
||||||
case .appStore:
|
case .appStore:
|
||||||
titleText = "In-App Purchase"
|
titleText = strings.Stars_Transaction_AppleTopUp_Title
|
||||||
|
via = strings.Stars_Transaction_AppleTopUp_Subtitle
|
||||||
case .playMarket:
|
case .playMarket:
|
||||||
titleText = "Play Market"
|
titleText = strings.Stars_Transaction_GoogleTopUp_Title
|
||||||
|
via = strings.Stars_Transaction_GoogleTopUp_Subtitle
|
||||||
case .premiumBot:
|
case .premiumBot:
|
||||||
titleText = "Premium Bot"
|
titleText = strings.Stars_Transaction_PremiumBotTopUp_Title
|
||||||
|
via = strings.Stars_Transaction_PremiumBotTopUp_Subtitle
|
||||||
case .fragment:
|
case .fragment:
|
||||||
titleText = "Fragment"
|
titleText = strings.Stars_Transaction_FragmentTopUp_Title
|
||||||
|
via = strings.Stars_Transaction_FragmentTopUp_Subtitle
|
||||||
case .unsupported:
|
case .unsupported:
|
||||||
titleText = "Unsupported"
|
titleText = strings.Stars_Transaction_Unsupported_Title
|
||||||
|
via = nil
|
||||||
}
|
}
|
||||||
|
descriptionText = transaction.description ?? ""
|
||||||
|
|
||||||
count = transaction.count
|
count = transaction.count
|
||||||
transactionId = transaction.id
|
transactionId = transaction.id
|
||||||
@ -196,7 +207,9 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
photo = transaction.photo
|
photo = transaction.photo
|
||||||
case let .receipt(receipt):
|
case let .receipt(receipt):
|
||||||
titleText = receipt.invoiceMedia.title
|
titleText = receipt.invoiceMedia.title
|
||||||
|
descriptionText = receipt.invoiceMedia.description
|
||||||
count = (receipt.invoice.prices.first?.amount ?? receipt.invoiceMedia.totalAmount) * -1
|
count = (receipt.invoice.prices.first?.amount ?? receipt.invoiceMedia.totalAmount) * -1
|
||||||
|
via = nil
|
||||||
transactionId = receipt.transactionId
|
transactionId = receipt.transactionId
|
||||||
date = receipt.date
|
date = receipt.date
|
||||||
if let peer = state.peerMap[receipt.botPaymentId] {
|
if let peer = state.peerMap[receipt.botPaymentId] {
|
||||||
@ -207,22 +220,15 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
photo = receipt.invoiceMedia.photo
|
photo = receipt.invoiceMedia.photo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let formattedAmount = presentationStringsFormattedNumber(abs(Int32(count)), dateTimeFormat.decimalSeparator)
|
||||||
|
if count < 0 {
|
||||||
|
amountText = "- \(formattedAmount)"
|
||||||
|
} else {
|
||||||
|
amountText = "+ \(formattedAmount)"
|
||||||
|
}
|
||||||
additionalText = strings.Stars_Transaction_Terms
|
additionalText = strings.Stars_Transaction_Terms
|
||||||
buttonText = strings.Common_OK
|
buttonText = strings.Common_OK
|
||||||
|
|
||||||
if count < 0 {
|
|
||||||
descriptionText = " - \(count * -1) # "
|
|
||||||
} else {
|
|
||||||
descriptionText = " + \(count) # "
|
|
||||||
}
|
|
||||||
|
|
||||||
let descriptionAttributedText = NSMutableAttributedString(string: descriptionText, font: Font.semibold(18.0), textColor: descriptionText.hasPrefix("-") ? theme.list.itemDestructiveColor : theme.list.itemDisclosureActions.constructive.fillColor)
|
|
||||||
if let range = descriptionAttributedText.string.range(of: "#"), let chevronImage = generateTintedImage(image: UIImage(bundleImageName: "Item List/PremiumIcon"), color: UIColor(rgb: 0xf09903)) {
|
|
||||||
descriptionAttributedText.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: descriptionAttributedText.string))
|
|
||||||
descriptionAttributedText.addAttribute(.foregroundColor, value: UIColor(rgb: 0xf09903), range: NSRange(range, in: descriptionAttributedText.string))
|
|
||||||
descriptionAttributedText.addAttribute(.baselineOffset, value: 2.0, range: NSRange(range, in: descriptionAttributedText.string))
|
|
||||||
}
|
|
||||||
|
|
||||||
let title = title.update(
|
let title = title.update(
|
||||||
component: MultilineTextComponent(
|
component: MultilineTextComponent(
|
||||||
text: .plain(NSAttributedString(
|
text: .plain(NSAttributedString(
|
||||||
@ -254,9 +260,10 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
transition: .immediate
|
transition: .immediate
|
||||||
)
|
)
|
||||||
|
|
||||||
let description = description.update(
|
let amountAttributedText = NSMutableAttributedString(string: amountText, font: Font.semibold(17.0), textColor: amountText.hasPrefix("-") ? theme.list.itemDestructiveColor : theme.list.itemDisclosureActions.constructive.fillColor)
|
||||||
|
let amount = amount.update(
|
||||||
component: BalancedTextComponent(
|
component: BalancedTextComponent(
|
||||||
text: .plain(descriptionAttributedText),
|
text: .plain(amountAttributedText),
|
||||||
horizontalAlignment: .center,
|
horizontalAlignment: .center,
|
||||||
maximumNumberOfLines: 0,
|
maximumNumberOfLines: 0,
|
||||||
lineSpacing: 0.2
|
lineSpacing: 0.2
|
||||||
@ -264,7 +271,16 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
availableSize: CGSize(width: context.availableSize.width - textSideInset * 2.0, height: context.availableSize.height),
|
availableSize: CGSize(width: context.availableSize.width - textSideInset * 2.0, height: context.availableSize.height),
|
||||||
transition: .immediate
|
transition: .immediate
|
||||||
)
|
)
|
||||||
|
|
||||||
|
let amountStar = amountStar.update(
|
||||||
|
component: BundleIconComponent(
|
||||||
|
name: "Premium/Stars/StarMedium",
|
||||||
|
tintColor: nil
|
||||||
|
),
|
||||||
|
availableSize: context.availableSize,
|
||||||
|
transition: .immediate
|
||||||
|
)
|
||||||
|
|
||||||
let tableFont = Font.regular(15.0)
|
let tableFont = Font.regular(15.0)
|
||||||
let tableTextColor = theme.list.itemPrimaryTextColor
|
let tableTextColor = theme.list.itemPrimaryTextColor
|
||||||
let tableLinkColor = theme.list.itemAccentColor
|
let tableLinkColor = theme.list.itemAccentColor
|
||||||
@ -294,6 +310,14 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
|
} else if let via {
|
||||||
|
tableItems.append(.init(
|
||||||
|
id: "via",
|
||||||
|
title: strings.Stars_Transaction_Via,
|
||||||
|
component: AnyComponent(
|
||||||
|
MultilineTextComponent(text: .plain(NSAttributedString(string: via, font: tableFont, textColor: tableTextColor)))
|
||||||
|
)
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
if let transactionId {
|
if let transactionId {
|
||||||
@ -393,10 +417,35 @@ private final class StarsTransactionSheetContent: CombinedComponent {
|
|||||||
var originY: CGFloat = 0.0
|
var originY: CGFloat = 0.0
|
||||||
originY += star.size.height - 23.0
|
originY += star.size.height - 23.0
|
||||||
|
|
||||||
context.add(description
|
if !descriptionText.isEmpty {
|
||||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: originY + description.size.height / 2.0))
|
let description = description.update(
|
||||||
|
component: MultilineTextComponent(
|
||||||
|
text: .plain(NSAttributedString(
|
||||||
|
string: descriptionText,
|
||||||
|
font: Font.regular(15.0),
|
||||||
|
textColor: theme.actionSheet.primaryTextColor,
|
||||||
|
paragraphAlignment: .center
|
||||||
|
)),
|
||||||
|
horizontalAlignment: .center,
|
||||||
|
maximumNumberOfLines: 3
|
||||||
|
),
|
||||||
|
availableSize: CGSize(width: context.availableSize.width - sideInset * 2.0 - 60.0, height: CGFloat.greatestFiniteMagnitude),
|
||||||
|
transition: .immediate
|
||||||
|
)
|
||||||
|
context.add(description
|
||||||
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: originY + description.size.height / 2.0))
|
||||||
|
)
|
||||||
|
originY += description.size.height + 10.0
|
||||||
|
}
|
||||||
|
|
||||||
|
context.add(amount
|
||||||
|
.position(CGPoint(x: context.availableSize.width / 2.0 - 10.0, y: originY + amount.size.height / 2.0))
|
||||||
)
|
)
|
||||||
originY += description.size.height + 20.0
|
context.add(amountStar
|
||||||
|
.position(CGPoint(x: context.availableSize.width / 2.0 + amount.size.width / 2.0 + amountStar.size.width / 2.0 - 7.0, y: originY + amountStar.size.height / 2.0))
|
||||||
|
)
|
||||||
|
|
||||||
|
originY += amount.size.height + 20.0
|
||||||
|
|
||||||
context.add(table
|
context.add(table
|
||||||
.position(CGPoint(x: context.availableSize.width / 2.0, y: originY + table.size.height / 2.0))
|
.position(CGPoint(x: context.availableSize.width / 2.0, y: originY + table.size.height / 2.0))
|
||||||
@ -1054,7 +1103,6 @@ private final class TransactionCellComponent: Component {
|
|||||||
|
|
||||||
let size = CGSize(width: textSize.width + spacing + buttonSize.width, height: textSize.height)
|
let size = CGSize(width: textSize.width + spacing + buttonSize.width, height: textSize.height)
|
||||||
|
|
||||||
|
|
||||||
let buttonFrame = CGRect(origin: CGPoint(x: textSize.width + spacing, y: floorToScreenPixels((size.height - buttonSize.height) / 2.0)), size: buttonSize)
|
let buttonFrame = CGRect(origin: CGPoint(x: textSize.width + spacing, y: floorToScreenPixels((size.height - buttonSize.height) / 2.0)), size: buttonSize)
|
||||||
if let buttonView = self.button.view {
|
if let buttonView = self.button.view {
|
||||||
if buttonView.superview == nil {
|
if buttonView.superview == nil {
|
||||||
@ -1063,7 +1111,7 @@ private final class TransactionCellComponent: Component {
|
|||||||
transition.setFrame(view: buttonView, frame: buttonFrame)
|
transition.setFrame(view: buttonView, frame: buttonFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
let textFrame = CGRect(origin: CGPoint(x: 0.0, y: floorToScreenPixels((size.height - textSize.height) / 2.0)), size: textSize)
|
let textFrame = CGRect(origin: CGPoint(x: 0.0, y: floorToScreenPixels((size.height - textSize.height) / 2.0) + 1.0), size: textSize)
|
||||||
if let textView = self.text.view {
|
if let textView = self.text.view {
|
||||||
if textView.superview == nil {
|
if textView.superview == nil {
|
||||||
self.addSubview(textView)
|
self.addSubview(textView)
|
||||||
|
|||||||
@ -203,7 +203,7 @@ final class StarsTransactionsListPanelComponent: Component {
|
|||||||
|
|
||||||
separatorView = UIView()
|
separatorView = UIView()
|
||||||
self.separatorViews[id] = separatorView
|
self.separatorViews[id] = separatorView
|
||||||
self.addSubview(separatorView)
|
self.scrollView.addSubview(separatorView)
|
||||||
}
|
}
|
||||||
|
|
||||||
separatorView.backgroundColor = environment.theme.list.itemBlocksSeparatorColor
|
separatorView.backgroundColor = environment.theme.list.itemBlocksSeparatorColor
|
||||||
@ -213,33 +213,38 @@ final class StarsTransactionsListPanelComponent: Component {
|
|||||||
let itemTitle: String
|
let itemTitle: String
|
||||||
let itemSubtitle: String?
|
let itemSubtitle: String?
|
||||||
let itemDate: String
|
let itemDate: String
|
||||||
let itemLabel: NSAttributedString
|
|
||||||
switch item.transaction.peer {
|
switch item.transaction.peer {
|
||||||
case let .peer(peer):
|
case let .peer(peer):
|
||||||
itemTitle = peer.displayTitle(strings: environment.strings, displayOrder: .firstLast)
|
itemTitle = peer.displayTitle(strings: environment.strings, displayOrder: .firstLast)
|
||||||
itemSubtitle = item.transaction.title
|
itemSubtitle = item.transaction.title
|
||||||
itemLabel = NSAttributedString(string: "- \(item.transaction.count * -1)", font: Font.medium(fontBaseDisplaySize), textColor: environment.theme.list.itemDestructiveColor)
|
|
||||||
case .appStore:
|
case .appStore:
|
||||||
itemTitle = "Stars Top-Up"
|
itemTitle = environment.strings.Stars_Intro_Transaction_AppleTopUp_Title
|
||||||
itemSubtitle = "via App Store"
|
itemSubtitle = environment.strings.Stars_Intro_Transaction_AppleTopUp_Subtitle
|
||||||
itemLabel = NSAttributedString(string: "+ \(item.transaction.count)", font: Font.medium(fontBaseDisplaySize), textColor: environment.theme.list.itemDisclosureActions.constructive.fillColor)
|
|
||||||
case .playMarket:
|
case .playMarket:
|
||||||
itemTitle = "Stars Top-Up"
|
itemTitle = environment.strings.Stars_Intro_Transaction_GoogleTopUp_Title
|
||||||
itemSubtitle = "via Play Market"
|
itemSubtitle = environment.strings.Stars_Intro_Transaction_GoogleTopUp_Subtitle
|
||||||
itemLabel = NSAttributedString(string: "+ \(item.transaction.count)", font: Font.medium(fontBaseDisplaySize), textColor: environment.theme.list.itemDisclosureActions.constructive.fillColor)
|
|
||||||
case .fragment:
|
case .fragment:
|
||||||
itemTitle = "Stars Top-Up"
|
itemTitle = environment.strings.Stars_Intro_Transaction_FragmentTopUp_Title
|
||||||
itemSubtitle = "via Fragment"
|
itemSubtitle = environment.strings.Stars_Intro_Transaction_FragmentTopUp_Subtitle
|
||||||
itemLabel = NSAttributedString(string: "+ \(item.transaction.count)", font: Font.medium(fontBaseDisplaySize), textColor: environment.theme.list.itemDisclosureActions.constructive.fillColor)
|
|
||||||
case .premiumBot:
|
case .premiumBot:
|
||||||
itemTitle = "Stars Top-Up"
|
itemTitle = environment.strings.Stars_Intro_Transaction_PremiumBotTopUp_Title
|
||||||
itemSubtitle = "via Premium Bot"
|
itemSubtitle = environment.strings.Stars_Intro_Transaction_PremiumBotTopUp_Subtitle
|
||||||
itemLabel = NSAttributedString(string: "+ \(item.transaction.count)", font: Font.medium(fontBaseDisplaySize), textColor: environment.theme.list.itemDisclosureActions.constructive.fillColor)
|
|
||||||
case .unsupported:
|
case .unsupported:
|
||||||
itemTitle = "Unsupported"
|
itemTitle = environment.strings.Stars_Intro_Transaction_Unsupported_Title
|
||||||
itemSubtitle = nil
|
itemSubtitle = nil
|
||||||
itemLabel = NSAttributedString(string: "+ \(item.transaction.count)", font: Font.medium(fontBaseDisplaySize), textColor: environment.theme.list.itemDisclosureActions.constructive.fillColor)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let itemLabel: NSAttributedString
|
||||||
|
let labelString: String
|
||||||
|
|
||||||
|
let formattedLabel = presentationStringsFormattedNumber(abs(Int32(item.transaction.count)), environment.dateTimeFormat.decimalSeparator)
|
||||||
|
if item.transaction.count < 0 {
|
||||||
|
labelString = "- \(formattedLabel)"
|
||||||
|
} else {
|
||||||
|
labelString = "+ \(formattedLabel)"
|
||||||
|
}
|
||||||
|
itemLabel = NSAttributedString(string: labelString, font: Font.medium(fontBaseDisplaySize), textColor: labelString.hasPrefix("-") ? environment.theme.list.itemDestructiveColor : environment.theme.list.itemDisclosureActions.constructive.fillColor)
|
||||||
|
|
||||||
itemDate = stringForMediumCompactDate(timestamp: item.transaction.date, strings: environment.strings, dateTimeFormat: environment.dateTimeFormat)
|
itemDate = stringForMediumCompactDate(timestamp: item.transaction.date, strings: environment.strings, dateTimeFormat: environment.dateTimeFormat)
|
||||||
|
|
||||||
var titleComponents: [AnyComponentWithIdentity<Empty>] = []
|
var titleComponents: [AnyComponentWithIdentity<Empty>] = []
|
||||||
@ -577,7 +582,7 @@ private final class LabelComponent: CombinedComponent {
|
|||||||
let iconSize = CGSize(width: 20.0, height: 20.0)
|
let iconSize = CGSize(width: 20.0, height: 20.0)
|
||||||
let icon = icon.update(
|
let icon = icon.update(
|
||||||
component: BundleIconComponent(
|
component: BundleIconComponent(
|
||||||
name: "Premium/Stars/Star",
|
name: "Premium/Stars/StarLarge",
|
||||||
tintColor: nil
|
tintColor: nil
|
||||||
),
|
),
|
||||||
availableSize: iconSize,
|
availableSize: iconSize,
|
||||||
@ -592,7 +597,7 @@ private final class LabelComponent: CombinedComponent {
|
|||||||
.position(CGPoint(x: text.size.width / 2.0, y: size.height / 2.0))
|
.position(CGPoint(x: text.size.width / 2.0, y: size.height / 2.0))
|
||||||
)
|
)
|
||||||
context.add(icon
|
context.add(icon
|
||||||
.position(CGPoint(x: totalWidth - iconSize.width / 2.0, y: size.height / 2.0))
|
.position(CGPoint(x: totalWidth - iconSize.width / 2.0, y: size.height / 2.0 - UIScreenPixel))
|
||||||
)
|
)
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
|||||||
@ -623,7 +623,9 @@ final class StarsTransactionsPanelContainerComponent: Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = self.header.update(
|
let sideInset: CGFloat = 16.0
|
||||||
|
let condensedPanelWidth: CGFloat = availableSize.width - sideInset * 2.0
|
||||||
|
let headerSize = self.header.update(
|
||||||
transition: transition,
|
transition: transition,
|
||||||
component: AnyComponent(StarsTransactionsHeaderComponent(
|
component: AnyComponent(StarsTransactionsHeaderComponent(
|
||||||
theme: component.theme,
|
theme: component.theme,
|
||||||
@ -648,13 +650,13 @@ final class StarsTransactionsPanelContainerComponent: Component {
|
|||||||
}
|
}
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: topPanelFrame.size
|
containerSize: CGSize(width: condensedPanelWidth, height: topPanelFrame.size.height)
|
||||||
)
|
)
|
||||||
if let headerView = self.header.view {
|
if let headerView = self.header.view {
|
||||||
if headerView.superview == nil {
|
if headerView.superview == nil {
|
||||||
self.addSubview(headerView)
|
self.addSubview(headerView)
|
||||||
}
|
}
|
||||||
transition.setFrame(view: headerView, frame: topPanelFrame)
|
transition.setFrame(view: headerView, frame: CGRect(origin: topPanelFrame.origin.offsetBy(dx: sideInset, dy: 0.0), size: headerSize))
|
||||||
}
|
}
|
||||||
|
|
||||||
let childEnvironment = StarsTransactionsPanelEnvironment(
|
let childEnvironment = StarsTransactionsPanelEnvironment(
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import BalancedTextComponent
|
|||||||
import Markdown
|
import Markdown
|
||||||
import PremiumStarComponent
|
import PremiumStarComponent
|
||||||
import ListSectionComponent
|
import ListSectionComponent
|
||||||
|
import BundleIconComponent
|
||||||
import TextFormat
|
import TextFormat
|
||||||
|
|
||||||
final class StarsTransactionsScreenComponent: Component {
|
final class StarsTransactionsScreenComponent: Component {
|
||||||
@ -90,7 +91,9 @@ final class StarsTransactionsScreenComponent: Component {
|
|||||||
|
|
||||||
private let balanceView = ComponentView<Empty>()
|
private let balanceView = ComponentView<Empty>()
|
||||||
|
|
||||||
private let topBalanceView = ComponentView<Empty>()
|
private let topBalanceTitleView = ComponentView<Empty>()
|
||||||
|
private let topBalanceValueView = ComponentView<Empty>()
|
||||||
|
private let topBalanceIconView = ComponentView<Empty>()
|
||||||
|
|
||||||
private let panelContainer = ComponentView<StarsTransactionsPanelContainerEnvironment>()
|
private let panelContainer = ComponentView<StarsTransactionsPanelContainerEnvironment>()
|
||||||
|
|
||||||
@ -241,8 +244,15 @@ final class StarsTransactionsScreenComponent: Component {
|
|||||||
panelContainerView.updateNavigationMergeFactor(value: 1.0 - expansionDistanceFactor, transition: transition)
|
panelContainerView.updateNavigationMergeFactor(value: 1.0 - expansionDistanceFactor, transition: transition)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let topBalanceView = self.topBalanceView.view {
|
let topBalanceAlpha = 1.0 - expansionDistanceFactor
|
||||||
topBalanceView.alpha = 1.0 - expansionDistanceFactor
|
if let view = self.topBalanceTitleView.view {
|
||||||
|
view.alpha = topBalanceAlpha
|
||||||
|
}
|
||||||
|
if let view = self.topBalanceValueView.view {
|
||||||
|
view.alpha = topBalanceAlpha
|
||||||
|
}
|
||||||
|
if let view = self.topBalanceIconView.view {
|
||||||
|
view.alpha = topBalanceAlpha
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,36 +418,69 @@ final class StarsTransactionsScreenComponent: Component {
|
|||||||
starTransition.setBounds(view: titleView, bounds: CGRect(origin: .zero, size: titleSize))
|
starTransition.setBounds(view: titleView, bounds: CGRect(origin: .zero, size: titleSize))
|
||||||
}
|
}
|
||||||
|
|
||||||
let textFont = Font.regular(14.0)
|
let topBalanceTitleSize = self.topBalanceTitleView.update(
|
||||||
let boldTextFont = Font.semibold(14.0)
|
|
||||||
let textColor = environment.theme.actionSheet.primaryTextColor
|
|
||||||
let linkColor = environment.theme.actionSheet.controlAccentColor
|
|
||||||
let markdownAttributes = MarkdownAttributes(body: MarkdownAttributeSet(font: textFont, textColor: textColor), bold: MarkdownAttributeSet(font: boldTextFont, textColor: textColor), link: MarkdownAttributeSet(font: textFont, textColor: linkColor), linkAttribute: { contents in
|
|
||||||
return (TelegramTextAttributes.URL, contents)
|
|
||||||
})
|
|
||||||
let balanceAttributedString = parseMarkdownIntoAttributedString(" \(environment.strings.Stars_Intro_Balance)\n # **\(self.starsState?.balance ?? 0)**", attributes: markdownAttributes, textAlignment: .right).mutableCopy() as! NSMutableAttributedString
|
|
||||||
if let range = balanceAttributedString.string.range(of: "#"), let chevronImage = generateTintedImage(image: UIImage(bundleImageName: "Item List/PremiumIcon"), color: UIColor(rgb: 0xf09903)) {
|
|
||||||
balanceAttributedString.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: balanceAttributedString.string))
|
|
||||||
balanceAttributedString.addAttribute(.foregroundColor, value: UIColor(rgb: 0xf09903), range: NSRange(range, in: balanceAttributedString.string))
|
|
||||||
balanceAttributedString.addAttribute(.baselineOffset, value: 2.0, range: NSRange(range, in: balanceAttributedString.string))
|
|
||||||
}
|
|
||||||
let topBalanceSize = self.topBalanceView.update(
|
|
||||||
transition: .immediate,
|
transition: .immediate,
|
||||||
component: AnyComponent(MultilineTextComponent(
|
component: AnyComponent(MultilineTextComponent(
|
||||||
text: .plain(balanceAttributedString),
|
text: .plain(NSAttributedString(
|
||||||
|
string: environment.strings.Stars_Intro_Balance,
|
||||||
|
font: Font.regular(14.0),
|
||||||
|
textColor: environment.theme.actionSheet.primaryTextColor
|
||||||
|
)),
|
||||||
horizontalAlignment: .right,
|
horizontalAlignment: .right,
|
||||||
maximumNumberOfLines: 0,
|
maximumNumberOfLines: 1
|
||||||
lineSpacing: 0.1
|
|
||||||
)),
|
)),
|
||||||
environment: {},
|
environment: {},
|
||||||
containerSize: CGSize(width: 120.0, height: 100.0)
|
containerSize: CGSize(width: 120.0, height: 100.0)
|
||||||
)
|
)
|
||||||
if let topBalanceView = self.topBalanceView.view {
|
|
||||||
if topBalanceView.superview == nil {
|
let topBalanceValueSize = self.topBalanceValueView.update(
|
||||||
topBalanceView.alpha = 0.0
|
transition: .immediate,
|
||||||
self.addSubview(topBalanceView)
|
component: AnyComponent(MultilineTextComponent(
|
||||||
|
text: .plain(NSAttributedString(
|
||||||
|
string: presentationStringsFormattedNumber(Int32(self.starsState?.balance ?? 0), environment.dateTimeFormat.decimalSeparator),
|
||||||
|
font: Font.semibold(14.0),
|
||||||
|
textColor: environment.theme.actionSheet.primaryTextColor
|
||||||
|
)),
|
||||||
|
horizontalAlignment: .right,
|
||||||
|
maximumNumberOfLines: 1
|
||||||
|
)),
|
||||||
|
environment: {},
|
||||||
|
containerSize: CGSize(width: 120.0, height: 100.0)
|
||||||
|
)
|
||||||
|
let topBalanceIconSize = self.topBalanceIconView.update(
|
||||||
|
transition: .immediate,
|
||||||
|
component: AnyComponent(BundleIconComponent(name: "Premium/Stars/StarSmall", tintColor: nil)),
|
||||||
|
environment: {},
|
||||||
|
containerSize: availableSize
|
||||||
|
)
|
||||||
|
|
||||||
|
let navigationHeight = environment.navigationHeight - environment.statusBarHeight
|
||||||
|
let topBalanceOriginY = environment.statusBarHeight + (navigationHeight - topBalanceTitleSize.height - topBalanceValueSize.height) / 2.0
|
||||||
|
let topBalanceTitleFrame = CGRect(origin: CGPoint(x: availableSize.width - topBalanceTitleSize.width - 16.0, y: topBalanceOriginY), size: topBalanceTitleSize)
|
||||||
|
if let topBalanceTitleView = self.topBalanceTitleView.view {
|
||||||
|
if topBalanceTitleView.superview == nil {
|
||||||
|
topBalanceTitleView.alpha = 0.0
|
||||||
|
self.addSubview(topBalanceTitleView)
|
||||||
}
|
}
|
||||||
starTransition.setFrame(view: topBalanceView, frame: CGRect(origin: CGPoint(x: availableSize.width - topBalanceSize.width - 16.0, y: 56.0), size: topBalanceSize))
|
starTransition.setFrame(view: topBalanceTitleView, frame: topBalanceTitleFrame)
|
||||||
|
}
|
||||||
|
|
||||||
|
let topBalanceValueFrame = CGRect(origin: CGPoint(x: availableSize.width - topBalanceValueSize.width - 16.0, y: topBalanceTitleFrame.maxY), size: topBalanceValueSize)
|
||||||
|
if let topBalanceValueView = self.topBalanceValueView.view {
|
||||||
|
if topBalanceValueView.superview == nil {
|
||||||
|
topBalanceValueView.alpha = 0.0
|
||||||
|
self.addSubview(topBalanceValueView)
|
||||||
|
}
|
||||||
|
starTransition.setFrame(view: topBalanceValueView, frame: topBalanceValueFrame)
|
||||||
|
}
|
||||||
|
|
||||||
|
let topBalanceIconFrame = CGRect(origin: CGPoint(x: topBalanceValueFrame.minX - topBalanceIconSize.width - 2.0, y: floorToScreenPixels(topBalanceValueFrame.midY - topBalanceIconSize.height / 2.0) - UIScreenPixel), size: topBalanceIconSize)
|
||||||
|
if let topBalanceIconView = self.topBalanceIconView.view {
|
||||||
|
if topBalanceIconView.superview == nil {
|
||||||
|
topBalanceIconView.alpha = 0.0
|
||||||
|
self.addSubview(topBalanceIconView)
|
||||||
|
}
|
||||||
|
starTransition.setFrame(view: topBalanceIconView, frame: topBalanceIconFrame)
|
||||||
}
|
}
|
||||||
|
|
||||||
contentHeight += 181.0
|
contentHeight += 181.0
|
||||||
|
|||||||
@ -262,11 +262,12 @@ private final class SheetContent: CombinedComponent {
|
|||||||
contentSize.height += 28.0
|
contentSize.height += 28.0
|
||||||
|
|
||||||
if state.cachedChevronImage == nil || state.cachedChevronImage?.1 !== theme {
|
if state.cachedChevronImage == nil || state.cachedChevronImage?.1 !== theme {
|
||||||
state.cachedChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Premium/Stars/Star"), color: UIColor(rgb: 0xf09903))!, theme)
|
state.cachedChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Premium/Stars/StarLarge"), color: UIColor(rgb: 0xf09903))!, theme)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let balanceValue = presentationStringsFormattedNumber(Int32(state.balance ?? 0), environment.dateTimeFormat.decimalSeparator)
|
||||||
let balanceAttributedString = NSMutableAttributedString(string: strings.Stars_Transfer_Balance, font: Font.regular(14.0), textColor: textColor)
|
let balanceAttributedString = NSMutableAttributedString(string: strings.Stars_Transfer_Balance, font: Font.regular(14.0), textColor: textColor)
|
||||||
balanceAttributedString.append(NSMutableAttributedString(string: "\n # \(state.balance ?? 0)", font: Font.semibold(16.0), textColor: textColor))
|
balanceAttributedString.append(NSMutableAttributedString(string: "\n # \(balanceValue)", font: Font.semibold(16.0), textColor: textColor))
|
||||||
if let range = balanceAttributedString.string.range(of: "#"), let chevronImage = state.cachedChevronImage?.0 {
|
if let range = balanceAttributedString.string.range(of: "#"), let chevronImage = state.cachedChevronImage?.0 {
|
||||||
balanceAttributedString.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: balanceAttributedString.string))
|
balanceAttributedString.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: balanceAttributedString.string))
|
||||||
balanceAttributedString.addAttribute(.foregroundColor, value: UIColor(rgb: 0xf09903), range: NSRange(range, in: balanceAttributedString.string))
|
balanceAttributedString.addAttribute(.foregroundColor, value: UIColor(rgb: 0xf09903), range: NSRange(range, in: balanceAttributedString.string))
|
||||||
@ -336,7 +337,7 @@ private final class SheetContent: CombinedComponent {
|
|||||||
let resultController = UndoOverlayController(
|
let resultController = UndoOverlayController(
|
||||||
presentationData: presentationData,
|
presentationData: presentationData,
|
||||||
content: .image(
|
content: .image(
|
||||||
image: UIImage(bundleImageName: "Premium/Stars/Star")!,
|
image: UIImage(bundleImageName: "Premium/Stars/StarLarge")!,
|
||||||
title: presentationData.strings.Stars_Transfer_PurchasedTitle,
|
title: presentationData.strings.Stars_Transfer_PurchasedTitle,
|
||||||
text: presentationData.strings.Stars_Transfer_PurchasedText(invoice.title, botTitle, presentationData.strings.Stars_Transfer_Purchased_Stars(Int32(invoice.totalAmount))).string,
|
text: presentationData.strings.Stars_Transfer_PurchasedText(invoice.title, botTitle, presentationData.strings.Stars_Transfer_Purchased_Stars(Int32(invoice.totalAmount))).string,
|
||||||
round: false,
|
round: false,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "transactionstar_20 (2).pdf",
|
"filename" : "balancestar_48 (2).pdf",
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
Binary file not shown.
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "balancestar_48 (2).pdf",
|
"filename" : "Star20.pdf",
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
BIN
submodules/TelegramUI/Images.xcassets/Premium/Stars/StarLarge.imageset/Star20.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Premium/Stars/StarLarge.imageset/Star20.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Premium/Stars/StarMedium.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Premium/Stars/StarMedium.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "star_18.pdf",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
submodules/TelegramUI/Images.xcassets/Premium/Stars/StarMedium.imageset/star_18.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Premium/Stars/StarMedium.imageset/star_18.pdf
vendored
Normal file
Binary file not shown.
12
submodules/TelegramUI/Images.xcassets/Premium/Stars/StarSmall.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Premium/Stars/StarSmall.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "star_16 (2).pdf",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
submodules/TelegramUI/Images.xcassets/Premium/Stars/StarSmall.imageset/star_16 (2).pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Premium/Stars/StarSmall.imageset/star_16 (2).pdf
vendored
Normal file
Binary file not shown.
@ -191,7 +191,7 @@ private enum CreateChannelEntry: ItemListNodeEntry {
|
|||||||
let arguments = arguments as! CreateChannelArguments
|
let arguments = arguments as! CreateChannelArguments
|
||||||
switch self {
|
switch self {
|
||||||
case let .channelInfo(_, _, dateTimeFormat, peer, state, avatar):
|
case let .channelInfo(_, _, dateTimeFormat, peer, state, avatar):
|
||||||
return ItemListAvatarAndNameInfoItem(accountContext: arguments.context, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .editSettings, peer: peer.flatMap(EnginePeer.init), presence: nil, memberCount: nil, state: state, sectionId: ItemListSectionId(self.section), style: .blocks(withTopInset: false, withExtendedBottomInset: false), editingNameUpdated: { editingName in
|
return ItemListAvatarAndNameInfoItem(itemContext: .accountContext(arguments.context), presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .editSettings, peer: peer.flatMap(EnginePeer.init), presence: nil, memberCount: nil, state: state, sectionId: ItemListSectionId(self.section), style: .blocks(withTopInset: false, withExtendedBottomInset: false), editingNameUpdated: { editingName in
|
||||||
arguments.updateEditingName(editingName)
|
arguments.updateEditingName(editingName)
|
||||||
}, editingNameCompleted: {
|
}, editingNameCompleted: {
|
||||||
arguments.focusOnDescription()
|
arguments.focusOnDescription()
|
||||||
|
|||||||
@ -318,7 +318,7 @@ private enum CreateGroupEntry: ItemListNodeEntry {
|
|||||||
let arguments = arguments as! CreateGroupArguments
|
let arguments = arguments as! CreateGroupArguments
|
||||||
switch self {
|
switch self {
|
||||||
case let .groupInfo(_, _, dateTimeFormat, peer, state, avatar):
|
case let .groupInfo(_, _, dateTimeFormat, peer, state, avatar):
|
||||||
return ItemListAvatarAndNameInfoItem(accountContext: arguments.context, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .editSettings, peer: peer.flatMap(EnginePeer.init), presence: nil, memberCount: nil, state: state, sectionId: ItemListSectionId(self.section), style: .blocks(withTopInset: false, withExtendedBottomInset: false), editingNameUpdated: { editingName in
|
return ItemListAvatarAndNameInfoItem(itemContext: .accountContext(arguments.context), presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .editSettings, peer: peer.flatMap(EnginePeer.init), presence: nil, memberCount: nil, state: state, sectionId: ItemListSectionId(self.section), style: .blocks(withTopInset: false, withExtendedBottomInset: false), editingNameUpdated: { editingName in
|
||||||
arguments.updateEditingName(editingName)
|
arguments.updateEditingName(editingName)
|
||||||
}, editingNameCompleted: {
|
}, editingNameCompleted: {
|
||||||
arguments.done()
|
arguments.done()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user