mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Support Dynamic Type
This commit is contained in:
parent
0f081f9ac3
commit
eaa8bcb08e
@ -3063,7 +3063,6 @@ Unused sets are archived when you add more.";
|
||||
|
||||
"Settings.Appearance" = "Appearance";
|
||||
"Appearance.Title" = "Appearance";
|
||||
"Appearance.TextSize" = "TEXT SIZE";
|
||||
"Appearance.Preview" = "CHAT PREVIEW";
|
||||
"Appearance.ColorTheme" = "COLOR THEME";
|
||||
"Appearance.ThemeDayClassic" = "Day Classic";
|
||||
@ -5115,3 +5114,9 @@ Any member of this group will be able to see messages in the channel.";
|
||||
|
||||
"Theme.Colors.ColorWallpaperWarning" = "Are you sure you want to change your chat wallpaper to a color?";
|
||||
"Theme.Colors.ColorWallpaperWarningProceed" = "Proceed";
|
||||
|
||||
"Appearance.TextSizeSetting" = "Text Size";
|
||||
"Appearance.TextSize.Automatic" = "System";
|
||||
"Appearance.TextSize.Title" = "Text Size";
|
||||
"Appearance.TextSize.UseSystem" = "User System Text Size";
|
||||
"Appearance.TextSize.Apply" = "Set";
|
||||
|
@ -162,7 +162,7 @@ enum BotCheckoutEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! BotCheckoutControllerArguments
|
||||
switch self {
|
||||
case let .header(theme, invoice, botName):
|
||||
@ -170,27 +170,27 @@ enum BotCheckoutEntry: ItemListNodeEntry {
|
||||
case let .price(_, theme, text, value, isFinal):
|
||||
return BotCheckoutPriceItem(theme: theme, title: text, label: value, isFinal: isFinal, sectionId: self.section)
|
||||
case let .paymentMethod(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
arguments.openPaymentMethod()
|
||||
})
|
||||
case let .shippingInfo(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
arguments.openInfo(.address(.street1))
|
||||
})
|
||||
case let .shippingMethod(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
arguments.openShippingMethod()
|
||||
})
|
||||
case let .nameInfo(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
arguments.openInfo(.name)
|
||||
})
|
||||
case let .emailInfo(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
arguments.openInfo(.email)
|
||||
})
|
||||
case let .phoneInfo(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
arguments.openInfo(.phone)
|
||||
})
|
||||
}
|
||||
@ -418,12 +418,12 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz
|
||||
openShippingMethodImpl?()
|
||||
})
|
||||
|
||||
let signal: Signal<(PresentationTheme, (ItemListNodeState, Any)), NoError> = combineLatest(context.sharedContext.presentationData, self.state.get(), paymentFormAndInfo.get(), context.account.postbox.loadedPeerWithId(messageId.peerId))
|
||||
|> map { presentationData, state, paymentFormAndInfo, botPeer -> (PresentationTheme, (ItemListNodeState, Any)) in
|
||||
let nodeState = ItemListNodeState(entries: botCheckoutControllerEntries(presentationData: presentationData, state: state, invoice: invoice, paymentForm: paymentFormAndInfo?.0, formInfo: paymentFormAndInfo?.1, validatedFormInfo: paymentFormAndInfo?.2, currentShippingOptionId: paymentFormAndInfo?.3, currentPaymentMethod: paymentFormAndInfo?.4, botPeer: botPeer), style: .plain, focusItemTag: nil, emptyStateItem: nil, animateChanges: false)
|
||||
|
||||
return (presentationData.theme, (nodeState, arguments))
|
||||
}
|
||||
let signal: Signal<(ItemListPresentationData, (ItemListNodeState, Any)), NoError> = combineLatest(context.sharedContext.presentationData, self.state.get(), paymentFormAndInfo.get(), context.account.postbox.loadedPeerWithId(messageId.peerId))
|
||||
|> map { presentationData, state, paymentFormAndInfo, botPeer -> (ItemListPresentationData, (ItemListNodeState, Any)) in
|
||||
let nodeState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: botCheckoutControllerEntries(presentationData: presentationData, state: state, invoice: invoice, paymentForm: paymentFormAndInfo?.0, formInfo: paymentFormAndInfo?.1, validatedFormInfo: paymentFormAndInfo?.2, currentShippingOptionId: paymentFormAndInfo?.3, currentPaymentMethod: paymentFormAndInfo?.4, botPeer: botPeer), style: .plain, focusItemTag: nil, emptyStateItem: nil, animateChanges: false)
|
||||
|
||||
return (ItemListPresentationData(presentationData), (nodeState, arguments))
|
||||
}
|
||||
|
||||
self.actionButton = BotCheckoutActionButton(inactiveFillColor: self.presentationData.theme.list.plainBackgroundColor, activeFillColor: self.presentationData.theme.list.itemAccentColor, foregroundColor: self.presentationData.theme.list.itemCheckColors.foregroundColor)
|
||||
self.actionButton.setState(.loading)
|
||||
|
@ -303,7 +303,7 @@ private final class BotCheckoutPasswordAlertContentNode: AlertContentNode {
|
||||
func botCheckoutPasswordEntryController(context: AccountContext, strings: PresentationStrings, cartTitle: String, period: Int32, requiresBiometrics: Bool, completion: @escaping (TemporaryTwoStepPasswordToken) -> Void) -> AlertController {
|
||||
var dismissImpl: (() -> Void)?
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let controller = AlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), contentNode: BotCheckoutPasswordAlertContentNode(context: context, theme: presentationData.theme, strings: strings, cardTitle: cartTitle, period: period, requiresBiometrics: requiresBiometrics, cancel: {
|
||||
let controller = AlertController(theme: AlertControllerTheme(presentationData: presentationData), contentNode: BotCheckoutPasswordAlertContentNode(context: context, theme: presentationData.theme, strings: strings, cardTitle: cartTitle, period: period, requiresBiometrics: requiresBiometrics, cancel: {
|
||||
dismissImpl?()
|
||||
}, completion: { token in
|
||||
completion(token)
|
||||
|
@ -149,7 +149,7 @@ enum BotReceiptEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! BotReceiptControllerArguments
|
||||
switch self {
|
||||
case let .header(theme, invoice, botName):
|
||||
@ -157,17 +157,17 @@ enum BotReceiptEntry: ItemListNodeEntry {
|
||||
case let .price(_, theme, text, value, isFinal):
|
||||
return BotCheckoutPriceItem(theme: theme, title: text, label: value, isFinal: isFinal, sectionId: self.section)
|
||||
case let .paymentMethod(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: nil)
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: nil)
|
||||
case let .shippingInfo(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: nil)
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: nil)
|
||||
case let .shippingMethod(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: nil)
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: nil)
|
||||
case let .nameInfo(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: nil)
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: nil)
|
||||
case let .emailInfo(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: nil)
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: nil)
|
||||
case let .phoneInfo(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: nil)
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none, action: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -275,11 +275,11 @@ final class BotReceiptControllerNode: ItemListControllerNode {
|
||||
|
||||
let arguments = BotReceiptControllerArguments(account: context.account)
|
||||
|
||||
let signal: Signal<(PresentationTheme, (ItemListNodeState, Any)), NoError> = combineLatest(context.sharedContext.presentationData, receiptData.get(), context.account.postbox.loadedPeerWithId(messageId.peerId))
|
||||
|> map { presentationData, receiptData, botPeer -> (PresentationTheme, (ItemListNodeState, Any)) in
|
||||
let nodeState = ItemListNodeState(entries: botReceiptControllerEntries(presentationData: presentationData, invoice: invoice, formInvoice: receiptData?.0, formInfo: receiptData?.1, shippingOption: receiptData?.2, paymentMethodTitle: receiptData?.3, botPeer: botPeer), style: .plain, focusItemTag: nil, emptyStateItem: nil, animateChanges: false)
|
||||
|
||||
return (presentationData.theme, (nodeState, arguments))
|
||||
let signal: Signal<(ItemListPresentationData, (ItemListNodeState, Any)), NoError> = combineLatest(context.sharedContext.presentationData, receiptData.get(), context.account.postbox.loadedPeerWithId(messageId.peerId))
|
||||
|> map { presentationData, receiptData, botPeer -> (ItemListPresentationData, (ItemListNodeState, Any)) in
|
||||
let nodeState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: botReceiptControllerEntries(presentationData: presentationData, invoice: invoice, formInvoice: receiptData?.0, formInfo: receiptData?.1, shippingOption: receiptData?.2, paymentMethodTitle: receiptData?.3, botPeer: botPeer), style: .plain, focusItemTag: nil, emptyStateItem: nil, animateChanges: false)
|
||||
|
||||
return (ItemListPresentationData(presentationData), (nodeState, arguments))
|
||||
}
|
||||
|
||||
self.actionButton = BotCheckoutActionButton(inactiveFillColor: self.presentationData.theme.list.plainBackgroundColor, activeFillColor: self.presentationData.theme.list.itemAccentColor, foregroundColor: self.presentationData.theme.list.plainBackgroundColor)
|
||||
|
@ -12,10 +12,6 @@ import PresentationDataUtils
|
||||
import AvatarNode
|
||||
import TelegramStringFormatting
|
||||
|
||||
private let titleFont = Font.regular(17.0)
|
||||
private let statusFont = Font.regular(14.0)
|
||||
private let dateFont = Font.regular(15.0)
|
||||
|
||||
private func callDurationString(strings: PresentationStrings, duration: Int32) -> String {
|
||||
if duration < 60 {
|
||||
return strings.Call_ShortSeconds(duration)
|
||||
@ -67,8 +63,7 @@ private func callListNeighbors(item: ListViewItem, topItem: ListViewItem?, botto
|
||||
}
|
||||
|
||||
class CallListCallItem: ListViewItem {
|
||||
let theme: PresentationTheme
|
||||
let strings: PresentationStrings
|
||||
let presentationData: ItemListPresentationData
|
||||
let dateTimeFormat: PresentationDateTimeFormat
|
||||
let account: Account
|
||||
let style: ItemListStyle
|
||||
@ -82,9 +77,8 @@ class CallListCallItem: ListViewItem {
|
||||
let headerAccessoryItem: ListViewAccessoryItem?
|
||||
let header: ListViewItemHeader?
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, account: Account, style: ItemListStyle, topMessage: Message, messages: [Message], editing: Bool, revealed: Bool, interaction: CallListNodeInteraction) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
init(presentationData: ItemListPresentationData, dateTimeFormat: PresentationDateTimeFormat, account: Account, style: ItemListStyle, topMessage: Message, messages: [Message], editing: Bool, revealed: Bool, interaction: CallListNodeInteraction) {
|
||||
self.presentationData = presentationData
|
||||
self.dateTimeFormat = dateTimeFormat
|
||||
self.account = account
|
||||
self.style = style
|
||||
@ -301,18 +295,22 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
||||
var updatedTheme: PresentationTheme?
|
||||
var updatedInfoIcon = false
|
||||
|
||||
if currentItem?.theme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
|
||||
updatedInfoIcon = true
|
||||
}
|
||||
|
||||
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
let statusFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 14.0 / 17.0))
|
||||
let dateFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 15.0 / 17.0))
|
||||
|
||||
let editingOffset: CGFloat
|
||||
var editableControlSizeAndApply: (CGSize, () -> ItemListEditableControlNode)?
|
||||
var editableControlSizeAndApply: (CGFloat, (CGFloat) -> ItemListEditableControlNode)?
|
||||
if item.editing {
|
||||
let sizeAndApply = editableControlLayout(50.0, item.theme, false)
|
||||
let sizeAndApply = editableControlLayout(item.presentationData.theme, false)
|
||||
editableControlSizeAndApply = sizeAndApply
|
||||
editingOffset = sizeAndApply.0.width
|
||||
editingOffset = sizeAndApply.0
|
||||
} else {
|
||||
editingOffset = 0.0
|
||||
}
|
||||
@ -328,12 +326,12 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
switch item.style {
|
||||
case .plain:
|
||||
itemBackgroundColor = item.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.theme.list.itemPlainSeparatorColor
|
||||
itemBackgroundColor = item.presentationData.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
insets = itemListNeighborsPlainInsets(neighbors)
|
||||
case .blocks:
|
||||
itemBackgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
itemSeparatorColor = item.theme.list.itemBlocksSeparatorColor
|
||||
itemBackgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
insets = itemListNeighborsGroupedInsets(neighbors)
|
||||
}
|
||||
|
||||
@ -347,7 +345,7 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
||||
var titleAttributedString: NSAttributedString?
|
||||
var statusAttributedString: NSAttributedString?
|
||||
|
||||
var titleColor = item.theme.list.itemPrimaryTextColor
|
||||
var titleColor = item.presentationData.theme.list.itemPrimaryTextColor
|
||||
var hasMissed = false
|
||||
var hasIncoming = false
|
||||
var hasOutgoing = false
|
||||
@ -363,7 +361,7 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
||||
hasIncoming = true
|
||||
|
||||
if let discardReason = discardReason, case .missed = discardReason {
|
||||
titleColor = item.theme.list.itemDestructiveColor
|
||||
titleColor = item.presentationData.theme.list.itemDestructiveColor
|
||||
hasMissed = true
|
||||
}
|
||||
} else {
|
||||
@ -397,7 +395,7 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
||||
} else if let lastName = user.lastName, !lastName.isEmpty {
|
||||
titleAttributedString = NSAttributedString(string: lastName, font: titleFont, textColor: titleColor)
|
||||
} else {
|
||||
titleAttributedString = NSAttributedString(string: item.strings.User_DeletedAccount, font: titleFont, textColor: titleColor)
|
||||
titleAttributedString = NSAttributedString(string: item.presentationData.strings.User_DeletedAccount, font: titleFont, textColor: titleColor)
|
||||
}
|
||||
} else if let group = peer as? TelegramGroup {
|
||||
titleAttributedString = NSAttributedString(string: group.title, font: titleFont, textColor: titleColor)
|
||||
@ -406,20 +404,20 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
|
||||
if hasMissed {
|
||||
statusAttributedString = NSAttributedString(string: item.strings.Notification_CallMissedShort, font: statusFont, textColor: item.theme.list.itemSecondaryTextColor)
|
||||
statusAttributedString = NSAttributedString(string: item.presentationData.strings.Notification_CallMissedShort, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
} else if hasIncoming && hasOutgoing {
|
||||
statusAttributedString = NSAttributedString(string: item.strings.Notification_CallOutgoingShort + ", " + item.strings.Notification_CallIncomingShort, font: statusFont, textColor: item.theme.list.itemSecondaryTextColor)
|
||||
statusAttributedString = NSAttributedString(string: item.presentationData.strings.Notification_CallOutgoingShort + ", " + item.presentationData.strings.Notification_CallIncomingShort, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
} else if hasIncoming {
|
||||
if let callDuration = callDuration, callDuration != 0 {
|
||||
statusAttributedString = NSAttributedString(string: item.strings.Notification_CallTimeFormat(item.strings.Notification_CallIncomingShort, callDurationString(strings: item.strings, duration: callDuration)).0, font: statusFont, textColor: item.theme.list.itemSecondaryTextColor)
|
||||
statusAttributedString = NSAttributedString(string: item.presentationData.strings.Notification_CallTimeFormat(item.presentationData.strings.Notification_CallIncomingShort, callDurationString(strings: item.presentationData.strings, duration: callDuration)).0, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
} else {
|
||||
statusAttributedString = NSAttributedString(string: item.strings.Notification_CallIncomingShort, font: statusFont, textColor: item.theme.list.itemSecondaryTextColor)
|
||||
statusAttributedString = NSAttributedString(string: item.presentationData.strings.Notification_CallIncomingShort, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
}
|
||||
} else {
|
||||
if let callDuration = callDuration, callDuration != 0 {
|
||||
statusAttributedString = NSAttributedString(string: item.strings.Notification_CallTimeFormat(item.strings.Notification_CallOutgoingShort, callDurationString(strings: item.strings, duration: callDuration)).0, font: statusFont, textColor: item.theme.list.itemSecondaryTextColor)
|
||||
statusAttributedString = NSAttributedString(string: item.presentationData.strings.Notification_CallTimeFormat(item.presentationData.strings.Notification_CallOutgoingShort, callDurationString(strings: item.presentationData.strings, duration: callDuration)).0, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
} else {
|
||||
statusAttributedString = NSAttributedString(string: item.strings.Notification_CallOutgoingShort, font: statusFont, textColor: item.theme.list.itemSecondaryTextColor)
|
||||
statusAttributedString = NSAttributedString(string: item.presentationData.strings.Notification_CallOutgoingShort, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -429,18 +427,21 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
||||
localtime_r(&t, &timeinfo)
|
||||
|
||||
let timestamp = Int32(CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970)
|
||||
let dateText = stringForRelativeTimestamp(strings: item.strings, relativeTimestamp: item.topMessage.timestamp, relativeTo: timestamp, dateTimeFormat: item.dateTimeFormat)
|
||||
let dateText = stringForRelativeTimestamp(strings: item.presentationData.strings, relativeTimestamp: item.topMessage.timestamp, relativeTo: timestamp, dateTimeFormat: item.dateTimeFormat)
|
||||
|
||||
let (dateLayout, dateApply) = makeDateLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: dateText, font: dateFont, textColor: item.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: max(0.0, params.width - leftInset - rightInset), height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let (dateLayout, dateApply) = makeDateLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: dateText, font: dateFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: max(0.0, params.width - leftInset - rightInset), height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: max(0.0, params.width - leftInset - dateRightInset - dateLayout.size.width - (item.editing ? -30.0 : 10.0)), height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let (statusLayout, statusApply) = makeStatusLayout(TextNodeLayoutArguments(attributedString: statusAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: max(0.0, params.width - leftInset - rightInset), height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let nodeLayout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: 50.0), insets: UIEdgeInsets(top: firstWithHeader ? 29.0 : 0.0, left: 0.0, bottom: 0.0, right: 0.0))
|
||||
let titleSpacing: CGFloat = -1.0
|
||||
let verticalInset: CGFloat = 6.0
|
||||
|
||||
let outgoingIcon = PresentationResourcesCallList.outgoingIcon(item.theme)
|
||||
let infoIcon = PresentationResourcesCallList.infoButton(item.theme)
|
||||
let nodeLayout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: titleLayout.size.height + titleSpacing + statusLayout.size.height + verticalInset * 2.0), insets: UIEdgeInsets(top: firstWithHeader ? 29.0 : 0.0, left: 0.0, bottom: 0.0, right: 0.0))
|
||||
|
||||
let outgoingIcon = PresentationResourcesCallList.outgoingIcon(item.presentationData.theme)
|
||||
let infoIcon = PresentationResourcesCallList.infoButton(item.presentationData.theme)
|
||||
|
||||
let contentSize = nodeLayout.contentSize
|
||||
|
||||
@ -451,7 +452,7 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
||||
if peer.isDeleted {
|
||||
overrideImage = .deletedIcon
|
||||
}
|
||||
strongSelf.avatarNode.setPeer(account: item.account, theme: item.theme, peer: peer, overrideImage: overrideImage, emptyColor: item.theme.list.mediaPlaceholderColor)
|
||||
strongSelf.avatarNode.setPeer(account: item.account, theme: item.presentationData.theme, peer: peer, overrideImage: overrideImage, emptyColor: item.presentationData.theme.list.mediaPlaceholderColor)
|
||||
}
|
||||
|
||||
return (strongSelf.avatarNode.ready, { [weak strongSelf] animated in
|
||||
@ -471,7 +472,7 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.topStripeNode.backgroundColor = itemSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = itemSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = itemBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.theme.list.itemHighlightedBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
}
|
||||
|
||||
switch item.style {
|
||||
@ -519,9 +520,9 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
|
||||
if let editableControlSizeAndApply = editableControlSizeAndApply {
|
||||
let editableControlFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset, y: 0.0), size: editableControlSizeAndApply.0)
|
||||
let editableControlFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset, y: 0.0), size: CGSize(width: editableControlSizeAndApply.0, height: nodeLayout.contentSize.height))
|
||||
if strongSelf.editableControlNode == nil {
|
||||
let editableControlNode = editableControlSizeAndApply.1()
|
||||
let editableControlNode = editableControlSizeAndApply.1(nodeLayout.contentSize.height)
|
||||
editableControlNode.tapped = {
|
||||
if let strongSelf = self {
|
||||
strongSelf.setRevealOptionsOpened(true, animated: true)
|
||||
@ -547,13 +548,13 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
||||
})
|
||||
}
|
||||
|
||||
transition.updateFrameAdditive(node: strongSelf.avatarNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset - 52.0, y: 5.0), size: CGSize(width: 40.0, height: 40.0)))
|
||||
transition.updateFrameAdditive(node: strongSelf.avatarNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset - 52.0, y: floor((contentSize.height - 40.0) / 2.0)), size: CGSize(width: 40.0, height: 40.0)))
|
||||
|
||||
let _ = titleApply()
|
||||
transition.updateFrameAdditive(node: strongSelf.titleNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset, y: 6.0), size: titleLayout.size))
|
||||
transition.updateFrameAdditive(node: strongSelf.titleNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset, y: verticalInset), size: titleLayout.size))
|
||||
|
||||
let _ = statusApply()
|
||||
transition.updateFrameAdditive(node: strongSelf.statusNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset, y: 27.0), size: statusLayout.size))
|
||||
transition.updateFrameAdditive(node: strongSelf.statusNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset, y: strongSelf.titleNode.frame.maxY + titleSpacing), size: statusLayout.size))
|
||||
|
||||
let _ = dateApply()
|
||||
transition.updateFrameAdditive(node: strongSelf.dateNode, frame: CGRect(origin: CGPoint(x: editingOffset + revealOffset + params.width - dateRightInset - dateLayout.size.width, y: floor((nodeLayout.contentSize.height - dateLayout.size.height) / 2.0) + 2.0), size: dateLayout.size))
|
||||
@ -585,11 +586,11 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.accessibilityArea.accessibilityValue = statusAttributedString?.string
|
||||
strongSelf.accessibilityArea.frame = CGRect(origin: CGPoint(), size: nodeLayout.contentSize)
|
||||
|
||||
strongSelf.infoButtonNode.accessibilityLabel = item.strings.Conversation_Info
|
||||
strongSelf.infoButtonNode.accessibilityLabel = item.presentationData.strings.Conversation_Info
|
||||
|
||||
strongSelf.view.accessibilityCustomActions = [UIAccessibilityCustomAction(name: item.strings.Common_Delete, target: strongSelf, selector: #selector(strongSelf.performLocalAccessibilityCustomAction(_:)))]
|
||||
strongSelf.view.accessibilityCustomActions = [UIAccessibilityCustomAction(name: item.presentationData.strings.Common_Delete, target: strongSelf, selector: #selector(strongSelf.performLocalAccessibilityCustomAction(_:)))]
|
||||
|
||||
strongSelf.setRevealOptions((left: [], right: [ItemListRevealOption(key: 0, title: item.strings.Common_Delete, icon: .none, color: item.theme.list.itemDisclosureActions.destructive.fillColor, textColor: item.theme.list.itemDisclosureActions.destructive.foregroundColor)]))
|
||||
strongSelf.setRevealOptions((left: [], right: [ItemListRevealOption(key: 0, title: item.presentationData.strings.Common_Delete, icon: .none, color: item.presentationData.theme.list.itemDisclosureActions.destructive.fillColor, textColor: item.presentationData.theme.list.itemDisclosureActions.destructive.foregroundColor)]))
|
||||
strongSelf.setRevealOptionsOpened(item.revealed, animated: animated)
|
||||
}
|
||||
})
|
||||
@ -667,9 +668,9 @@ class CallListCallItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
transition.updateFrameAdditive(node: self.avatarNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset - 52.0, y: 5.0), size: CGSize(width: 40.0, height: 40.0)))
|
||||
|
||||
transition.updateFrameAdditive(node: self.titleNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset, y: 6.0), size: self.titleNode.bounds.size))
|
||||
transition.updateFrameAdditive(node: self.titleNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset, y: self.titleNode.frame.minY), size: self.titleNode.bounds.size))
|
||||
|
||||
transition.updateFrameAdditive(node: self.statusNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset, y: 27.0), size: self.statusNode.bounds.size))
|
||||
transition.updateFrameAdditive(node: self.statusNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset, y: self.statusNode.frame.minY), size: self.statusNode.bounds.size))
|
||||
|
||||
transition.updateFrameAdditive(node: self.dateNode, frame: CGRect(origin: CGPoint(x: editingOffset + revealOffset + self.bounds.size.width - dateRightInset - self.dateNode.bounds.size.width, y: self.dateNode.frame.minY), size: self.dateNode.bounds.size))
|
||||
|
||||
|
@ -113,42 +113,42 @@ struct CallListNodeState: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
private func mappedInsertEntries(account: Account, showSettings: Bool, nodeInteraction: CallListNodeInteraction, entries: [CallListNodeViewTransitionInsertEntry]) -> [ListViewInsertItem] {
|
||||
private func mappedInsertEntries(account: Account, presentationData: ItemListPresentationData, showSettings: Bool, nodeInteraction: CallListNodeInteraction, entries: [CallListNodeViewTransitionInsertEntry]) -> [ListViewInsertItem] {
|
||||
return entries.map { entry -> ListViewInsertItem in
|
||||
switch entry.entry {
|
||||
case let .displayTab(theme, text, value):
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ItemListSwitchItem(theme: theme, title: text, value: value, enabled: true, sectionId: 0, style: .blocks, updated: { value in
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enabled: true, sectionId: 0, style: .blocks, updated: { value in
|
||||
nodeInteraction.updateShowCallsTab(value)
|
||||
}), directionHint: entry.directionHint)
|
||||
case let .displayTabInfo(theme, text):
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ItemListTextItem(theme: theme, text: .plain(text), sectionId: 0), directionHint: entry.directionHint)
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: 0), directionHint: entry.directionHint)
|
||||
case let .messageEntry(topMessage, messages, theme, strings, dateTimeFormat, editing, hasActiveRevealControls):
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: CallListCallItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, account: account, style: showSettings ? .blocks : .plain, topMessage: topMessage, messages: messages, editing: editing, revealed: hasActiveRevealControls, interaction: nodeInteraction), directionHint: entry.directionHint)
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: CallListCallItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, account: account, style: showSettings ? .blocks : .plain, topMessage: topMessage, messages: messages, editing: editing, revealed: hasActiveRevealControls, interaction: nodeInteraction), directionHint: entry.directionHint)
|
||||
case let .holeEntry(_, theme):
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: CallListHoleItem(theme: theme), directionHint: entry.directionHint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func mappedUpdateEntries(account: Account, showSettings: Bool, nodeInteraction: CallListNodeInteraction, entries: [CallListNodeViewTransitionUpdateEntry]) -> [ListViewUpdateItem] {
|
||||
private func mappedUpdateEntries(account: Account, presentationData: ItemListPresentationData, showSettings: Bool, nodeInteraction: CallListNodeInteraction, entries: [CallListNodeViewTransitionUpdateEntry]) -> [ListViewUpdateItem] {
|
||||
return entries.map { entry -> ListViewUpdateItem in
|
||||
switch entry.entry {
|
||||
case let .displayTab(theme, text, value):
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ItemListSwitchItem(theme: theme, title: text, value: value, enabled: true, sectionId: 0, style: .blocks, updated: { value in
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enabled: true, sectionId: 0, style: .blocks, updated: { value in
|
||||
nodeInteraction.updateShowCallsTab(value)
|
||||
}), directionHint: entry.directionHint)
|
||||
case let .displayTabInfo(theme, text):
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ItemListTextItem(theme: theme, text: .plain(text), sectionId: 0), directionHint: entry.directionHint)
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: 0), directionHint: entry.directionHint)
|
||||
case let .messageEntry(topMessage, messages, theme, strings, dateTimeFormat, editing, hasActiveRevealControls):
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: CallListCallItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, account: account, style: showSettings ? .blocks : .plain, topMessage: topMessage, messages: messages, editing: editing, revealed: hasActiveRevealControls, interaction: nodeInteraction), directionHint: entry.directionHint)
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: CallListCallItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, account: account, style: showSettings ? .blocks : .plain, topMessage: topMessage, messages: messages, editing: editing, revealed: hasActiveRevealControls, interaction: nodeInteraction), directionHint: entry.directionHint)
|
||||
case let .holeEntry(_, theme):
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: CallListHoleItem(theme: theme), directionHint: entry.directionHint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func mappedCallListNodeViewListTransition(account: Account, showSettings: Bool, nodeInteraction: CallListNodeInteraction, transition: CallListNodeViewTransition) -> CallListNodeListViewTransition {
|
||||
return CallListNodeListViewTransition(callListView: transition.callListView, deleteItems: transition.deleteItems, insertItems: mappedInsertEntries(account: account, showSettings: showSettings, nodeInteraction: nodeInteraction, entries: transition.insertEntries), updateItems: mappedUpdateEntries(account: account, showSettings: showSettings, nodeInteraction: nodeInteraction, entries: transition.updateEntries), options: transition.options, scrollToItem: transition.scrollToItem, stationaryItemRange: transition.stationaryItemRange)
|
||||
private func mappedCallListNodeViewListTransition(account: Account, presentationData: ItemListPresentationData, showSettings: Bool, nodeInteraction: CallListNodeInteraction, transition: CallListNodeViewTransition) -> CallListNodeListViewTransition {
|
||||
return CallListNodeListViewTransition(callListView: transition.callListView, deleteItems: transition.deleteItems, insertItems: mappedInsertEntries(account: account, presentationData: presentationData, showSettings: showSettings, nodeInteraction: nodeInteraction, entries: transition.insertEntries), updateItems: mappedUpdateEntries(account: account, presentationData: presentationData, showSettings: showSettings, nodeInteraction: nodeInteraction, entries: transition.updateEntries), options: transition.options, scrollToItem: transition.scrollToItem, stationaryItemRange: transition.stationaryItemRange)
|
||||
}
|
||||
|
||||
private final class CallListOpaqueTransactionState {
|
||||
@ -343,7 +343,7 @@ final class CallListControllerNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
return preparedCallListNodeViewTransition(from: previous, to: processedView, reason: reason, disableAnimations: false, account: context.account, scrollPosition: update.scrollPosition)
|
||||
|> map({ mappedCallListNodeViewListTransition(account: context.account, showSettings: showSettings, nodeInteraction: nodeInteraction, transition: $0) })
|
||||
|> map({ mappedCallListNodeViewListTransition(account: context.account, presentationData: ItemListPresentationData(presentationData), showSettings: showSettings, nodeInteraction: nodeInteraction, transition: $0) })
|
||||
|> runOn(prepareOnMainQueue ? Queue.mainQueue() : viewProcessingQueue)
|
||||
}
|
||||
|
||||
|
@ -1491,7 +1491,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
])
|
||||
strongSelf.present(actionSheet, in: .window(.root))
|
||||
} else {
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: strongSelf.presentationData.strings.ChatList_DeleteSavedMessagesConfirmationTitle, text: strongSelf.presentationData.strings.ChatList_DeleteSavedMessagesConfirmationText, actions: [
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: strongSelf.presentationData.strings.ChatList_DeleteSavedMessagesConfirmationTitle, text: strongSelf.presentationData.strings.ChatList_DeleteSavedMessagesConfirmationText, actions: [
|
||||
TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {
|
||||
}),
|
||||
TextAlertAction(type: .destructiveAction, title: strongSelf.presentationData.strings.ChatList_DeleteSavedMessagesConfirmationAction, action: {
|
||||
@ -1565,7 +1565,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: strongSelf.presentationData.strings.ChatList_DeleteForEveryoneConfirmationTitle, text: strongSelf.presentationData.strings.ChatList_DeleteForEveryoneConfirmationText, actions: [
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: strongSelf.presentationData.strings.ChatList_DeleteForEveryoneConfirmationTitle, text: strongSelf.presentationData.strings.ChatList_DeleteForEveryoneConfirmationText, actions: [
|
||||
TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {
|
||||
completion(false)
|
||||
}),
|
||||
@ -1596,7 +1596,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController,
|
||||
])
|
||||
self.present(actionSheet, in: .window(.root))
|
||||
} else if peer.peerId == self.context.account.peerId {
|
||||
self.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: self.presentationData.theme), title: self.presentationData.strings.ChatList_DeleteSavedMessagesConfirmationTitle, text: self.presentationData.strings.ChatList_DeleteSavedMessagesConfirmationText, actions: [
|
||||
self.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: self.presentationData), title: self.presentationData.strings.ChatList_DeleteSavedMessagesConfirmationTitle, text: self.presentationData.strings.ChatList_DeleteSavedMessagesConfirmationText, actions: [
|
||||
TextAlertAction(type: .genericAction, title: self.presentationData.strings.Common_Cancel, action: {
|
||||
completion(false)
|
||||
}),
|
||||
|
@ -77,7 +77,7 @@ final class ChatListControllerNode: ASDisplayNode {
|
||||
self.groupId = groupId
|
||||
self.presentationData = presentationData
|
||||
|
||||
self.chatListNode = ChatListNode(context: context, groupId: groupId, controlsHistoryPreload: controlsHistoryPreload, mode: .chatList, theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)
|
||||
self.chatListNode = ChatListNode(context: context, groupId: groupId, controlsHistoryPreload: controlsHistoryPreload, mode: .chatList, theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)
|
||||
|
||||
self.controller = controller
|
||||
|
||||
@ -151,7 +151,7 @@ final class ChatListControllerNode: ASDisplayNode {
|
||||
|
||||
self.backgroundColor = self.presentationData.theme.chatList.backgroundColor
|
||||
|
||||
self.chatListNode.updateThemeAndStrings(theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations)
|
||||
self.chatListNode.updateThemeAndStrings(theme: self.presentationData.theme, fontSize: self.presentationData.fontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations)
|
||||
self.searchDisplayController?.updatePresentationData(presentationData)
|
||||
self.chatListEmptyNode?.updateThemeAndStrings(theme: self.presentationData.theme, strings: self.presentationData.strings)
|
||||
|
||||
|
@ -16,6 +16,7 @@ import ChatListSearchItemHeader
|
||||
import ContactListUI
|
||||
import ContextUI
|
||||
import PhoneNumberFormat
|
||||
import ItemListUI
|
||||
|
||||
private enum ChatListRecentEntryStableId: Hashable {
|
||||
case topPeers
|
||||
@ -80,7 +81,7 @@ private enum ChatListRecentEntry: Comparable, Identifiable {
|
||||
}
|
||||
}
|
||||
|
||||
func item(context: AccountContext, filter: ChatListNodePeersFilter, peerSelected: @escaping (Peer) -> Void, peerContextAction: ((Peer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?, clearRecentlySearchedPeers: @escaping () -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, deletePeer: @escaping (PeerId) -> Void) -> ListViewItem {
|
||||
func item(context: AccountContext, presentationData: ChatListPresentationData, filter: ChatListNodePeersFilter, peerSelected: @escaping (Peer) -> Void, peerContextAction: ((Peer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?, clearRecentlySearchedPeers: @escaping () -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, deletePeer: @escaping (PeerId) -> Void) -> ListViewItem {
|
||||
switch self {
|
||||
case let .topPeers(peers, theme, strings):
|
||||
return ChatListRecentPeersListItem(theme: theme, strings: strings, account: context.account, peers: peers, peerSelected: { peer in
|
||||
@ -174,7 +175,7 @@ private enum ChatListRecentEntry: Comparable, Identifiable {
|
||||
badge = ContactsPeerItemBadge(count: peer.unreadCount, type: isMuted ? .inactive : .active)
|
||||
}
|
||||
|
||||
return ContactsPeerItem(theme: theme, strings: strings, sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: context.account, peerMode: .generalSearch, peer: .peer(peer: primaryPeer, chatPeer: chatPeer), status: status, badge: badge, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: true, editing: false, revealed: hasRevealControls), index: nil, header: ChatListSearchItemHeader(type: .recentPeers, theme: theme, strings: strings, actionTitle: strings.WebSearch_RecentSectionClear, action: {
|
||||
return ContactsPeerItem(presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: context.account, peerMode: .generalSearch, peer: .peer(peer: primaryPeer, chatPeer: chatPeer), status: status, badge: badge, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: true, editing: false, revealed: hasRevealControls), index: nil, header: ChatListSearchItemHeader(type: .recentPeers, theme: theme, strings: strings, actionTitle: strings.WebSearch_RecentSectionClear, action: {
|
||||
clearRecentlySearchedPeers()
|
||||
}), action: { _ in
|
||||
if let chatPeer = peer.peer.peers[peer.peer.peerId] {
|
||||
@ -329,7 +330,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
||||
}
|
||||
}
|
||||
|
||||
public func item(context: AccountContext, enableHeaders: Bool, filter: ChatListNodePeersFilter, interaction: ChatListNodeInteraction, peerContextAction: ((Peer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?) -> ListViewItem {
|
||||
public func item(context: AccountContext, presentationData: PresentationData, enableHeaders: Bool, filter: ChatListNodePeersFilter, interaction: ChatListNodeInteraction, peerContextAction: ((Peer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?) -> ListViewItem {
|
||||
switch self {
|
||||
case let .localPeer(peer, associatedPeer, unreadBadge, _, theme, strings, nameSortOrder, nameDisplayOrder):
|
||||
let primaryPeer: Peer
|
||||
@ -383,7 +384,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
||||
header = ChatListSearchItemHeader(type: .localPeers, theme: theme, strings: strings, actionTitle: nil, action: nil)
|
||||
}
|
||||
|
||||
return ContactsPeerItem(theme: theme, strings: strings, sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: context.account, peerMode: .generalSearch, peer: .peer(peer: primaryPeer, chatPeer: chatPeer), status: .none, badge: badge, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in
|
||||
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: context.account, peerMode: .generalSearch, peer: .peer(peer: primaryPeer, chatPeer: chatPeer), status: .none, badge: badge, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in
|
||||
interaction.peerSelected(peer)
|
||||
}, contextAction: peerContextAction.flatMap { peerContextAction in
|
||||
return { node, gesture in
|
||||
@ -435,7 +436,7 @@ public enum ChatListSearchEntry: Comparable, Identifiable {
|
||||
header = ChatListSearchItemHeader(type: .globalPeers, theme: theme, strings: strings, actionTitle: nil, action: nil)
|
||||
}
|
||||
|
||||
return ContactsPeerItem(theme: theme, strings: strings, sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: context.account, peerMode: .generalSearch, peer: .peer(peer: peer.peer, chatPeer: peer.peer), status: .addressName(suffixString), badge: badge, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in
|
||||
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: context.account, peerMode: .generalSearch, peer: .peer(peer: peer.peer, chatPeer: peer.peer), status: .addressName(suffixString), badge: badge, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in
|
||||
interaction.peerSelected(peer.peer)
|
||||
}, contextAction: peerContextAction.flatMap { peerContextAction in
|
||||
return { node, gesture in
|
||||
@ -472,22 +473,22 @@ public struct ChatListSearchContainerTransition {
|
||||
}
|
||||
}
|
||||
|
||||
private func chatListSearchContainerPreparedRecentTransition(from fromEntries: [ChatListRecentEntry], to toEntries: [ChatListRecentEntry], context: AccountContext, filter: ChatListNodePeersFilter, peerSelected: @escaping (Peer) -> Void, peerContextAction: ((Peer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?, clearRecentlySearchedPeers: @escaping () -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, deletePeer: @escaping (PeerId) -> Void) -> ChatListSearchContainerRecentTransition {
|
||||
private func chatListSearchContainerPreparedRecentTransition(from fromEntries: [ChatListRecentEntry], to toEntries: [ChatListRecentEntry], context: AccountContext, presentationData: ChatListPresentationData, filter: ChatListNodePeersFilter, peerSelected: @escaping (Peer) -> Void, peerContextAction: ((Peer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?, clearRecentlySearchedPeers: @escaping () -> Void, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, deletePeer: @escaping (PeerId) -> Void) -> ChatListSearchContainerRecentTransition {
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
|
||||
|
||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, filter: filter, peerSelected: peerSelected, peerContextAction: peerContextAction, clearRecentlySearchedPeers: clearRecentlySearchedPeers, setPeerIdWithRevealedOptions: setPeerIdWithRevealedOptions, deletePeer: deletePeer), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, filter: filter, peerSelected: peerSelected, peerContextAction: peerContextAction, clearRecentlySearchedPeers: clearRecentlySearchedPeers, setPeerIdWithRevealedOptions: setPeerIdWithRevealedOptions, deletePeer: deletePeer), directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, filter: filter, peerSelected: peerSelected, peerContextAction: peerContextAction, clearRecentlySearchedPeers: clearRecentlySearchedPeers, setPeerIdWithRevealedOptions: setPeerIdWithRevealedOptions, deletePeer: deletePeer), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, filter: filter, peerSelected: peerSelected, peerContextAction: peerContextAction, clearRecentlySearchedPeers: clearRecentlySearchedPeers, setPeerIdWithRevealedOptions: setPeerIdWithRevealedOptions, deletePeer: deletePeer), directionHint: nil) }
|
||||
|
||||
return ChatListSearchContainerRecentTransition(deletions: deletions, insertions: insertions, updates: updates)
|
||||
}
|
||||
|
||||
public func chatListSearchContainerPreparedTransition(from fromEntries: [ChatListSearchEntry], to toEntries: [ChatListSearchEntry], displayingResults: Bool, context: AccountContext, enableHeaders: Bool, filter: ChatListNodePeersFilter, interaction: ChatListNodeInteraction, peerContextAction: ((Peer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?) -> ChatListSearchContainerTransition {
|
||||
public func chatListSearchContainerPreparedTransition(from fromEntries: [ChatListSearchEntry], to toEntries: [ChatListSearchEntry], displayingResults: Bool, context: AccountContext, presentationData: PresentationData, enableHeaders: Bool, filter: ChatListNodePeersFilter, interaction: ChatListNodeInteraction, peerContextAction: ((Peer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?) -> ChatListSearchContainerTransition {
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
|
||||
|
||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, enableHeaders: enableHeaders, filter: filter, interaction: interaction, peerContextAction: peerContextAction), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, enableHeaders: enableHeaders, filter: filter, interaction: interaction, peerContextAction: peerContextAction), directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, enableHeaders: enableHeaders, filter: filter, interaction: interaction, peerContextAction: peerContextAction), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context, presentationData: presentationData, enableHeaders: enableHeaders, filter: filter, interaction: interaction, peerContextAction: peerContextAction), directionHint: nil) }
|
||||
|
||||
return ChatListSearchContainerTransition(deletions: deletions, insertions: insertions, updates: updates, displayingResults: displayingResults)
|
||||
}
|
||||
@ -585,7 +586,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
self.dimNode = ASDisplayNode()
|
||||
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.presentationDataPromise = Promise(ChatListPresentationData(theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations))
|
||||
self.presentationDataPromise = Promise(ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.fontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations))
|
||||
|
||||
self.recentListNode = ListView()
|
||||
self.recentListNode.verticalScrollIndicatorColor = self.presentationData.theme.list.scrollIndicatorColor
|
||||
@ -970,13 +971,16 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
|
||||
self.updatedRecentPeersDisposable.set(managedUpdatedRecentPeers(accountPeerId: context.account.peerId, postbox: context.account.postbox, network: context.account.network).start())
|
||||
|
||||
self.recentDisposable.set((recentItems
|
||||
|> deliverOnMainQueue).start(next: { [weak self] entries in
|
||||
self.recentDisposable.set((combineLatest(queue: .mainQueue(),
|
||||
presentationDataPromise.get(),
|
||||
recentItems
|
||||
)
|
||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData, entries in
|
||||
if let strongSelf = self {
|
||||
let previousEntries = previousRecentItems.swap(entries)
|
||||
|
||||
let firstTime = previousEntries == nil
|
||||
let transition = chatListSearchContainerPreparedRecentTransition(from: previousEntries ?? [], to: entries, context: context, filter: filter, peerSelected: { peer in
|
||||
let transition = chatListSearchContainerPreparedRecentTransition(from: previousEntries ?? [], to: entries, context: context, presentationData: presentationData, filter: filter, peerSelected: { peer in
|
||||
openPeer(peer, true)
|
||||
let _ = addRecentlySearchedPeer(postbox: context.account.postbox, peerId: peer.id).start()
|
||||
self?.recentListNode.clearHighlightAnimated(true)
|
||||
@ -1002,7 +1006,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
let previousEntries = previousSearchItems.swap(entriesAndFlags?.0)
|
||||
|
||||
let firstTime = previousEntries == nil
|
||||
let transition = chatListSearchContainerPreparedTransition(from: previousEntries ?? [], to: entriesAndFlags?.0 ?? [], displayingResults: entriesAndFlags?.0 != nil, context: context, enableHeaders: true, filter: filter, interaction: interaction, peerContextAction: peerContextAction)
|
||||
let transition = chatListSearchContainerPreparedTransition(from: previousEntries ?? [], to: entriesAndFlags?.0 ?? [], displayingResults: entriesAndFlags?.0 != nil, context: context, presentationData: strongSelf.presentationData, enableHeaders: true, filter: filter, interaction: interaction, peerContextAction: peerContextAction)
|
||||
strongSelf.enqueueTransition(transition, firstTime: firstTime)
|
||||
}
|
||||
}))
|
||||
@ -1012,7 +1016,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo
|
||||
if let strongSelf = self {
|
||||
let previousTheme = strongSelf.presentationData.theme
|
||||
strongSelf.presentationData = presentationData
|
||||
strongSelf.presentationDataPromise.set(.single(ChatListPresentationData(theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)))
|
||||
strongSelf.presentationDataPromise.set(.single(ChatListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: presentationData.disableAnimations)))
|
||||
|
||||
if previousTheme !== presentationData.theme {
|
||||
strongSelf.updateTheme(theme: presentationData.theme)
|
||||
|
@ -163,11 +163,6 @@ public class ChatListItem: ListViewItem, ChatListSearchItemNeighbour {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.medium(16.0)
|
||||
private let textFont = Font.regular(15.0)
|
||||
private let dateFont = Font.regular(14.0)
|
||||
private let badgeFont = Font.regular(14.0)
|
||||
|
||||
private let pinIcon = ItemListRevealOptionIcon.animation(animation: "anim_pin", scale: 0.33333, offset: 0.0, keysToColor: nil, flip: false)
|
||||
private let unpinIcon = ItemListRevealOptionIcon.animation(animation: "anim_unpin", scale: 0.33333, offset: 0.0, keysToColor: ["un Outlines.Group 1.Stroke 1"], flip: false)
|
||||
private let muteIcon = ItemListRevealOptionIcon.animation(animation: "anim_mute", scale: 0.33333, offset: 0.0, keysToColor: ["un Outlines.Group 1.Stroke 1"], flip: false)
|
||||
@ -197,8 +192,6 @@ private enum RevealOptionKey: Int32 {
|
||||
case unhide
|
||||
}
|
||||
|
||||
private let itemHeight: CGFloat = 76.0
|
||||
|
||||
private func canArchivePeer(id: PeerId, accountPeerId: PeerId) -> Bool {
|
||||
if id.namespace == Namespaces.Peer.CloudUser && id.id == 777000 {
|
||||
return false
|
||||
@ -653,6 +646,11 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
let currentChatListSearchResult = self.cachedChatListSearchResult
|
||||
|
||||
return { item, params, first, last, firstWithHeader, nextIsPinned in
|
||||
let titleFont = Font.medium(floor(item.presentationData.fontSize.itemListBaseFontSize * 16.0 / 17.0))
|
||||
let textFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 15.0 / 17.0))
|
||||
let dateFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 14.0 / 17.0))
|
||||
let badgeFont = Font.regular(14.0)
|
||||
|
||||
let account = item.context.account
|
||||
var message: Message?
|
||||
enum ContentPeer {
|
||||
@ -749,7 +747,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
var currentSecretIconImage: UIImage?
|
||||
|
||||
var selectableControlSizeAndApply: (CGFloat, (CGSize, Bool) -> ItemListSelectableControlNode)?
|
||||
var reorderControlSizeAndApply: (CGSize, (Bool) -> ItemListEditableReorderControlNode)?
|
||||
var reorderControlSizeAndApply: (CGFloat, (CGFloat, Bool) -> ItemListEditableReorderControlNode)?
|
||||
|
||||
let editingOffset: CGFloat
|
||||
var reorderInset: CGFloat = 0.0
|
||||
@ -761,9 +759,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
editingOffset = sizeAndApply.0
|
||||
|
||||
if item.index.pinningIndex != nil && !isAd && !isPeerGroup {
|
||||
let sizeAndApply = reorderControlLayout(itemHeight, item.presentationData.theme)
|
||||
let sizeAndApply = reorderControlLayout(item.presentationData.theme)
|
||||
reorderControlSizeAndApply = sizeAndApply
|
||||
reorderInset = sizeAndApply.0.width
|
||||
reorderInset = sizeAndApply.0
|
||||
}
|
||||
} else {
|
||||
editingOffset = 0.0
|
||||
@ -1076,13 +1074,14 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
let layoutOffset: CGFloat = 0.0
|
||||
|
||||
let rawContentRect = CGRect(origin: CGPoint(x: 2.0, y: layoutOffset + 8.0), size: CGSize(width: params.width - leftInset - params.rightInset - 10.0 - 1.0 - editingOffset, height: itemHeight - 12.0 - 9.0))
|
||||
let rawContentOriginX = 2.0
|
||||
let rawContentWidth = params.width - leftInset - params.rightInset - 10.0
|
||||
|
||||
let (dateLayout, dateApply) = dateLayout(TextNodeLayoutArguments(attributedString: dateAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: rawContentRect.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let (dateLayout, dateApply) = dateLayout(TextNodeLayoutArguments(attributedString: dateAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: rawContentWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let (badgeLayout, badgeApply) = badgeLayout(CGSize(width: rawContentRect.width, height: CGFloat.greatestFiniteMagnitude), currentBadgeBackgroundImage, badgeContent)
|
||||
let (badgeLayout, badgeApply) = badgeLayout(CGSize(width: rawContentWidth, height: CGFloat.greatestFiniteMagnitude), currentBadgeBackgroundImage, badgeContent)
|
||||
|
||||
let (mentionBadgeLayout, mentionBadgeApply) = mentionBadgeLayout(CGSize(width: rawContentRect.width, height: CGFloat.greatestFiniteMagnitude), currentMentionBadgeImage, mentionBadgeContent)
|
||||
let (mentionBadgeLayout, mentionBadgeApply) = mentionBadgeLayout(CGSize(width: rawContentWidth, height: CGFloat.greatestFiniteMagnitude), currentMentionBadgeImage, mentionBadgeContent)
|
||||
|
||||
var badgeSize: CGFloat = 0.0
|
||||
if !badgeLayout.width.isZero {
|
||||
@ -1106,21 +1105,21 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
badgeSize = max(badgeSize, reorderInset)
|
||||
|
||||
let (authorLayout, authorApply) = authorLayout(TextNodeLayoutArguments(attributedString: hideAuthor ? nil : authorAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: rawContentRect.width - badgeSize, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets(top: 2.0, left: 1.0, bottom: 2.0, right: 1.0)))
|
||||
let (authorLayout, authorApply) = authorLayout(TextNodeLayoutArguments(attributedString: hideAuthor ? nil : authorAttributedString, backgroundColor: nil, minimumNumberOfLines: 1, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: rawContentWidth - badgeSize, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets(top: 2.0, left: 1.0, bottom: 2.0, right: 1.0)))
|
||||
|
||||
var textCutout: TextNodeCutout?
|
||||
if !textLeftCutout.isZero {
|
||||
textCutout = TextNodeCutout(topLeft: CGSize(width: textLeftCutout, height: 4.0), topRight: nil, bottomRight: nil)
|
||||
}
|
||||
let (textLayout, textApply) = textLayout(TextNodeLayoutArguments(attributedString: textAttributedString, backgroundColor: nil, maximumNumberOfLines: authorAttributedString == nil ? 2 : 1, truncationType: .end, constrainedSize: CGSize(width: rawContentRect.width - badgeSize, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: textCutout, insets: UIEdgeInsets(top: 2.0, left: 1.0, bottom: 2.0, right: 1.0)))
|
||||
let (textLayout, textApply) = textLayout(TextNodeLayoutArguments(attributedString: textAttributedString, backgroundColor: nil, minimumNumberOfLines: authorAttributedString == nil ? 2 : 1, maximumNumberOfLines: authorAttributedString == nil ? 2 : 1, truncationType: .end, constrainedSize: CGSize(width: rawContentWidth - badgeSize, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: textCutout, insets: UIEdgeInsets(top: 2.0, left: 1.0, bottom: 2.0, right: 1.0)))
|
||||
|
||||
let titleRect = CGRect(origin: rawContentRect.origin, size: CGSize(width: rawContentRect.width - dateLayout.size.width - 10.0 - statusWidth - titleIconsWidth, height: rawContentRect.height))
|
||||
let (titleLayout, titleApply) = titleLayout(TextNodeLayoutArguments(attributedString: titleAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: titleRect.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let titleRectWidth = rawContentWidth - dateLayout.size.width - 10.0 - statusWidth - titleIconsWidth
|
||||
let (titleLayout, titleApply) = titleLayout(TextNodeLayoutArguments(attributedString: titleAttributedString, backgroundColor: nil, minimumNumberOfLines: 1, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: titleRectWidth, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
var inputActivitiesSize: CGSize?
|
||||
var inputActivitiesApply: (() -> Void)?
|
||||
if let inputActivities = inputActivities, !inputActivities.isEmpty {
|
||||
let (size, apply) = inputActivitiesLayout(CGSize(width: rawContentRect.width - badgeSize, height: 40.0), item.presentationData.strings, item.presentationData.theme.chatList.messageTextColor, item.index.messageIndex.id.peerId, inputActivities)
|
||||
let (size, apply) = inputActivitiesLayout(CGSize(width: rawContentWidth - badgeSize, height: 40.0), item.presentationData.strings, item.presentationData.theme.chatList.messageTextColor, item.index.messageIndex.id.peerId, inputActivities)
|
||||
inputActivitiesSize = size
|
||||
inputActivitiesApply = apply
|
||||
}
|
||||
@ -1178,6 +1177,18 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
animateContent = true
|
||||
}
|
||||
|
||||
let titleSpacing: CGFloat = -1.0
|
||||
let authorSpacing: CGFloat = -3.0
|
||||
var itemHeight: CGFloat = 8.0 * 2.0 + titleLayout.size.height + titleSpacing
|
||||
if authorLayout.size.height.isZero {
|
||||
itemHeight += textLayout.size.height
|
||||
} else {
|
||||
itemHeight += authorLayout.size.height
|
||||
itemHeight += authorSpacing + textLayout.size.height
|
||||
}
|
||||
|
||||
let rawContentRect = CGRect(origin: CGPoint(x: 2.0, y: layoutOffset + 8.0), size: CGSize(width: rawContentWidth, height: itemHeight - 12.0 - 9.0))
|
||||
|
||||
let insets = ChatListItemNode.insets(first: first, last: last, firstWithHeader: firstWithHeader)
|
||||
var heightOffset: CGFloat = 0.0
|
||||
if item.hiddenOffset {
|
||||
@ -1282,9 +1293,9 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
var animateBadges = animateContent
|
||||
if let reorderControlSizeAndApply = reorderControlSizeAndApply {
|
||||
let reorderControlFrame = CGRect(origin: CGPoint(x: params.width + revealOffset - params.rightInset - reorderControlSizeAndApply.0.width, y: layoutOffset), size: reorderControlSizeAndApply.0)
|
||||
let reorderControlFrame = CGRect(origin: CGPoint(x: params.width + revealOffset - params.rightInset - reorderControlSizeAndApply.0, y: layoutOffset), size: CGSize(width: reorderControlSizeAndApply.0, height: layout.contentSize.height))
|
||||
if strongSelf.reorderControlNode == nil {
|
||||
let reorderControlNode = reorderControlSizeAndApply.1(false)
|
||||
let reorderControlNode = reorderControlSizeAndApply.1(layout.contentSize.height, false)
|
||||
strongSelf.reorderControlNode = reorderControlNode
|
||||
strongSelf.addSubnode(reorderControlNode)
|
||||
reorderControlNode.frame = reorderControlFrame
|
||||
@ -1297,7 +1308,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
transition.updateAlpha(node: strongSelf.pinnedIconNode, alpha: 0.0)
|
||||
transition.updateAlpha(node: strongSelf.statusNode, alpha: 0.0)
|
||||
} else if let reorderControlNode = strongSelf.reorderControlNode {
|
||||
let _ = reorderControlSizeAndApply.1(false)
|
||||
let _ = reorderControlSizeAndApply.1(layout.contentSize.height, false)
|
||||
transition.updateFrame(node: reorderControlNode, frame: reorderControlFrame)
|
||||
}
|
||||
} else if let reorderControlNode = strongSelf.reorderControlNode {
|
||||
@ -1313,7 +1324,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
transition.updateAlpha(node: strongSelf.statusNode, alpha: 1.0)
|
||||
}
|
||||
|
||||
let avatarFrame = CGRect(origin: CGPoint(x: leftInset - 78.0 + editingOffset + 10.0 + revealOffset, y: layoutOffset + 7.0), size: CGSize(width: 60.0, height: 60.0))
|
||||
let avatarFrame = CGRect(origin: CGPoint(x: leftInset - 78.0 + editingOffset + 10.0 + revealOffset, y: floor((layout.contentSize.height - 60.0) / 2.0)), size: CGSize(width: 60.0, height: 60.0))
|
||||
transition.updateFrame(node: strongSelf.avatarNode, frame: avatarFrame)
|
||||
|
||||
let onlineFrame = CGRect(origin: CGPoint(x: avatarFrame.maxX - onlineLayout.width - 2.0, y: avatarFrame.maxY - onlineLayout.height - 2.0), size: onlineLayout)
|
||||
@ -1611,7 +1622,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
let leftInset: CGFloat = params.leftInset + 78.0
|
||||
|
||||
let rawContentRect = CGRect(origin: CGPoint(x: 2.0, y: layoutOffset + 8.0), size: CGSize(width: params.width - leftInset - params.rightInset - 10.0 - 1.0 - editingOffset, height: itemHeight - 12.0 - 9.0))
|
||||
let rawContentRect = CGRect(origin: CGPoint(x: 2.0, y: layoutOffset + 8.0), size: CGSize(width: params.width - leftInset - params.rightInset - 10.0 - 1.0 - editingOffset, height: self.bounds.size.height - 12.0 - 9.0))
|
||||
|
||||
let contentRect = rawContentRect.offsetBy(dx: editingOffset + leftInset + offset, dy: 0.0)
|
||||
|
||||
@ -1806,7 +1817,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
if let item = self.item {
|
||||
if case .groupReference = item.content {
|
||||
self.layer.sublayerTransform = CATransform3DMakeTranslation(0.0, currentValue - itemHeight, 0.0)
|
||||
self.layer.sublayerTransform = CATransform3DMakeTranslation(0.0, currentValue - self.bounds.size.height, 0.0)
|
||||
} else {
|
||||
var separatorFrame = self.separatorNode.frame
|
||||
separatorFrame.origin.y = currentValue - UIScreenPixel
|
||||
|
@ -12,6 +12,7 @@ import AccountContext
|
||||
import TelegramNotices
|
||||
import ContactsPeerItem
|
||||
import ContextUI
|
||||
import ItemListUI
|
||||
|
||||
public enum ChatListNodeMode {
|
||||
case chatList
|
||||
@ -202,7 +203,7 @@ private func mappedInsertEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
}
|
||||
}
|
||||
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ContactsPeerItem(theme: presentationData.theme, strings: presentationData.strings, sortOrder: presentationData.nameSortOrder, displayOrder: presentationData.nameDisplayOrder, account: context.account, peerMode: .generalSearch, peer: .peer(peer: itemPeer, chatPeer: chatPeer), status: .none, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: nil, action: { _ in
|
||||
return ListViewInsertItem(index: entry.index, previousIndex: entry.previousIndex, item: ContactsPeerItem(presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings), sortOrder: presentationData.nameSortOrder, displayOrder: presentationData.nameDisplayOrder, account: context.account, peerMode: .generalSearch, peer: .peer(peer: itemPeer, chatPeer: chatPeer), status: .none, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: nil, action: { _ in
|
||||
if let chatPeer = chatPeer {
|
||||
nodeInteraction.peerSelected(chatPeer)
|
||||
}
|
||||
@ -241,7 +242,7 @@ private func mappedUpdateEntries(context: AccountContext, nodeInteraction: ChatL
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ContactsPeerItem(theme: presentationData.theme, strings: presentationData.strings, sortOrder: presentationData.nameSortOrder, displayOrder: presentationData.nameDisplayOrder, account: context.account, peerMode: .generalSearch, peer: .peer(peer: itemPeer, chatPeer: chatPeer), status: .none, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: nil, action: { _ in
|
||||
return ListViewUpdateItem(index: entry.index, previousIndex: entry.previousIndex, item: ContactsPeerItem(presentationData: ItemListPresentationData(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings), sortOrder: presentationData.nameSortOrder, displayOrder: presentationData.nameDisplayOrder, account: context.account, peerMode: .generalSearch, peer: .peer(peer: itemPeer, chatPeer: chatPeer), status: .none, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: nil, action: { _ in
|
||||
if let chatPeer = chatPeer {
|
||||
nodeInteraction.peerSelected(chatPeer)
|
||||
}
|
||||
@ -378,13 +379,13 @@ public final class ChatListNode: ListView {
|
||||
|
||||
private var hapticFeedback: HapticFeedback?
|
||||
|
||||
public init(context: AccountContext, groupId: PeerGroupId, controlsHistoryPreload: Bool, mode: ChatListNodeMode, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, disableAnimations: Bool) {
|
||||
public init(context: AccountContext, groupId: PeerGroupId, controlsHistoryPreload: Bool, mode: ChatListNodeMode, theme: PresentationTheme, fontSize: PresentationFontSize, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, disableAnimations: Bool) {
|
||||
self.context = context
|
||||
self.groupId = groupId
|
||||
self.controlsHistoryPreload = controlsHistoryPreload
|
||||
self.mode = mode
|
||||
|
||||
self.currentState = ChatListNodeState(presentationData: ChatListPresentationData(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, disableAnimations: disableAnimations), editing: false, peerIdWithRevealedOptions: nil, selectedPeerIds: Set(), peerInputActivities: nil, pendingRemovalPeerIds: Set(), pendingClearHistoryPeerIds: Set(), archiveShouldBeTemporaryRevealed: false)
|
||||
self.currentState = ChatListNodeState(presentationData: ChatListPresentationData(theme: theme, fontSize: fontSize, strings: strings, dateTimeFormat: dateTimeFormat, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, disableAnimations: disableAnimations), editing: false, peerIdWithRevealedOptions: nil, selectedPeerIds: Set(), peerInputActivities: nil, pendingRemovalPeerIds: Set(), pendingClearHistoryPeerIds: Set(), archiveShouldBeTemporaryRevealed: false)
|
||||
self.statePromise = ValuePromise(self.currentState, ignoreRepeated: true)
|
||||
|
||||
self.theme = theme
|
||||
@ -1070,7 +1071,7 @@ public final class ChatListNode: ListView {
|
||||
self.activityStatusesDisposable?.dispose()
|
||||
}
|
||||
|
||||
public func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, disableAnimations: Bool) {
|
||||
public func updateThemeAndStrings(theme: PresentationTheme, fontSize: PresentationFontSize, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, disableAnimations: Bool) {
|
||||
if theme !== self.currentState.presentationData.theme || strings !== self.currentState.presentationData.strings || dateTimeFormat != self.currentState.presentationData.dateTimeFormat || disableAnimations != self.currentState.presentationData.disableAnimations {
|
||||
self.theme = theme
|
||||
if self.keepTopItemOverscrollBackground != nil {
|
||||
@ -1080,7 +1081,7 @@ public final class ChatListNode: ListView {
|
||||
|
||||
self.updateState { state in
|
||||
var state = state
|
||||
state.presentationData = ChatListPresentationData(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, disableAnimations: disableAnimations)
|
||||
state.presentationData = ChatListPresentationData(theme: theme, fontSize: fontSize, strings: strings, dateTimeFormat: dateTimeFormat, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, disableAnimations: disableAnimations)
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
@ -5,14 +5,16 @@ import TelegramUIPreferences
|
||||
|
||||
public final class ChatListPresentationData {
|
||||
public let theme: PresentationTheme
|
||||
public let fontSize: PresentationFontSize
|
||||
public let strings: PresentationStrings
|
||||
public let dateTimeFormat: PresentationDateTimeFormat
|
||||
public let nameSortOrder: PresentationPersonNameOrder
|
||||
public let nameDisplayOrder: PresentationPersonNameOrder
|
||||
public let disableAnimations: Bool
|
||||
|
||||
public init(theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, disableAnimations: Bool) {
|
||||
public init(theme: PresentationTheme, fontSize: PresentationFontSize, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, disableAnimations: Bool) {
|
||||
self.theme = theme
|
||||
self.fontSize = fontSize
|
||||
self.strings = strings
|
||||
self.dateTimeFormat = dateTimeFormat
|
||||
self.nameSortOrder = nameSortOrder
|
||||
|
@ -131,17 +131,17 @@ private enum CreatePollEntry: ItemListNodeEntry {
|
||||
return lhs.sortId < rhs.sortId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! CreatePollControllerArguments
|
||||
switch self {
|
||||
case let .textHeader(theme, text, accessoryText):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, accessoryText: accessoryText, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, accessoryText: accessoryText, sectionId: self.section)
|
||||
case let .text(theme, placeholder, text, maxLength):
|
||||
return ItemListMultilineInputItem(theme: theme, text: text, placeholder: placeholder, maxLength: ItemListMultilineInputItemTextLimit(value: maxLength, display: false), sectionId: self.section, style: .blocks, textUpdated: { value in
|
||||
return ItemListMultilineInputItem(presentationData: presentationData, text: text, placeholder: placeholder, maxLength: ItemListMultilineInputItemTextLimit(value: maxLength, display: false), sectionId: self.section, style: .blocks, textUpdated: { value in
|
||||
arguments.updatePollText(value)
|
||||
}, tag: CreatePollEntryTag.text)
|
||||
case let .optionsHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .option(theme, strings, id, _, placeholder, text, revealed, hasNext):
|
||||
return CreatePollOptionItem(theme: theme, strings: strings, id: id, placeholder: placeholder, value: text, maxLength: maxOptionLength, editing: CreatePollOptionItemEditing(editable: true, hasActiveRevealControls: revealed), sectionId: self.section, setItemIdWithRevealedOptions: { id, fromId in
|
||||
arguments.setItemIdWithRevealedOptions(id, fromId)
|
||||
@ -159,7 +159,7 @@ private enum CreatePollEntry: ItemListNodeEntry {
|
||||
arguments.addOption()
|
||||
})
|
||||
case let .optionsInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -381,8 +381,8 @@ public func createPollController(context: AccountContext, peerId: PeerId, comple
|
||||
ensureVisibleItemTag = focusItemTag
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.CreatePoll_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: createPollControllerEntries(presentationData: presentationData, state: state, limitsConfiguration: limitsConfiguration), style: .blocks, focusItemTag: focusItemTag, ensureVisibleItemTag: ensureVisibleItemTag, animateChanges: previousIds != nil && previousIds != optionIds)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.CreatePoll_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: createPollControllerEntries(presentationData: presentationData, state: state, limitsConfiguration: limitsConfiguration), style: .blocks, focusItemTag: focusItemTag, ensureVisibleItemTag: ensureVisibleItemTag, animateChanges: previousIds != nil && previousIds != optionIds)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -235,8 +235,8 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode,
|
||||
updatedTheme = item.theme
|
||||
}
|
||||
|
||||
let controlSizeAndApply = editableControlLayout(44.0, item.theme, false)
|
||||
let reorderSizeAndApply = reorderControlLayout(44.0, item.theme)
|
||||
let controlSizeAndApply = editableControlLayout(item.theme, false)
|
||||
let reorderSizeAndApply = reorderControlLayout(item.theme)
|
||||
|
||||
let separatorHeight = UIScreenPixel
|
||||
|
||||
@ -370,12 +370,12 @@ class CreatePollOptionItemNode: ItemListRevealOptionsItemNode, ItemListItemNode,
|
||||
strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layout.contentSize.width, height: separatorHeight))
|
||||
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height - UIScreenPixel), size: CGSize(width: layout.contentSize.width - bottomStripeInset, height: separatorHeight))
|
||||
|
||||
let _ = controlSizeAndApply.1()
|
||||
let editableControlFrame = CGRect(origin: CGPoint(x: params.leftInset + 6.0 + revealOffset, y: 0.0), size: controlSizeAndApply.0)
|
||||
let _ = controlSizeAndApply.1(layout.contentSize.height)
|
||||
let editableControlFrame = CGRect(origin: CGPoint(x: params.leftInset + 6.0 + revealOffset, y: 0.0), size: CGSize(width: controlSizeAndApply.0, height: contentSize.height))
|
||||
strongSelf.editableControlNode.frame = editableControlFrame
|
||||
|
||||
let _ = reorderSizeAndApply.1(displayTextLimit && layout.contentSize.height <= 44.0)
|
||||
let reorderControlFrame = CGRect(origin: CGPoint(x: params.width + revealOffset - params.rightInset - reorderSizeAndApply.0.width, y: 0.0), size: reorderSizeAndApply.0)
|
||||
let _ = reorderSizeAndApply.1(layout.contentSize.height, displayTextLimit && layout.contentSize.height <= 44.0)
|
||||
let reorderControlFrame = CGRect(origin: CGPoint(x: params.width + revealOffset - params.rightInset - reorderSizeAndApply.0, y: 0.0), size: CGSize(width: reorderSizeAndApply.0, height: layout.contentSize.height))
|
||||
strongSelf.reorderControlNode.frame = reorderControlFrame
|
||||
|
||||
let _ = textLimitApply()
|
||||
|
@ -15,7 +15,7 @@ public enum ContactListActionItemHighlight {
|
||||
}
|
||||
|
||||
class ContactListActionItem: ListViewItem, ListViewItemWithHeader {
|
||||
let theme: PresentationTheme
|
||||
let presentationData: ItemListPresentationData
|
||||
let title: String
|
||||
let icon: ContactListActionItemIcon
|
||||
let highlight: ContactListActionItemHighlight
|
||||
@ -23,8 +23,8 @@ class ContactListActionItem: ListViewItem, ListViewItemWithHeader {
|
||||
let action: () -> Void
|
||||
let header: ListViewItemHeader?
|
||||
|
||||
init(theme: PresentationTheme, title: String, icon: ContactListActionItemIcon, highlight: ContactListActionItemHighlight = .cell, clearHighlightAutomatically: Bool = true, header: ListViewItemHeader?, action: @escaping () -> Void) {
|
||||
self.theme = theme
|
||||
init(presentationData: ItemListPresentationData, title: String, icon: ContactListActionItemIcon, highlight: ContactListActionItemHighlight = .cell, clearHighlightAutomatically: Bool = true, header: ListViewItemHeader?, action: @escaping () -> Void) {
|
||||
self.presentationData = presentationData
|
||||
self.title = title
|
||||
self.icon = icon
|
||||
self.highlight = highlight
|
||||
@ -110,8 +110,6 @@ class ContactListActionItem: ListViewItem, ListViewItemWithHeader {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.regular(17.0)
|
||||
|
||||
class ContactListActionItemNode: ListViewItemNode {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let topStripeNode: ASDisplayNode
|
||||
@ -123,8 +121,6 @@ class ContactListActionItemNode: ListViewItemNode {
|
||||
|
||||
private let activateArea: AccessibilityAreaNode
|
||||
|
||||
private var theme: PresentationTheme?
|
||||
|
||||
private var item: ContactListActionItem?
|
||||
|
||||
init() {
|
||||
@ -167,23 +163,25 @@ class ContactListActionItemNode: ListViewItemNode {
|
||||
|
||||
func asyncLayout() -> (_ item: ContactListActionItem, _ params: ListViewItemLayoutParams, _ firstWithHeader: Bool, _ last: Bool) -> (ListViewItemNodeLayout, () -> Void) {
|
||||
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||
let currentTheme = self.theme
|
||||
let currentItem = self.item
|
||||
|
||||
return { item, params, firstWithHeader, last in
|
||||
var updatedTheme: PresentationTheme?
|
||||
|
||||
if currentTheme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
}
|
||||
|
||||
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
|
||||
var leftInset: CGFloat = 16.0 + params.leftInset
|
||||
if case .generic = item.icon {
|
||||
leftInset += 49.0
|
||||
}
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: item.theme.list.itemAccentColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - 10.0 - leftInset - params.rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: item.presentationData.theme.list.itemAccentColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - 10.0 - leftInset - params.rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let contentSize = CGSize(width: params.width, height: 50.0)
|
||||
let contentSize = CGSize(width: params.width, height: 12.0 * 2.0 + titleLayout.size.height)
|
||||
let insets = UIEdgeInsets(top: firstWithHeader ? 29.0 : 0.0, left: 0.0, bottom: 0.0, right: 0.0)
|
||||
let separatorHeight = UIScreenPixel
|
||||
|
||||
@ -192,18 +190,17 @@ class ContactListActionItemNode: ListViewItemNode {
|
||||
return (layout, { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.item = item
|
||||
strongSelf.theme = item.theme
|
||||
|
||||
strongSelf.activateArea.accessibilityLabel = item.title
|
||||
strongSelf.activateArea.frame = CGRect(origin: CGPoint(x: params.leftInset, y: 0.0), size: CGSize(width: layout.contentSize.width - params.leftInset - params.rightInset, height: layout.contentSize.height))
|
||||
|
||||
if let _ = updatedTheme {
|
||||
strongSelf.topStripeNode.backgroundColor = item.theme.list.itemPlainSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemPlainSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.theme.list.plainBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.theme.list.itemHighlightedBackgroundColor
|
||||
strongSelf.topStripeNode.backgroundColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.plainBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
|
||||
strongSelf.iconNode.image = generateTintedImage(image: item.icon.image, color: item.theme.list.itemAccentColor)
|
||||
strongSelf.iconNode.image = generateTintedImage(image: item.icon.image, color: item.presentationData.theme.list.itemAccentColor)
|
||||
}
|
||||
|
||||
let _ = titleApply()
|
||||
@ -218,12 +215,12 @@ class ContactListActionItemNode: ListViewItemNode {
|
||||
let iconSpacing: CGFloat = 4.0
|
||||
let totalWidth: CGFloat = titleLayout.size.width + image.size.width + iconSpacing
|
||||
switch position {
|
||||
case .left:
|
||||
iconFrame = CGRect(origin: CGPoint(x: params.leftInset + floor((contentSize.width - params.leftInset - params.rightInset - totalWidth) / 2.0), y: floor((contentSize.height - image.size.height) / 2.0)), size: image.size)
|
||||
titleOffset = iconFrame.minX + iconSpacing
|
||||
case .right:
|
||||
iconFrame = CGRect(origin: CGPoint(x: params.leftInset + floor((contentSize.width - params.leftInset - params.rightInset - totalWidth) / 2.0) + totalWidth - image.size.width, y: floor((contentSize.height - image.size.height) / 2.0)), size: image.size)
|
||||
titleOffset = iconFrame.maxX - totalWidth
|
||||
case .left:
|
||||
iconFrame = CGRect(origin: CGPoint(x: params.leftInset + floor((contentSize.width - params.leftInset - params.rightInset - totalWidth) / 2.0), y: floor((contentSize.height - image.size.height) / 2.0)), size: image.size)
|
||||
titleOffset = iconFrame.minX + iconSpacing
|
||||
case .right:
|
||||
iconFrame = CGRect(origin: CGPoint(x: params.leftInset + floor((contentSize.width - params.leftInset - params.rightInset - totalWidth) / 2.0) + totalWidth - image.size.width, y: floor((contentSize.height - image.size.height) / 2.0)), size: image.size)
|
||||
titleOffset = iconFrame.maxX - totalWidth
|
||||
}
|
||||
default:
|
||||
iconFrame = CGRect(origin: CGPoint(x: params.leftInset + floor((leftInset - params.leftInset - image.size.width) / 2.0) + 3.0, y: floor((contentSize.height - image.size.height) / 2.0)), size: image.size)
|
||||
|
@ -152,9 +152,7 @@ private enum ContactListNodeEntry: Comparable, Identifiable {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
func item(account: Account, interaction: ContactListNodeInteraction) -> ListViewItem {
|
||||
func item(account: Account, presentationData: PresentationData, interaction: ContactListNodeInteraction) -> ListViewItem {
|
||||
switch self {
|
||||
case let .search(theme, strings):
|
||||
return ChatListSearchItem(theme: theme, placeholder: strings.Contacts_SearchLabel, activate: {
|
||||
@ -165,19 +163,19 @@ private enum ContactListNodeEntry: Comparable, Identifiable {
|
||||
if case .presence = sortOrder {
|
||||
text = strings.Contacts_SortedByPresence
|
||||
}
|
||||
return ContactListActionItem(theme: theme, title: text, icon: .inline(dropDownIcon, .right), highlight: .alpha, header: nil, action: {
|
||||
return ContactListActionItem(presentationData: ItemListPresentationData(presentationData), title: text, icon: .inline(dropDownIcon, .right), highlight: .alpha, header: nil, action: {
|
||||
interaction.openSortMenu()
|
||||
})
|
||||
case let .permissionInfo(theme, title, text, suppressed):
|
||||
return InfoListItem(theme: theme, title: title, text: .plain(text), style: .plain, closeAction: suppressed ? nil : {
|
||||
return InfoListItem(presentationData: ItemListPresentationData(presentationData), title: title, text: .plain(text), style: .plain, closeAction: suppressed ? nil : {
|
||||
interaction.suppressWarning()
|
||||
})
|
||||
case let .permissionEnable(theme, text):
|
||||
return ContactListActionItem(theme: theme, title: text, icon: .none, header: nil, action: {
|
||||
return ContactListActionItem(presentationData: ItemListPresentationData(presentationData), title: text, icon: .none, header: nil, action: {
|
||||
interaction.authorize()
|
||||
})
|
||||
case let .option(_, option, header, theme, _):
|
||||
return ContactListActionItem(theme: theme, title: option.title, icon: option.icon, clearHighlightAutomatically: false, header: header, action: option.action)
|
||||
return ContactListActionItem(presentationData: ItemListPresentationData(presentationData), title: option.title, icon: option.icon, clearHighlightAutomatically: false, header: header, action: option.action)
|
||||
case let .peer(_, peer, presence, header, selection, theme, strings, dateTimeFormat, nameSortOrder, nameDisplayOrder, enabled):
|
||||
let status: ContactsPeerItemStatus
|
||||
let itemPeer: ContactsPeerItemPeer
|
||||
@ -221,7 +219,7 @@ private enum ContactListNodeEntry: Comparable, Identifiable {
|
||||
}
|
||||
}
|
||||
}
|
||||
return ContactsPeerItem(theme: theme, strings: strings, sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: account, peerMode: .peer, peer: itemPeer, status: status, enabled: enabled, selection: selection, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in
|
||||
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: account, peerMode: .peer, peer: itemPeer, status: status, enabled: enabled, selection: selection, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in
|
||||
interaction.openPeer(peer)
|
||||
}, itemHighlighting: interaction.itemHighlighting, contextAction: itemContextAction)
|
||||
}
|
||||
@ -602,12 +600,12 @@ private func contactListNodeEntries(accountPeer: Peer?, peers: [ContactListPeer]
|
||||
return entries
|
||||
}
|
||||
|
||||
private func preparedContactListNodeTransition(account: Account, from fromEntries: [ContactListNodeEntry], to toEntries: [ContactListNodeEntry], interaction: ContactListNodeInteraction, firstTime: Bool, isEmpty: Bool, generateIndexSections: Bool, animation: ContactListAnimation) -> ContactsListNodeTransition {
|
||||
private func preparedContactListNodeTransition(account: Account, presentationData: PresentationData, from fromEntries: [ContactListNodeEntry], to toEntries: [ContactListNodeEntry], interaction: ContactListNodeInteraction, firstTime: Bool, isEmpty: Bool, generateIndexSections: Bool, animation: ContactListAnimation) -> ContactsListNodeTransition {
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
|
||||
|
||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, interaction: interaction), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, interaction: interaction), directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, presentationData: presentationData, interaction: interaction), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, presentationData: presentationData, interaction: interaction), directionHint: nil) }
|
||||
|
||||
var shouldFixScroll = false
|
||||
var indexSections: [String] = []
|
||||
@ -772,7 +770,7 @@ public final class ContactListNode: ASDisplayNode {
|
||||
|
||||
private var presentationData: PresentationData
|
||||
private var presentationDataDisposable: Disposable?
|
||||
private let themeAndStringsPromise: Promise<(PresentationTheme, PresentationStrings, PresentationDateTimeFormat, PresentationPersonNameOrder, PresentationPersonNameOrder, Bool)>
|
||||
private let presentationDataPromise: Promise<PresentationData>
|
||||
|
||||
private var authorizationNode: PermissionContentNode
|
||||
private let displayPermissionPlaceholder: Bool
|
||||
@ -790,7 +788,7 @@ public final class ContactListNode: ASDisplayNode {
|
||||
|
||||
self.indexNode = CollectionIndexNode()
|
||||
|
||||
self.themeAndStringsPromise = Promise((self.presentationData.theme, self.presentationData.strings, self.presentationData.dateTimeFormat, self.presentationData.nameSortOrder, self.presentationData.nameDisplayOrder, self.presentationData.disableAnimations))
|
||||
self.presentationDataPromise = Promise(self.presentationData)
|
||||
|
||||
let contactsAuthorization = Promise<AccessType>()
|
||||
contactsAuthorization.set(.single(.allowed)
|
||||
@ -900,7 +898,7 @@ public final class ContactListNode: ASDisplayNode {
|
||||
var firstTime: Int32 = 1
|
||||
let selectionStateSignal = self.selectionStatePromise.get()
|
||||
let transition: Signal<ContactsListNodeTransition, NoError>
|
||||
let themeAndStringsPromise = self.themeAndStringsPromise
|
||||
let presentationDataPromise = self.presentationDataPromise
|
||||
|
||||
transition = presentation
|
||||
|> mapToSignal { presentation in
|
||||
@ -980,8 +978,8 @@ public final class ContactListNode: ASDisplayNode {
|
||||
foundDeviceContacts = .single([:])
|
||||
}
|
||||
|
||||
return combineLatest(foundLocalContacts, foundRemoteContacts, foundDeviceContacts, selectionStateSignal, themeAndStringsPromise.get())
|
||||
|> mapToQueue { localPeersAndStatuses, remotePeers, deviceContacts, selectionState, themeAndStrings -> Signal<ContactsListNodeTransition, NoError> in
|
||||
return combineLatest(foundLocalContacts, foundRemoteContacts, foundDeviceContacts, selectionStateSignal, presentationDataPromise.get())
|
||||
|> mapToQueue { localPeersAndStatuses, remotePeers, deviceContacts, selectionState, presentationData -> Signal<ContactsListNodeTransition, NoError> in
|
||||
let signal = deferred { () -> Signal<ContactsListNodeTransition, NoError> in
|
||||
var existingPeerIds = Set<PeerId>()
|
||||
var disabledPeerIds = Set<PeerId>()
|
||||
@ -1084,9 +1082,9 @@ public final class ContactListNode: ASDisplayNode {
|
||||
peers.append(.deviceContact(stableId, contact.0))
|
||||
}
|
||||
|
||||
let entries = contactListNodeEntries(accountPeer: nil, peers: peers, presences: localPeersAndStatuses.1, presentation: presentation, selectionState: selectionState, theme: themeAndStrings.0, strings: themeAndStrings.1, dateTimeFormat: themeAndStrings.2, sortOrder: themeAndStrings.3, displayOrder: themeAndStrings.4, disabledPeerIds: disabledPeerIds, authorizationStatus: .allowed, warningSuppressed: (true, true), displaySortOptions: false)
|
||||
let entries = contactListNodeEntries(accountPeer: nil, peers: peers, presences: localPeersAndStatuses.1, presentation: presentation, selectionState: selectionState, theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, sortOrder: presentationData.nameSortOrder, displayOrder: presentationData.nameDisplayOrder, disabledPeerIds: disabledPeerIds, authorizationStatus: .allowed, warningSuppressed: (true, true), displaySortOptions: false)
|
||||
let previous = previousEntries.swap(entries)
|
||||
return .single(preparedContactListNodeTransition(account: context.account, from: previous ?? [], to: entries, interaction: interaction, firstTime: previous == nil, isEmpty: false, generateIndexSections: generateSections, animation: .none))
|
||||
return .single(preparedContactListNodeTransition(account: context.account, presentationData: presentationData, from: previous ?? [], to: entries, interaction: interaction, firstTime: previous == nil, isEmpty: false, generateIndexSections: generateSections, animation: .none))
|
||||
}
|
||||
|
||||
if OSAtomicCompareAndSwap32(1, 0, &firstTime) {
|
||||
@ -1129,8 +1127,8 @@ public final class ContactListNode: ASDisplayNode {
|
||||
chatListSignal = .single([])
|
||||
}
|
||||
|
||||
return (combineLatest(self.contactPeersViewPromise.get(), chatListSignal, selectionStateSignal, themeAndStringsPromise.get(), contactsAuthorization.get(), contactsWarningSuppressed.get())
|
||||
|> mapToQueue { view, chatListPeers, selectionState, themeAndStrings, authorizationStatus, warningSuppressed -> Signal<ContactsListNodeTransition, NoError> in
|
||||
return (combineLatest(self.contactPeersViewPromise.get(), chatListSignal, selectionStateSignal, presentationDataPromise.get(), contactsAuthorization.get(), contactsWarningSuppressed.get())
|
||||
|> mapToQueue { view, chatListPeers, selectionState, presentationData, authorizationStatus, warningSuppressed -> Signal<ContactsListNodeTransition, NoError> in
|
||||
let signal = deferred { () -> Signal<ContactsListNodeTransition, NoError> in
|
||||
var peers = view.peers.map({ ContactListPeer.peer(peer: $0, isGlobal: false, participantCount: nil) })
|
||||
for (peer, memberCount) in chatListPeers {
|
||||
@ -1162,7 +1160,7 @@ public final class ContactListNode: ASDisplayNode {
|
||||
if (authorizationStatus == .notDetermined || authorizationStatus == .denied) && peers.isEmpty {
|
||||
isEmpty = true
|
||||
}
|
||||
let entries = contactListNodeEntries(accountPeer: view.accountPeer, peers: peers, presences: view.peerPresences, presentation: presentation, selectionState: selectionState, theme: themeAndStrings.0, strings: themeAndStrings.1, dateTimeFormat: themeAndStrings.2, sortOrder: themeAndStrings.3, displayOrder: themeAndStrings.4, disabledPeerIds: disabledPeerIds, authorizationStatus: authorizationStatus, warningSuppressed: warningSuppressed, displaySortOptions: displaySortOptions)
|
||||
let entries = contactListNodeEntries(accountPeer: view.accountPeer, peers: peers, presences: view.peerPresences, presentation: presentation, selectionState: selectionState, theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, sortOrder: presentationData.nameSortOrder, displayOrder: presentationData.nameDisplayOrder, disabledPeerIds: disabledPeerIds, authorizationStatus: authorizationStatus, warningSuppressed: warningSuppressed, displaySortOptions: displaySortOptions)
|
||||
let previous = previousEntries.swap(entries)
|
||||
|
||||
var hadPermissionInfo = false
|
||||
@ -1186,13 +1184,13 @@ public final class ContactListNode: ASDisplayNode {
|
||||
if hadPermissionInfo != hasPermissionInfo {
|
||||
animation = .insertion
|
||||
}
|
||||
else if let previous = previous, !themeAndStrings.5, (entries.count - previous.count) < 20 {
|
||||
else if let previous = previous, !presentationData.disableAnimations, (entries.count - previous.count) < 20 {
|
||||
animation = .default
|
||||
} else {
|
||||
animation = .none
|
||||
}
|
||||
|
||||
return .single(preparedContactListNodeTransition(account: context.account, from: previous ?? [], to: entries, interaction: interaction, firstTime: previous == nil, isEmpty: isEmpty, generateIndexSections: generateSections, animation: animation))
|
||||
return .single(preparedContactListNodeTransition(account: context.account, presentationData: presentationData, from: previous ?? [], to: entries, interaction: interaction, firstTime: previous == nil, isEmpty: isEmpty, generateIndexSections: generateSections, animation: animation))
|
||||
}
|
||||
|
||||
if OSAtomicCompareAndSwap32(1, 0, &firstTime) {
|
||||
@ -1221,7 +1219,7 @@ public final class ContactListNode: ASDisplayNode {
|
||||
if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings || previousDisableAnimations != presentationData.disableAnimations {
|
||||
strongSelf.backgroundColor = presentationData.theme.chatList.backgroundColor
|
||||
strongSelf.listNode.verticalScrollIndicatorColor = presentationData.theme.list.scrollIndicatorColor
|
||||
strongSelf.themeAndStringsPromise.set(.single((presentationData.theme, presentationData.strings, presentationData.dateTimeFormat, presentationData.nameSortOrder, presentationData.nameDisplayOrder, presentationData.disableAnimations)))
|
||||
strongSelf.presentationDataPromise.set(.single(presentationData))
|
||||
|
||||
let authorizationPreviousHidden = strongSelf.authorizationNode.isHidden
|
||||
strongSelf.authorizationNode.removeFromSupernode()
|
||||
|
@ -15,6 +15,7 @@ import ChatListSearchItemHeader
|
||||
import ContactsPeerItem
|
||||
import ContextUI
|
||||
import PhoneNumberFormat
|
||||
import ItemListUI
|
||||
|
||||
private enum ContactListSearchGroup {
|
||||
case contacts
|
||||
@ -68,7 +69,7 @@ private struct ContactListSearchEntry: Identifiable, Comparable {
|
||||
return lhs.index < rhs.index
|
||||
}
|
||||
|
||||
func item(account: Account, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, timeFormat: PresentationDateTimeFormat, openPeer: @escaping (ContactListPeer) -> Void, contextAction: ((Peer, ASDisplayNode, ContextGesture?) -> Void)?) -> ListViewItem {
|
||||
func item(account: Account, presentationData: PresentationData, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, timeFormat: PresentationDateTimeFormat, openPeer: @escaping (ContactListPeer) -> Void, contextAction: ((Peer, ASDisplayNode, ContextGesture?) -> Void)?) -> ListViewItem {
|
||||
let header: ListViewItemHeader
|
||||
let status: ContactsPeerItemStatus
|
||||
switch self.group {
|
||||
@ -100,7 +101,7 @@ private struct ContactListSearchEntry: Identifiable, Comparable {
|
||||
case let .deviceContact(stableId, contact):
|
||||
peerItem = .deviceContact(stableId: stableId, contact: contact)
|
||||
}
|
||||
return ContactsPeerItem(theme: self.theme, strings: self.strings, sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: account, peerMode: .peer, peer: peerItem, status: status, enabled: self.enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in
|
||||
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: account, peerMode: .peer, peer: peerItem, status: status, enabled: self.enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in
|
||||
openPeer(peer)
|
||||
}, contextAction: contextAction.flatMap { contextAction in
|
||||
return nativePeer.flatMap { nativePeer in
|
||||
@ -119,12 +120,12 @@ struct ContactListSearchContainerTransition {
|
||||
let isSearching: Bool
|
||||
}
|
||||
|
||||
private func contactListSearchContainerPreparedRecentTransition(from fromEntries: [ContactListSearchEntry], to toEntries: [ContactListSearchEntry], isSearching: Bool, account: Account, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, timeFormat: PresentationDateTimeFormat, openPeer: @escaping (ContactListPeer) -> Void, contextAction: ((Peer, ASDisplayNode, ContextGesture?) -> Void)?) -> ContactListSearchContainerTransition {
|
||||
private func contactListSearchContainerPreparedRecentTransition(from fromEntries: [ContactListSearchEntry], to toEntries: [ContactListSearchEntry], isSearching: Bool, account: Account, presentationData: PresentationData, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, timeFormat: PresentationDateTimeFormat, openPeer: @escaping (ContactListPeer) -> Void, contextAction: ((Peer, ASDisplayNode, ContextGesture?) -> Void)?) -> ContactListSearchContainerTransition {
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
|
||||
|
||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, timeFormat: timeFormat, openPeer: openPeer, contextAction: contextAction), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, timeFormat: timeFormat, openPeer: openPeer, contextAction: contextAction), directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, presentationData: presentationData, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, timeFormat: timeFormat, openPeer: openPeer, contextAction: contextAction), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, presentationData: presentationData, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, timeFormat: timeFormat, openPeer: openPeer, contextAction: contextAction), directionHint: nil) }
|
||||
|
||||
return ContactListSearchContainerTransition(deletions: deletions, insertions: insertions, updates: updates, isSearching: isSearching)
|
||||
}
|
||||
@ -323,7 +324,7 @@ public final class ContactsSearchContainerNode: SearchDisplayControllerContentNo
|
||||
if let strongSelf = self {
|
||||
let previousItems = previousSearchItems.swap(items ?? [])
|
||||
|
||||
let transition = contactListSearchContainerPreparedRecentTransition(from: previousItems, to: items ?? [], isSearching: items != nil, account: context.account, nameSortOrder: strongSelf.presentationData.nameSortOrder, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder, timeFormat: strongSelf.presentationData.dateTimeFormat, openPeer: { peer in self?.listNode.clearHighlightAnimated(true)
|
||||
let transition = contactListSearchContainerPreparedRecentTransition(from: previousItems, to: items ?? [], isSearching: items != nil, account: context.account, presentationData: strongSelf.presentationData, nameSortOrder: strongSelf.presentationData.nameSortOrder, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder, timeFormat: strongSelf.presentationData.dateTimeFormat, openPeer: { peer in self?.listNode.clearHighlightAnimated(true)
|
||||
self?.openPeer(peer)
|
||||
}, contextAction: strongSelf.contextAction)
|
||||
|
||||
|
@ -17,6 +17,7 @@ import ContactsPeerItem
|
||||
import ChatListSearchItemHeader
|
||||
import AppBundle
|
||||
import PhoneNumberFormat
|
||||
import ItemListUI
|
||||
|
||||
private enum InviteContactsEntryId: Hashable {
|
||||
case option(index: Int)
|
||||
@ -46,10 +47,10 @@ private enum InviteContactsEntry: Comparable, Identifiable {
|
||||
}
|
||||
}
|
||||
|
||||
func item(account: Account, interaction: InviteContactsInteraction) -> ListViewItem {
|
||||
func item(account: Account, presentationData: PresentationData, interaction: InviteContactsInteraction) -> ListViewItem {
|
||||
switch self {
|
||||
case let .option(_, option, theme, _):
|
||||
return ContactListActionItem(theme: theme, title: option.title, icon: option.icon, header: nil, action: option.action)
|
||||
return ContactListActionItem(presentationData: ItemListPresentationData(presentationData), title: option.title, icon: option.icon, header: nil, action: option.action)
|
||||
case let .peer(_, id, contact, count, selection, theme, strings, nameSortOrder, nameDisplayOrder):
|
||||
let status: ContactsPeerItemStatus
|
||||
if count != 0 {
|
||||
@ -58,7 +59,7 @@ private enum InviteContactsEntry: Comparable, Identifiable {
|
||||
status = .none
|
||||
}
|
||||
let peer = TelegramUser(id: PeerId(namespace: -1, id: 0), accessHash: nil, firstName: contact.firstName, lastName: contact.lastName, username: nil, phone: nil, photo: [], botInfo: nil, restrictionInfo: nil, flags: [])
|
||||
return ContactsPeerItem(theme: theme, strings: strings, sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: account, peerMode: .peer, peer: .peer(peer: peer, chatPeer: peer), status: status, enabled: true, selection: selection, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: ChatListSearchItemHeader(type: .contacts, theme: theme, strings: strings, actionTitle: nil, action: nil), action: { _ in
|
||||
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: account, peerMode: .peer, peer: .peer(peer: peer, chatPeer: peer), status: status, enabled: true, selection: selection, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: ChatListSearchItemHeader(type: .contacts, theme: theme, strings: strings, actionTitle: nil, action: nil), action: { _ in
|
||||
interaction.toggleContact(id)
|
||||
})
|
||||
}
|
||||
@ -201,12 +202,12 @@ private func inviteContactsEntries(accountPeer: Peer?, sortedContacts: [(DeviceC
|
||||
return entries
|
||||
}
|
||||
|
||||
private func preparedInviteContactsTransition(account: Account, from fromEntries: [InviteContactsEntry], to toEntries: [InviteContactsEntry], sortedContacts: [(DeviceContactStableId, DeviceContactBasicData, Int32)]?, interaction: InviteContactsInteraction, isLoading: Bool, firstTime: Bool, crossfade: Bool) -> InviteContactsTransition {
|
||||
private func preparedInviteContactsTransition(account: Account, presentationData: PresentationData, from fromEntries: [InviteContactsEntry], to toEntries: [InviteContactsEntry], sortedContacts: [(DeviceContactStableId, DeviceContactBasicData, Int32)]?, interaction: InviteContactsInteraction, isLoading: Bool, firstTime: Bool, crossfade: Bool) -> InviteContactsTransition {
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
|
||||
|
||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, interaction: interaction), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, interaction: interaction), directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, presentationData: presentationData, interaction: interaction), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, presentationData: presentationData, interaction: interaction), directionHint: nil) }
|
||||
|
||||
return InviteContactsTransition(deletions: deletions, insertions: insertions, updates: updates, sortedContacts: sortedContacts, isLoading: isLoading, firstTime: firstTime, crossfade: crossfade)
|
||||
}
|
||||
@ -263,7 +264,7 @@ final class InviteContactsControllerNode: ASDisplayNode {
|
||||
private var presentationData: PresentationData
|
||||
private var presentationDataDisposable: Disposable?
|
||||
|
||||
private let themeAndStringsPromise: Promise<(PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder)>
|
||||
private let presentationDataPromise: Promise<PresentationData>
|
||||
|
||||
private let _ready = Promise<Bool>()
|
||||
private var readyValue = false {
|
||||
@ -288,7 +289,7 @@ final class InviteContactsControllerNode: ASDisplayNode {
|
||||
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
self.themeAndStringsPromise = Promise((self.presentationData.theme, self.presentationData.strings, self.presentationData.nameSortOrder, self.presentationData.nameDisplayOrder))
|
||||
self.presentationDataPromise = Promise(self.presentationData)
|
||||
|
||||
self.listNode = ListView()
|
||||
|
||||
@ -316,7 +317,7 @@ final class InviteContactsControllerNode: ASDisplayNode {
|
||||
let previousStrings = strongSelf.presentationData.strings
|
||||
|
||||
strongSelf.presentationData = presentationData
|
||||
strongSelf.themeAndStringsPromise.set(.single((presentationData.theme, presentationData.strings, presentationData.nameSortOrder, presentationData.nameDisplayOrder)))
|
||||
strongSelf.presentationDataPromise.set(.single(presentationData))
|
||||
|
||||
if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings {
|
||||
strongSelf.updateThemeAndStrings()
|
||||
@ -327,7 +328,7 @@ final class InviteContactsControllerNode: ASDisplayNode {
|
||||
let account = self.context.account
|
||||
let selectionStateSignal = self.selectionStatePromise.get()
|
||||
let transition: Signal<InviteContactsTransition, NoError>
|
||||
let themeAndStringsPromise = self.themeAndStringsPromise
|
||||
let presentationDataPromise = self.presentationDataPromise
|
||||
let previousEntries = Atomic<[InviteContactsEntry]?>(value: nil)
|
||||
|
||||
let interaction = InviteContactsInteraction(toggleContact: { [weak self] id in
|
||||
@ -403,19 +404,19 @@ final class InviteContactsControllerNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
let processingQueue = Queue()
|
||||
transition = (combineLatest(.single(nil) |> then(sortedContacts), selectionStateSignal, themeAndStringsPromise.get(), .single(true) |> delay(0.2, queue: Queue.mainQueue()))
|
||||
|> mapToQueue { sortedContacts, selectionState, themeAndStrings, ready -> Signal<InviteContactsTransition, NoError> in
|
||||
transition = (combineLatest(.single(nil) |> then(sortedContacts), selectionStateSignal, presentationDataPromise.get(), .single(true) |> delay(0.2, queue: Queue.mainQueue()))
|
||||
|> mapToQueue { sortedContacts, selectionState, presentationData, ready -> Signal<InviteContactsTransition, NoError> in
|
||||
guard sortedContacts != nil || ready else {
|
||||
return .never()
|
||||
}
|
||||
|
||||
let signal = deferred { () -> Signal<InviteContactsTransition, NoError> in
|
||||
let entries = inviteContactsEntries(accountPeer: nil, sortedContacts: sortedContacts, selectionState: selectionState, theme: themeAndStrings.0, strings: themeAndStrings.1, nameSortOrder: themeAndStrings.2, nameDisplayOrder: themeAndStrings.3, interaction: interaction)
|
||||
let entries = inviteContactsEntries(accountPeer: nil, sortedContacts: sortedContacts, selectionState: selectionState, theme: presentationData.theme, strings: presentationData.strings, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, interaction: interaction)
|
||||
let previous = previousEntries.swap(entries)
|
||||
let previousContacts = currentSortedContacts.with { $0 }
|
||||
let crossfade = previous != nil && previousContacts == nil
|
||||
|
||||
return .single(preparedInviteContactsTransition(account: context.account, from: previous ?? [], to: entries, sortedContacts: sortedContacts, interaction: interaction, isLoading: sortedContacts == nil, firstTime: previous == nil, crossfade: crossfade))
|
||||
return .single(preparedInviteContactsTransition(account: context.account, presentationData: presentationData, from: previous ?? [], to: entries, sortedContacts: sortedContacts, interaction: interaction, isLoading: sortedContacts == nil, firstTime: previous == nil, crossfade: crossfade))
|
||||
}
|
||||
return signal
|
||||
|> runOn(processingQueue)
|
||||
|
@ -27,11 +27,6 @@ public final class ContactItemHighlighting {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.regular(17.0)
|
||||
private let titleBoldFont = Font.medium(17.0)
|
||||
private let statusFont = Font.regular(13.0)
|
||||
private let badgeFont = Font.regular(14.0)
|
||||
|
||||
public enum ContactsPeerItemStatus {
|
||||
case none
|
||||
case presence(PeerPresence, PresentationDateTimeFormat)
|
||||
@ -110,8 +105,7 @@ public enum ContactsPeerItemPeer: Equatable {
|
||||
}
|
||||
|
||||
public class ContactsPeerItem: ListViewItem, ListViewItemWithHeader {
|
||||
let theme: PresentationTheme
|
||||
let strings: PresentationStrings
|
||||
let presentationData: ItemListPresentationData
|
||||
let sortOrder: PresentationPersonNameOrder
|
||||
let displayOrder: PresentationPersonNameOrder
|
||||
let account: Account
|
||||
@ -136,9 +130,8 @@ public class ContactsPeerItem: ListViewItem, ListViewItemWithHeader {
|
||||
|
||||
public let header: ListViewItemHeader?
|
||||
|
||||
public init(theme: PresentationTheme, strings: PresentationStrings, sortOrder: PresentationPersonNameOrder, displayOrder: PresentationPersonNameOrder, account: Account, peerMode: ContactsPeerItemPeerMode, peer: ContactsPeerItemPeer, status: ContactsPeerItemStatus, badge: ContactsPeerItemBadge? = nil, enabled: Bool, selection: ContactsPeerItemSelection, editing: ContactsPeerItemEditing, options: [ItemListPeerItemRevealOption] = [], actionIcon: ContactsPeerItemActionIcon = .none, index: PeerNameIndex?, header: ListViewItemHeader?, action: @escaping (ContactsPeerItemPeer) -> Void, setPeerIdWithRevealedOptions: ((PeerId?, PeerId?) -> Void)? = nil, deletePeer: ((PeerId) -> Void)? = nil, itemHighlighting: ContactItemHighlighting? = nil, contextAction: ((ASDisplayNode, ContextGesture?) -> Void)? = nil) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
public init(presentationData: ItemListPresentationData, sortOrder: PresentationPersonNameOrder, displayOrder: PresentationPersonNameOrder, account: Account, peerMode: ContactsPeerItemPeerMode, peer: ContactsPeerItemPeer, status: ContactsPeerItemStatus, badge: ContactsPeerItemBadge? = nil, enabled: Bool, selection: ContactsPeerItemSelection, editing: ContactsPeerItemEditing, options: [ItemListPeerItemRevealOption] = [], actionIcon: ContactsPeerItemActionIcon = .none, index: PeerNameIndex?, header: ListViewItemHeader?, action: @escaping (ContactsPeerItemPeer) -> Void, setPeerIdWithRevealedOptions: ((PeerId?, PeerId?) -> Void)? = nil, deletePeer: ((PeerId) -> Void)? = nil, itemHighlighting: ContactItemHighlighting? = nil, contextAction: ((ASDisplayNode, ContextGesture?) -> Void)? = nil) {
|
||||
self.presentationData = presentationData
|
||||
self.sortOrder = sortOrder
|
||||
self.displayOrder = displayOrder
|
||||
self.account = account
|
||||
@ -203,7 +196,7 @@ public class ContactsPeerItem: ListViewItem, ListViewItemWithHeader {
|
||||
}
|
||||
}
|
||||
}
|
||||
self.headerAccessoryItem = ContactsSectionHeaderAccessoryItem(sectionHeader: .letter(letter), theme: theme)
|
||||
self.headerAccessoryItem = ContactsSectionHeaderAccessoryItem(sectionHeader: .letter(letter), theme: presentationData.theme)
|
||||
} else {
|
||||
self.headerAccessoryItem = nil
|
||||
}
|
||||
@ -439,8 +432,13 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
return { [weak self] item, params, first, last, firstWithHeader in
|
||||
var updatedTheme: PresentationTheme?
|
||||
|
||||
if currentItem?.theme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
let titleBoldFont = Font.medium(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
let statusFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 13.0 / 17.0))
|
||||
let badgeFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 14.0 / 17.0))
|
||||
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
}
|
||||
var leftInset: CGFloat = 65.0 + params.leftInset
|
||||
let rightInset: CGFloat = 10.0 + params.rightInset
|
||||
@ -448,39 +446,39 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
let updatedSelectionNode: CheckNode?
|
||||
var isSelected = false
|
||||
switch item.selection {
|
||||
case .none:
|
||||
updatedSelectionNode = nil
|
||||
case let .selectable(selected):
|
||||
leftInset += 28.0
|
||||
isSelected = selected
|
||||
|
||||
let selectionNode: CheckNode
|
||||
if let current = currentSelectionNode {
|
||||
selectionNode = current
|
||||
updatedSelectionNode = selectionNode
|
||||
} else {
|
||||
selectionNode = CheckNode(strokeColor: item.theme.list.itemCheckColors.strokeColor, fillColor: item.theme.list.itemCheckColors.fillColor, foregroundColor: item.theme.list.itemCheckColors.foregroundColor, style: .plain)
|
||||
selectionNode.isUserInteractionEnabled = false
|
||||
updatedSelectionNode = selectionNode
|
||||
}
|
||||
case .none:
|
||||
updatedSelectionNode = nil
|
||||
case let .selectable(selected):
|
||||
leftInset += 28.0
|
||||
isSelected = selected
|
||||
|
||||
let selectionNode: CheckNode
|
||||
if let current = currentSelectionNode {
|
||||
selectionNode = current
|
||||
updatedSelectionNode = selectionNode
|
||||
} else {
|
||||
selectionNode = CheckNode(strokeColor: item.presentationData.theme.list.itemCheckColors.strokeColor, fillColor: item.presentationData.theme.list.itemCheckColors.fillColor, foregroundColor: item.presentationData.theme.list.itemCheckColors.foregroundColor, style: .plain)
|
||||
selectionNode.isUserInteractionEnabled = false
|
||||
updatedSelectionNode = selectionNode
|
||||
}
|
||||
}
|
||||
|
||||
var verificationIconImage: UIImage?
|
||||
switch item.peer {
|
||||
case let .peer(peer, _):
|
||||
if let peer = peer, peer.isVerified {
|
||||
verificationIconImage = PresentationResourcesChatList.verifiedIcon(item.theme)
|
||||
}
|
||||
case .deviceContact:
|
||||
break
|
||||
case let .peer(peer, _):
|
||||
if let peer = peer, peer.isVerified {
|
||||
verificationIconImage = PresentationResourcesChatList.verifiedIcon(item.presentationData.theme)
|
||||
}
|
||||
case .deviceContact:
|
||||
break
|
||||
}
|
||||
|
||||
let actionIconImage: UIImage?
|
||||
switch item.actionIcon {
|
||||
case .none:
|
||||
actionIconImage = nil
|
||||
case .add:
|
||||
actionIconImage = PresentationResourcesItemList.plusIconImage(item.theme)
|
||||
case .none:
|
||||
actionIconImage = nil
|
||||
case .add:
|
||||
actionIconImage = PresentationResourcesItemList.plusIconImage(item.presentationData.theme)
|
||||
}
|
||||
|
||||
var titleAttributedString: NSAttributedString?
|
||||
@ -488,94 +486,94 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
var userPresence: TelegramUserPresence?
|
||||
|
||||
switch item.peer {
|
||||
case let .peer(peer, chatPeer):
|
||||
if let peer = peer {
|
||||
let textColor: UIColor
|
||||
if let _ = chatPeer as? TelegramSecretChat {
|
||||
textColor = item.theme.chatList.secretTitleColor
|
||||
} else {
|
||||
textColor = item.theme.list.itemPrimaryTextColor
|
||||
}
|
||||
if let user = peer as? TelegramUser {
|
||||
if peer.id == item.account.peerId, case .generalSearch = item.peerMode {
|
||||
titleAttributedString = NSAttributedString(string: item.strings.DialogList_SavedMessages, font: titleBoldFont, textColor: textColor)
|
||||
} else if let firstName = user.firstName, let lastName = user.lastName, !firstName.isEmpty, !lastName.isEmpty {
|
||||
let string = NSMutableAttributedString()
|
||||
switch item.displayOrder {
|
||||
case .firstLast:
|
||||
string.append(NSAttributedString(string: firstName, font: item.sortOrder == .firstLast ? titleBoldFont : titleFont, textColor: textColor))
|
||||
string.append(NSAttributedString(string: " ", font: titleFont, textColor: textColor))
|
||||
string.append(NSAttributedString(string: lastName, font: item.sortOrder == .firstLast ? titleFont : titleBoldFont, textColor: textColor))
|
||||
case .lastFirst:
|
||||
string.append(NSAttributedString(string: lastName, font: item.sortOrder == .firstLast ? titleFont : titleBoldFont, textColor: textColor))
|
||||
string.append(NSAttributedString(string: " ", font: titleFont, textColor: textColor))
|
||||
string.append(NSAttributedString(string: firstName, font: item.sortOrder == .firstLast ? titleBoldFont : titleFont, textColor: textColor))
|
||||
}
|
||||
titleAttributedString = string
|
||||
} else if let firstName = user.firstName, !firstName.isEmpty {
|
||||
titleAttributedString = NSAttributedString(string: firstName, font: titleBoldFont, textColor: textColor)
|
||||
} else if let lastName = user.lastName, !lastName.isEmpty {
|
||||
titleAttributedString = NSAttributedString(string: lastName, font: titleBoldFont, textColor: textColor)
|
||||
} else {
|
||||
titleAttributedString = NSAttributedString(string: item.strings.User_DeletedAccount, font: titleBoldFont, textColor: textColor)
|
||||
}
|
||||
} else if let group = peer as? TelegramGroup {
|
||||
titleAttributedString = NSAttributedString(string: group.title, font: titleBoldFont, textColor: item.theme.list.itemPrimaryTextColor)
|
||||
} else if let channel = peer as? TelegramChannel {
|
||||
titleAttributedString = NSAttributedString(string: channel.title, font: titleBoldFont, textColor: item.theme.list.itemPrimaryTextColor)
|
||||
}
|
||||
|
||||
switch item.status {
|
||||
case .none:
|
||||
break
|
||||
case let .presence(presence, dateTimeFormat):
|
||||
let presence = (presence as? TelegramUserPresence) ?? TelegramUserPresence(status: .none, lastActivity: 0)
|
||||
userPresence = presence
|
||||
let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970
|
||||
let (string, activity) = stringAndActivityForUserPresence(strings: item.strings, dateTimeFormat: dateTimeFormat, presence: presence, relativeTo: Int32(timestamp))
|
||||
statusAttributedString = NSAttributedString(string: string, font: statusFont, textColor: activity ? item.theme.list.itemAccentColor : item.theme.list.itemSecondaryTextColor)
|
||||
case let .addressName(suffix):
|
||||
if let addressName = peer.addressName {
|
||||
let addressNameString = NSAttributedString(string: "@" + addressName, font: statusFont, textColor: item.theme.list.itemAccentColor)
|
||||
if !suffix.isEmpty {
|
||||
let suffixString = NSAttributedString(string: suffix, font: statusFont, textColor: item.theme.list.itemSecondaryTextColor)
|
||||
let finalString = NSMutableAttributedString()
|
||||
finalString.append(addressNameString)
|
||||
finalString.append(suffixString)
|
||||
statusAttributedString = finalString
|
||||
} else {
|
||||
statusAttributedString = addressNameString
|
||||
}
|
||||
} else if !suffix.isEmpty {
|
||||
statusAttributedString = NSAttributedString(string: suffix, font: statusFont, textColor: item.theme.list.itemSecondaryTextColor)
|
||||
}
|
||||
case let .custom(text):
|
||||
statusAttributedString = NSAttributedString(string: text, font: statusFont, textColor: item.theme.list.itemSecondaryTextColor)
|
||||
}
|
||||
}
|
||||
case let .deviceContact(_, contact):
|
||||
let textColor: UIColor = item.theme.list.itemPrimaryTextColor
|
||||
|
||||
if !contact.firstName.isEmpty, !contact.lastName.isEmpty {
|
||||
let string = NSMutableAttributedString()
|
||||
string.append(NSAttributedString(string: contact.firstName, font: titleFont, textColor: textColor))
|
||||
string.append(NSAttributedString(string: " ", font: titleFont, textColor: textColor))
|
||||
string.append(NSAttributedString(string: contact.lastName, font: titleBoldFont, textColor: textColor))
|
||||
titleAttributedString = string
|
||||
} else if !contact.firstName.isEmpty {
|
||||
titleAttributedString = NSAttributedString(string: contact.firstName, font: titleBoldFont, textColor: textColor)
|
||||
} else if !contact.lastName.isEmpty {
|
||||
titleAttributedString = NSAttributedString(string: contact.lastName, font: titleBoldFont, textColor: textColor)
|
||||
case let .peer(peer, chatPeer):
|
||||
if let peer = peer {
|
||||
let textColor: UIColor
|
||||
if let _ = chatPeer as? TelegramSecretChat {
|
||||
textColor = item.presentationData.theme.chatList.secretTitleColor
|
||||
} else {
|
||||
titleAttributedString = NSAttributedString(string: item.strings.User_DeletedAccount, font: titleBoldFont, textColor: textColor)
|
||||
textColor = item.presentationData.theme.list.itemPrimaryTextColor
|
||||
}
|
||||
if let user = peer as? TelegramUser {
|
||||
if peer.id == item.account.peerId, case .generalSearch = item.peerMode {
|
||||
titleAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_SavedMessages, font: titleBoldFont, textColor: textColor)
|
||||
} else if let firstName = user.firstName, let lastName = user.lastName, !firstName.isEmpty, !lastName.isEmpty {
|
||||
let string = NSMutableAttributedString()
|
||||
switch item.displayOrder {
|
||||
case .firstLast:
|
||||
string.append(NSAttributedString(string: firstName, font: item.sortOrder == .firstLast ? titleBoldFont : titleFont, textColor: textColor))
|
||||
string.append(NSAttributedString(string: " ", font: titleFont, textColor: textColor))
|
||||
string.append(NSAttributedString(string: lastName, font: item.sortOrder == .firstLast ? titleFont : titleBoldFont, textColor: textColor))
|
||||
case .lastFirst:
|
||||
string.append(NSAttributedString(string: lastName, font: item.sortOrder == .firstLast ? titleFont : titleBoldFont, textColor: textColor))
|
||||
string.append(NSAttributedString(string: " ", font: titleFont, textColor: textColor))
|
||||
string.append(NSAttributedString(string: firstName, font: item.sortOrder == .firstLast ? titleBoldFont : titleFont, textColor: textColor))
|
||||
}
|
||||
titleAttributedString = string
|
||||
} else if let firstName = user.firstName, !firstName.isEmpty {
|
||||
titleAttributedString = NSAttributedString(string: firstName, font: titleBoldFont, textColor: textColor)
|
||||
} else if let lastName = user.lastName, !lastName.isEmpty {
|
||||
titleAttributedString = NSAttributedString(string: lastName, font: titleBoldFont, textColor: textColor)
|
||||
} else {
|
||||
titleAttributedString = NSAttributedString(string: item.presentationData.strings.User_DeletedAccount, font: titleBoldFont, textColor: textColor)
|
||||
}
|
||||
} else if let group = peer as? TelegramGroup {
|
||||
titleAttributedString = NSAttributedString(string: group.title, font: titleBoldFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor)
|
||||
} else if let channel = peer as? TelegramChannel {
|
||||
titleAttributedString = NSAttributedString(string: channel.title, font: titleBoldFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor)
|
||||
}
|
||||
|
||||
switch item.status {
|
||||
case let .custom(text):
|
||||
statusAttributedString = NSAttributedString(string: text, font: statusFont, textColor: item.theme.list.itemSecondaryTextColor)
|
||||
default:
|
||||
break
|
||||
case .none:
|
||||
break
|
||||
case let .presence(presence, dateTimeFormat):
|
||||
let presence = (presence as? TelegramUserPresence) ?? TelegramUserPresence(status: .none, lastActivity: 0)
|
||||
userPresence = presence
|
||||
let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970
|
||||
let (string, activity) = stringAndActivityForUserPresence(strings: item.presentationData.strings, dateTimeFormat: dateTimeFormat, presence: presence, relativeTo: Int32(timestamp))
|
||||
statusAttributedString = NSAttributedString(string: string, font: statusFont, textColor: activity ? item.presentationData.theme.list.itemAccentColor : item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
case let .addressName(suffix):
|
||||
if let addressName = peer.addressName {
|
||||
let addressNameString = NSAttributedString(string: "@" + addressName, font: statusFont, textColor: item.presentationData.theme.list.itemAccentColor)
|
||||
if !suffix.isEmpty {
|
||||
let suffixString = NSAttributedString(string: suffix, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
let finalString = NSMutableAttributedString()
|
||||
finalString.append(addressNameString)
|
||||
finalString.append(suffixString)
|
||||
statusAttributedString = finalString
|
||||
} else {
|
||||
statusAttributedString = addressNameString
|
||||
}
|
||||
} else if !suffix.isEmpty {
|
||||
statusAttributedString = NSAttributedString(string: suffix, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
}
|
||||
case let .custom(text):
|
||||
statusAttributedString = NSAttributedString(string: text, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
}
|
||||
}
|
||||
case let .deviceContact(_, contact):
|
||||
let textColor: UIColor = item.presentationData.theme.list.itemPrimaryTextColor
|
||||
|
||||
if !contact.firstName.isEmpty, !contact.lastName.isEmpty {
|
||||
let string = NSMutableAttributedString()
|
||||
string.append(NSAttributedString(string: contact.firstName, font: titleFont, textColor: textColor))
|
||||
string.append(NSAttributedString(string: " ", font: titleFont, textColor: textColor))
|
||||
string.append(NSAttributedString(string: contact.lastName, font: titleBoldFont, textColor: textColor))
|
||||
titleAttributedString = string
|
||||
} else if !contact.firstName.isEmpty {
|
||||
titleAttributedString = NSAttributedString(string: contact.firstName, font: titleBoldFont, textColor: textColor)
|
||||
} else if !contact.lastName.isEmpty {
|
||||
titleAttributedString = NSAttributedString(string: contact.lastName, font: titleBoldFont, textColor: textColor)
|
||||
} else {
|
||||
titleAttributedString = NSAttributedString(string: item.presentationData.strings.User_DeletedAccount, font: titleBoldFont, textColor: textColor)
|
||||
}
|
||||
|
||||
switch item.status {
|
||||
case let .custom(text):
|
||||
statusAttributedString = NSAttributedString(string: text, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var badgeTextLayoutAndApply: (TextNodeLayout, () -> TextNode)?
|
||||
@ -584,11 +582,11 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
let badgeTextColor: UIColor
|
||||
switch badge.type {
|
||||
case .inactive:
|
||||
currentBadgeBackgroundImage = PresentationResourcesChatList.badgeBackgroundInactive(item.theme)
|
||||
badgeTextColor = item.theme.chatList.unreadBadgeInactiveTextColor
|
||||
currentBadgeBackgroundImage = PresentationResourcesChatList.badgeBackgroundInactive(item.presentationData.theme)
|
||||
badgeTextColor = item.presentationData.theme.chatList.unreadBadgeInactiveTextColor
|
||||
case .active:
|
||||
currentBadgeBackgroundImage = PresentationResourcesChatList.badgeBackgroundActive(item.theme)
|
||||
badgeTextColor = item.theme.chatList.unreadBadgeActiveTextColor
|
||||
currentBadgeBackgroundImage = PresentationResourcesChatList.badgeBackgroundActive(item.presentationData.theme)
|
||||
badgeTextColor = item.presentationData.theme.chatList.unreadBadgeActiveTextColor
|
||||
}
|
||||
let badgeAttributedString = NSAttributedString(string: badge.count > 0 ? "\(badge.count)" : " ", font: badgeFont, textColor: badgeTextColor)
|
||||
badgeTextLayoutAndApply = makeBadgeTextLayout(TextNodeLayoutArguments(attributedString: badgeAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: 50.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
@ -613,13 +611,22 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
let (statusLayout, statusApply) = makeStatusLayout(TextNodeLayoutArguments(attributedString: statusAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: max(0.0, params.width - leftInset - rightInset - badgeSize), height: CGFloat.infinity), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let nodeLayout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: 50.0), insets: UIEdgeInsets(top: firstWithHeader ? 29.0 : 0.0, left: 0.0, bottom: 0.0, right: 0.0))
|
||||
let verticalInset: CGFloat = statusAttributedString == nil ? 11.0 : 6.0
|
||||
|
||||
let statusHeightComponent: CGFloat
|
||||
if statusAttributedString == nil {
|
||||
statusHeightComponent = 0.0
|
||||
} else {
|
||||
statusHeightComponent = -1.0 + statusLayout.size.height
|
||||
}
|
||||
|
||||
let nodeLayout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: verticalInset * 2.0 + titleLayout.size.height + statusHeightComponent), insets: UIEdgeInsets(top: firstWithHeader ? 29.0 : 0.0, left: 0.0, bottom: 0.0, right: 0.0))
|
||||
|
||||
let titleFrame: CGRect
|
||||
if statusAttributedString != nil {
|
||||
titleFrame = CGRect(origin: CGPoint(x: leftInset, y: 6.0), size: titleLayout.size)
|
||||
titleFrame = CGRect(origin: CGPoint(x: leftInset, y: verticalInset), size: titleLayout.size)
|
||||
} else {
|
||||
titleFrame = CGRect(origin: CGPoint(x: leftInset, y: 14.0), size: titleLayout.size)
|
||||
titleFrame = CGRect(origin: CGPoint(x: leftInset, y: floor((nodeLayout.contentSize.height - titleLayout.size.height) / 2.0)), size: titleLayout.size)
|
||||
}
|
||||
|
||||
let peerRevealOptions: [ItemListRevealOption]
|
||||
@ -631,14 +638,14 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
let textColor: UIColor
|
||||
switch option.type {
|
||||
case .neutral:
|
||||
color = item.theme.list.itemDisclosureActions.constructive.fillColor
|
||||
textColor = item.theme.list.itemDisclosureActions.constructive.foregroundColor
|
||||
color = item.presentationData.theme.list.itemDisclosureActions.constructive.fillColor
|
||||
textColor = item.presentationData.theme.list.itemDisclosureActions.constructive.foregroundColor
|
||||
case .warning:
|
||||
color = item.theme.list.itemDisclosureActions.warning.fillColor
|
||||
textColor = item.theme.list.itemDisclosureActions.warning.foregroundColor
|
||||
color = item.presentationData.theme.list.itemDisclosureActions.warning.fillColor
|
||||
textColor = item.presentationData.theme.list.itemDisclosureActions.warning.foregroundColor
|
||||
case .destructive:
|
||||
color = item.theme.list.itemDisclosureActions.destructive.fillColor
|
||||
textColor = item.theme.list.itemDisclosureActions.destructive.foregroundColor
|
||||
color = item.presentationData.theme.list.itemDisclosureActions.destructive.fillColor
|
||||
textColor = item.presentationData.theme.list.itemDisclosureActions.destructive.foregroundColor
|
||||
}
|
||||
mappedOptions.append(ItemListRevealOption(key: index, title: option.title, icon: .none, color: color, textColor: textColor))
|
||||
index += 1
|
||||
@ -669,7 +676,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
} else if peer.isDeleted {
|
||||
overrideImage = .deletedIcon
|
||||
}
|
||||
strongSelf.avatarNode.setPeer(account: item.account, theme: item.theme, peer: peer, overrideImage: overrideImage, emptyColor: item.theme.list.mediaPlaceholderColor, synchronousLoad: synchronousLoads)
|
||||
strongSelf.avatarNode.setPeer(account: item.account, theme: item.presentationData.theme, peer: peer, overrideImage: overrideImage, emptyColor: item.presentationData.theme.list.mediaPlaceholderColor, synchronousLoad: synchronousLoads)
|
||||
}
|
||||
case let .deviceContact(_, contact):
|
||||
let letters: [String]
|
||||
@ -695,12 +702,12 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
let revealOffset = strongSelf.revealOffset
|
||||
|
||||
if let _ = updatedTheme {
|
||||
strongSelf.separatorNode.backgroundColor = item.theme.list.itemPlainSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.theme.list.plainBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.theme.list.itemHighlightedBackgroundColor
|
||||
strongSelf.separatorNode.backgroundColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.plainBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
}
|
||||
|
||||
transition.updateFrame(node: strongSelf.avatarNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset - 50.0, y: 5.0), size: CGSize(width: 40.0, height: 40.0)))
|
||||
transition.updateFrame(node: strongSelf.avatarNode, frame: CGRect(origin: CGPoint(x: revealOffset + leftInset - 50.0, y: floor((nodeLayout.contentSize.height - 40.0) / 2.0)), size: CGSize(width: 40.0, height: 40.0)))
|
||||
|
||||
let _ = titleApply()
|
||||
transition.updateFrame(node: strongSelf.titleNode, frame: titleFrame.offsetBy(dx: revealOffset, dy: 0.0))
|
||||
@ -709,7 +716,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.statusNode.alpha = item.enabled ? 1.0 : 1.0
|
||||
|
||||
let _ = statusApply()
|
||||
let statusFrame = CGRect(origin: CGPoint(x: revealOffset + leftInset, y: 27.0), size: statusLayout.size)
|
||||
let statusFrame = CGRect(origin: CGPoint(x: revealOffset + leftInset, y: strongSelf.titleNode.frame.maxY - 1.0), size: statusLayout.size)
|
||||
let previousStatusFrame = strongSelf.statusNode.frame
|
||||
|
||||
strongSelf.statusNode.frame = statusFrame
|
||||
@ -826,7 +833,7 @@ public class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.updateLayout(size: nodeLayout.contentSize, leftInset: params.leftInset, rightInset: params.rightInset)
|
||||
|
||||
if item.editing.editable {
|
||||
strongSelf.setRevealOptions((left: [], right: [ItemListRevealOption(key: 0, title: item.strings.Common_Delete, icon: .none, color: item.theme.list.itemDisclosureActions.destructive.fillColor, textColor: item.theme.list.itemDisclosureActions.destructive.foregroundColor)]))
|
||||
strongSelf.setRevealOptions((left: [], right: [ItemListRevealOption(key: 0, title: item.presentationData.strings.Common_Delete, icon: .none, color: item.presentationData.theme.list.itemDisclosureActions.destructive.fillColor, textColor: item.presentationData.theme.list.itemDisclosureActions.destructive.foregroundColor)]))
|
||||
strongSelf.setRevealOptionsOpened(item.editing.revealed, animated: animated)
|
||||
} else {
|
||||
strongSelf.setRevealOptions((left: [], right: peerRevealOptions))
|
||||
|
@ -254,7 +254,7 @@ public final class DeviceAccess {
|
||||
completion(response)
|
||||
if !response, let presentationData = presentationData {
|
||||
let text = presentationData.strings.AccessDenied_Camera
|
||||
present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: presentationData.strings.AccessDenied_Title, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: {
|
||||
present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: presentationData.strings.AccessDenied_Title, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: {
|
||||
openSettings()
|
||||
})]), nil)
|
||||
}
|
||||
@ -268,7 +268,7 @@ public final class DeviceAccess {
|
||||
text = presentationData.strings.AccessDenied_Camera
|
||||
}
|
||||
completion(false)
|
||||
present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: presentationData.strings.AccessDenied_Title, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: {
|
||||
present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: presentationData.strings.AccessDenied_Title, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: {
|
||||
openSettings()
|
||||
})]), nil)
|
||||
} else if status == PGCameraAuthorizationStatusAuthorized {
|
||||
@ -296,7 +296,7 @@ public final class DeviceAccess {
|
||||
case .voiceCall:
|
||||
text = presentationData.strings.AccessDenied_CallMicrophone
|
||||
}
|
||||
present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: presentationData.strings.AccessDenied_Title, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: {
|
||||
present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: presentationData.strings.AccessDenied_Title, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: {
|
||||
openSettings()
|
||||
})]), nil)
|
||||
if case .voiceCall = microphoneSubject {
|
||||
@ -322,7 +322,7 @@ public final class DeviceAccess {
|
||||
case .wallpaper:
|
||||
text = presentationData.strings.AccessDenied_Wallpapers
|
||||
}
|
||||
present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: presentationData.strings.AccessDenied_Title, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: {
|
||||
present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: presentationData.strings.AccessDenied_Title, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: {
|
||||
openSettings()
|
||||
})]), nil)
|
||||
}
|
||||
@ -358,7 +358,7 @@ public final class DeviceAccess {
|
||||
completion(false)
|
||||
if let presentationData = presentationData {
|
||||
let text = presentationData.strings.AccessDenied_LocationAlwaysDenied
|
||||
present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: presentationData.strings.AccessDenied_Title, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: {
|
||||
present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: presentationData.strings.AccessDenied_Title, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: {
|
||||
openSettings()
|
||||
})]), nil)
|
||||
}
|
||||
@ -377,7 +377,7 @@ public final class DeviceAccess {
|
||||
} else {
|
||||
text = presentationData.strings.AccessDenied_LocationDisabled
|
||||
}
|
||||
present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: presentationData.strings.AccessDenied_Title, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: {
|
||||
present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: presentationData.strings.AccessDenied_Title, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: {
|
||||
openSettings()
|
||||
})]), nil)
|
||||
}
|
||||
@ -450,7 +450,7 @@ public final class DeviceAccess {
|
||||
}
|
||||
case .cellularData:
|
||||
if let presentationData = presentationData {
|
||||
present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: presentationData.strings.Permissions_CellularDataTitle_v0, text: presentationData.strings.Permissions_CellularDataText_v0, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: {
|
||||
present(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: presentationData.strings.Permissions_CellularDataTitle_v0, text: presentationData.strings.Permissions_CellularDataText_v0, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_NotNow, action: {}), TextAlertAction(type: .genericAction, title: presentationData.strings.AccessDenied_Settings, action: {
|
||||
openSettings()
|
||||
})]), nil)
|
||||
}
|
||||
|
@ -17,8 +17,9 @@ public final class AlertControllerTheme: Equatable {
|
||||
public let accentColor: UIColor
|
||||
public let destructiveColor: UIColor
|
||||
public let disabledColor: UIColor
|
||||
public let baseFontSize: CGFloat
|
||||
|
||||
public init(backgroundType: ActionSheetControllerThemeBackgroundType, backgroundColor: UIColor, separatorColor: UIColor, highlightedItemColor: UIColor, primaryColor: UIColor, secondaryColor: UIColor, accentColor: UIColor, destructiveColor: UIColor, disabledColor: UIColor) {
|
||||
public init(backgroundType: ActionSheetControllerThemeBackgroundType, backgroundColor: UIColor, separatorColor: UIColor, highlightedItemColor: UIColor, primaryColor: UIColor, secondaryColor: UIColor, accentColor: UIColor, destructiveColor: UIColor, disabledColor: UIColor, baseFontSize: CGFloat) {
|
||||
self.backgroundType = backgroundType
|
||||
self.backgroundColor = backgroundColor
|
||||
self.separatorColor = separatorColor
|
||||
@ -28,6 +29,7 @@ public final class AlertControllerTheme: Equatable {
|
||||
self.accentColor = accentColor
|
||||
self.destructiveColor = destructiveColor
|
||||
self.disabledColor = disabledColor
|
||||
self.baseFontSize = baseFontSize
|
||||
}
|
||||
|
||||
public static func ==(lhs: AlertControllerTheme, rhs: AlertControllerTheme) -> Bool {
|
||||
@ -58,6 +60,9 @@ public final class AlertControllerTheme: Equatable {
|
||||
if lhs.disabledColor != rhs.disabledColor {
|
||||
return false
|
||||
}
|
||||
if lhs.baseFontSize != rhs.baseFontSize {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ public final class TextAlertContentActionNode: HighlightableButtonNode {
|
||||
}
|
||||
|
||||
private func updateTitle() {
|
||||
var font = Font.regular(17.0)
|
||||
var font = Font.regular(theme.baseFontSize)
|
||||
var color: UIColor
|
||||
switch self.action.type {
|
||||
case .defaultAction, .genericAction:
|
||||
@ -83,7 +83,7 @@ public final class TextAlertContentActionNode: HighlightableButtonNode {
|
||||
}
|
||||
switch self.action.type {
|
||||
case .defaultAction:
|
||||
font = Font.semibold(17.0)
|
||||
font = Font.semibold(theme.baseFontSize)
|
||||
case .destructiveAction, .genericAction:
|
||||
break
|
||||
}
|
||||
@ -360,15 +360,15 @@ public func standardTextAlertController(theme: AlertControllerTheme, title: Stri
|
||||
var dismissImpl: (() -> Void)?
|
||||
let attributedText: NSAttributedString
|
||||
if parseMarkdown {
|
||||
let font = title == nil ? Font.semibold(17.0) : Font.regular(13.0)
|
||||
let boldFont = title == nil ? Font.bold(17.0) : Font.semibold(13.0)
|
||||
let font = title == nil ? Font.semibold(theme.baseFontSize) : Font.regular(floor(theme.baseFontSize * 13.0 / 17.0))
|
||||
let boldFont = title == nil ? Font.bold(theme.baseFontSize) : Font.semibold(floor(theme.baseFontSize * 13.0 / 17.0))
|
||||
let body = MarkdownAttributeSet(font: font, textColor: theme.primaryColor)
|
||||
let bold = MarkdownAttributeSet(font: boldFont, textColor: theme.primaryColor)
|
||||
attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: body, bold: bold, link: body, linkAttribute: { _ in nil }), textAlignment: .center)
|
||||
} else {
|
||||
attributedText = NSAttributedString(string: text, font: title == nil ? Font.semibold(17.0) : Font.regular(13.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||
attributedText = NSAttributedString(string: text, font: title == nil ? Font.semibold(theme.baseFontSize) : Font.regular(floor(theme.baseFontSize * 13.0 / 17.0)), textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||
}
|
||||
let controller = AlertController(theme: theme, contentNode: TextAlertContentNode(theme: theme, title: title != nil ? NSAttributedString(string: title!, font: Font.semibold(17.0), textColor: theme.primaryColor, paragraphAlignment: .center) : nil, text: attributedText, actions: actions.map { action in
|
||||
let controller = AlertController(theme: theme, contentNode: TextAlertContentNode(theme: theme, title: title != nil ? NSAttributedString(string: title!, font: Font.semibold(theme.baseFontSize), textColor: theme.primaryColor, paragraphAlignment: .center) : nil, text: attributedText, actions: actions.map { action in
|
||||
return TextAlertAction(type: action.type, title: action.title, action: {
|
||||
dismissImpl?()
|
||||
action.action()
|
||||
|
@ -85,6 +85,7 @@ private func displayLineFrame(frame: CGRect, isRTL: Bool, boundingRect: CGRect,
|
||||
public final class TextNodeLayoutArguments {
|
||||
public let attributedString: NSAttributedString?
|
||||
public let backgroundColor: UIColor?
|
||||
public let minimumNumberOfLines: Int
|
||||
public let maximumNumberOfLines: Int
|
||||
public let truncationType: CTLineTruncationType
|
||||
public let constrainedSize: CGSize
|
||||
@ -95,9 +96,10 @@ public final class TextNodeLayoutArguments {
|
||||
public let lineColor: UIColor?
|
||||
public let textShadowColor: UIColor?
|
||||
|
||||
public init(attributedString: NSAttributedString?, backgroundColor: UIColor? = nil, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, constrainedSize: CGSize, alignment: NSTextAlignment = .natural, lineSpacing: CGFloat = 0.12, cutout: TextNodeCutout? = nil, insets: UIEdgeInsets = UIEdgeInsets(), lineColor: UIColor? = nil, textShadowColor: UIColor? = nil) {
|
||||
public init(attributedString: NSAttributedString?, backgroundColor: UIColor? = nil, minimumNumberOfLines: Int = 0, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, constrainedSize: CGSize, alignment: NSTextAlignment = .natural, lineSpacing: CGFloat = 0.12, cutout: TextNodeCutout? = nil, insets: UIEdgeInsets = UIEdgeInsets(), lineColor: UIColor? = nil, textShadowColor: UIColor? = nil) {
|
||||
self.attributedString = attributedString
|
||||
self.backgroundColor = backgroundColor
|
||||
self.minimumNumberOfLines = minimumNumberOfLines
|
||||
self.maximumNumberOfLines = maximumNumberOfLines
|
||||
self.truncationType = truncationType
|
||||
self.constrainedSize = constrainedSize
|
||||
@ -778,7 +780,7 @@ public class TextNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
private class func calculateLayout(attributedString: NSAttributedString?, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, backgroundColor: UIColor?, constrainedSize: CGSize, alignment: NSTextAlignment, lineSpacingFactor: CGFloat, cutout: TextNodeCutout?, insets: UIEdgeInsets, lineColor: UIColor?, textShadowColor: UIColor?) -> TextNodeLayout {
|
||||
private class func calculateLayout(attributedString: NSAttributedString?, minimumNumberOfLines: Int, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, backgroundColor: UIColor?, constrainedSize: CGSize, alignment: NSTextAlignment, lineSpacingFactor: CGFloat, cutout: TextNodeCutout?, insets: UIEdgeInsets, lineColor: UIColor?, textShadowColor: UIColor?) -> TextNodeLayout {
|
||||
if let attributedString = attributedString {
|
||||
let stringLength = attributedString.length
|
||||
|
||||
@ -997,6 +999,17 @@ public class TextNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
|
||||
if lines.count < minimumNumberOfLines {
|
||||
var lineCount = lines.count
|
||||
while lineCount < minimumNumberOfLines {
|
||||
if lineCount != 0 {
|
||||
layoutSize.height += fontLineSpacing
|
||||
}
|
||||
layoutSize.height += fontLineHeight
|
||||
lineCount += 1
|
||||
}
|
||||
}
|
||||
|
||||
return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, alignment: alignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(width: ceil(layoutSize.width) + insets.left + insets.right, height: ceil(layoutSize.height) + insets.top + insets.bottom), rawTextSize: CGSize(width: ceil(rawLayoutSize.width) + insets.left + insets.right, height: ceil(rawLayoutSize.height) + insets.top + insets.bottom), truncated: truncated, firstLineOffset: firstLineOffset, lines: lines, blockQuotes: blockQuotes, backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor)
|
||||
} else {
|
||||
return TextNodeLayout(attributedString: attributedString, maximumNumberOfLines: maximumNumberOfLines, truncationType: truncationType, constrainedSize: constrainedSize, alignment: alignment, lineSpacing: lineSpacingFactor, cutout: cutout, insets: insets, size: CGSize(), rawTextSize: CGSize(), truncated: false, firstLineOffset: 0.0, lines: [], blockQuotes: [], backgroundColor: backgroundColor, lineColor: lineColor, textShadowColor: textShadowColor)
|
||||
@ -1143,11 +1156,11 @@ public class TextNode: ASDisplayNode {
|
||||
if stringMatch {
|
||||
layout = existingLayout
|
||||
} else {
|
||||
layout = TextNode.calculateLayout(attributedString: arguments.attributedString, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor)
|
||||
layout = TextNode.calculateLayout(attributedString: arguments.attributedString, minimumNumberOfLines: arguments.minimumNumberOfLines, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor)
|
||||
updated = true
|
||||
}
|
||||
} else {
|
||||
layout = TextNode.calculateLayout(attributedString: arguments.attributedString, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor)
|
||||
layout = TextNode.calculateLayout(attributedString: arguments.attributedString, minimumNumberOfLines: arguments.minimumNumberOfLines, maximumNumberOfLines: arguments.maximumNumberOfLines, truncationType: arguments.truncationType, backgroundColor: arguments.backgroundColor, constrainedSize: arguments.constrainedSize, alignment: arguments.alignment, lineSpacingFactor: arguments.lineSpacing, cutout: arguments.cutout, insets: arguments.insets, lineColor: arguments.lineColor, textShadowColor: arguments.textShadowColor)
|
||||
updated = true
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ public final class HashtagSearchController: TelegramBaseController {
|
||||
self.title = query
|
||||
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil)
|
||||
|
||||
let chatListPresentationData = ChatListPresentationData(theme: self.presentationData.theme, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations)
|
||||
let chatListPresentationData = ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.fontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: self.presentationData.disableAnimations)
|
||||
|
||||
let location: SearchMessagesLocation = .general
|
||||
let search = searchMessages(account: context.account, location: location, query: query, state: nil)
|
||||
@ -79,7 +79,7 @@ public final class HashtagSearchController: TelegramBaseController {
|
||||
let previousEntries = previousSearchItems.swap(entries)
|
||||
|
||||
let firstTime = previousEntries == nil
|
||||
let transition = chatListSearchContainerPreparedTransition(from: previousEntries ?? [], to: entries, displayingResults: true, context: strongSelf.context, enableHeaders: false, filter: [], interaction: interaction, peerContextAction: nil)
|
||||
let transition = chatListSearchContainerPreparedTransition(from: previousEntries ?? [], to: entries, displayingResults: true, context: strongSelf.context, presentationData: strongSelf.presentationData, enableHeaders: false, filter: [], interaction: interaction, peerContextAction: nil)
|
||||
strongSelf.controllerNode.enqueueTransition(transition, firstTime: firstTime)
|
||||
}
|
||||
})
|
||||
|
@ -139,8 +139,7 @@ public enum ItemListAvatarAndNameInfoItemMode {
|
||||
|
||||
public class ItemListAvatarAndNameInfoItem: ListViewItem, ItemListItem {
|
||||
let account: Account
|
||||
let theme: PresentationTheme
|
||||
let strings: PresentationStrings
|
||||
let presentationData: ItemListPresentationData
|
||||
let dateTimeFormat: PresentationDateTimeFormat
|
||||
let mode: ItemListAvatarAndNameInfoItemMode
|
||||
let peer: Peer?
|
||||
@ -162,10 +161,9 @@ public class ItemListAvatarAndNameInfoItem: ListViewItem, ItemListItem {
|
||||
|
||||
public let selectable: Bool
|
||||
|
||||
public init(account: Account, theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, mode: ItemListAvatarAndNameInfoItemMode, peer: Peer?, presence: PeerPresence?, label: String? = nil, cachedData: CachedPeerData?, 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(account: Account, presentationData: ItemListPresentationData, dateTimeFormat: PresentationDateTimeFormat, mode: ItemListAvatarAndNameInfoItemMode, peer: Peer?, presence: PeerPresence?, label: String? = nil, cachedData: CachedPeerData?, 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.account = account
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.presentationData = presentationData
|
||||
self.dateTimeFormat = dateTimeFormat
|
||||
self.mode = mode
|
||||
self.peer = peer
|
||||
@ -234,8 +232,6 @@ public class ItemListAvatarAndNameInfoItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
|
||||
private let avatarFont = avatarPlaceholderFont(size: 28.0)
|
||||
private let nameFont = Font.medium(19.0)
|
||||
private let statusFont = Font.regular(15.0)
|
||||
|
||||
public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNode, ItemListItemFocusableNode, UITextFieldDelegate {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
@ -362,20 +358,23 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
||||
return { item, params, neighbors in
|
||||
let baseWidth = params.width - params.leftInset - params.rightInset
|
||||
|
||||
let nameFont = Font.medium(floor(item.presentationData.fontSize.itemListBaseFontSize * 19.0 / 17.0))
|
||||
let statusFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 15.0 / 17.0))
|
||||
|
||||
var updatedTheme: PresentationTheme?
|
||||
|
||||
if currentItem?.theme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
}
|
||||
|
||||
var credibilityIconImage: UIImage?
|
||||
var credibilityIconOffset: CGFloat = 4.0
|
||||
if let peer = item.peer {
|
||||
if peer.isScam {
|
||||
credibilityIconImage = PresentationResourcesChatList.scamIcon(item.theme, type: .regular)
|
||||
credibilityIconImage = PresentationResourcesChatList.scamIcon(item.presentationData.theme, type: .regular)
|
||||
credibilityIconOffset = 6.0
|
||||
} else if peer.isVerified {
|
||||
credibilityIconImage = PresentationResourcesItemList.verifiedPeerIcon(item.theme)
|
||||
credibilityIconImage = PresentationResourcesItemList.verifiedPeerIcon(item.presentationData.theme)
|
||||
}
|
||||
}
|
||||
|
||||
@ -398,7 +397,7 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
||||
nameMaximumNumberOfLines = 2
|
||||
}
|
||||
|
||||
let (nameNodeLayout, nameNodeApply) = layoutNameNode(TextNodeLayoutArguments(attributedString: NSAttributedString(string: displayTitle.composedDisplayTitle(strings: item.strings), font: nameFont, textColor: item.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(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 = ""
|
||||
let statusColor: UIColor
|
||||
@ -415,64 +414,64 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
||||
}
|
||||
statusText += "@\(username)"
|
||||
}
|
||||
statusColor = item.theme.list.itemSecondaryTextColor
|
||||
statusColor = item.presentationData.theme.list.itemSecondaryTextColor
|
||||
case .generic, .contact, .editSettings:
|
||||
if let label = item.label {
|
||||
statusText = label
|
||||
statusColor = item.theme.list.itemSecondaryTextColor
|
||||
statusColor = item.presentationData.theme.list.itemSecondaryTextColor
|
||||
} else if peer.flags.contains(.isSupport), !servicePeer {
|
||||
statusText = item.strings.Bot_GenericSupportStatus
|
||||
statusColor = item.theme.list.itemSecondaryTextColor
|
||||
statusText = item.presentationData.strings.Bot_GenericSupportStatus
|
||||
statusColor = item.presentationData.theme.list.itemSecondaryTextColor
|
||||
} else if let _ = peer.botInfo {
|
||||
statusText = item.strings.Bot_GenericBotStatus
|
||||
statusColor = item.theme.list.itemSecondaryTextColor
|
||||
statusText = item.presentationData.strings.Bot_GenericBotStatus
|
||||
statusColor = item.presentationData.theme.list.itemSecondaryTextColor
|
||||
} else if case .generic = item.mode, !servicePeer {
|
||||
let presence = (item.presence as? TelegramUserPresence) ?? TelegramUserPresence(status: .none, lastActivity: 0)
|
||||
let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970
|
||||
let (string, activity) = stringAndActivityForUserPresence(strings: item.strings, dateTimeFormat: item.dateTimeFormat, presence: presence, relativeTo: Int32(timestamp), expanded: true)
|
||||
let (string, activity) = stringAndActivityForUserPresence(strings: item.presentationData.strings, dateTimeFormat: item.dateTimeFormat, presence: presence, relativeTo: Int32(timestamp), expanded: true)
|
||||
statusText = string
|
||||
if activity {
|
||||
statusColor = item.theme.list.itemAccentColor
|
||||
statusColor = item.presentationData.theme.list.itemAccentColor
|
||||
} else {
|
||||
statusColor = item.theme.list.itemSecondaryTextColor
|
||||
statusColor = item.presentationData.theme.list.itemSecondaryTextColor
|
||||
}
|
||||
} else {
|
||||
statusText = ""
|
||||
statusColor = item.theme.list.itemPrimaryTextColor
|
||||
statusColor = item.presentationData.theme.list.itemPrimaryTextColor
|
||||
}
|
||||
}
|
||||
} else if let channel = item.peer as? TelegramChannel {
|
||||
if let cachedChannelData = item.cachedData as? CachedChannelData, let memberCount = cachedChannelData.participantsSummary.memberCount {
|
||||
if case .group = channel.info {
|
||||
if memberCount == 0 {
|
||||
statusText = item.strings.Group_Status
|
||||
statusText = item.presentationData.strings.Group_Status
|
||||
} else {
|
||||
statusText = item.strings.Conversation_StatusMembers(memberCount)
|
||||
statusText = item.presentationData.strings.Conversation_StatusMembers(memberCount)
|
||||
}
|
||||
} else {
|
||||
if memberCount == 0 {
|
||||
statusText = item.strings.Channel_Status
|
||||
statusText = item.presentationData.strings.Channel_Status
|
||||
} else {
|
||||
statusText = item.strings.Conversation_StatusSubscribers(memberCount)
|
||||
statusText = item.presentationData.strings.Conversation_StatusSubscribers(memberCount)
|
||||
}
|
||||
}
|
||||
statusColor = item.theme.list.itemSecondaryTextColor
|
||||
statusColor = item.presentationData.theme.list.itemSecondaryTextColor
|
||||
} else {
|
||||
switch channel.info {
|
||||
case .broadcast:
|
||||
statusText = item.strings.Channel_Status
|
||||
statusColor = item.theme.list.itemSecondaryTextColor
|
||||
statusText = item.presentationData.strings.Channel_Status
|
||||
statusColor = item.presentationData.theme.list.itemSecondaryTextColor
|
||||
case .group:
|
||||
statusText = item.strings.Group_Status
|
||||
statusColor = item.theme.list.itemSecondaryTextColor
|
||||
statusText = item.presentationData.strings.Group_Status
|
||||
statusColor = item.presentationData.theme.list.itemSecondaryTextColor
|
||||
}
|
||||
}
|
||||
} else if let group = item.peer as? TelegramGroup {
|
||||
statusText = item.strings.GroupInfo_ParticipantCount(Int32(group.participantCount))
|
||||
statusColor = item.theme.list.itemSecondaryTextColor
|
||||
statusText = item.presentationData.strings.GroupInfo_ParticipantCount(Int32(group.participantCount))
|
||||
statusColor = item.presentationData.theme.list.itemSecondaryTextColor
|
||||
} else {
|
||||
statusText = ""
|
||||
statusColor = item.theme.list.itemPrimaryTextColor
|
||||
statusColor = item.presentationData.theme.list.itemPrimaryTextColor
|
||||
}
|
||||
|
||||
var availableStatusWidth = baseWidth - 20
|
||||
@ -484,36 +483,42 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
||||
|
||||
let separatorHeight = UIScreenPixel
|
||||
|
||||
let nameSpacing: CGFloat = 3.0
|
||||
|
||||
let hasCorners = itemListHasRoundedBlockLayout(params)
|
||||
let contentSize: CGSize
|
||||
var insets: UIEdgeInsets
|
||||
let itemBackgroundColor: UIColor
|
||||
let itemSeparatorColor: UIColor
|
||||
switch item.style {
|
||||
case .plain:
|
||||
itemBackgroundColor = item.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.theme.list.itemPlainSeparatorColor
|
||||
contentSize = CGSize(width: params.width, height: 96.0)
|
||||
insets = itemListNeighborsPlainInsets(neighbors)
|
||||
case let .blocks(withTopInset, withExtendedBottomInset):
|
||||
itemBackgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
itemSeparatorColor = item.theme.list.itemBlocksSeparatorColor
|
||||
contentSize = CGSize(width: params.width, height: 92.0)
|
||||
if withTopInset || hasCorners {
|
||||
insets = itemListNeighborsGroupedInsets(neighbors)
|
||||
} else {
|
||||
let topInset: CGFloat
|
||||
switch neighbors.top {
|
||||
case .sameSection, .none:
|
||||
topInset = 0.0
|
||||
case .otherSection:
|
||||
topInset = separatorHeight + 35.0
|
||||
}
|
||||
insets = UIEdgeInsets(top: topInset, left: 0.0, bottom: separatorHeight, right: 0.0)
|
||||
if withExtendedBottomInset {
|
||||
insets.bottom += 12.0
|
||||
}
|
||||
case .plain:
|
||||
let verticalInset: CGFloat = 15.0
|
||||
itemBackgroundColor = item.presentationData.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
let baseHeight = nameNodeLayout.size.height + nameSpacing + statusNodeLayout.size.height + 40.0
|
||||
contentSize = CGSize(width: params.width, height: max(baseHeight, verticalInset * 2.0 + 66.0))
|
||||
insets = itemListNeighborsPlainInsets(neighbors)
|
||||
case let .blocks(withTopInset, withExtendedBottomInset):
|
||||
let verticalInset: CGFloat = 13.0
|
||||
itemBackgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
let baseHeight = nameNodeLayout.size.height + nameSpacing + statusNodeLayout.size.height + 30.0
|
||||
contentSize = CGSize(width: params.width, height: max(baseHeight, verticalInset * 2.0 + 66.0))
|
||||
if withTopInset || hasCorners {
|
||||
insets = itemListNeighborsGroupedInsets(neighbors)
|
||||
} else {
|
||||
let topInset: CGFloat
|
||||
switch neighbors.top {
|
||||
case .sameSection, .none:
|
||||
topInset = 0.0
|
||||
case .otherSection:
|
||||
topInset = separatorHeight + 35.0
|
||||
}
|
||||
insets = UIEdgeInsets(top: topInset, left: 0.0, bottom: separatorHeight, right: 0.0)
|
||||
if withExtendedBottomInset {
|
||||
insets.bottom += 12.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var updateAvatarOverlayImage: UIImage?
|
||||
@ -538,15 +543,15 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
||||
strongSelf.topStripeNode.backgroundColor = itemSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = itemSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = itemBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.theme.list.itemHighlightedBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
|
||||
strongSelf.inputSeparator?.backgroundColor = itemSeparatorColor
|
||||
strongSelf.callButton.setImage(PresentationResourcesChat.chatInfoCallButtonImage(item.theme), for: [])
|
||||
strongSelf.callButton.setImage(PresentationResourcesChat.chatInfoCallButtonImage(item.presentationData.theme), for: [])
|
||||
|
||||
strongSelf.inputFirstClearButton?.setImage(generateClearIcon(color: item.theme.list.inputClearButtonColor), for: [])
|
||||
strongSelf.inputSecondClearButton?.setImage(generateClearIcon(color: item.theme.list.inputClearButtonColor), for: [])
|
||||
strongSelf.inputFirstClearButton?.setImage(generateClearIcon(color: item.presentationData.theme.list.inputClearButtonColor), for: [])
|
||||
strongSelf.inputSecondClearButton?.setImage(generateClearIcon(color: item.presentationData.theme.list.inputClearButtonColor), for: [])
|
||||
|
||||
updatedArrowImage = PresentationResourcesItemList.disclosureArrowImage(item.theme)
|
||||
updatedArrowImage = PresentationResourcesItemList.disclosureArrowImage(item.presentationData.theme)
|
||||
}
|
||||
|
||||
if item.updatingImage != nil {
|
||||
@ -584,11 +589,8 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
||||
strongSelf.callButton.removeFromSupernode()
|
||||
}
|
||||
|
||||
let avatarOriginY: CGFloat
|
||||
switch item.style {
|
||||
case .plain:
|
||||
avatarOriginY = 15.0
|
||||
|
||||
if strongSelf.backgroundNode.supernode != nil {
|
||||
strongSelf.backgroundNode.removeFromSupernode()
|
||||
}
|
||||
@ -602,8 +604,6 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
||||
strongSelf.maskNode.removeFromSupernode()
|
||||
}
|
||||
case .blocks:
|
||||
avatarOriginY = 13.0
|
||||
|
||||
if strongSelf.backgroundNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0)
|
||||
}
|
||||
@ -637,7 +637,7 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
||||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: params.width, height: contentSize.height))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
@ -668,10 +668,10 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
||||
overrideImage = .deletedIcon
|
||||
}
|
||||
|
||||
strongSelf.avatarNode.setPeer(account: item.account, theme: item.theme, peer: peer, overrideImage: overrideImage, emptyColor: ignoreEmpty ? nil : item.theme.list.mediaPlaceholderColor, synchronousLoad: synchronousLoads)
|
||||
strongSelf.avatarNode.setPeer(account: item.account, theme: item.presentationData.theme, peer: peer, overrideImage: overrideImage, emptyColor: ignoreEmpty ? nil : item.presentationData.theme.list.mediaPlaceholderColor, synchronousLoad: synchronousLoads)
|
||||
}
|
||||
|
||||
let avatarFrame = CGRect(origin: CGPoint(x: params.leftInset + 15.0, y: avatarOriginY), 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))
|
||||
strongSelf.avatarNode.frame = avatarFrame
|
||||
strongSelf.updatingAvatarOverlay.frame = avatarFrame
|
||||
|
||||
@ -711,7 +711,7 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
||||
if strongSelf.inputSeparator == nil {
|
||||
animateIn = true
|
||||
}
|
||||
let keyboardAppearance = item.theme.rootController.keyboardColor.keyboardAppearance
|
||||
let keyboardAppearance = item.presentationData.theme.rootController.keyboardColor.keyboardAppearance
|
||||
switch editingName {
|
||||
case let .personName(firstName, lastName, _):
|
||||
if strongSelf.inputSeparator == nil {
|
||||
@ -725,10 +725,10 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
||||
if strongSelf.inputFirstField == nil {
|
||||
let inputFirstField = TextFieldNodeView()
|
||||
inputFirstField.delegate = self
|
||||
inputFirstField.font = Font.regular(17.0)
|
||||
inputFirstField.font = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
inputFirstField.autocorrectionType = .no
|
||||
inputFirstField.returnKeyType = .next
|
||||
inputFirstField.attributedText = NSAttributedString(string: firstName, font: Font.regular(17.0), textColor: item.theme.list.itemPrimaryTextColor)
|
||||
inputFirstField.attributedText = NSAttributedString(string: firstName, font: Font.regular(item.presentationData.fontSize.itemListBaseFontSize), textColor: item.presentationData.theme.list.itemPrimaryTextColor)
|
||||
strongSelf.inputFirstField = inputFirstField
|
||||
strongSelf.view.addSubview(inputFirstField)
|
||||
inputFirstField.addTarget(self, action: #selector(strongSelf.textFieldDidChange(_:)), for: .editingChanged)
|
||||
@ -736,8 +736,8 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
||||
strongSelf.inputFirstField?.text = firstName
|
||||
}
|
||||
|
||||
strongSelf.inputFirstField?.textColor = item.theme.list.itemPrimaryTextColor
|
||||
strongSelf.inputFirstField?.attributedPlaceholder = NSAttributedString(string: item.strings.UserInfo_FirstNamePlaceholder, font: Font.regular(17.0), textColor: item.theme.list.itemPlaceholderTextColor)
|
||||
strongSelf.inputFirstField?.textColor = item.presentationData.theme.list.itemPrimaryTextColor
|
||||
strongSelf.inputFirstField?.attributedPlaceholder = NSAttributedString(string: item.presentationData.strings.UserInfo_FirstNamePlaceholder, font: Font.regular(item.presentationData.fontSize.itemListBaseFontSize), textColor: item.presentationData.theme.list.itemPlaceholderTextColor)
|
||||
if strongSelf.inputFirstField?.keyboardAppearance != keyboardAppearance {
|
||||
strongSelf.inputFirstField?.keyboardAppearance = keyboardAppearance
|
||||
}
|
||||
@ -747,7 +747,7 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
||||
strongSelf.inputFirstClearButton?.imageNode.displaysAsynchronously = false
|
||||
strongSelf.inputFirstClearButton?.imageNode.displayWithoutProcessing = true
|
||||
strongSelf.inputFirstClearButton?.displaysAsynchronously = false
|
||||
strongSelf.inputFirstClearButton?.setImage(generateClearIcon(color: item.theme.list.inputClearButtonColor), for: [])
|
||||
strongSelf.inputFirstClearButton?.setImage(generateClearIcon(color: item.presentationData.theme.list.inputClearButtonColor), for: [])
|
||||
strongSelf.inputFirstClearButton?.addTarget(strongSelf, action: #selector(strongSelf.firstClearPressed), forControlEvents: .touchUpInside)
|
||||
strongSelf.inputFirstClearButton?.isHidden = true
|
||||
strongSelf.addSubnode(strongSelf.inputFirstClearButton!)
|
||||
@ -756,10 +756,10 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
||||
if strongSelf.inputSecondField == nil {
|
||||
let inputSecondField = TextFieldNodeView()
|
||||
inputSecondField.delegate = self
|
||||
inputSecondField.font = Font.regular(17.0)
|
||||
inputSecondField.font = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
inputSecondField.autocorrectionType = .no
|
||||
inputSecondField.returnKeyType = .done
|
||||
inputSecondField.attributedText = NSAttributedString(string: lastName, font: Font.regular(17.0), textColor: item.theme.list.itemPrimaryTextColor)
|
||||
inputSecondField.attributedText = NSAttributedString(string: lastName, font: Font.regular(item.presentationData.fontSize.itemListBaseFontSize), textColor: item.presentationData.theme.list.itemPrimaryTextColor)
|
||||
strongSelf.inputSecondField = inputSecondField
|
||||
strongSelf.view.addSubview(inputSecondField)
|
||||
inputSecondField.addTarget(self, action: #selector(strongSelf.textFieldDidChange(_:)), for: .editingChanged)
|
||||
@ -767,8 +767,8 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
||||
strongSelf.inputSecondField?.text = lastName
|
||||
}
|
||||
|
||||
strongSelf.inputSecondField?.textColor = item.theme.list.itemPrimaryTextColor
|
||||
strongSelf.inputSecondField?.attributedPlaceholder = NSAttributedString(string: item.strings.UserInfo_LastNamePlaceholder, font: Font.regular(17.0), textColor: item.theme.list.itemPlaceholderTextColor)
|
||||
strongSelf.inputSecondField?.textColor = item.presentationData.theme.list.itemPrimaryTextColor
|
||||
strongSelf.inputSecondField?.attributedPlaceholder = NSAttributedString(string: item.presentationData.strings.UserInfo_LastNamePlaceholder, font: Font.regular(item.presentationData.fontSize.itemListBaseFontSize), textColor: item.presentationData.theme.list.itemPlaceholderTextColor)
|
||||
if strongSelf.inputSecondField?.keyboardAppearance != keyboardAppearance {
|
||||
strongSelf.inputSecondField?.keyboardAppearance = keyboardAppearance
|
||||
}
|
||||
@ -778,7 +778,7 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
||||
strongSelf.inputSecondClearButton?.imageNode.displaysAsynchronously = false
|
||||
strongSelf.inputSecondClearButton?.imageNode.displayWithoutProcessing = true
|
||||
strongSelf.inputSecondClearButton?.displaysAsynchronously = false
|
||||
strongSelf.inputSecondClearButton?.setImage(generateClearIcon(color: item.theme.list.inputClearButtonColor), for: [])
|
||||
strongSelf.inputSecondClearButton?.setImage(generateClearIcon(color: item.presentationData.theme.list.inputClearButtonColor), for: [])
|
||||
strongSelf.inputSecondClearButton?.addTarget(strongSelf, action: #selector(strongSelf.secondClearPressed), forControlEvents: .touchUpInside)
|
||||
strongSelf.inputSecondClearButton?.isHidden = true
|
||||
strongSelf.addSubnode(strongSelf.inputSecondClearButton!)
|
||||
@ -812,24 +812,24 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
||||
if strongSelf.inputFirstField == nil {
|
||||
let inputFirstField = TextFieldNodeView()
|
||||
inputFirstField.delegate = self
|
||||
inputFirstField.font = Font.regular(19.0)
|
||||
inputFirstField.font = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 19.0 / 17.0))
|
||||
inputFirstField.autocorrectionType = .no
|
||||
inputFirstField.attributedText = NSAttributedString(string: title, font: Font.regular(19.0), textColor: item.theme.list.itemPrimaryTextColor)
|
||||
inputFirstField.attributedText = NSAttributedString(string: title, font: Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 19.0 / 17.0)), textColor: item.presentationData.theme.list.itemPrimaryTextColor)
|
||||
strongSelf.inputFirstField = inputFirstField
|
||||
strongSelf.view.addSubview(inputFirstField)
|
||||
inputFirstField.addTarget(self, action: #selector(strongSelf.textFieldDidChange(_:)), for: .editingChanged)
|
||||
} else if strongSelf.inputFirstField?.text != title {
|
||||
strongSelf.inputFirstField?.text = title
|
||||
}
|
||||
strongSelf.inputFirstField?.textColor = item.theme.list.itemPrimaryTextColor
|
||||
strongSelf.inputFirstField?.textColor = item.presentationData.theme.list.itemPrimaryTextColor
|
||||
let placeholder: String
|
||||
switch type {
|
||||
case .group:
|
||||
placeholder = item.strings.GroupInfo_GroupNamePlaceholder
|
||||
placeholder = item.presentationData.strings.GroupInfo_GroupNamePlaceholder
|
||||
case .channel:
|
||||
placeholder = item.strings.GroupInfo_ChannelListNamePlaceholder
|
||||
placeholder = item.presentationData.strings.GroupInfo_ChannelListNamePlaceholder
|
||||
}
|
||||
strongSelf.inputFirstField?.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(19.0), textColor: item.theme.list.itemPlaceholderTextColor)
|
||||
strongSelf.inputFirstField?.attributedPlaceholder = NSAttributedString(string: placeholder, font: Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 19.0 / 17.0)), textColor: item.presentationData.theme.list.itemPlaceholderTextColor)
|
||||
if strongSelf.inputFirstField?.keyboardAppearance != keyboardAppearance {
|
||||
strongSelf.inputFirstField?.keyboardAppearance = keyboardAppearance
|
||||
}
|
||||
@ -839,7 +839,7 @@ public class ItemListAvatarAndNameInfoItemNode: ListViewItemNode, ItemListItemNo
|
||||
strongSelf.inputFirstClearButton?.imageNode.displaysAsynchronously = false
|
||||
strongSelf.inputFirstClearButton?.imageNode.displayWithoutProcessing = true
|
||||
strongSelf.inputFirstClearButton?.displaysAsynchronously = false
|
||||
strongSelf.inputFirstClearButton?.setImage(generateClearIcon(color: item.theme.list.inputClearButtonColor), for: [])
|
||||
strongSelf.inputFirstClearButton?.setImage(generateClearIcon(color: item.presentationData.theme.list.inputClearButtonColor), for: [])
|
||||
strongSelf.inputFirstClearButton?.addTarget(strongSelf, action: #selector(strongSelf.firstClearPressed), forControlEvents: .touchUpInside)
|
||||
strongSelf.inputFirstClearButton?.isHidden = true
|
||||
strongSelf.addSubnode(strongSelf.inputFirstClearButton!)
|
||||
|
@ -13,7 +13,7 @@ public enum ItemListPeerActionItemHeight {
|
||||
}
|
||||
|
||||
public class ItemListPeerActionItem: ListViewItem, ItemListItem {
|
||||
let theme: PresentationTheme
|
||||
let presentationData: ItemListPresentationData
|
||||
let icon: UIImage?
|
||||
let title: String
|
||||
public let alwaysPlain: Bool
|
||||
@ -22,8 +22,8 @@ public class ItemListPeerActionItem: ListViewItem, ItemListItem {
|
||||
public let sectionId: ItemListSectionId
|
||||
let action: () -> Void
|
||||
|
||||
public init(theme: PresentationTheme, icon: UIImage?, title: String, alwaysPlain: Bool = false, sectionId: ItemListSectionId, height: ItemListPeerActionItemHeight = .peerList, editing: Bool, action: @escaping () -> Void) {
|
||||
self.theme = theme
|
||||
public init(presentationData: ItemListPresentationData, icon: UIImage?, title: String, alwaysPlain: Bool = false, sectionId: ItemListSectionId, height: ItemListPeerActionItemHeight = .peerList, editing: Bool, action: @escaping () -> Void) {
|
||||
self.presentationData = presentationData
|
||||
self.icon = icon
|
||||
self.title = title
|
||||
self.alwaysPlain = alwaysPlain
|
||||
@ -87,8 +87,6 @@ public class ItemListPeerActionItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.regular(17.0)
|
||||
|
||||
class ItemListPeerActionItemNode: ListViewItemNode {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let topStripeNode: ASDisplayNode
|
||||
@ -146,31 +144,33 @@ class ItemListPeerActionItemNode: ListViewItemNode {
|
||||
return { item, params, neighbors in
|
||||
var updatedTheme: PresentationTheme?
|
||||
|
||||
if currentItem?.theme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
}
|
||||
let leftInset: CGFloat
|
||||
let height: CGFloat
|
||||
let vertcalInset: CGFloat
|
||||
let verticalOffset: CGFloat
|
||||
switch item.height {
|
||||
case .generic:
|
||||
height = 44.0
|
||||
verticalOffset = -3.0
|
||||
vertcalInset = 11.0
|
||||
verticalOffset = 0.0
|
||||
leftInset = 59.0 + params.leftInset
|
||||
case .peerList:
|
||||
height = 50.0
|
||||
vertcalInset = 14.0
|
||||
verticalOffset = 0.0
|
||||
leftInset = 65.0 + params.leftInset
|
||||
}
|
||||
|
||||
let editingOffset: CGFloat = (item.editing ? 38.0 : 0.0)
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: item.theme.list.itemAccentColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - editingOffset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: item.presentationData.theme.list.itemAccentColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - editingOffset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let separatorHeight = UIScreenPixel
|
||||
|
||||
let insets = itemListNeighborsGroupedInsets(neighbors)
|
||||
let contentSize = CGSize(width: params.width, height: height)
|
||||
let contentSize = CGSize(width: params.width, height: titleLayout.size.height + vertcalInset * 2.0)
|
||||
|
||||
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
||||
let layoutSize = layout.size
|
||||
@ -183,10 +183,10 @@ class ItemListPeerActionItemNode: ListViewItemNode {
|
||||
strongSelf.activateArea.accessibilityLabel = item.title
|
||||
|
||||
if let _ = updatedTheme {
|
||||
strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.theme.list.itemHighlightedBackgroundColor
|
||||
strongSelf.topStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
}
|
||||
|
||||
let _ = titleApply()
|
||||
@ -240,16 +240,16 @@ class ItemListPeerActionItemNode: ListViewItemNode {
|
||||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight))
|
||||
transition.updateFrame(node: strongSelf.bottomStripeNode, frame: CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)))
|
||||
|
||||
transition.updateFrame(node: strongSelf.titleNode, frame: CGRect(origin: CGPoint(x: leftInset + editingOffset, y: 14.0 + verticalOffset), size: titleLayout.size))
|
||||
transition.updateFrame(node: strongSelf.titleNode, frame: CGRect(origin: CGPoint(x: leftInset + editingOffset, y: vertcalInset + verticalOffset), size: titleLayout.size))
|
||||
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: height + UIScreenPixel + UIScreenPixel))
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: layout.contentSize.height + UIScreenPixel + UIScreenPixel))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -107,8 +107,7 @@ public struct ItemListPeerItemRevealOptions {
|
||||
}
|
||||
|
||||
public final class ItemListPeerItem: ListViewItem, ItemListItem {
|
||||
let theme: PresentationTheme
|
||||
let strings: PresentationStrings
|
||||
let presentationData: ItemListPresentationData
|
||||
let dateTimeFormat: PresentationDateTimeFormat
|
||||
let nameDisplayOrder: PresentationPersonNameOrder
|
||||
let account: Account
|
||||
@ -136,9 +135,8 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem {
|
||||
let noInsets: Bool
|
||||
public let tag: ItemListItemTag?
|
||||
|
||||
public init(theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, account: Account, peer: Peer, height: ItemListPeerItemHeight = .peerList, aliasHandling: ItemListPeerItemAliasHandling = .standard, nameColor: ItemListPeerItemNameColor = .primary, nameStyle: ItemListPeerItemNameStyle = .distinctBold, presence: PeerPresence?, text: ItemListPeerItemText, label: ItemListPeerItemLabel, editing: ItemListPeerItemEditing, revealOptions: ItemListPeerItemRevealOptions? = nil, switchValue: ItemListPeerItemSwitch?, enabled: Bool, selectable: Bool, sectionId: ItemListSectionId, action: (() -> Void)?, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, removePeer: @escaping (PeerId) -> Void, toggleUpdated: ((Bool) -> Void)? = nil, contextAction: ((ASDisplayNode, ContextGesture?) -> Void)? = nil, hasTopStripe: Bool = true, hasTopGroupInset: Bool = true, noInsets: Bool = false, tag: ItemListItemTag? = nil) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
public init(presentationData: ItemListPresentationData, dateTimeFormat: PresentationDateTimeFormat, nameDisplayOrder: PresentationPersonNameOrder, account: Account, peer: Peer, height: ItemListPeerItemHeight = .peerList, aliasHandling: ItemListPeerItemAliasHandling = .standard, nameColor: ItemListPeerItemNameColor = .primary, nameStyle: ItemListPeerItemNameStyle = .distinctBold, presence: PeerPresence?, text: ItemListPeerItemText, label: ItemListPeerItemLabel, editing: ItemListPeerItemEditing, revealOptions: ItemListPeerItemRevealOptions? = nil, switchValue: ItemListPeerItemSwitch?, enabled: Bool, selectable: Bool, sectionId: ItemListSectionId, action: (() -> Void)?, setPeerIdWithRevealedOptions: @escaping (PeerId?, PeerId?) -> Void, removePeer: @escaping (PeerId) -> Void, toggleUpdated: ((Bool) -> Void)? = nil, contextAction: ((ASDisplayNode, ContextGesture?) -> Void)? = nil, hasTopStripe: Bool = true, hasTopGroupInset: Bool = true, noInsets: Bool = false, tag: ItemListItemTag? = nil) {
|
||||
self.presentationData = presentationData
|
||||
self.dateTimeFormat = dateTimeFormat
|
||||
self.nameDisplayOrder = nameDisplayOrder
|
||||
self.account = account
|
||||
@ -211,11 +209,6 @@ public final class ItemListPeerItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.regular(17.0)
|
||||
private let titleBoldFont = Font.medium(17.0)
|
||||
private let statusFont = Font.regular(14.0)
|
||||
private let labelFont = Font.regular(13.0)
|
||||
private let labelDisclosureFont = Font.regular(17.0)
|
||||
private let avatarFont = avatarPlaceholderFont(size: 15.0)
|
||||
private let badgeFont = Font.regular(15.0)
|
||||
|
||||
@ -344,17 +337,26 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
var updateArrowImage: UIImage?
|
||||
var updatedTheme: PresentationTheme?
|
||||
|
||||
let statusFontSize: CGFloat = floor(item.presentationData.fontSize.itemListBaseFontSize * 14.0 / 17.0)
|
||||
let labelFontSize: CGFloat = floor(item.presentationData.fontSize.itemListBaseFontSize * 13.0 / 17.0)
|
||||
|
||||
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
let titleBoldFont = Font.medium(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
let statusFont = Font.regular(statusFontSize)
|
||||
let labelFont = Font.regular(labelFontSize)
|
||||
let labelDisclosureFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
|
||||
var updatedLabelBadgeImage: UIImage?
|
||||
|
||||
var badgeColor: UIColor?
|
||||
if case .badge = item.label {
|
||||
badgeColor = item.theme.list.itemAccentColor
|
||||
badgeColor = item.presentationData.theme.list.itemAccentColor
|
||||
}
|
||||
|
||||
let badgeDiameter: CGFloat = 20.0
|
||||
if currentItem?.theme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
updateArrowImage = PresentationResourcesItemList.disclosureArrowImage(item.theme)
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
updateArrowImage = PresentationResourcesItemList.disclosureArrowImage(item.presentationData.theme)
|
||||
if let badgeColor = badgeColor {
|
||||
updatedLabelBadgeImage = generateStretchableFilledCircleImage(diameter: badgeDiameter, color: badgeColor)
|
||||
}
|
||||
@ -376,21 +378,21 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
let textColor: UIColor
|
||||
switch option.type {
|
||||
case .neutral:
|
||||
color = item.theme.list.itemDisclosureActions.constructive.fillColor
|
||||
textColor = item.theme.list.itemDisclosureActions.constructive.foregroundColor
|
||||
color = item.presentationData.theme.list.itemDisclosureActions.constructive.fillColor
|
||||
textColor = item.presentationData.theme.list.itemDisclosureActions.constructive.foregroundColor
|
||||
case .warning:
|
||||
color = item.theme.list.itemDisclosureActions.warning.fillColor
|
||||
textColor = item.theme.list.itemDisclosureActions.warning.foregroundColor
|
||||
color = item.presentationData.theme.list.itemDisclosureActions.warning.fillColor
|
||||
textColor = item.presentationData.theme.list.itemDisclosureActions.warning.foregroundColor
|
||||
case .destructive:
|
||||
color = item.theme.list.itemDisclosureActions.destructive.fillColor
|
||||
textColor = item.theme.list.itemDisclosureActions.destructive.foregroundColor
|
||||
color = item.presentationData.theme.list.itemDisclosureActions.destructive.fillColor
|
||||
textColor = item.presentationData.theme.list.itemDisclosureActions.destructive.foregroundColor
|
||||
}
|
||||
mappedOptions.append(ItemListRevealOption(key: index, title: option.title, icon: .none, color: color, textColor: textColor))
|
||||
index += 1
|
||||
}
|
||||
peerRevealOptions = mappedOptions
|
||||
} else {
|
||||
peerRevealOptions = [ItemListRevealOption(key: 0, title: item.strings.Common_Delete, icon: .none, color: item.theme.list.itemDisclosureActions.destructive.fillColor, textColor: item.theme.list.itemDisclosureActions.destructive.foregroundColor)]
|
||||
peerRevealOptions = [ItemListRevealOption(key: 0, title: item.presentationData.strings.Common_Delete, icon: .none, color: item.presentationData.theme.list.itemDisclosureActions.destructive.fillColor, textColor: item.presentationData.theme.list.itemDisclosureActions.destructive.foregroundColor)]
|
||||
}
|
||||
} else {
|
||||
peerRevealOptions = []
|
||||
@ -402,19 +404,19 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
|
||||
if let switchValue = item.switchValue {
|
||||
switch switchValue.style {
|
||||
case .standard:
|
||||
if currentSwitchNode == nil {
|
||||
currentSwitchNode = SwitchNode()
|
||||
}
|
||||
rightInset += switchSize.width
|
||||
currentCheckNode = nil
|
||||
case .check:
|
||||
checkImage = PresentationResourcesItemList.checkIconImage(item.theme)
|
||||
if currentCheckNode == nil {
|
||||
currentCheckNode = ASImageNode()
|
||||
}
|
||||
rightInset += 24.0
|
||||
currentSwitchNode = nil
|
||||
case .standard:
|
||||
if currentSwitchNode == nil {
|
||||
currentSwitchNode = SwitchNode()
|
||||
}
|
||||
rightInset += switchSize.width
|
||||
currentCheckNode = nil
|
||||
case .check:
|
||||
checkImage = PresentationResourcesItemList.checkIconImage(item.presentationData.theme)
|
||||
if currentCheckNode == nil {
|
||||
currentCheckNode = ASImageNode()
|
||||
}
|
||||
rightInset += 24.0
|
||||
currentSwitchNode = nil
|
||||
}
|
||||
} else {
|
||||
currentSwitchNode = nil
|
||||
@ -423,34 +425,34 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
|
||||
let titleColor: UIColor
|
||||
switch item.nameColor {
|
||||
case .primary:
|
||||
titleColor = item.theme.list.itemPrimaryTextColor
|
||||
case .secret:
|
||||
titleColor = item.theme.chatList.secretTitleColor
|
||||
case .primary:
|
||||
titleColor = item.presentationData.theme.list.itemPrimaryTextColor
|
||||
case .secret:
|
||||
titleColor = item.presentationData.theme.chatList.secretTitleColor
|
||||
}
|
||||
|
||||
let currentBoldFont: UIFont
|
||||
switch item.nameStyle {
|
||||
case .distinctBold:
|
||||
currentBoldFont = titleBoldFont
|
||||
case .plain:
|
||||
currentBoldFont = titleFont
|
||||
case .distinctBold:
|
||||
currentBoldFont = titleBoldFont
|
||||
case .plain:
|
||||
currentBoldFont = titleFont
|
||||
}
|
||||
|
||||
if item.peer.id == item.account.peerId, case .threatSelfAsSaved = item.aliasHandling {
|
||||
titleAttributedString = NSAttributedString(string: item.strings.DialogList_SavedMessages, font: currentBoldFont, textColor: titleColor)
|
||||
titleAttributedString = NSAttributedString(string: item.presentationData.strings.DialogList_SavedMessages, font: currentBoldFont, textColor: titleColor)
|
||||
} else if let user = item.peer as? TelegramUser {
|
||||
if let firstName = user.firstName, let lastName = user.lastName, !firstName.isEmpty, !lastName.isEmpty {
|
||||
let string = NSMutableAttributedString()
|
||||
switch item.nameDisplayOrder {
|
||||
case .firstLast:
|
||||
string.append(NSAttributedString(string: firstName, font: titleFont, textColor: titleColor))
|
||||
string.append(NSAttributedString(string: " ", font: titleFont, textColor: titleColor))
|
||||
string.append(NSAttributedString(string: lastName, font: currentBoldFont, textColor: titleColor))
|
||||
case .lastFirst:
|
||||
string.append(NSAttributedString(string: lastName, font: currentBoldFont, textColor: titleColor))
|
||||
string.append(NSAttributedString(string: " ", font: titleFont, textColor: titleColor))
|
||||
string.append(NSAttributedString(string: firstName, font: titleFont, textColor: titleColor))
|
||||
case .firstLast:
|
||||
string.append(NSAttributedString(string: firstName, font: titleFont, textColor: titleColor))
|
||||
string.append(NSAttributedString(string: " ", font: titleFont, textColor: titleColor))
|
||||
string.append(NSAttributedString(string: lastName, font: currentBoldFont, textColor: titleColor))
|
||||
case .lastFirst:
|
||||
string.append(NSAttributedString(string: lastName, font: currentBoldFont, textColor: titleColor))
|
||||
string.append(NSAttributedString(string: " ", font: titleFont, textColor: titleColor))
|
||||
string.append(NSAttributedString(string: firstName, font: titleFont, textColor: titleColor))
|
||||
}
|
||||
titleAttributedString = string
|
||||
} else if let firstName = user.firstName, !firstName.isEmpty {
|
||||
@ -458,7 +460,7 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
} else if let lastName = user.lastName, !lastName.isEmpty {
|
||||
titleAttributedString = NSAttributedString(string: lastName, font: currentBoldFont, textColor: titleColor)
|
||||
} else {
|
||||
titleAttributedString = NSAttributedString(string: item.strings.User_DeletedAccount, font: currentBoldFont, textColor: titleColor)
|
||||
titleAttributedString = NSAttributedString(string: item.presentationData.strings.User_DeletedAccount, font: currentBoldFont, textColor: titleColor)
|
||||
}
|
||||
} else if let group = item.peer as? TelegramGroup {
|
||||
titleAttributedString = NSAttributedString(string: group.title, font: currentBoldFont, textColor: titleColor)
|
||||
@ -467,52 +469,60 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
}
|
||||
|
||||
switch item.text {
|
||||
case .presence:
|
||||
if let user = item.peer as? TelegramUser, let botInfo = user.botInfo {
|
||||
let botStatus: String
|
||||
if botInfo.flags.contains(.hasAccessToChatHistory) {
|
||||
botStatus = item.strings.Bot_GroupStatusReadsHistory
|
||||
} else {
|
||||
botStatus = item.strings.Bot_GroupStatusDoesNotReadHistory
|
||||
}
|
||||
statusAttributedString = NSAttributedString(string: botStatus, font: statusFont, textColor: item.theme.list.itemSecondaryTextColor)
|
||||
} else if let presence = item.presence as? TelegramUserPresence {
|
||||
let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970
|
||||
let (string, activity) = stringAndActivityForUserPresence(strings: item.strings, dateTimeFormat: item.dateTimeFormat, presence: presence, relativeTo: Int32(timestamp))
|
||||
statusAttributedString = NSAttributedString(string: string, font: statusFont, textColor: activity ? item.theme.list.itemAccentColor : item.theme.list.itemSecondaryTextColor)
|
||||
case .presence:
|
||||
if let user = item.peer as? TelegramUser, let botInfo = user.botInfo {
|
||||
let botStatus: String
|
||||
if botInfo.flags.contains(.hasAccessToChatHistory) {
|
||||
botStatus = item.presentationData.strings.Bot_GroupStatusReadsHistory
|
||||
} else {
|
||||
statusAttributedString = NSAttributedString(string: item.strings.LastSeen_Offline, font: statusFont, textColor: item.theme.list.itemSecondaryTextColor)
|
||||
botStatus = item.presentationData.strings.Bot_GroupStatusDoesNotReadHistory
|
||||
}
|
||||
case let .text(text):
|
||||
statusAttributedString = NSAttributedString(string: text, font: statusFont, textColor: item.theme.list.itemSecondaryTextColor)
|
||||
case .none:
|
||||
break
|
||||
statusAttributedString = NSAttributedString(string: botStatus, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
} else if let presence = item.presence as? TelegramUserPresence {
|
||||
let timestamp = CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970
|
||||
let (string, activity) = stringAndActivityForUserPresence(strings: item.presentationData.strings, dateTimeFormat: item.dateTimeFormat, presence: presence, relativeTo: Int32(timestamp))
|
||||
statusAttributedString = NSAttributedString(string: string, font: statusFont, textColor: activity ? item.presentationData.theme.list.itemAccentColor : item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
} else {
|
||||
statusAttributedString = NSAttributedString(string: item.presentationData.strings.LastSeen_Offline, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
}
|
||||
case let .text(text):
|
||||
statusAttributedString = NSAttributedString(string: text, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
case .none:
|
||||
break
|
||||
}
|
||||
|
||||
let leftInset: CGFloat
|
||||
let height: CGFloat
|
||||
let verticalInset: CGFloat
|
||||
let verticalOffset: CGFloat
|
||||
let avatarSize: CGFloat
|
||||
switch item.height {
|
||||
case .generic:
|
||||
height = 44.0
|
||||
verticalOffset = -3.0
|
||||
avatarSize = 31.0
|
||||
leftInset = 59.0 + params.leftInset
|
||||
case .peerList:
|
||||
height = 50.0
|
||||
verticalOffset = 0.0
|
||||
avatarSize = 40.0
|
||||
leftInset = 65.0 + params.leftInset
|
||||
case .generic:
|
||||
if case .none = item.text {
|
||||
verticalInset = 11.0
|
||||
} else {
|
||||
verticalInset = 6.0
|
||||
}
|
||||
verticalOffset = 0.0
|
||||
avatarSize = 31.0
|
||||
leftInset = 59.0 + params.leftInset
|
||||
case .peerList:
|
||||
if case .none = item.text {
|
||||
verticalInset = 14.0
|
||||
} else {
|
||||
verticalInset = 8.0
|
||||
}
|
||||
verticalOffset = 0.0
|
||||
avatarSize = 40.0
|
||||
leftInset = 65.0 + params.leftInset
|
||||
}
|
||||
|
||||
var editableControlSizeAndApply: (CGSize, () -> ItemListEditableControlNode)?
|
||||
var editableControlSizeAndApply: (CGFloat, (CGFloat) -> ItemListEditableControlNode)?
|
||||
|
||||
let editingOffset: CGFloat
|
||||
if item.editing.editing {
|
||||
let sizeAndApply = editableControlLayout(50.0, item.theme, false)
|
||||
let sizeAndApply = editableControlLayout(item.presentationData.theme, false)
|
||||
editableControlSizeAndApply = sizeAndApply
|
||||
editingOffset = sizeAndApply.0.width
|
||||
editingOffset = sizeAndApply.0
|
||||
} else {
|
||||
editingOffset = 0.0
|
||||
}
|
||||
@ -530,7 +540,7 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
case let .custom(value):
|
||||
selectedFont = value
|
||||
}
|
||||
labelAttributedString = NSAttributedString(string: text, font: selectedFont, textColor: item.theme.list.itemSecondaryTextColor)
|
||||
labelAttributedString = NSAttributedString(string: text, font: selectedFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
labelInset += 15.0
|
||||
case let .disclosure(text):
|
||||
if let currentLabelArrowNode = currentLabelArrowNode {
|
||||
@ -540,28 +550,28 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
arrowNode.isLayerBacked = true
|
||||
arrowNode.displayWithoutProcessing = true
|
||||
arrowNode.displaysAsynchronously = false
|
||||
arrowNode.image = PresentationResourcesItemList.disclosureArrowImage(item.theme)
|
||||
arrowNode.image = PresentationResourcesItemList.disclosureArrowImage(item.presentationData.theme)
|
||||
updatedLabelArrowNode = arrowNode
|
||||
}
|
||||
labelInset += 40.0
|
||||
labelAttributedString = NSAttributedString(string: text, font: labelDisclosureFont, textColor: item.theme.list.itemSecondaryTextColor)
|
||||
labelAttributedString = NSAttributedString(string: text, font: labelDisclosureFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
case let .badge(text):
|
||||
labelAttributedString = NSAttributedString(string: text, font: badgeFont, textColor: item.theme.list.itemCheckColors.foregroundColor)
|
||||
labelAttributedString = NSAttributedString(string: text, font: badgeFont, textColor: item.presentationData.theme.list.itemCheckColors.foregroundColor)
|
||||
labelInset += 15.0
|
||||
}
|
||||
|
||||
let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: labelAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 16.0 - editingOffset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 12.0 - labelLayout.size.width - editingOffset - rightInset - labelInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let (statusLayout, statusApply) = makeStatusLayout(TextNodeLayoutArguments(attributedString: statusAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 8.0 - editingOffset - rightInset - labelInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 12.0 - labelLayout.size.width - editingOffset - rightInset - labelLayout.size.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let (statusLayout, statusApply) = makeStatusLayout(TextNodeLayoutArguments(attributedString: statusAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 8.0 - editingOffset - rightInset - labelLayout.size.width, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
var insets = itemListNeighborsGroupedInsets(neighbors)
|
||||
if !item.hasTopGroupInset {
|
||||
switch neighbors.top {
|
||||
case .none:
|
||||
insets.top = 0.0
|
||||
default:
|
||||
break
|
||||
case .none:
|
||||
insets.top = 0.0
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
if item.noInsets {
|
||||
@ -569,7 +579,12 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
insets.bottom = 0.0
|
||||
}
|
||||
|
||||
let contentSize = CGSize(width: params.width, height: height)
|
||||
let titleSpacing: CGFloat = 1.0
|
||||
|
||||
let minHeight: CGFloat = titleLayout.size.height + verticalInset * 2.0
|
||||
let rawHeight: CGFloat = verticalInset * 2.0 + titleLayout.size.height + titleSpacing + statusLayout.size.height
|
||||
|
||||
let contentSize = CGSize(width: params.width, height: max(minHeight, rawHeight))
|
||||
let separatorHeight = UIScreenPixel
|
||||
|
||||
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
||||
@ -578,7 +593,7 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
if !item.enabled {
|
||||
if currentDisabledOverlayNode == nil {
|
||||
currentDisabledOverlayNode = ASDisplayNode()
|
||||
currentDisabledOverlayNode?.backgroundColor = item.theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.5)
|
||||
currentDisabledOverlayNode?.backgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.5)
|
||||
}
|
||||
} else {
|
||||
currentDisabledOverlayNode = nil
|
||||
@ -607,10 +622,10 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
}
|
||||
|
||||
if let _ = updatedTheme {
|
||||
strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.theme.list.itemHighlightedBackgroundColor
|
||||
strongSelf.topStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
}
|
||||
|
||||
let revealOffset = strongSelf.revealOffset
|
||||
@ -640,9 +655,9 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
}
|
||||
|
||||
if let editableControlSizeAndApply = editableControlSizeAndApply {
|
||||
let editableControlFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset, y: 0.0), size: editableControlSizeAndApply.0)
|
||||
let editableControlFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset, y: 0.0), size: CGSize(width: editableControlSizeAndApply.0, height: layout.contentSize.height))
|
||||
if strongSelf.editableControlNode == nil {
|
||||
let editableControlNode = editableControlSizeAndApply.1()
|
||||
let editableControlNode = editableControlSizeAndApply.1(layout.contentSize.height)
|
||||
editableControlNode.tapped = {
|
||||
if let strongSelf = self {
|
||||
strongSelf.setRevealOptionsOpened(true, animated: true)
|
||||
@ -692,34 +707,34 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
var hasTopCorners = false
|
||||
var hasBottomCorners = false
|
||||
switch neighbors.top {
|
||||
case .sameSection(false):
|
||||
strongSelf.topStripeNode.isHidden = true
|
||||
default:
|
||||
hasTopCorners = true
|
||||
strongSelf.topStripeNode.isHidden = hasCorners || !item.hasTopStripe
|
||||
case .sameSection(false):
|
||||
strongSelf.topStripeNode.isHidden = true
|
||||
default:
|
||||
hasTopCorners = true
|
||||
strongSelf.topStripeNode.isHidden = hasCorners || !item.hasTopStripe
|
||||
}
|
||||
let bottomStripeInset: CGFloat
|
||||
let bottomStripeOffset: CGFloat
|
||||
switch neighbors.bottom {
|
||||
case .sameSection(false):
|
||||
bottomStripeInset = leftInset + editingOffset
|
||||
bottomStripeOffset = -separatorHeight
|
||||
default:
|
||||
bottomStripeInset = 0.0
|
||||
bottomStripeOffset = 0.0
|
||||
hasBottomCorners = true
|
||||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
case .sameSection(false):
|
||||
bottomStripeInset = leftInset + editingOffset
|
||||
bottomStripeOffset = -separatorHeight
|
||||
default:
|
||||
bottomStripeInset = 0.0
|
||||
bottomStripeOffset = 0.0
|
||||
hasBottomCorners = true
|
||||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
transition.updateFrame(node: strongSelf.topStripeNode, frame: CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)))
|
||||
transition.updateFrame(node: strongSelf.bottomStripeNode, frame: CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)))
|
||||
|
||||
transition.updateFrame(node: strongSelf.titleNode, frame: CGRect(origin: CGPoint(x: leftInset + revealOffset + editingOffset, y: (statusAttributedString == nil ? 14.0 : 6.0) + verticalOffset), size: titleLayout.size))
|
||||
transition.updateFrame(node: strongSelf.statusNode, frame: CGRect(origin: CGPoint(x: leftInset + revealOffset + editingOffset, y: 27.0 + verticalOffset), size: statusLayout.size))
|
||||
transition.updateFrame(node: strongSelf.titleNode, frame: CGRect(origin: CGPoint(x: leftInset + revealOffset + editingOffset, y: verticalInset + verticalOffset), size: titleLayout.size))
|
||||
transition.updateFrame(node: strongSelf.statusNode, frame: CGRect(origin: CGPoint(x: leftInset + revealOffset + editingOffset, y: strongSelf.titleNode.frame.maxY + titleSpacing), size: statusLayout.size))
|
||||
|
||||
if let currentSwitchNode = currentSwitchNode {
|
||||
if currentSwitchNode !== strongSelf.switchNode {
|
||||
@ -795,19 +810,19 @@ public class ItemListPeerItemNode: ItemListRevealOptionsItemNode, ItemListItemNo
|
||||
|
||||
strongSelf.labelBadgeNode.frame = CGRect(origin: CGPoint(x: revealOffset + params.width - rightLabelInset - badgeWidth, y: labelFrame.minY - 1.0), size: CGSize(width: badgeWidth, height: badgeDiameter))
|
||||
|
||||
transition.updateFrame(node: strongSelf.avatarNode, frame: CGRect(origin: CGPoint(x: params.leftInset + revealOffset + editingOffset + 15.0, y: floorToScreenPixels((height - avatarSize) / 2.0)), size: CGSize(width: avatarSize, height: avatarSize)))
|
||||
transition.updateFrame(node: strongSelf.avatarNode, frame: CGRect(origin: CGPoint(x: params.leftInset + revealOffset + editingOffset + 15.0, y: floorToScreenPixels((layout.contentSize.height - avatarSize) / 2.0)), size: CGSize(width: avatarSize, height: avatarSize)))
|
||||
|
||||
if item.peer.id == item.account.peerId, case .threatSelfAsSaved = item.aliasHandling {
|
||||
strongSelf.avatarNode.setPeer(account: item.account, theme: item.theme, peer: item.peer, overrideImage: .savedMessagesIcon, emptyColor: item.theme.list.mediaPlaceholderColor, synchronousLoad: synchronousLoad)
|
||||
strongSelf.avatarNode.setPeer(account: item.account, theme: item.presentationData.theme, peer: item.peer, overrideImage: .savedMessagesIcon, emptyColor: item.presentationData.theme.list.mediaPlaceholderColor, synchronousLoad: synchronousLoad)
|
||||
} else {
|
||||
var overrideImage: AvatarNodeImageOverride?
|
||||
if item.peer.isDeleted {
|
||||
overrideImage = .deletedIcon
|
||||
}
|
||||
strongSelf.avatarNode.setPeer(account: item.account, theme: item.theme, peer: item.peer, overrideImage: overrideImage, emptyColor: item.theme.list.mediaPlaceholderColor, synchronousLoad: synchronousLoad)
|
||||
strongSelf.avatarNode.setPeer(account: item.account, theme: item.presentationData.theme, peer: item.peer, overrideImage: overrideImage, emptyColor: item.presentationData.theme.list.mediaPlaceholderColor, synchronousLoad: synchronousLoad)
|
||||
}
|
||||
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: height + UIScreenPixel + UIScreenPixel))
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: layout.contentSize.height + UIScreenPixel + UIScreenPixel))
|
||||
|
||||
if let presence = item.presence as? TelegramUserPresence {
|
||||
strongSelf.peerPresenceManager?.reset(presence: presence)
|
||||
|
@ -34,8 +34,7 @@ public enum ItemListStickerPackItemControl: Equatable {
|
||||
}
|
||||
|
||||
public final class ItemListStickerPackItem: ListViewItem, ItemListItem {
|
||||
let theme: PresentationTheme
|
||||
let strings: PresentationStrings
|
||||
let presentationData: ItemListPresentationData
|
||||
let account: Account
|
||||
let packInfo: StickerPackCollectionInfo
|
||||
let itemCount: String
|
||||
@ -51,9 +50,8 @@ public final class ItemListStickerPackItem: ListViewItem, ItemListItem {
|
||||
let addPack: () -> Void
|
||||
let removePack: () -> Void
|
||||
|
||||
public init(theme: PresentationTheme, strings: PresentationStrings, account: Account, packInfo: StickerPackCollectionInfo, itemCount: String, topItem: StickerPackItem?, unread: Bool, control: ItemListStickerPackItemControl, editing: ItemListStickerPackItemEditing, enabled: Bool, playAnimatedStickers: Bool, sectionId: ItemListSectionId, action: (() -> Void)?, setPackIdWithRevealedOptions: @escaping (ItemCollectionId?, ItemCollectionId?) -> Void, addPack: @escaping () -> Void, removePack: @escaping () -> Void) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
public init(presentationData: ItemListPresentationData, account: Account, packInfo: StickerPackCollectionInfo, itemCount: String, topItem: StickerPackItem?, unread: Bool, control: ItemListStickerPackItemControl, editing: ItemListStickerPackItemEditing, enabled: Bool, playAnimatedStickers: Bool, sectionId: ItemListSectionId, action: (() -> Void)?, setPackIdWithRevealedOptions: @escaping (ItemCollectionId?, ItemCollectionId?) -> Void, addPack: @escaping () -> Void, removePack: @escaping () -> Void) {
|
||||
self.presentationData = presentationData
|
||||
self.account = account
|
||||
self.packInfo = packInfo
|
||||
self.itemCount = itemCount
|
||||
@ -116,9 +114,6 @@ public final class ItemListStickerPackItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.bold(15.0)
|
||||
private let statusFont = Font.regular(14.0)
|
||||
|
||||
public enum StickerPackThumbnailItem: Equatable {
|
||||
case still(TelegramMediaImageRepresentation)
|
||||
case animated(MediaResource)
|
||||
@ -274,18 +269,21 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
|
||||
let currentItem = self.layoutParams?.0
|
||||
|
||||
return { item, params, neighbors in
|
||||
let titleFont = Font.bold(floor(item.presentationData.fontSize.itemListBaseFontSize * 15.0 / 17.0))
|
||||
let statusFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 14.0 / 17.0))
|
||||
|
||||
var titleAttributedString: NSAttributedString?
|
||||
var statusAttributedString: NSAttributedString?
|
||||
|
||||
var updatedTheme: PresentationTheme?
|
||||
|
||||
if currentItem?.theme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
}
|
||||
|
||||
let packRevealOptions: [ItemListRevealOption]
|
||||
if item.editing.editable && item.enabled {
|
||||
packRevealOptions = [ItemListRevealOption(key: 0, title: item.strings.Common_Delete, icon: .none, color: item.theme.list.itemDisclosureActions.destructive.fillColor, textColor: item.theme.list.itemDisclosureActions.destructive.foregroundColor)]
|
||||
packRevealOptions = [ItemListRevealOption(key: 0, title: item.presentationData.strings.Common_Delete, icon: .none, color: item.presentationData.theme.list.itemDisclosureActions.destructive.fillColor, textColor: item.presentationData.theme.list.itemDisclosureActions.destructive.foregroundColor)]
|
||||
} else {
|
||||
packRevealOptions = []
|
||||
}
|
||||
@ -300,57 +298,60 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
|
||||
case let .installation(installed):
|
||||
rightInset += 50.0
|
||||
if installed {
|
||||
installationActionImage = PresentationResourcesItemList.secondaryCheckIconImage(item.theme)
|
||||
installationActionImage = PresentationResourcesItemList.secondaryCheckIconImage(item.presentationData.theme)
|
||||
} else {
|
||||
installationActionImage = PresentationResourcesItemList.plusIconImage(item.theme)
|
||||
installationActionImage = PresentationResourcesItemList.plusIconImage(item.presentationData.theme)
|
||||
}
|
||||
case .selection:
|
||||
rightInset += 16.0
|
||||
checkImage = PresentationResourcesItemList.checkIconImage(item.theme)
|
||||
checkImage = PresentationResourcesItemList.checkIconImage(item.presentationData.theme)
|
||||
}
|
||||
|
||||
var unreadImage: UIImage?
|
||||
if item.unread {
|
||||
unreadImage = PresentationResourcesItemList.stickerUnreadDotImage(item.theme)
|
||||
unreadImage = PresentationResourcesItemList.stickerUnreadDotImage(item.presentationData.theme)
|
||||
}
|
||||
|
||||
titleAttributedString = NSAttributedString(string: item.packInfo.title, font: titleFont, textColor: item.theme.list.itemPrimaryTextColor)
|
||||
statusAttributedString = NSAttributedString(string: item.itemCount, font: statusFont, textColor: item.theme.list.itemSecondaryTextColor)
|
||||
titleAttributedString = NSAttributedString(string: item.packInfo.title, font: titleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor)
|
||||
statusAttributedString = NSAttributedString(string: item.itemCount, font: statusFont, textColor: item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
|
||||
let leftInset: CGFloat = 65.0 + params.leftInset
|
||||
|
||||
let verticalInset: CGFloat = 11.0
|
||||
let titleSpacing: CGFloat = 2.0
|
||||
|
||||
let insets = itemListNeighborsGroupedInsets(neighbors)
|
||||
let contentSize = CGSize(width: params.width, height: 59.0)
|
||||
let separatorHeight = UIScreenPixel
|
||||
|
||||
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
||||
let layoutSize = layout.size
|
||||
|
||||
var editableControlSizeAndApply: (CGSize, () -> ItemListEditableControlNode)?
|
||||
var reorderControlSizeAndApply: (CGSize, (Bool) -> ItemListEditableReorderControlNode)?
|
||||
var editableControlSizeAndApply: (CGFloat, (CGFloat) -> ItemListEditableControlNode)?
|
||||
var reorderControlSizeAndApply: (CGFloat, (CGFloat, Bool) -> ItemListEditableReorderControlNode)?
|
||||
|
||||
var editingOffset: CGFloat = 0.0
|
||||
var reorderInset: CGFloat = 0.0
|
||||
|
||||
if item.editing.editing {
|
||||
let sizeAndApply = editableControlLayout(59.0, item.theme, false)
|
||||
let sizeAndApply = editableControlLayout(item.presentationData.theme, false)
|
||||
editableControlSizeAndApply = sizeAndApply
|
||||
editingOffset = sizeAndApply.0.width
|
||||
editingOffset = sizeAndApply.0
|
||||
|
||||
if item.editing.reorderable {
|
||||
let sizeAndApply = reorderControlLayout(contentSize.height, item.theme)
|
||||
let sizeAndApply = reorderControlLayout(item.presentationData.theme)
|
||||
reorderControlSizeAndApply = sizeAndApply
|
||||
reorderInset = sizeAndApply.0.width
|
||||
reorderInset = sizeAndApply.0
|
||||
}
|
||||
}
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 8.0 - editingOffset - rightInset - 10.0 - reorderInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let (statusLayout, statusApply) = makeStatusLayout(TextNodeLayoutArguments(attributedString: statusAttributedString, backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 8.0 - editingOffset - rightInset - reorderInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let contentSize = CGSize(width: params.width, height: verticalInset * 2.0 + titleLayout.size.height + titleSpacing + statusLayout.size.height)
|
||||
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
||||
let layoutSize = layout.size
|
||||
|
||||
if !item.enabled {
|
||||
if currentDisabledOverlayNode == nil {
|
||||
currentDisabledOverlayNode = ASDisplayNode()
|
||||
currentDisabledOverlayNode?.backgroundColor = item.theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.5)
|
||||
currentDisabledOverlayNode?.backgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor.withAlphaComponent(0.5)
|
||||
}
|
||||
} else {
|
||||
currentDisabledOverlayNode = nil
|
||||
@ -420,10 +421,10 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
|
||||
if let _ = updatedTheme {
|
||||
strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.theme.list.itemHighlightedBackgroundColor
|
||||
strongSelf.topStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
}
|
||||
|
||||
let revealOffset = strongSelf.revealOffset
|
||||
@ -453,9 +454,9 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
|
||||
if let editableControlSizeAndApply = editableControlSizeAndApply {
|
||||
let editableControlFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset, y: 0.0), size: editableControlSizeAndApply.0)
|
||||
let editableControlFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset, y: 0.0), size: CGSize(width: editableControlSizeAndApply.0, height: layout.size.height))
|
||||
if strongSelf.editableControlNode == nil {
|
||||
let editableControlNode = editableControlSizeAndApply.1()
|
||||
let editableControlNode = editableControlSizeAndApply.1(layout.size.height)
|
||||
editableControlNode.tapped = {
|
||||
if let strongSelf = self {
|
||||
strongSelf.setRevealOptionsOpened(true, animated: true)
|
||||
@ -484,13 +485,13 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
if let reorderControlSizeAndApply = reorderControlSizeAndApply {
|
||||
if strongSelf.reorderControlNode == nil {
|
||||
let reorderControlNode = reorderControlSizeAndApply.1(false)
|
||||
let reorderControlNode = reorderControlSizeAndApply.1(layout.contentSize.height, false)
|
||||
strongSelf.reorderControlNode = reorderControlNode
|
||||
strongSelf.addSubnode(reorderControlNode)
|
||||
reorderControlNode.alpha = 0.0
|
||||
transition.updateAlpha(node: reorderControlNode, alpha: 1.0)
|
||||
}
|
||||
let reorderControlFrame = CGRect(origin: CGPoint(x: params.width + revealOffset - params.rightInset - reorderControlSizeAndApply.0.width, y: 0.0), size: reorderControlSizeAndApply.0)
|
||||
let reorderControlFrame = CGRect(origin: CGPoint(x: params.width + revealOffset - params.rightInset - reorderControlSizeAndApply.0, y: 0.0), size: CGSize(width: reorderControlSizeAndApply.0, height: layout.contentSize.height))
|
||||
strongSelf.reorderControlNode?.frame = reorderControlFrame
|
||||
} else if let reorderControlNode = strongSelf.reorderControlNode {
|
||||
strongSelf.reorderControlNode = nil
|
||||
@ -568,7 +569,7 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
@ -583,12 +584,12 @@ class ItemListStickerPackItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.unreadNode.isHidden = true
|
||||
}
|
||||
|
||||
transition.updateFrame(node: strongSelf.titleNode, frame: CGRect(origin: CGPoint(x: (strongSelf.unreadNode.isHidden ? 0.0 : 10.0) + leftInset + revealOffset + editingOffset, y: 11.0), size: titleLayout.size))
|
||||
transition.updateFrame(node: strongSelf.statusNode, frame: CGRect(origin: CGPoint(x: leftInset + revealOffset + editingOffset, y: 32.0), size: statusLayout.size))
|
||||
transition.updateFrame(node: strongSelf.titleNode, frame: CGRect(origin: CGPoint(x: (strongSelf.unreadNode.isHidden ? 0.0 : 10.0) + leftInset + revealOffset + editingOffset, y: verticalInset), size: titleLayout.size))
|
||||
transition.updateFrame(node: strongSelf.statusNode, frame: CGRect(origin: CGPoint(x: leftInset + revealOffset + editingOffset, y: strongSelf.titleNode.frame.maxY + titleSpacing), size: statusLayout.size))
|
||||
|
||||
let boundingSize = CGSize(width: 34.0, height: 34.0)
|
||||
if let thumbnailItem = thumbnailItem, let imageSize = imageSize {
|
||||
let imageFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset + editingOffset + 15.0 + floor((boundingSize.width - imageSize.width) / 2.0), y: 11.0 + floor((boundingSize.height - imageSize.height) / 2.0)), size: imageSize)
|
||||
let imageFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset + editingOffset + 15.0 + floor((boundingSize.width - imageSize.width) / 2.0), y: floor((layout.size.height - imageSize.height) / 2.0)), size: imageSize)
|
||||
switch thumbnailItem {
|
||||
case .still:
|
||||
transition.updateFrame(node: strongSelf.imageNode, frame: imageFrame)
|
||||
|
@ -80,7 +80,7 @@ public final class ItemListControllerTabBarItem: Equatable {
|
||||
}
|
||||
|
||||
public struct ItemListControllerState {
|
||||
let theme: PresentationTheme
|
||||
let presentationData: ItemListPresentationData
|
||||
let title: ItemListControllerTitle
|
||||
let leftNavigationButton: ItemListNavigationButton?
|
||||
let rightNavigationButton: ItemListNavigationButton?
|
||||
@ -89,8 +89,8 @@ public struct ItemListControllerState {
|
||||
let tabBarItem: ItemListControllerTabBarItem?
|
||||
let animateChanges: Bool
|
||||
|
||||
public init(theme: PresentationTheme, title: ItemListControllerTitle, leftNavigationButton: ItemListNavigationButton?, rightNavigationButton: ItemListNavigationButton?, secondaryRightNavigationButton: ItemListNavigationButton? = nil, backNavigationButton: ItemListBackButton?, tabBarItem: ItemListControllerTabBarItem? = nil, animateChanges: Bool = true) {
|
||||
self.theme = theme
|
||||
public init(presentationData: ItemListPresentationData, title: ItemListControllerTitle, leftNavigationButton: ItemListNavigationButton?, rightNavigationButton: ItemListNavigationButton?, secondaryRightNavigationButton: ItemListNavigationButton? = nil, backNavigationButton: ItemListBackButton?, tabBarItem: ItemListControllerTabBarItem? = nil, animateChanges: Bool = true) {
|
||||
self.presentationData = presentationData
|
||||
self.title = title
|
||||
self.leftNavigationButton = leftNavigationButton
|
||||
self.rightNavigationButton = rightNavigationButton
|
||||
@ -111,8 +111,7 @@ open class ItemListController: ViewController, KeyShortcutResponder, Presentable
|
||||
private var navigationButtonActions: (left: (() -> Void)?, right: (() -> Void)?, secondaryRight: (() -> Void)?) = (nil, nil, nil)
|
||||
private var segmentedTitleView: ItemListControllerSegmentedTitleView?
|
||||
|
||||
private var theme: PresentationTheme
|
||||
private var strings: PresentationStrings
|
||||
private var presentationData: ItemListPresentationData
|
||||
|
||||
private var validLayout: ContainerViewLayout?
|
||||
|
||||
@ -228,21 +227,20 @@ open class ItemListController: ViewController, KeyShortcutResponder, Presentable
|
||||
public var willDisappear: ((Bool) -> Void)?
|
||||
public var didDisappear: ((Bool) -> Void)?
|
||||
|
||||
public init<ItemGenerationArguments>(theme: PresentationTheme, strings: PresentationStrings, updatedPresentationData: Signal<(theme: PresentationTheme, strings: PresentationStrings), NoError>, state: Signal<(ItemListControllerState, (ItemListNodeState, ItemGenerationArguments)), NoError>, tabBarItem: Signal<ItemListControllerTabBarItem, NoError>?) {
|
||||
public init<ItemGenerationArguments>(presentationData: ItemListPresentationData, updatedPresentationData: Signal<ItemListPresentationData, NoError>, state: Signal<(ItemListControllerState, (ItemListNodeState, ItemGenerationArguments)), NoError>, tabBarItem: Signal<ItemListControllerTabBarItem, NoError>?) {
|
||||
self.state = state
|
||||
|> map { controllerState, nodeStateAndArgument -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||
return (controllerState, (nodeStateAndArgument.0, nodeStateAndArgument.1))
|
||||
}
|
||||
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.presentationData = presentationData
|
||||
|
||||
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: theme), strings: NavigationBarStrings(presentationStrings: strings)))
|
||||
super.init(navigationBarPresentationData: NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: presentationData.theme), strings: NavigationBarStrings(presentationStrings: presentationData.strings)))
|
||||
|
||||
self.isOpaqueWhenInOverlay = true
|
||||
self.blocksBackgroundWhenInOverlay = true
|
||||
|
||||
self.statusBar.statusBarStyle = theme.rootController.statusBarStyle.style
|
||||
self.statusBar.statusBarStyle = presentationData.theme.rootController.statusBarStyle.style
|
||||
|
||||
self.scrollToTop = { [weak self] in
|
||||
self?.willScrollToTop?()
|
||||
@ -292,7 +290,7 @@ open class ItemListController: ViewController, KeyShortcutResponder, Presentable
|
||||
if let segmentedTitleView = strongSelf.segmentedTitleView, segmentedTitleView.segments == sections {
|
||||
segmentedTitleView.index = index
|
||||
} else {
|
||||
let segmentedTitleView = ItemListControllerSegmentedTitleView(theme: controllerState.theme, segments: sections, selectedIndex: index)
|
||||
let segmentedTitleView = ItemListControllerSegmentedTitleView(theme: controllerState.presentationData.theme, segments: sections, selectedIndex: index)
|
||||
strongSelf.segmentedTitleView = segmentedTitleView
|
||||
strongSelf.navigationItem.titleView = strongSelf.segmentedTitleView
|
||||
segmentedTitleView.indexUpdated = { index in
|
||||
@ -305,7 +303,7 @@ open class ItemListController: ViewController, KeyShortcutResponder, Presentable
|
||||
}
|
||||
strongSelf.navigationButtonActions = (left: controllerState.leftNavigationButton?.action, right: controllerState.rightNavigationButton?.action, secondaryRight: controllerState.secondaryRightNavigationButton?.action)
|
||||
|
||||
let themeUpdated = strongSelf.theme !== controllerState.theme
|
||||
let themeUpdated = strongSelf.presentationData != controllerState.presentationData
|
||||
if strongSelf.leftNavigationButtonTitleAndStyle?.0 != controllerState.leftNavigationButton?.content || strongSelf.leftNavigationButtonTitleAndStyle?.1 != controllerState.leftNavigationButton?.style || themeUpdated {
|
||||
if let leftNavigationButton = controllerState.leftNavigationButton {
|
||||
let item: UIBarButtonItem
|
||||
@ -318,11 +316,11 @@ open class ItemListController: ViewController, KeyShortcutResponder, Presentable
|
||||
var image: UIImage?
|
||||
switch icon {
|
||||
case .search:
|
||||
image = PresentationResourcesRootController.navigationCompactSearchIcon(controllerState.theme)
|
||||
image = PresentationResourcesRootController.navigationCompactSearchIcon(controllerState.presentationData.theme)
|
||||
case .add:
|
||||
image = PresentationResourcesRootController.navigationAddIcon(controllerState.theme)
|
||||
image = PresentationResourcesRootController.navigationAddIcon(controllerState.presentationData.theme)
|
||||
case .action:
|
||||
image = PresentationResourcesRootController.navigationShareIcon(controllerState.theme)
|
||||
image = PresentationResourcesRootController.navigationShareIcon(controllerState.presentationData.theme)
|
||||
}
|
||||
item = UIBarButtonItem(image: image, style: leftNavigationButton.style.barButtonItemStyle, target: strongSelf, action: #selector(strongSelf.leftNavigationButtonPressed))
|
||||
}
|
||||
@ -363,7 +361,7 @@ open class ItemListController: ViewController, KeyShortcutResponder, Presentable
|
||||
for (content, style, _) in rightNavigationButtonTitleAndStyle {
|
||||
let item: UIBarButtonItem
|
||||
if case .activity = style {
|
||||
item = UIBarButtonItem(customDisplayNode: ProgressNavigationButtonNode(color: controllerState.theme.rootController.navigationBar.controlColor))
|
||||
item = UIBarButtonItem(customDisplayNode: ProgressNavigationButtonNode(color: controllerState.presentationData.theme.rootController.navigationBar.controlColor))
|
||||
} else {
|
||||
let action: Selector = (index == 0 && rightNavigationButtonTitleAndStyle.count > 1) ? #selector(strongSelf.secondaryRightNavigationButtonPressed) : #selector(strongSelf.rightNavigationButtonPressed)
|
||||
switch content {
|
||||
@ -375,11 +373,11 @@ open class ItemListController: ViewController, KeyShortcutResponder, Presentable
|
||||
var image: UIImage?
|
||||
switch icon {
|
||||
case .search:
|
||||
image = PresentationResourcesRootController.navigationCompactSearchIcon(controllerState.theme)
|
||||
image = PresentationResourcesRootController.navigationCompactSearchIcon(controllerState.presentationData.theme)
|
||||
case .add:
|
||||
image = PresentationResourcesRootController.navigationAddIcon(controllerState.theme)
|
||||
image = PresentationResourcesRootController.navigationAddIcon(controllerState.presentationData.theme)
|
||||
case .action:
|
||||
image = PresentationResourcesRootController.navigationShareIcon(controllerState.theme)
|
||||
image = PresentationResourcesRootController.navigationShareIcon(controllerState.presentationData.theme)
|
||||
}
|
||||
item = UIBarButtonItem(image: image, style: style.barButtonItemStyle, target: strongSelf, action: action)
|
||||
}
|
||||
@ -409,25 +407,27 @@ open class ItemListController: ViewController, KeyShortcutResponder, Presentable
|
||||
}
|
||||
}
|
||||
|
||||
if strongSelf.theme !== controllerState.theme {
|
||||
strongSelf.theme = controllerState.theme
|
||||
if strongSelf.presentationData != controllerState.presentationData {
|
||||
strongSelf.presentationData = controllerState.presentationData
|
||||
|
||||
strongSelf.navigationBar?.updatePresentationData(NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: strongSelf.theme), strings: NavigationBarStrings(presentationStrings: strongSelf.strings)))
|
||||
strongSelf.statusBar.updateStatusBarStyle(strongSelf.theme.rootController.statusBarStyle.style, animated: true)
|
||||
strongSelf.navigationBar?.updatePresentationData(NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: strongSelf.presentationData.theme), strings: NavigationBarStrings(presentationStrings: strongSelf.presentationData.strings)))
|
||||
strongSelf.statusBar.updateStatusBarStyle(strongSelf.presentationData.theme.rootController.statusBarStyle.style, animated: true)
|
||||
|
||||
strongSelf.segmentedTitleView?.theme = controllerState.theme
|
||||
strongSelf.segmentedTitleView?.theme = controllerState.presentationData.theme
|
||||
|
||||
var items = strongSelf.navigationItem.rightBarButtonItems ?? []
|
||||
for i in 0 ..< strongSelf.rightNavigationButtonTitleAndStyle.count {
|
||||
if case .activity = strongSelf.rightNavigationButtonTitleAndStyle[i].1 {
|
||||
items[i] = UIBarButtonItem(customDisplayNode: ProgressNavigationButtonNode(color: controllerState.theme.rootController.navigationBar.controlColor))!
|
||||
items[i] = UIBarButtonItem(customDisplayNode: ProgressNavigationButtonNode(color: controllerState.presentationData.theme.rootController.navigationBar.controlColor))!
|
||||
}
|
||||
}
|
||||
strongSelf.navigationItem.setRightBarButtonItems(items, animated: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
} |> map { ($0.theme, $1) }
|
||||
}
|
||||
|> map { ($0.presentationData, $1) }
|
||||
|
||||
let displayNode = ItemListControllerNode(controller: self, navigationBar: self.navigationBar!, updateNavigationOffset: { [weak self] offset in
|
||||
if let strongSelf = self {
|
||||
strongSelf.navigationOffset = offset
|
||||
|
@ -15,7 +15,7 @@ public protocol ItemListNodeAnyEntry {
|
||||
var tag: ItemListItemTag? { get }
|
||||
func isLessThan(_ rhs: ItemListNodeAnyEntry) -> Bool
|
||||
func isEqual(_ rhs: ItemListNodeAnyEntry) -> Bool
|
||||
func item(_ arguments: Any) -> ListViewItem
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem
|
||||
}
|
||||
|
||||
public protocol ItemListNodeEntry: Comparable, Identifiable, ItemListNodeAnyEntry {
|
||||
@ -46,18 +46,18 @@ private struct ItemListNodeEntryTransition {
|
||||
let updates: [ListViewUpdateItem]
|
||||
}
|
||||
|
||||
private func preparedItemListNodeEntryTransition(from fromEntries: [ItemListNodeAnyEntry], to toEntries: [ItemListNodeAnyEntry], arguments: Any) -> ItemListNodeEntryTransition {
|
||||
private func preparedItemListNodeEntryTransition(from fromEntries: [ItemListNodeAnyEntry], to toEntries: [ItemListNodeAnyEntry], presentationData: ItemListPresentationData, arguments: Any, presentationDataUpdated: Bool) -> ItemListNodeEntryTransition {
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries, isLess: { lhs, rhs in
|
||||
return lhs.isLessThan(rhs)
|
||||
}, isEqual: { lhs, rhs in
|
||||
return lhs.isEqual(rhs)
|
||||
}, getId: { value in
|
||||
return value.anyId
|
||||
})
|
||||
}, allUpdated: presentationDataUpdated)
|
||||
|
||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(arguments), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(arguments), directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(presentationData: presentationData, arguments: arguments), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(presentationData: presentationData, arguments: arguments), directionHint: nil) }
|
||||
|
||||
return ItemListNodeEntryTransition(deletions: deletions, insertions: insertions, updates: updates)
|
||||
}
|
||||
@ -85,6 +85,7 @@ private struct ItemListNodeTransition {
|
||||
}
|
||||
|
||||
public final class ItemListNodeState {
|
||||
let presentationData: ItemListPresentationData
|
||||
let entries: [ItemListNodeAnyEntry]
|
||||
let style: ItemListStyle
|
||||
let emptyStateItem: ItemListControllerEmptyStateItem?
|
||||
@ -96,7 +97,8 @@ public final class ItemListNodeState {
|
||||
let ensureVisibleItemTag: ItemListItemTag?
|
||||
let initialScrollToItem: ListViewScrollToItem?
|
||||
|
||||
public init<T: ItemListNodeEntry>(entries: [T], style: ItemListStyle, focusItemTag: ItemListItemTag? = nil, ensureVisibleItemTag: ItemListItemTag? = nil, emptyStateItem: ItemListControllerEmptyStateItem? = nil, searchItem: ItemListControllerSearch? = nil, initialScrollToItem: ListViewScrollToItem? = nil, crossfadeState: Bool = false, animateChanges: Bool = true, scrollEnabled: Bool = true) {
|
||||
public init<T: ItemListNodeEntry>(presentationData: ItemListPresentationData, entries: [T], style: ItemListStyle, focusItemTag: ItemListItemTag? = nil, ensureVisibleItemTag: ItemListItemTag? = nil, emptyStateItem: ItemListControllerEmptyStateItem? = nil, searchItem: ItemListControllerSearch? = nil, initialScrollToItem: ListViewScrollToItem? = nil, crossfadeState: Bool = false, animateChanges: Bool = true, scrollEnabled: Bool = true) {
|
||||
self.presentationData = presentationData
|
||||
self.entries = entries.map { $0 }
|
||||
self.style = style
|
||||
self.emptyStateItem = emptyStateItem
|
||||
@ -226,7 +228,7 @@ open class ItemListControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
|
||||
var alwaysSynchronous = false
|
||||
|
||||
public init(controller: ItemListController?, navigationBar: NavigationBar, updateNavigationOffset: @escaping (CGFloat) -> Void, state: Signal<(PresentationTheme, (ItemListNodeState, Any)), NoError>) {
|
||||
public init(controller: ItemListController?, navigationBar: NavigationBar, updateNavigationOffset: @escaping (CGFloat) -> Void, state: Signal<(ItemListPresentationData, (ItemListNodeState, Any)), NoError>) {
|
||||
self.navigationBar = navigationBar
|
||||
self.updateNavigationOffset = updateNavigationOffset
|
||||
|
||||
@ -298,7 +300,8 @@ open class ItemListControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
}
|
||||
|
||||
let previousState = Atomic<ItemListNodeState?>(value: nil)
|
||||
self.transitionDisposable.set(((state |> map { theme, stateAndArguments -> ItemListNodeTransition in
|
||||
self.transitionDisposable.set(((state
|
||||
|> map { presentationData, stateAndArguments -> ItemListNodeTransition in
|
||||
let (state, arguments) = stateAndArguments
|
||||
if state.entries.count > 1 {
|
||||
for i in 1 ..< state.entries.count {
|
||||
@ -306,7 +309,7 @@ open class ItemListControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
}
|
||||
}
|
||||
let previous = previousState.swap(state)
|
||||
let transition = preparedItemListNodeEntryTransition(from: previous?.entries ?? [], to: state.entries, arguments: arguments)
|
||||
let transition = preparedItemListNodeEntryTransition(from: previous?.entries ?? [], to: state.entries, presentationData: presentationData, arguments: arguments, presentationDataUpdated: previous?.presentationData != presentationData)
|
||||
var updatedStyle: ItemListStyle?
|
||||
if previous?.style != state.style {
|
||||
updatedStyle = state.style
|
||||
@ -317,8 +320,9 @@ open class ItemListControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
scrollToItem = state.initialScrollToItem
|
||||
}
|
||||
|
||||
return ItemListNodeTransition(theme: theme, entries: transition, updateStyle: updatedStyle, emptyStateItem: state.emptyStateItem, searchItem: state.searchItem, focusItemTag: state.focusItemTag, ensureVisibleItemTag: state.ensureVisibleItemTag, scrollToItem: scrollToItem, firstTime: previous == nil, animated: previous != nil && state.animateChanges, animateAlpha: previous != nil && state.animateChanges, crossfade: state.crossfadeState, mergedEntries: state.entries, scrollEnabled: state.scrollEnabled)
|
||||
}) |> deliverOnMainQueue).start(next: { [weak self] transition in
|
||||
return ItemListNodeTransition(theme: presentationData.theme, entries: transition, updateStyle: updatedStyle, emptyStateItem: state.emptyStateItem, searchItem: state.searchItem, focusItemTag: state.focusItemTag, ensureVisibleItemTag: state.ensureVisibleItemTag, scrollToItem: scrollToItem, firstTime: previous == nil, animated: previous != nil && state.animateChanges, animateAlpha: previous != nil && state.animateChanges, crossfade: state.crossfadeState, mergedEntries: state.entries, scrollEnabled: state.scrollEnabled)
|
||||
})
|
||||
|> deliverOnMainQueue).start(next: { [weak self] transition in
|
||||
if let strongSelf = self {
|
||||
strongSelf.enqueueTransition(transition)
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ public final class ItemListEditableControlNode: ASDisplayNode {
|
||||
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))))
|
||||
}
|
||||
|
||||
public static func asyncLayout(_ node: ItemListEditableControlNode?) -> (_ height: CGFloat, _ theme: PresentationTheme, _ hidden: Bool) -> (CGSize, () -> ItemListEditableControlNode) {
|
||||
return { height, theme, hidden in
|
||||
public static func asyncLayout(_ node: ItemListEditableControlNode?) -> (_ theme: PresentationTheme, _ hidden: Bool) -> (CGFloat, (CGFloat) -> ItemListEditableControlNode) {
|
||||
return { theme, hidden in
|
||||
let image = PresentationResourcesItemList.itemListDeleteIndicatorIcon(theme)
|
||||
|
||||
let resultNode: ItemListEditableControlNode
|
||||
@ -35,7 +35,7 @@ public final class ItemListEditableControlNode: ASDisplayNode {
|
||||
}
|
||||
resultNode.iconNode.image = image
|
||||
|
||||
return (CGSize(width: 38.0, height: height), {
|
||||
return (38.0, { height in
|
||||
if let image = image {
|
||||
resultNode.iconNode.frame = CGRect(origin: CGPoint(x: 12.0, y: floor((height - image.size.height) / 2.0)), size: image.size)
|
||||
resultNode.iconNode.isHidden = hidden
|
||||
|
@ -19,8 +19,8 @@ public final class ItemListEditableReorderControlNode: ASDisplayNode {
|
||||
self.addSubnode(self.iconNode)
|
||||
}
|
||||
|
||||
public static func asyncLayout(_ node: ItemListEditableReorderControlNode?) -> (_ height: CGFloat, _ theme: PresentationTheme) -> (CGSize, (Bool) -> ItemListEditableReorderControlNode) {
|
||||
return { height, theme in
|
||||
public static func asyncLayout(_ node: ItemListEditableReorderControlNode?) -> (_ theme: PresentationTheme) -> (CGFloat, (CGFloat, Bool) -> ItemListEditableReorderControlNode) {
|
||||
return { theme in
|
||||
let image = PresentationResourcesItemList.itemListReorderIndicatorIcon(theme)
|
||||
|
||||
let resultNode: ItemListEditableReorderControlNode
|
||||
@ -31,7 +31,7 @@ public final class ItemListEditableReorderControlNode: ASDisplayNode {
|
||||
}
|
||||
resultNode.iconNode.image = image
|
||||
|
||||
return (CGSize(width: 40.0, height: height), { offsetForLabel in
|
||||
return (40.0, { height, offsetForLabel in
|
||||
if let image = image {
|
||||
resultNode.iconNode.frame = CGRect(origin: CGPoint(x: 7.0, y: floor((height - image.size.height) / 2.0) - (offsetForLabel ? 6.0 : 0.0)), size: image.size)
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import TelegramUIPreferences
|
||||
import TelegramPresentationData
|
||||
|
||||
public protocol ItemListItemTag {
|
||||
func isEqual(to other: ItemListItemTag) -> Bool
|
||||
@ -148,3 +150,93 @@ public func itemListNeighborsGroupedInsets(_ neighbors: ItemListNeighbors) -> UI
|
||||
public func itemListHasRoundedBlockLayout(_ params: ListViewItemLayoutParams) -> Bool {
|
||||
return params.width > 480.0
|
||||
}
|
||||
|
||||
public final class ItemListPresentationData: Equatable {
|
||||
public let theme: PresentationTheme
|
||||
public let fontSize: PresentationFontSize
|
||||
public let strings: PresentationStrings
|
||||
|
||||
public init(theme: PresentationTheme, fontSize: PresentationFontSize, strings: PresentationStrings) {
|
||||
self.theme = theme
|
||||
self.fontSize = fontSize
|
||||
self.strings = strings
|
||||
}
|
||||
|
||||
public static func ==(lhs: ItemListPresentationData, rhs: ItemListPresentationData) -> Bool {
|
||||
if lhs.theme !== rhs.theme {
|
||||
return false
|
||||
}
|
||||
if lhs.strings !== rhs.strings {
|
||||
return false
|
||||
}
|
||||
if lhs.fontSize != rhs.fontSize {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public extension PresentationFontSize {
|
||||
var itemListBaseHeaderFontSize: CGFloat {
|
||||
switch self {
|
||||
case .extraSmall:
|
||||
return 13.0
|
||||
case .small:
|
||||
return 14.0
|
||||
case .medium:
|
||||
return 15.0
|
||||
case .regular:
|
||||
return 16.0
|
||||
case .large:
|
||||
return 18.0
|
||||
case .extraLarge:
|
||||
return 22.0
|
||||
case .extraLargeX2:
|
||||
return 25.0
|
||||
}
|
||||
}
|
||||
|
||||
var itemListBaseFontSize: CGFloat {
|
||||
switch self {
|
||||
case .extraSmall:
|
||||
return 14.0
|
||||
case .small:
|
||||
return 15.0
|
||||
case .medium:
|
||||
return 16.0
|
||||
case .regular:
|
||||
return 17.0
|
||||
case .large:
|
||||
return 19.0
|
||||
case .extraLarge:
|
||||
return 23.0
|
||||
case .extraLargeX2:
|
||||
return 26.0
|
||||
}
|
||||
}
|
||||
|
||||
var itemListBaseLabelFontSize: CGFloat {
|
||||
switch self {
|
||||
case .extraSmall:
|
||||
return 11.0
|
||||
case .small:
|
||||
return 12.0
|
||||
case .medium:
|
||||
return 13.0
|
||||
case .regular:
|
||||
return 14.0
|
||||
case .large:
|
||||
return 16.0
|
||||
case .extraLarge:
|
||||
return 20.0
|
||||
case .extraLargeX2:
|
||||
return 23.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension ItemListPresentationData {
|
||||
convenience init(_ presentationData: PresentationData) {
|
||||
self.init(theme: presentationData.theme, fontSize: presentationData.fontSize, strings: presentationData.strings)
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ public enum ItemListActionAlignment {
|
||||
}
|
||||
|
||||
public class ItemListActionItem: ListViewItem, ItemListItem {
|
||||
let theme: PresentationTheme
|
||||
let presentationData: ItemListPresentationData
|
||||
let title: String
|
||||
let kind: ItemListActionKind
|
||||
let alignment: ItemListActionAlignment
|
||||
@ -29,8 +29,8 @@ public class ItemListActionItem: ListViewItem, ItemListItem {
|
||||
let clearHighlightAutomatically: Bool
|
||||
public let tag: Any?
|
||||
|
||||
public init(theme: PresentationTheme, title: String, kind: ItemListActionKind, alignment: ItemListActionAlignment, sectionId: ItemListSectionId, style: ItemListStyle, action: @escaping () -> Void, longTapAction: (() -> Void)? = nil, clearHighlightAutomatically: Bool = true, tag: Any? = nil) {
|
||||
self.theme = theme
|
||||
public init(presentationData: ItemListPresentationData, title: String, kind: ItemListActionKind, alignment: ItemListActionAlignment, sectionId: ItemListSectionId, style: ItemListStyle, action: @escaping () -> Void, longTapAction: (() -> Void)? = nil, clearHighlightAutomatically: Bool = true, tag: Any? = nil) {
|
||||
self.presentationData = presentationData
|
||||
self.title = title
|
||||
self.kind = kind
|
||||
self.alignment = alignment
|
||||
@ -85,8 +85,6 @@ public class ItemListActionItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.regular(17.0)
|
||||
|
||||
public class ItemListActionItemNode: ListViewItemNode, ItemListItemNode {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let topStripeNode: ASDisplayNode
|
||||
@ -138,22 +136,24 @@ public class ItemListActionItemNode: ListViewItemNode, ItemListItemNode {
|
||||
let currentItem = self.item
|
||||
|
||||
return { item, params, neighbors in
|
||||
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
|
||||
var updatedTheme: PresentationTheme?
|
||||
|
||||
if currentItem?.theme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
}
|
||||
|
||||
let textColor: UIColor
|
||||
switch item.kind {
|
||||
case .destructive:
|
||||
textColor = item.theme.list.itemDestructiveColor
|
||||
case .generic:
|
||||
textColor = item.theme.list.itemAccentColor
|
||||
case .neutral:
|
||||
textColor = item.theme.list.itemPrimaryTextColor
|
||||
case .disabled:
|
||||
textColor = item.theme.list.itemDisabledTextColor
|
||||
case .destructive:
|
||||
textColor = item.presentationData.theme.list.itemDestructiveColor
|
||||
case .generic:
|
||||
textColor = item.presentationData.theme.list.itemAccentColor
|
||||
case .neutral:
|
||||
textColor = item.presentationData.theme.list.itemPrimaryTextColor
|
||||
case .disabled:
|
||||
textColor = item.presentationData.theme.list.itemDisabledTextColor
|
||||
}
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: textColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.leftInset - params.rightInset - 20.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
@ -165,16 +165,16 @@ public class ItemListActionItemNode: ListViewItemNode, ItemListItemNode {
|
||||
let itemBackgroundColor: UIColor
|
||||
let itemSeparatorColor: UIColor
|
||||
switch item.style {
|
||||
case .plain:
|
||||
itemBackgroundColor = item.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.theme.list.itemPlainSeparatorColor
|
||||
contentSize = CGSize(width: params.width, height: 44.0)
|
||||
insets = itemListNeighborsPlainInsets(neighbors)
|
||||
case .blocks:
|
||||
itemBackgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
itemSeparatorColor = item.theme.list.itemBlocksSeparatorColor
|
||||
contentSize = CGSize(width: params.width, height: 44.0)
|
||||
insets = itemListNeighborsGroupedInsets(neighbors)
|
||||
case .plain:
|
||||
itemBackgroundColor = item.presentationData.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
contentSize = CGSize(width: params.width, height: titleLayout.size.height + 22.0)
|
||||
insets = itemListNeighborsPlainInsets(neighbors)
|
||||
case .blocks:
|
||||
itemBackgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
contentSize = CGSize(width: params.width, height: titleLayout.size.height + 22.0)
|
||||
insets = itemListNeighborsGroupedInsets(neighbors)
|
||||
}
|
||||
|
||||
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
||||
@ -199,7 +199,7 @@ public class ItemListActionItemNode: ListViewItemNode, ItemListItemNode {
|
||||
strongSelf.topStripeNode.backgroundColor = itemSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = itemSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = itemBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.theme.list.itemHighlightedBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
}
|
||||
|
||||
let _ = titleApply()
|
||||
@ -258,7 +258,7 @@ public class ItemListActionItemNode: ListViewItemNode, ItemListItemNode {
|
||||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
@ -267,13 +267,13 @@ public class ItemListActionItemNode: ListViewItemNode, ItemListItemNode {
|
||||
}
|
||||
|
||||
switch item.alignment {
|
||||
case .natural:
|
||||
strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 11.0), size: titleLayout.size)
|
||||
case .center:
|
||||
strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: params.leftInset + floor((params.width - params.leftInset - params.rightInset - titleLayout.size.width) / 2.0), y: 11.0), size: titleLayout.size)
|
||||
case .natural:
|
||||
strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 11.0), size: titleLayout.size)
|
||||
case .center:
|
||||
strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: params.leftInset + floor((params.width - params.leftInset - params.rightInset - titleLayout.size.width) / 2.0), y: 11.0), size: titleLayout.size)
|
||||
}
|
||||
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: 44.0 + UIScreenPixel + UIScreenPixel))
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: layout.contentSize.height + UIScreenPixel + UIScreenPixel))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -8,15 +8,15 @@ import ActivityIndicator
|
||||
|
||||
public class ItemListActivityTextItem: ListViewItem, ItemListItem {
|
||||
let displayActivity: Bool
|
||||
let theme: PresentationTheme
|
||||
let presentationData: ItemListPresentationData
|
||||
let text: NSAttributedString
|
||||
public let sectionId: ItemListSectionId
|
||||
|
||||
public let isAlwaysPlain: Bool = true
|
||||
|
||||
public init(displayActivity: Bool, theme: PresentationTheme, text: NSAttributedString, sectionId: ItemListSectionId) {
|
||||
public init(displayActivity: Bool, presentationData: ItemListPresentationData, text: NSAttributedString, sectionId: ItemListSectionId) {
|
||||
self.displayActivity = displayActivity
|
||||
self.theme = theme
|
||||
self.presentationData = presentationData
|
||||
self.text = text
|
||||
self.sectionId = sectionId
|
||||
}
|
||||
@ -58,8 +58,6 @@ public class ItemListActivityTextItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.regular(14.0)
|
||||
|
||||
public class ItemListActivityTextItemNode: ListViewItemNode {
|
||||
private let titleNode: TextNode
|
||||
private let activityIndicator: ActivityIndicator
|
||||
@ -87,6 +85,8 @@ public class ItemListActivityTextItemNode: ListViewItemNode {
|
||||
let leftInset: CGFloat = 12.0 + params.leftInset
|
||||
let verticalInset: CGFloat = 7.0
|
||||
|
||||
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseHeaderFontSize)
|
||||
|
||||
var activityWidth: CGFloat = 0.0
|
||||
if item.displayActivity {
|
||||
activityWidth = 25.0
|
||||
@ -116,9 +116,9 @@ public class ItemListActivityTextItemNode: ListViewItemNode {
|
||||
let _ = titleApply()
|
||||
|
||||
strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: leftInset, y: verticalInset), size: titleLayout.size)
|
||||
strongSelf.activityIndicator.frame = CGRect(origin: CGPoint(x: leftInset, y: 7.0), size: CGSize(width: 16.0, height: 16.0))
|
||||
strongSelf.activityIndicator.frame = CGRect(origin: CGPoint(x: leftInset, y: floor((contentSize.height - 16.0) / 2.0)), size: CGSize(width: 16.0, height: 16.0))
|
||||
|
||||
strongSelf.activityIndicator.type = .custom(item.theme.list.itemAccentColor, 16.0, 2.0, false)
|
||||
strongSelf.activityIndicator.type = .custom(item.presentationData.theme.list.itemAccentColor, 16.0, 2.0, false)
|
||||
|
||||
if item.displayActivity {
|
||||
strongSelf.activityIndicator.isHidden = false
|
||||
|
@ -16,7 +16,7 @@ public enum ItemListCheckboxItemColor {
|
||||
}
|
||||
|
||||
public class ItemListCheckboxItem: ListViewItem, ItemListItem {
|
||||
let theme: PresentationTheme
|
||||
let presentationData: ItemListPresentationData
|
||||
let title: String
|
||||
let style: ItemListCheckboxItemStyle
|
||||
let color: ItemListCheckboxItemColor
|
||||
@ -25,8 +25,8 @@ public class ItemListCheckboxItem: ListViewItem, ItemListItem {
|
||||
public let sectionId: ItemListSectionId
|
||||
let action: () -> Void
|
||||
|
||||
public init(theme: PresentationTheme, title: String, style: ItemListCheckboxItemStyle, color: ItemListCheckboxItemColor = .accent, checked: Bool, zeroSeparatorInsets: Bool, sectionId: ItemListSectionId, action: @escaping () -> Void) {
|
||||
self.theme = theme
|
||||
public init(presentationData: ItemListPresentationData, title: String, style: ItemListCheckboxItemStyle, color: ItemListCheckboxItemColor = .accent, checked: Bool, zeroSeparatorInsets: Bool, sectionId: ItemListSectionId, action: @escaping () -> Void) {
|
||||
self.presentationData = presentationData
|
||||
self.title = title
|
||||
self.style = style
|
||||
self.color = color
|
||||
@ -77,8 +77,6 @@ public class ItemListCheckboxItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.regular(17.0)
|
||||
|
||||
public class ItemListCheckboxItemNode: ListViewItemNode {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let topStripeNode: ASDisplayNode
|
||||
@ -141,34 +139,36 @@ public class ItemListCheckboxItemNode: ListViewItemNode {
|
||||
var leftInset: CGFloat = params.leftInset
|
||||
|
||||
switch item.style {
|
||||
case .left:
|
||||
leftInset += 44.0
|
||||
case .right:
|
||||
leftInset += 16.0
|
||||
case .left:
|
||||
leftInset += 44.0
|
||||
case .right:
|
||||
leftInset += 16.0
|
||||
}
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: item.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 20.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 20.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let separatorHeight = UIScreenPixel
|
||||
|
||||
let insets = itemListNeighborsGroupedInsets(neighbors)
|
||||
let contentSize = CGSize(width: params.width, height: 44.0)
|
||||
let contentSize = CGSize(width: params.width, height: titleLayout.size.height + 22.0)
|
||||
|
||||
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
||||
|
||||
var updateCheckImage: UIImage?
|
||||
var updatedTheme: PresentationTheme?
|
||||
|
||||
if currentItem?.theme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
}
|
||||
|
||||
if currentItem?.theme !== item.theme || currentItem?.color != item.color {
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme || currentItem?.color != item.color {
|
||||
switch item.color {
|
||||
case .accent:
|
||||
updateCheckImage = PresentationResourcesItemList.checkIconImage(item.theme)
|
||||
case .secondary:
|
||||
updateCheckImage = PresentationResourcesItemList.secondaryCheckIconImage(item.theme)
|
||||
case .accent:
|
||||
updateCheckImage = PresentationResourcesItemList.checkIconImage(item.presentationData.theme)
|
||||
case .secondary:
|
||||
updateCheckImage = PresentationResourcesItemList.secondaryCheckIconImage(item.presentationData.theme)
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,20 +190,20 @@ public class ItemListCheckboxItemNode: ListViewItemNode {
|
||||
}
|
||||
|
||||
if let _ = updatedTheme {
|
||||
strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.theme.list.itemHighlightedBackgroundColor
|
||||
strongSelf.topStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
}
|
||||
|
||||
let _ = titleApply()
|
||||
|
||||
if let image = strongSelf.iconNode.image {
|
||||
switch item.style {
|
||||
case .left:
|
||||
strongSelf.iconNode.frame = CGRect(origin: CGPoint(x: params.leftInset + floor((leftInset - params.leftInset - image.size.width) / 2.0), y: floor((contentSize.height - image.size.height) / 2.0)), size: image.size)
|
||||
case .right:
|
||||
strongSelf.iconNode.frame = CGRect(origin: CGPoint(x: params.width - params.rightInset - image.size.width - floor((44.0 - image.size.width) / 2.0), y: floor((contentSize.height - image.size.height) / 2.0)), size: image.size)
|
||||
case .left:
|
||||
strongSelf.iconNode.frame = CGRect(origin: CGPoint(x: params.leftInset + floor((leftInset - params.leftInset - image.size.width) / 2.0), y: floor((contentSize.height - image.size.height) / 2.0)), size: image.size)
|
||||
case .right:
|
||||
strongSelf.iconNode.frame = CGRect(origin: CGPoint(x: params.width - params.rightInset - image.size.width - floor((44.0 - image.size.width) / 2.0), y: floor((contentSize.height - image.size.height) / 2.0)), size: image.size)
|
||||
}
|
||||
}
|
||||
strongSelf.iconNode.isHidden = !item.checked
|
||||
@ -244,7 +244,7 @@ public class ItemListCheckboxItemNode: ListViewItemNode {
|
||||
}
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
|
@ -24,7 +24,7 @@ public enum ItemListDisclosureLabelStyle {
|
||||
}
|
||||
|
||||
public class ItemListDisclosureItem: ListViewItem, ItemListItem {
|
||||
let theme: PresentationTheme
|
||||
let presentationData: ItemListPresentationData
|
||||
let icon: UIImage?
|
||||
let title: String
|
||||
let titleColor: ItemListDisclosureItemTitleColor
|
||||
@ -38,8 +38,8 @@ public class ItemListDisclosureItem: ListViewItem, ItemListItem {
|
||||
let clearHighlightAutomatically: Bool
|
||||
public let tag: ItemListItemTag?
|
||||
|
||||
public init(theme: PresentationTheme, icon: UIImage? = nil, title: String, enabled: Bool = true, titleColor: ItemListDisclosureItemTitleColor = .primary, label: String, labelStyle: ItemListDisclosureLabelStyle = .text, sectionId: ItemListSectionId, style: ItemListStyle, disclosureStyle: ItemListDisclosureStyle = .arrow, action: (() -> Void)?, clearHighlightAutomatically: Bool = true, tag: ItemListItemTag? = nil) {
|
||||
self.theme = theme
|
||||
public init(presentationData: ItemListPresentationData, icon: UIImage? = nil, title: String, enabled: Bool = true, titleColor: ItemListDisclosureItemTitleColor = .primary, label: String, labelStyle: ItemListDisclosureLabelStyle = .text, sectionId: ItemListSectionId, style: ItemListStyle, disclosureStyle: ItemListDisclosureStyle = .arrow, action: (() -> Void)?, clearHighlightAutomatically: Bool = true, tag: ItemListItemTag? = nil) {
|
||||
self.presentationData = presentationData
|
||||
self.icon = icon
|
||||
self.title = title
|
||||
self.titleColor = titleColor
|
||||
@ -99,9 +99,7 @@ public class ItemListDisclosureItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.regular(17.0)
|
||||
private let badgeFont = Font.regular(15.0)
|
||||
private let detailFont = Font.regular(13.0)
|
||||
|
||||
public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
@ -190,12 +188,12 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode {
|
||||
let currentHasBadge = self.labelBadgeNode.image != nil
|
||||
|
||||
return { item, params, neighbors in
|
||||
let rightInset: CGFloat
|
||||
var rightInset: CGFloat
|
||||
switch item.disclosureStyle {
|
||||
case .none:
|
||||
rightInset = 16.0 + params.rightInset
|
||||
case .arrow:
|
||||
rightInset = 34.0 + params.rightInset
|
||||
case .none:
|
||||
rightInset = 16.0 + params.rightInset
|
||||
case .arrow:
|
||||
rightInset = 34.0 + params.rightInset
|
||||
}
|
||||
|
||||
var updateArrowImage: UIImage?
|
||||
@ -221,9 +219,9 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode {
|
||||
}
|
||||
|
||||
let badgeDiameter: CGFloat = 20.0
|
||||
if currentItem?.theme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
updateArrowImage = PresentationResourcesItemList.disclosureArrowImage(item.theme)
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
updateArrowImage = PresentationResourcesItemList.disclosureArrowImage(item.presentationData.theme)
|
||||
if let badgeColor = badgeColor {
|
||||
updatedLabelBadgeImage = generateStretchableFilledCircleImage(diameter: badgeDiameter, color: badgeColor)
|
||||
}
|
||||
@ -247,29 +245,41 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode {
|
||||
leftInset += 43.0
|
||||
}
|
||||
|
||||
let titleColor: UIColor
|
||||
if item.enabled {
|
||||
titleColor = item.titleColor == .accent ? item.theme.list.itemAccentColor : item.theme.list.itemPrimaryTextColor
|
||||
} else {
|
||||
titleColor = item.theme.list.itemDisabledTextColor
|
||||
var additionalTextRightInset: CGFloat = 0.0
|
||||
switch item.labelStyle {
|
||||
case .badge:
|
||||
additionalTextRightInset += 44.0
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: titleColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - 20.0 - leftInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let titleColor: UIColor
|
||||
if item.enabled {
|
||||
titleColor = item.titleColor == .accent ? item.presentationData.theme.list.itemAccentColor : item.presentationData.theme.list.itemPrimaryTextColor
|
||||
} else {
|
||||
titleColor = item.presentationData.theme.list.itemDisabledTextColor
|
||||
}
|
||||
|
||||
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: titleColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - 20.0 - leftInset - additionalTextRightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let detailFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 13.0 / 17.0))
|
||||
|
||||
let labelFont: UIFont
|
||||
let labelBadgeColor: UIColor
|
||||
var labelConstrain: CGFloat = params.width - params.rightInset - leftInset - 40.0 - titleLayout.size.width - 10.0
|
||||
switch item.labelStyle {
|
||||
case .badge:
|
||||
labelBadgeColor = item.theme.list.itemCheckColors.foregroundColor
|
||||
labelFont = badgeFont
|
||||
case .detailText, .multilineDetailText:
|
||||
labelBadgeColor = item.theme.list.itemSecondaryTextColor
|
||||
labelFont = detailFont
|
||||
labelConstrain = params.width - params.rightInset - 40.0 - leftInset
|
||||
default:
|
||||
labelBadgeColor = item.theme.list.itemSecondaryTextColor
|
||||
labelFont = titleFont
|
||||
case .badge:
|
||||
labelBadgeColor = item.presentationData.theme.list.itemCheckColors.foregroundColor
|
||||
labelFont = badgeFont
|
||||
case .detailText, .multilineDetailText:
|
||||
labelBadgeColor = item.presentationData.theme.list.itemSecondaryTextColor
|
||||
labelFont = detailFont
|
||||
labelConstrain = params.width - params.rightInset - 40.0 - leftInset
|
||||
default:
|
||||
labelBadgeColor = item.presentationData.theme.list.itemSecondaryTextColor
|
||||
labelFont = titleFont
|
||||
}
|
||||
var multilineLabel = false
|
||||
if case .multilineDetailText = item.labelStyle {
|
||||
@ -278,27 +288,30 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode {
|
||||
|
||||
let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.label, font: labelFont, textColor:labelBadgeColor), backgroundColor: nil, maximumNumberOfLines: multilineLabel ? 0 : 1, truncationType: .end, constrainedSize: CGSize(width: labelConstrain, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let verticalInset: CGFloat = 11.0
|
||||
let titleSpacing: CGFloat = 3.0
|
||||
|
||||
let height: CGFloat
|
||||
switch item.labelStyle {
|
||||
case .detailText:
|
||||
height = 64.0
|
||||
case .multilineDetailText:
|
||||
height = 44.0 + labelLayout.size.height
|
||||
default:
|
||||
height = 44.0
|
||||
case .detailText:
|
||||
height = verticalInset * 2.0 + titleLayout.size.height + titleSpacing + labelLayout.size.height
|
||||
case .multilineDetailText:
|
||||
height = verticalInset * 2.0 + titleLayout.size.height + titleSpacing + labelLayout.size.height
|
||||
default:
|
||||
height = verticalInset * 2.0 + titleLayout.size.height
|
||||
}
|
||||
|
||||
switch item.style {
|
||||
case .plain:
|
||||
itemBackgroundColor = item.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.theme.list.itemPlainSeparatorColor
|
||||
contentSize = CGSize(width: params.width, height: height)
|
||||
insets = itemListNeighborsPlainInsets(neighbors)
|
||||
case .blocks:
|
||||
itemBackgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
itemSeparatorColor = item.theme.list.itemBlocksSeparatorColor
|
||||
contentSize = CGSize(width: params.width, height: height)
|
||||
insets = itemListNeighborsGroupedInsets(neighbors)
|
||||
case .plain:
|
||||
itemBackgroundColor = item.presentationData.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
contentSize = CGSize(width: params.width, height: height)
|
||||
insets = itemListNeighborsPlainInsets(neighbors)
|
||||
case .blocks:
|
||||
itemBackgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
contentSize = CGSize(width: params.width, height: height)
|
||||
insets = itemListNeighborsGroupedInsets(neighbors)
|
||||
}
|
||||
|
||||
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
||||
@ -343,70 +356,71 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode {
|
||||
strongSelf.topStripeNode.backgroundColor = itemSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = itemSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = itemBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.theme.list.itemHighlightedBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
}
|
||||
|
||||
let _ = titleApply()
|
||||
let _ = labelApply()
|
||||
|
||||
switch item.style {
|
||||
case .plain:
|
||||
if strongSelf.backgroundNode.supernode != nil {
|
||||
strongSelf.backgroundNode.removeFromSupernode()
|
||||
}
|
||||
if strongSelf.topStripeNode.supernode != nil {
|
||||
strongSelf.topStripeNode.removeFromSupernode()
|
||||
}
|
||||
if strongSelf.bottomStripeNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 0)
|
||||
}
|
||||
if strongSelf.maskNode.supernode != nil {
|
||||
strongSelf.maskNode.removeFromSupernode()
|
||||
}
|
||||
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: leftInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - leftInset, height: separatorHeight))
|
||||
case .blocks:
|
||||
if strongSelf.backgroundNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0)
|
||||
}
|
||||
if strongSelf.topStripeNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.topStripeNode, at: 1)
|
||||
}
|
||||
if strongSelf.bottomStripeNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2)
|
||||
}
|
||||
if strongSelf.maskNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
|
||||
}
|
||||
|
||||
let hasCorners = itemListHasRoundedBlockLayout(params)
|
||||
var hasTopCorners = false
|
||||
var hasBottomCorners = false
|
||||
switch neighbors.top {
|
||||
case .sameSection(false):
|
||||
strongSelf.topStripeNode.isHidden = true
|
||||
default:
|
||||
hasTopCorners = true
|
||||
strongSelf.topStripeNode.isHidden = hasCorners
|
||||
}
|
||||
let bottomStripeInset: CGFloat
|
||||
switch neighbors.bottom {
|
||||
case .sameSection(false):
|
||||
bottomStripeInset = leftInset
|
||||
default:
|
||||
bottomStripeInset = 0.0
|
||||
hasBottomCorners = true
|
||||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: separatorHeight))
|
||||
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - bottomStripeInset, height: separatorHeight))
|
||||
case .plain:
|
||||
if strongSelf.backgroundNode.supernode != nil {
|
||||
strongSelf.backgroundNode.removeFromSupernode()
|
||||
}
|
||||
if strongSelf.topStripeNode.supernode != nil {
|
||||
strongSelf.topStripeNode.removeFromSupernode()
|
||||
}
|
||||
if strongSelf.bottomStripeNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 0)
|
||||
}
|
||||
if strongSelf.maskNode.supernode != nil {
|
||||
strongSelf.maskNode.removeFromSupernode()
|
||||
}
|
||||
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: leftInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - leftInset, height: separatorHeight))
|
||||
case .blocks:
|
||||
if strongSelf.backgroundNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0)
|
||||
}
|
||||
if strongSelf.topStripeNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.topStripeNode, at: 1)
|
||||
}
|
||||
if strongSelf.bottomStripeNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2)
|
||||
}
|
||||
if strongSelf.maskNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.maskNode, at: 3)
|
||||
}
|
||||
|
||||
let hasCorners = itemListHasRoundedBlockLayout(params)
|
||||
var hasTopCorners = false
|
||||
var hasBottomCorners = false
|
||||
switch neighbors.top {
|
||||
case .sameSection(false):
|
||||
strongSelf.topStripeNode.isHidden = true
|
||||
default:
|
||||
hasTopCorners = true
|
||||
strongSelf.topStripeNode.isHidden = hasCorners
|
||||
}
|
||||
let bottomStripeInset: CGFloat
|
||||
switch neighbors.bottom {
|
||||
case .sameSection(false):
|
||||
bottomStripeInset = leftInset
|
||||
default:
|
||||
bottomStripeInset = 0.0
|
||||
hasBottomCorners = true
|
||||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: separatorHeight))
|
||||
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - bottomStripeInset, height: separatorHeight))
|
||||
}
|
||||
|
||||
strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 11.0), size: titleLayout.size)
|
||||
let titleFrame = CGRect(origin: CGPoint(x: leftInset, y: 11.0), size: titleLayout.size)
|
||||
strongSelf.titleNode.frame = titleFrame
|
||||
|
||||
if let updateBadgeImage = updatedLabelBadgeImage {
|
||||
if strongSelf.labelBadgeNode.supernode == nil {
|
||||
@ -420,14 +434,15 @@ public class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode {
|
||||
}
|
||||
|
||||
let badgeWidth = max(badgeDiameter, labelLayout.size.width + 10.0)
|
||||
strongSelf.labelBadgeNode.frame = CGRect(origin: CGPoint(x: params.width - rightInset - badgeWidth, y: 12.0), size: CGSize(width: badgeWidth, height: badgeDiameter))
|
||||
let badgeFrame = CGRect(origin: CGPoint(x: params.width - rightInset - badgeWidth, y: floor((contentSize.height - badgeDiameter) / 2.0)), size: CGSize(width: badgeWidth, height: badgeDiameter))
|
||||
strongSelf.labelBadgeNode.frame = badgeFrame
|
||||
|
||||
let labelFrame: CGRect
|
||||
switch item.labelStyle {
|
||||
case .badge:
|
||||
labelFrame = CGRect(origin: CGPoint(x: params.width - rightInset - badgeWidth + (badgeWidth - labelLayout.size.width) / 2.0, y: 13.0), size: labelLayout.size)
|
||||
labelFrame = CGRect(origin: CGPoint(x: params.width - rightInset - badgeWidth + (badgeWidth - labelLayout.size.width) / 2.0, y: badgeFrame.minY + 1), size: labelLayout.size)
|
||||
case .detailText, .multilineDetailText:
|
||||
labelFrame = CGRect(origin: CGPoint(x: leftInset, y: 36.0), size: labelLayout.size)
|
||||
labelFrame = CGRect(origin: CGPoint(x: leftInset, y: titleFrame.maxY + titleSpacing), size: labelLayout.size)
|
||||
default:
|
||||
labelFrame = CGRect(origin: CGPoint(x: params.width - rightInset - labelLayout.size.width, y: 11.0), size: labelLayout.size)
|
||||
}
|
||||
|
@ -19,15 +19,15 @@ public enum InfoListItemLinkAction {
|
||||
public class InfoListItem: ListViewItem {
|
||||
public let selectable: Bool = false
|
||||
|
||||
let theme: PresentationTheme
|
||||
let presentationData: ItemListPresentationData
|
||||
let title: String
|
||||
let text: InfoListItemText
|
||||
let style: ItemListStyle
|
||||
let linkAction: ((InfoListItemLinkAction) -> Void)?
|
||||
let closeAction: (() -> Void)?
|
||||
|
||||
public init(theme: PresentationTheme, title: String, text: InfoListItemText, style: ItemListStyle, linkAction: ((InfoListItemLinkAction) -> Void)? = nil, closeAction: (() -> Void)?) {
|
||||
self.theme = theme
|
||||
public init(presentationData: ItemListPresentationData, title: String, text: InfoListItemText, style: ItemListStyle, linkAction: ((InfoListItemLinkAction) -> Void)? = nil, closeAction: (() -> Void)?) {
|
||||
self.presentationData = presentationData
|
||||
self.title = title
|
||||
self.text = text
|
||||
self.style = style
|
||||
@ -72,9 +72,9 @@ public class InfoListItem: ListViewItem {
|
||||
public class ItemListInfoItem: InfoListItem, ItemListItem {
|
||||
public let sectionId: ItemListSectionId
|
||||
|
||||
public init(theme: PresentationTheme, title: String, text: InfoListItemText, style: ItemListStyle, sectionId: ItemListSectionId, linkAction: ((InfoListItemLinkAction) -> Void)? = nil, closeAction: (() -> Void)?) {
|
||||
public init(presentationData: ItemListPresentationData, title: String, text: InfoListItemText, style: ItemListStyle, sectionId: ItemListSectionId, linkAction: ((InfoListItemLinkAction) -> Void)? = nil, closeAction: (() -> Void)?) {
|
||||
self.sectionId = sectionId
|
||||
super.init(theme: theme, title: title, text: text, style: style, linkAction: linkAction, closeAction: closeAction)
|
||||
super.init(presentationData: presentationData, title: title, text: text, style: style, linkAction: linkAction, closeAction: closeAction)
|
||||
}
|
||||
|
||||
override public func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal<Void, NoError>?, (ListViewItemApply) -> Void)) -> Void) {
|
||||
@ -111,11 +111,6 @@ public class ItemListInfoItem: InfoListItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.semibold(17.0)
|
||||
private let textFont = Font.regular(16.0)
|
||||
private let textBoldFont = Font.semibold(16.0)
|
||||
private let badgeFont = Font.regular(15.0)
|
||||
|
||||
class InfoItemNode: ListViewItemNode {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let topStripeNode: ASDisplayNode
|
||||
@ -211,6 +206,11 @@ class InfoItemNode: ListViewItemNode {
|
||||
return { item, params, neighbors in
|
||||
let leftInset: CGFloat = 15.0 + params.leftInset
|
||||
let rightInset: CGFloat = 15.0 + params.rightInset
|
||||
|
||||
let titleFont = Font.semibold(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
let textFont = Font.regular(item.presentationData.fontSize.itemListBaseHeaderFontSize)
|
||||
let textBoldFont = Font.semibold(item.presentationData.fontSize.itemListBaseHeaderFontSize)
|
||||
let badgeFont = Font.regular(15.0)
|
||||
|
||||
var updatedTheme: PresentationTheme?
|
||||
var updatedBadgeImage: UIImage?
|
||||
@ -218,10 +218,10 @@ class InfoItemNode: ListViewItemNode {
|
||||
var updatedCloseIcon: UIImage?
|
||||
|
||||
let badgeDiameter: CGFloat = 20.0
|
||||
if currentItem?.theme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
updatedBadgeImage = generateStretchableFilledCircleImage(diameter: badgeDiameter, color: item.theme.list.itemDestructiveColor)
|
||||
updatedCloseIcon = PresentationResourcesItemList.itemListCloseIconImage(item.theme)
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
updatedBadgeImage = generateStretchableFilledCircleImage(diameter: badgeDiameter, color: item.presentationData.theme.list.itemDestructiveColor)
|
||||
updatedCloseIcon = PresentationResourcesItemList.itemListCloseIconImage(item.presentationData.theme)
|
||||
}
|
||||
|
||||
let insets: UIEdgeInsets
|
||||
@ -236,26 +236,26 @@ class InfoItemNode: ListViewItemNode {
|
||||
let itemSeparatorColor: UIColor
|
||||
|
||||
switch item.style {
|
||||
case .plain:
|
||||
itemBackgroundColor = item.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.theme.list.itemPlainSeparatorColor
|
||||
case .blocks:
|
||||
itemBackgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
itemSeparatorColor = item.theme.list.itemBlocksSeparatorColor
|
||||
case .plain:
|
||||
itemBackgroundColor = item.presentationData.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
case .blocks:
|
||||
itemBackgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
}
|
||||
|
||||
let attributedText: NSAttributedString
|
||||
switch item.text {
|
||||
case let .plain(text):
|
||||
attributedText = NSAttributedString(string: text, font: textFont, textColor: item.theme.list.itemPrimaryTextColor)
|
||||
case let .markdown(text):
|
||||
attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: textFont, textColor: item.theme.list.itemPrimaryTextColor), bold: MarkdownAttributeSet(font: textBoldFont, textColor: item.theme.list.itemPrimaryTextColor), link: MarkdownAttributeSet(font: textFont, textColor: item.theme.list.itemAccentColor), linkAttribute: { contents in
|
||||
return (TelegramTextAttributes.URL, contents)
|
||||
}))
|
||||
case let .plain(text):
|
||||
attributedText = NSAttributedString(string: text, font: textFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor)
|
||||
case let .markdown(text):
|
||||
attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: textFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), bold: MarkdownAttributeSet(font: textBoldFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), link: MarkdownAttributeSet(font: textFont, textColor: item.presentationData.theme.list.itemAccentColor), linkAttribute: { contents in
|
||||
return (TelegramTextAttributes.URL, contents)
|
||||
}))
|
||||
}
|
||||
|
||||
let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "!", font: badgeFont, textColor: item.theme.list.itemCheckColors.foregroundColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: badgeDiameter, height: badgeDiameter), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: item.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 2, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset - badgeDiameter - 8.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: "!", font: badgeFont, textColor: item.presentationData.theme.list.itemCheckColors.foregroundColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: badgeDiameter, height: badgeDiameter), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 2, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset - badgeDiameter - 8.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 3, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let contentSize = CGSize(width: params.width, height: titleLayout.size.height + textLayout.size.height + 36.0)
|
||||
@ -320,7 +320,7 @@ class InfoItemNode: ListViewItemNode {
|
||||
|
||||
strongSelf.closeButton.isHidden = item.closeAction == nil
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
@ -338,7 +338,7 @@ class InfoItemNode: ListViewItemNode {
|
||||
strongSelf.closeButton.setImage(updatedCloseIcon, for: [])
|
||||
}
|
||||
|
||||
strongSelf.badgeNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 15.0), size: CGSize(width: badgeDiameter, height: badgeDiameter))
|
||||
strongSelf.badgeNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 15.0 + floor((titleLayout.size.height - badgeDiameter) / 2.0)), size: CGSize(width: badgeDiameter, height: badgeDiameter))
|
||||
|
||||
strongSelf.labelNode.frame = CGRect(origin: CGPoint(x: strongSelf.badgeNode.frame.midX - labelLayout.size.width / 2.0, y: strongSelf.badgeNode.frame.minY + 1.0), size: labelLayout.size)
|
||||
|
||||
@ -420,7 +420,7 @@ class InfoItemNode: ListViewItemNode {
|
||||
if let current = self.linkHighlightingNode {
|
||||
linkHighlightingNode = current
|
||||
} else {
|
||||
linkHighlightingNode = LinkHighlightingNode(color: item.theme.list.itemAccentColor.withAlphaComponent(0.5))
|
||||
linkHighlightingNode = LinkHighlightingNode(color: item.presentationData.theme.list.itemAccentColor.withAlphaComponent(0.5))
|
||||
self.linkHighlightingNode = linkHighlightingNode
|
||||
self.insertSubnode(linkHighlightingNode, belowSubnode: self.textNode)
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ public struct ItemListMultilineInputInlineAction {
|
||||
}
|
||||
|
||||
public class ItemListMultilineInputItem: ListViewItem, ItemListItem {
|
||||
let theme: PresentationTheme
|
||||
let presentationData: ItemListPresentationData
|
||||
let text: String
|
||||
let placeholder: String
|
||||
public let sectionId: ItemListSectionId
|
||||
@ -51,8 +51,8 @@ public class ItemListMultilineInputItem: ListViewItem, ItemListItem {
|
||||
let inlineAction: ItemListMultilineInputInlineAction?
|
||||
public let tag: ItemListItemTag?
|
||||
|
||||
public init(theme: PresentationTheme, text: String, placeholder: String, maxLength: ItemListMultilineInputItemTextLimit?, sectionId: ItemListSectionId, style: ItemListStyle, capitalization: Bool = true, autocorrection: Bool = true, returnKeyType: UIReturnKeyType = .default, minimalHeight: CGFloat? = nil, textUpdated: @escaping (String) -> Void, shouldUpdateText: @escaping (String) -> Bool = { _ in return true }, processPaste: ((String) -> Void)? = nil, updatedFocus: ((Bool) -> Void)? = nil, tag: ItemListItemTag? = nil, action: (() -> Void)? = nil, inlineAction: ItemListMultilineInputInlineAction? = nil) {
|
||||
self.theme = theme
|
||||
public init(presentationData: ItemListPresentationData, text: String, placeholder: String, maxLength: ItemListMultilineInputItemTextLimit?, sectionId: ItemListSectionId, style: ItemListStyle, capitalization: Bool = true, autocorrection: Bool = true, returnKeyType: UIReturnKeyType = .default, minimalHeight: CGFloat? = nil, textUpdated: @escaping (String) -> Void, shouldUpdateText: @escaping (String) -> Bool = { _ in return true }, processPaste: ((String) -> Void)? = nil, updatedFocus: ((Bool) -> Void)? = nil, tag: ItemListItemTag? = nil, action: (() -> Void)? = nil, inlineAction: ItemListMultilineInputInlineAction? = nil) {
|
||||
self.presentationData = presentationData
|
||||
self.text = text
|
||||
self.placeholder = placeholder
|
||||
self.maxLength = maxLength
|
||||
@ -105,8 +105,6 @@ public class ItemListMultilineInputItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.regular(17.0)
|
||||
|
||||
public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNodeDelegate, ItemListItemNode, ItemListItemFocusableNode {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let topStripeNode: ASDisplayNode
|
||||
@ -159,9 +157,11 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
|
||||
|
||||
var textColor: UIColor = .black
|
||||
if let item = self.item {
|
||||
textColor = item.theme.list.itemPrimaryTextColor
|
||||
textColor = item.presentationData.theme.list.itemPrimaryTextColor
|
||||
self.textNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(item.presentationData.fontSize.itemListBaseFontSize), NSAttributedString.Key.foregroundColor.rawValue: textColor]
|
||||
} else {
|
||||
self.textNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(17.0), NSAttributedString.Key.foregroundColor.rawValue: textColor]
|
||||
}
|
||||
self.textNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(17.0), NSAttributedString.Key.foregroundColor.rawValue: textColor]
|
||||
self.textNode.clipsToBounds = true
|
||||
self.textNode.delegate = self
|
||||
self.textNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0)
|
||||
@ -175,8 +175,8 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
|
||||
|
||||
return { item, params, neighbors in
|
||||
var updatedTheme: PresentationTheme?
|
||||
if currentItem?.theme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
}
|
||||
|
||||
let itemBackgroundColor: UIColor
|
||||
@ -185,11 +185,11 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
|
||||
let leftInset = 16.0 + params.rightInset
|
||||
switch item.style {
|
||||
case .plain:
|
||||
itemBackgroundColor = item.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.theme.list.itemPlainSeparatorColor
|
||||
itemBackgroundColor = item.presentationData.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
case .blocks:
|
||||
itemBackgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
itemSeparatorColor = item.theme.list.itemBlocksSeparatorColor
|
||||
itemBackgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
}
|
||||
|
||||
var limitTextString: NSAttributedString?
|
||||
@ -206,7 +206,7 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
|
||||
let displayTextLimit = textLength > maxLength.value * 70 / 100
|
||||
let remainingCount = maxLength.value - textLength
|
||||
if displayTextLimit {
|
||||
limitTextString = NSAttributedString(string: "\(remainingCount)", font: Font.regular(13.0), textColor: remainingCount < 0 ? item.theme.list.itemDestructiveColor : item.theme.list.itemSecondaryTextColor)
|
||||
limitTextString = NSAttributedString(string: "\(remainingCount)", font: Font.regular(13.0), textColor: remainingCount < 0 ? item.presentationData.theme.list.itemDestructiveColor : item.presentationData.theme.list.itemSecondaryTextColor)
|
||||
}
|
||||
|
||||
rightInset += 30.0 + 4.0
|
||||
@ -226,8 +226,8 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
|
||||
if measureText.hasSuffix("\n") || measureText.isEmpty {
|
||||
measureText += "|"
|
||||
}
|
||||
let attributedMeasureText = NSAttributedString(string: measureText, font: Font.regular(17.0), textColor: .black)
|
||||
let attributedText = NSAttributedString(string: item.text, font: Font.regular(17.0), textColor: item.theme.list.itemPrimaryTextColor)
|
||||
let attributedMeasureText = NSAttributedString(string: measureText, font: Font.regular(item.presentationData.fontSize.itemListBaseFontSize), textColor: .black)
|
||||
let attributedText = NSAttributedString(string: item.text, font: Font.regular(item.presentationData.fontSize.itemListBaseFontSize), textColor: item.presentationData.theme.list.itemPrimaryTextColor)
|
||||
let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: attributedMeasureText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - 16.0 - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let separatorHeight = UIScreenPixel
|
||||
@ -246,7 +246,7 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
|
||||
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
||||
let layoutSize = layout.size
|
||||
|
||||
let attributedPlaceholderText = NSAttributedString(string: item.placeholder, font: Font.regular(17.0), textColor: item.theme.list.itemPlaceholderTextColor)
|
||||
let attributedPlaceholderText = NSAttributedString(string: item.placeholder, font: Font.regular(item.presentationData.fontSize.itemListBaseFontSize), textColor: item.presentationData.theme.list.itemPlaceholderTextColor)
|
||||
|
||||
return (layout, { [weak self] in
|
||||
if let strongSelf = self {
|
||||
@ -259,12 +259,12 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
|
||||
strongSelf.backgroundNode.backgroundColor = itemBackgroundColor
|
||||
|
||||
if strongSelf.isNodeLoaded {
|
||||
strongSelf.textNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(17.0), NSAttributedString.Key.foregroundColor.rawValue: item.theme.list.itemPrimaryTextColor]
|
||||
strongSelf.textNode.tintColor = item.theme.list.itemAccentColor
|
||||
strongSelf.textNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(item.presentationData.fontSize.itemListBaseFontSize), NSAttributedString.Key.foregroundColor.rawValue: item.presentationData.theme.list.itemPrimaryTextColor]
|
||||
strongSelf.textNode.tintColor = item.presentationData.theme.list.itemAccentColor
|
||||
}
|
||||
|
||||
if let inlineAction = item.inlineAction {
|
||||
strongSelf.inlineActionButtonNode?.setImage(generateTintedImage(image: inlineAction.icon, color: item.theme.list.itemAccentColor), for: .normal)
|
||||
strongSelf.inlineActionButtonNode?.setImage(generateTintedImage(image: inlineAction.icon, color: item.presentationData.theme.list.itemAccentColor), for: .normal)
|
||||
}
|
||||
}
|
||||
|
||||
@ -323,7 +323,7 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
|
||||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
@ -334,7 +334,7 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
|
||||
strongSelf.textNode.attributedPlaceholderText = attributedPlaceholderText
|
||||
}
|
||||
|
||||
strongSelf.textNode.keyboardAppearance = item.theme.rootController.keyboardColor.keyboardAppearance
|
||||
strongSelf.textNode.keyboardAppearance = item.presentationData.theme.rootController.keyboardColor.keyboardAppearance
|
||||
|
||||
strongSelf.textClippingNode.frame = CGRect(origin: CGPoint(x: leftInset, y: textTopInset), size: CGSize(width: params.width - leftInset - params.rightInset, height: textLayout.size.height))
|
||||
strongSelf.textNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: params.width - leftInset - 16.0 - rightInset, height: textLayout.size.height + 1.0))
|
||||
@ -355,7 +355,7 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
|
||||
inlineActionButtonNode = currentInlineActionButtonNode
|
||||
} else {
|
||||
inlineActionButtonNode = HighlightableButtonNode()
|
||||
inlineActionButtonNode.setImage(generateTintedImage(image: inlineAction.icon, color: item.theme.list.itemAccentColor), for: .normal)
|
||||
inlineActionButtonNode.setImage(generateTintedImage(image: inlineAction.icon, color: item.presentationData.theme.list.itemAccentColor), for: .normal)
|
||||
inlineActionButtonNode.addTarget(strongSelf, action: #selector(strongSelf.inlineActionPressed), forControlEvents: .touchUpInside)
|
||||
strongSelf.addSubnode(inlineActionButtonNode)
|
||||
strongSelf.inlineActionButtonNode = inlineActionButtonNode
|
||||
@ -431,7 +431,7 @@ public class ItemListMultilineInputItemNode: ListViewItemNode, ASEditableTextNod
|
||||
if let item = self.item {
|
||||
if let text = self.textNode.attributedText {
|
||||
let updatedText = text.string
|
||||
let updatedAttributedText = NSAttributedString(string: updatedText, font: Font.regular(17.0), textColor: item.theme.list.itemPrimaryTextColor)
|
||||
let updatedAttributedText = NSAttributedString(string: updatedText, font: Font.regular(item.presentationData.fontSize.itemListBaseFontSize), textColor: item.presentationData.theme.list.itemPrimaryTextColor)
|
||||
if text.string != updatedAttributedText.string {
|
||||
self.textNode.attributedText = updatedAttributedText
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ public enum ItemListMultilineTextBaseFont {
|
||||
}
|
||||
|
||||
public class ItemListMultilineTextItem: ListViewItem, ItemListItem {
|
||||
let theme: PresentationTheme
|
||||
let presentationData: ItemListPresentationData
|
||||
let text: String
|
||||
let enabledEntityTypes: EnabledEntityTypes
|
||||
let font: ItemListMultilineTextBaseFont
|
||||
@ -27,8 +27,8 @@ public class ItemListMultilineTextItem: ListViewItem, ItemListItem {
|
||||
|
||||
public let selectable: Bool
|
||||
|
||||
public init(theme: PresentationTheme, text: String, enabledEntityTypes: EnabledEntityTypes, font: ItemListMultilineTextBaseFont = .default, sectionId: ItemListSectionId, style: ItemListStyle, action: (() -> Void)? = nil, longTapAction: (() -> Void)? = nil, linkItemAction: ((TextLinkItemActionType, TextLinkItem) -> Void)? = nil, tag: Any? = nil) {
|
||||
self.theme = theme
|
||||
public init(presentationData: ItemListPresentationData, text: String, enabledEntityTypes: EnabledEntityTypes, font: ItemListMultilineTextBaseFont = .default, sectionId: ItemListSectionId, style: ItemListStyle, action: (() -> Void)? = nil, longTapAction: (() -> Void)? = nil, linkItemAction: ((TextLinkItemActionType, TextLinkItem) -> Void)? = nil, tag: Any? = nil) {
|
||||
self.presentationData = presentationData
|
||||
self.text = text
|
||||
self.enabledEntityTypes = enabledEntityTypes
|
||||
self.font = font
|
||||
@ -81,12 +81,6 @@ public class ItemListMultilineTextItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.regular(17.0)
|
||||
private let titleBoldFont = Font.medium(17.0)
|
||||
private let titleItalicFont = Font.italic(17.0)
|
||||
private let titleBoldItalicFont = Font.semiboldItalic(17.0)
|
||||
private let titleFixedFont = Font.regular(17.0)
|
||||
|
||||
public class ItemListMultilineTextItemNode: ListViewItemNode {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let topStripeNode: ASDisplayNode
|
||||
@ -165,11 +159,11 @@ public class ItemListMultilineTextItemNode: ListViewItemNode {
|
||||
return { item, params, neighbors in
|
||||
var updatedTheme: PresentationTheme?
|
||||
|
||||
if currentItem?.theme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
}
|
||||
|
||||
let textColor: UIColor = item.theme.list.itemPrimaryTextColor
|
||||
let textColor: UIColor = item.presentationData.theme.list.itemPrimaryTextColor
|
||||
|
||||
let leftInset: CGFloat
|
||||
let itemBackgroundColor: UIColor
|
||||
@ -177,30 +171,33 @@ public class ItemListMultilineTextItemNode: ListViewItemNode {
|
||||
|
||||
switch item.style {
|
||||
case .plain:
|
||||
itemBackgroundColor = item.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.theme.list.itemPlainSeparatorColor
|
||||
itemBackgroundColor = item.presentationData.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
leftInset = 16.0 + params.leftInset
|
||||
case .blocks:
|
||||
itemBackgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
itemSeparatorColor = item.theme.list.itemBlocksSeparatorColor
|
||||
itemBackgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
leftInset = 16.0 + params.rightInset
|
||||
}
|
||||
|
||||
var baseFont = titleFont
|
||||
var linkFont = titleFont
|
||||
var boldFont = titleBoldFont
|
||||
var italicFont = titleItalicFont
|
||||
var boldItalicFont = titleBoldItalicFont
|
||||
let fontSize = item.presentationData.fontSize.itemListBaseFontSize
|
||||
|
||||
var baseFont = Font.regular(fontSize)
|
||||
var linkFont = baseFont
|
||||
var boldFont = Font.medium(fontSize)
|
||||
var italicFont = Font.italic(fontSize)
|
||||
var boldItalicFont = Font.semiboldItalic(fontSize)
|
||||
let titleFixedFont = Font.monospace(fontSize)
|
||||
if case .monospace = item.font {
|
||||
baseFont = Font.monospace(17.0)
|
||||
linkFont = Font.monospace(17.0)
|
||||
boldFont = Font.semiboldMonospace(17.0)
|
||||
italicFont = Font.italicMonospace(17.0)
|
||||
boldItalicFont = Font.semiboldItalicMonospace(17.0)
|
||||
baseFont = Font.monospace(fontSize)
|
||||
linkFont = Font.monospace(fontSize)
|
||||
boldFont = Font.semiboldMonospace(fontSize)
|
||||
italicFont = Font.italicMonospace(fontSize)
|
||||
boldItalicFont = Font.semiboldItalicMonospace(fontSize)
|
||||
}
|
||||
|
||||
let entities = generateTextEntities(item.text, enabledTypes: item.enabledEntityTypes)
|
||||
let string = stringWithAppliedEntities(item.text, entities: entities, baseColor: textColor, linkColor: item.theme.list.itemAccentColor, baseFont: baseFont, linkFont: linkFont, boldFont: boldFont, italicFont: italicFont, boldItalicFont: boldItalicFont, fixedFont: titleFixedFont, blockQuoteFont: titleFont)
|
||||
let string = stringWithAppliedEntities(item.text, entities: entities, baseColor: textColor, linkColor: item.presentationData.theme.list.itemAccentColor, baseFont: baseFont, linkFont: linkFont, boldFont: boldFont, italicFont: italicFont, boldItalicFont: boldItalicFont, fixedFont: titleFixedFont, blockQuoteFont: baseFont)
|
||||
|
||||
let (titleLayout, titleApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: string, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
@ -231,7 +228,7 @@ public class ItemListMultilineTextItemNode: ListViewItemNode {
|
||||
strongSelf.topStripeNode.backgroundColor = itemSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = itemSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = itemBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.theme.list.itemHighlightedBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
}
|
||||
|
||||
let _ = titleApply()
|
||||
@ -289,7 +286,7 @@ public class ItemListMultilineTextItemNode: ListViewItemNode {
|
||||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
@ -416,7 +413,7 @@ public class ItemListMultilineTextItemNode: ListViewItemNode {
|
||||
if let current = self.linkHighlightingNode {
|
||||
linkHighlightingNode = current
|
||||
} else {
|
||||
linkHighlightingNode = LinkHighlightingNode(color: item.theme.list.itemAccentColor.withAlphaComponent(0.5))
|
||||
linkHighlightingNode = LinkHighlightingNode(color: item.presentationData.theme.list.itemAccentColor.withAlphaComponent(0.5))
|
||||
self.linkHighlightingNode = linkHighlightingNode
|
||||
self.insertSubnode(linkHighlightingNode, belowSubnode: self.textNode)
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ public enum ItemListSectionHeaderActivityIndicator {
|
||||
}
|
||||
|
||||
public class ItemListSectionHeaderItem: ListViewItem, ItemListItem {
|
||||
let theme: PresentationTheme
|
||||
let presentationData: ItemListPresentationData
|
||||
let text: String
|
||||
let multiline: Bool
|
||||
let activityIndicator: ItemListSectionHeaderActivityIndicator
|
||||
@ -48,8 +48,8 @@ public class ItemListSectionHeaderItem: ListViewItem, ItemListItem {
|
||||
|
||||
public let isAlwaysPlain: Bool = true
|
||||
|
||||
public init(theme: PresentationTheme, text: String, multiline: Bool = false, activityIndicator: ItemListSectionHeaderActivityIndicator = .none, accessoryText: ItemListSectionHeaderAccessoryText? = nil, sectionId: ItemListSectionId) {
|
||||
self.theme = theme
|
||||
public init(presentationData: ItemListPresentationData, text: String, multiline: Bool = false, activityIndicator: ItemListSectionHeaderActivityIndicator = .none, accessoryText: ItemListSectionHeaderAccessoryText? = nil, sectionId: ItemListSectionId) {
|
||||
self.presentationData = presentationData
|
||||
self.text = text
|
||||
self.multiline = multiline
|
||||
self.activityIndicator = activityIndicator
|
||||
@ -93,8 +93,6 @@ public class ItemListSectionHeaderItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.regular(14.0)
|
||||
|
||||
public class ItemListSectionHeaderItemNode: ListViewItemNode {
|
||||
private var item: ItemListSectionHeaderItem?
|
||||
|
||||
@ -135,16 +133,18 @@ public class ItemListSectionHeaderItemNode: ListViewItemNode {
|
||||
return { item, params, neighbors in
|
||||
let leftInset: CGFloat = 15.0 + params.leftInset
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.text, font: titleFont, textColor: item.theme.list.sectionHeaderTextColor), backgroundColor: nil, maximumNumberOfLines: item.multiline ? 0 : 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.leftInset - params.rightInset - 20.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseHeaderFontSize)
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.text, font: titleFont, textColor: item.presentationData.theme.list.sectionHeaderTextColor), backgroundColor: nil, maximumNumberOfLines: item.multiline ? 0 : 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.leftInset - params.rightInset - 20.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
var accessoryTextString: NSAttributedString?
|
||||
var accessoryIcon: UIImage?
|
||||
if let accessoryText = item.accessoryText {
|
||||
let color: UIColor
|
||||
switch accessoryText.color {
|
||||
case .generic:
|
||||
color = item.theme.list.sectionHeaderTextColor
|
||||
case .destructive:
|
||||
color = item.theme.list.freeTextErrorColor
|
||||
case .generic:
|
||||
color = item.presentationData.theme.list.sectionHeaderTextColor
|
||||
case .destructive:
|
||||
color = item.presentationData.theme.list.freeTextErrorColor
|
||||
}
|
||||
accessoryTextString = NSAttributedString(string: accessoryText.value, font: titleFont, textColor: color)
|
||||
accessoryIcon = accessoryText.icon
|
||||
@ -208,7 +208,7 @@ public class ItemListSectionHeaderItemNode: ListViewItemNode {
|
||||
if let currentActivityIndicator = strongSelf.activityIndicator {
|
||||
activityIndicator = currentActivityIndicator
|
||||
} else {
|
||||
activityIndicator = ActivityIndicator(type: .custom(item.theme.list.sectionHeaderTextColor, 18.0, 1.0, false))
|
||||
activityIndicator = ActivityIndicator(type: .custom(item.presentationData.theme.list.sectionHeaderTextColor, 18.0, 1.0, false))
|
||||
strongSelf.addSubnode(activityIndicator)
|
||||
strongSelf.activityIndicator = activityIndicator
|
||||
}
|
||||
@ -227,12 +227,12 @@ public class ItemListSectionHeaderItemNode: ListViewItemNode {
|
||||
|
||||
var activityIndicatorOrigin: CGPoint?
|
||||
switch item.activityIndicator {
|
||||
case .left:
|
||||
activityIndicatorOrigin = CGPoint(x: strongSelf.titleNode.frame.maxX + 6.0, y: 7.0 - UIScreenPixel)
|
||||
case .right:
|
||||
activityIndicatorOrigin = CGPoint(x: params.width - leftInset - 18.0, y: 7.0 - UIScreenPixel)
|
||||
default:
|
||||
break
|
||||
case .left:
|
||||
activityIndicatorOrigin = CGPoint(x: strongSelf.titleNode.frame.maxX + 6.0, y: 7.0 - UIScreenPixel)
|
||||
case .right:
|
||||
activityIndicatorOrigin = CGPoint(x: params.width - leftInset - 18.0, y: 7.0 - UIScreenPixel)
|
||||
default:
|
||||
break
|
||||
}
|
||||
if let activityIndicatorOrigin = activityIndicatorOrigin {
|
||||
strongSelf.activityIndicator?.frame = CGRect(origin: activityIndicatorOrigin, size: CGSize(width: 18.0, height: 18.0))
|
||||
|
@ -30,8 +30,7 @@ public enum ItemListSingleLineInputClearType: Equatable {
|
||||
}
|
||||
|
||||
public class ItemListSingleLineInputItem: ListViewItem, ItemListItem {
|
||||
let theme: PresentationTheme
|
||||
let strings: PresentationStrings
|
||||
let presentationData: ItemListPresentationData
|
||||
let title: NSAttributedString
|
||||
let text: String
|
||||
let placeholder: String
|
||||
@ -48,9 +47,8 @@ public class ItemListSingleLineInputItem: ListViewItem, ItemListItem {
|
||||
let updatedFocus: ((Bool) -> Void)?
|
||||
public let tag: ItemListItemTag?
|
||||
|
||||
public init(theme: PresentationTheme, strings: PresentationStrings, title: NSAttributedString, text: String, placeholder: String, type: ItemListSingleLineInputItemType = .regular(capitalization: true, autocorrection: true), returnKeyType: UIReturnKeyType = .`default`, spacing: CGFloat = 0.0, clearType: ItemListSingleLineInputClearType = .none, enabled: Bool = true, tag: ItemListItemTag? = nil, sectionId: ItemListSectionId, textUpdated: @escaping (String) -> Void, shouldUpdateText: @escaping (String) -> Bool = { _ in return true }, processPaste: ((String) -> String)? = nil, updatedFocus: ((Bool) -> Void)? = nil, action: @escaping () -> Void) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
public init(presentationData: ItemListPresentationData, title: NSAttributedString, text: String, placeholder: String, type: ItemListSingleLineInputItemType = .regular(capitalization: true, autocorrection: true), returnKeyType: UIReturnKeyType = .`default`, spacing: CGFloat = 0.0, clearType: ItemListSingleLineInputClearType = .none, enabled: Bool = true, tag: ItemListItemTag? = nil, sectionId: ItemListSectionId, textUpdated: @escaping (String) -> Void, shouldUpdateText: @escaping (String) -> Bool = { _ in return true }, processPaste: ((String) -> String)? = nil, updatedFocus: ((Bool) -> Void)? = nil, action: @escaping () -> Void) {
|
||||
self.presentationData = presentationData
|
||||
self.title = title
|
||||
self.text = text
|
||||
self.placeholder = placeholder
|
||||
@ -103,8 +101,6 @@ public class ItemListSingleLineInputItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.regular(17.0)
|
||||
|
||||
public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDelegate, ItemListItemNode, ItemListItemFocusableNode {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let topStripeNode: ASDisplayNode
|
||||
@ -168,14 +164,19 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
|
||||
override public func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
self.textNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(17.0)]
|
||||
self.textNode.textField.font = Font.regular(17.0)
|
||||
if let item = self.item {
|
||||
self.textNode.textField.textColor = item.theme.list.itemPrimaryTextColor
|
||||
self.textNode.textField.keyboardAppearance = item.theme.rootController.keyboardColor.keyboardAppearance
|
||||
self.textNode.textField.tintColor = item.theme.list.itemAccentColor
|
||||
self.textNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(item.presentationData.fontSize.itemListBaseFontSize)]
|
||||
self.textNode.textField.font = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
|
||||
self.textNode.textField.textColor = item.presentationData.theme.list.itemPrimaryTextColor
|
||||
self.textNode.textField.keyboardAppearance = item.presentationData.theme.rootController.keyboardColor.keyboardAppearance
|
||||
self.textNode.textField.tintColor = item.presentationData.theme.list.itemAccentColor
|
||||
self.textNode.textField.accessibilityHint = item.placeholder
|
||||
} else {
|
||||
self.textNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(17.0)]
|
||||
self.textNode.textField.font = Font.regular(17.0)
|
||||
}
|
||||
|
||||
self.textNode.clipsToBounds = true
|
||||
self.textNode.textField.delegate = self
|
||||
self.textNode.textField.addTarget(self, action: #selector(self.textFieldTextChanged(_:)), for: .editingChanged)
|
||||
@ -191,9 +192,14 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
|
||||
var updatedTheme: PresentationTheme?
|
||||
|
||||
var updatedClearIcon: UIImage?
|
||||
if currentItem?.theme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
updatedClearIcon = PresentationResourcesItemList.itemListClearInputIcon(item.theme)
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
updatedClearIcon = PresentationResourcesItemList.itemListClearInputIcon(item.presentationData.theme)
|
||||
}
|
||||
|
||||
var fontUpdated = false
|
||||
if currentItem?.presentationData.fontSize != item.presentationData.fontSize {
|
||||
fontUpdated = true
|
||||
}
|
||||
|
||||
let leftInset: CGFloat = 16.0 + params.leftInset
|
||||
@ -205,32 +211,36 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
|
||||
|
||||
let titleString = NSMutableAttributedString(attributedString: item.title)
|
||||
titleString.removeAttribute(NSAttributedString.Key.font, range: NSMakeRange(0, titleString.length))
|
||||
titleString.addAttributes([NSAttributedString.Key.font: Font.regular(17.0)], range: NSMakeRange(0, titleString.length))
|
||||
titleString.addAttributes([NSAttributedString.Key.font: Font.regular(item.presentationData.fontSize.itemListBaseFontSize)], range: NSMakeRange(0, titleString.length))
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: titleString, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - 32.0 - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let separatorHeight = UIScreenPixel
|
||||
|
||||
let contentSize = CGSize(width: params.width, height: 44.0)
|
||||
let contentSize = CGSize(width: params.width, height: titleLayout.size.height + 22.0)
|
||||
let insets = itemListNeighborsGroupedInsets(neighbors)
|
||||
|
||||
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
||||
let layoutSize = layout.size
|
||||
|
||||
let attributedPlaceholderText = NSAttributedString(string: item.placeholder, font: Font.regular(17.0), textColor: item.theme.list.itemPlaceholderTextColor)
|
||||
let attributedPlaceholderText = NSAttributedString(string: item.placeholder, font: Font.regular(item.presentationData.fontSize.itemListBaseFontSize), textColor: item.presentationData.theme.list.itemPlaceholderTextColor)
|
||||
|
||||
return (layout, { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.item = item
|
||||
|
||||
if let _ = updatedTheme {
|
||||
strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
strongSelf.topStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
|
||||
strongSelf.textNode.textField.textColor = item.theme.list.itemPrimaryTextColor
|
||||
strongSelf.textNode.textField.keyboardAppearance = item.theme.rootController.keyboardColor.keyboardAppearance
|
||||
strongSelf.textNode.textField.tintColor = item.theme.list.itemAccentColor
|
||||
strongSelf.textNode.textField.textColor = item.presentationData.theme.list.itemPrimaryTextColor
|
||||
strongSelf.textNode.textField.keyboardAppearance = item.presentationData.theme.rootController.keyboardColor.keyboardAppearance
|
||||
strongSelf.textNode.textField.tintColor = item.presentationData.theme.list.itemAccentColor
|
||||
}
|
||||
|
||||
if fontUpdated {
|
||||
strongSelf.textNode.textField.typingAttributes = [NSAttributedString.Key.font: Font.regular(item.presentationData.fontSize.itemListBaseFontSize)]
|
||||
}
|
||||
|
||||
let _ = titleApply()
|
||||
@ -242,40 +252,40 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
|
||||
let keyboardType: UIKeyboardType
|
||||
|
||||
switch item.type {
|
||||
case let .regular(capitalization, autocorrection):
|
||||
secureEntry = false
|
||||
capitalizationType = capitalization ? .sentences : .none
|
||||
autocorrectionType = autocorrection ? .default : .no
|
||||
keyboardType = .default
|
||||
case .email:
|
||||
secureEntry = false
|
||||
capitalizationType = .none
|
||||
autocorrectionType = .no
|
||||
keyboardType = .emailAddress
|
||||
case .password:
|
||||
secureEntry = true
|
||||
capitalizationType = .none
|
||||
autocorrectionType = .no
|
||||
keyboardType = .default
|
||||
case .number:
|
||||
secureEntry = false
|
||||
capitalizationType = .none
|
||||
autocorrectionType = .no
|
||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||
keyboardType = .asciiCapableNumberPad
|
||||
} else {
|
||||
keyboardType = .numberPad
|
||||
}
|
||||
case .decimal:
|
||||
secureEntry = false
|
||||
capitalizationType = .none
|
||||
autocorrectionType = .no
|
||||
keyboardType = .decimalPad
|
||||
case .username:
|
||||
secureEntry = false
|
||||
capitalizationType = .none
|
||||
autocorrectionType = .no
|
||||
keyboardType = .asciiCapable
|
||||
case let .regular(capitalization, autocorrection):
|
||||
secureEntry = false
|
||||
capitalizationType = capitalization ? .sentences : .none
|
||||
autocorrectionType = autocorrection ? .default : .no
|
||||
keyboardType = .default
|
||||
case .email:
|
||||
secureEntry = false
|
||||
capitalizationType = .none
|
||||
autocorrectionType = .no
|
||||
keyboardType = .emailAddress
|
||||
case .password:
|
||||
secureEntry = true
|
||||
capitalizationType = .none
|
||||
autocorrectionType = .no
|
||||
keyboardType = .default
|
||||
case .number:
|
||||
secureEntry = false
|
||||
capitalizationType = .none
|
||||
autocorrectionType = .no
|
||||
if #available(iOSApplicationExtension 10.0, iOS 10.0, *) {
|
||||
keyboardType = .asciiCapableNumberPad
|
||||
} else {
|
||||
keyboardType = .numberPad
|
||||
}
|
||||
case .decimal:
|
||||
secureEntry = false
|
||||
capitalizationType = .none
|
||||
autocorrectionType = .no
|
||||
keyboardType = .decimalPad
|
||||
case .username:
|
||||
secureEntry = false
|
||||
capitalizationType = .none
|
||||
autocorrectionType = .no
|
||||
keyboardType = .asciiCapable
|
||||
}
|
||||
|
||||
if strongSelf.textNode.textField.isSecureTextEntry != secureEntry {
|
||||
@ -302,7 +312,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
|
||||
strongSelf.textNode.textField.text = item.text
|
||||
}
|
||||
|
||||
strongSelf.textNode.frame = CGRect(origin: CGPoint(x: leftInset + titleLayout.size.width + item.spacing, y: floor((layout.contentSize.height - 40.0) / 2.0)), size: CGSize(width: max(1.0, params.width - (leftInset + rightInset + titleLayout.size.width + item.spacing)), height: 40.0))
|
||||
strongSelf.textNode.frame = CGRect(origin: CGPoint(x: leftInset + titleLayout.size.width + item.spacing, y: 1.0), size: CGSize(width: max(1.0, params.width - (leftInset + rightInset + titleLayout.size.width + item.spacing)), height: layout.contentSize.height - 2.0))
|
||||
|
||||
if let image = updatedClearIcon {
|
||||
strongSelf.clearIconNode.image = image
|
||||
@ -349,7 +359,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
|
||||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
@ -364,7 +374,7 @@ public class ItemListSingleLineInputItemNode: ListViewItemNode, UITextFieldDeleg
|
||||
strongSelf.textNode.isUserInteractionEnabled = item.enabled
|
||||
strongSelf.textNode.alpha = item.enabled ? 1.0 : 0.4
|
||||
|
||||
strongSelf.clearButtonNode.accessibilityLabel = item.strings.VoiceOver_Editing_ClearText
|
||||
strongSelf.clearButtonNode.accessibilityLabel = item.presentationData.strings.VoiceOver_Editing_ClearText
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -12,12 +12,13 @@ public enum ItemListSwitchItemNodeType {
|
||||
}
|
||||
|
||||
public class ItemListSwitchItem: ListViewItem, ItemListItem {
|
||||
let theme: PresentationTheme
|
||||
let presentationData: ItemListPresentationData
|
||||
let title: String
|
||||
let value: Bool
|
||||
let type: ItemListSwitchItemNodeType
|
||||
let enableInteractiveChanges: Bool
|
||||
let enabled: Bool
|
||||
let disableLeadingInset: Bool
|
||||
let maximumNumberOfLines: Int
|
||||
public let sectionId: ItemListSectionId
|
||||
let style: ItemListStyle
|
||||
@ -25,13 +26,14 @@ public class ItemListSwitchItem: ListViewItem, ItemListItem {
|
||||
let activatedWhileDisabled: () -> Void
|
||||
public let tag: ItemListItemTag?
|
||||
|
||||
public init(theme: PresentationTheme, title: String, value: Bool, type: ItemListSwitchItemNodeType = .regular, enableInteractiveChanges: Bool = true, enabled: Bool = true, maximumNumberOfLines: Int = 1, sectionId: ItemListSectionId, style: ItemListStyle, updated: @escaping (Bool) -> Void, activatedWhileDisabled: @escaping () -> Void = {}, tag: ItemListItemTag? = nil) {
|
||||
self.theme = theme
|
||||
public init(presentationData: ItemListPresentationData, title: String, value: Bool, type: ItemListSwitchItemNodeType = .regular, enableInteractiveChanges: Bool = true, enabled: Bool = true, disableLeadingInset: Bool = false, maximumNumberOfLines: Int = 1, sectionId: ItemListSectionId, style: ItemListStyle, updated: @escaping (Bool) -> Void, activatedWhileDisabled: @escaping () -> Void = {}, tag: ItemListItemTag? = nil) {
|
||||
self.presentationData = presentationData
|
||||
self.title = title
|
||||
self.value = value
|
||||
self.type = type
|
||||
self.enableInteractiveChanges = enableInteractiveChanges
|
||||
self.enabled = enabled
|
||||
self.disableLeadingInset = disableLeadingInset
|
||||
self.maximumNumberOfLines = maximumNumberOfLines
|
||||
self.sectionId = sectionId
|
||||
self.style = style
|
||||
@ -78,8 +80,6 @@ public class ItemListSwitchItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.regular(17.0)
|
||||
|
||||
private protocol ItemListSwitchNodeImpl {
|
||||
var frameColor: UIColor { get set }
|
||||
var contentColor: UIColor { get set }
|
||||
@ -131,7 +131,7 @@ public class ItemListSwitchItemNode: ListViewItemNode, ItemListItemNode {
|
||||
return self.item?.tag
|
||||
}
|
||||
|
||||
init(type: ItemListSwitchItemNodeType) {
|
||||
public init(type: ItemListSwitchItemNodeType) {
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
self.backgroundNode.isLayerBacked = true
|
||||
self.backgroundNode.backgroundColor = .white
|
||||
@ -195,31 +195,38 @@ public class ItemListSwitchItemNode: ListViewItemNode, ItemListItemNode {
|
||||
|
||||
return { item, params, neighbors in
|
||||
var contentSize: CGSize
|
||||
let insets: UIEdgeInsets
|
||||
var insets: UIEdgeInsets
|
||||
let separatorHeight = UIScreenPixel
|
||||
let itemBackgroundColor: UIColor
|
||||
let itemSeparatorColor: UIColor
|
||||
|
||||
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
|
||||
var updatedTheme: PresentationTheme?
|
||||
|
||||
if currentItem?.theme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
}
|
||||
|
||||
switch item.style {
|
||||
case .plain:
|
||||
itemBackgroundColor = item.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.theme.list.itemPlainSeparatorColor
|
||||
contentSize = CGSize(width: params.width, height: 44.0)
|
||||
insets = itemListNeighborsPlainInsets(neighbors)
|
||||
case .blocks:
|
||||
itemBackgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
itemSeparatorColor = item.theme.list.itemBlocksSeparatorColor
|
||||
contentSize = CGSize(width: params.width, height: 44.0)
|
||||
insets = itemListNeighborsGroupedInsets(neighbors)
|
||||
case .plain:
|
||||
itemBackgroundColor = item.presentationData.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
contentSize = CGSize(width: params.width, height: 44.0)
|
||||
insets = itemListNeighborsPlainInsets(neighbors)
|
||||
case .blocks:
|
||||
itemBackgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
contentSize = CGSize(width: params.width, height: 44.0)
|
||||
insets = itemListNeighborsGroupedInsets(neighbors)
|
||||
}
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: item.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: item.maximumNumberOfLines, truncationType: .end, constrainedSize: CGSize(width: params.width - params.leftInset - params.rightInset - 80.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
if item.disableLeadingInset {
|
||||
insets.top = 0.0
|
||||
insets.bottom = 0.0
|
||||
}
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: item.maximumNumberOfLines, truncationType: .end, constrainedSize: CGSize(width: params.width - params.leftInset - params.rightInset - 80.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
contentSize.height = max(contentSize.height, titleLayout.size.height + 22.0)
|
||||
|
||||
@ -280,13 +287,13 @@ public class ItemListSwitchItemNode: ListViewItemNode, ItemListItemNode {
|
||||
strongSelf.bottomStripeNode.backgroundColor = itemSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = itemBackgroundColor
|
||||
|
||||
strongSelf.switchNode.frameColor = item.theme.list.itemSwitchColors.frameColor
|
||||
strongSelf.switchNode.contentColor = item.theme.list.itemSwitchColors.contentColor
|
||||
strongSelf.switchNode.handleColor = item.theme.list.itemSwitchColors.handleColor
|
||||
strongSelf.switchNode.positiveContentColor = item.theme.list.itemSwitchColors.positiveColor
|
||||
strongSelf.switchNode.negativeContentColor = item.theme.list.itemSwitchColors.negativeColor
|
||||
strongSelf.switchNode.frameColor = item.presentationData.theme.list.itemSwitchColors.frameColor
|
||||
strongSelf.switchNode.contentColor = item.presentationData.theme.list.itemSwitchColors.contentColor
|
||||
strongSelf.switchNode.handleColor = item.presentationData.theme.list.itemSwitchColors.handleColor
|
||||
strongSelf.switchNode.positiveContentColor = item.presentationData.theme.list.itemSwitchColors.positiveColor
|
||||
strongSelf.switchNode.negativeContentColor = item.presentationData.theme.list.itemSwitchColors.negativeColor
|
||||
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.theme.list.itemHighlightedBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
}
|
||||
|
||||
let _ = titleApply()
|
||||
@ -342,7 +349,7 @@ public class ItemListSwitchItemNode: ListViewItemNode, ItemListItemNode {
|
||||
strongSelf.bottomStripeNode.isHidden = hasCorners
|
||||
}
|
||||
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.presentationData.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil
|
||||
|
||||
strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight)))
|
||||
strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0)
|
||||
@ -357,7 +364,7 @@ public class ItemListSwitchItemNode: ListViewItemNode, ItemListItemNode {
|
||||
}
|
||||
let switchSize = switchView.bounds.size
|
||||
|
||||
strongSelf.switchNode.frame = CGRect(origin: CGPoint(x: params.width - params.rightInset - switchSize.width - 15.0, y: 6.0), size: switchSize)
|
||||
strongSelf.switchNode.frame = CGRect(origin: CGPoint(x: params.width - params.rightInset - switchSize.width - 15.0, y: floor((contentSize.height - switchSize.height) / 2.0)), size: switchSize)
|
||||
strongSelf.switchGestureNode.frame = strongSelf.switchNode.frame
|
||||
if switchView.isOn != item.value {
|
||||
switchView.setOn(item.value, animated: animated)
|
||||
|
@ -17,15 +17,15 @@ public enum ItemListTextItemLinkAction {
|
||||
}
|
||||
|
||||
public class ItemListTextItem: ListViewItem, ItemListItem {
|
||||
let theme: PresentationTheme
|
||||
let presentationData: ItemListPresentationData
|
||||
let text: ItemListTextItemText
|
||||
public let sectionId: ItemListSectionId
|
||||
let linkAction: ((ItemListTextItemLinkAction) -> Void)?
|
||||
let style: ItemListStyle
|
||||
public let isAlwaysPlain: Bool = true
|
||||
|
||||
public init(theme: PresentationTheme, text: ItemListTextItemText, sectionId: ItemListSectionId, linkAction: ((ItemListTextItemLinkAction) -> Void)? = nil, style: ItemListStyle = .blocks) {
|
||||
self.theme = theme
|
||||
public init(presentationData: ItemListPresentationData, text: ItemListTextItemText, sectionId: ItemListSectionId, linkAction: ((ItemListTextItemLinkAction) -> Void)? = nil, style: ItemListStyle = .blocks) {
|
||||
self.presentationData = presentationData
|
||||
self.text = text
|
||||
self.sectionId = sectionId
|
||||
self.linkAction = linkAction
|
||||
@ -69,9 +69,6 @@ public class ItemListTextItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.regular(14.0)
|
||||
private let titleBoldFont = Font.semibold(14.0)
|
||||
|
||||
public class ItemListTextItemNode: ListViewItemNode {
|
||||
private let titleNode: TextNode
|
||||
private let activateArea: AccessibilityAreaNode
|
||||
@ -110,14 +107,17 @@ public class ItemListTextItemNode: ListViewItemNode {
|
||||
let leftInset: CGFloat = 15.0 + params.leftInset
|
||||
let verticalInset: CGFloat = 7.0
|
||||
|
||||
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseHeaderFontSize)
|
||||
let titleBoldFont = Font.semibold(item.presentationData.fontSize.itemListBaseHeaderFontSize)
|
||||
|
||||
let attributedText: NSAttributedString
|
||||
switch item.text {
|
||||
case let .plain(text):
|
||||
attributedText = NSAttributedString(string: text, font: titleFont, textColor: item.theme.list.freeTextColor)
|
||||
case let .markdown(text):
|
||||
attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: titleFont, textColor: item.theme.list.freeTextColor), bold: MarkdownAttributeSet(font: titleBoldFont, textColor: item.theme.list.freeTextColor), link: MarkdownAttributeSet(font: titleFont, textColor: item.theme.list.itemAccentColor), linkAttribute: { contents in
|
||||
return (TelegramTextAttributes.URL, contents)
|
||||
}))
|
||||
case let .plain(text):
|
||||
attributedText = NSAttributedString(string: text, font: titleFont, textColor: item.presentationData.theme.list.freeTextColor)
|
||||
case let .markdown(text):
|
||||
attributedText = parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: titleFont, textColor: item.presentationData.theme.list.freeTextColor), bold: MarkdownAttributeSet(font: titleBoldFont, textColor: item.presentationData.theme.list.freeTextColor), link: MarkdownAttributeSet(font: titleFont, textColor: item.presentationData.theme.list.itemAccentColor), linkAttribute: { contents in
|
||||
return (TelegramTextAttributes.URL, contents)
|
||||
}))
|
||||
}
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - leftInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
|
@ -14,7 +14,7 @@ public enum ItemListTextWithLabelItemTextColor {
|
||||
}
|
||||
|
||||
public final class ItemListTextWithLabelItem: ListViewItem, ItemListItem {
|
||||
let theme: PresentationTheme
|
||||
let presentationData: ItemListPresentationData
|
||||
public let label: String
|
||||
public let text: String
|
||||
let style: ItemListStyle
|
||||
@ -30,8 +30,8 @@ public final class ItemListTextWithLabelItem: ListViewItem, ItemListItem {
|
||||
|
||||
public let tag: Any?
|
||||
|
||||
public init(theme: PresentationTheme, label: String, text: String, style: ItemListStyle = .plain, labelColor: ItemListTextWithLabelItemTextColor = .primary, textColor: ItemListTextWithLabelItemTextColor = .primary, enabledEntityTypes: EnabledEntityTypes, multiline: Bool, selected: Bool? = nil, sectionId: ItemListSectionId, action: (() -> Void)?, longTapAction: (() -> Void)? = nil, linkItemAction: ((TextLinkItemActionType, TextLinkItem) -> Void)? = nil, tag: Any? = nil) {
|
||||
self.theme = theme
|
||||
public init(presentationData: ItemListPresentationData, label: String, text: String, style: ItemListStyle = .plain, labelColor: ItemListTextWithLabelItemTextColor = .primary, textColor: ItemListTextWithLabelItemTextColor = .primary, enabledEntityTypes: EnabledEntityTypes, multiline: Bool, selected: Bool? = nil, sectionId: ItemListSectionId, action: (() -> Void)?, longTapAction: (() -> Void)? = nil, linkItemAction: ((TextLinkItemActionType, TextLinkItem) -> Void)? = nil, tag: Any? = nil) {
|
||||
self.presentationData = presentationData
|
||||
self.label = label
|
||||
self.text = text
|
||||
self.style = style
|
||||
@ -90,13 +90,6 @@ public final class ItemListTextWithLabelItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let labelFont = Font.regular(14.0)
|
||||
private let textFont = Font.regular(17.0)
|
||||
private let textBoldFont = Font.medium(17.0)
|
||||
private let textItalicFont = Font.italic(17.0)
|
||||
private let textBoldItalicFont = Font.semiboldItalic(17.0)
|
||||
private let textFixedFont = Font.regular(17.0)
|
||||
|
||||
public class ItemListTextWithLabelItemNode: ListViewItemNode {
|
||||
let labelNode: TextNode
|
||||
let textNode: TextNode
|
||||
@ -173,8 +166,8 @@ public class ItemListTextWithLabelItemNode: ListViewItemNode {
|
||||
|
||||
return { item, params, neighbors in
|
||||
var updatedTheme: PresentationTheme?
|
||||
if currentItem?.theme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
}
|
||||
|
||||
let insets = itemListNeighborsPlainInsets(neighbors)
|
||||
@ -182,39 +175,46 @@ public class ItemListTextWithLabelItemNode: ListViewItemNode {
|
||||
let rightInset: CGFloat = 8.0 + params.rightInset
|
||||
let separatorHeight = UIScreenPixel
|
||||
|
||||
let labelFont = Font.regular(item.presentationData.fontSize.itemListBaseLabelFontSize)
|
||||
let textFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
let textBoldFont = Font.medium(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
let textItalicFont = Font.italic(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
let textBoldItalicFont = Font.semiboldItalic(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
let textFixedFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
|
||||
var leftOffset: CGFloat = 0.0
|
||||
var selectionNodeWidthAndApply: (CGFloat, (CGSize, Bool) -> ItemListSelectableControlNode)?
|
||||
if let selected = item.selected {
|
||||
let (selectionWidth, selectionApply) = selectionNodeLayout(item.theme.list.itemCheckColors.strokeColor, item.theme.list.itemCheckColors.fillColor, item.theme.list.itemCheckColors.foregroundColor, selected, false)
|
||||
let (selectionWidth, selectionApply) = selectionNodeLayout(item.presentationData.theme.list.itemCheckColors.strokeColor, item.presentationData.theme.list.itemCheckColors.fillColor, item.presentationData.theme.list.itemCheckColors.foregroundColor, selected, false)
|
||||
selectionNodeWidthAndApply = (selectionWidth, selectionApply)
|
||||
leftOffset += selectionWidth - 8.0
|
||||
}
|
||||
|
||||
let labelColor: UIColor
|
||||
switch item.labelColor {
|
||||
case .primary:
|
||||
labelColor = item.theme.list.itemPrimaryTextColor
|
||||
case .accent:
|
||||
labelColor = item.theme.list.itemAccentColor
|
||||
case .highlighted:
|
||||
labelColor = item.theme.list.itemHighlightedColor
|
||||
case .primary:
|
||||
labelColor = item.presentationData.theme.list.itemPrimaryTextColor
|
||||
case .accent:
|
||||
labelColor = item.presentationData.theme.list.itemAccentColor
|
||||
case .highlighted:
|
||||
labelColor = item.presentationData.theme.list.itemHighlightedColor
|
||||
}
|
||||
let (labelLayout, labelApply) = makeLabelLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.label, font: labelFont, textColor: labelColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftOffset - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let entities = generateTextEntities(item.text, enabledTypes: item.enabledEntityTypes)
|
||||
let baseColor: UIColor
|
||||
switch item.textColor {
|
||||
case .primary:
|
||||
baseColor = item.theme.list.itemPrimaryTextColor
|
||||
case .accent:
|
||||
baseColor = item.theme.list.itemAccentColor
|
||||
case .highlighted:
|
||||
baseColor = item.theme.list.itemHighlightedColor
|
||||
case .primary:
|
||||
baseColor = item.presentationData.theme.list.itemPrimaryTextColor
|
||||
case .accent:
|
||||
baseColor = item.presentationData.theme.list.itemAccentColor
|
||||
case .highlighted:
|
||||
baseColor = item.presentationData.theme.list.itemHighlightedColor
|
||||
}
|
||||
let string = stringWithAppliedEntities(item.text, entities: entities, baseColor: baseColor, linkColor: item.theme.list.itemAccentColor, baseFont: textFont, linkFont: textFont, boldFont: textBoldFont, italicFont: textItalicFont, boldItalicFont: textBoldItalicFont, fixedFont: textFixedFont, blockQuoteFont: textFont)
|
||||
let string = stringWithAppliedEntities(item.text, entities: entities, baseColor: baseColor, linkColor: item.presentationData.theme.list.itemAccentColor, baseFont: textFont, linkFont: textFont, boldFont: textBoldFont, italicFont: textItalicFont, boldItalicFont: textBoldItalicFont, fixedFont: textFixedFont, blockQuoteFont: textFont)
|
||||
|
||||
let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: string, backgroundColor: nil, maximumNumberOfLines: item.multiline ? 0 : 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftOffset - leftInset - rightInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let contentSize = CGSize(width: params.width, height: textLayout.size.height + 39.0)
|
||||
let contentSize = CGSize(width: params.width, height: textLayout.size.height + labelLayout.size.height + 22.0)
|
||||
let nodeLayout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
||||
return (nodeLayout, { [weak self] animation in
|
||||
if let strongSelf = self {
|
||||
@ -233,15 +233,15 @@ public class ItemListTextWithLabelItemNode: ListViewItemNode {
|
||||
if let _ = updatedTheme {
|
||||
switch item.style {
|
||||
case .plain:
|
||||
strongSelf.topStripeNode.backgroundColor = item.theme.list.itemPlainSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemPlainSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.theme.list.plainBackgroundColor
|
||||
strongSelf.topStripeNode.backgroundColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.plainBackgroundColor
|
||||
case .blocks:
|
||||
strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
strongSelf.topStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
}
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.theme.list.itemHighlightedBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
}
|
||||
|
||||
let _ = labelApply()
|
||||
@ -267,8 +267,9 @@ public class ItemListTextWithLabelItemNode: ListViewItemNode {
|
||||
})
|
||||
}
|
||||
|
||||
strongSelf.labelNode.frame = CGRect(origin: CGPoint(x: leftOffset + leftInset, y: 11.0), size: labelLayout.size)
|
||||
strongSelf.textNode.frame = CGRect(origin: CGPoint(x: leftOffset + leftInset, y: 31.0), size: textLayout.size)
|
||||
let labelFrame = CGRect(origin: CGPoint(x: leftOffset + leftInset, y: 11.0), size: labelLayout.size)
|
||||
strongSelf.labelNode.frame = labelFrame
|
||||
strongSelf.textNode.frame = CGRect(origin: CGPoint(x: leftOffset + leftInset, y: labelFrame.maxY + 3.0), size: textLayout.size)
|
||||
|
||||
let leftInset: CGFloat
|
||||
switch item.style {
|
||||
@ -436,7 +437,7 @@ public class ItemListTextWithLabelItemNode: ListViewItemNode {
|
||||
if let current = self.linkHighlightingNode {
|
||||
linkHighlightingNode = current
|
||||
} else {
|
||||
linkHighlightingNode = LinkHighlightingNode(color: item.theme.list.itemAccentColor.withAlphaComponent(0.5))
|
||||
linkHighlightingNode = LinkHighlightingNode(color: item.presentationData.theme.list.itemAccentColor.withAlphaComponent(0.5))
|
||||
self.linkHighlightingNode = linkHighlightingNode
|
||||
self.insertSubnode(linkHighlightingNode, belowSubnode: self.textNode)
|
||||
}
|
||||
|
@ -217,21 +217,21 @@ private final class LanguageSuggestionAlertContentNode: AlertContentNode {
|
||||
return self.isUserInteractionEnabled
|
||||
}
|
||||
|
||||
init(theme: PresentationTheme, strings: LanguageSuggestionControllerStrings, englishStrings: LanguageSuggestionControllerStrings, suggestedLocalization: LocalizationInfo, openSelection: @escaping () -> Void, applyLocalization: @escaping (String, () -> Void) -> Void, dismiss: @escaping () -> Void) {
|
||||
init(presentationData: PresentationData, strings: LanguageSuggestionControllerStrings, englishStrings: LanguageSuggestionControllerStrings, suggestedLocalization: LocalizationInfo, openSelection: @escaping () -> Void, applyLocalization: @escaping (String, () -> Void) -> Void, dismiss: @escaping () -> Void) {
|
||||
let selectedLocalization = ValuePromise(suggestedLocalization.languageCode, ignoreRepeated: true)
|
||||
|
||||
self.titleNode = ASTextNode()
|
||||
self.titleNode.attributedText = NSAttributedString(string: strings.ChooseLanguage, font: Font.bold(17.0), textColor: theme.actionSheet.primaryTextColor, paragraphAlignment: .center)
|
||||
self.titleNode.attributedText = NSAttributedString(string: strings.ChooseLanguage, font: Font.bold(presentationData.fontSize.baseDisplaySize), textColor: presentationData.theme.actionSheet.primaryTextColor, paragraphAlignment: .center)
|
||||
self.titleNode.maximumNumberOfLines = 2
|
||||
|
||||
self.subtitleNode = ASTextNode()
|
||||
self.subtitleNode.attributedText = NSAttributedString(string: englishStrings.ChooseLanguage, font: Font.regular(14.0), textColor: theme.actionSheet.secondaryTextColor, paragraphAlignment: .center)
|
||||
self.subtitleNode.attributedText = NSAttributedString(string: englishStrings.ChooseLanguage, font: Font.regular(floor(presentationData.fontSize.baseDisplaySize * 14.0 / 17.0)), textColor: presentationData.theme.actionSheet.secondaryTextColor, paragraphAlignment: .center)
|
||||
self.subtitleNode.maximumNumberOfLines = 2
|
||||
|
||||
self.titleSeparatorNode = ASDisplayNode()
|
||||
self.titleSeparatorNode.backgroundColor = theme.actionSheet.opaqueItemSeparatorColor
|
||||
self.titleSeparatorNode.backgroundColor = presentationData.theme.actionSheet.opaqueItemSeparatorColor
|
||||
|
||||
self.activityIndicator = ActivityIndicator(type: .custom(theme.actionSheet.controlAccentColor, 22.0, 1.0, false))
|
||||
self.activityIndicator = ActivityIndicator(type: .custom(presentationData.theme.actionSheet.controlAccentColor, 22.0, 1.0, false))
|
||||
self.activityIndicator.isHidden = true
|
||||
|
||||
var items: [LanguageSuggestionItem] = []
|
||||
@ -250,7 +250,7 @@ private final class LanguageSuggestionAlertContentNode: AlertContentNode {
|
||||
applyImpl?()
|
||||
}))
|
||||
|
||||
self.nodes = items.map { LanguageSuggestionItemNode(theme: theme, item: $0) }
|
||||
self.nodes = items.map { LanguageSuggestionItemNode(theme: presentationData.theme, item: $0) }
|
||||
|
||||
super.init()
|
||||
|
||||
@ -334,7 +334,8 @@ public func languageSuggestionController(context: AccountContext, suggestedLocal
|
||||
return nil
|
||||
}
|
||||
|
||||
let theme = context.sharedContext.currentPresentationData.with { $0 }.theme
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let theme = context.sharedContext.presentationData
|
||||
let strings = LanguageSuggestionControllerStrings(localization: suggestedLocalization)
|
||||
guard let mainPath = getAppBundle().path(forResource: "en", ofType: "lproj") else {
|
||||
return nil
|
||||
@ -344,7 +345,7 @@ public func languageSuggestionController(context: AccountContext, suggestedLocal
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
var dismissImpl: ((Bool) -> Void)?
|
||||
let contentNode = LanguageSuggestionAlertContentNode(theme: theme, strings: strings, englishStrings: englishStrings, suggestedLocalization: localization, openSelection: {
|
||||
let contentNode = LanguageSuggestionAlertContentNode(presentationData: presentationData, strings: strings, englishStrings: englishStrings, suggestedLocalization: localization, openSelection: {
|
||||
dismissImpl?(true)
|
||||
openSelection()
|
||||
}, applyLocalization: { languageCode, startActivity in
|
||||
@ -360,7 +361,7 @@ public func languageSuggestionController(context: AccountContext, suggestedLocal
|
||||
}, dismiss: {
|
||||
dismissImpl?(true)
|
||||
})
|
||||
let controller = AlertController(theme: AlertControllerTheme(presentationTheme: theme), contentNode: contentNode)
|
||||
let controller = AlertController(theme: AlertControllerTheme(presentationData: presentationData), contentNode: contentNode)
|
||||
dismissImpl = { [weak controller] animated in
|
||||
if animated {
|
||||
controller?.dismissAnimated()
|
||||
|
@ -279,8 +279,10 @@ const CGFloat TGPhotoEditorSliderViewInternalMargin = 7.0f;
|
||||
|
||||
- (void)setTrackColor:(UIColor *)trackColor
|
||||
{
|
||||
_trackColor = trackColor;
|
||||
[self setNeedsDisplay];
|
||||
if (_trackColor == nil || ![_trackColor isEqual:trackColor]) {
|
||||
_trackColor = trackColor;
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
}
|
||||
|
||||
- (UIColor *)startColor
|
||||
|
@ -8,6 +8,7 @@ import SyncCore
|
||||
import SwiftSignalKit
|
||||
import MergeLists
|
||||
import ItemListPeerItem
|
||||
import ItemListUI
|
||||
|
||||
public final class MessageReactionListController: ViewController {
|
||||
private let context: AccountContext
|
||||
@ -93,7 +94,7 @@ private struct MessageReactionListEntry: Comparable, Identifiable {
|
||||
}
|
||||
|
||||
func item(context: AccountContext, presentationData: PresentationData) -> ListViewItem {
|
||||
return ItemListPeerItem(theme: presentationData.theme, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, account: context.account, peer: self.item.peer, height: .peerList, nameStyle: .distinctBold, presence: nil, text: .none, label: .text(self.item.reaction, .custom(Font.regular(19.0))), editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: false, sectionId: 0, action: {
|
||||
return ItemListPeerItem(presentationData: ItemListPresentationData(presentationData), dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, account: context.account, peer: self.item.peer, height: .peerList, nameStyle: .distinctBold, presence: nil, text: .none, label: .text(self.item.reaction, .custom(Font.regular(19.0))), editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: false, sectionId: 0, action: {
|
||||
|
||||
}, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, noInsets: true, tag: nil)
|
||||
}
|
||||
|
@ -125,23 +125,23 @@ private enum NotificationSoundSelectionEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! NotificationSoundSelectionArguments
|
||||
switch self {
|
||||
case let.modernHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .classicHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .none(_, theme, text, selected):
|
||||
return ItemListCheckboxItem(theme: theme, title: text, style: .left, checked: selected, zeroSeparatorInsets: true, sectionId: self.section, action: {
|
||||
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: true, sectionId: self.section, action: {
|
||||
arguments.selectSound(.none)
|
||||
})
|
||||
case let .default(_, theme, text, selected):
|
||||
return ItemListCheckboxItem(theme: theme, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.selectSound(.default)
|
||||
})
|
||||
case let .sound(_, _, theme, text, sound, selected):
|
||||
return ItemListCheckboxItem(theme: theme, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.selectSound(sound)
|
||||
})
|
||||
}
|
||||
@ -294,8 +294,8 @@ public func notificationSoundSelectionController(context: AccountContext, isModa
|
||||
arguments.complete()
|
||||
})
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.Notifications_TextTone), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(entries: notificationsAndSoundsEntries(presentationData: presentationData, defaultSound: defaultSound, state: state), style: .blocks)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.Notifications_TextTone), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: notificationsAndSoundsEntries(presentationData: presentationData, defaultSound: defaultSound, state: state), style: .blocks)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -68,18 +68,18 @@ private enum ResetPasswordEntry: ItemListNodeEntry, Equatable {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! ResetPasswordControllerArguments
|
||||
switch self {
|
||||
case let .code(theme, strings, text, value):
|
||||
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: text, textColor: theme.list.itemPrimaryTextColor), text: value, placeholder: "", type: .number, spacing: 10.0, tag: ResetPasswordEntryTag.code, sectionId: self.section, textUpdated: { updatedText in
|
||||
return ItemListSingleLineInputItem(presentationData: presentationData, title: NSAttributedString(string: text, textColor: theme.list.itemPrimaryTextColor), text: value, placeholder: "", type: .number, spacing: 10.0, tag: ResetPasswordEntryTag.code, sectionId: self.section, textUpdated: { updatedText in
|
||||
arguments.updateCodeText(updatedText)
|
||||
}, action: {
|
||||
})
|
||||
case let .codeInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .helpInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .markdown(text), sectionId: self.section, linkAction: { action in
|
||||
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section, linkAction: { action in
|
||||
if case .tap = action {
|
||||
arguments.openHelp()
|
||||
}
|
||||
@ -193,8 +193,8 @@ public func resetPasswordController(context: AccountContext, emailPattern: Strin
|
||||
})
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.TwoStepAuth_RecoveryTitle), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: resetPasswordControllerEntries(presentationData: presentationData, state: state, pattern: emailPattern), style: .blocks, focusItemTag: ResetPasswordEntryTag.code, emptyStateItem: nil, animateChanges: false)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.TwoStepAuth_RecoveryTitle), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: resetPasswordControllerEntries(presentationData: presentationData, state: state, pattern: emailPattern), style: .blocks, focusItemTag: ResetPasswordEntryTag.code, emptyStateItem: nil, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ public final class TwoFactorDataInputScreen: ViewController {
|
||||
return
|
||||
}
|
||||
if values[0] != values[1] {
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: nil, text: strongSelf.presentationData.strings.TwoStepAuth_SetupPasswordConfirmFailed, actions: [
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: nil, text: strongSelf.presentationData.strings.TwoStepAuth_SetupPasswordConfirmFailed, actions: [
|
||||
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})
|
||||
]), in: .window(.root))
|
||||
return
|
||||
@ -289,7 +289,7 @@ public final class TwoFactorDataInputScreen: ViewController {
|
||||
}
|
||||
switch strongSelf.mode {
|
||||
case let .emailAddress(password, hint):
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationData.theme), title: strongSelf.presentationData.strings.TwoFactorSetup_Email_SkipConfirmationTitle, text: strongSelf.presentationData.strings.TwoFactorSetup_Email_SkipConfirmationText, actions: [
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: strongSelf.presentationData.strings.TwoFactorSetup_Email_SkipConfirmationTitle, text: strongSelf.presentationData.strings.TwoFactorSetup_Email_SkipConfirmationText, actions: [
|
||||
TextAlertAction(type: .destructiveAction, title: strongSelf.presentationData.strings.TwoFactorSetup_Email_SkipConfirmationSkip, action: {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
|
@ -365,11 +365,11 @@ private enum ChannelAdminEntry: ItemListNodeEntry {
|
||||
}
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! ChannelAdminControllerArguments
|
||||
switch self {
|
||||
case let .info(theme, strings, dateTimeFormat, peer, presence):
|
||||
return ItemListAvatarAndNameInfoItem(account: arguments.account, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, mode: .generic, peer: peer, presence: presence, cachedData: nil, state: ItemListAvatarAndNameInfoItemState(), sectionId: self.section, style: .blocks(withTopInset: true, withExtendedBottomInset: false), editingNameUpdated: { _ in
|
||||
return ItemListAvatarAndNameInfoItem(account: arguments.account, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .generic, peer: peer, presence: presence, cachedData: nil, state: ItemListAvatarAndNameInfoItemState(), sectionId: self.section, style: .blocks(withTopInset: true, withExtendedBottomInset: false), editingNameUpdated: { _ in
|
||||
}, avatarTapped: {
|
||||
})
|
||||
case let .rankTitle(theme, text, count, limit):
|
||||
@ -377,9 +377,9 @@ private enum ChannelAdminEntry: ItemListNodeEntry {
|
||||
if let count = count {
|
||||
accessoryText = ItemListSectionHeaderAccessoryText(value: "\(limit - count)", color: count > limit ? .destructive : .generic)
|
||||
}
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, accessoryText: accessoryText, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, accessoryText: accessoryText, sectionId: self.section)
|
||||
case let .rank(theme, strings, placeholder, text, enabled):
|
||||
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: "", textColor: .black), text: text, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: true), spacing: 0.0, clearType: enabled ? .always : .none, enabled: enabled, tag: ChannelAdminEntryTag.rank, sectionId: self.section, textUpdated: { updatedText in
|
||||
return ItemListSingleLineInputItem(presentationData: presentationData, title: NSAttributedString(string: "", textColor: .black), text: text, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: true), spacing: 0.0, clearType: enabled ? .always : .none, enabled: enabled, tag: ChannelAdminEntryTag.rank, sectionId: self.section, textUpdated: { updatedText in
|
||||
arguments.updateRank(text, updatedText)
|
||||
}, shouldUpdateText: { text in
|
||||
if text.containsEmoji {
|
||||
@ -393,23 +393,23 @@ private enum ChannelAdminEntry: ItemListNodeEntry {
|
||||
arguments.dismissInput()
|
||||
})
|
||||
case let .rankInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .rightsTitle(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .rightItem(theme, _, text, right, flags, value, enabled):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, type: .icon, enabled: enabled, sectionId: self.section, style: .blocks, updated: { _ in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, type: .icon, enabled: enabled, sectionId: self.section, style: .blocks, updated: { _ in
|
||||
arguments.toggleRight(right, flags)
|
||||
}, activatedWhileDisabled: {
|
||||
arguments.toggleRightWhileDisabled(right, flags)
|
||||
})
|
||||
case let .addAdminsInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .transfer(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .center, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .center, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.transferOwnership()
|
||||
}, tag: nil)
|
||||
case let .dismiss(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .destructive, alignment: .center, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .destructive, alignment: .center, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.dismissAdmin()
|
||||
}, tag: nil)
|
||||
}
|
||||
@ -829,7 +829,7 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
||||
text = presentationData.strings.Channel_EditAdmin_CannotEdit
|
||||
}
|
||||
|
||||
presentControllerImpl?(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
|
||||
presentControllerImpl?(standardTextAlertController(theme: AlertControllerTheme(presentationData: presentationData), title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
|
||||
})
|
||||
}, transferOwnership: {
|
||||
let _ = (context.account.postbox.transaction { transaction -> (peer: Peer?, member: Peer?) in
|
||||
@ -1169,9 +1169,9 @@ public func channelAdminController(context: AccountContext, peerId: PeerId, admi
|
||||
})
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.Channel_Management_LabelEditor), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.Channel_Management_LabelEditor), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
|
||||
let listState = ItemListNodeState(entries: channelAdminControllerEntries(presentationData: presentationData, state: state, accountPeerId: context.account.peerId, channelView: channelView, adminView: adminView, initialParticipant: initialParticipant, canEdit: canEdit), style: .blocks, focusItemTag: focusItemTag, ensureVisibleItemTag: nil, emptyStateItem: nil, animateChanges: true)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelAdminControllerEntries(presentationData: presentationData, state: state, accountPeerId: context.account.peerId, channelView: channelView, adminView: adminView, initialParticipant: initialParticipant, canEdit: canEdit), style: .blocks, focusItemTag: focusItemTag, ensureVisibleItemTag: nil, emptyStateItem: nil, animateChanges: true)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -201,15 +201,15 @@ private enum ChannelAdminsEntry: ItemListNodeEntry {
|
||||
}
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! ChannelAdminsControllerArguments
|
||||
switch self {
|
||||
case let .recentActions(theme, text):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: "", sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openRecentActions()
|
||||
})
|
||||
case let .adminsHeader(theme, title):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: title, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: title, sectionId: self.section)
|
||||
case let .adminPeerItem(theme, strings, dateTimeFormat, nameDisplayOrder, _, _, participant, editing, enabled, hasAction):
|
||||
let peerText: String
|
||||
var action: (() -> Void)?
|
||||
@ -236,17 +236,17 @@ private enum ChannelAdminsEntry: ItemListNodeEntry {
|
||||
arguments.openAdmin(participant.participant)
|
||||
}
|
||||
}
|
||||
return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: participant.peer, presence: nil, text: .text(peerText), label: .none, editing: editing, switchValue: nil, enabled: enabled, selectable: true, sectionId: self.section, action: action, setPeerIdWithRevealedOptions: { previousId, id in
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: participant.peer, presence: nil, text: .text(peerText), label: .none, editing: editing, switchValue: nil, enabled: enabled, selectable: true, sectionId: self.section, action: action, setPeerIdWithRevealedOptions: { previousId, id in
|
||||
arguments.setPeerIdWithRevealedOptions(previousId, id)
|
||||
}, removePeer: { peerId in
|
||||
arguments.removeAdmin(peerId)
|
||||
})
|
||||
case let .addAdmin(theme, text, editing):
|
||||
return ItemListPeerActionItem(theme: theme, icon: PresentationResourcesItemList.addPersonIcon(theme), title: text, sectionId: self.section, editing: editing, action: {
|
||||
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.addPersonIcon(theme), title: text, sectionId: self.section, editing: editing, action: {
|
||||
arguments.addAdmin()
|
||||
})
|
||||
case let .adminsInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -757,8 +757,8 @@ public func channelAdminsController(context: AccountContext, peerId: PeerId, loa
|
||||
emptyStateItem = ItemListLoadingIndicatorEmptyStateItem(theme: presentationData.theme)
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(isGroup ? presentationData.strings.ChatAdmins_Title : presentationData.strings.Channel_Management_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, secondaryRightNavigationButton: secondaryRightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
let listState = ItemListNodeState(entries: channelAdminsControllerEntries(presentationData: presentationData, accountPeerId: context.account.peerId, view: view, state: state, participants: admins), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, animateChanges: previous != nil && admins != nil && previous!.count >= admins!.count)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(isGroup ? presentationData.strings.ChatAdmins_Title : presentationData.strings.Channel_Management_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, secondaryRightNavigationButton: secondaryRightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelAdminsControllerEntries(presentationData: presentationData, accountPeerId: context.account.peerId, view: view, state: state, participants: admins), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, animateChanges: previous != nil && admins != nil && previous!.count >= admins!.count)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
} |> afterDisposed {
|
||||
|
@ -221,29 +221,29 @@ private enum ChannelBannedMemberEntry: ItemListNodeEntry {
|
||||
}
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! ChannelBannedMemberControllerArguments
|
||||
switch self {
|
||||
case let .info(theme, strings, dateTimeFormat, peer, presence):
|
||||
return ItemListAvatarAndNameInfoItem(account: arguments.account, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, mode: .generic, peer: peer, presence: presence, cachedData: nil, state: ItemListAvatarAndNameInfoItemState(), sectionId: self.section, style: .blocks(withTopInset: true, withExtendedBottomInset: false), editingNameUpdated: { _ in
|
||||
return ItemListAvatarAndNameInfoItem(account: arguments.account, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .generic, peer: peer, presence: presence, cachedData: nil, state: ItemListAvatarAndNameInfoItemState(), sectionId: self.section, style: .blocks(withTopInset: true, withExtendedBottomInset: false), editingNameUpdated: { _ in
|
||||
}, avatarTapped: {
|
||||
})
|
||||
case let .rightsHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .rightItem(theme, _, text, right, value, enabled):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, type: .icon, enableInteractiveChanges: enabled, enabled: enabled, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, type: .icon, enableInteractiveChanges: enabled, enabled: enabled, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.toggleRight(right, value)
|
||||
}, activatedWhileDisabled: {
|
||||
arguments.toggleRightWhileDisabled(right)
|
||||
})
|
||||
case let .timeout(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openTimeout()
|
||||
})
|
||||
case let .exceptionInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .delete(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .destructive, alignment: .center, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .destructive, alignment: .center, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.delete()
|
||||
})
|
||||
}
|
||||
@ -731,9 +731,9 @@ public func channelBannedMemberController(context: AccountContext, peerId: PeerI
|
||||
title = presentationData.strings.GroupPermission_NewTitle
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
|
||||
let listState = ItemListNodeState(entries: channelBannedMemberControllerEntries(presentationData: presentationData, state: state, accountPeerId: context.account.peerId, channelView: channelView, memberView: memberView, initialParticipant: initialParticipant, initialBannedBy: initialBannedByPeer), style: .blocks, emptyStateItem: nil, animateChanges: true)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelBannedMemberControllerEntries(presentationData: presentationData, state: state, accountPeerId: context.account.peerId, channelView: channelView, memberView: memberView, initialParticipant: initialParticipant, initialBannedBy: initialBannedByPeer), style: .blocks, emptyStateItem: nil, animateChanges: true)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -148,17 +148,17 @@ private enum ChannelBlacklistEntry: ItemListNodeEntry {
|
||||
}
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! ChannelBlacklistControllerArguments
|
||||
switch self {
|
||||
case let .add(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.addPeer()
|
||||
})
|
||||
case let .addInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .bannedHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .peerItem(theme, strings, dateTimeFormat, nameDisplayOrder, _, participant, editing, enabled):
|
||||
var text: ItemListPeerItemText = .none
|
||||
switch participant.participant {
|
||||
@ -169,7 +169,7 @@ private enum ChannelBlacklistEntry: ItemListNodeEntry {
|
||||
default:
|
||||
break
|
||||
}
|
||||
return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: participant.peer, presence: nil, text: text, label: .none, editing: editing, switchValue: nil, enabled: enabled, selectable: true, sectionId: self.section, action: {
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: participant.peer, presence: nil, text: text, label: .none, editing: editing, switchValue: nil, enabled: enabled, selectable: true, sectionId: self.section, action: {
|
||||
arguments.openPeer(participant)
|
||||
}, setPeerIdWithRevealedOptions: { previousId, id in
|
||||
arguments.setPeerIdWithRevealedOptions(previousId, id)
|
||||
@ -498,8 +498,8 @@ public func channelBlacklistController(context: AccountContext, peerId: PeerId)
|
||||
})
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.GroupRemoved_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, secondaryRightNavigationButton: secondaryRightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
let listState = ItemListNodeState(entries: channelBlacklistControllerEntries(presentationData: presentationData, view: view, state: state, participants: participants), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, animateChanges: previous != nil && participants != nil && previous!.count >= participants!.count)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.GroupRemoved_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, secondaryRightNavigationButton: secondaryRightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelBlacklistControllerEntries(presentationData: presentationData, view: view, state: state, participants: participants), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, animateChanges: previous != nil && participants != nil && previous!.count >= participants!.count)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ import MergeLists
|
||||
import AccountContext
|
||||
import SearchUI
|
||||
import ContactsPeerItem
|
||||
import ItemListUI
|
||||
|
||||
private enum ChannelDiscussionGroupSearchContent: Equatable {
|
||||
case peer(Peer)
|
||||
@ -68,10 +69,10 @@ private final class ChannelDiscussionGroupSearchEntry: Comparable, Identifiable
|
||||
return lhs.index < rhs.index
|
||||
}
|
||||
|
||||
func item(account: Account, theme: PresentationTheme, strings: PresentationStrings, interaction: ChannelDiscussionGroupSearchInteraction) -> ListViewItem {
|
||||
func item(account: Account, presentationData: PresentationData, interaction: ChannelDiscussionGroupSearchInteraction) -> ListViewItem {
|
||||
switch self.content {
|
||||
case let .peer(peer):
|
||||
return ContactsPeerItem(theme: theme, strings: strings, sortOrder: .firstLast, displayOrder: .firstLast, account: account, peerMode: .peer, peer: .peer(peer: peer, chatPeer: peer), status: .none, enabled: true, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: nil, action: { _ in
|
||||
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: .firstLast, displayOrder: .firstLast, account: account, peerMode: .peer, peer: .peer(peer: peer, chatPeer: peer), status: .none, enabled: true, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: nil, action: { _ in
|
||||
interaction.peerSelected(peer)
|
||||
})
|
||||
}
|
||||
@ -85,12 +86,12 @@ struct ChannelDiscussionGroupSearchContainerTransition {
|
||||
let isSearching: Bool
|
||||
}
|
||||
|
||||
private func channelDiscussionGroupSearchContainerPreparedRecentTransition(from fromEntries: [ChannelDiscussionGroupSearchEntry], to toEntries: [ChannelDiscussionGroupSearchEntry], isSearching: Bool, account: Account, theme: PresentationTheme, strings: PresentationStrings, interaction: ChannelDiscussionGroupSearchInteraction) -> ChannelDiscussionGroupSearchContainerTransition {
|
||||
private func channelDiscussionGroupSearchContainerPreparedRecentTransition(from fromEntries: [ChannelDiscussionGroupSearchEntry], to toEntries: [ChannelDiscussionGroupSearchEntry], isSearching: Bool, account: Account, presentationData: PresentationData, interaction: ChannelDiscussionGroupSearchInteraction) -> ChannelDiscussionGroupSearchContainerTransition {
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
|
||||
|
||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, theme: theme, strings: strings, interaction: interaction), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, theme: theme, strings: strings, interaction: interaction), directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, presentationData: presentationData, interaction: interaction), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, presentationData: presentationData, interaction: interaction), directionHint: nil) }
|
||||
|
||||
return ChannelDiscussionGroupSearchContainerTransition(deletions: deletions, insertions: insertions, updates: updates, isSearching: isSearching)
|
||||
}
|
||||
@ -114,14 +115,14 @@ final class ChannelDiscussionGroupSearchContainerNode: SearchDisplayControllerCo
|
||||
private var presentationData: PresentationData
|
||||
private var presentationDataDisposable: Disposable?
|
||||
|
||||
private let themeAndStringsPromise: Promise<(PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, PresentationDateTimeFormat)>
|
||||
private let presentationDataPromise: Promise<PresentationData>
|
||||
|
||||
init(context: AccountContext, peers: [Peer], openPeer: @escaping (Peer) -> Void) {
|
||||
self.context = context
|
||||
self.openPeer = openPeer
|
||||
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.themeAndStringsPromise = Promise((self.presentationData.theme, self.presentationData.strings, self.presentationData.nameSortOrder, self.presentationData.nameDisplayOrder, self.presentationData.dateTimeFormat))
|
||||
self.presentationDataPromise = Promise(self.presentationData)
|
||||
|
||||
self.dimNode = ASDisplayNode()
|
||||
self.listNode = ListView()
|
||||
@ -186,12 +187,12 @@ final class ChannelDiscussionGroupSearchContainerNode: SearchDisplayControllerCo
|
||||
|
||||
let previousSearchItems = Atomic<[ChannelDiscussionGroupSearchEntry]?>(value: nil)
|
||||
|
||||
self.searchDisposable.set((combineLatest(foundItems, self.themeAndStringsPromise.get())
|
||||
|> deliverOnMainQueue).start(next: { [weak self] entries, themeAndStrings in
|
||||
self.searchDisposable.set((combineLatest(foundItems, self.presentationDataPromise.get())
|
||||
|> deliverOnMainQueue).start(next: { [weak self] entries, presentationData in
|
||||
if let strongSelf = self {
|
||||
let previousEntries = previousSearchItems.swap(entries)
|
||||
let firstTime = previousEntries == nil
|
||||
let transition = channelDiscussionGroupSearchContainerPreparedRecentTransition(from: previousEntries ?? [], to: entries ?? [], isSearching: entries != nil, account: context.account, theme: themeAndStrings.0, strings: themeAndStrings.1, interaction: interaction)
|
||||
let transition = channelDiscussionGroupSearchContainerPreparedRecentTransition(from: previousEntries ?? [], to: entries ?? [], isSearching: entries != nil, account: context.account, presentationData: presentationData, interaction: interaction)
|
||||
strongSelf.enqueueTransition(transition, firstTime: firstTime)
|
||||
}
|
||||
}))
|
||||
|
@ -128,13 +128,13 @@ private enum ChannelDiscussionGroupSetupControllerEntry: ItemListNodeEntry {
|
||||
return lhs.sortIndex < rhs.sortIndex
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! ChannelDiscussionGroupSetupControllerArguments
|
||||
switch self {
|
||||
case let .header(theme, strings, title, isGroup, label):
|
||||
return ChannelDiscussionGroupSetupHeaderItem(theme: theme, strings: strings, title: title, isGroup: isGroup, label: label, sectionId: self.section)
|
||||
case let .create(theme, text):
|
||||
return ItemListPeerActionItem(theme: theme, icon: PresentationResourcesItemList.plusIconImage(theme), title: text, sectionId: self.section, editing: false, action: {
|
||||
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.plusIconImage(theme), title: text, sectionId: self.section, editing: false, action: {
|
||||
arguments.createGroup()
|
||||
})
|
||||
case let .group(_, theme, strings, peer, nameOrder):
|
||||
@ -144,13 +144,13 @@ private enum ChannelDiscussionGroupSetupControllerEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
text = strings.Channel_DiscussionGroup_PrivateGroup
|
||||
}
|
||||
return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: PresentationDateTimeFormat(timeFormat: .regular, dateFormat: .monthFirst, dateSeparator: ".", decimalSeparator: ".", groupingSeparator: "."), nameDisplayOrder: nameOrder, account: arguments.account, peer: peer, aliasHandling: .standard, nameStyle: .plain, presence: nil, text: .text(text), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: {
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: PresentationDateTimeFormat(timeFormat: .regular, dateFormat: .monthFirst, dateSeparator: ".", decimalSeparator: ".", groupingSeparator: "."), nameDisplayOrder: nameOrder, account: arguments.account, peer: peer, aliasHandling: .standard, nameStyle: .plain, presence: nil, text: .text(text), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: {
|
||||
arguments.selectGroup(peer.id)
|
||||
}, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in })
|
||||
case let .groupsInfo(theme, title):
|
||||
return ItemListTextItem(theme: theme, text: .plain(title), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(title), sectionId: self.section)
|
||||
case let .unlink(theme, title):
|
||||
return ItemListActionItem(theme: theme, title: title, kind: .destructive, alignment: .center, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: title, kind: .destructive, alignment: .center, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.unlinkGroup()
|
||||
})
|
||||
}
|
||||
@ -591,8 +591,8 @@ public func channelDiscussionGroupSetupController(context: AccountContext, peerI
|
||||
}
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: channelDiscussionGroupSetupControllerEntries(presentationData: presentationData, view: view, groups: groups), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, crossfadeState: crossfade, animateChanges: false)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelDiscussionGroupSetupControllerEntries(presentationData: presentationData, view: view, groups: groups), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, crossfadeState: crossfade, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -322,85 +322,85 @@ private enum ChannelInfoEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! ChannelInfoControllerArguments
|
||||
switch self {
|
||||
case let .info(theme, strings, dateTimeFormat, peer, cachedData, state, updatingAvatar):
|
||||
return ItemListAvatarAndNameInfoItem(account: arguments.account, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, mode: .generic, peer: peer, presence: nil, cachedData: cachedData, state: state, sectionId: self.section, style: .plain, editingNameUpdated: { editingName in
|
||||
return ItemListAvatarAndNameInfoItem(account: arguments.account, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .generic, peer: peer, presence: nil, cachedData: cachedData, state: state, sectionId: self.section, style: .plain, editingNameUpdated: { editingName in
|
||||
arguments.updateEditingName(editingName)
|
||||
}, avatarTapped: {
|
||||
arguments.tapAvatarAction()
|
||||
}, context: arguments.avatarAndNameInfoContext, updatingImage: updatingAvatar)
|
||||
case let .about(theme, text, value):
|
||||
return ItemListTextWithLabelItem(theme: theme, label: text, text: foldMultipleLineBreaks(value), enabledEntityTypes: [.url, .mention, .hashtag], multiline: true, sectionId: self.section, action: nil, longTapAction: {
|
||||
return ItemListTextWithLabelItem(presentationData: presentationData, label: text, text: foldMultipleLineBreaks(value), enabledEntityTypes: [.url, .mention, .hashtag], multiline: true, sectionId: self.section, action: nil, longTapAction: {
|
||||
arguments.displayContextMenu(ChannelInfoEntryTag.about, value)
|
||||
}, linkItemAction: { action, itemLink in
|
||||
arguments.aboutLinkAction(action, itemLink)
|
||||
}, tag: ChannelInfoEntryTag.about)
|
||||
case let .addressName(theme, text, value):
|
||||
return ItemListTextWithLabelItem(theme: theme, label: text, text: "https://t.me/\(value)", textColor: .accent, enabledEntityTypes: [], multiline: false, sectionId: self.section, action: {
|
||||
return ItemListTextWithLabelItem(presentationData: presentationData, label: text, text: "https://t.me/\(value)", textColor: .accent, enabledEntityTypes: [], multiline: false, sectionId: self.section, action: {
|
||||
arguments.displayAddressNameContextMenu("https://t.me/\(value)")
|
||||
}, longTapAction: {
|
||||
arguments.displayContextMenu(ChannelInfoEntryTag.link, "https://t.me/\(value)")
|
||||
}, tag: ChannelInfoEntryTag.link)
|
||||
case let .channelPhotoSetup(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
arguments.changeProfilePhoto()
|
||||
})
|
||||
case let .channelTypeSetup(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .plain, action: {
|
||||
arguments.openChannelTypeSetup()
|
||||
})
|
||||
case let .discussionGroupSetup(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .plain, action: {
|
||||
arguments.openDiscussionGroupSetup()
|
||||
})
|
||||
case let .discussionGroupSetupInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .channelDescriptionSetup(theme, placeholder, value):
|
||||
return ItemListMultilineInputItem(theme: theme, text: value, placeholder: placeholder, maxLength: ItemListMultilineInputItemTextLimit(value: 255, display: true), sectionId: self.section, style: .plain, textUpdated: { updatedText in
|
||||
return ItemListMultilineInputItem(presentationData: presentationData, text: value, placeholder: placeholder, maxLength: ItemListMultilineInputItemTextLimit(value: 255, display: true), sectionId: self.section, style: .plain, textUpdated: { updatedText in
|
||||
arguments.updateEditingDescriptionText(updatedText)
|
||||
})
|
||||
case let .admins(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .plain, action: {
|
||||
arguments.openAdmins()
|
||||
})
|
||||
case let .members(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .plain, action: {
|
||||
arguments.openMembers()
|
||||
})
|
||||
case let .banned(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .plain, action: {
|
||||
arguments.openBanned()
|
||||
})
|
||||
case let .signMessages(theme, text, value):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, sectionId: self.section, style: .plain, updated: { updated in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, sectionId: self.section, style: .plain, updated: { updated in
|
||||
arguments.toggleSignatures(updated)
|
||||
})
|
||||
case let .signInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section, style: .plain)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section, style: .plain)
|
||||
case let .sharedMedia(theme, text):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: self.section, style: .plain, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: "", sectionId: self.section, style: .plain, action: {
|
||||
arguments.openSharedMedia()
|
||||
})
|
||||
case let .stats(theme, text):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: self.section, style: .plain, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: "", sectionId: self.section, style: .plain, action: {
|
||||
arguments.openStats()
|
||||
})
|
||||
case let .notifications(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .plain, action: {
|
||||
arguments.changeNotificationMuteSettings()
|
||||
})
|
||||
case let .report(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
arguments.reportChannel()
|
||||
})
|
||||
case let .leave(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .destructive, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .destructive, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
arguments.leaveChannel()
|
||||
})
|
||||
case let .deleteChannel(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .destructive, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .destructive, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
arguments.deleteChannel()
|
||||
})
|
||||
}
|
||||
@ -1086,8 +1086,8 @@ public func channelInfoController(context: AccountContext, peerId: PeerId) -> Vi
|
||||
crossfadeState = true
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.UserInfo_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(entries: channelInfoEntries(account: context.account, presentationData: presentationData, view: view, globalNotificationSettings: globalNotificationSettings, state: state), style: .plain, crossfadeState: crossfadeState, animateChanges: false)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.UserInfo_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelInfoEntries(account: context.account, presentationData: presentationData, view: view, globalNotificationSettings: globalNotificationSettings, state: state), style: .plain, crossfadeState: crossfadeState, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
} |> afterDisposed {
|
||||
|
@ -178,19 +178,19 @@ private enum ChannelMembersEntry: ItemListNodeEntry {
|
||||
}
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! ChannelMembersControllerArguments
|
||||
switch self {
|
||||
case let .addMember(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.addMember()
|
||||
})
|
||||
case let .inviteLink(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.inviteViaLink()
|
||||
})
|
||||
case let .addMemberInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .peerItem(_, theme, strings, dateTimeFormat, nameDisplayOrder, participant, editing, enabled):
|
||||
let text: ItemListPeerItemText
|
||||
if let user = participant.peer as? TelegramUser, let _ = user.botInfo {
|
||||
@ -198,7 +198,7 @@ private enum ChannelMembersEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
text = .presence
|
||||
}
|
||||
return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: participant.peer, presence: participant.presences[participant.peer.id], text: text, label: .none, editing: editing, switchValue: nil, enabled: enabled, selectable: true, sectionId: self.section, action: {
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: participant.peer, presence: participant.presences[participant.peer.id], text: text, label: .none, editing: editing, switchValue: nil, enabled: enabled, selectable: true, sectionId: self.section, action: {
|
||||
arguments.openPeer(participant.peer)
|
||||
}, setPeerIdWithRevealedOptions: { previousId, id in
|
||||
arguments.setPeerIdWithRevealedOptions(previousId, id)
|
||||
@ -520,8 +520,8 @@ public func channelMembersController(context: AccountContext, peerId: PeerId) ->
|
||||
let previous = previousPeers
|
||||
previousPeers = peers
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.Channel_Subscribers_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, secondaryRightNavigationButton: secondaryRightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
let listState = ItemListNodeState(entries: ChannelMembersControllerEntries(context: context, presentationData: presentationData, view: view, state: state, participants: peers), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, animateChanges: previous != nil && peers != nil && previous!.count >= peers!.count)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.Channel_Subscribers_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, secondaryRightNavigationButton: secondaryRightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: ChannelMembersControllerEntries(context: context, presentationData: presentationData, view: view, state: state, participants: peers), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, animateChanges: previous != nil && peers != nil && previous!.count >= peers!.count)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import SearchUI
|
||||
import ItemListPeerItem
|
||||
import ContactsPeerItem
|
||||
import ChatListSearchItemHeader
|
||||
import ItemListUI
|
||||
|
||||
enum ChannelMembersSearchMode {
|
||||
case searchMembers
|
||||
@ -138,10 +139,10 @@ private final class ChannelMembersSearchEntry: Comparable, Identifiable {
|
||||
return lhs.index < rhs.index
|
||||
}
|
||||
|
||||
func item(account: Account, theme: PresentationTheme, strings: PresentationStrings, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, interaction: ChannelMembersSearchContainerInteraction) -> ListViewItem {
|
||||
func item(account: Account, presentationData: PresentationData, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, interaction: ChannelMembersSearchContainerInteraction) -> ListViewItem {
|
||||
switch self.content {
|
||||
case let .peer(peer):
|
||||
return ContactsPeerItem(theme: theme, strings: strings, sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: account, peerMode: .peer, peer: .peer(peer: peer, chatPeer: peer), status: .none, enabled: true, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: self.section.chatListHeaderType.flatMap({ ChatListSearchItemHeader(type: $0, theme: theme, strings: strings, actionTitle: nil, action: nil) }), action: { _ in
|
||||
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: account, peerMode: .peer, peer: .peer(peer: peer, chatPeer: peer), status: .none, enabled: true, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: self.section.chatListHeaderType.flatMap({ ChatListSearchItemHeader(type: $0, theme: presentationData.theme, strings: presentationData.strings, actionTitle: nil, action: nil) }), action: { _ in
|
||||
interaction.peerSelected(peer, nil)
|
||||
})
|
||||
case let .participant(participant, label, revealActions, revealed, enabled):
|
||||
@ -175,7 +176,7 @@ private final class ChannelMembersSearchEntry: Comparable, Identifiable {
|
||||
actionIcon = .add
|
||||
}
|
||||
|
||||
return ContactsPeerItem(theme: theme, strings: strings, sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: account, peerMode: .peer, peer: .peer(peer: participant.peer, chatPeer: participant.peer), status: status, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: revealed), options: options, actionIcon: actionIcon, index: nil, header: self.section.chatListHeaderType.flatMap({ ChatListSearchItemHeader(type: $0, theme: theme, strings: strings, actionTitle: nil, action: nil) }), action: { _ in
|
||||
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: account, peerMode: .peer, peer: .peer(peer: participant.peer, chatPeer: participant.peer), status: status, enabled: enabled, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: revealed), options: options, actionIcon: actionIcon, index: nil, header: self.section.chatListHeaderType.flatMap({ ChatListSearchItemHeader(type: $0, theme: presentationData.theme, strings: presentationData.strings, actionTitle: nil, action: nil) }), action: { _ in
|
||||
interaction.peerSelected(participant.peer, participant)
|
||||
}, setPeerIdWithRevealedOptions: { peerId, fromPeerId in
|
||||
interaction.setPeerIdWithRevealedOptions(RevealedPeerId(peerId: participant.peer.id, section: self.section), fromPeerId.flatMap({ RevealedPeerId(peerId: $0, section: self.section) }))
|
||||
@ -259,12 +260,12 @@ final class GroupMembersSearchContext {
|
||||
}
|
||||
}
|
||||
|
||||
private func channelMembersSearchContainerPreparedRecentTransition(from fromEntries: [ChannelMembersSearchEntry], to toEntries: [ChannelMembersSearchEntry], isSearching: Bool, account: Account, theme: PresentationTheme, strings: PresentationStrings, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, interaction: ChannelMembersSearchContainerInteraction) -> ChannelMembersSearchContainerTransition {
|
||||
private func channelMembersSearchContainerPreparedRecentTransition(from fromEntries: [ChannelMembersSearchEntry], to toEntries: [ChannelMembersSearchEntry], isSearching: Bool, account: Account, presentationData: PresentationData, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, interaction: ChannelMembersSearchContainerInteraction) -> ChannelMembersSearchContainerTransition {
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries)
|
||||
|
||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, theme: theme, strings: strings, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, interaction: interaction), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, theme: theme, strings: strings, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, interaction: interaction), directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, presentationData: presentationData, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, interaction: interaction), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, presentationData: presentationData, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, interaction: interaction), directionHint: nil) }
|
||||
|
||||
return ChannelMembersSearchContainerTransition(deletions: deletions, insertions: insertions, updates: updates, isSearching: isSearching)
|
||||
}
|
||||
@ -295,7 +296,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
|
||||
private let removeMemberDisposable = MetaDisposable()
|
||||
|
||||
private let themeAndStringsPromise: Promise<(PresentationTheme, PresentationStrings, PresentationPersonNameOrder, PresentationPersonNameOrder, PresentationDateTimeFormat)>
|
||||
private let presentationDataPromise: Promise<PresentationData>
|
||||
|
||||
init(context: AccountContext, peerId: PeerId, mode: ChannelMembersSearchMode, filters: [ChannelMembersSearchFilter], searchContext: GroupMembersSearchContext?, openPeer: @escaping (Peer, RenderedChannelParticipant?) -> Void, updateActivity: @escaping (Bool) -> Void, pushController: @escaping (ViewController) -> Void) {
|
||||
self.context = context
|
||||
@ -303,7 +304,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
self.mode = mode
|
||||
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.themeAndStringsPromise = Promise((self.presentationData.theme, self.presentationData.strings, self.presentationData.nameSortOrder, self.presentationData.nameDisplayOrder, self.presentationData.dateTimeFormat))
|
||||
self.presentationDataPromise = Promise(self.presentationData)
|
||||
|
||||
self.emptyQueryListNode = ListView()
|
||||
self.listNode = ListView()
|
||||
@ -433,12 +434,12 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
removeMemberDisposable.set(signal.start())
|
||||
})
|
||||
|
||||
let themeAndStringsPromise = self.themeAndStringsPromise
|
||||
let presentationDataPromise = self.presentationDataPromise
|
||||
|
||||
let emptyQueryItems: Signal<[ChannelMembersSearchEntry]?, NoError>
|
||||
if let searchContext = searchContext {
|
||||
emptyQueryItems = combineLatest(queue: .mainQueue(), statePromise.get(), searchContext.state.get(), context.account.postbox.peerView(id: peerId) |> take(1), themeAndStringsPromise.get())
|
||||
|> map { state, searchState, peerView, themeAndStrings -> [ChannelMembersSearchEntry]? in
|
||||
emptyQueryItems = combineLatest(queue: .mainQueue(), statePromise.get(), searchContext.state.get(), context.account.postbox.peerView(id: peerId) |> take(1), presentationDataPromise.get())
|
||||
|> map { state, searchState, peerView, presentationData -> [ChannelMembersSearchEntry]? in
|
||||
if let channel = peerView.peers[peerId] as? TelegramChannel {
|
||||
var entries: [ChannelMembersSearchEntry] = []
|
||||
|
||||
@ -483,7 +484,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
if case .searchMembers = mode {
|
||||
switch participant.participant {
|
||||
case .creator:
|
||||
label = themeAndStrings.1.Channel_Management_LabelOwner
|
||||
label = presentationData.strings.Channel_Management_LabelOwner
|
||||
default:
|
||||
break
|
||||
}
|
||||
@ -496,15 +497,15 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
var peerActions: [ParticipantRevealAction] = []
|
||||
if case .searchMembers = mode {
|
||||
if canPromote {
|
||||
peerActions.append(ParticipantRevealAction(type: .neutral, title: themeAndStrings.1.GroupInfo_ActionPromote, action: .promote))
|
||||
peerActions.append(ParticipantRevealAction(type: .neutral, title: presentationData.strings.GroupInfo_ActionPromote, action: .promote))
|
||||
}
|
||||
if canRestrict {
|
||||
peerActions.append(ParticipantRevealAction(type: .warning, title: themeAndStrings.1.GroupInfo_ActionRestrict, action: .restrict))
|
||||
peerActions.append(ParticipantRevealAction(type: .destructive, title: themeAndStrings.1.Common_Delete, action: .remove))
|
||||
peerActions.append(ParticipantRevealAction(type: .warning, title: presentationData.strings.GroupInfo_ActionRestrict, action: .restrict))
|
||||
peerActions.append(ParticipantRevealAction(type: .destructive, title: presentationData.strings.Common_Delete, action: .remove))
|
||||
}
|
||||
}
|
||||
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .participant(participant: participant, label: label, revealActions: peerActions, revealed: state.revealedPeerId == RevealedPeerId(peerId: participant.peer.id, section: section), enabled: enabled), section: section, dateTimeFormat: themeAndStrings.4))
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .participant(participant: participant, label: label, revealActions: peerActions, revealed: state.revealedPeerId == RevealedPeerId(peerId: participant.peer.id, section: section), enabled: enabled), section: section, dateTimeFormat: presentationData.dateTimeFormat))
|
||||
index += 1
|
||||
}
|
||||
|
||||
@ -617,8 +618,8 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
foundRemotePeers = .single(([], []))
|
||||
}
|
||||
|
||||
return combineLatest(foundGroupMembers, foundMembers, foundContacts, foundRemotePeers, themeAndStringsPromise.get(), statePromise.get())
|
||||
|> map { foundGroupMembers, foundMembers, foundContacts, foundRemotePeers, themeAndStrings, state -> [ChannelMembersSearchEntry]? in
|
||||
return combineLatest(foundGroupMembers, foundMembers, foundContacts, foundRemotePeers, presentationDataPromise.get(), statePromise.get())
|
||||
|> map { foundGroupMembers, foundMembers, foundContacts, foundRemotePeers, presentationData, state -> [ChannelMembersSearchEntry]? in
|
||||
var entries: [ChannelMembersSearchEntry] = []
|
||||
|
||||
var existingPeerIds = Set<PeerId>()
|
||||
@ -693,16 +694,16 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
var enabled = true
|
||||
if case .banAndPromoteActions = mode {
|
||||
if case .creator = participant.participant {
|
||||
label = themeAndStrings.1.Channel_Management_LabelOwner
|
||||
label = presentationData.strings.Channel_Management_LabelOwner
|
||||
enabled = false
|
||||
}
|
||||
} else if case .searchMembers = mode {
|
||||
switch participant.participant {
|
||||
case .creator:
|
||||
label = themeAndStrings.1.Channel_Management_LabelOwner
|
||||
label = presentationData.strings.Channel_Management_LabelOwner
|
||||
case let .member(member):
|
||||
if member.adminInfo != nil {
|
||||
label = themeAndStrings.1.Channel_Management_LabelEditor
|
||||
label = presentationData.strings.Channel_Management_LabelEditor
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -714,15 +715,15 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
var peerActions: [ParticipantRevealAction] = []
|
||||
if case .searchMembers = mode {
|
||||
if canPromote {
|
||||
peerActions.append(ParticipantRevealAction(type: .neutral, title: themeAndStrings.1.GroupInfo_ActionPromote, action: .promote))
|
||||
peerActions.append(ParticipantRevealAction(type: .neutral, title: presentationData.strings.GroupInfo_ActionPromote, action: .promote))
|
||||
}
|
||||
if canRestrict {
|
||||
peerActions.append(ParticipantRevealAction(type: .warning, title: themeAndStrings.1.GroupInfo_ActionRestrict, action: .restrict))
|
||||
peerActions.append(ParticipantRevealAction(type: .destructive, title: themeAndStrings.1.Common_Delete, action: .remove))
|
||||
peerActions.append(ParticipantRevealAction(type: .warning, title: presentationData.strings.GroupInfo_ActionRestrict, action: .restrict))
|
||||
peerActions.append(ParticipantRevealAction(type: .destructive, title: presentationData.strings.Common_Delete, action: .remove))
|
||||
}
|
||||
} else if case .searchAdmins = mode {
|
||||
if canRestrict {
|
||||
peerActions.append(ParticipantRevealAction(type: .destructive, title: themeAndStrings.1.Common_Delete, action: .remove))
|
||||
peerActions.append(ParticipantRevealAction(type: .destructive, title: presentationData.strings.Common_Delete, action: .remove))
|
||||
}
|
||||
}
|
||||
|
||||
@ -730,14 +731,14 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
case .searchAdmins:
|
||||
switch participant.participant {
|
||||
case .creator:
|
||||
label = themeAndStrings.1.Channel_Management_LabelOwner
|
||||
label = presentationData.strings.Channel_Management_LabelOwner
|
||||
case let .member(_, _, adminInfo, _, _):
|
||||
if let adminInfo = adminInfo {
|
||||
if let peer = participant.peers[adminInfo.promotedBy] {
|
||||
if peer.id == participant.peer.id {
|
||||
label = themeAndStrings.1.Channel_Management_LabelAdministrator
|
||||
label = presentationData.strings.Channel_Management_LabelAdministrator
|
||||
} else {
|
||||
label = themeAndStrings.1.Channel_Management_PromotedBy(peer.displayTitle(strings: themeAndStrings.1, displayOrder: themeAndStrings.3)).0
|
||||
label = presentationData.strings.Channel_Management_PromotedBy(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -752,7 +753,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
if !exceptionsString.isEmpty {
|
||||
exceptionsString.append(", ")
|
||||
}
|
||||
exceptionsString.append(compactStringForGroupPermission(strings: themeAndStrings.1, right: rights))
|
||||
exceptionsString.append(compactStringForGroupPermission(strings: presentationData.strings, right: rights))
|
||||
}
|
||||
}
|
||||
label = exceptionsString
|
||||
@ -764,7 +765,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
switch participant.participant {
|
||||
case let .member(_, _, _, banInfo, _):
|
||||
if let banInfo = banInfo, let peer = participant.peers[banInfo.restrictedBy] {
|
||||
label = themeAndStrings.1.Channel_Management_RemovedBy(peer.displayTitle(strings: themeAndStrings.1, displayOrder: themeAndStrings.3)).0
|
||||
label = presentationData.strings.Channel_Management_RemovedBy(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0
|
||||
}
|
||||
default:
|
||||
break
|
||||
@ -772,7 +773,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
default:
|
||||
break
|
||||
}
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .participant(participant: participant, label: label, revealActions: peerActions, revealed: state.revealedPeerId == RevealedPeerId(peerId: participant.peer.id, section: section), enabled: enabled), section: section, dateTimeFormat: themeAndStrings.4))
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .participant(participant: participant, label: label, revealActions: peerActions, revealed: state.revealedPeerId == RevealedPeerId(peerId: participant.peer.id, section: section), enabled: enabled), section: section, dateTimeFormat: presentationData.dateTimeFormat))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
@ -796,12 +797,12 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
var enabled = true
|
||||
if case .banAndPromoteActions = mode {
|
||||
if case .creator = participant.participant {
|
||||
label = themeAndStrings.1.Channel_Management_LabelOwner
|
||||
label = presentationData.strings.Channel_Management_LabelOwner
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .participant(participant: participant, label: label, revealActions: [], revealed: false, enabled: enabled), section: section, dateTimeFormat: themeAndStrings.4, addIcon: addIcon))
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .participant(participant: participant, label: label, revealActions: [], revealed: false, enabled: enabled), section: section, dateTimeFormat: presentationData.dateTimeFormat, addIcon: addIcon))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
@ -809,7 +810,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
for peer in foundContacts.0 {
|
||||
if !existingPeerIds.contains(peer.id) {
|
||||
existingPeerIds.insert(peer.id)
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .peer(peer), section: .contacts, dateTimeFormat: themeAndStrings.4))
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .peer(peer), section: .contacts, dateTimeFormat: presentationData.dateTimeFormat))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
@ -818,7 +819,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
let peer = foundPeer.peer
|
||||
if !existingPeerIds.contains(peer.id) && peer is TelegramUser {
|
||||
existingPeerIds.insert(peer.id)
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .peer(peer), section: .global, dateTimeFormat: themeAndStrings.4))
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .peer(peer), section: .global, dateTimeFormat: presentationData.dateTimeFormat))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
@ -827,7 +828,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
let peer = foundPeer.peer
|
||||
if !existingPeerIds.contains(peer.id) && peer is TelegramUser {
|
||||
existingPeerIds.insert(peer.id)
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .peer(peer), section: .global, dateTimeFormat: themeAndStrings.4))
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .peer(peer), section: .global, dateTimeFormat: presentationData.dateTimeFormat))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
@ -905,8 +906,8 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
foundRemotePeers = .single(([], []))
|
||||
}
|
||||
|
||||
return combineLatest(foundGroupMembers, foundMembers, foundRemotePeers, themeAndStringsPromise.get(), statePromise.get())
|
||||
|> map { foundGroupMembers, foundMembers, foundRemotePeers, themeAndStrings, state -> [ChannelMembersSearchEntry]? in
|
||||
return combineLatest(foundGroupMembers, foundMembers, foundRemotePeers, presentationDataPromise.get(), statePromise.get())
|
||||
|> map { foundGroupMembers, foundMembers, foundRemotePeers, presentationData, state -> [ChannelMembersSearchEntry]? in
|
||||
var entries: [ChannelMembersSearchEntry] = []
|
||||
|
||||
var existingPeerIds = Set<PeerId>()
|
||||
@ -977,16 +978,16 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
var enabled = true
|
||||
if case .banAndPromoteActions = mode {
|
||||
if case .creator = participant.participant {
|
||||
label = themeAndStrings.1.Channel_Management_LabelOwner
|
||||
label = presentationData.strings.Channel_Management_LabelOwner
|
||||
enabled = false
|
||||
}
|
||||
} else if case .searchMembers = mode {
|
||||
switch participant.participant {
|
||||
case .creator:
|
||||
label = themeAndStrings.1.Channel_Management_LabelOwner
|
||||
label = presentationData.strings.Channel_Management_LabelOwner
|
||||
case let .member(member):
|
||||
if member.adminInfo != nil {
|
||||
label = themeAndStrings.1.Channel_Management_LabelEditor
|
||||
label = presentationData.strings.Channel_Management_LabelEditor
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -998,11 +999,11 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
var peerActions: [ParticipantRevealAction] = []
|
||||
/*if case .searchMembers = mode {
|
||||
if canPromote {
|
||||
peerActions.append(ParticipantRevealAction(type: .neutral, title: themeAndStrings.1.GroupInfo_ActionPromote, action: .promote))
|
||||
peerActions.append(ParticipantRevealAction(type: .neutral, title: presentationData.strings.GroupInfo_ActionPromote, action: .promote))
|
||||
}
|
||||
if canRestrict {
|
||||
peerActions.append(ParticipantRevealAction(type: .warning, title: themeAndStrings.1.GroupInfo_ActionRestrict, action: .restrict))
|
||||
peerActions.append(ParticipantRevealAction(type: .destructive, title: themeAndStrings.1.Common_Delete, action: .remove))
|
||||
peerActions.append(ParticipantRevealAction(type: .warning, title: presentationData.strings.GroupInfo_ActionRestrict, action: .restrict))
|
||||
peerActions.append(ParticipantRevealAction(type: .destructive, title: presentationData.strings.Common_Delete, action: .remove))
|
||||
}
|
||||
}*/
|
||||
|
||||
@ -1010,14 +1011,14 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
case .searchAdmins:
|
||||
switch participant.participant {
|
||||
case .creator:
|
||||
label = themeAndStrings.1.Channel_Management_LabelOwner
|
||||
label = presentationData.strings.Channel_Management_LabelOwner
|
||||
case let .member(_, _, adminInfo, _, _):
|
||||
if let adminInfo = adminInfo {
|
||||
if let peer = participant.peers[adminInfo.promotedBy] {
|
||||
if peer.id == participant.peer.id {
|
||||
label = themeAndStrings.1.Channel_Management_LabelAdministrator
|
||||
label = presentationData.strings.Channel_Management_LabelAdministrator
|
||||
} else {
|
||||
label = themeAndStrings.1.Channel_Management_PromotedBy(peer.displayTitle(strings: themeAndStrings.1, displayOrder: themeAndStrings.3)).0
|
||||
label = presentationData.strings.Channel_Management_PromotedBy(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1032,7 +1033,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
if !exceptionsString.isEmpty {
|
||||
exceptionsString.append(", ")
|
||||
}
|
||||
exceptionsString.append(compactStringForGroupPermission(strings: themeAndStrings.1, right: rights))
|
||||
exceptionsString.append(compactStringForGroupPermission(strings: presentationData.strings, right: rights))
|
||||
}
|
||||
}
|
||||
label = exceptionsString
|
||||
@ -1044,7 +1045,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
switch participant.participant {
|
||||
case let .member(_, _, _, banInfo, _):
|
||||
if let banInfo = banInfo, let peer = participant.peers[banInfo.restrictedBy] {
|
||||
label = themeAndStrings.1.Channel_Management_RemovedBy(peer.displayTitle(strings: themeAndStrings.1, displayOrder: themeAndStrings.3)).0
|
||||
label = presentationData.strings.Channel_Management_RemovedBy(peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder)).0
|
||||
}
|
||||
default:
|
||||
break
|
||||
@ -1052,7 +1053,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
default:
|
||||
break
|
||||
}
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .participant(participant: participant, label: label, revealActions: peerActions, revealed: state.revealedPeerId == RevealedPeerId(peerId: participant.peer.id, section: section), enabled: enabled), section: section, dateTimeFormat: themeAndStrings.4))
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .participant(participant: participant, label: label, revealActions: peerActions, revealed: state.revealedPeerId == RevealedPeerId(peerId: participant.peer.id, section: section), enabled: enabled), section: section, dateTimeFormat: presentationData.dateTimeFormat))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
@ -1076,12 +1077,12 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
var enabled = true
|
||||
if case .banAndPromoteActions = mode {
|
||||
if case .creator = participant.participant {
|
||||
label = themeAndStrings.1.Channel_Management_LabelOwner
|
||||
label = presentationData.strings.Channel_Management_LabelOwner
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .participant(participant: participant, label: label, revealActions: [], revealed: false, enabled: enabled), section: section, dateTimeFormat: themeAndStrings.4, addIcon: addIcon))
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .participant(participant: participant, label: label, revealActions: [], revealed: false, enabled: enabled), section: section, dateTimeFormat: presentationData.dateTimeFormat, addIcon: addIcon))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
@ -1090,7 +1091,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
let peer = foundPeer.peer
|
||||
if !existingPeerIds.contains(peer.id) && peer is TelegramUser {
|
||||
existingPeerIds.insert(peer.id)
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .peer(peer), section: .global, dateTimeFormat: themeAndStrings.4))
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .peer(peer), section: .global, dateTimeFormat: presentationData.dateTimeFormat))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
@ -1099,7 +1100,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
let peer = foundPeer.peer
|
||||
if !existingPeerIds.contains(peer.id) && peer is TelegramUser {
|
||||
existingPeerIds.insert(peer.id)
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .peer(peer), section: .global, dateTimeFormat: themeAndStrings.4))
|
||||
entries.append(ChannelMembersSearchEntry(index: index, content: .peer(peer), section: .global, dateTimeFormat: presentationData.dateTimeFormat))
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
@ -1114,29 +1115,29 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod
|
||||
let previousSearchItems = Atomic<[ChannelMembersSearchEntry]?>(value: nil)
|
||||
let previousEmptyQueryItems = Atomic<[ChannelMembersSearchEntry]?>(value: nil)
|
||||
|
||||
self.emptyQueryDisposable.set((combineLatest(emptyQueryItems, self.themeAndStringsPromise.get())
|
||||
|> deliverOnMainQueue).start(next: { [weak self] entries, themeAndStrings in
|
||||
self.emptyQueryDisposable.set((combineLatest(emptyQueryItems, self.presentationDataPromise.get())
|
||||
|> deliverOnMainQueue).start(next: { [weak self] entries, presentationData in
|
||||
if let strongSelf = self {
|
||||
let previousEntries = previousEmptyQueryItems.swap(entries)
|
||||
let firstTime = previousEntries == nil
|
||||
let transition = channelMembersSearchContainerPreparedRecentTransition(from: previousEntries ?? [], to: entries ?? [], isSearching: entries != nil, account: context.account, theme: themeAndStrings.0, strings: themeAndStrings.1, nameSortOrder: themeAndStrings.2, nameDisplayOrder: themeAndStrings.3, interaction: interaction)
|
||||
let transition = channelMembersSearchContainerPreparedRecentTransition(from: previousEntries ?? [], to: entries ?? [], isSearching: entries != nil, account: context.account, presentationData: presentationData, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, interaction: interaction)
|
||||
strongSelf.enqueueEmptyQueryTransition(transition, firstTime: firstTime)
|
||||
|
||||
if entries == nil {
|
||||
strongSelf.emptyQueryListNode.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
|
||||
} else {
|
||||
strongSelf.emptyQueryListNode.backgroundColor = themeAndStrings.0.chatList.backgroundColor
|
||||
strongSelf.emptyQueryListNode.backgroundColor = presentationData.theme.chatList.backgroundColor
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
self.searchDisposable.set((combineLatest(foundItems, self.themeAndStringsPromise.get())
|
||||
|> deliverOnMainQueue).start(next: { [weak self] entries, themeAndStrings in
|
||||
self.searchDisposable.set((combineLatest(foundItems, self.presentationDataPromise.get())
|
||||
|> deliverOnMainQueue).start(next: { [weak self] entries, presentationData in
|
||||
if let strongSelf = self {
|
||||
let previousEntries = previousSearchItems.swap(entries)
|
||||
updateActivity(false)
|
||||
let firstTime = previousEntries == nil
|
||||
let transition = channelMembersSearchContainerPreparedRecentTransition(from: previousEntries ?? [], to: entries ?? [], isSearching: entries != nil, account: context.account, theme: themeAndStrings.0, strings: themeAndStrings.1, nameSortOrder: themeAndStrings.2, nameDisplayOrder: themeAndStrings.3, interaction: interaction)
|
||||
let transition = channelMembersSearchContainerPreparedRecentTransition(from: previousEntries ?? [], to: entries ?? [], isSearching: entries != nil, account: context.account, presentationData: presentationData, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, interaction: interaction)
|
||||
strongSelf.enqueueTransition(transition, firstTime: firstTime)
|
||||
}
|
||||
}))
|
||||
|
@ -14,6 +14,7 @@ import TemporaryCachedPeerDataManager
|
||||
import SearchBarNode
|
||||
import ContactsPeerItem
|
||||
import SearchUI
|
||||
import ItemListUI
|
||||
|
||||
private final class ChannelMembersSearchInteraction {
|
||||
let openPeer: (Peer, RenderedChannelParticipant?) -> Void
|
||||
@ -59,7 +60,7 @@ private enum ChannelMembersSearchEntry: Comparable, Identifiable {
|
||||
}
|
||||
}
|
||||
|
||||
func item(account: Account, theme: PresentationTheme, strings: PresentationStrings, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, interaction: ChannelMembersSearchInteraction) -> ListViewItem {
|
||||
func item(account: Account, presentationData: PresentationData, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, interaction: ChannelMembersSearchInteraction) -> ListViewItem {
|
||||
switch self {
|
||||
case let .peer(_, participant, editing, label, enabled):
|
||||
let status: ContactsPeerItemStatus
|
||||
@ -68,7 +69,7 @@ private enum ChannelMembersSearchEntry: Comparable, Identifiable {
|
||||
} else {
|
||||
status = .none
|
||||
}
|
||||
return ContactsPeerItem(theme: theme, strings: strings, sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: account, peerMode: .peer, peer: .peer(peer: participant.peer, chatPeer: nil), status: status, enabled: enabled, selection: .none, editing: editing, index: nil, header: nil, action: { _ in
|
||||
return ContactsPeerItem(presentationData: ItemListPresentationData(presentationData), sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: account, peerMode: .peer, peer: .peer(peer: participant.peer, chatPeer: nil), status: status, enabled: enabled, selection: .none, editing: editing, index: nil, header: nil, action: { _ in
|
||||
interaction.openPeer(participant.peer, participant)
|
||||
})
|
||||
}
|
||||
@ -82,12 +83,12 @@ private struct ChannelMembersSearchTransition {
|
||||
let initial: Bool
|
||||
}
|
||||
|
||||
private func preparedTransition(from fromEntries: [ChannelMembersSearchEntry]?, to toEntries: [ChannelMembersSearchEntry], account: Account, theme: PresentationTheme, strings: PresentationStrings, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, interaction: ChannelMembersSearchInteraction) -> ChannelMembersSearchTransition {
|
||||
private func preparedTransition(from fromEntries: [ChannelMembersSearchEntry]?, to toEntries: [ChannelMembersSearchEntry], account: Account, presentationData: PresentationData, nameSortOrder: PresentationPersonNameOrder, nameDisplayOrder: PresentationPersonNameOrder, interaction: ChannelMembersSearchInteraction) -> ChannelMembersSearchTransition {
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries ?? [], rightList: toEntries)
|
||||
|
||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, theme: theme, strings: strings, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, interaction: interaction), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, theme: theme, strings: strings, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, interaction: interaction), directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, presentationData: presentationData, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, interaction: interaction), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(account: account, presentationData: presentationData, nameSortOrder: nameSortOrder, nameDisplayOrder: nameDisplayOrder, interaction: interaction), directionHint: nil) }
|
||||
|
||||
return ChannelMembersSearchTransition(deletions: deletions, insertions: insertions, updates: updates, initial: fromEntries == nil)
|
||||
}
|
||||
@ -232,7 +233,7 @@ class ChannelMembersSearchControllerNode: ASDisplayNode {
|
||||
}
|
||||
let previous = previousEntries.swap(entries)
|
||||
|
||||
strongSelf.enqueueTransition(preparedTransition(from: previous, to: entries, account: context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, nameSortOrder: strongSelf.presentationData.nameSortOrder, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder, interaction: interaction))
|
||||
strongSelf.enqueueTransition(preparedTransition(from: previous, to: entries, account: context.account, presentationData: strongSelf.presentationData, nameSortOrder: strongSelf.presentationData.nameSortOrder, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder, interaction: interaction))
|
||||
})
|
||||
disposableAndLoadMoreControl = (disposable, nil)
|
||||
} else {
|
||||
@ -290,7 +291,7 @@ class ChannelMembersSearchControllerNode: ASDisplayNode {
|
||||
|
||||
let previous = previousEntries.swap(entries)
|
||||
|
||||
strongSelf.enqueueTransition(preparedTransition(from: previous, to: entries, account: context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, nameSortOrder: strongSelf.presentationData.nameSortOrder, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder, interaction: interaction))
|
||||
strongSelf.enqueueTransition(preparedTransition(from: previous, to: entries, account: context.account, presentationData: strongSelf.presentationData, nameSortOrder: strongSelf.presentationData.nameSortOrder, nameDisplayOrder: strongSelf.presentationData.nameDisplayOrder, interaction: interaction))
|
||||
})
|
||||
}
|
||||
self.disposable = disposableAndLoadMoreControl.0
|
||||
|
@ -415,7 +415,7 @@ private func commitChannelOwnershipTransferController(context: AccountContext, p
|
||||
|
||||
let disposable = MetaDisposable()
|
||||
|
||||
let contentNode = ChannelOwnershipTransferAlertContentNode(theme: AlertControllerTheme(presentationTheme: presentationData.theme), ptheme: presentationData.theme, strings: presentationData.strings, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
|
||||
let contentNode = ChannelOwnershipTransferAlertContentNode(theme: AlertControllerTheme(presentationData: presentationData), ptheme: presentationData.theme, strings: presentationData.strings, actions: [TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
|
||||
dismissImpl?()
|
||||
}), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Done, action: {
|
||||
proceedImpl?()
|
||||
@ -425,9 +425,9 @@ private func commitChannelOwnershipTransferController(context: AccountContext, p
|
||||
proceedImpl?()
|
||||
}
|
||||
|
||||
let controller = AlertController(theme: AlertControllerTheme(presentationTheme: presentationData.theme), contentNode: contentNode)
|
||||
let controller = AlertController(theme: AlertControllerTheme(presentationData: presentationData), contentNode: contentNode)
|
||||
let presentationDataDisposable = context.sharedContext.presentationData.start(next: { [weak controller, weak contentNode] presentationData in
|
||||
controller?.theme = AlertControllerTheme(presentationTheme: presentationData.theme)
|
||||
controller?.theme = AlertControllerTheme(presentationData: presentationData)
|
||||
contentNode?.inputFieldNode.updateTheme(presentationData.theme)
|
||||
})
|
||||
controller.dismissed = {
|
||||
@ -507,7 +507,7 @@ private func commitChannelOwnershipTransferController(context: AccountContext, p
|
||||
|
||||
private func confirmChannelOwnershipTransferController(context: AccountContext, peer: Peer, member: TelegramUser, present: @escaping (ViewController, Any?) -> Void, completion: @escaping (PeerId?) -> Void) -> ViewController {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let theme = AlertControllerTheme(presentationTheme: presentationData.theme)
|
||||
let theme = AlertControllerTheme(presentationData: presentationData)
|
||||
|
||||
var isGroup = true
|
||||
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
|
||||
@ -538,9 +538,9 @@ private func confirmChannelOwnershipTransferController(context: AccountContext,
|
||||
|
||||
func channelOwnershipTransferController(context: AccountContext, peer: Peer, member: TelegramUser, initialError: ChannelOwnershipTransferError, present: @escaping (ViewController, Any?) -> Void, completion: @escaping (PeerId?) -> Void) -> ViewController {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
let theme = AlertControllerTheme(presentationTheme: presentationData.theme)
|
||||
let theme = AlertControllerTheme(presentationData: presentationData)
|
||||
|
||||
var title: NSAttributedString? = NSAttributedString(string: presentationData.strings.OwnershipTransfer_SecurityCheck, font: Font.medium(17.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||
var title: NSAttributedString? = NSAttributedString(string: presentationData.strings.OwnershipTransfer_SecurityCheck, font: Font.medium(presentationData.fontSize.itemListBaseFontSize), textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||
|
||||
var text = presentationData.strings.OwnershipTransfer_SecurityRequirements
|
||||
var isGroup = true
|
||||
|
@ -216,13 +216,13 @@ private enum ChannelPermissionsEntry: ItemListNodeEntry {
|
||||
}
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! ChannelPermissionsControllerArguments
|
||||
switch self {
|
||||
case let .permissionsHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .permission(theme, _, title, value, rights, enabled):
|
||||
return ItemListSwitchItem(theme: theme, title: title, value: value, type: .icon, enableInteractiveChanges: enabled != nil, enabled: enabled ?? true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: title, value: value, type: .icon, enableInteractiveChanges: enabled != nil, enabled: enabled ?? true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
if let _ = enabled {
|
||||
arguments.updatePermission(rights, value)
|
||||
} else {
|
||||
@ -232,21 +232,21 @@ private enum ChannelPermissionsEntry: ItemListNodeEntry {
|
||||
arguments.presentRestrictedPermissionAlert(rights)
|
||||
})
|
||||
case let .slowmodeHeader(theme, value):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: value, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: value, sectionId: self.section)
|
||||
case let .slowmode(theme, strings, value):
|
||||
return ChatSlowmodeItem(theme: theme, strings: strings, value: value, enabled: true, sectionId: self.section, updated: { value in
|
||||
arguments.updateSlowmode(value)
|
||||
})
|
||||
case let .slowmodeInfo(theme, value):
|
||||
return ItemListTextItem(theme: theme, text: .plain(value), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(value), sectionId: self.section)
|
||||
case let .kicked(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openKicked()
|
||||
})
|
||||
case let .exceptionsHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .add(theme, text):
|
||||
return ItemListPeerActionItem(theme: theme, icon: PresentationResourcesItemList.addPersonIcon(theme), title: text, sectionId: self.section, editing: false, action: {
|
||||
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.addPersonIcon(theme), title: text, sectionId: self.section, editing: false, action: {
|
||||
arguments.addPeer()
|
||||
})
|
||||
case let .peerItem(theme, strings, dateTimeFormat, nameDisplayOrder, _, participant, editing, enabled, canOpen, defaultBannedRights):
|
||||
@ -270,7 +270,7 @@ private enum ChannelPermissionsEntry: ItemListNodeEntry {
|
||||
default:
|
||||
break
|
||||
}
|
||||
return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: participant.peer, presence: nil, text: text, label: .none, editing: editing, switchValue: nil, enabled: enabled, selectable: true, sectionId: self.section, action: canOpen ? {
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: participant.peer, presence: nil, text: text, label: .none, editing: editing, switchValue: nil, enabled: enabled, selectable: true, sectionId: self.section, action: canOpen ? {
|
||||
arguments.openPeer(participant.participant)
|
||||
} : {
|
||||
arguments.openPeerInfo(participant.peer)
|
||||
@ -828,8 +828,8 @@ public func channelPermissionsController(context: AccountContext, peerId origina
|
||||
})
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.GroupInfo_Permissions_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
let listState = ItemListNodeState(entries: channelPermissionsControllerEntries(presentationData: presentationData, view: view, state: state, participants: participants), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, animateChanges: previous != nil && participants != nil && previous!.count >= participants!.count)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.GroupInfo_Permissions_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: channelPermissionsControllerEntries(presentationData: presentationData, view: view, state: state, participants: participants), style: .blocks, emptyStateItem: emptyStateItem, searchItem: searchItem, animateChanges: previous != nil && participants != nil && previous!.count >= participants!.count)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -263,35 +263,35 @@ private enum ChannelVisibilityEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! ChannelVisibilityControllerArguments
|
||||
switch self {
|
||||
case let .typeHeader(theme, title):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: title, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: title, sectionId: self.section)
|
||||
case let .typePublic(theme, text, selected):
|
||||
return ItemListCheckboxItem(theme: theme, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.updateCurrentType(.publicChannel)
|
||||
})
|
||||
case let .typePrivate(theme, text, selected):
|
||||
return ItemListCheckboxItem(theme: theme, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.updateCurrentType(.privateChannel)
|
||||
})
|
||||
case let .typeInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .publicLinkHeader(theme, title):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: title, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: title, sectionId: self.section)
|
||||
case let .publicLinkAvailability(theme, text, value):
|
||||
let attr = NSMutableAttributedString(string: text, textColor: value ? theme.list.freeTextColor : theme.list.freeTextErrorColor)
|
||||
attr.addAttribute(.font, value: Font.regular(13), range: NSMakeRange(0, attr.length))
|
||||
return ItemListActivityTextItem(displayActivity: value, theme: theme, text: attr, sectionId: self.section)
|
||||
return ItemListActivityTextItem(displayActivity: value, presentationData: presentationData, text: attr, sectionId: self.section)
|
||||
case let .privateLink(theme, text, value):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: value != nil ? .neutral : .disabled, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: value != nil ? .neutral : .disabled, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
if let value = value {
|
||||
arguments.displayPrivateLinkMenu(value)
|
||||
}
|
||||
}, tag: ChannelVisibilityEntryTag.privateLink)
|
||||
case let .editablePublicLink(theme, strings, placeholder, currentText):
|
||||
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: "t.me/", textColor: theme.list.itemPrimaryTextColor), text: currentText, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: false), clearType: .always, tag: ChannelVisibilityEntryTag.publicLink, sectionId: self.section, textUpdated: { updatedText in
|
||||
return ItemListSingleLineInputItem(presentationData: presentationData, title: NSAttributedString(string: "t.me/", textColor: theme.list.itemPrimaryTextColor), text: currentText, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: false), clearType: .always, tag: ChannelVisibilityEntryTag.publicLink, sectionId: self.section, textUpdated: { updatedText in
|
||||
arguments.updatePublicLinkText(currentText, updatedText)
|
||||
}, updatedFocus: { focus in
|
||||
if focus {
|
||||
@ -300,21 +300,21 @@ private enum ChannelVisibilityEntry: ItemListNodeEntry {
|
||||
}, action: {
|
||||
})
|
||||
case let .privateLinkInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .privateLinkCopy(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.copyPrivateLink()
|
||||
})
|
||||
case let .privateLinkRevoke(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.revokePrivateLink()
|
||||
})
|
||||
case let .privateLinkShare(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.sharePrivateLink()
|
||||
})
|
||||
case let .publicLinkInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .markdown(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section)
|
||||
case let .publicLinkStatus(theme, text, status):
|
||||
var displayActivity = false
|
||||
let color: UIColor
|
||||
@ -334,15 +334,15 @@ private enum ChannelVisibilityEntry: ItemListNodeEntry {
|
||||
color = theme.list.freeTextColor
|
||||
displayActivity = true
|
||||
}
|
||||
return ItemListActivityTextItem(displayActivity: displayActivity, theme: theme, text: NSAttributedString(string: text, textColor: color), sectionId: self.section)
|
||||
return ItemListActivityTextItem(displayActivity: displayActivity, presentationData: presentationData, text: NSAttributedString(string: text, textColor: color), sectionId: self.section)
|
||||
case let .existingLinksInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .existingLinkPeerItem(_, theme, strings, dateTimeFormat, nameDisplayOrder, peer, editing, enabled):
|
||||
var label = ""
|
||||
if let addressName = peer.addressName {
|
||||
label = "t.me/" + addressName
|
||||
}
|
||||
return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: nil, text: .text(label), label: .none, editing: editing, switchValue: nil, enabled: enabled, selectable: true, sectionId: self.section, action: nil, setPeerIdWithRevealedOptions: { previousId, id in
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: nil, text: .text(label), label: .none, editing: editing, switchValue: nil, enabled: enabled, selectable: true, sectionId: self.section, action: nil, setPeerIdWithRevealedOptions: { previousId, id in
|
||||
arguments.setPeerIdWithRevealedOptions(previousId, id)
|
||||
}, removePeer: { peerId in
|
||||
arguments.revokePeerId(peerId)
|
||||
@ -1214,8 +1214,8 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId,
|
||||
focusItemTag = ChannelVisibilityEntryTag.publicLink
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: entries, style: .blocks, focusItemTag: focusItemTag, crossfadeState: crossfade, animateChanges: false)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: entries, style: .blocks, focusItemTag: focusItemTag, crossfadeState: crossfade, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
} |> afterDisposed {
|
||||
|
@ -77,17 +77,17 @@ private enum ConvertToSupergroupEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! ConvertToSupergroupArguments
|
||||
switch self {
|
||||
case let .info(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .markdown(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section)
|
||||
case let .action(theme, title):
|
||||
return ItemListActionItem(theme: theme, title: title, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: title, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.convert()
|
||||
})
|
||||
case let .actionInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .markdown(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -166,8 +166,8 @@ public func convertToSupergroupController(context: AccountContext, peerId: PeerI
|
||||
rightNavigationButton = ItemListNavigationButton(content: .none, style: .activity, enabled: true, action: {})
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.ConvertToSupergroup_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(entries: convertToSupergroupEntries(presentationData: presentationData), style: .blocks)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.ConvertToSupergroup_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: convertToSupergroupEntries(presentationData: presentationData), style: .blocks)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -392,35 +392,35 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
|
||||
return lhs.sortIndex < rhs.sortIndex
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! DeviceContactInfoControllerArguments
|
||||
switch self {
|
||||
case let .info(_, theme, strings, dateTimeFormat, peer, state, jobSummary, isPlain):
|
||||
return ItemListAvatarAndNameInfoItem(account: arguments.account, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, mode: .contact, peer: peer, presence: nil, label: jobSummary, cachedData: nil, state: state, sectionId: self.section, style: arguments.isPlain ? .plain : .blocks(withTopInset: false, withExtendedBottomInset: true), editingNameUpdated: { editingName in
|
||||
return ItemListAvatarAndNameInfoItem(account: arguments.account, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .contact, peer: peer, presence: nil, label: jobSummary, cachedData: nil, state: state, sectionId: self.section, style: arguments.isPlain ? .plain : .blocks(withTopInset: false, withExtendedBottomInset: true), editingNameUpdated: { editingName in
|
||||
arguments.updateEditingName(editingName)
|
||||
}, avatarTapped: {
|
||||
}, context: nil, call: nil)
|
||||
case let .sendMessage(_, theme, title):
|
||||
return ItemListActionItem(theme: theme, title: title, kind: .generic, alignment: .natural, sectionId: self.section, style: arguments.isPlain ? .plain : .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: title, kind: .generic, alignment: .natural, sectionId: self.section, style: arguments.isPlain ? .plain : .blocks, action: {
|
||||
arguments.performAction(.sendMessage)
|
||||
})
|
||||
case let .invite(_, theme, title):
|
||||
return ItemListActionItem(theme: theme, title: title, kind: .generic, alignment: .natural, sectionId: self.section, style: arguments.isPlain ? .plain : .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: title, kind: .generic, alignment: .natural, sectionId: self.section, style: arguments.isPlain ? .plain : .blocks, action: {
|
||||
arguments.performAction(.invite)
|
||||
})
|
||||
case let .createContact(_, theme, title):
|
||||
return ItemListActionItem(theme: theme, title: title, kind: .generic, alignment: .natural, sectionId: self.section, style: arguments.isPlain ? .plain : .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: title, kind: .generic, alignment: .natural, sectionId: self.section, style: arguments.isPlain ? .plain : .blocks, action: {
|
||||
arguments.performAction(.createContact)
|
||||
})
|
||||
case let .addToExisting(_, theme, title):
|
||||
return ItemListActionItem(theme: theme, title: title, kind: .generic, alignment: .natural, sectionId: self.section, style: arguments.isPlain ? .plain : .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: title, kind: .generic, alignment: .natural, sectionId: self.section, style: arguments.isPlain ? .plain : .blocks, action: {
|
||||
arguments.performAction(.addToExisting)
|
||||
})
|
||||
case let .company(_, theme, title, value, selected):
|
||||
return ItemListTextWithLabelItem(theme: theme, label: title, text: value, style: arguments.isPlain ? .plain : .blocks, enabledEntityTypes: [], multiline: true, selected: selected, sectionId: self.section, action: {
|
||||
return ItemListTextWithLabelItem(presentationData: presentationData, label: title, text: value, style: arguments.isPlain ? .plain : .blocks, enabledEntityTypes: [], multiline: true, selected: selected, sectionId: self.section, action: {
|
||||
}, tag: nil)
|
||||
case let .phoneNumber(_, index, theme, title, label, value, selected, isInteractionEnabled):
|
||||
return ItemListTextWithLabelItem(theme: theme, label: title, text: value, style: arguments.isPlain ? .plain : .blocks, textColor: .accent, enabledEntityTypes: [], multiline: false, selected: selected, sectionId: self.section, action: isInteractionEnabled ? {
|
||||
return ItemListTextWithLabelItem(presentationData: presentationData, label: title, text: value, style: arguments.isPlain ? .plain : .blocks, textColor: .accent, enabledEntityTypes: [], multiline: false, selected: selected, sectionId: self.section, action: isInteractionEnabled ? {
|
||||
if selected != nil {
|
||||
arguments.toggleSelection(.phoneNumber(label, value))
|
||||
} else {
|
||||
@ -432,13 +432,13 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
|
||||
}
|
||||
} : nil, tag: DeviceContactInfoEntryTag.info(index))
|
||||
case let .phoneNumberSharingInfo(_, theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .markdown(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section)
|
||||
case let .phoneNumberShareViaException(_, theme, text, value):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, sectionId: self.section, style: arguments.isPlain ? .plain : .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, sectionId: self.section, style: arguments.isPlain ? .plain : .blocks, updated: { value in
|
||||
arguments.updateShareViaException(value)
|
||||
})
|
||||
case let .phoneNumberShareViaExceptionInfo(_, theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .markdown(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section)
|
||||
case let .editingPhoneNumber(_, theme, strings, id, title, label, value, hasActiveRevealControls):
|
||||
return UserInfoEditingPhoneItem(theme: theme, strings: strings, id: id, label: title, value: value, editing: UserInfoEditingPhoneItemEditing(editable: true, hasActiveRevealControls: hasActiveRevealControls), sectionId: self.section, setPhoneIdWithRevealedOptions: { lhs, rhs in
|
||||
arguments.setPhoneIdWithRevealedOptions(lhs, rhs)
|
||||
@ -454,7 +454,7 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
|
||||
arguments.addPhoneNumber()
|
||||
})
|
||||
case let .email(_, index, theme, title, label, value, selected):
|
||||
return ItemListTextWithLabelItem(theme: theme, label: title, text: value, style: arguments.isPlain ? .plain : .blocks, textColor: .accent, enabledEntityTypes: [], multiline: false, selected: selected, sectionId: self.section, action: {
|
||||
return ItemListTextWithLabelItem(presentationData: presentationData, label: title, text: value, style: arguments.isPlain ? .plain : .blocks, textColor: .accent, enabledEntityTypes: [], multiline: false, selected: selected, sectionId: self.section, action: {
|
||||
if selected != nil {
|
||||
arguments.toggleSelection(.email(label, value))
|
||||
} else {
|
||||
@ -466,7 +466,7 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
|
||||
}
|
||||
}, tag: DeviceContactInfoEntryTag.info(index))
|
||||
case let .url(_, index, theme, title, label, value, selected):
|
||||
return ItemListTextWithLabelItem(theme: theme, label: title, text: value, style: arguments.isPlain ? .plain : .blocks, textColor: .accent, enabledEntityTypes: [], multiline: false, selected: selected, sectionId: self.section, action: {
|
||||
return ItemListTextWithLabelItem(presentationData: presentationData, label: title, text: value, style: arguments.isPlain ? .plain : .blocks, textColor: .accent, enabledEntityTypes: [], multiline: false, selected: selected, sectionId: self.section, action: {
|
||||
if selected != nil {
|
||||
arguments.toggleSelection(.url(label, value))
|
||||
} else {
|
||||
@ -505,7 +505,7 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
|
||||
}
|
||||
}, tag: DeviceContactInfoEntryTag.info(index))
|
||||
case let .birthday(_, theme, title, value, text, selected):
|
||||
return ItemListTextWithLabelItem(theme: theme, label: title, text: text, style: arguments.isPlain ? .plain : .blocks, textColor: .accent, enabledEntityTypes: [], multiline: true, selected: selected, sectionId: self.section, action: {
|
||||
return ItemListTextWithLabelItem(presentationData: presentationData, label: title, text: text, style: arguments.isPlain ? .plain : .blocks, textColor: .accent, enabledEntityTypes: [], multiline: true, selected: selected, sectionId: self.section, action: {
|
||||
if selected != nil {
|
||||
arguments.toggleSelection(.birthday)
|
||||
} else {
|
||||
@ -534,7 +534,7 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
|
||||
}
|
||||
}, tag: DeviceContactInfoEntryTag.birthday)
|
||||
case let .socialProfile(_, index, theme, title, value, text, selected):
|
||||
return ItemListTextWithLabelItem(theme: theme, label: title, text: text, style: arguments.isPlain ? .plain : .blocks, textColor: .accent, enabledEntityTypes: [], multiline: true, selected: selected, sectionId: self.section, action: {
|
||||
return ItemListTextWithLabelItem(presentationData: presentationData, label: title, text: text, style: arguments.isPlain ? .plain : .blocks, textColor: .accent, enabledEntityTypes: [], multiline: true, selected: selected, sectionId: self.section, action: {
|
||||
if selected != nil {
|
||||
arguments.toggleSelection(.socialProfile(value))
|
||||
} else if value.url.count > 0 {
|
||||
@ -546,7 +546,7 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
|
||||
}
|
||||
}, tag: DeviceContactInfoEntryTag.info(index))
|
||||
case let .instantMessenger(_, index, theme, title, value, text, selected):
|
||||
return ItemListTextWithLabelItem(theme: theme, label: title, text: text, style: arguments.isPlain ? .plain : .blocks, textColor: .accent, enabledEntityTypes: [], multiline: true, selected: selected, sectionId: self.section, action: {
|
||||
return ItemListTextWithLabelItem(presentationData: presentationData, label: title, text: text, style: arguments.isPlain ? .plain : .blocks, textColor: .accent, enabledEntityTypes: [], multiline: true, selected: selected, sectionId: self.section, action: {
|
||||
if selected != nil {
|
||||
arguments.toggleSelection(.instantMessenger(value))
|
||||
}
|
||||
@ -556,7 +556,7 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
|
||||
}
|
||||
}, tag: DeviceContactInfoEntryTag.info(index))
|
||||
case let .note(_, theme, title, text, selected):
|
||||
return ItemListTextWithLabelItem(theme: theme, label: title, text: text, style: arguments.isPlain ? .plain : .blocks, enabledEntityTypes: [], multiline: true, selected: selected, sectionId: self.section, action: {
|
||||
return ItemListTextWithLabelItem(presentationData: presentationData, label: title, text: text, style: arguments.isPlain ? .plain : .blocks, enabledEntityTypes: [], multiline: true, selected: selected, sectionId: self.section, action: {
|
||||
if selected != nil {
|
||||
arguments.toggleSelection(.note)
|
||||
}
|
||||
@ -1214,7 +1214,7 @@ public func deviceContactInfoController(context: AccountContext, subject: Device
|
||||
selecting = true
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: nil)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: nil)
|
||||
|
||||
let editingPhoneIds = Set<Int64>(state.phoneNumbers.map({ $0.id }))
|
||||
let previousPhoneIds = previousEditingPhoneIds.swap(editingPhoneIds)
|
||||
@ -1236,7 +1236,7 @@ public func deviceContactInfoController(context: AccountContext, subject: Device
|
||||
focusItemTag = DeviceContactInfoEntryTag.editingPhone(insertedPhoneId)
|
||||
}
|
||||
|
||||
let listState = ItemListNodeState(entries: deviceContactInfoEntries(account: context.account, presentationData: presentationData, peer: peerAndContactData.0, isShare: isShare, shareViaException: shareViaException, contactData: peerAndContactData.2, isContact: peerAndContactData.1 != nil, state: state, selecting: selecting, editingPhoneNumbers: editingPhones), style: isShare ? .blocks : .plain, focusItemTag: focusItemTag)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: deviceContactInfoEntries(account: context.account, presentationData: presentationData, peer: peerAndContactData.0, isShare: isShare, shareViaException: shareViaException, contactData: peerAndContactData.2, isContact: peerAndContactData.1 != nil, state: state, selecting: selecting, editingPhoneNumbers: editingPhones), style: isShare ? .blocks : .plain, focusItemTag: focusItemTag)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -493,27 +493,27 @@ private enum GroupInfoEntry: ItemListNodeEntry {
|
||||
return lhs.sortIndex < rhs.sortIndex
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! GroupInfoArguments
|
||||
switch self {
|
||||
case let .info(theme, strings, dateTimeFormat, peer, cachedData, state, updatingAvatar):
|
||||
return ItemListAvatarAndNameInfoItem(account: arguments.context.account, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, mode: .generic, peer: peer, presence: nil, cachedData: cachedData, state: state, sectionId: self.section, style: .blocks(withTopInset: false, withExtendedBottomInset: false), editingNameUpdated: { editingName in
|
||||
return ItemListAvatarAndNameInfoItem(account: arguments.context.account, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .generic, peer: peer, presence: nil, cachedData: cachedData, state: state, sectionId: self.section, style: .blocks(withTopInset: false, withExtendedBottomInset: false), editingNameUpdated: { editingName in
|
||||
arguments.updateEditingName(editingName)
|
||||
}, avatarTapped: {
|
||||
arguments.tapAvatarAction()
|
||||
}, context: arguments.avatarAndNameInfoContext, updatingImage: updatingAvatar)
|
||||
case let .setGroupPhoto(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.changeProfilePhoto()
|
||||
})
|
||||
case let .about(theme, text):
|
||||
return ItemListMultilineTextItem(theme: theme, text: foldMultipleLineBreaks(text), enabledEntityTypes: [.url, .mention, .hashtag], sectionId: self.section, style: .blocks, longTapAction: {
|
||||
return ItemListMultilineTextItem(presentationData: presentationData, text: foldMultipleLineBreaks(text), enabledEntityTypes: [.url, .mention, .hashtag], sectionId: self.section, style: .blocks, longTapAction: {
|
||||
arguments.displayAboutContextMenu(text)
|
||||
}, linkItemAction: { action, itemLink in
|
||||
arguments.aboutLinkAction(action, itemLink)
|
||||
}, tag: GroupInfoEntryTag.about)
|
||||
case let .locationHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .location(theme, location):
|
||||
let imageSignal = chatMapSnapshotImage(account: arguments.context.account, resource: MapSnapshotMediaResource(latitude: location.latitude, longitude: location.longitude, width: 90, height: 90))
|
||||
return ItemListAddressItem(theme: theme, label: "", text: location.address.replacingOccurrences(of: ", ", with: "\n"), imageSignal: imageSignal, selected: nil, sectionId: self.section, style: .blocks, action: {
|
||||
@ -522,53 +522,53 @@ private enum GroupInfoEntry: ItemListNodeEntry {
|
||||
arguments.displayLocationContextMenu(location.address.replacingOccurrences(of: "\n", with: ", "))
|
||||
}, tag: GroupInfoEntryTag.location)
|
||||
case let .changeLocation(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.changeLocation()
|
||||
}, clearHighlightAutomatically: false)
|
||||
case let .link(theme, url):
|
||||
return ItemListActionItem(theme: theme, title: url, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: url, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.displayUsernameShareMenu(url)
|
||||
}, longTapAction: {
|
||||
arguments.displayUsernameContextMenu(url)
|
||||
}, tag: GroupInfoEntryTag.link)
|
||||
case let .notifications(theme, title, text):
|
||||
return ItemListDisclosureItem(theme: theme, title: title, label: text, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: title, label: text, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.changeNotificationMuteSettings()
|
||||
})
|
||||
case let .stickerPack(theme, title, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: title, label: value, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: title, label: value, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openStickerPackSetup()
|
||||
})
|
||||
case let .preHistory(theme, title, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: title, label: value, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: title, label: value, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openPreHistory()
|
||||
})
|
||||
case let .sharedMedia(theme, title):
|
||||
return ItemListDisclosureItem(theme: theme, title: title, label: "", sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: title, label: "", sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openSharedMedia()
|
||||
})
|
||||
case let .addMember(theme, title, editing):
|
||||
return ItemListPeerActionItem(theme: theme, icon: PresentationResourcesItemList.addPersonIcon(theme), title: title, sectionId: self.section, editing: editing, action: {
|
||||
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.addPersonIcon(theme), title: title, sectionId: self.section, editing: editing, action: {
|
||||
arguments.addMember()
|
||||
})
|
||||
case let .groupTypeSetup(theme, title, text):
|
||||
return ItemListDisclosureItem(theme: theme, title: title, label: text, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: title, label: text, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openGroupTypeSetup()
|
||||
})
|
||||
case let .linkedChannelSetup(theme, title, text):
|
||||
return ItemListDisclosureItem(theme: theme, title: title, label: text, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: title, label: text, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openLinkedChannelSetup()
|
||||
})
|
||||
case let .groupDescriptionSetup(theme, placeholder, text):
|
||||
return ItemListMultilineInputItem(theme: theme, text: text, placeholder: placeholder, maxLength: ItemListMultilineInputItemTextLimit(value: 255, display: true), sectionId: self.section, style: .blocks, textUpdated: { updatedText in
|
||||
return ItemListMultilineInputItem(presentationData: presentationData, text: text, placeholder: placeholder, maxLength: ItemListMultilineInputItemTextLimit(value: 255, display: true), sectionId: self.section, style: .blocks, textUpdated: { updatedText in
|
||||
arguments.updateEditingDescriptionText(updatedText)
|
||||
})
|
||||
case let .permissions(theme, title, text):
|
||||
return ItemListDisclosureItem(theme: theme, icon: PresentationResourcesChat.groupInfoPermissionsIcon(theme), title: title, label: text, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesChat.groupInfoPermissionsIcon(theme), title: title, label: text, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openPermissions()
|
||||
})
|
||||
case let .administrators(theme, title, text):
|
||||
return ItemListDisclosureItem(theme: theme, icon: PresentationResourcesChat.groupInfoAdminsIcon(theme), title: title, label: text, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesChat.groupInfoAdminsIcon(theme), title: title, label: text, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openAdministrators()
|
||||
})
|
||||
case let .member(theme, strings, dateTimeFormat, nameDisplayOrder, _, _, peer, participant, presence, memberStatus, editing, actions, enabled, selectable):
|
||||
@ -598,7 +598,7 @@ private enum GroupInfoEntry: ItemListNodeEntry {
|
||||
}
|
||||
}))
|
||||
}
|
||||
return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.context.account, peer: peer, presence: presence, text: .presence, label: label == nil ? .none : .text(label!, .standard), editing: editing, revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: enabled, selectable: selectable, sectionId: self.section, action: {
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.context.account, peer: peer, presence: presence, text: .presence, label: label == nil ? .none : .text(label!, .standard), editing: editing, revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: enabled, selectable: selectable, sectionId: self.section, action: {
|
||||
if let infoController = arguments.context.sharedContext.makePeerInfoController(context: arguments.context, peer: peer, mode: .generic), selectable {
|
||||
arguments.pushController(infoController)
|
||||
}
|
||||
@ -608,11 +608,11 @@ private enum GroupInfoEntry: ItemListNodeEntry {
|
||||
arguments.removePeer(peerId)
|
||||
})
|
||||
case let .expand(theme, title):
|
||||
return ItemListPeerActionItem(theme: theme, icon: PresentationResourcesItemList.downArrowImage(theme), title: title, sectionId: self.section, editing: false, action: {
|
||||
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.downArrowImage(theme), title: title, sectionId: self.section, editing: false, action: {
|
||||
arguments.expandParticipants()
|
||||
})
|
||||
case let .leave(theme, title):
|
||||
return ItemListActionItem(theme: theme, title: title, kind: .destructive, alignment: .center, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: title, kind: .destructive, alignment: .center, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.leave()
|
||||
})
|
||||
default:
|
||||
@ -2322,7 +2322,7 @@ public func groupInfoController(context: AccountContext, peerId originalPeerId:
|
||||
})
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.GroupInfo_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, secondaryRightNavigationButton: secondaryRightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.GroupInfo_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, secondaryRightNavigationButton: secondaryRightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
|
||||
let entries = groupInfoEntries(account: context.account, presentationData: presentationData, view: view, channelMembers: channelMembers, globalNotificationSettings: globalNotificationSettings, state: state)
|
||||
var memberIds: [PeerId] = []
|
||||
@ -2344,7 +2344,7 @@ public func groupInfoController(context: AccountContext, peerId originalPeerId:
|
||||
}
|
||||
}
|
||||
|
||||
let listState = ItemListNodeState(entries: entries, style: .blocks, searchItem: searchItem, animateChanges: animateChanges)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: entries, style: .blocks, searchItem: searchItem, animateChanges: animateChanges)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -78,21 +78,21 @@ private enum GroupPreHistorySetupEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! GroupPreHistorySetupArguments
|
||||
switch self {
|
||||
case let .header(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .visible(theme, text, value):
|
||||
return ItemListCheckboxItem(theme: theme, title: text, style: .left, checked: value, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: value, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.toggle(true)
|
||||
})
|
||||
case let .hidden(theme, text, value):
|
||||
return ItemListCheckboxItem(theme: theme, title: text, style: .left, checked: value, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: value, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.toggle(false)
|
||||
})
|
||||
case let .info(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .markdown(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -199,8 +199,8 @@ public func groupPreHistorySetupController(context: AccountContext, peerId: Peer
|
||||
})
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.Group_Setup_HistoryTitle), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(entries: groupPreHistorySetupEntries(isSupergroup: peerId.namespace == Namespaces.Peer.CloudChannel, presentationData: presentationData, defaultValue: defaultValue, state: state), style: .blocks)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.Group_Setup_HistoryTitle), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: groupPreHistorySetupEntries(isSupergroup: peerId.namespace == Namespaces.Peer.CloudChannel, presentationData: presentationData, defaultValue: defaultValue, state: state), style: .blocks)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -208,11 +208,11 @@ private enum GroupStickerPackEntry: ItemListNodeEntry {
|
||||
}
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! GroupStickerPackSetupControllerArguments
|
||||
switch self {
|
||||
case let .search(theme, strings, prefix, placeholder, value):
|
||||
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: prefix, textColor: theme.list.itemPrimaryTextColor), text: value, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: false), spacing: 0.0, clearType: .always, tag: nil, sectionId: self.section, textUpdated: { value in
|
||||
return ItemListSingleLineInputItem(presentationData: presentationData, title: NSAttributedString(string: prefix, textColor: theme.list.itemPrimaryTextColor), text: value, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: false), spacing: 0.0, clearType: .always, tag: nil, sectionId: self.section, textUpdated: { value in
|
||||
arguments.updateSearchText(value)
|
||||
}, processPaste: { text in
|
||||
if let url = (URL(string: text) ?? URL(string: "http://" + text)), url.host == "t.me" || url.host == "telegram.me" {
|
||||
@ -224,11 +224,11 @@ private enum GroupStickerPackEntry: ItemListNodeEntry {
|
||||
return text
|
||||
}, action: {})
|
||||
case let .searchInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section, linkAction: nil)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section, linkAction: nil)
|
||||
case let .packsTitle(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .pack(_, theme, strings, info, topItem, count, playAnimatedStickers, selected):
|
||||
return ItemListStickerPackItem(theme: theme, strings: strings, account: arguments.account, packInfo: info, itemCount: count, topItem: topItem, unread: false, control: selected ? .selection : .none, editing: ItemListStickerPackItemEditing(editable: false, editing: false, revealed: false, reorderable: false), enabled: true, playAnimatedStickers: playAnimatedStickers, sectionId: self.section, action: {
|
||||
return ItemListStickerPackItem(presentationData: presentationData, account: arguments.account, packInfo: info, itemCount: count, topItem: topItem, unread: false, control: selected ? .selection : .none, editing: ItemListStickerPackItemEditing(editable: false, editing: false, revealed: false, reorderable: false), enabled: true, playAnimatedStickers: playAnimatedStickers, sectionId: self.section, action: {
|
||||
if selected {
|
||||
arguments.openStickerPack(info)
|
||||
} else {
|
||||
@ -462,7 +462,7 @@ public func groupStickerPackSetupController(context: AccountContext, peerId: Pee
|
||||
}
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.Channel_Info_Stickers), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.Channel_Info_Stickers), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
|
||||
let hasData = initialData != nil
|
||||
let hadData = previousHadData.swap(hasData)
|
||||
@ -472,7 +472,7 @@ public func groupStickerPackSetupController(context: AccountContext, peerId: Pee
|
||||
emptyStateItem = ItemListLoadingIndicatorEmptyStateItem(theme: presentationData.theme)
|
||||
}
|
||||
|
||||
let listState = ItemListNodeState(entries: groupStickerPackSetupControllerEntries(presentationData: presentationData, searchText: searchState.0, view: view, initialData: initialData, searchState: searchState.1, stickerSettings: stickerSettings), style: .blocks, emptyStateItem: emptyStateItem, animateChanges: hasData && hadData)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: groupStickerPackSetupControllerEntries(presentationData: presentationData, searchText: searchState.0, view: view, initialData: initialData, searchState: searchState.1, stickerSettings: stickerSettings), style: .blocks, emptyStateItem: emptyStateItem, animateChanges: hasData && hadData)
|
||||
return (controllerState, (listState, arguments))
|
||||
} |> afterDisposed {
|
||||
actionsDisposable.dispose()
|
||||
|
@ -90,11 +90,11 @@ private enum GroupsInCommonEntry: ItemListNodeEntry {
|
||||
}
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! GroupsInCommonControllerArguments
|
||||
switch self {
|
||||
case let .peerItem(_, theme, strings, dateTimeFormat, nameDisplayOrder, peer):
|
||||
return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: nil, text: .none, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: {
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: nil, text: .none, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: {
|
||||
arguments.openPeer(peer.id)
|
||||
}, setPeerIdWithRevealedOptions: { _, _ in
|
||||
}, removePeer: { _ in
|
||||
@ -178,8 +178,8 @@ public func groupsInCommonController(context: AccountContext, peerId: PeerId) ->
|
||||
let previous = previousPeers
|
||||
previousPeers = peers
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.UserInfo_GroupsInCommon), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: groupsInCommonControllerEntries(presentationData: presentationData, state: state, peers: peers), style: .blocks, emptyStateItem: emptyStateItem, animateChanges: previous != nil && peers != nil && previous!.count >= peers!.count)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.UserInfo_GroupsInCommon), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: groupsInCommonControllerEntries(presentationData: presentationData, state: state, peers: peers), style: .blocks, emptyStateItem: emptyStateItem, animateChanges: previous != nil && peers != nil && previous!.count >= peers!.count)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
} |> afterDisposed {
|
||||
|
@ -12,16 +12,14 @@ import PresentationDataUtils
|
||||
import TelegramStringFormatting
|
||||
|
||||
class ItemListCallListItem: ListViewItem, ItemListItem {
|
||||
let theme: PresentationTheme
|
||||
let strings: PresentationStrings
|
||||
let presentationData: ItemListPresentationData
|
||||
let dateTimeFormat: PresentationDateTimeFormat
|
||||
let messages: [Message]
|
||||
let sectionId: ItemListSectionId
|
||||
let style: ItemListStyle
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, messages: [Message], sectionId: ItemListSectionId, style: ItemListStyle) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
init(presentationData: ItemListPresentationData, dateTimeFormat: PresentationDateTimeFormat, messages: [Message], sectionId: ItemListSectionId, style: ItemListStyle) {
|
||||
self.presentationData = presentationData
|
||||
self.dateTimeFormat = dateTimeFormat
|
||||
self.messages = messages
|
||||
self.sectionId = sectionId
|
||||
@ -62,10 +60,6 @@ class ItemListCallListItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.regular(15.0)
|
||||
private let font = Font.regular(14.0)
|
||||
private let typeFont = Font.medium(14.0)
|
||||
|
||||
private func stringForCallType(message: Message, strings: PresentationStrings) -> String {
|
||||
var string = ""
|
||||
for media in message.media {
|
||||
@ -181,10 +175,14 @@ class ItemListCallListItemNode: ListViewItemNode {
|
||||
|
||||
var updatedTheme: PresentationTheme?
|
||||
|
||||
if currentItem?.theme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
}
|
||||
|
||||
let titleFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 15.0 / 17.0))
|
||||
let font = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 14.0 / 17.0))
|
||||
let typeFont = Font.medium(floor(item.presentationData.fontSize.itemListBaseFontSize * 14.0 / 17.0))
|
||||
|
||||
let contentSize: CGSize
|
||||
var contentHeight: CGFloat = 0.0
|
||||
let insets: UIEdgeInsets
|
||||
@ -196,18 +194,18 @@ class ItemListCallListItemNode: ListViewItemNode {
|
||||
|
||||
switch item.style {
|
||||
case .plain:
|
||||
itemBackgroundColor = item.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.theme.list.itemPlainSeparatorColor
|
||||
itemBackgroundColor = item.presentationData.theme.list.plainBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemPlainSeparatorColor
|
||||
insets = itemListNeighborsPlainInsets(neighbors)
|
||||
case .blocks:
|
||||
itemBackgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
itemSeparatorColor = item.theme.list.itemBlocksSeparatorColor
|
||||
itemBackgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
itemSeparatorColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
insets = itemListNeighborsGroupedInsets(neighbors)
|
||||
}
|
||||
|
||||
let earliestMessage = item.messages.sorted(by: {$0.timestamp < $1.timestamp}).first!
|
||||
let titleText = stringForDate(timestamp: earliestMessage.timestamp, strings: item.strings)
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: titleText, font: titleFont, textColor: item.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - 20.0 - leftInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let titleText = stringForDate(timestamp: earliestMessage.timestamp, strings: item.presentationData.strings)
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: titleText, font: titleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - 20.0 - leftInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
contentHeight += titleLayout.size.height + 18.0
|
||||
|
||||
@ -217,11 +215,11 @@ class ItemListCallListItemNode: ListViewItemNode {
|
||||
for message in item.messages {
|
||||
let makeTimeLayout = makeNodesLayout[index].0
|
||||
let time = stringForMessageTimestamp(timestamp: message.timestamp, dateTimeFormat: item.dateTimeFormat)
|
||||
let (timeLayout, timeApply) = makeTimeLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: time, font: font, textColor: item.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - 20.0 - leftInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let (timeLayout, timeApply) = makeTimeLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: time, font: font, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - 20.0 - leftInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let makeTypeLayout = makeNodesLayout[index].1
|
||||
let type = stringForCallType(message: message, strings: item.strings)
|
||||
let (typeLayout, typeApply) = makeTypeLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: type, font: typeFont, textColor: item.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - 20.0 - leftInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
let type = stringForCallType(message: message, strings: item.presentationData.strings)
|
||||
let (typeLayout, typeApply) = makeTypeLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: type, font: typeFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - 20.0 - leftInset, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
nodesLayout.append((timeLayout, typeLayout))
|
||||
nodesApply.append((timeApply, typeApply))
|
||||
|
@ -254,11 +254,11 @@ private enum PeerReportControllerEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! PeerReportControllerArguments
|
||||
switch self {
|
||||
case let .text(theme, title, value):
|
||||
return ItemListMultilineInputItem(theme: theme, text: value, placeholder: title, maxLength: nil, sectionId: self.section, style: .blocks, textUpdated: { text in
|
||||
return ItemListMultilineInputItem(presentationData: presentationData, text: value, placeholder: title, maxLength: nil, sectionId: self.section, style: .blocks, textUpdated: { text in
|
||||
arguments.updateText(text)
|
||||
}, tag: PeerReportControllerEntryTag.text)
|
||||
}
|
||||
@ -338,11 +338,11 @@ private func peerReportController(context: AccountContext, subject: PeerReportSu
|
||||
})
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.ReportPeer_ReasonOther_Title), leftNavigationButton: ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: {
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.ReportPeer_ReasonOther_Title), leftNavigationButton: ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: {
|
||||
dismissImpl?()
|
||||
completion(false)
|
||||
}), rightNavigationButton: rightButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(entries: peerReportControllerEntries(presentationData: presentationData, state: state), style: .blocks, focusItemTag: PeerReportControllerEntryTag.text)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: peerReportControllerEntries(presentationData: presentationData, state: state), style: .blocks, focusItemTag: PeerReportControllerEntryTag.text)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -57,11 +57,11 @@ private enum PhoneLabelEntry: ItemListNodeEntry {
|
||||
return lhs.index < rhs.index
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! PhoneLabelArguments
|
||||
switch self {
|
||||
case let .label(_, theme, value, text, selected):
|
||||
return ItemListCheckboxItem(theme: theme, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: selected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.selectLabel(value)
|
||||
})
|
||||
}
|
||||
@ -120,8 +120,8 @@ public func phoneLabelController(context: AccountContext, currentLabel: String,
|
||||
arguments.complete()
|
||||
})
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.PhoneLabel_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(entries: phoneLabelEntries(presentationData: presentationData, state: state), style: .blocks)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.PhoneLabel_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: phoneLabelEntries(presentationData: presentationData, state: state), style: .blocks)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -393,11 +393,11 @@ private enum UserInfoEntry: ItemListNodeEntry {
|
||||
return lhs.sortIndex < rhs.sortIndex
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! UserInfoControllerArguments
|
||||
switch self {
|
||||
case let .info(theme, strings, dateTimeFormat, peer, presence, cachedData, state, displayCall):
|
||||
return ItemListAvatarAndNameInfoItem(account: arguments.account, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, mode: .generic, peer: peer, presence: presence, cachedData: cachedData, state: state, sectionId: self.section, style: .plain, editingNameUpdated: { editingName in
|
||||
return ItemListAvatarAndNameInfoItem(account: arguments.account, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .generic, peer: peer, presence: presence, cachedData: cachedData, state: state, sectionId: self.section, style: .plain, editingNameUpdated: { editingName in
|
||||
arguments.updateEditingName(editingName)
|
||||
}, avatarTapped: {
|
||||
arguments.tapAvatarAction()
|
||||
@ -405,63 +405,63 @@ private enum UserInfoEntry: ItemListNodeEntry {
|
||||
arguments.call()
|
||||
} : nil)
|
||||
case let .calls(theme, strings, dateTimeFormat, messages):
|
||||
return ItemListCallListItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, messages: messages, sectionId: self.section, style: .plain)
|
||||
return ItemListCallListItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, messages: messages, sectionId: self.section, style: .plain)
|
||||
case let .about(theme, peer, text, value):
|
||||
var enabledEntityTypes: EnabledEntityTypes = []
|
||||
if let peer = peer as? TelegramUser, let _ = peer.botInfo {
|
||||
enabledEntityTypes = [.url, .mention, .hashtag]
|
||||
}
|
||||
return ItemListTextWithLabelItem(theme: theme, label: text, text: foldMultipleLineBreaks(value), enabledEntityTypes: enabledEntityTypes, multiline: true, sectionId: self.section, action: nil, longTapAction: {
|
||||
return ItemListTextWithLabelItem(presentationData: presentationData, label: text, text: foldMultipleLineBreaks(value), enabledEntityTypes: enabledEntityTypes, multiline: true, sectionId: self.section, action: nil, longTapAction: {
|
||||
arguments.displayAboutContextMenu(value)
|
||||
}, linkItemAction: { action, itemLink in
|
||||
arguments.aboutLinkAction(action, itemLink)
|
||||
}, tag: UserInfoEntryTag.about)
|
||||
case let .phoneNumber(theme, _, label, value, isMain):
|
||||
return ItemListTextWithLabelItem(theme: theme, label: label, text: value, textColor: isMain ? .highlighted : .accent, enabledEntityTypes: [], multiline: false, sectionId: self.section, action: {
|
||||
return ItemListTextWithLabelItem(presentationData: presentationData, label: label, text: value, textColor: isMain ? .highlighted : .accent, enabledEntityTypes: [], multiline: false, sectionId: self.section, action: {
|
||||
arguments.openCallMenu(value)
|
||||
}, longTapAction: {
|
||||
arguments.displayCopyContextMenu(.phoneNumber, value)
|
||||
}, tag: UserInfoEntryTag.phoneNumber)
|
||||
case let .requestPhoneNumber(theme, label, value):
|
||||
return ItemListTextWithLabelItem(theme: theme, label: label, text: value, textColor: .accent, enabledEntityTypes: [], multiline: false, sectionId: self.section, action: {
|
||||
return ItemListTextWithLabelItem(presentationData: presentationData, label: label, text: value, textColor: .accent, enabledEntityTypes: [], multiline: false, sectionId: self.section, action: {
|
||||
arguments.requestPhoneNumber()
|
||||
})
|
||||
case let .userName(theme, text, value):
|
||||
return ItemListTextWithLabelItem(theme: theme, label: text, text: "@\(value)", textColor: .accent, enabledEntityTypes: [], multiline: false, sectionId: self.section, action: {
|
||||
return ItemListTextWithLabelItem(presentationData: presentationData, label: text, text: "@\(value)", textColor: .accent, enabledEntityTypes: [], multiline: false, sectionId: self.section, action: {
|
||||
arguments.displayUsernameContextMenu("@\(value)")
|
||||
}, longTapAction: {
|
||||
arguments.displayCopyContextMenu(.username, "@\(value)")
|
||||
}, tag: UserInfoEntryTag.username)
|
||||
case let .sendMessage(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
arguments.openChat()
|
||||
})
|
||||
case let .addContact(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
arguments.addContact()
|
||||
})
|
||||
case let .shareContact(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
arguments.shareContact()
|
||||
})
|
||||
case let .shareMyContact(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
arguments.shareMyContact()
|
||||
})
|
||||
case let .startSecretChat(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
arguments.startSecretChat()
|
||||
})
|
||||
case let .sharedMedia(theme, text):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: self.section, style: .plain, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: "", sectionId: self.section, style: .plain, action: {
|
||||
arguments.openSharedMedia()
|
||||
})
|
||||
case let .notifications(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .plain, action: {
|
||||
arguments.changeNotificationMuteSettings()
|
||||
})
|
||||
case let .groupsInCommon(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .plain, action: {
|
||||
arguments.openGroupsInCommon()
|
||||
})
|
||||
case let .secretEncryptionKey(theme, text, fingerprint):
|
||||
@ -469,31 +469,31 @@ private enum UserInfoEntry: ItemListNodeEntry {
|
||||
arguments.openEncryptionKey(fingerprint)
|
||||
})
|
||||
case let .botAddToGroup(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
arguments.addBotToGroup()
|
||||
})
|
||||
case let .botShare(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
arguments.shareBot()
|
||||
})
|
||||
case let .botSettings(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
arguments.botSettings()
|
||||
})
|
||||
case let .botHelp(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
arguments.botHelp()
|
||||
})
|
||||
case let .botPrivacy(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
arguments.botPrivacy()
|
||||
})
|
||||
case let .botReport(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
arguments.report()
|
||||
})
|
||||
case let .block(theme, text, action):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .destructive, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .destructive, alignment: .natural, sectionId: self.section, style: .plain, action: {
|
||||
switch action {
|
||||
case .block:
|
||||
arguments.updatePeerBlocked(true)
|
||||
@ -1304,8 +1304,8 @@ public func userInfoController(context: AccountContext, peerId: PeerId, mode: Pe
|
||||
})
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.UserInfo_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: nil)
|
||||
let listState = ItemListNodeState(entries: userInfoEntries(account: context.account, presentationData: presentationData, view: view.0, cachedPeerData: view.1, deviceContacts: deviceContacts, mode: mode, state: state, peerChatState: (combinedView.views[.peerChatState(peerId: peerId)] as? PeerChatStateView)?.chatState, globalNotificationSettings: globalNotificationSettings), style: .plain)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.UserInfo_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: nil)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: userInfoEntries(account: context.account, presentationData: presentationData, view: view.0, cachedPeerData: view.1, deviceContacts: deviceContacts, mode: mode, state: state, peerChatState: (combinedView.views[.peerChatState(peerId: peerId)] as? PeerChatStateView)?.chatState, globalNotificationSettings: globalNotificationSettings), style: .plain)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN
|
||||
updatedTheme = item.theme
|
||||
}
|
||||
|
||||
let controlSizeAndApply = editableControlLayout(44.0, item.theme, false)
|
||||
let controlSizeAndApply = editableControlLayout(item.theme, false)
|
||||
|
||||
let textColor = item.theme.list.itemAccentColor
|
||||
|
||||
@ -261,8 +261,8 @@ class UserInfoEditingPhoneItemNode: ItemListRevealOptionsItemNode, ItemListItemN
|
||||
|
||||
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: leftInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - leftInset, height: separatorHeight))
|
||||
|
||||
let _ = controlSizeAndApply.1()
|
||||
let editableControlFrame = CGRect(origin: CGPoint(x: params.leftInset + 4.0 + revealOffset, y: 0.0), size: controlSizeAndApply.0)
|
||||
let _ = controlSizeAndApply.1(layout.contentSize.height)
|
||||
let editableControlFrame = CGRect(origin: CGPoint(x: params.leftInset + 4.0 + revealOffset, y: 0.0), size: CGSize(width: controlSizeAndApply.0, height: layout.contentSize.height))
|
||||
strongSelf.editableControlNode.frame = editableControlFrame
|
||||
|
||||
let labelFrame = CGRect(origin: CGPoint(x: revealOffset + leftInset + 30.0, y: 12.0), size: labelLayout.size)
|
||||
|
@ -190,23 +190,23 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
|
||||
return result
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! PeersNearbyControllerArguments
|
||||
switch self {
|
||||
case let .header(theme, text):
|
||||
return PeersNearbyHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
case let .usersHeader(theme, text, loading):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, activityIndicator: loading ? .left : .none, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, activityIndicator: loading ? .left : .none, sectionId: self.section)
|
||||
case let .empty(theme, text):
|
||||
return ItemListPlaceholderItem(theme: theme, text: text, sectionId: self.section, style: .blocks)
|
||||
case let .user(_, theme, strings, dateTimeFormat, nameDisplayOrder, peer):
|
||||
return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.context.account, peer: peer.peer.0, aliasHandling: .standard, nameColor: .primary, nameStyle: .distinctBold, presence: nil, text: .text(strings.Map_DistanceAway(stringForDistance(peer.distance)).0), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: {
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.context.account, peer: peer.peer.0, aliasHandling: .standard, nameColor: .primary, nameStyle: .distinctBold, presence: nil, text: .text(strings.Map_DistanceAway(stringForDistance(peer.distance)).0), label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: {
|
||||
arguments.openChat(peer.peer.0)
|
||||
}, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, toggleUpdated: nil, hasTopGroupInset: false, tag: nil)
|
||||
case let .groupsHeader(theme, text, loading):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, activityIndicator: loading ? .left : .none, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, activityIndicator: loading ? .left : .none, sectionId: self.section)
|
||||
case let .createGroup(theme, title, latitude, longitude, address):
|
||||
return ItemListPeerActionItem(theme: theme, icon: PresentationResourcesItemList.createGroupIcon(theme), title: title, alwaysPlain: false, sectionId: self.section, editing: false, action: {
|
||||
return ItemListPeerActionItem(presentationData: presentationData, icon: PresentationResourcesItemList.createGroupIcon(theme), title: title, alwaysPlain: false, sectionId: self.section, editing: false, action: {
|
||||
if let latitude = latitude, let longitude = longitude {
|
||||
arguments.openCreateGroup(latitude, longitude, address)
|
||||
}
|
||||
@ -218,11 +218,11 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
text = .text(strings.Map_DistanceAway(stringForDistance(peer.distance)).0)
|
||||
}
|
||||
return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.context.account, peer: peer.peer.0, aliasHandling: .standard, nameColor: .primary, nameStyle: .distinctBold, presence: nil, text: text, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: {
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.context.account, peer: peer.peer.0, aliasHandling: .standard, nameColor: .primary, nameStyle: .distinctBold, presence: nil, text: text, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: {
|
||||
arguments.openChat(peer.peer.0)
|
||||
}, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, toggleUpdated: nil, hasTopGroupInset: false, tag: nil)
|
||||
case let .channelsHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .channel(_, theme, strings, dateTimeFormat, nameDisplayOrder, peer):
|
||||
var text: ItemListPeerItemText
|
||||
if let cachedData = peer.peer.1 as? CachedChannelData, let memberCount = cachedData.participantsSummary.memberCount {
|
||||
@ -230,7 +230,7 @@ private enum PeersNearbyEntry: ItemListNodeEntry {
|
||||
} else {
|
||||
text = .text(strings.Map_DistanceAway(stringForDistance(peer.distance)).0)
|
||||
}
|
||||
return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.context.account, peer: peer.peer.0, aliasHandling: .standard, nameColor: .primary, nameStyle: .distinctBold, presence: nil, text: text, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: {
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.context.account, peer: peer.peer.0, aliasHandling: .standard, nameColor: .primary, nameStyle: .distinctBold, presence: nil, text: text, label: .none, editing: ItemListPeerItemEditing(editable: false, editing: false, revealed: false), revealOptions: nil, switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: {
|
||||
arguments.openChat(peer.peer.0)
|
||||
}, setPeerIdWithRevealedOptions: { _, _ in }, removePeer: { _ in }, toggleUpdated: nil, hasTopGroupInset: false, tag: nil)
|
||||
}
|
||||
@ -425,8 +425,8 @@ public func peersNearbyController(context: AccountContext) -> ViewController {
|
||||
crossfade = true
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.PeopleNearby_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
let listState = ItemListNodeState(entries: peersNearbyControllerEntries(data: data, presentationData: presentationData, displayLoading: displayLoading), style: .blocks, emptyStateItem: nil, crossfadeState: crossfade, animateChanges: !crossfade)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.PeopleNearby_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: peersNearbyControllerEntries(data: data, presentationData: presentationData, displayLoading: displayLoading), style: .blocks, emptyStateItem: nil, crossfadeState: crossfade, animateChanges: !crossfade)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -286,6 +286,20 @@ final class ChatListIndexTable: Table {
|
||||
alteredPeerIds.insert(peerId)
|
||||
}
|
||||
|
||||
var additionalAlteredPeerIds = Set<PeerId>()
|
||||
for peerId in alteredPeerIds {
|
||||
guard let peer = postbox.peerTable.get(peerId) else {
|
||||
continue
|
||||
}
|
||||
if let associatedPeerId = peer.associatedPeerId {
|
||||
additionalAlteredPeerIds.insert(associatedPeerId)
|
||||
}
|
||||
if let reverseAssociatedPeerId = postbox.reverseAssociatedPeerTable.get(peerId: peerId).first {
|
||||
additionalAlteredPeerIds.insert(reverseAssociatedPeerId)
|
||||
}
|
||||
}
|
||||
alteredPeerIds.formUnion(additionalAlteredPeerIds)
|
||||
|
||||
func alterTags(_ totalUnreadState: inout ChatListTotalUnreadState, _ peerId: PeerId, _ tag: PeerSummaryCounterTags, _ f: (ChatListTotalUnreadCounters, ChatListTotalUnreadCounters) -> (ChatListTotalUnreadCounters, ChatListTotalUnreadCounters)) {
|
||||
if totalUnreadState.absoluteCounters[tag] == nil {
|
||||
totalUnreadState.absoluteCounters[tag] = ChatListTotalUnreadCounters(messageCount: 0, chatCount: 0)
|
||||
@ -404,10 +418,10 @@ final class ChatListIndexTable: Table {
|
||||
var initialFilteredStates: CombinedPeerReadState = initialStates
|
||||
var currentFilteredStates: CombinedPeerReadState = currentStates
|
||||
|
||||
if transactionParticipationInTotalUnreadCountUpdates.added.contains(peerId) {
|
||||
if transactionParticipationInTotalUnreadCountUpdates.added.contains(peerId) || transactionParticipationInTotalUnreadCountUpdates.added.contains(notificationPeerId) {
|
||||
initialFilteredValue = (0, false, false)
|
||||
initialFilteredStates = CombinedPeerReadState(states: [])
|
||||
} else if transactionParticipationInTotalUnreadCountUpdates.removed.contains(peerId) {
|
||||
} else if transactionParticipationInTotalUnreadCountUpdates.removed.contains(peerId) || transactionParticipationInTotalUnreadCountUpdates.removed.contains(notificationPeerId) {
|
||||
currentFilteredValue = (0, false, false)
|
||||
currentFilteredStates = CombinedPeerReadState(states: [])
|
||||
} else {
|
||||
|
@ -5,9 +5,9 @@ import AccountContext
|
||||
import SwiftSignalKit
|
||||
|
||||
public func textAlertController(context: AccountContext, title: String?, text: String, actions: [TextAlertAction], actionLayout: TextAlertContentActionLayout = .horizontal, allowInputInset: Bool = true) -> AlertController {
|
||||
return textAlertController(alertContext: AlertControllerContext(theme: AlertControllerTheme(presentationTheme: context.sharedContext.currentPresentationData.with({ $0 }).theme), themeSignal: context.sharedContext.presentationData |> map { presentationData in AlertControllerTheme(presentationTheme: presentationData.theme) }), title: title, text: text, actions: actions, actionLayout: actionLayout, allowInputInset: allowInputInset)
|
||||
return textAlertController(alertContext: AlertControllerContext(theme: AlertControllerTheme(presentationData: context.sharedContext.currentPresentationData.with { $0 }), themeSignal: context.sharedContext.presentationData |> map { presentationData in AlertControllerTheme(presentationData: presentationData) }), title: title, text: text, actions: actions, actionLayout: actionLayout, allowInputInset: allowInputInset)
|
||||
}
|
||||
|
||||
public func richTextAlertController(context: AccountContext, title: NSAttributedString?, text: NSAttributedString, actions: [TextAlertAction], actionLayout: TextAlertContentActionLayout = .horizontal, allowInputInset: Bool = true, dismissAutomatically: Bool = true) -> AlertController {
|
||||
return richTextAlertController(alertContext: AlertControllerContext(theme: AlertControllerTheme(presentationTheme: context.sharedContext.currentPresentationData.with({ $0 }).theme), themeSignal: context.sharedContext.presentationData |> map { presentationData in AlertControllerTheme(presentationTheme: presentationData.theme) }), title: title, text: text, actions: actions, actionLayout: actionLayout, allowInputInset: allowInputInset, dismissAutomatically: dismissAutomatically)
|
||||
return richTextAlertController(alertContext: AlertControllerContext(theme: AlertControllerTheme(presentationData: context.sharedContext.currentPresentationData.with { $0 }), themeSignal: context.sharedContext.presentationData |> map { presentationData in AlertControllerTheme(presentationData: presentationData) }), title: title, text: text, actions: actions, actionLayout: actionLayout, allowInputInset: allowInputInset, dismissAutomatically: dismissAutomatically)
|
||||
}
|
||||
|
@ -13,6 +13,6 @@ public extension ItemListController {
|
||||
|
||||
convenience init<ItemGenerationArguments>(sharedContext: SharedAccountContext, state: Signal<(ItemListControllerState, (ItemListNodeState, ItemGenerationArguments)), NoError>, tabBarItem: Signal<ItemListControllerTabBarItem, NoError>? = nil) {
|
||||
let presentationData = sharedContext.currentPresentationData.with { $0 }
|
||||
self.init(theme: presentationData.theme, strings: presentationData.strings, updatedPresentationData: sharedContext.presentationData |> map { ($0.theme, $0.strings) }, state: state, tabBarItem: tabBarItem)
|
||||
self.init(presentationData: ItemListPresentationData(presentationData), updatedPresentationData: sharedContext.presentationData |> map(ItemListPresentationData.init(_:)), state: state, tabBarItem: tabBarItem)
|
||||
}
|
||||
}
|
||||
|
@ -86,17 +86,17 @@ private enum ChangePhoneNumberCodeEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! ChangePhoneNumberCodeControllerArguments
|
||||
switch self {
|
||||
case let .codeEntry(theme, strings, title, text):
|
||||
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: title, textColor: .black), text: text, placeholder: "", type: .number, spacing: 10.0, tag: ChangePhoneNumberCodeTag.input, sectionId: self.section, textUpdated: { updatedText in
|
||||
return ItemListSingleLineInputItem(presentationData: presentationData, title: NSAttributedString(string: title, textColor: .black), text: text, placeholder: "", type: .number, spacing: 10.0, tag: ChangePhoneNumberCodeTag.input, sectionId: self.section, textUpdated: { updatedText in
|
||||
arguments.updateEntryText(updatedText)
|
||||
}, action: {
|
||||
arguments.next()
|
||||
})
|
||||
case let .codeInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -184,7 +184,7 @@ private final class ChangePhoneNumberCodeControllerImpl: ItemListController, Cha
|
||||
self.applyCodeImpl = applyCodeImpl
|
||||
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
super.init(theme: presentationData.theme, strings: presentationData.strings, updatedPresentationData: context.sharedContext.presentationData |> map { ($0.theme, $0.strings) }, state: state, tabBarItem: nil)
|
||||
super.init(presentationData: ItemListPresentationData(presentationData), updatedPresentationData: context.sharedContext.presentationData |> map(ItemListPresentationData.init(_:)), state: state, tabBarItem: nil)
|
||||
}
|
||||
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
@ -313,8 +313,8 @@ func changePhoneNumberCodeController(context: AccountContext, phoneNumber: Strin
|
||||
})
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(formatPhoneNumber(phoneNumber)), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: changePhoneNumberCodeControllerEntries(presentationData: presentationData, state: state, codeData: data, timeout: timeout, strings: presentationData.strings), style: .blocks, focusItemTag: ChangePhoneNumberCodeTag.input, emptyStateItem: nil, animateChanges: false)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(formatPhoneNumber(phoneNumber)), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: changePhoneNumberCodeControllerEntries(presentationData: presentationData, state: state, codeData: data, timeout: timeout, strings: presentationData.strings), style: .blocks, focusItemTag: ChangePhoneNumberCodeTag.input, emptyStateItem: nil, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
} |> afterDisposed {
|
||||
|
@ -142,35 +142,35 @@ private enum AutodownloadMediaCategoryEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! AutodownloadMediaConnectionTypeControllerArguments
|
||||
switch self {
|
||||
case let .master(theme, text, value):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.toggleMaster(value)
|
||||
})
|
||||
case let .dataUsageHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .dataUsageItem(theme, strings, value, customPosition, enabled):
|
||||
return AutodownloadDataUsagePickerItem(theme: theme, strings: strings, value: value, customPosition: customPosition, enabled: enabled, sectionId: self.section, updated: { preset in
|
||||
arguments.changePreset(preset)
|
||||
})
|
||||
case let .typesHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .photos(theme, text, value, enabled):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, enabled: enabled, label: value, labelStyle: .detailText, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, enabled: enabled, label: value, labelStyle: .detailText, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.customize(.photo)
|
||||
})
|
||||
case let .videos(theme, text, value, enabled):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, enabled: enabled, label: value, labelStyle: .detailText, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, enabled: enabled, label: value, labelStyle: .detailText, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.customize(.video)
|
||||
})
|
||||
case let .files(theme, text, value, enabled):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, enabled: enabled, label: value, labelStyle: .detailText, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, enabled: enabled, label: value, labelStyle: .detailText, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.customize(.file)
|
||||
})
|
||||
case let .voiceMessagesInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -345,8 +345,8 @@ func autodownloadMediaConnectionTypeController(context: AccountContext, connecti
|
||||
title = presentationData.strings.AutoDownloadSettings_WifiTitle
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: autodownloadMediaConnectionTypeControllerEntries(presentationData: presentationData, connectionType: connectionType, settings: automaticMediaDownloadSettings), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: autodownloadMediaConnectionTypeControllerEntries(presentationData: presentationData, connectionType: connectionType, settings: automaticMediaDownloadSettings), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -170,39 +170,39 @@ private enum AutodownloadMediaCategoryEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! AutodownloadMediaCategoryControllerArguments
|
||||
switch self {
|
||||
case let .peerHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .peerContacts(theme, text, value):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.togglePeer(.contact)
|
||||
})
|
||||
case let .peerOtherPrivate(theme, text, value):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.togglePeer(.otherPrivate)
|
||||
})
|
||||
case let .peerGroups(theme, text, value):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.togglePeer(.group)
|
||||
})
|
||||
case let .peerChannels(theme, text, value):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.togglePeer(.channel)
|
||||
})
|
||||
case let .sizeHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .sizeItem(theme, decimalSeparator, text, value):
|
||||
return AutodownloadSizeLimitItem(theme: theme, decimalSeparator: decimalSeparator, text: text, value: value, sectionId: self.section, updated: { value in
|
||||
arguments.adjustSize(value)
|
||||
})
|
||||
case let .sizePreload(theme, text, value, enabled):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value && enabled, enableInteractiveChanges: true, enabled: enabled, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value && enabled, enableInteractiveChanges: true, enabled: enabled, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.toggleVideoPreload()
|
||||
})
|
||||
case let .sizePreloadInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -427,8 +427,8 @@ func autodownloadMediaCategoryController(context: AccountContext, connectionType
|
||||
title = presentationData.strings.AutoDownloadSettings_DocumentsTitle
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: autodownloadMediaCategoryControllerEntries(presentationData: presentationData, connectionType: connectionType, category: category, settings: automaticMediaDownloadSettings), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: autodownloadMediaCategoryControllerEntries(presentationData: presentationData, connectionType: connectionType, category: category, settings: automaticMediaDownloadSettings), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -272,73 +272,73 @@ private enum DataAndStorageEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! DataAndStorageControllerArguments
|
||||
switch self {
|
||||
case let .storageUsage(theme, text):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: "", sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openStorageUsage()
|
||||
})
|
||||
case let .networkUsage(theme, text):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: "", sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openNetworkUsage()
|
||||
})
|
||||
case let .automaticDownloadHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .automaticDownloadCellular(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, labelStyle: .detailText, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, labelStyle: .detailText, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openAutomaticDownloadConnectionType(.cellular)
|
||||
})
|
||||
case let .automaticDownloadWifi(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, labelStyle: .detailText, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, labelStyle: .detailText, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openAutomaticDownloadConnectionType(.wifi)
|
||||
})
|
||||
case let .automaticDownloadReset(theme, text, enabled):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: enabled ? .generic : .disabled, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: enabled ? .generic : .disabled, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
if enabled {
|
||||
arguments.resetAutomaticDownload()
|
||||
}
|
||||
}, tag: DataAndStorageEntryTag.automaticDownloadReset)
|
||||
case let .autoplayHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .autoplayGifs(theme, text, value):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.toggleAutoplayGifs(value)
|
||||
}, tag: DataAndStorageEntryTag.autoplayGifs)
|
||||
case let .autoplayVideos(theme, text, value):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.toggleAutoplayVideos(value)
|
||||
}, tag: DataAndStorageEntryTag.autoplayVideos)
|
||||
case let .voiceCallsHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .useLessVoiceData(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openVoiceUseLessData()
|
||||
})
|
||||
case let .otherHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .saveIncomingPhotos(theme, text):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: "", sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: "", sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openSaveIncomingPhotos()
|
||||
})
|
||||
case let .saveEditedPhotos(theme, text, value):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.toggleSaveEditedPhotos(value)
|
||||
}, tag: DataAndStorageEntryTag.saveEditedPhotos)
|
||||
case let .openLinksIn(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openBrowserSelection()
|
||||
})
|
||||
case let .downloadInBackground(theme, text, value):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.toggleDownloadInBackground(value)
|
||||
}, tag: DataAndStorageEntryTag.downloadInBackground)
|
||||
case let .downloadInBackgroundInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .connectionHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .connectionProxy(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.openProxy()
|
||||
})
|
||||
}
|
||||
@ -600,8 +600,8 @@ func dataAndStorageController(context: AccountContext, focusOnItemTag: DataAndSt
|
||||
defaultWebBrowser = presentationData.strings.WebBrowser_InAppSafari
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.ChatSettings_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: dataAndStorageControllerEntries(state: state, data: dataAndStorageData, presentationData: presentationData, defaultWebBrowser: defaultWebBrowser), style: .blocks, ensureVisibleItemTag: focusOnItemTag, emptyStateItem: nil, animateChanges: false)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.ChatSettings_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: dataAndStorageControllerEntries(state: state, data: dataAndStorageData, presentationData: presentationData, defaultWebBrowser: defaultWebBrowser), style: .blocks, ensureVisibleItemTag: focusOnItemTag, emptyStateItem: nil, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
} |> afterDisposed {
|
||||
|
@ -255,51 +255,51 @@ private enum NetworkUsageStatsEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! NetworkUsageStatsControllerArguments
|
||||
switch self {
|
||||
case let .messagesHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .messagesSent(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
case let .messagesReceived(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
case let .imageHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .imageSent(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
case let .imageReceived(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
case let .videoHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .videoSent(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
case let .videoReceived(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
case let .audioHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .audioSent(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
case let .audioReceived(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
case let .fileHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .fileSent(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
case let .fileReceived(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
case let .callHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .callSent(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
case let .callReceived(theme, text, value):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, disclosureStyle: .none , action: nil)
|
||||
case let .reset(theme, section, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.resetStatistics(section)
|
||||
})
|
||||
case let .resetTimestamp(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -416,8 +416,8 @@ func networkUsageStatsController(context: AccountContext) -> ViewController {
|
||||
let signal = combineLatest(context.sharedContext.presentationData, section.get(), stats.get()) |> deliverOnMainQueue
|
||||
|> map { presentationData, section, stats -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .sectionControl([presentationData.strings.NetworkUsageSettings_Cellular, presentationData.strings.NetworkUsageSettings_Wifi], 0), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: networkUsageStatsControllerEntries(presentationData: presentationData, section: section, stats: stats), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .sectionControl([presentationData.strings.NetworkUsageSettings_Cellular, presentationData.strings.NetworkUsageSettings_Wifi], 0), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: networkUsageStatsControllerEntries(presentationData: presentationData, section: section, stats: stats), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -202,11 +202,11 @@ private enum ProxySettingsControllerEntry: ItemListNodeEntry {
|
||||
}
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! ProxySettingsControllerArguments
|
||||
switch self {
|
||||
case let .enabled(theme, text, value, createsNew):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, enableInteractiveChanges: !createsNew, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enableInteractiveChanges: !createsNew, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
if createsNew {
|
||||
arguments.addNewServer()
|
||||
} else {
|
||||
@ -214,7 +214,7 @@ private enum ProxySettingsControllerEntry: ItemListNodeEntry {
|
||||
}
|
||||
})
|
||||
case let .serversHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .addServer(theme, text, _):
|
||||
return ProxySettingsActionItem(theme: theme, title: text, icon: .add, sectionId: self.section, editing: false, action: {
|
||||
arguments.addNewServer()
|
||||
@ -234,11 +234,11 @@ private enum ProxySettingsControllerEntry: ItemListNodeEntry {
|
||||
arguments.shareProxyList()
|
||||
})
|
||||
case let .useForCalls(theme, text, value):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.toggleUseForCalls(value)
|
||||
})
|
||||
case let .useForCallsInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -315,10 +315,10 @@ public enum ProxySettingsControllerMode {
|
||||
|
||||
public func proxySettingsController(context: AccountContext, mode: ProxySettingsControllerMode = .default) -> ViewController {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
return proxySettingsController(accountManager: context.sharedContext.accountManager, context: context, postbox: context.account.postbox, network: context.account.network, mode: mode, theme: presentationData.theme, strings: presentationData.strings, updatedPresentationData: context.sharedContext.presentationData |> map { ($0.theme, $0.strings) })
|
||||
return proxySettingsController(accountManager: context.sharedContext.accountManager, context: context, postbox: context.account.postbox, network: context.account.network, mode: mode, presentationData: presentationData, updatedPresentationData: context.sharedContext.presentationData)
|
||||
}
|
||||
|
||||
public func proxySettingsController(accountManager: AccountManager, context: AccountContext? = nil, postbox: Postbox, network: Network, mode: ProxySettingsControllerMode, theme: PresentationTheme, strings: PresentationStrings, updatedPresentationData: Signal<(theme: PresentationTheme, strings: PresentationStrings), NoError>) -> ViewController {
|
||||
public func proxySettingsController(accountManager: AccountManager, context: AccountContext? = nil, postbox: Postbox, network: Network, mode: ProxySettingsControllerMode, presentationData: PresentationData, updatedPresentationData: Signal<PresentationData, NoError>) -> ViewController {
|
||||
var presentControllerImpl: ((ViewController, Any?) -> Void)?
|
||||
var pushControllerImpl: ((ViewController) -> Void)?
|
||||
var dismissImpl: (() -> Void)?
|
||||
@ -347,7 +347,7 @@ public func proxySettingsController(accountManager: AccountManager, context: Acc
|
||||
return current
|
||||
}).start()
|
||||
}, addNewServer: {
|
||||
pushControllerImpl?(proxyServerSettingsController(theme: theme, strings: strings, updatedPresentationData: updatedPresentationData, accountManager: accountManager, postbox: postbox, network: network, currentSettings: nil))
|
||||
pushControllerImpl?(proxyServerSettingsController(presentationData: presentationData, updatedPresentationData: updatedPresentationData, accountManager: accountManager, postbox: postbox, network: network, currentSettings: nil))
|
||||
}, activateServer: { server in
|
||||
let _ = updateProxySettingsInteractively(accountManager: accountManager, { current in
|
||||
var current = current
|
||||
@ -360,7 +360,7 @@ public func proxySettingsController(accountManager: AccountManager, context: Acc
|
||||
return current
|
||||
}).start()
|
||||
}, editServer: { server in
|
||||
pushControllerImpl?(proxyServerSettingsController(theme: theme, strings: strings, updatedPresentationData: updatedPresentationData, accountManager: accountManager, postbox: postbox, network: network, currentSettings: server))
|
||||
pushControllerImpl?(proxyServerSettingsController(presentationData: presentationData, updatedPresentationData: updatedPresentationData, accountManager: accountManager, postbox: postbox, network: network, currentSettings: server))
|
||||
}, removeServer: { server in
|
||||
let _ = updateProxySettingsInteractively(accountManager: accountManager, { current in
|
||||
var current = current
|
||||
@ -407,10 +407,10 @@ public func proxySettingsController(accountManager: AccountManager, context: Acc
|
||||
})
|
||||
|
||||
let signal = combineLatest(updatedPresentationData, statePromise.get(), proxySettings.get(), statusesContext.statuses(), network.connectionStatus)
|
||||
|> map { themeAndStrings, state, proxySettings, statuses, connectionStatus -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||
|> map { presentationData, state, proxySettings, statuses, connectionStatus -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||
var leftNavigationButton: ItemListNavigationButton?
|
||||
if case .modal = mode {
|
||||
leftNavigationButton = ItemListNavigationButton(content: .text(themeAndStrings.strings.Common_Cancel), style: .regular, enabled: true, action: {
|
||||
leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: {
|
||||
dismissImpl?()
|
||||
})
|
||||
}
|
||||
@ -419,7 +419,7 @@ public func proxySettingsController(accountManager: AccountManager, context: Acc
|
||||
if proxySettings.servers.isEmpty {
|
||||
rightNavigationButton = nil
|
||||
} else if state.editing {
|
||||
rightNavigationButton = ItemListNavigationButton(content: .text(strings.Common_Done), style: .bold, enabled: true, action: {
|
||||
rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Done), style: .bold, enabled: true, action: {
|
||||
updateState { state in
|
||||
var state = state
|
||||
state.editing = false
|
||||
@ -427,7 +427,7 @@ public func proxySettingsController(accountManager: AccountManager, context: Acc
|
||||
}
|
||||
})
|
||||
} else {
|
||||
rightNavigationButton = ItemListNavigationButton(content: .text(strings.Common_Edit), style: .regular, enabled: true, action: {
|
||||
rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Edit), style: .regular, enabled: true, action: {
|
||||
updateState { state in
|
||||
var state = state
|
||||
state.editing = true
|
||||
@ -436,13 +436,13 @@ public func proxySettingsController(accountManager: AccountManager, context: Acc
|
||||
})
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: themeAndStrings.0, title: .text(themeAndStrings.1.SocksProxySetup_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: themeAndStrings.1.Common_Back))
|
||||
let listState = ItemListNodeState(entries: proxySettingsControllerEntries(theme: themeAndStrings.0, strings: themeAndStrings.1, state: state, proxySettings: proxySettings, statuses: statuses, connectionStatus: connectionStatus), style: .blocks)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.SocksProxySetup_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: proxySettingsControllerEntries(theme: presentationData.theme, strings: presentationData.strings, state: state, proxySettings: proxySettings, statuses: statuses, connectionStatus: connectionStatus), style: .blocks)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
||||
let controller = ItemListController(theme: theme, strings: strings, updatedPresentationData: updatedPresentationData, state: signal, tabBarItem: nil)
|
||||
let controller = ItemListController(presentationData: ItemListPresentationData(presentationData), updatedPresentationData: updatedPresentationData |> map(ItemListPresentationData.init(_:)), state: signal, tabBarItem: nil)
|
||||
controller.navigationPresentation = .modal
|
||||
presentControllerImpl = { [weak controller] c, a in
|
||||
controller?.present(c, in: .window(.root), with: a)
|
||||
|
@ -25,27 +25,27 @@ public final class ProxyServerActionSheetController: ActionSheetController {
|
||||
|
||||
convenience public init(context: AccountContext, server: ProxyServerSettings) {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
self.init(theme: presentationData.theme, strings: presentationData.strings, accountManager: context.sharedContext.accountManager, postbox: context.account.postbox, network: context.account.network, server: server, presentationData: context.sharedContext.presentationData)
|
||||
self.init(presentationData: presentationData, accountManager: context.sharedContext.accountManager, postbox: context.account.postbox, network: context.account.network, server: server, updatedPresentationData: context.sharedContext.presentationData)
|
||||
}
|
||||
|
||||
public init(theme: PresentationTheme, strings: PresentationStrings, accountManager: AccountManager, postbox: Postbox, network: Network, server: ProxyServerSettings, presentationData: Signal<PresentationData, NoError>?) {
|
||||
let sheetTheme = ActionSheetControllerTheme(presentationTheme: theme)
|
||||
public init(presentationData: PresentationData, accountManager: AccountManager, postbox: Postbox, network: Network, server: ProxyServerSettings, updatedPresentationData: Signal<PresentationData, NoError>?) {
|
||||
let sheetTheme = ActionSheetControllerTheme(presentationTheme: presentationData.theme)
|
||||
super.init(theme: sheetTheme)
|
||||
|
||||
self._ready.set(.single(true))
|
||||
|
||||
var items: [ActionSheetItem] = []
|
||||
if case .mtp = server.connection {
|
||||
items.append(ActionSheetTextItem(title: strings.SocksProxySetup_AdNoticeHelp))
|
||||
items.append(ActionSheetTextItem(title: presentationData.strings.SocksProxySetup_AdNoticeHelp))
|
||||
}
|
||||
items.append(ProxyServerInfoItem(strings: strings, network: network, server: server))
|
||||
items.append(ProxyServerActionItem(accountManager:accountManager, postbox: postbox, network: network, presentationTheme: theme, strings: strings, server: server, dismiss: { [weak self] success in
|
||||
items.append(ProxyServerInfoItem(strings: presentationData.strings, network: network, server: server))
|
||||
items.append(ProxyServerActionItem(accountManager:accountManager, postbox: postbox, network: network, presentationData: presentationData, server: server, dismiss: { [weak self] success in
|
||||
guard let strongSelf = self, !strongSelf.isDismissed else {
|
||||
return
|
||||
}
|
||||
strongSelf.isDismissed = true
|
||||
if success {
|
||||
strongSelf.present(OverlayStatusController(theme: theme, type: .shieldSuccess(strings.SocksProxySetup_ProxyEnabled, false)), in: .window(.root))
|
||||
strongSelf.present(OverlayStatusController(theme: presentationData.theme, type: .shieldSuccess(presentationData.strings.SocksProxySetup_ProxyEnabled, false)), in: .window(.root))
|
||||
}
|
||||
strongSelf.dismissAnimated()
|
||||
}, present: { [weak self] c, a in
|
||||
@ -54,14 +54,14 @@ public final class ProxyServerActionSheetController: ActionSheetController {
|
||||
self.setItemGroups([
|
||||
ActionSheetItemGroup(items: items),
|
||||
ActionSheetItemGroup(items: [
|
||||
ActionSheetButtonItem(title: strings.Common_Cancel, action: { [weak self] in
|
||||
ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { [weak self] in
|
||||
self?.dismissAnimated()
|
||||
})
|
||||
])
|
||||
])
|
||||
|
||||
if let presentationData = presentationData {
|
||||
self.presentationDisposable = presentationData.start(next: { [weak self] presentationData in
|
||||
if let updatedPresentationData = updatedPresentationData {
|
||||
self.presentationDisposable = updatedPresentationData.start(next: { [weak self] presentationData in
|
||||
if let strongSelf = self {
|
||||
strongSelf.theme = ActionSheetControllerTheme(presentationTheme: presentationData.theme)
|
||||
}
|
||||
@ -267,25 +267,23 @@ private final class ProxyServerActionItem: ActionSheetItem {
|
||||
private let accountManager: AccountManager
|
||||
private let postbox: Postbox
|
||||
private let network: Network
|
||||
private let presentationTheme: PresentationTheme
|
||||
private let strings: PresentationStrings
|
||||
private let presentationData: PresentationData
|
||||
private let server: ProxyServerSettings
|
||||
private let dismiss: (Bool) -> Void
|
||||
private let present: (ViewController, Any?) -> Void
|
||||
|
||||
init(accountManager: AccountManager, postbox: Postbox, network: Network, presentationTheme: PresentationTheme, strings: PresentationStrings, server: ProxyServerSettings, dismiss: @escaping (Bool) -> Void, present: @escaping (ViewController, Any?) -> Void) {
|
||||
init(accountManager: AccountManager, postbox: Postbox, network: Network, presentationData: PresentationData, server: ProxyServerSettings, dismiss: @escaping (Bool) -> Void, present: @escaping (ViewController, Any?) -> Void) {
|
||||
self.accountManager = accountManager
|
||||
self.postbox = postbox
|
||||
self.network = network
|
||||
self.presentationTheme = presentationTheme
|
||||
self.strings = strings
|
||||
self.presentationData = presentationData
|
||||
self.server = server
|
||||
self.dismiss = dismiss
|
||||
self.present = present
|
||||
}
|
||||
|
||||
func node(theme: ActionSheetControllerTheme) -> ActionSheetItemNode {
|
||||
return ProxyServerActionItemNode(accountManager: self.accountManager, postbox: self.postbox, network: self.network, presentationTheme: self.presentationTheme, theme: theme, strings: self.strings, server: self.server, dismiss: self.dismiss, present: self.present)
|
||||
return ProxyServerActionItemNode(accountManager: self.accountManager, postbox: self.postbox, network: self.network, presentationData: self.presentationData, theme: theme, server: self.server, dismiss: self.dismiss, present: self.present)
|
||||
}
|
||||
|
||||
func updateNode(_ node: ActionSheetItemNode) {
|
||||
@ -296,9 +294,8 @@ private final class ProxyServerActionItemNode: ActionSheetItemNode {
|
||||
private let accountManager: AccountManager
|
||||
private let postbox: Postbox
|
||||
private let network: Network
|
||||
private let presentationTheme: PresentationTheme
|
||||
private let presentationData: PresentationData
|
||||
private let theme: ActionSheetControllerTheme
|
||||
private let strings: PresentationStrings
|
||||
private let server: ProxyServerSettings
|
||||
private let dismiss: (Bool) -> Void
|
||||
private let present: (ViewController, Any?) -> Void
|
||||
@ -310,13 +307,12 @@ private final class ProxyServerActionItemNode: ActionSheetItemNode {
|
||||
private let disposable = MetaDisposable()
|
||||
private var revertSettings: ProxySettings?
|
||||
|
||||
init(accountManager: AccountManager, postbox: Postbox, network: Network, presentationTheme: PresentationTheme, theme: ActionSheetControllerTheme, strings: PresentationStrings, server: ProxyServerSettings, dismiss: @escaping (Bool) -> Void, present: @escaping (ViewController, Any?) -> Void) {
|
||||
init(accountManager: AccountManager, postbox: Postbox, network: Network, presentationData: PresentationData, theme: ActionSheetControllerTheme, server: ProxyServerSettings, dismiss: @escaping (Bool) -> Void, present: @escaping (ViewController, Any?) -> Void) {
|
||||
self.accountManager = accountManager
|
||||
self.postbox = postbox
|
||||
self.network = network
|
||||
self.theme = theme
|
||||
self.presentationTheme = presentationTheme
|
||||
self.strings = strings
|
||||
self.presentationData = presentationData
|
||||
self.server = server
|
||||
self.dismiss = dismiss
|
||||
self.present = present
|
||||
@ -324,7 +320,7 @@ private final class ProxyServerActionItemNode: ActionSheetItemNode {
|
||||
self.titleNode = ImmediateTextNode()
|
||||
self.titleNode.isUserInteractionEnabled = false
|
||||
self.titleNode.displaysAsynchronously = false
|
||||
self.titleNode.attributedText = NSAttributedString(string: strings.SocksProxySetup_ConnectAndSave, font: Font.regular(20.0), textColor: theme.controlAccentColor)
|
||||
self.titleNode.attributedText = NSAttributedString(string: presentationData.strings.SocksProxySetup_ConnectAndSave, font: Font.regular(20.0), textColor: theme.controlAccentColor)
|
||||
|
||||
self.activityIndicator = ActivityIndicator(type: .custom(theme.controlAccentColor, 22.0, 1.5, false))
|
||||
self.activityIndicator.isHidden = true
|
||||
@ -401,7 +397,7 @@ private final class ProxyServerActionItemNode: ActionSheetItemNode {
|
||||
if let strongSelf = self {
|
||||
strongSelf.revertSettings = previousSettings
|
||||
strongSelf.buttonNode.isUserInteractionEnabled = false
|
||||
strongSelf.titleNode.attributedText = NSAttributedString(string: strongSelf.strings.SocksProxySetup_Connecting, font: Font.regular(20.0), textColor: strongSelf.theme.primaryTextColor)
|
||||
strongSelf.titleNode.attributedText = NSAttributedString(string: strongSelf.presentationData.strings.SocksProxySetup_Connecting, font: Font.regular(20.0), textColor: strongSelf.theme.primaryTextColor)
|
||||
strongSelf.activityIndicator.isHidden = false
|
||||
strongSelf.setNeedsLayout()
|
||||
|
||||
@ -433,11 +429,11 @@ private final class ProxyServerActionItemNode: ActionSheetItemNode {
|
||||
let _ = updateProxySettingsInteractively(accountManager: strongSelf.accountManager, { _ in
|
||||
return previousSettings
|
||||
})
|
||||
strongSelf.titleNode.attributedText = NSAttributedString(string: strongSelf.strings.SocksProxySetup_ConnectAndSave, font: Font.regular(20.0), textColor: strongSelf.theme.controlAccentColor)
|
||||
strongSelf.titleNode.attributedText = NSAttributedString(string: strongSelf.presentationData.strings.SocksProxySetup_ConnectAndSave, font: Font.regular(20.0), textColor: strongSelf.theme.controlAccentColor)
|
||||
strongSelf.buttonNode.isUserInteractionEnabled = true
|
||||
strongSelf.setNeedsLayout()
|
||||
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationTheme: strongSelf.presentationTheme), title: nil, text: strongSelf.strings.SocksProxySetup_FailedToConnect, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.strings.Common_OK, action: {})]), nil)
|
||||
strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: nil, text: strongSelf.presentationData.strings.SocksProxySetup_FailedToConnect, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), nil)
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
@ -118,17 +118,17 @@ private enum ProxySettingsEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! proxyServerSettingsControllerArguments
|
||||
switch self {
|
||||
case let .usePasteboardSettings(theme, title):
|
||||
return ItemListActionItem(theme: theme, title: title, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: title, kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.usePasteboardSettings()
|
||||
})
|
||||
case let .usePasteboardInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .modeSocks5(theme, text, value):
|
||||
return ItemListCheckboxItem(theme: theme, title: text, style: .left, checked: value, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: value, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.updateState { state in
|
||||
var state = state
|
||||
state.mode = .socks5
|
||||
@ -136,7 +136,7 @@ private enum ProxySettingsEntry: ItemListNodeEntry {
|
||||
}
|
||||
})
|
||||
case let .modeMtp(theme, text, value):
|
||||
return ItemListCheckboxItem(theme: theme, title: text, style: .left, checked: value, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: value, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.updateState { state in
|
||||
var state = state
|
||||
state.mode = .mtp
|
||||
@ -144,9 +144,9 @@ private enum ProxySettingsEntry: ItemListNodeEntry {
|
||||
}
|
||||
})
|
||||
case let .connectionHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .connectionServer(theme, strings, placeholder, text):
|
||||
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(), text: text, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: false), sectionId: self.section, textUpdated: { value in
|
||||
return ItemListSingleLineInputItem(presentationData: presentationData, title: NSAttributedString(), text: text, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: false), sectionId: self.section, textUpdated: { value in
|
||||
arguments.updateState { current in
|
||||
var state = current
|
||||
state.host = value
|
||||
@ -154,7 +154,7 @@ private enum ProxySettingsEntry: ItemListNodeEntry {
|
||||
}
|
||||
}, action: {})
|
||||
case let .connectionPort(theme, strings, placeholder, text):
|
||||
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(), text: text, placeholder: placeholder, type: .number, sectionId: self.section, textUpdated: { value in
|
||||
return ItemListSingleLineInputItem(presentationData: presentationData, title: NSAttributedString(), text: text, placeholder: placeholder, type: .number, sectionId: self.section, textUpdated: { value in
|
||||
arguments.updateState { current in
|
||||
var state = current
|
||||
state.port = value
|
||||
@ -162,9 +162,9 @@ private enum ProxySettingsEntry: ItemListNodeEntry {
|
||||
}
|
||||
}, action: {})
|
||||
case let .credentialsHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .credentialsUsername(theme, strings, placeholder, text):
|
||||
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(), text: text, placeholder: placeholder, sectionId: self.section, textUpdated: { value in
|
||||
return ItemListSingleLineInputItem(presentationData: presentationData, title: NSAttributedString(), text: text, placeholder: placeholder, sectionId: self.section, textUpdated: { value in
|
||||
arguments.updateState { current in
|
||||
var state = current
|
||||
state.username = value
|
||||
@ -172,7 +172,7 @@ private enum ProxySettingsEntry: ItemListNodeEntry {
|
||||
}
|
||||
}, action: {})
|
||||
case let .credentialsPassword(theme, strings, placeholder, text):
|
||||
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(), text: text, placeholder: placeholder, type: .password, sectionId: self.section, textUpdated: { value in
|
||||
return ItemListSingleLineInputItem(presentationData: presentationData, title: NSAttributedString(), text: text, placeholder: placeholder, type: .password, sectionId: self.section, textUpdated: { value in
|
||||
arguments.updateState { current in
|
||||
var state = current
|
||||
state.password = value
|
||||
@ -180,7 +180,7 @@ private enum ProxySettingsEntry: ItemListNodeEntry {
|
||||
}
|
||||
}, action: {})
|
||||
case let .credentialsSecret(theme, strings, placeholder, text):
|
||||
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(), text: text, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: false), sectionId: self.section, textUpdated: { value in
|
||||
return ItemListSingleLineInputItem(presentationData: presentationData, title: NSAttributedString(), text: text, placeholder: placeholder, type: .regular(capitalization: false, autocorrection: false), sectionId: self.section, textUpdated: { value in
|
||||
arguments.updateState { current in
|
||||
var state = current
|
||||
state.secret = value
|
||||
@ -188,7 +188,7 @@ private enum ProxySettingsEntry: ItemListNodeEntry {
|
||||
}
|
||||
}, action: {})
|
||||
case let .share(theme, text, enabled):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: enabled ? .generic : .disabled, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: enabled ? .generic : .disabled, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.share()
|
||||
})
|
||||
}
|
||||
@ -225,7 +225,7 @@ private struct ProxyServerSettingsControllerState: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
private func proxyServerSettingsControllerEntries(presentationData: (theme: PresentationTheme, strings: PresentationStrings), state: ProxyServerSettingsControllerState, pasteboardSettings: ProxyServerSettings?) -> [ProxySettingsEntry] {
|
||||
private func proxyServerSettingsControllerEntries(presentationData: PresentationData, state: ProxyServerSettingsControllerState, pasteboardSettings: ProxyServerSettings?) -> [ProxySettingsEntry] {
|
||||
var entries: [ProxySettingsEntry] = []
|
||||
|
||||
if let _ = pasteboardSettings {
|
||||
@ -271,10 +271,10 @@ private func proxyServerSettings(with state: ProxyServerSettingsControllerState)
|
||||
|
||||
public func proxyServerSettingsController(context: AccountContext, currentSettings: ProxyServerSettings? = nil) -> ViewController {
|
||||
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
return proxyServerSettingsController(context: context, theme: presentationData.theme, strings: presentationData.strings, updatedPresentationData: context.sharedContext.presentationData |> map { ($0.theme, $0.strings) }, accountManager: context.sharedContext.accountManager, postbox: context.account.postbox, network: context.account.network, currentSettings: currentSettings)
|
||||
return proxyServerSettingsController(context: context, presentationData: presentationData, updatedPresentationData: context.sharedContext.presentationData, accountManager: context.sharedContext.accountManager, postbox: context.account.postbox, network: context.account.network, currentSettings: currentSettings)
|
||||
}
|
||||
|
||||
func proxyServerSettingsController(context: AccountContext? = nil, theme: PresentationTheme, strings: PresentationStrings, updatedPresentationData: Signal<(theme: PresentationTheme, strings: PresentationStrings), NoError>, accountManager: AccountManager, postbox: Postbox, network: Network, currentSettings: ProxyServerSettings?) -> ViewController {
|
||||
func proxyServerSettingsController(context: AccountContext? = nil, presentationData: PresentationData, updatedPresentationData: Signal<PresentationData, NoError>, accountManager: AccountManager, postbox: Postbox, network: Network, currentSettings: ProxyServerSettings?) -> ViewController {
|
||||
var currentMode: ProxyServerSettingsControllerMode = .socks5
|
||||
var currentUsername: String?
|
||||
var currentPassword: String?
|
||||
@ -366,13 +366,13 @@ func proxyServerSettingsController(context: AccountContext? = nil, theme: Presen
|
||||
}
|
||||
})
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.SocksProxySetup_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: proxyServerSettingsControllerEntries(presentationData: presentationData, state: state, pasteboardSettings: pasteboardSettings), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.SocksProxySetup_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: proxyServerSettingsControllerEntries(presentationData: presentationData, state: state, pasteboardSettings: pasteboardSettings), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
||||
let controller = ItemListController(theme: theme, strings: strings, updatedPresentationData: updatedPresentationData, state: signal, tabBarItem: nil)
|
||||
let controller = ItemListController(presentationData: ItemListPresentationData(presentationData), updatedPresentationData: updatedPresentationData |> map(ItemListPresentationData.init(_:)), state: signal, tabBarItem: nil)
|
||||
controller.navigationPresentation = .modal
|
||||
presentControllerImpl = { [weak controller] c, d in
|
||||
controller?.present(c, in: .window(.root), with: d)
|
||||
@ -389,7 +389,7 @@ func proxyServerSettingsController(context: AccountContext? = nil, theme: Presen
|
||||
let link = shareLink(for: server)
|
||||
controller?.view.endEditing(true)
|
||||
if #available(iOSApplicationExtension 9.0, iOS 9.0, *) {
|
||||
let controller = ShareProxyServerActionSheetController(theme: theme, strings: strings, updatedPresentationData: updatedPresentationData, link: link)
|
||||
let controller = ShareProxyServerActionSheetController(presentationData: presentationData, updatedPresentationData: updatedPresentationData, link: link)
|
||||
presentControllerImpl?(controller, nil)
|
||||
} else if let context = context {
|
||||
let controller = ShareController(context: context, subject: .url(link), preferredAction: .default, showInChat: nil, externalShare: true, immediateExternalShare: true, switchableAccounts: [])
|
||||
|
@ -240,20 +240,20 @@ private final class ProxySettingsServerItemNode: ItemListRevealOptionsItemNode {
|
||||
titleAttributedString.append(NSAttributedString(string: ":\(item.server.port)", font: titleFont, textColor: item.theme.list.itemSecondaryTextColor))
|
||||
let statusAttributedString = NSAttributedString(string: item.label, font: statusFont, textColor: item.labelAccent ? item.theme.list.itemAccentColor : item.theme.list.itemSecondaryTextColor)
|
||||
|
||||
var editableControlSizeAndApply: (CGSize, () -> ItemListEditableControlNode)?
|
||||
var reorderControlSizeAndApply: (CGSize, (Bool) -> ItemListEditableReorderControlNode)?
|
||||
var editableControlSizeAndApply: (CGFloat, (CGFloat) -> ItemListEditableControlNode)?
|
||||
var reorderControlSizeAndApply: (CGFloat, (CGFloat, Bool) -> ItemListEditableReorderControlNode)?
|
||||
|
||||
let editingOffset: CGFloat
|
||||
var reorderInset: CGFloat = 0.0
|
||||
|
||||
if item.editing.editing {
|
||||
let sizeAndApply = editableControlLayout(64.0, item.theme, false)
|
||||
let sizeAndApply = editableControlLayout(item.theme, false)
|
||||
editableControlSizeAndApply = sizeAndApply
|
||||
editingOffset = sizeAndApply.0.width
|
||||
editingOffset = sizeAndApply.0
|
||||
|
||||
let reorderSizeAndApply = reorderControlLayout(65.0, item.theme)
|
||||
let reorderSizeAndApply = reorderControlLayout(item.theme)
|
||||
reorderControlSizeAndApply = reorderSizeAndApply
|
||||
reorderInset = reorderSizeAndApply.0.width
|
||||
reorderInset = reorderSizeAndApply.0
|
||||
} else {
|
||||
editingOffset = 0.0
|
||||
}
|
||||
@ -310,9 +310,9 @@ private final class ProxySettingsServerItemNode: ItemListRevealOptionsItemNode {
|
||||
}
|
||||
|
||||
if let editableControlSizeAndApply = editableControlSizeAndApply {
|
||||
let editableControlFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset, y: 0.0), size: editableControlSizeAndApply.0)
|
||||
let editableControlFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset, y: 0.0), size: CGSize(width: editableControlSizeAndApply.0, height: layout.contentSize.height))
|
||||
if strongSelf.editableControlNode == nil {
|
||||
let editableControlNode = editableControlSizeAndApply.1()
|
||||
let editableControlNode = editableControlSizeAndApply.1(layout.contentSize.height)
|
||||
editableControlNode.tapped = {
|
||||
if let strongSelf = self {
|
||||
strongSelf.setRevealOptionsOpened(true, animated: true)
|
||||
@ -341,13 +341,13 @@ private final class ProxySettingsServerItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
if let reorderControlSizeAndApply = reorderControlSizeAndApply {
|
||||
if strongSelf.reorderControlNode == nil {
|
||||
let reorderControlNode = reorderControlSizeAndApply.1(false)
|
||||
let reorderControlNode = reorderControlSizeAndApply.1(layout.contentSize.height, false)
|
||||
strongSelf.reorderControlNode = reorderControlNode
|
||||
strongSelf.addSubnode(reorderControlNode)
|
||||
reorderControlNode.alpha = 0.0
|
||||
transition.updateAlpha(node: reorderControlNode, alpha: 1.0)
|
||||
}
|
||||
let reorderControlFrame = CGRect(origin: CGPoint(x: params.width + revealOffset - params.rightInset - reorderControlSizeAndApply.0.width, y: 0.0), size: reorderControlSizeAndApply.0)
|
||||
let reorderControlFrame = CGRect(origin: CGPoint(x: params.width + revealOffset - params.rightInset - reorderControlSizeAndApply.0, y: 0.0), size: CGSize(width: reorderControlSizeAndApply.0, height: layout.contentSize.height))
|
||||
strongSelf.reorderControlNode?.frame = reorderControlFrame
|
||||
} else if let reorderControlNode = strongSelf.reorderControlNode {
|
||||
strongSelf.reorderControlNode = nil
|
||||
|
@ -60,25 +60,25 @@ private enum SaveIncomingMediaEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! SaveIncomingMediaControllerArguments
|
||||
switch self {
|
||||
case let .header(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .contacts(theme, text, value):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.toggle(.contact)
|
||||
})
|
||||
case let .otherPrivate(theme, text, value):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.toggle(.otherPrivate)
|
||||
})
|
||||
case let .groups(theme, text, value):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.toggle(.group)
|
||||
})
|
||||
case let .channels(theme, text, value):
|
||||
return ItemListSwitchItem(theme: theme, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: text, value: value, enableInteractiveChanges: true, enabled: true, sectionId: self.section, style: .blocks, updated: { value in
|
||||
arguments.toggle(.channel)
|
||||
})
|
||||
}
|
||||
@ -125,8 +125,8 @@ func saveIncomingMediaController(context: AccountContext) -> ViewController {
|
||||
automaticMediaDownloadSettings = MediaAutoDownloadSettings.defaultSettings
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.SaveIncomingPhotosSettings_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: saveIncomingMediaControllerEntries(presentationData: presentationData, settings: automaticMediaDownloadSettings), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.SaveIncomingPhotosSettings_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: saveIncomingMediaControllerEntries(presentationData: presentationData, settings: automaticMediaDownloadSettings), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -21,8 +21,8 @@ public final class ShareProxyServerActionSheetController: ActionSheetController
|
||||
|
||||
private var isDismissed: Bool = false
|
||||
|
||||
public init(theme: PresentationTheme, strings: PresentationStrings, updatedPresentationData: Signal<(theme: PresentationTheme, strings: PresentationStrings), NoError>, link: String) {
|
||||
let sheetTheme = ActionSheetControllerTheme(presentationTheme: theme)
|
||||
public init(presentationData: PresentationData, updatedPresentationData: Signal<PresentationData, NoError>, link: String) {
|
||||
let sheetTheme = ActionSheetControllerTheme(presentationTheme: presentationData.theme)
|
||||
super.init(theme: sheetTheme)
|
||||
|
||||
let presentActivityController: (Any) -> Void = { [weak self] item in
|
||||
@ -35,10 +35,10 @@ public final class ShareProxyServerActionSheetController: ActionSheetController
|
||||
}
|
||||
|
||||
var items: [ActionSheetItem] = []
|
||||
items.append(ProxyServerQRCodeItem(strings: strings, link: link, ready: { [weak self] in
|
||||
items.append(ProxyServerQRCodeItem(strings: presentationData.strings, link: link, ready: { [weak self] in
|
||||
self?._ready.set(.single(true))
|
||||
}))
|
||||
items.append(ActionSheetButtonItem(title: strings.SocksProxySetup_ShareQRCode, action: { [weak self] in
|
||||
items.append(ActionSheetButtonItem(title: presentationData.strings.SocksProxySetup_ShareQRCode, action: { [weak self] in
|
||||
self?.dismissAnimated()
|
||||
let _ = (qrCode(string: link, color: .black, backgroundColor: .white, icon: .proxy)
|
||||
|> map { _, generator -> UIImage? in
|
||||
@ -52,22 +52,22 @@ public final class ShareProxyServerActionSheetController: ActionSheetController
|
||||
}
|
||||
})
|
||||
}))
|
||||
items.append(ActionSheetButtonItem(title: strings.SocksProxySetup_ShareLink, action: { [weak self] in
|
||||
items.append(ActionSheetButtonItem(title: presentationData.strings.SocksProxySetup_ShareLink, action: { [weak self] in
|
||||
self?.dismissAnimated()
|
||||
presentActivityController(link)
|
||||
}))
|
||||
self.setItemGroups([
|
||||
ActionSheetItemGroup(items: items),
|
||||
ActionSheetItemGroup(items: [
|
||||
ActionSheetButtonItem(title: strings.Common_Cancel, action: { [weak self] in
|
||||
ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { [weak self] in
|
||||
self?.dismissAnimated()
|
||||
})
|
||||
])
|
||||
])
|
||||
|
||||
self.presentationDisposable = updatedPresentationData.start(next: { [weak self] theme, strings in
|
||||
self.presentationDisposable = updatedPresentationData.start(next: { [weak self] presentationData in
|
||||
if let strongSelf = self {
|
||||
strongSelf.theme = ActionSheetControllerTheme(presentationTheme: theme)
|
||||
strongSelf.theme = ActionSheetControllerTheme(presentationTheme: presentationData.theme)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -195,36 +195,36 @@ private enum StorageUsageEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! StorageUsageControllerArguments
|
||||
switch self {
|
||||
case let .keepMediaHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .keepMedia(theme, strings, value):
|
||||
return KeepMediaDurationPickerItem(theme: theme, strings: strings, value: value, sectionId: self.section, updated: { updatedValue in
|
||||
arguments.updateKeepMediaTimeout(updatedValue)
|
||||
})
|
||||
case let .keepMediaInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .markdown(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section)
|
||||
case let .storageHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .storageUsage(theme, dateTimeFormat, categories):
|
||||
return StorageUsageItem(theme: theme, dateTimeFormat: dateTimeFormat, categories: categories, sectionId: self.section)
|
||||
case let .collecting(theme, text):
|
||||
return CalculatingCacheSizeItem(theme: theme, title: text, sectionId: self.section, style: .blocks)
|
||||
case let .clearAll(theme, text, enabled):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: enabled ? .generic : .disabled, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: enabled ? .generic : .disabled, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
if enabled {
|
||||
arguments.openClearAll()
|
||||
}
|
||||
})
|
||||
case let .peersHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .peer(_, theme, strings, dateTimeFormat, nameDisplayOrder, peer, chatPeer, value, revealed):
|
||||
var options: [ItemListPeerItemRevealOption] = [ItemListPeerItemRevealOption(type: .destructive, title: strings.ClearCache_Clear, action: {
|
||||
arguments.clearPeerMedia(peer.id)
|
||||
})]
|
||||
return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, aliasHandling: .threatSelfAsSaved, nameColor: chatPeer == nil ? .primary : .secret, presence: nil, text: .none, label: .disclosure(value), editing: ItemListPeerItemEditing(editable: true, editing: false, revealed: revealed), revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: {
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, aliasHandling: .threatSelfAsSaved, nameColor: chatPeer == nil ? .primary : .secret, presence: nil, text: .none, label: .disclosure(value), editing: ItemListPeerItemEditing(editable: true, editing: false, revealed: revealed), revealOptions: ItemListPeerItemRevealOptions(options: options), switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: {
|
||||
let resolvedPeer = chatPeer ?? peer
|
||||
arguments.openPeerMedia(resolvedPeer.id)
|
||||
}, setPeerIdWithRevealedOptions: { peerId, fromPeerId in
|
||||
@ -924,8 +924,8 @@ public func storageUsageController(context: AccountContext, cacheUsagePromise: P
|
||||
dismissImpl?()
|
||||
}) : nil
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.Cache_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: storageUsageControllerEntries(presentationData: presentationData, cacheSettings: cacheSettings, cacheStats: cacheStats, state: state), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.Cache_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: storageUsageControllerEntries(presentationData: presentationData, cacheSettings: cacheSettings, cacheStats: cacheStats, state: state), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
} |> afterDisposed {
|
||||
|
@ -79,23 +79,23 @@ private enum VoiceCallDataSavingEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! VoiceCallDataSavingControllerArguments
|
||||
switch self {
|
||||
case let .never(theme, text, value):
|
||||
return ItemListCheckboxItem(theme: theme, title: text, style: .left, checked: value, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: value, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.updateSelection(.never)
|
||||
})
|
||||
case let .cellular(theme, text, value):
|
||||
return ItemListCheckboxItem(theme: theme, title: text, style: .left, checked: value, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: value, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.updateSelection(.cellular)
|
||||
})
|
||||
case let .always(theme, text, value):
|
||||
return ItemListCheckboxItem(theme: theme, title: text, style: .left, checked: value, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
return ItemListCheckboxItem(presentationData: presentationData, title: text, style: .left, checked: value, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.updateSelection(.always)
|
||||
})
|
||||
case let .info(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -155,8 +155,8 @@ func voiceCallDataSavingController(context: AccountContext) -> ViewController {
|
||||
|
||||
let dataSaving = effectiveDataSaving(for: sharedSettings.0, autodownloadSettings: sharedSettings.1)
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.CallSettings_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(entries: voiceCallDataSavingControllerEntries(presentationData: presentationData, dataSaving: dataSaving), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.CallSettings_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: false)
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: voiceCallDataSavingControllerEntries(presentationData: presentationData, dataSaving: dataSaving), style: .blocks, emptyStateItem: nil, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -65,11 +65,11 @@ private enum WebBrowserSettingsControllerEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! WebBrowserSettingsControllerArguments
|
||||
switch self {
|
||||
case let .browserHeader(theme, text):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: text, sectionId: self.section)
|
||||
case let .browser(theme, title, application, identifier, selected, _):
|
||||
return WebBrowserItem(account: arguments.context.account, theme: theme, title: title, application: application, checked: selected, sectionId: self.section) {
|
||||
arguments.updateDefaultBrowser(identifier)
|
||||
@ -109,8 +109,8 @@ public func webBrowserSettingsController(context: AccountContext) -> ViewControl
|
||||
|> map { presentationData, sharedData -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||
let settings = (sharedData.entries[ApplicationSpecificSharedDataKeys.webBrowserSettings] as? WebBrowserSettings) ?? WebBrowserSettings.defaultSettings
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.WebBrowser_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(entries: webBrowserSettingsControllerEntries(context: context, presentationData: presentationData, selectedBrowser: settings.defaultWebBrowser), style: .blocks, animateChanges: false)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.WebBrowser_Title), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: webBrowserSettingsControllerEntries(context: context, presentationData: presentationData, selectedBrowser: settings.defaultWebBrowser), style: .blocks, animateChanges: false)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -73,15 +73,15 @@ private enum DebugAccountsControllerEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! DebugAccountsControllerArguments
|
||||
switch self {
|
||||
case let .record(theme, record, current):
|
||||
return ItemListCheckboxItem(theme: theme, title: "\(UInt64(bitPattern: record.id.int64))", style: .left, checked: current, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
return ItemListCheckboxItem(presentationData: presentationData, title: "\(UInt64(bitPattern: record.id.int64))", style: .left, checked: current, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.switchAccount(record.id)
|
||||
})
|
||||
case let .loginNewAccount(theme):
|
||||
return ItemListActionItem(theme: theme, title: "Login to another account", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: "Login to another account", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.loginNewAccount()
|
||||
})
|
||||
}
|
||||
@ -135,8 +135,8 @@ public func debugAccountsController(context: AccountContext, accountManager: Acc
|
||||
|
||||
let signal = combineLatest(context.sharedContext.presentationData, accountManager.accountRecords())
|
||||
|> map { presentationData, view -> (ItemListControllerState, (ItemListNodeState, Any)) in
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text("Accounts"), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(entries: debugAccountsControllerEntries(view: view, presentationData: presentationData), style: .blocks)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text("Accounts"), leftNavigationButton: nil, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: debugAccountsControllerEntries(view: view, presentationData: presentationData), style: .blocks)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -147,11 +147,11 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! DebugControllerArguments
|
||||
switch self {
|
||||
case let .sendLogs(theme):
|
||||
return ItemListDisclosureItem(theme: theme, title: "Send Logs", label: "", sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: "Send Logs", label: "", sectionId: self.section, style: .blocks, action: {
|
||||
let _ = (Logger.shared.collectLogs()
|
||||
|> deliverOnMainQueue).start(next: { logs in
|
||||
let presentationData = arguments.sharedContext.currentPresentationData.with { $0 }
|
||||
@ -202,7 +202,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
})
|
||||
})
|
||||
case let .sendOneLog(theme):
|
||||
return ItemListDisclosureItem(theme: theme, title: "Send Latest Log", label: "", sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: "Send Latest Log", label: "", sectionId: self.section, style: .blocks, action: {
|
||||
let _ = (Logger.shared.collectLogs()
|
||||
|> deliverOnMainQueue).start(next: { logs in
|
||||
let presentationData = arguments.sharedContext.currentPresentationData.with { $0 }
|
||||
@ -257,7 +257,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
})
|
||||
})
|
||||
case let .sendNotificationLogs(theme):
|
||||
return ItemListDisclosureItem(theme: theme, title: "Send Notification Logs", label: "", sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: "Send Notification Logs", label: "", sectionId: self.section, style: .blocks, action: {
|
||||
let _ = (Logger(basePath: arguments.sharedContext.basePath + "/notificationServiceLogs").collectLogs()
|
||||
|> deliverOnMainQueue).start(next: { logs in
|
||||
guard let context = arguments.context else {
|
||||
@ -280,7 +280,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
})
|
||||
})
|
||||
case let .sendCriticalLogs(theme):
|
||||
return ItemListDisclosureItem(theme: theme, title: "Send Critical Logs", label: "", sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: "Send Critical Logs", label: "", sectionId: self.section, style: .blocks, action: {
|
||||
let _ = (Logger.shared.collectShortLogFiles()
|
||||
|> deliverOnMainQueue).start(next: { logs in
|
||||
let presentationData = arguments.sharedContext.currentPresentationData.with { $0 }
|
||||
@ -331,38 +331,38 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
})
|
||||
})
|
||||
case let .accounts(theme):
|
||||
return ItemListDisclosureItem(theme: theme, title: "Accounts", label: "", sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: "Accounts", label: "", sectionId: self.section, style: .blocks, action: {
|
||||
guard let context = arguments.context else {
|
||||
return
|
||||
}
|
||||
arguments.pushController(debugAccountsController(context: context, accountManager: arguments.sharedContext.accountManager))
|
||||
})
|
||||
case let .logToFile(theme, value):
|
||||
return ItemListSwitchItem(theme: theme, title: "Log to File", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: "Log to File", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
let _ = updateLoggingSettings(accountManager: arguments.sharedContext.accountManager, {
|
||||
$0.withUpdatedLogToFile(value)
|
||||
}).start()
|
||||
})
|
||||
case let .logToConsole(theme, value):
|
||||
return ItemListSwitchItem(theme: theme, title: "Log to Console", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: "Log to Console", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
let _ = updateLoggingSettings(accountManager: arguments.sharedContext.accountManager, {
|
||||
$0.withUpdatedLogToConsole(value)
|
||||
}).start()
|
||||
})
|
||||
case let .redactSensitiveData(theme, value):
|
||||
return ItemListSwitchItem(theme: theme, title: "Remove Sensitive Data", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: "Remove Sensitive Data", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
let _ = updateLoggingSettings(accountManager: arguments.sharedContext.accountManager, {
|
||||
$0.withUpdatedRedactSensitiveData(value)
|
||||
}).start()
|
||||
})
|
||||
case let .enableRaiseToSpeak(theme, value):
|
||||
return ItemListSwitchItem(theme: theme, title: "Enable Raise to Speak", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: "Enable Raise to Speak", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
let _ = updateMediaInputSettingsInteractively(accountManager: arguments.sharedContext.accountManager, {
|
||||
$0.withUpdatedEnableRaiseToSpeak(value)
|
||||
}).start()
|
||||
})
|
||||
case let .keepChatNavigationStack(theme, value):
|
||||
return ItemListSwitchItem(theme: theme, title: "Keep Chat Stack", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: "Keep Chat Stack", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
let _ = updateExperimentalUISettingsInteractively(accountManager: arguments.sharedContext.accountManager, { settings in
|
||||
var settings = settings
|
||||
settings.keepChatNavigationStack = value
|
||||
@ -370,7 +370,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
}).start()
|
||||
})
|
||||
case let .skipReadHistory(theme, value):
|
||||
return ItemListSwitchItem(theme: theme, title: "Skip read history", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: "Skip read history", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
let _ = updateExperimentalUISettingsInteractively(accountManager: arguments.sharedContext.accountManager, { settings in
|
||||
var settings = settings
|
||||
settings.skipReadHistory = value
|
||||
@ -378,7 +378,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
}).start()
|
||||
})
|
||||
case let .crashOnSlowQueries(theme, value):
|
||||
return ItemListSwitchItem(theme: theme, title: "Crash when slow", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: "Crash when slow", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
let _ = updateExperimentalUISettingsInteractively(accountManager: arguments.sharedContext.accountManager, { settings in
|
||||
var settings = settings
|
||||
settings.crashOnLongQueries = value
|
||||
@ -386,13 +386,13 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
}).start()
|
||||
})
|
||||
case let .clearTips(theme):
|
||||
return ItemListActionItem(theme: theme, title: "Clear Tips", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: "Clear Tips", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
let _ = (arguments.sharedContext.accountManager.transaction { transaction -> Void in
|
||||
transaction.clearNotices()
|
||||
}).start()
|
||||
})
|
||||
case let .reimport(theme):
|
||||
return ItemListActionItem(theme: theme, title: "Reimport Application Data", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: "Reimport Application Data", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
let appGroupName = "group.\(Bundle.main.bundleIdentifier!)"
|
||||
let maybeAppGroupUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupName)
|
||||
|
||||
@ -407,7 +407,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
}
|
||||
})
|
||||
case let .resetData(theme):
|
||||
return ItemListActionItem(theme: theme, title: "Reset Data", kind: .destructive, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: "Reset Data", kind: .destructive, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
let presentationData = arguments.sharedContext.currentPresentationData.with { $0 }
|
||||
let actionSheet = ActionSheetController(presentationTheme: presentationData.theme)
|
||||
actionSheet.setItemGroups([ActionSheetItemGroup(items: [
|
||||
@ -426,7 +426,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
arguments.presentController(actionSheet, nil)
|
||||
})
|
||||
case let .resetDatabase(theme):
|
||||
return ItemListActionItem(theme: theme, title: "Clear Database", kind: .destructive, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: "Clear Database", kind: .destructive, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
guard let context = arguments.context else {
|
||||
return
|
||||
}
|
||||
@ -448,7 +448,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
arguments.presentController(actionSheet, nil)
|
||||
})
|
||||
case let .resetHoles(theme):
|
||||
return ItemListActionItem(theme: theme, title: "Reset Holes", kind: .destructive, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: "Reset Holes", kind: .destructive, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
guard let context = arguments.context else {
|
||||
return
|
||||
}
|
||||
@ -463,13 +463,13 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
})
|
||||
})
|
||||
case let .resetBiometricsData(theme):
|
||||
return ItemListActionItem(theme: theme, title: "Reset Biometrics Data", kind: .destructive, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: "Reset Biometrics Data", kind: .destructive, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
let _ = updatePresentationPasscodeSettingsInteractively(accountManager: arguments.sharedContext.accountManager, { settings in
|
||||
return settings.withUpdatedBiometricsDomainState(nil).withUpdatedShareBiometricsDomainState(nil)
|
||||
}).start()
|
||||
})
|
||||
case let .optimizeDatabase(theme):
|
||||
return ItemListActionItem(theme: theme, title: "Optimize Database", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: "Optimize Database", kind: .generic, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
guard let context = arguments.context else {
|
||||
return
|
||||
}
|
||||
@ -485,7 +485,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
})
|
||||
})
|
||||
case let .photoPreview(theme, value):
|
||||
return ItemListSwitchItem(theme: theme, title: "Photo Preview", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: "Photo Preview", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
let _ = arguments.sharedContext.accountManager.transaction ({ transaction in
|
||||
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings, { settings in
|
||||
var settings = settings as? ExperimentalUISettings ?? ExperimentalUISettings.defaultSettings
|
||||
@ -495,7 +495,7 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
}).start()
|
||||
})
|
||||
case let .knockoutWallpaper(theme, value):
|
||||
return ItemListSwitchItem(theme: theme, title: "Knockout Wallpaper", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
return ItemListSwitchItem(presentationData: presentationData, title: "Knockout Wallpaper", value: value, sectionId: self.section, style: .blocks, updated: { value in
|
||||
let _ = arguments.sharedContext.accountManager.transaction ({ transaction in
|
||||
transaction.updateSharedData(ApplicationSpecificSharedDataKeys.experimentalUISettings, { settings in
|
||||
var settings = settings as? ExperimentalUISettings ?? ExperimentalUISettings.defaultSettings
|
||||
@ -505,13 +505,13 @@ private enum DebugControllerEntry: ItemListNodeEntry {
|
||||
}).start()
|
||||
})
|
||||
case let .hostInfo(theme, string):
|
||||
return ItemListTextItem(theme: theme, text: .plain(string), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(string), sectionId: self.section)
|
||||
case let .versionInfo(theme):
|
||||
let bundle = Bundle.main
|
||||
let bundleId = bundle.bundleIdentifier ?? ""
|
||||
let bundleVersion = bundle.infoDictionary?["CFBundleShortVersionString"] ?? ""
|
||||
let bundleBuild = bundle.infoDictionary?[kCFBundleVersionKey as String] ?? ""
|
||||
return ItemListTextItem(theme: theme, text: .plain("\(bundleId)\n\(bundleVersion) (\(bundleBuild))"), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain("\(bundleId)\n\(bundleVersion) (\(bundleBuild))"), sectionId: self.section)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -612,8 +612,8 @@ public func debugController(sharedContext: SharedAccountContext, context: Accoun
|
||||
})
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text("Debug"), leftNavigationButton: leftNavigationButton, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(entries: debugControllerEntries(presentationData: presentationData, loggingSettings: loggingSettings, mediaInputSettings: mediaInputSettings, experimentalSettings: experimentalSettings, networkSettings: networkSettings, hasLegacyAppData: hasLegacyAppData), style: .blocks)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text("Debug"), leftNavigationButton: leftNavigationButton, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: debugControllerEntries(presentationData: presentationData, loggingSettings: loggingSettings, mediaInputSettings: mediaInputSettings, experimentalSettings: experimentalSettings, networkSettings: networkSettings, hasLegacyAppData: hasLegacyAppData), style: .blocks)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -191,37 +191,37 @@ private enum SettingsEntry: ItemListNodeEntry {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! EditSettingsItemArguments
|
||||
switch self {
|
||||
case let .userInfo(theme, strings, dateTimeFormat, peer, cachedData, state, updatingImage):
|
||||
return ItemListAvatarAndNameInfoItem(account: arguments.context.account, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, mode: .editSettings, peer: peer, presence: TelegramUserPresence(status: .present(until: Int32.max), lastActivity: 0), cachedData: cachedData, state: state, sectionId: ItemListSectionId(self.section), style: .blocks(withTopInset: false, withExtendedBottomInset: false), editingNameUpdated: { editingName in
|
||||
return ItemListAvatarAndNameInfoItem(account: arguments.context.account, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .editSettings, peer: peer, presence: TelegramUserPresence(status: .present(until: Int32.max), lastActivity: 0), cachedData: cachedData, state: state, sectionId: ItemListSectionId(self.section), style: .blocks(withTopInset: false, withExtendedBottomInset: false), editingNameUpdated: { editingName in
|
||||
arguments.updateEditingName(editingName)
|
||||
}, avatarTapped: {
|
||||
arguments.avatarTapAction()
|
||||
}, context: arguments.avatarAndNameInfoContext, updatingImage: updatingImage)
|
||||
case let .userInfoNotice(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .bioText(theme, currentText, placeholder):
|
||||
return ItemListMultilineInputItem(theme: theme, text: currentText, placeholder: placeholder, maxLength: ItemListMultilineInputItemTextLimit(value: 70, display: true), sectionId: self.section, style: .blocks, textUpdated: { updatedText in
|
||||
return ItemListMultilineInputItem(presentationData: presentationData, text: currentText, placeholder: placeholder, maxLength: ItemListMultilineInputItemTextLimit(value: 70, display: true), sectionId: self.section, style: .blocks, textUpdated: { updatedText in
|
||||
arguments.updateBioText(currentText, updatedText)
|
||||
}, tag: EditSettingsEntryTag.bio)
|
||||
case let .bioInfo(theme, text):
|
||||
return ItemListTextItem(theme: theme, text: .plain(text), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(text), sectionId: self.section)
|
||||
case let .phoneNumber(theme, text, number):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: number, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: number, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
||||
arguments.pushController(ChangePhoneNumberIntroController(context: arguments.context, phoneNumber: number))
|
||||
})
|
||||
case let .username(theme, text, address):
|
||||
return ItemListDisclosureItem(theme: theme, title: text, label: address, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, title: text, label: address, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
||||
arguments.pushController(usernameSetupController(context: arguments.context))
|
||||
})
|
||||
case let .addAccount(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .generic, alignment: .center, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .generic, alignment: .center, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
||||
arguments.addAccount()
|
||||
})
|
||||
case let .logOut(theme, text):
|
||||
return ItemListActionItem(theme: theme, title: text, kind: .destructive, alignment: .center, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: text, kind: .destructive, alignment: .center, sectionId: ItemListSectionId(self.section), style: .blocks, action: {
|
||||
arguments.logout()
|
||||
})
|
||||
}
|
||||
@ -438,8 +438,8 @@ func editSettingsController(context: AccountContext, currentName: ItemListAvatar
|
||||
})
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.EditProfile_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(entries: editSettingsEntries(presentationData: presentationData, state: state, view: view, canAddAccounts: canAddAccounts), style: .blocks, ensureVisibleItemTag: focusOnItemTag)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.EditProfile_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: editSettingsEntries(presentationData: presentationData, state: state, view: view, canAddAccounts: canAddAccounts), style: .blocks, ensureVisibleItemTag: focusOnItemTag)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
} |> afterDisposed {
|
||||
|
@ -52,10 +52,10 @@ private enum LanguageListEntry: Comparable, Identifiable {
|
||||
return lhs.index() < rhs.index()
|
||||
}
|
||||
|
||||
func item(theme: PresentationTheme, strings: PresentationStrings, searchMode: Bool, openSearch: @escaping () -> Void, selectLocalization: @escaping (LocalizationInfo) -> Void, setItemWithRevealedOptions: @escaping (String?, String?) -> Void, removeItem: @escaping (String) -> Void) -> ListViewItem {
|
||||
func item(presentationData: PresentationData, searchMode: Bool, openSearch: @escaping () -> Void, selectLocalization: @escaping (LocalizationInfo) -> Void, setItemWithRevealedOptions: @escaping (String?, String?) -> Void, removeItem: @escaping (String) -> Void) -> ListViewItem {
|
||||
switch self {
|
||||
case let .localization(_, info, type, selected, activity, revealed, editing):
|
||||
return LocalizationListItem(theme: theme, strings: strings, id: info.languageCode, title: info.title, subtitle: info.localizedTitle, checked: selected, activity: activity, editing: LocalizationListItemEditing(editable: !selected && !searchMode && !info.isOfficial, editing: editing, revealed: !selected && revealed, reorderable: false), sectionId: type == .official ? LanguageListSection.official.rawValue : LanguageListSection.unofficial.rawValue, alwaysPlain: searchMode, action: {
|
||||
return LocalizationListItem(presentationData: ItemListPresentationData(presentationData), id: info.languageCode, title: info.title, subtitle: info.localizedTitle, checked: selected, activity: activity, editing: LocalizationListItemEditing(editable: !selected && !searchMode && !info.isOfficial, editing: editing, revealed: !selected && revealed, reorderable: false), sectionId: type == .official ? LanguageListSection.official.rawValue : LanguageListSection.unofficial.rawValue, alwaysPlain: searchMode, action: {
|
||||
selectLocalization(info)
|
||||
}, setItemWithRevealedOptions: setItemWithRevealedOptions, removeItem: removeItem)
|
||||
}
|
||||
@ -69,12 +69,12 @@ private struct LocalizationListSearchContainerTransition {
|
||||
let isSearching: Bool
|
||||
}
|
||||
|
||||
private func preparedLanguageListSearchContainerTransition(theme: PresentationTheme, strings: PresentationStrings, from fromEntries: [LanguageListEntry], to toEntries: [LanguageListEntry], selectLocalization: @escaping (LocalizationInfo) -> Void, isSearching: Bool, forceUpdate: Bool) -> LocalizationListSearchContainerTransition {
|
||||
private func preparedLanguageListSearchContainerTransition(presentationData: PresentationData, from fromEntries: [LanguageListEntry], to toEntries: [LanguageListEntry], selectLocalization: @escaping (LocalizationInfo) -> Void, isSearching: Bool, forceUpdate: Bool) -> LocalizationListSearchContainerTransition {
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries, allUpdated: forceUpdate)
|
||||
|
||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(theme: theme, strings: strings, searchMode: true, openSearch: {}, selectLocalization: selectLocalization, setItemWithRevealedOptions: { _, _ in }, removeItem: { _ in }), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(theme: theme, strings: strings, searchMode: true, openSearch: {}, selectLocalization: selectLocalization, setItemWithRevealedOptions: { _, _ in }, removeItem: { _ in }), directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(presentationData: presentationData, searchMode: true, openSearch: {}, selectLocalization: selectLocalization, setItemWithRevealedOptions: { _, _ in }, removeItem: { _ in }), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(presentationData: presentationData, searchMode: true, openSearch: {}, selectLocalization: selectLocalization, setItemWithRevealedOptions: { _, _ in }, removeItem: { _ in }), directionHint: nil) }
|
||||
|
||||
return LocalizationListSearchContainerTransition(deletions: deletions, insertions: insertions, updates: updates, isSearching: isSearching)
|
||||
}
|
||||
@ -92,12 +92,12 @@ private final class LocalizationListSearchContainerNode: SearchDisplayController
|
||||
private var presentationData: PresentationData
|
||||
private var presentationDataDisposable: Disposable?
|
||||
|
||||
private let themeAndStringsPromise: Promise<(PresentationTheme, PresentationStrings)>
|
||||
private let presentationDataPromise: Promise<PresentationData>
|
||||
|
||||
init(context: AccountContext, listState: LocalizationListState, selectLocalization: @escaping (LocalizationInfo) -> Void, applyingCode: Signal<String?, NoError>) {
|
||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
self.themeAndStringsPromise = Promise((self.presentationData.theme, self.presentationData.strings))
|
||||
self.presentationDataPromise = Promise(self.presentationData)
|
||||
|
||||
self.dimNode = ASDisplayNode()
|
||||
self.dimNode.backgroundColor = UIColor.black.withAlphaComponent(0.5)
|
||||
@ -134,18 +134,18 @@ private final class LocalizationListSearchContainerNode: SearchDisplayController
|
||||
}
|
||||
|
||||
let previousEntriesHolder = Atomic<([LanguageListEntry], PresentationTheme, PresentationStrings)?>(value: nil)
|
||||
self.searchDisposable.set(combineLatest(queue: .mainQueue(), foundItems, self.themeAndStringsPromise.get(), applyingCode).start(next: { [weak self] items, themeAndStrings, applyingCode in
|
||||
self.searchDisposable.set(combineLatest(queue: .mainQueue(), foundItems, self.presentationDataPromise.get(), applyingCode).start(next: { [weak self] items, presentationData, applyingCode in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
var entries: [LanguageListEntry] = []
|
||||
if let items = items {
|
||||
for item in items {
|
||||
entries.append(.localization(index: entries.count, info: item, type: .official, selected: themeAndStrings.1.primaryComponent.languageCode == item.languageCode, activity: applyingCode == item.languageCode, revealed: false, editing: false))
|
||||
entries.append(.localization(index: entries.count, info: item, type: .official, selected: presentationData.strings.primaryComponent.languageCode == item.languageCode, activity: applyingCode == item.languageCode, revealed: false, editing: false))
|
||||
}
|
||||
}
|
||||
let previousEntriesAndPresentationData = previousEntriesHolder.swap((entries, themeAndStrings.0, themeAndStrings.1))
|
||||
let transition = preparedLanguageListSearchContainerTransition(theme: themeAndStrings.0, strings: themeAndStrings.1, from: previousEntriesAndPresentationData?.0 ?? [], to: entries, selectLocalization: selectLocalization, isSearching: items != nil, forceUpdate: previousEntriesAndPresentationData?.1 !== themeAndStrings.0 || previousEntriesAndPresentationData?.2 !== themeAndStrings.1)
|
||||
let previousEntriesAndPresentationData = previousEntriesHolder.swap((entries, presentationData.theme, presentationData.strings))
|
||||
let transition = preparedLanguageListSearchContainerTransition(presentationData: presentationData, from: previousEntriesAndPresentationData?.0 ?? [], to: entries, selectLocalization: selectLocalization, isSearching: items != nil, forceUpdate: previousEntriesAndPresentationData?.1 !== presentationData.theme || previousEntriesAndPresentationData?.2 !== presentationData.strings)
|
||||
strongSelf.enqueueTransition(transition)
|
||||
}))
|
||||
|
||||
@ -159,7 +159,7 @@ private final class LocalizationListSearchContainerNode: SearchDisplayController
|
||||
|
||||
if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings {
|
||||
strongSelf.updateThemeAndStrings(theme: presentationData.theme, strings: presentationData.strings)
|
||||
strongSelf.themeAndStringsPromise.set(.single((presentationData.theme, presentationData.strings)))
|
||||
strongSelf.presentationDataPromise.set(.single(presentationData))
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -272,12 +272,12 @@ private struct LanguageListNodeTransition {
|
||||
let animated: Bool
|
||||
}
|
||||
|
||||
private func preparedLanguageListNodeTransition(theme: PresentationTheme, strings: PresentationStrings, from fromEntries: [LanguageListEntry], to toEntries: [LanguageListEntry], openSearch: @escaping () -> Void, selectLocalization: @escaping (LocalizationInfo) -> Void, setItemWithRevealedOptions: @escaping (String?, String?) -> Void, removeItem: @escaping (String) -> Void, firstTime: Bool, isLoading: Bool, forceUpdate: Bool, animated: Bool) -> LanguageListNodeTransition {
|
||||
private func preparedLanguageListNodeTransition(presentationData: PresentationData, from fromEntries: [LanguageListEntry], to toEntries: [LanguageListEntry], openSearch: @escaping () -> Void, selectLocalization: @escaping (LocalizationInfo) -> Void, setItemWithRevealedOptions: @escaping (String?, String?) -> Void, removeItem: @escaping (String) -> Void, firstTime: Bool, isLoading: Bool, forceUpdate: Bool, animated: Bool) -> LanguageListNodeTransition {
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries, allUpdated: forceUpdate)
|
||||
|
||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(theme: theme, strings: strings, searchMode: false, openSearch: openSearch, selectLocalization: selectLocalization, setItemWithRevealedOptions: setItemWithRevealedOptions, removeItem: removeItem), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(theme: theme, strings: strings, searchMode: false, openSearch: openSearch, selectLocalization: selectLocalization, setItemWithRevealedOptions: setItemWithRevealedOptions, removeItem: removeItem), directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(presentationData: presentationData, searchMode: false, openSearch: openSearch, selectLocalization: selectLocalization, setItemWithRevealedOptions: setItemWithRevealedOptions, removeItem: removeItem), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(presentationData: presentationData, searchMode: false, openSearch: openSearch, selectLocalization: selectLocalization, setItemWithRevealedOptions: setItemWithRevealedOptions, removeItem: removeItem), directionHint: nil) }
|
||||
|
||||
return LanguageListNodeTransition(deletions: deletions, insertions: insertions, updates: updates, firstTime: firstTime, isLoading: isLoading, animated: animated)
|
||||
}
|
||||
@ -299,7 +299,7 @@ final class LocalizationListControllerNode: ViewControllerTracingNode {
|
||||
private var activityIndicator: ActivityIndicator?
|
||||
private var searchDisplayController: SearchDisplayController?
|
||||
|
||||
private let presentationDataValue = Promise<(PresentationTheme, PresentationStrings)>()
|
||||
private let presentationDataValue = Promise<PresentationData>()
|
||||
private var updatedDisposable: Disposable?
|
||||
private var listDisposable: Disposable?
|
||||
private let applyDisposable = MetaDisposable()
|
||||
@ -316,7 +316,7 @@ final class LocalizationListControllerNode: ViewControllerTracingNode {
|
||||
init(context: AccountContext, presentationData: PresentationData, navigationBar: NavigationBar, requestActivateSearch: @escaping () -> Void, requestDeactivateSearch: @escaping () -> Void, updateCanStartEditing: @escaping (Bool?) -> Void, present: @escaping (ViewController, Any?) -> Void) {
|
||||
self.context = context
|
||||
self.presentationData = presentationData
|
||||
self.presentationDataValue.set(.single((presentationData.theme, presentationData.strings)))
|
||||
self.presentationDataValue.set(.single(presentationData))
|
||||
self.navigationBar = navigationBar
|
||||
self.requestActivateSearch = requestActivateSearch
|
||||
self.requestDeactivateSearch = requestDeactivateSearch
|
||||
@ -411,8 +411,8 @@ final class LocalizationListControllerNode: ViewControllerTracingNode {
|
||||
entries.append(.localization(index: entries.count, info: info, type: .official, selected: info.languageCode == activeLanguageCode, activity: applyingCode == info.languageCode, revealed: revealedCode == info.languageCode, editing: false))
|
||||
}
|
||||
}
|
||||
let previousEntriesAndPresentationData = previousEntriesHolder.swap((entries, presentationData.0, presentationData.1))
|
||||
let transition = preparedLanguageListNodeTransition(theme: presentationData.0, strings: presentationData.1, from: previousEntriesAndPresentationData?.0 ?? [], to: entries, openSearch: openSearch, selectLocalization: { [weak self] info in self?.selectLocalization(info) }, setItemWithRevealedOptions: setItemWithRevealedOptions, removeItem: removeItem, firstTime: previousEntriesAndPresentationData == nil, isLoading: entries.isEmpty, forceUpdate: previousEntriesAndPresentationData?.1 !== presentationData.0 || previousEntriesAndPresentationData?.2 !== presentationData.1, animated: (previousEntriesAndPresentationData?.0.count ?? 0) >= entries.count)
|
||||
let previousEntriesAndPresentationData = previousEntriesHolder.swap((entries, presentationData.theme, presentationData.strings))
|
||||
let transition = preparedLanguageListNodeTransition(presentationData: presentationData, from: previousEntriesAndPresentationData?.0 ?? [], to: entries, openSearch: openSearch, selectLocalization: { [weak self] info in self?.selectLocalization(info) }, setItemWithRevealedOptions: setItemWithRevealedOptions, removeItem: removeItem, firstTime: previousEntriesAndPresentationData == nil, isLoading: entries.isEmpty, forceUpdate: previousEntriesAndPresentationData?.1 !== presentationData.theme || previousEntriesAndPresentationData?.2 !== presentationData.strings, animated: (previousEntriesAndPresentationData?.0.count ?? 0) >= entries.count)
|
||||
strongSelf.enqueueTransition(transition)
|
||||
})
|
||||
self.updatedDisposable = synchronizedLocalizationListState(postbox: context.account.postbox, network: context.account.network).start()
|
||||
@ -426,7 +426,7 @@ final class LocalizationListControllerNode: ViewControllerTracingNode {
|
||||
|
||||
func updatePresentationData(_ presentationData: PresentationData) {
|
||||
self.presentationData = presentationData
|
||||
self.presentationDataValue.set(.single((presentationData.theme, presentationData.strings)))
|
||||
self.presentationDataValue.set(.single(presentationData))
|
||||
self.backgroundColor = presentationData.theme.list.blocksBackgroundColor
|
||||
self.listNode.keepTopItemOverscrollBackground = ListViewKeepTopItemOverscrollBackground(color: presentationData.theme.chatList.backgroundColor, direction: true)
|
||||
self.searchDisplayController?.updatePresentationData(presentationData)
|
||||
|
@ -17,8 +17,7 @@ struct LocalizationListItemEditing: Equatable {
|
||||
}
|
||||
|
||||
class LocalizationListItem: ListViewItem, ItemListItem {
|
||||
let theme: PresentationTheme
|
||||
let strings: PresentationStrings
|
||||
let presentationData: ItemListPresentationData
|
||||
let id: String
|
||||
let title: String
|
||||
let subtitle: String
|
||||
@ -31,9 +30,8 @@ class LocalizationListItem: ListViewItem, ItemListItem {
|
||||
let setItemWithRevealedOptions: (String?, String?) -> Void
|
||||
let removeItem: (String) -> Void
|
||||
|
||||
init(theme: PresentationTheme, strings: PresentationStrings, id: String, title: String, subtitle: String, checked: Bool, activity: Bool, editing: LocalizationListItemEditing, sectionId: ItemListSectionId, alwaysPlain: Bool, action: @escaping () -> Void, setItemWithRevealedOptions: @escaping (String?, String?) -> Void, removeItem: @escaping (String) -> Void) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
init(presentationData: ItemListPresentationData, id: String, title: String, subtitle: String, checked: Bool, activity: Bool, editing: LocalizationListItemEditing, sectionId: ItemListSectionId, alwaysPlain: Bool, action: @escaping () -> Void, setItemWithRevealedOptions: @escaping (String?, String?) -> Void, removeItem: @escaping (String) -> Void) {
|
||||
self.presentationData = presentationData
|
||||
self.id = id
|
||||
self.title = title
|
||||
self.subtitle = subtitle
|
||||
@ -96,9 +94,6 @@ class LocalizationListItem: ListViewItem, ItemListItem {
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.regular(17.0)
|
||||
private let subtitleFont = Font.regular(13.0)
|
||||
|
||||
class LocalizationListItemNode: ItemListRevealOptionsItemNode {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let topStripeNode: ASDisplayNode
|
||||
@ -176,38 +171,38 @@ class LocalizationListItemNode: ItemListRevealOptionsItemNode {
|
||||
return { item, params, neighbors in
|
||||
var leftInset: CGFloat = params.leftInset
|
||||
|
||||
let titleFont = Font.regular(item.presentationData.fontSize.itemListBaseFontSize)
|
||||
let subtitleFont = Font.regular(floor(item.presentationData.fontSize.itemListBaseFontSize * 13.0 / 17.0))
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 50.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let (subtitleLayout, subtitleApply) = makeSubtitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.subtitle, font: subtitleFont, textColor: item.presentationData.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 50.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let insets = itemListNeighborsGroupedInsets(neighbors)
|
||||
let contentSize = CGSize(width: params.width, height: 58.0)
|
||||
let contentSize = CGSize(width: params.width, height: titleLayout.size.height + 1.0 + subtitleLayout.size.height + 8.0 * 2.0)
|
||||
|
||||
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
||||
|
||||
var editableControlSizeAndApply: (CGSize, () -> ItemListEditableControlNode)?
|
||||
var editableControlSizeAndApply: (CGFloat, (CGFloat) -> ItemListEditableControlNode)?
|
||||
|
||||
var editingOffset: CGFloat = 0.0
|
||||
|
||||
if item.editing.editing {
|
||||
let sizeAndApply = editableControlLayout(layout.contentSize.height, item.theme, false)
|
||||
let sizeAndApply = editableControlLayout(item.presentationData.theme, false)
|
||||
editableControlSizeAndApply = sizeAndApply
|
||||
editingOffset = sizeAndApply.0.width
|
||||
editingOffset = sizeAndApply.0
|
||||
}
|
||||
|
||||
leftInset += 16.0
|
||||
|
||||
let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.title, font: titleFont, textColor: item.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 50.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let (subtitleLayout, subtitleApply) = makeSubtitleLayout(TextNodeLayoutArguments(attributedString: NSAttributedString(string: item.subtitle, font: subtitleFont, textColor: item.theme.list.itemPrimaryTextColor), backgroundColor: nil, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset - 50.0, height: CGFloat.greatestFiniteMagnitude), alignment: .natural, cutout: nil, insets: UIEdgeInsets()))
|
||||
|
||||
let separatorHeight = UIScreenPixel
|
||||
|
||||
var updateCheckImage: UIImage?
|
||||
var updatedTheme: PresentationTheme?
|
||||
|
||||
if currentItem?.theme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
}
|
||||
|
||||
if currentItem?.theme !== item.theme {
|
||||
updateCheckImage = PresentationResourcesItemList.checkIconImage(item.theme)
|
||||
if currentItem?.presentationData.theme !== item.presentationData.theme {
|
||||
updatedTheme = item.presentationData.theme
|
||||
updateCheckImage = PresentationResourcesItemList.checkIconImage(item.presentationData.theme)
|
||||
}
|
||||
|
||||
return (layout, { [weak self] animated in
|
||||
@ -226,16 +221,16 @@ class LocalizationListItemNode: ItemListRevealOptionsItemNode {
|
||||
|
||||
if let updateCheckImage = updateCheckImage {
|
||||
strongSelf.iconNode.image = updateCheckImage
|
||||
strongSelf.activityNode.type = ActivityIndicatorType.custom(item.theme.list.itemAccentColor, 22.0, 0.0, false)
|
||||
strongSelf.activityNode.type = ActivityIndicatorType.custom(item.presentationData.theme.list.itemAccentColor, 22.0, 0.0, false)
|
||||
}
|
||||
|
||||
strongSelf.activityNode.isHidden = !item.activity
|
||||
|
||||
if let _ = updatedTheme {
|
||||
strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.theme.list.itemHighlightedBackgroundColor
|
||||
strongSelf.topStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = item.presentationData.theme.list.itemBlocksSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = item.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.presentationData.theme.list.itemHighlightedBackgroundColor
|
||||
}
|
||||
|
||||
let _ = titleApply()
|
||||
@ -275,12 +270,12 @@ class LocalizationListItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height - separatorHeight), size: CGSize(width: params.width - bottomStripeInset, height: separatorHeight))
|
||||
|
||||
transition.updateFrame(node: strongSelf.titleNode, frame: CGRect(origin: CGPoint(x: editingOffset + revealOffset + leftInset, y: 8.0), size: titleLayout.size))
|
||||
transition.updateFrame(node: strongSelf.subtitleNode, frame: CGRect(origin: CGPoint(x: editingOffset + revealOffset + leftInset, y: 31.0), size: subtitleLayout.size))
|
||||
transition.updateFrame(node: strongSelf.subtitleNode, frame: CGRect(origin: CGPoint(x: editingOffset + revealOffset + leftInset, y: strongSelf.titleNode.frame.maxY + 1.0), size: subtitleLayout.size))
|
||||
|
||||
if let editableControlSizeAndApply = editableControlSizeAndApply {
|
||||
let editableControlFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset, y: 0.0), size: editableControlSizeAndApply.0)
|
||||
let editableControlFrame = CGRect(origin: CGPoint(x: params.leftInset + revealOffset, y: 0.0), size: CGSize(width: editableControlSizeAndApply.0, height: layout.contentSize.height))
|
||||
if strongSelf.editableControlNode == nil {
|
||||
let editableControlNode = editableControlSizeAndApply.1()
|
||||
let editableControlNode = editableControlSizeAndApply.1(layout.contentSize.height)
|
||||
editableControlNode.tapped = {
|
||||
if let strongSelf = self {
|
||||
strongSelf.setRevealOptionsOpened(true, animated: true)
|
||||
@ -312,7 +307,7 @@ class LocalizationListItemNode: ItemListRevealOptionsItemNode {
|
||||
strongSelf.updateLayout(size: layout.contentSize, leftInset: params.leftInset, rightInset: params.rightInset)
|
||||
|
||||
if item.editing.editable {
|
||||
strongSelf.setRevealOptions((left: [], right: [ItemListRevealOption(key: 0, title: item.strings.Common_Delete, icon: .none, color: item.theme.list.itemDisclosureActions.destructive.fillColor, textColor: item.theme.list.itemDisclosureActions.destructive.foregroundColor)]))
|
||||
strongSelf.setRevealOptions((left: [], right: [ItemListRevealOption(key: 0, title: item.presentationData.strings.Common_Delete, icon: .none, color: item.presentationData.theme.list.itemDisclosureActions.destructive.fillColor, textColor: item.presentationData.theme.list.itemDisclosureActions.destructive.foregroundColor)]))
|
||||
} else {
|
||||
strongSelf.setRevealOptions((left: [], right: []))
|
||||
}
|
||||
|
@ -73,37 +73,37 @@ private enum LogoutOptionsEntry: ItemListNodeEntry, Equatable {
|
||||
return lhs.stableId < rhs.stableId
|
||||
}
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! LogoutOptionsItemArguments
|
||||
switch self {
|
||||
case let .alternativeHeader(theme, title):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: title, sectionId: self.section)
|
||||
return ItemListSectionHeaderItem(presentationData: presentationData, text: title, sectionId: self.section)
|
||||
case let .addAccount(theme, title, text):
|
||||
return ItemListDisclosureItem(theme: theme, icon: PresentationResourcesSettings.addAccount, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.addAccount, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
arguments.addAccount()
|
||||
})
|
||||
case let .setPasscode(theme, title, text):
|
||||
return ItemListDisclosureItem(theme: theme, icon: PresentationResourcesSettings.setPasscode, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.setPasscode, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
arguments.setPasscode()
|
||||
})
|
||||
case let .clearCache(theme, title, text):
|
||||
return ItemListDisclosureItem(theme: theme, icon: PresentationResourcesSettings.clearCache, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.clearCache, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
arguments.clearCache()
|
||||
})
|
||||
case let .changePhoneNumber(theme, title, text):
|
||||
return ItemListDisclosureItem(theme: theme, icon: PresentationResourcesSettings.changePhoneNumber, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.changePhoneNumber, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
arguments.changePhoneNumber()
|
||||
})
|
||||
case let .contactSupport(theme, title, text):
|
||||
return ItemListDisclosureItem(theme: theme, icon: PresentationResourcesSettings.support, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.support, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: {
|
||||
arguments.contactSupport()
|
||||
})
|
||||
case let .logout(theme, title):
|
||||
return ItemListActionItem(theme: theme, title: title, kind: .destructive, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: title, kind: .destructive, alignment: .natural, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.logout()
|
||||
})
|
||||
case let .logoutInfo(theme, title):
|
||||
return ItemListTextItem(theme: theme, text: .plain(title), sectionId: self.section)
|
||||
return ItemListTextItem(presentationData: presentationData, text: .plain(title), sectionId: self.section)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -239,8 +239,8 @@ func logoutOptionsController(context: AccountContext, navigationController: Navi
|
||||
break
|
||||
}
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.LogoutOptions_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(entries: logoutOptionsEntries(presentationData: presentationData, canAddAccounts: canAddAccounts, hasPasscode: hasPasscode, hasWallets: hasWallets), style: .blocks)
|
||||
let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.LogoutOptions_Title), leftNavigationButton: leftNavigationButton, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back))
|
||||
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: logoutOptionsEntries(presentationData: presentationData, canAddAccounts: canAddAccounts, hasPasscode: hasPasscode, hasWallets: hasWallets), style: .blocks)
|
||||
|
||||
return (controllerState, (listState, arguments))
|
||||
}
|
||||
|
@ -510,7 +510,7 @@ private enum NotificationExceptionEntry : ItemListNodeEntry {
|
||||
case addException(PresentationTheme, PresentationStrings, NotificationExceptionMode.Mode, Bool)
|
||||
case removeAll(PresentationTheme, PresentationStrings)
|
||||
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! NotificationExceptionArguments
|
||||
switch self {
|
||||
case let .search(theme, strings):
|
||||
@ -527,11 +527,11 @@ private enum NotificationExceptionEntry : ItemListNodeEntry {
|
||||
case .channels:
|
||||
icon = PresentationResourcesItemList.addChannelIcon(theme)
|
||||
}
|
||||
return ItemListPeerActionItem(theme: theme, icon: icon, title: strings.Notification_Exceptions_AddException, alwaysPlain: true, sectionId: self.section, editing: editing, action: {
|
||||
return ItemListPeerActionItem(presentationData: presentationData, icon: icon, title: strings.Notification_Exceptions_AddException, alwaysPlain: true, sectionId: self.section, editing: editing, action: {
|
||||
arguments.selectPeer()
|
||||
})
|
||||
case let .peer(_, peer, theme, strings, dateTimeFormat, nameDisplayOrder, value, _, revealed, editing, isSearching):
|
||||
return ItemListPeerItem(theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: nil, text: .text(value), label: .none, editing: ItemListPeerItemEditing(editable: true, editing: editing, revealed: revealed), switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: {
|
||||
return ItemListPeerItem(presentationData: presentationData, dateTimeFormat: dateTimeFormat, nameDisplayOrder: nameDisplayOrder, account: arguments.account, peer: peer, presence: nil, text: .text(value), label: .none, editing: ItemListPeerItemEditing(editable: true, editing: editing, revealed: revealed), switchValue: nil, enabled: true, selectable: true, sectionId: self.section, action: {
|
||||
arguments.openPeer(peer)
|
||||
}, setPeerIdWithRevealedOptions: { peerId, fromPeerId in
|
||||
arguments.updateRevealedPeerId(peerId)
|
||||
@ -539,12 +539,12 @@ private enum NotificationExceptionEntry : ItemListNodeEntry {
|
||||
arguments.deletePeer(peer)
|
||||
}, hasTopStripe: false, hasTopGroupInset: false, noInsets: isSearching)
|
||||
case let .addPeer(_, peer, theme, strings, _, nameDisplayOrder):
|
||||
return ContactsPeerItem(theme: theme, strings: strings, sortOrder: nameDisplayOrder, displayOrder: nameDisplayOrder, account: arguments.account, peerMode: .peer, peer: .peer(peer: peer, chatPeer: peer), status: .none, enabled: true, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), options: [], actionIcon: .add, index: nil, header: ChatListSearchItemHeader(type: .addToExceptions, theme: theme, strings: strings, actionTitle: nil, action: nil), action: { _ in
|
||||
return ContactsPeerItem(presentationData: presentationData, sortOrder: nameDisplayOrder, displayOrder: nameDisplayOrder, account: arguments.account, peerMode: .peer, peer: .peer(peer: peer, chatPeer: peer), status: .none, enabled: true, selection: .none, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), options: [], actionIcon: .add, index: nil, header: ChatListSearchItemHeader(type: .addToExceptions, theme: theme, strings: strings, actionTitle: nil, action: nil), action: { _ in
|
||||
arguments.openPeer(peer)
|
||||
}, setPeerIdWithRevealedOptions: { _, _ in
|
||||
})
|
||||
case let .removeAll(theme, strings):
|
||||
return ItemListActionItem(theme: theme, title: strings.Notification_Exceptions_DeleteAll, kind: .destructive, alignment: .center, sectionId: self.section, style: .blocks, action: {
|
||||
return ItemListActionItem(presentationData: presentationData, title: strings.Notification_Exceptions_DeleteAll, kind: .destructive, alignment: .center, sectionId: self.section, style: .blocks, action: {
|
||||
arguments.removeAll()
|
||||
})
|
||||
}
|
||||
@ -651,12 +651,12 @@ private struct NotificationExceptionNodeTransition {
|
||||
let animated: Bool
|
||||
}
|
||||
|
||||
private func preparedExceptionsListNodeTransition(theme: PresentationTheme, strings: PresentationStrings, from fromEntries: [NotificationExceptionEntry], to toEntries: [NotificationExceptionEntry], arguments: NotificationExceptionArguments, firstTime: Bool, forceUpdate: Bool, animated: Bool) -> NotificationExceptionNodeTransition {
|
||||
private func preparedExceptionsListNodeTransition(presentationData: ItemListPresentationData, from fromEntries: [NotificationExceptionEntry], to toEntries: [NotificationExceptionEntry], arguments: NotificationExceptionArguments, firstTime: Bool, forceUpdate: Bool, animated: Bool) -> NotificationExceptionNodeTransition {
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries, allUpdated: forceUpdate)
|
||||
|
||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(arguments), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(arguments), directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(presentationData: presentationData, arguments: arguments), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(presentationData: presentationData, arguments: arguments), directionHint: nil) }
|
||||
|
||||
return NotificationExceptionNodeTransition(deletions: deletions, insertions: insertions, updates: updates, firstTime: firstTime, animated: animated)
|
||||
}
|
||||
@ -995,7 +995,7 @@ final class NotificationExceptionsControllerNode: ViewControllerTracingNode {
|
||||
animated = false
|
||||
}
|
||||
|
||||
let transition = preparedExceptionsListNodeTransition(theme: presentationData.theme, strings: presentationData.strings, from: previousEntriesAndPresentationData?.0 ?? [], to: entries, arguments: arguments, firstTime: previousEntriesAndPresentationData == nil, forceUpdate: previousEntriesAndPresentationData?.1 !== presentationData.theme || previousEntriesAndPresentationData?.2 !== presentationData.strings, animated: animated)
|
||||
let transition = preparedExceptionsListNodeTransition(presentationData: ItemListPresentationData(presentationData), from: previousEntriesAndPresentationData?.0 ?? [], to: entries, arguments: arguments, firstTime: previousEntriesAndPresentationData == nil, forceUpdate: previousEntriesAndPresentationData?.1 !== presentationData.theme || previousEntriesAndPresentationData?.2 !== presentationData.strings, animated: animated)
|
||||
|
||||
self?.listNode.keepTopItemOverscrollBackground = entries.count <= 1 ? nil : ListViewKeepTopItemOverscrollBackground(color: presentationData.theme.chatList.backgroundColor, direction: true)
|
||||
|
||||
@ -1152,12 +1152,12 @@ private struct NotificationExceptionsSearchContainerTransition {
|
||||
let isSearching: Bool
|
||||
}
|
||||
|
||||
private func preparedNotificationExceptionsSearchContainerTransition(theme: PresentationTheme, strings: PresentationStrings, from fromEntries: [NotificationExceptionEntry], to toEntries: [NotificationExceptionEntry], arguments: NotificationExceptionArguments, isSearching: Bool, forceUpdate: Bool) -> NotificationExceptionsSearchContainerTransition {
|
||||
private func preparedNotificationExceptionsSearchContainerTransition(presentationData: ItemListPresentationData, from fromEntries: [NotificationExceptionEntry], to toEntries: [NotificationExceptionEntry], arguments: NotificationExceptionArguments, isSearching: Bool, forceUpdate: Bool) -> NotificationExceptionsSearchContainerTransition {
|
||||
let (deleteIndices, indicesAndItems, updateIndices) = mergeListsStableWithUpdates(leftList: fromEntries, rightList: toEntries, allUpdated: forceUpdate)
|
||||
|
||||
let deletions = deleteIndices.map { ListViewDeleteItem(index: $0, directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(arguments), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(arguments), directionHint: nil) }
|
||||
let insertions = indicesAndItems.map { ListViewInsertItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(presentationData: presentationData, arguments: arguments), directionHint: nil) }
|
||||
let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(presentationData: presentationData, arguments: arguments), directionHint: nil) }
|
||||
|
||||
return NotificationExceptionsSearchContainerTransition(deletions: deletions, insertions: insertions, updates: updates, isSearching: isSearching)
|
||||
}
|
||||
@ -1266,7 +1266,7 @@ private final class NotificationExceptionsSearchContainerNode: SearchDisplayCont
|
||||
let entries = notificationsExceptionEntries(presentationData: presentationData, state: state.0, query: state.1, foundPeers: foundPeers)
|
||||
let previousEntriesAndPresentationData = previousEntriesHolder.swap((entries, presentationData.theme, presentationData.strings))
|
||||
|
||||
let transition = preparedNotificationExceptionsSearchContainerTransition(theme: presentationData.theme, strings: presentationData.strings, from: previousEntriesAndPresentationData?.0 ?? [], to: entries, arguments: arguments, isSearching: state.1 != nil && !state.1!.isEmpty, forceUpdate: previousEntriesAndPresentationData?.1 !== presentationData.theme || previousEntriesAndPresentationData?.2 !== presentationData.strings)
|
||||
let transition = preparedNotificationExceptionsSearchContainerTransition(presentationData: ItemListPresentationData(presentationData), from: previousEntriesAndPresentationData?.0 ?? [], to: entries, arguments: arguments, isSearching: state.1 != nil && !state.1!.isEmpty, forceUpdate: previousEntriesAndPresentationData?.1 !== presentationData.theme || previousEntriesAndPresentationData?.2 !== presentationData.strings)
|
||||
|
||||
self?.enqueueTransition(transition)
|
||||
}))
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user