Merge commit '2db0d25dd26614aabe94ea311611a9cbdb4ea177'

This commit is contained in:
Peter
2019-10-29 23:29:21 +04:00
15 changed files with 115 additions and 62 deletions

View File

@@ -105,6 +105,8 @@ private final class DateSelectionActionSheetItemNode: ActionSheetItemNode {
self.pickerView = UIDatePicker()
self.pickerView.timeZone = TimeZone(secondsFromGMT: 0)
self.pickerView.setValue(theme.primaryTextColor, forKey: "textColor")
self.pickerView.datePickerMode = .countDownTimer
self.pickerView.datePickerMode = .date
self.pickerView.date = Date(timeIntervalSince1970: Double(roundDateToDays(currentValue)))
self.pickerView.locale = localeWithStrings(strings)
@@ -117,8 +119,6 @@ private final class DateSelectionActionSheetItemNode: ActionSheetItemNode {
self.pickerView.maximumDate = Date(timeIntervalSince1970: Double(Int32.max - 1))
}
self.pickerView.setValue(theme.primaryTextColor, forKey: "textColor")
super.init(theme: theme)
self.view.addSubview(self.pickerView)

View File

@@ -48,6 +48,11 @@ static const void *positionChangedKey = &positionChangedKey;
self.backgroundColor = [UIColor redColor];
self.tintColor = [UIColor redColor];
UIView *handleView = self.subviews[0].subviews.lastObject;
if (iosMajorVersion() >= 13) {
handleView = self.subviews[0].subviews[1].subviews.lastObject;
} else {
handleView = self.subviews[0].subviews.lastObject;
}
static Class subclass;
static dispatch_once_t onceToken;

View File

@@ -94,14 +94,14 @@ private final class PeerBanTimeoutActionSheetItemNode: ActionSheetItemNode {
self.valueChanged = valueChanged
self.pickerView = UIDatePicker()
self.pickerView.setValue(theme.primaryTextColor, forKey: "textColor")
self.pickerView.datePickerMode = .countDownTimer
self.pickerView.datePickerMode = .date
self.pickerView.date = Date(timeIntervalSince1970: Double(roundDateToDays(currentValue)))
self.pickerView.locale = localeWithStrings(strings)
self.pickerView.minimumDate = Date()
self.pickerView.maximumDate = Date(timeIntervalSince1970: Double(Int32.max - 1))
self.pickerView.setValue(theme.primaryTextColor, forKey: "textColor")
super.init(theme: theme)
self.view.addSubview(self.pickerView)

View File

@@ -12,7 +12,33 @@ public enum QrCodeIcon {
case custom(UIImage?)
}
public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = nil, icon: QrCodeIcon, ecl: String = "M") -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> {
private func floorToContextPixels(_ value: CGFloat, scale: CGFloat? = UIScreenScale) -> CGFloat {
var scale = scale ?? UIScreenScale
return floor(value * scale) / scale
}
private func roundToContextPixels(_ value: CGFloat, scale: CGFloat? = UIScreenScale) -> CGFloat {
var scale = scale ?? UIScreenScale
return round(value * scale) / scale
}
public func qrCodeCutout(size: Int, dimensions: CGSize, scale: CGFloat?) -> (Int, CGRect, CGFloat) {
var cutoutSize = Int(round(CGFloat(size) * 0.297))
if size == 39 {
cutoutSize = 11
} else if cutoutSize % 2 == 0 {
cutoutSize += 1
}
cutoutSize = min(23, cutoutSize)
let quadSize = floorToContextPixels(dimensions.width / CGFloat(size), scale: scale)
let cutoutSide = quadSize * CGFloat(cutoutSize - 2)
let cutoutRect = CGRect(x: floorToContextPixels((dimensions.width - cutoutSide) / 2.0, scale: scale), y: floorToContextPixels((dimensions.height - cutoutSide) / 2.0, scale: scale), width: cutoutSide, height: cutoutSide)
return (cutoutSize, cutoutRect, quadSize)
}
public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = nil, icon: QrCodeIcon, ecl: String = "M") -> Signal<(Int, (TransformImageArguments) -> DrawingContext?), NoError> {
return Signal<(Data, Int, Int), NoError> { subscriber in
if let data = string.data(using: .isoLatin1, allowLossyConversion: false), let filter = CIFilter(name: "CIQRCodeGenerator") {
filter.setValue(data, forKey: "inputMessage")
@@ -43,29 +69,20 @@ public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = n
return EmptyDisposable
}
|> map { data, size, bytesPerRow in
return { arguments in
return (size, { arguments in
let context = DrawingContext(size: arguments.drawingSize, scale: arguments.scale ?? 0.0, clear: true)
let side = floorToScreenPixels(arguments.drawingSize.width / CGFloat(size))
let padding: CGFloat = floor((arguments.drawingSize.width - CGFloat(side * CGFloat(size))) / 2.0)
let drawingRect = arguments.drawingRect
let fittedSize = arguments.imageSize.aspectFilled(arguments.boundingSize).fitted(arguments.imageSize)
let fittedRect = CGRect(origin: CGPoint(x: drawingRect.origin.x + (drawingRect.size.width - fittedSize.width) / 2.0, y: drawingRect.origin.y + (drawingRect.size.height - fittedSize.height) / 2.0), size: fittedSize)
let codeScale: CGFloat = 1.10256
let clipSide = fittedRect.width * 0.23124
let clipRect = CGRect(x: fittedRect.midX - clipSide / 2.0, y: fittedRect.midY - clipSide / 2.0, width: clipSide, height: clipSide)
let (cutoutSize, clipRect, side) = qrCodeCutout(size: size, dimensions: fittedSize, scale: arguments.scale)
let padding: CGFloat = roundToContextPixels((arguments.drawingSize.width - CGFloat(side * CGFloat(size))) / 2.0, scale: arguments.scale)
let cutout: (Int, Int)?
if case .none = icon {
cutout = nil
} else {
var cutoutSize = Int(ceil((clipSide + side * 2.0) / side))
if size == 39 {
cutoutSize = 11
} else if cutoutSize % 2 == 0 {
cutoutSize += 1
}
let start = (size - cutoutSize) / 2
cutout = (start, start + cutoutSize - 1)
}
@@ -211,7 +228,7 @@ public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = n
c.setStrokeColor(color.cgColor)
c.setFillColor(color.cgColor)
let markerSide = floorToScreenPixels(CGFloat(markerSize - 1) * squareSize.width * 1.05)
let markerSide = floorToContextPixels(CGFloat(markerSize - 1) * squareSize.width * 1.05, scale: arguments.scale)
func drawMarker(x: CGFloat, y: CGFloat) {
var path = UIBezierPath(roundedRect: CGRect(x: x + squareSize.width / 2.0, y: y + squareSize.width / 2.0, width: markerSide, height: markerSide), cornerRadius: markerSide / 3.5)
@@ -233,7 +250,7 @@ public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = n
switch icon {
case .proxy:
let iconScale = fittedRect.width / 420.0 * codeScale
let iconScale = clipRect.size.width * 0.01111
let iconSize = CGSize(width: 65.0 * iconScale, height: 79.0 * iconScale)
let point = CGPoint(x: fittedRect.midX - iconSize.width / 2.0, y: fittedRect.midY - iconSize.height / 2.0)
c.translateBy(x: point.x, y: point.y)
@@ -268,6 +285,6 @@ public func qrCode(string: String, color: UIColor, backgroundColor: UIColor? = n
}
return context
}
})
}
}

View File

@@ -41,8 +41,8 @@ public final class ShareProxyServerActionSheetController: ActionSheetController
items.append(ActionSheetButtonItem(title: strings.SocksProxySetup_ShareQRCode, action: { [weak self] in
self?.dismissAnimated()
let _ = (qrCode(string: link, color: .black, backgroundColor: .white, icon: .proxy)
|> map { generator -> UIImage? in
let imageSize = CGSize(width: 512.0, height: 512.0)
|> map { _, generator -> UIImage? in
let imageSize = CGSize(width: 768.0, height: 768.0)
let context = generator(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets(), scale: 1.0))
return context?.generateImage()
}
@@ -128,7 +128,9 @@ private final class ProxyServerQRCodeItemNode: ActionSheetItemNode {
self.label.attributedText = NSAttributedString(string: strings.SocksProxySetup_ShareQRCodeInfo, font: ActionSheetTextNode.defaultFont, textColor: self.theme.secondaryTextColor, paragraphAlignment: .center)
self.imageNode = TransformImageNode()
self.imageNode.setSignal(qrCode(string: link, color: .black, backgroundColor: .white, icon: .proxy), attemptSynchronously: true)
self.imageNode.clipsToBounds = true
self.imageNode.setSignal(qrCode(string: link, color: .black, backgroundColor: .white, icon: .proxy) |> map { $0.1 }, attemptSynchronously: true)
self.imageNode.cornerRadius = 14.0
super.init(theme: theme)

View File

@@ -245,7 +245,7 @@ private enum ThemeAutoNightSettingsControllerEntry: ItemListNodeEntry {
case let .themeHeader(theme, title):
return ItemListSectionHeaderItem(theme: theme, text: title, sectionId: self.section)
case let .themeItem(theme, strings, themes, currentTheme, themeSpecificAccentColors):
return ThemeSettingsThemeItem(context: arguments.context, theme: theme, strings: strings, sectionId: self.section, themes: themes, themeSpecificAccentColors: themeSpecificAccentColors, currentTheme: currentTheme, updatedTheme: { theme in
return ThemeSettingsThemeItem(context: arguments.context, theme: theme, strings: strings, sectionId: self.section, themes: themes, displayUnsupported: false, themeSpecificAccentColors: themeSpecificAccentColors, currentTheme: currentTheme, updatedTheme: { theme in
arguments.updateTheme(theme)
}, contextAction: nil)
}

View File

@@ -99,13 +99,13 @@ private final class ThemeAutoNightTimeSelectionActionSheetItemNode: ActionSheetI
self.valueChanged = valueChanged
self.pickerView = UIDatePicker()
self.pickerView.setValue(theme.primaryTextColor, forKey: "textColor")
self.pickerView.datePickerMode = .countDownTimer
self.pickerView.datePickerMode = .time
self.pickerView.timeZone = TimeZone(secondsFromGMT: 0)
self.pickerView.date = Date(timeIntervalSince1970: Double(currentValue))
self.pickerView.locale = Locale.current
self.pickerView.setValue(theme.primaryTextColor, forKey: "textColor")
super.init(theme: theme)
self.view.addSubview(self.pickerView)

View File

@@ -319,7 +319,7 @@ private enum ThemeSettingsControllerEntry: ItemListNodeEntry {
case let .themeListHeader(theme, text):
return ItemListSectionHeaderItem(theme: theme, text: text, sectionId: self.section)
case let .themeItem(theme, strings, themes, currentTheme, themeSpecificAccentColors, _):
return ThemeSettingsThemeItem(context: arguments.context, theme: theme, strings: strings, sectionId: self.section, themes: themes, themeSpecificAccentColors: themeSpecificAccentColors, currentTheme: currentTheme, updatedTheme: { theme in
return ThemeSettingsThemeItem(context: arguments.context, theme: theme, strings: strings, sectionId: self.section, themes: themes, displayUnsupported: true, themeSpecificAccentColors: themeSpecificAccentColors, currentTheme: currentTheme, updatedTheme: { theme in
if case let .cloud(theme) = theme, theme.theme.file == nil {
if theme.theme.isCreator {
arguments.editTheme(theme)

View File

@@ -87,17 +87,19 @@ class ThemeSettingsThemeItem: ListViewItem, ItemListItem {
let theme: PresentationTheme
let strings: PresentationStrings
let themes: [PresentationThemeReference]
let displayUnsupported: Bool
let themeSpecificAccentColors: [Int64: PresentationThemeAccentColor]
let currentTheme: PresentationThemeReference
let updatedTheme: (PresentationThemeReference) -> Void
let contextAction: ((PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void)?
let tag: ItemListItemTag?
init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, sectionId: ItemListSectionId, themes: [PresentationThemeReference], themeSpecificAccentColors: [Int64: PresentationThemeAccentColor], currentTheme: PresentationThemeReference, updatedTheme: @escaping (PresentationThemeReference) -> Void, contextAction: ((PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void)?, tag: ItemListItemTag? = nil) {
init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, sectionId: ItemListSectionId, themes: [PresentationThemeReference], displayUnsupported: Bool, themeSpecificAccentColors: [Int64: PresentationThemeAccentColor], currentTheme: PresentationThemeReference, updatedTheme: @escaping (PresentationThemeReference) -> Void, contextAction: ((PresentationThemeReference, ASDisplayNode, ContextGesture?) -> Void)?, tag: ItemListItemTag? = nil) {
self.context = context
self.theme = theme
self.strings = strings
self.themes = themes
self.displayUnsupported = displayUnsupported
self.themeSpecificAccentColors = themeSpecificAccentColors
self.currentTheme = currentTheme
self.updatedTheme = updatedTheme
@@ -389,6 +391,10 @@ class ThemeSettingsThemeItemNode: ListViewItemNode, ItemListItemNode {
var i = 0
for theme in item.themes {
if !item.displayUnsupported, case let .cloud(theme) = theme, theme.theme.file == nil {
continue
}
let imageNode: ThemeSettingsThemeItemIconNode
if strongSelf.nodes.count > i {
imageNode = strongSelf.nodes[i]

View File

@@ -84,14 +84,14 @@ private final class ChatDateSelectorItemNode: ActionSheetItemNode {
self.valueChanged = valueChanged
self.pickerView = UIDatePicker()
self.pickerView.setValue(theme.primaryTextColor, forKey: "textColor")
self.pickerView.datePickerMode = .countDownTimer
self.pickerView.datePickerMode = .date
self.pickerView.locale = Locale(identifier: strings.baseLanguageCode)
self.pickerView.setValue(theme.primaryTextColor, forKey: "textColor")
self.pickerView.minimumDate = Date(timeIntervalSince1970: 1376438400.0)
self.pickerView.maximumDate = Date(timeIntervalSinceNow: 2.0)
super.init(theme: theme)
self.view.addSubview(self.pickerView)

View File

@@ -134,11 +134,12 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
let pickerView = UIDatePicker()
pickerView.timeZone = TimeZone(secondsFromGMT: 0)
pickerView.setValue(self.presentationData.theme.actionSheet.primaryTextColor, forKey: "textColor")
pickerView.datePickerMode = .countDownTimer
pickerView.datePickerMode = .dateAndTime
pickerView.locale = Locale.current
pickerView.timeZone = TimeZone.current
pickerView.minuteInterval = 1
pickerView.setValue(self.presentationData.theme.actionSheet.primaryTextColor, forKey: "textColor")
self.contentContainerNode.view.addSubview(pickerView)
pickerView.addTarget(self, action: #selector(self.datePickerUpdated), for: .valueChanged)
self.pickerView = pickerView
@@ -315,14 +316,14 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
var buttonOffset: CGFloat = 0.0
if case .scheduledMessages(true) = self.mode {
buttonOffset += 44.0
buttonOffset += 60.0
}
let bottomInset: CGFloat = 10.0 + cleanInsets.bottom
let titleHeight: CGFloat = 54.0
var contentHeight = titleHeight + bottomInset + 52.0 + 17.0 + buttonOffset
let pickerHeight: CGFloat = min(216.0, layout.size.height - contentHeight - buttonOffset)
contentHeight = titleHeight + bottomInset + 52.0 + 17.0 + pickerHeight
var contentHeight = titleHeight + bottomInset + 52.0 + 17.0
let pickerHeight: CGFloat = min(216.0, layout.size.height - contentHeight)
contentHeight = titleHeight + bottomInset + 52.0 + 17.0 + pickerHeight + buttonOffset
let width = horizontalContainerFillingSizeForLayout(layout: layout, sideInset: layout.safeInsets.left)
@@ -351,7 +352,7 @@ class ChatScheduleTimeControllerNode: ViewControllerTracingNode, UIScrollViewDel
transition.updateFrame(node: self.doneButton, frame: CGRect(x: buttonInset, y: contentHeight - buttonHeight - insets.bottom - 10.0 - buttonOffset, width: contentFrame.width, height: buttonHeight))
let onlineSize = self.onlineButton.measure(CGSize(width: width, height: titleHeight))
let onlineFrame = CGRect(origin: CGPoint(x: ceil((layout.size.width - onlineSize.width) / 2.0), y: contentHeight - 36.0 - insets.bottom), size: onlineSize)
let onlineFrame = CGRect(origin: CGPoint(x: ceil((layout.size.width - onlineSize.width) / 2.0), y: contentHeight - 45.0 - insets.bottom), size: onlineSize)
transition.updateFrame(node: self.onlineButton, frame: onlineFrame)
self.pickerView?.frame = CGRect(origin: CGPoint(x: 0.0, y: 54.0), size: CGSize(width: contentFrame.width, height: pickerHeight))

View File

@@ -504,15 +504,22 @@ func openChatTheme(context: AccountContext, message: Message, pushController: @e
} else if let contentFile = content.file, contentFile.mimeType == mimeType {
file = contentFile
}
if case let .theme(slug) = resolvedUrl, let file = file {
if let path = context.sharedContext.accountManager.mediaBox.completedResourcePath(file.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead), let theme = makePresentationTheme(data: data) {
let controller = ThemePreviewController(context: context, previewTheme: theme, source: .slug(slug, file))
pushController(controller)
}
} else {
let displayUnsupportedAlert: () -> Void = {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
present(textAlertController(context: context, title: nil, text: presentationData.strings.Theme_Unsupported, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
}
if case let .theme(slug) = resolvedUrl, let file = file {
if let path = context.sharedContext.accountManager.mediaBox.completedResourcePath(file.resource), let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .mappedRead) {
if let theme = makePresentationTheme(data: data) {
let controller = ThemePreviewController(context: context, previewTheme: theme, source: .slug(slug, file))
pushController(controller)
} else {
displayUnsupportedAlert()
}
}
} else {
displayUnsupportedAlert()
}
})
}
}

View File

@@ -22,12 +22,11 @@ private let identifierDelimiterSet: CharacterSet = {
var set = CharacterSet.punctuationCharacters
set.formUnion(CharacterSet.whitespacesAndNewlines)
set.insert("|")
set.insert("/")
return set
}()
private let externalIdentifierDelimiterSet: CharacterSet = {
var set = CharacterSet.punctuationCharacters
set.formUnion(CharacterSet.whitespacesAndNewlines)
set.insert("|")
var set = identifierDelimiterSet
set.remove(".")
return set
}()
@@ -196,8 +195,10 @@ public func generateTextEntities(_ text: String, enabledTypes: EnabledEntityType
if let scalar = scalar {
if scalar == "/" {
notFound = false
if previousScalar != nil && !delimiterSet.contains(previousScalar!) {
currentEntity = nil
if let previousScalar = previousScalar, !delimiterSet.contains(previousScalar) {
if let entity = currentEntity, entity.0 == .command {
currentEntity = nil
}
} else {
if let (type, range) = currentEntity {
commitEntity(utf16, type, range, enabledTypes, &entities)

View File

@@ -10,7 +10,7 @@ import SolidRoundedButtonNode
private func shareInvoiceQrCode(context: WalletContext, invoice: String) {
let _ = (qrCode(string: invoice, color: .black, backgroundColor: .white, icon: .custom(UIImage(bundleImageName: "Wallet/QrGem")))
|> map { generator -> UIImage? in
|> map { _, generator -> UIImage? in
let imageSize = CGSize(width: 768.0, height: 768.0)
let context = generator(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: imageSize, intrinsicInsets: UIEdgeInsets(), scale: 1.0))
return context?.generateImage()
@@ -151,12 +151,15 @@ private final class WalletReceiveScreenNode: ViewControllerTracingNode {
private let qrButtonNode: HighlightTrackingButtonNode
private let qrImageNode: TransformImageNode
private let qrIconNode: AnimatedStickerNode
private var qrCodeSize: Int?
private let urlTextNode: ImmediateTextNode
private let buttonNode: SolidRoundedButtonNode
private let secondaryButtonNode: HighlightableButtonNode
private var validLayout: (ContainerViewLayout, CGFloat)?
var openCreateInvoice: (() -> Void)?
var displayCopyContextMenu: ((ASDisplayNode, CGRect, String) -> Void)?
@@ -202,7 +205,15 @@ private final class WalletReceiveScreenNode: ViewControllerTracingNode {
self.addSubnode(self.buttonNode)
self.addSubnode(self.secondaryButtonNode)
self.qrImageNode.setSignal(qrCode(string: urlForMode(mode), color: .black, backgroundColor: .white, icon: .cutout), attemptSynchronously: true)
self.qrImageNode.setSignal(qrCode(string: urlForMode(mode), color: .black, backgroundColor: .white, icon: .cutout) |> beforeNext { [weak self] size, _ in
guard let strongSelf = self else {
return
}
strongSelf.qrCodeSize = size
if let (layout, navigationHeight) = strongSelf.validLayout {
strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate)
}
} |> map { $0.1 }, attemptSynchronously: true)
self.qrButtonNode.addTarget(self, action: #selector(self.qrPressed), forControlEvents: .touchUpInside)
self.qrButtonNode.highligthedChanged = { [weak self] highlighted in
@@ -275,6 +286,8 @@ private final class WalletReceiveScreenNode: ViewControllerTracingNode {
}
func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) {
self.validLayout = (layout, navigationHeight)
var insets = layout.insets(options: [])
insets.top += navigationHeight
let inset: CGFloat = 22.0
@@ -295,11 +308,12 @@ private final class WalletReceiveScreenNode: ViewControllerTracingNode {
transition.updateFrame(node: self.qrImageNode, frame: imageFrame)
transition.updateFrame(node: self.qrButtonNode, frame: imageFrame)
let iconSide = floor(imageSide * 0.24)
let iconSize = CGSize(width: iconSide, height: iconSide)
self.qrIconNode.updateLayout(size: iconSize)
transition.updateBounds(node: self.qrIconNode, bounds: CGRect(origin: CGPoint(), size: iconSize))
transition.updatePosition(node: self.qrIconNode, position: imageFrame.center.offsetBy(dx: 0.0, dy: -1.0))
if let qrCodeSize = self.qrCodeSize {
let (_, cutoutFrame, _) = qrCodeCutout(size: qrCodeSize, dimensions: imageSize, scale: nil)
self.qrIconNode.updateLayout(size: cutoutFrame.size)
transition.updateBounds(node: self.qrIconNode, bounds: CGRect(origin: CGPoint(), size: cutoutFrame.size))
transition.updatePosition(node: self.qrIconNode, position: imageFrame.center.offsetBy(dx: 0.0, dy: -1.0))
}
if self.urlTextNode.attributedText?.string.isEmpty ?? true {
var url = urlForMode(self.mode)

View File

@@ -427,21 +427,21 @@ private final class WalletTransactionInfoScreenNode: ViewControllerTracingNode,
var feesString: String = ""
if case let .completed(transaction) = walletTransaction {
if transaction.storageFee != 0 {
feesString.append(formatBalanceText(transaction.storageFee, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator) + " storage fee")
}
if transaction.otherFee != 0 {
feesString.append(formatBalanceText(transaction.otherFee, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator) + " transaction fee")
}
if transaction.storageFee != 0 {
if !feesString.isEmpty {
feesString.append("\n")
}
feesString.append(formatBalanceText(transaction.otherFee, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator) + " transaction fee")
feesString.append(formatBalanceText(transaction.storageFee, decimalSeparator: presentationData.dateTimeFormat.decimalSeparator) + " storage fee")
}
self.feesInfoIconNode.isHidden = feesString.isEmpty
}
self.feesNode.attributedText = NSAttributedString(string: feesString, font: subtitleFont, textColor: seccondaryTextColor)
self.feesButtonNode.addTarget(self, action: #selector(feesPressed), forControlEvents: .touchUpInside)
self.feesButtonNode.addTarget(self, action: #selector(self.feesPressed), forControlEvents: .touchUpInside)
var commentBackgroundColor = presentationData.theme.transaction.descriptionBackgroundColor
if commentBackgroundColor.distance(to: presentationData.theme.list.plainBackgroundColor) < 100 {