mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Fix wallet issues
This commit is contained in:
parent
6502e9bd4d
commit
7805b4ccc0
@ -609,7 +609,9 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
self.resetHeaderItemsFlashTimer(start: true)
|
||||
self.updateHeaderItemsFlashing(animated: true)
|
||||
self.resetScrollIndicatorFlashTimer(start: true)
|
||||
self.didEndScrolling?()
|
||||
if !scrollView.isTracking {
|
||||
self.didEndScrolling?()
|
||||
}
|
||||
}
|
||||
|
||||
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
@ -3945,6 +3947,16 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture
|
||||
}
|
||||
}
|
||||
|
||||
public func scrollToOffsetFromTop(_ offset: CGFloat) -> Bool {
|
||||
for itemNode in self.itemNodes {
|
||||
if itemNode.index == 0 {
|
||||
self.scroller.setContentOffset(CGPoint(x: 0.0, y: offset), animated: true)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
public func scrollWithDirection(_ direction: ListViewScrollDirection, distance: CGFloat) -> Bool {
|
||||
var accessibilityFocusedNode: (ASDisplayNode, CGRect)?
|
||||
for itemNode in self.itemNodes {
|
||||
|
BIN
submodules/WalletUI/Resources/Animations/WalletInitializing.tgs
Normal file
BIN
submodules/WalletUI/Resources/Animations/WalletInitializing.tgs
Normal file
Binary file not shown.
Binary file not shown.
@ -0,0 +1,516 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import AsyncDisplayKit
|
||||
import SwiftSignalKit
|
||||
|
||||
enum ItemListDisclosureItemTitleColor {
|
||||
case primary
|
||||
case accent
|
||||
}
|
||||
|
||||
enum ItemListDisclosureStyle {
|
||||
case arrow
|
||||
case none
|
||||
}
|
||||
|
||||
enum ItemListDisclosureLabelStyle {
|
||||
case text
|
||||
case detailText
|
||||
case multilineDetailText
|
||||
case badge(UIColor)
|
||||
case color(UIColor)
|
||||
}
|
||||
|
||||
class ItemListDisclosureItem: ListViewItem, ItemListItem {
|
||||
let theme: WalletTheme
|
||||
let icon: UIImage?
|
||||
let title: String
|
||||
let titleColor: ItemListDisclosureItemTitleColor
|
||||
let enabled: Bool
|
||||
let label: String
|
||||
let labelStyle: ItemListDisclosureLabelStyle
|
||||
let sectionId: ItemListSectionId
|
||||
let style: ItemListStyle
|
||||
let disclosureStyle: ItemListDisclosureStyle
|
||||
let action: (() -> Void)?
|
||||
let clearHighlightAutomatically: Bool
|
||||
let tag: ItemListItemTag?
|
||||
|
||||
init(theme: WalletTheme, 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
|
||||
self.icon = icon
|
||||
self.title = title
|
||||
self.titleColor = titleColor
|
||||
self.enabled = enabled
|
||||
self.labelStyle = labelStyle
|
||||
self.label = label
|
||||
self.sectionId = sectionId
|
||||
self.style = style
|
||||
self.disclosureStyle = disclosureStyle
|
||||
self.action = action
|
||||
self.clearHighlightAutomatically = clearHighlightAutomatically
|
||||
self.tag = tag
|
||||
}
|
||||
|
||||
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) {
|
||||
async {
|
||||
let node = ItemListDisclosureItemNode()
|
||||
let (layout, apply) = node.asyncLayout()(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem))
|
||||
|
||||
node.contentSize = layout.contentSize
|
||||
node.insets = layout.insets
|
||||
|
||||
Queue.mainQueue().async {
|
||||
completion(node, {
|
||||
return (nil, { _ in apply() })
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: @escaping () -> ListViewItemNode, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping (ListViewItemApply) -> Void) -> Void) {
|
||||
Queue.mainQueue().async {
|
||||
if let nodeValue = node() as? ItemListDisclosureItemNode {
|
||||
let makeLayout = nodeValue.asyncLayout()
|
||||
|
||||
async {
|
||||
let (layout, apply) = makeLayout(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem))
|
||||
Queue.mainQueue().async {
|
||||
completion(layout, { _ in
|
||||
apply()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var selectable: Bool = true
|
||||
|
||||
func selected(listView: ListView){
|
||||
if self.clearHighlightAutomatically {
|
||||
listView.clearHighlightAnimated(true)
|
||||
}
|
||||
if self.enabled {
|
||||
self.action?()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private let titleFont = Font.regular(17.0)
|
||||
private let badgeFont = Font.regular(15.0)
|
||||
private let detailFont = Font.regular(13.0)
|
||||
|
||||
class ItemListDisclosureItemNode: ListViewItemNode, ItemListItemNode {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let topStripeNode: ASDisplayNode
|
||||
private let bottomStripeNode: ASDisplayNode
|
||||
private let highlightedBackgroundNode: ASDisplayNode
|
||||
private let maskNode: ASImageNode
|
||||
|
||||
let iconNode: ASImageNode
|
||||
let titleNode: TextNode
|
||||
let labelNode: TextNode
|
||||
let arrowNode: ASImageNode
|
||||
let labelBadgeNode: ASImageNode
|
||||
let labelImageNode: ASImageNode
|
||||
|
||||
private let activateArea: AccessibilityAreaNode
|
||||
|
||||
private var item: ItemListDisclosureItem?
|
||||
|
||||
override var canBeSelected: Bool {
|
||||
if let item = self.item, let _ = item.action {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
var tag: ItemListItemTag? {
|
||||
return self.item?.tag
|
||||
}
|
||||
|
||||
init() {
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
self.backgroundNode.isLayerBacked = true
|
||||
self.backgroundNode.backgroundColor = .white
|
||||
|
||||
self.maskNode = ASImageNode()
|
||||
|
||||
self.topStripeNode = ASDisplayNode()
|
||||
self.topStripeNode.isLayerBacked = true
|
||||
|
||||
self.bottomStripeNode = ASDisplayNode()
|
||||
self.bottomStripeNode.isLayerBacked = true
|
||||
|
||||
self.iconNode = ASImageNode()
|
||||
self.iconNode.isLayerBacked = true
|
||||
self.iconNode.displaysAsynchronously = false
|
||||
|
||||
self.titleNode = TextNode()
|
||||
self.titleNode.isUserInteractionEnabled = false
|
||||
|
||||
self.labelNode = TextNode()
|
||||
self.labelNode.isUserInteractionEnabled = false
|
||||
|
||||
self.arrowNode = ASImageNode()
|
||||
self.arrowNode.displayWithoutProcessing = true
|
||||
self.arrowNode.displaysAsynchronously = false
|
||||
self.arrowNode.isLayerBacked = true
|
||||
|
||||
self.labelBadgeNode = ASImageNode()
|
||||
self.labelImageNode = ASImageNode()
|
||||
self.labelBadgeNode.displayWithoutProcessing = true
|
||||
self.labelBadgeNode.displaysAsynchronously = false
|
||||
self.labelBadgeNode.isLayerBacked = true
|
||||
|
||||
self.highlightedBackgroundNode = ASDisplayNode()
|
||||
self.highlightedBackgroundNode.isLayerBacked = true
|
||||
|
||||
self.activateArea = AccessibilityAreaNode()
|
||||
|
||||
super.init(layerBacked: false, dynamicBounce: false)
|
||||
|
||||
self.addSubnode(self.titleNode)
|
||||
self.addSubnode(self.labelNode)
|
||||
self.addSubnode(self.arrowNode)
|
||||
|
||||
self.addSubnode(self.activateArea)
|
||||
}
|
||||
|
||||
func asyncLayout() -> (_ item: ItemListDisclosureItem, _ params: ListViewItemLayoutParams, _ insets: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) {
|
||||
let makeTitleLayout = TextNode.asyncLayout(self.titleNode)
|
||||
let makeLabelLayout = TextNode.asyncLayout(self.labelNode)
|
||||
|
||||
let currentItem = self.item
|
||||
|
||||
let currentHasBadge = self.labelBadgeNode.image != nil
|
||||
|
||||
return { item, params, neighbors in
|
||||
let rightInset: CGFloat
|
||||
switch item.disclosureStyle {
|
||||
case .none:
|
||||
rightInset = 16.0 + params.rightInset
|
||||
case .arrow:
|
||||
rightInset = 34.0 + params.rightInset
|
||||
}
|
||||
|
||||
var updateArrowImage: UIImage?
|
||||
var updatedTheme: WalletTheme?
|
||||
|
||||
var updatedLabelBadgeImage: UIImage?
|
||||
var updatedLabelImage: UIImage?
|
||||
|
||||
var badgeColor: UIColor?
|
||||
if case let .badge(color) = item.labelStyle {
|
||||
if item.label.count > 0 {
|
||||
badgeColor = color
|
||||
}
|
||||
}
|
||||
if case let .color(color) = item.labelStyle {
|
||||
var updatedColor = true
|
||||
if let currentItem = currentItem, case let .color(previousColor) = currentItem.labelStyle, color.isEqual(previousColor) {
|
||||
updatedColor = false
|
||||
}
|
||||
if updatedColor {
|
||||
updatedLabelImage = generateFilledCircleImage(diameter: 17.0, color: color)
|
||||
}
|
||||
}
|
||||
|
||||
let badgeDiameter: CGFloat = 20.0
|
||||
if currentItem?.theme !== item.theme {
|
||||
updatedTheme = item.theme
|
||||
updateArrowImage = disclosureArrowImage(item.theme)
|
||||
if let badgeColor = badgeColor {
|
||||
updatedLabelBadgeImage = generateStretchableFilledCircleImage(diameter: badgeDiameter, color: badgeColor)
|
||||
}
|
||||
} else if let badgeColor = badgeColor, !currentHasBadge {
|
||||
updatedLabelBadgeImage = generateStretchableFilledCircleImage(diameter: badgeDiameter, color: badgeColor)
|
||||
}
|
||||
|
||||
var updateIcon = false
|
||||
if currentItem?.icon != item.icon {
|
||||
updateIcon = true
|
||||
}
|
||||
|
||||
let contentSize: CGSize
|
||||
let insets: UIEdgeInsets
|
||||
let separatorHeight = UIScreenPixel
|
||||
let itemBackgroundColor: UIColor
|
||||
let itemSeparatorColor: UIColor
|
||||
|
||||
var leftInset = 16.0 + params.leftInset
|
||||
if let _ = item.icon {
|
||||
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
|
||||
}
|
||||
|
||||
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 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.plainBackgroundColor
|
||||
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
|
||||
}
|
||||
var multilineLabel = false
|
||||
if case .multilineDetailText = item.labelStyle {
|
||||
multilineLabel = true
|
||||
}
|
||||
|
||||
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 height: CGFloat
|
||||
switch item.labelStyle {
|
||||
case .detailText:
|
||||
height = 64.0
|
||||
case .multilineDetailText:
|
||||
height = 44.0 + labelLayout.size.height
|
||||
default:
|
||||
height = 44.0
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets)
|
||||
|
||||
return (ListViewItemNodeLayout(contentSize: contentSize, insets: insets), { [weak self] in
|
||||
if let strongSelf = self {
|
||||
strongSelf.item = item
|
||||
|
||||
strongSelf.activateArea.frame = CGRect(origin: CGPoint(x: params.leftInset, y: 0.0), size: CGSize(width: params.width - params.leftInset - params.rightInset, height: layout.contentSize.height))
|
||||
strongSelf.activateArea.accessibilityLabel = item.title
|
||||
strongSelf.activateArea.accessibilityValue = item.label
|
||||
if item.enabled {
|
||||
strongSelf.activateArea.accessibilityTraits = []
|
||||
} else {
|
||||
strongSelf.activateArea.accessibilityTraits = .notEnabled
|
||||
}
|
||||
|
||||
if let icon = item.icon {
|
||||
if strongSelf.iconNode.supernode == nil {
|
||||
strongSelf.addSubnode(strongSelf.iconNode)
|
||||
}
|
||||
if updateIcon {
|
||||
strongSelf.iconNode.image = icon
|
||||
}
|
||||
let iconY: CGFloat
|
||||
if case .multilineDetailText = item.labelStyle {
|
||||
iconY = 14.0
|
||||
} else {
|
||||
iconY = floor((layout.contentSize.height - icon.size.height) / 2.0)
|
||||
}
|
||||
strongSelf.iconNode.frame = CGRect(origin: CGPoint(x: params.leftInset + floor((leftInset - params.leftInset - icon.size.width) / 2.0), y: iconY), size: icon.size)
|
||||
} else if strongSelf.iconNode.supernode != nil {
|
||||
strongSelf.iconNode.image = nil
|
||||
strongSelf.iconNode.removeFromSupernode()
|
||||
}
|
||||
|
||||
if let updateArrowImage = updateArrowImage {
|
||||
strongSelf.arrowNode.image = updateArrowImage
|
||||
}
|
||||
|
||||
if let _ = updatedTheme {
|
||||
strongSelf.topStripeNode.backgroundColor = itemSeparatorColor
|
||||
strongSelf.bottomStripeNode.backgroundColor = itemSeparatorColor
|
||||
strongSelf.backgroundNode.backgroundColor = itemBackgroundColor
|
||||
strongSelf.highlightedBackgroundNode.backgroundColor = item.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 ? 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))
|
||||
}
|
||||
|
||||
strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: leftInset, y: 11.0), size: titleLayout.size)
|
||||
|
||||
if let updateBadgeImage = updatedLabelBadgeImage {
|
||||
if strongSelf.labelBadgeNode.supernode == nil {
|
||||
strongSelf.insertSubnode(strongSelf.labelBadgeNode, belowSubnode: strongSelf.labelNode)
|
||||
}
|
||||
strongSelf.labelBadgeNode.image = updateBadgeImage
|
||||
}
|
||||
if badgeColor == nil && strongSelf.labelBadgeNode.supernode != nil {
|
||||
strongSelf.labelBadgeNode.image = nil
|
||||
strongSelf.labelBadgeNode.removeFromSupernode()
|
||||
}
|
||||
|
||||
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 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)
|
||||
case .detailText, .multilineDetailText:
|
||||
labelFrame = CGRect(origin: CGPoint(x: leftInset, y: 36.0), size: labelLayout.size)
|
||||
default:
|
||||
labelFrame = CGRect(origin: CGPoint(x: params.width - rightInset - labelLayout.size.width, y: 11.0), size: labelLayout.size)
|
||||
}
|
||||
strongSelf.labelNode.frame = labelFrame
|
||||
|
||||
if case .color = item.labelStyle {
|
||||
if let updatedLabelImage = updatedLabelImage {
|
||||
strongSelf.labelImageNode.image = updatedLabelImage
|
||||
}
|
||||
if strongSelf.labelImageNode.supernode == nil {
|
||||
strongSelf.addSubnode(strongSelf.labelImageNode)
|
||||
}
|
||||
if let image = strongSelf.labelImageNode.image {
|
||||
strongSelf.labelImageNode.frame = CGRect(origin: CGPoint(x: params.width - params.rightInset - 50.0, y: floor((layout.contentSize.height - image.size.height) / 2.0)), size: image.size)
|
||||
}
|
||||
} else if strongSelf.labelImageNode.supernode != nil {
|
||||
strongSelf.labelImageNode.removeFromSupernode()
|
||||
strongSelf.labelImageNode.image = nil
|
||||
}
|
||||
|
||||
if let arrowImage = strongSelf.arrowNode.image {
|
||||
strongSelf.arrowNode.frame = CGRect(origin: CGPoint(x: params.width - params.rightInset - 7.0 - arrowImage.size.width, y: floorToScreenPixels((height - arrowImage.size.height) / 2.0)), size: arrowImage.size)
|
||||
}
|
||||
|
||||
switch item.disclosureStyle {
|
||||
case .none:
|
||||
strongSelf.arrowNode.isHidden = true
|
||||
case .arrow:
|
||||
strongSelf.arrowNode.isHidden = false
|
||||
}
|
||||
|
||||
strongSelf.highlightedBackgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -UIScreenPixel), size: CGSize(width: params.width, height: height + UIScreenPixel))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
override func setHighlighted(_ highlighted: Bool, at point: CGPoint, animated: Bool) {
|
||||
super.setHighlighted(highlighted, at: point, animated: animated)
|
||||
|
||||
if highlighted && (self.item?.enabled ?? false) {
|
||||
self.highlightedBackgroundNode.alpha = 1.0
|
||||
if self.highlightedBackgroundNode.supernode == nil {
|
||||
var anchorNode: ASDisplayNode?
|
||||
if self.bottomStripeNode.supernode != nil {
|
||||
anchorNode = self.bottomStripeNode
|
||||
} else if self.topStripeNode.supernode != nil {
|
||||
anchorNode = self.topStripeNode
|
||||
} else if self.backgroundNode.supernode != nil {
|
||||
anchorNode = self.backgroundNode
|
||||
}
|
||||
if let anchorNode = anchorNode {
|
||||
self.insertSubnode(self.highlightedBackgroundNode, aboveSubnode: anchorNode)
|
||||
} else {
|
||||
self.addSubnode(self.highlightedBackgroundNode)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if self.highlightedBackgroundNode.supernode != nil {
|
||||
if animated {
|
||||
self.highlightedBackgroundNode.layer.animateAlpha(from: self.highlightedBackgroundNode.alpha, to: 0.0, duration: 0.4, completion: { [weak self] completed in
|
||||
if let strongSelf = self {
|
||||
if completed {
|
||||
strongSelf.highlightedBackgroundNode.removeFromSupernode()
|
||||
}
|
||||
}
|
||||
})
|
||||
self.highlightedBackgroundNode.alpha = 0.0
|
||||
} else {
|
||||
self.highlightedBackgroundNode.removeFromSupernode()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4)
|
||||
}
|
||||
|
||||
override func animateAdded(_ currentTimestamp: Double, duration: Double) {
|
||||
self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
}
|
||||
|
||||
override func animateRemoved(_ currentTimestamp: Double, duration: Double) {
|
||||
self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false)
|
||||
}
|
||||
}
|
@ -11,22 +11,25 @@ private final class WalletConfigurationScreenArguments {
|
||||
let updateState: ((WalletConfigurationScreenState) -> WalletConfigurationScreenState) -> Void
|
||||
let dismissInput: () -> Void
|
||||
let updateSelectedMode: (WalletConfigurationScreenMode) -> Void
|
||||
let updateBlockchainName: (String) -> Void
|
||||
|
||||
init(updateState: @escaping ((WalletConfigurationScreenState) -> WalletConfigurationScreenState) -> Void, dismissInput: @escaping () -> Void, updateSelectedMode: @escaping (WalletConfigurationScreenMode) -> Void) {
|
||||
init(updateState: @escaping ((WalletConfigurationScreenState) -> WalletConfigurationScreenState) -> Void, dismissInput: @escaping () -> Void, updateSelectedMode: @escaping (WalletConfigurationScreenMode) -> Void, updateBlockchainName: @escaping (String) -> Void) {
|
||||
self.updateState = updateState
|
||||
self.dismissInput = dismissInput
|
||||
self.updateSelectedMode = updateSelectedMode
|
||||
self.updateBlockchainName = updateBlockchainName
|
||||
}
|
||||
}
|
||||
|
||||
private enum WalletConfigurationScreenMode {
|
||||
case `default`
|
||||
case url
|
||||
case customString
|
||||
}
|
||||
|
||||
private enum WalletConfigurationScreenSection: Int32 {
|
||||
case mode
|
||||
case configString
|
||||
case blockchainName
|
||||
}
|
||||
|
||||
private enum WalletConfigurationScreenEntryTag: ItemListItemTag {
|
||||
@ -42,27 +45,38 @@ private enum WalletConfigurationScreenEntryTag: ItemListItemTag {
|
||||
}
|
||||
|
||||
private enum WalletConfigurationScreenEntry: ItemListNodeEntry, Equatable {
|
||||
case modeDefault(WalletTheme, String, Bool)
|
||||
case modeUrl(WalletTheme, String, Bool)
|
||||
case modeCustomString(WalletTheme, String, Bool)
|
||||
case configUrl(WalletTheme, WalletStrings, String, String)
|
||||
case configString(WalletTheme, String, String)
|
||||
case blockchainNameHeader(WalletTheme, String)
|
||||
case blockchainName(WalletTheme, WalletStrings, String, String)
|
||||
|
||||
var section: ItemListSectionId {
|
||||
switch self {
|
||||
case .modeDefault, .modeCustomString:
|
||||
case .modeUrl, .modeCustomString:
|
||||
return WalletConfigurationScreenSection.mode.rawValue
|
||||
case .configString:
|
||||
case .configUrl, .configString:
|
||||
return WalletConfigurationScreenSection.configString.rawValue
|
||||
case .blockchainNameHeader, .blockchainName:
|
||||
return WalletConfigurationScreenSection.blockchainName.rawValue
|
||||
}
|
||||
}
|
||||
|
||||
var stableId: Int32 {
|
||||
switch self {
|
||||
case .modeDefault:
|
||||
case .modeUrl:
|
||||
return 0
|
||||
case .modeCustomString:
|
||||
return 1
|
||||
case .configString:
|
||||
case .configUrl:
|
||||
return 2
|
||||
case .configString:
|
||||
return 3
|
||||
case .blockchainNameHeader:
|
||||
return 4
|
||||
case .blockchainName:
|
||||
return 5
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,14 +87,22 @@ private enum WalletConfigurationScreenEntry: ItemListNodeEntry, Equatable {
|
||||
func item(_ arguments: Any) -> ListViewItem {
|
||||
let arguments = arguments as! WalletConfigurationScreenArguments
|
||||
switch self {
|
||||
case let .modeDefault(theme, text, isSelected):
|
||||
case let .modeUrl(theme, text, isSelected):
|
||||
return ItemListCheckboxItem(theme: theme, title: text, style: .left, checked: isSelected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.updateSelectedMode(.default)
|
||||
arguments.updateSelectedMode(.url)
|
||||
})
|
||||
case let .modeCustomString(theme, text, isSelected):
|
||||
return ItemListCheckboxItem(theme: theme, title: text, style: .left, checked: isSelected, zeroSeparatorInsets: false, sectionId: self.section, action: {
|
||||
arguments.updateSelectedMode(.customString)
|
||||
})
|
||||
case let .configUrl(theme, strings, placeholder, text):
|
||||
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: ""), text: text, placeholder: placeholder, sectionId: self.section, textUpdated: { value in
|
||||
arguments.updateState { state in
|
||||
var state = state
|
||||
state.configUrl = value
|
||||
return state
|
||||
}
|
||||
}, action: {})
|
||||
case let .configString(theme, placeholder, text):
|
||||
return ItemListMultilineInputItem(theme: theme, text: text, placeholder: placeholder, maxLength: nil, sectionId: self.section, style: .blocks, capitalization: false, autocorrection: false, returnKeyType: .done, minimalHeight: nil, textUpdated: { value in
|
||||
arguments.updateState { state in
|
||||
@ -91,18 +113,29 @@ private enum WalletConfigurationScreenEntry: ItemListNodeEntry, Equatable {
|
||||
}, shouldUpdateText: { _ in
|
||||
return true
|
||||
}, processPaste: nil, updatedFocus: nil, tag: WalletConfigurationScreenEntryTag.configStringText, action: nil, inlineAction: nil)
|
||||
case let .blockchainNameHeader(theme, title):
|
||||
return ItemListSectionHeaderItem(theme: theme, text: title, sectionId: self.section)
|
||||
case let .blockchainName(theme, strings, title, value):
|
||||
return ItemListSingleLineInputItem(theme: theme, strings: strings, title: NSAttributedString(string: ""), text: value, placeholder: title, sectionId: self.section, textUpdated: { value in
|
||||
arguments.updateBlockchainName(value)
|
||||
}, action: {})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct WalletConfigurationScreenState: Equatable {
|
||||
var mode: WalletConfigurationScreenMode
|
||||
var configUrl: String
|
||||
var configString: String
|
||||
var blockchainName: String
|
||||
|
||||
var isEmpty: Bool {
|
||||
if self.blockchainName.isEmpty {
|
||||
return true
|
||||
}
|
||||
switch self.mode {
|
||||
case .default:
|
||||
return false
|
||||
case .url:
|
||||
return self.configUrl.isEmpty || URL(string: self.configUrl) == nil
|
||||
case .customString:
|
||||
return self.configString.isEmpty
|
||||
}
|
||||
@ -112,16 +145,19 @@ private struct WalletConfigurationScreenState: Equatable {
|
||||
private func walletConfigurationScreenEntries(presentationData: WalletPresentationData, state: WalletConfigurationScreenState) -> [WalletConfigurationScreenEntry] {
|
||||
var entries: [WalletConfigurationScreenEntry] = []
|
||||
|
||||
entries.append(.modeDefault(presentationData.theme, "Default", state.mode == .default))
|
||||
entries.append(.modeUrl(presentationData.theme, "URL", state.mode == .url))
|
||||
entries.append(.modeCustomString(presentationData.theme, "Custom", state.mode == .customString))
|
||||
|
||||
switch state.mode {
|
||||
case .default:
|
||||
break
|
||||
case .url:
|
||||
entries.append(.configUrl(presentationData.theme, presentationData.strings, "URL", state.configUrl))
|
||||
case .customString:
|
||||
entries.append(.configString(presentationData.theme, "", state.configString))
|
||||
entries.append(.configString(presentationData.theme, "JSON", state.configString))
|
||||
}
|
||||
|
||||
entries.append(.blockchainNameHeader(presentationData.theme, "BLOCKCHAIN NAME"))
|
||||
entries.append(.blockchainName(presentationData.theme, presentationData.strings, "Blockchain Name", state.blockchainName))
|
||||
|
||||
return entries
|
||||
}
|
||||
|
||||
@ -134,15 +170,16 @@ private final class WalletConfigurationScreenImpl: ItemListController, WalletCon
|
||||
}
|
||||
}
|
||||
|
||||
func walletConfigurationScreen(context: WalletContext, currentConfiguration: CustomWalletConfiguration?) -> ViewController {
|
||||
func walletConfigurationScreen(context: WalletContext, currentConfiguration: LocalWalletConfiguration) -> ViewController {
|
||||
var configUrl = ""
|
||||
var configString = ""
|
||||
if let currentConfiguration = currentConfiguration {
|
||||
switch currentConfiguration {
|
||||
case let .string(string):
|
||||
configString = string
|
||||
}
|
||||
switch currentConfiguration.source {
|
||||
case let .url(url):
|
||||
configUrl = url
|
||||
case let .string(string):
|
||||
configString = string
|
||||
}
|
||||
let initialState = WalletConfigurationScreenState(mode: currentConfiguration == nil ? .default : .customString, configString: configString)
|
||||
let initialState = WalletConfigurationScreenState(mode: configString.isEmpty ? .url : .customString, configUrl: configUrl, configString: configString, blockchainName: currentConfiguration.blockchainName)
|
||||
let statePromise = ValuePromise(initialState, ignoreRepeated: true)
|
||||
let stateValue = Atomic(value: initialState)
|
||||
let updateState: ((WalletConfigurationScreenState) -> WalletConfigurationScreenState) -> Void = { f in
|
||||
@ -166,6 +203,12 @@ func walletConfigurationScreen(context: WalletContext, currentConfiguration: Cus
|
||||
state.mode = mode
|
||||
return state
|
||||
}
|
||||
}, updateBlockchainName: { value in
|
||||
updateState { state in
|
||||
var state = state
|
||||
state.blockchainName = value
|
||||
return state
|
||||
}
|
||||
})
|
||||
|
||||
let signal = combineLatest(queue: .mainQueue(), .single(context.presentationData), statePromise.get())
|
||||
@ -175,19 +218,34 @@ func walletConfigurationScreen(context: WalletContext, currentConfiguration: Cus
|
||||
})
|
||||
let rightNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Wallet_Configuration_Apply), style: .bold, enabled: !state.isEmpty, action: {
|
||||
let state = stateValue.with { $0 }
|
||||
let configuration: CustomWalletConfiguration?
|
||||
let source: LocalWalletConfigurationSource
|
||||
let blockchainName = state.blockchainName
|
||||
if blockchainName.isEmpty {
|
||||
return
|
||||
}
|
||||
switch state.mode {
|
||||
case .default:
|
||||
configuration = nil
|
||||
case .url:
|
||||
if state.configUrl.isEmpty {
|
||||
return
|
||||
} else {
|
||||
source = .url(state.configUrl)
|
||||
}
|
||||
case .customString:
|
||||
if state.configString.isEmpty {
|
||||
configuration = nil
|
||||
return
|
||||
} else {
|
||||
configuration = .string(state.configString)
|
||||
source = .string(state.configString)
|
||||
}
|
||||
}
|
||||
context.storage.updateCustomWalletConfiguration(configuration)
|
||||
dismissImpl?()
|
||||
let _ = (context.storage.updateLocalWalletConfiguration { current in
|
||||
var current = current
|
||||
current.source = source
|
||||
current.blockchainName = blockchainName
|
||||
return current
|
||||
}
|
||||
|> deliverOnMainQueue).start(completed: {
|
||||
dismissImpl?()
|
||||
})
|
||||
})
|
||||
|
||||
let controllerState = ItemListControllerState(theme: presentationData.theme, title: .text(presentationData.strings.Wallet_Configuration_Title), leftNavigationButton: nil, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Wallet_Navigation_Back), animateChanges: false)
|
||||
|
@ -15,6 +15,8 @@ public protocol WalletContext {
|
||||
var presentationData: WalletPresentationData { get }
|
||||
|
||||
var supportsCustomConfigurations: Bool { get }
|
||||
var termsUrl: String? { get }
|
||||
var feeInfoUrl: String? { get }
|
||||
|
||||
var inForeground: Signal<Bool, NoError> { get }
|
||||
|
||||
|
@ -10,14 +10,16 @@ class WalletInfoEmptyItem: ListViewItem {
|
||||
let theme: WalletTheme
|
||||
let strings: WalletStrings
|
||||
let address: String
|
||||
let loading: Bool
|
||||
let displayAddressContextMenu: (ASDisplayNode, CGRect) -> Void
|
||||
|
||||
let selectable: Bool = false
|
||||
|
||||
init(theme: WalletTheme, strings: WalletStrings, address: String, displayAddressContextMenu: @escaping (ASDisplayNode, CGRect) -> Void) {
|
||||
init(theme: WalletTheme, strings: WalletStrings, address: String, loading: Bool, displayAddressContextMenu: @escaping (ASDisplayNode, CGRect) -> Void) {
|
||||
self.theme = theme
|
||||
self.strings = strings
|
||||
self.address = address
|
||||
self.loading = loading
|
||||
self.displayAddressContextMenu = displayAddressContextMenu
|
||||
}
|
||||
|
||||
@ -66,10 +68,6 @@ final class WalletInfoEmptyItemNode: ListViewItemNode {
|
||||
self.offsetContainer = ASDisplayNode()
|
||||
|
||||
self.animationNode = AnimatedStickerNode()
|
||||
if let path = getAppBundle().path(forResource: "WalletEmpty", ofType: "tgs") {
|
||||
self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 280, height: 280, playbackMode: .once, mode: .direct)
|
||||
self.animationNode.visibility = true
|
||||
}
|
||||
|
||||
self.titleNode = TextNode()
|
||||
self.titleNode.displaysAsynchronously = false
|
||||
@ -158,13 +156,26 @@ final class WalletInfoEmptyItemNode: ListViewItemNode {
|
||||
let textFrame = CGRect(origin: CGPoint(x: floor((params.width - textLayout.size.width) / 2.0), y: titleFrame.maxY + titleSpacing), size: textLayout.size)
|
||||
let addressFrame = CGRect(origin: CGPoint(x: floor((params.width - addressLayout.size.width) / 2.0), y: textFrame.maxY + titleSpacing), size: addressLayout.size)
|
||||
|
||||
let layout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: addressFrame.maxY + 32.0), insets: UIEdgeInsets())
|
||||
let layout = ListViewItemNodeLayout(contentSize: CGSize(width: params.width, height: (item.loading ? iconFrame.maxY : addressFrame.maxY) + 32.0), insets: UIEdgeInsets())
|
||||
|
||||
return (layout, {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.item = item
|
||||
|
||||
if strongSelf.item?.loading != item.loading {
|
||||
if item.loading {
|
||||
if let path = getAppBundle().path(forResource: "WalletInitializing", ofType: "tgs") {
|
||||
strongSelf.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 280, height: 280, playbackMode: .loop, mode: .direct)
|
||||
strongSelf.animationNode.visibility = true
|
||||
}
|
||||
} else {
|
||||
if let path = getAppBundle().path(forResource: "WalletEmpty", ofType: "tgs") {
|
||||
strongSelf.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 280, height: 280, playbackMode: .once, mode: .direct)
|
||||
strongSelf.animationNode.visibility = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
strongSelf.item = item
|
||||
|
||||
@ -182,6 +193,10 @@ final class WalletInfoEmptyItemNode: ListViewItemNode {
|
||||
transition.updateFrameAdditive(node: strongSelf.titleNode, frame: titleFrame)
|
||||
transition.updateFrameAdditive(node: strongSelf.textNode, frame: textFrame)
|
||||
transition.updateFrameAdditive(node: strongSelf.addressNode, frame: addressFrame)
|
||||
|
||||
strongSelf.titleNode.isHidden = item.loading
|
||||
strongSelf.textNode.isHidden = item.loading
|
||||
strongSelf.addressNode.isHidden = item.loading
|
||||
|
||||
strongSelf.contentSize = layout.contentSize
|
||||
strongSelf.insets = layout.insets
|
||||
|
@ -103,9 +103,24 @@ public final class WalletInfoScreen: ViewController {
|
||||
guard let strongSelf = self, let walletInfo = strongSelf.walletInfo else {
|
||||
return
|
||||
}
|
||||
var randomId: Int64 = 0
|
||||
arc4random_buf(&randomId, 8)
|
||||
strongSelf.push(walletSendScreen(context: strongSelf.context, randomId: randomId, walletInfo: walletInfo))
|
||||
guard let combinedState = (strongSelf.displayNode as! WalletInfoScreenNode).combinedState else {
|
||||
return
|
||||
}
|
||||
if (strongSelf.displayNode as! WalletInfoScreenNode).reloadingState {
|
||||
strongSelf.present(standardTextAlertController(theme: strongSelf.presentationData.theme.alert, title: nil, text: strongSelf.presentationData.strings.Wallet_Send_SyncInProgress, actions: [
|
||||
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Wallet_Alert_OK, action: {
|
||||
})
|
||||
]), in: .window(.root))
|
||||
} else if !combinedState.pendingTransactions.isEmpty {
|
||||
strongSelf.present(standardTextAlertController(theme: strongSelf.presentationData.theme.alert, title: nil, text: strongSelf.presentationData.strings.Wallet_Send_TransactionInProgress, actions: [
|
||||
TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Wallet_Alert_OK, action: {
|
||||
})
|
||||
]), in: .window(.root))
|
||||
} else {
|
||||
var randomId: Int64 = 0
|
||||
arc4random_buf(&randomId, 8)
|
||||
strongSelf.push(walletSendScreen(context: strongSelf.context, randomId: randomId, walletInfo: walletInfo))
|
||||
}
|
||||
}, receiveAction: { [weak self] in
|
||||
guard let strongSelf = self, let walletInfo = strongSelf.walletInfo else {
|
||||
return
|
||||
@ -141,6 +156,7 @@ final class WalletInfoBalanceNode: ASDisplayNode {
|
||||
let balanceIntegralTextNode: ImmediateTextNode
|
||||
let balanceFractionalTextNode: ImmediateTextNode
|
||||
let balanceIconNode: AnimatedStickerNode
|
||||
private var balanceIconNodeIsStatic: Bool
|
||||
|
||||
var balance: (String, UIColor) = (" ", .white) {
|
||||
didSet {
|
||||
@ -179,6 +195,7 @@ final class WalletInfoBalanceNode: ASDisplayNode {
|
||||
self.balanceIconNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 120, height: 120, mode: .direct)
|
||||
self.balanceIconNode.visibility = true
|
||||
}
|
||||
self.balanceIconNodeIsStatic = true
|
||||
|
||||
super.init()
|
||||
|
||||
@ -209,14 +226,33 @@ final class WalletInfoBalanceNode: ASDisplayNode {
|
||||
balanceFractionalTextFrame.origin.x -= (balanceFractionalTextFrame.width / 4.0) * scaleTransition + 0.25 * (balanceFractionalTextFrame.width / 2.0) * (1.0 - scaleTransition)
|
||||
balanceFractionalTextFrame.origin.y += balanceFractionalTextFrame.height * 0.5 * (0.8 - fractionalScale)
|
||||
|
||||
let isBalanceEmpty = self.balance.0.isEmpty || self.balance.0 == " "
|
||||
|
||||
let balanceIconFrame: CGRect
|
||||
balanceIconFrame = CGRect(origin: CGPoint(x: apparentBalanceIntegralTextFrame.minX - balanceIconSize.width - balanceIconSpacing * integralScale, y: balanceIntegralTextFrame.midY - balanceIconSize.height / 2.0 + balanceVerticalIconOffset), size: balanceIconSize)
|
||||
if isBalanceEmpty {
|
||||
balanceIconFrame = CGRect(origin: CGPoint(x: floor((width - balanceIconSize.width) / 2.0), y: balanceIntegralTextFrame.midY - balanceIconSize.height / 2.0 + balanceVerticalIconOffset), size: balanceIconSize)
|
||||
} else {
|
||||
balanceIconFrame = CGRect(origin: CGPoint(x: apparentBalanceIntegralTextFrame.minX - balanceIconSize.width - balanceIconSpacing * integralScale, y: balanceIntegralTextFrame.midY - balanceIconSize.height / 2.0 + balanceVerticalIconOffset), size: balanceIconSize)
|
||||
}
|
||||
|
||||
transition.updateFrameAsPositionAndBounds(node: self.balanceIntegralTextNode, frame: balanceIntegralTextFrame)
|
||||
transition.updateTransformScale(node: self.balanceIntegralTextNode, scale: integralScale)
|
||||
transition.updateFrameAsPositionAndBounds(node: self.balanceFractionalTextNode, frame: balanceFractionalTextFrame)
|
||||
transition.updateTransformScale(node: self.balanceFractionalTextNode, scale: fractionalScale)
|
||||
|
||||
if !isBalanceEmpty != self.balanceIconNodeIsStatic {
|
||||
self.balanceIconNodeIsStatic = !isBalanceEmpty
|
||||
if isBalanceEmpty {
|
||||
if let path = getAppBundle().path(forResource: "WalletIntroLoading", ofType: "tgs") {
|
||||
self.balanceIconNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 120, height: 120, mode: .direct)
|
||||
}
|
||||
} else {
|
||||
if let path = getAppBundle().path(forResource: "WalletIntroStatic", ofType: "tgs") {
|
||||
self.balanceIconNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 120, height: 120, mode: .direct)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.balanceIconNode.updateLayout(size: balanceIconFrame.size)
|
||||
transition.updateFrameAsPositionAndBounds(node: self.balanceIconNode, frame: balanceIconFrame)
|
||||
transition.updateTransformScale(node: self.balanceIconNode, scale: scaleTransition * 1.0 + (1.0 - scaleTransition) * 0.8)
|
||||
@ -319,7 +355,7 @@ private final class WalletInfoHeaderNode: ASDisplayNode {
|
||||
|
||||
let effectiveOffset = max(offset, navigationHeight)
|
||||
|
||||
let minButtonsOffset = maxOffset - buttonHeight - sideInset
|
||||
let minButtonsOffset = maxOffset - buttonHeight * 2.0 - sideInset
|
||||
let maxButtonsOffset = maxOffset
|
||||
let buttonTransition: CGFloat = max(0.0, min(1.0, (effectiveOffset - minButtonsOffset) / (maxButtonsOffset - minButtonsOffset)))
|
||||
let buttonAlpha: CGFloat = buttonTransition
|
||||
@ -344,11 +380,11 @@ private final class WalletInfoHeaderNode: ASDisplayNode {
|
||||
|
||||
let refreshSize = CGSize(width: 0.0, height: 0.0)
|
||||
transition.updateFrame(node: self.refreshNode, frame: CGRect(origin: CGPoint(x: floor((size.width - refreshSize.width) / 2.0), y: navigationHeight - 44.0 + floor((44.0 - refreshSize.height) / 2.0)), size: refreshSize))
|
||||
transition.updateAlpha(node: self.refreshNode, alpha: headerScaleTransition)
|
||||
if self.balance == nil {
|
||||
self.refreshNode.update(state: .pullToRefresh(self.timestamp ?? 0, 0.0))
|
||||
} else if self.isRefreshing {
|
||||
transition.updateAlpha(node: self.refreshNode, alpha: headerScaleTransition, beginWithCurrentState: true)
|
||||
if self.isRefreshing {
|
||||
self.refreshNode.update(state: .refreshing)
|
||||
} else if self.balance == nil {
|
||||
self.refreshNode.update(state: .pullToRefresh(self.timestamp ?? 0, 0.0))
|
||||
} else {
|
||||
let refreshOffset: CGFloat = 20.0
|
||||
let refreshScaleTransition: CGFloat = max(0.0, (offset - maxOffset) / refreshOffset)
|
||||
@ -379,7 +415,7 @@ private final class WalletInfoHeaderNode: ASDisplayNode {
|
||||
self.sendButtonNode.isHidden = false
|
||||
} else {
|
||||
if self.balance == nil {
|
||||
self.receiveGramsButtonNode.isHidden = true
|
||||
self.receiveGramsButtonNode.isHidden = false
|
||||
self.receiveButtonNode.isHidden = true
|
||||
self.sendButtonNode.isHidden = true
|
||||
} else {
|
||||
@ -389,9 +425,9 @@ private final class WalletInfoHeaderNode: ASDisplayNode {
|
||||
}
|
||||
}
|
||||
if self.balance == nil {
|
||||
self.balanceNode.isHidden = true
|
||||
self.balanceNode.isHidden = false
|
||||
self.balanceSubtitleNode.isHidden = true
|
||||
self.refreshNode.isHidden = true
|
||||
self.refreshNode.isHidden = false
|
||||
} else {
|
||||
self.balanceNode.isHidden = false
|
||||
self.balanceSubtitleNode.isHidden = false
|
||||
@ -399,13 +435,13 @@ private final class WalletInfoHeaderNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
transition.updateFrame(node: self.receiveGramsButtonNode, frame: fullButtonFrame)
|
||||
transition.updateAlpha(node: self.receiveGramsButtonNode, alpha: buttonAlpha)
|
||||
transition.updateAlpha(node: self.receiveGramsButtonNode, alpha: buttonAlpha, beginWithCurrentState: true)
|
||||
transition.updateFrame(node: self.receiveButtonNode, frame: leftButtonFrame)
|
||||
transition.updateAlpha(node: self.receiveButtonNode, alpha: buttonAlpha)
|
||||
transition.updateAlpha(node: self.receiveButtonNode, alpha: buttonAlpha, beginWithCurrentState: true)
|
||||
self.receiveGramsButtonNode.updateLayout(width: fullButtonFrame.width, transition: transition)
|
||||
self.receiveButtonNode.updateLayout(width: leftButtonFrame.width, transition: transition)
|
||||
transition.updateFrame(node: self.sendButtonNode, frame: sendButtonFrame)
|
||||
transition.updateAlpha(node: self.sendButtonNode, alpha: buttonAlpha)
|
||||
transition.updateAlpha(node: self.sendButtonNode, alpha: buttonAlpha, beginWithCurrentState: true)
|
||||
self.sendButtonNode.updateLayout(width: sendButtonFrame.width, transition: transition)
|
||||
}
|
||||
|
||||
@ -453,7 +489,7 @@ private enum WalletInfoListEntryId: Hashable {
|
||||
}
|
||||
|
||||
private enum WalletInfoListEntry: Equatable, Comparable, Identifiable {
|
||||
case empty(String)
|
||||
case empty(String, Bool)
|
||||
case transaction(Int, WalletInfoTransaction)
|
||||
|
||||
var stableId: WalletInfoListEntryId {
|
||||
@ -491,8 +527,8 @@ private enum WalletInfoListEntry: Equatable, Comparable, Identifiable {
|
||||
|
||||
func item(theme: WalletTheme, strings: WalletStrings, dateTimeFormat: WalletPresentationDateTimeFormat, action: @escaping (WalletInfoTransaction) -> Void, displayAddressContextMenu: @escaping (ASDisplayNode, CGRect) -> Void) -> ListViewItem {
|
||||
switch self {
|
||||
case let .empty(address):
|
||||
return WalletInfoEmptyItem(theme: theme, strings: strings, address: address, displayAddressContextMenu: { node, frame in
|
||||
case let .empty(address, loading):
|
||||
return WalletInfoEmptyItem(theme: theme, strings: strings, address: address, loading: loading, displayAddressContextMenu: { node, frame in
|
||||
displayAddressContextMenu(node, frame)
|
||||
})
|
||||
case let .transaction(_, transaction):
|
||||
@ -526,7 +562,6 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
|
||||
|
||||
private let headerNode: WalletInfoHeaderNode
|
||||
private let listNode: ListView
|
||||
private let loadingIndicator: UIActivityIndicatorView
|
||||
|
||||
private var enqueuedTransactions: [WalletInfoListTransaction] = []
|
||||
|
||||
@ -536,7 +571,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
|
||||
private let transactionListDisposable = MetaDisposable()
|
||||
|
||||
private var listOffset: CGFloat?
|
||||
private var reloadingState: Bool = false
|
||||
private(set) var reloadingState: Bool = false
|
||||
private var loadingMoreTransactions: Bool = false
|
||||
private var canLoadMoreTransactions: Bool = true
|
||||
|
||||
@ -567,18 +602,15 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
|
||||
self.listNode = ListView()
|
||||
self.listNode.verticalScrollIndicatorColor = UIColor(white: 0.0, alpha: 0.3)
|
||||
self.listNode.verticalScrollIndicatorFollowsOverscroll = true
|
||||
self.listNode.isHidden = true
|
||||
self.listNode.isHidden = false
|
||||
self.listNode.view.disablesInteractiveModalDismiss = true
|
||||
|
||||
self.loadingIndicator = UIActivityIndicatorView(style: .whiteLarge)
|
||||
|
||||
super.init()
|
||||
|
||||
self.backgroundColor = self.presentationData.theme.list.itemBlocksBackgroundColor
|
||||
|
||||
self.addSubnode(self.listNode)
|
||||
self.addSubnode(self.headerNode)
|
||||
self.view.addSubview(self.loadingIndicator)
|
||||
|
||||
var canBeginRefresh = true
|
||||
var isScrolling = false
|
||||
@ -630,11 +662,11 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
|
||||
switch strongSelf.listNode.visibleContentOffset() {
|
||||
case let .known(offset):
|
||||
if offset < strongSelf.listNode.insets.top {
|
||||
/*if offset > strongSelf.listNode.insets.top / 2.0 {
|
||||
if offset > strongSelf.listNode.insets.top / 2.0 {
|
||||
strongSelf.scrollToHideHeader()
|
||||
} else {
|
||||
strongSelf.scrollToTop()
|
||||
}*/
|
||||
}
|
||||
}
|
||||
default:
|
||||
break
|
||||
@ -717,20 +749,19 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
|
||||
guard let (_, navigationHeight) = self.validLayout else {
|
||||
return
|
||||
}
|
||||
self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: ListViewScrollToItem(index: 0, position: .top(navigationHeight), animated: true, curve: .Spring(duration: 0.4), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
|
||||
let _ = self.listNode.scrollToOffsetFromTop(self.headerNode.frame.maxY - navigationHeight)
|
||||
}
|
||||
|
||||
func scrollToTop() {
|
||||
self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Spring(duration: 0.4), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
|
||||
if !self.listNode.scrollToOffsetFromTop(0.0) {
|
||||
self.listNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Spring(duration: 0.4), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in })
|
||||
}
|
||||
}
|
||||
|
||||
func containerLayoutUpdated(layout: ContainerViewLayout, navigationHeight: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
let isFirstLayout = self.validLayout == nil
|
||||
self.validLayout = (layout, navigationHeight)
|
||||
|
||||
let indicatorSize = self.loadingIndicator.bounds.size
|
||||
self.loadingIndicator.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - indicatorSize.width) / 2.0), y: floor((layout.size.height - indicatorSize.height) / 2.0)), size: indicatorSize)
|
||||
|
||||
let headerHeight: CGFloat = navigationHeight + 260.0
|
||||
let topInset: CGFloat = headerHeight
|
||||
|
||||
@ -809,17 +840,9 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
|
||||
if strongSelf.combinedState != nil {
|
||||
return
|
||||
}
|
||||
if state == nil {
|
||||
strongSelf.loadingIndicator.startAnimating()
|
||||
} else {
|
||||
strongSelf.loadingIndicator.stopAnimating()
|
||||
strongSelf.loadingIndicator.isHidden = true
|
||||
}
|
||||
combinedState = state
|
||||
case let .updated(state):
|
||||
isUpdated = true
|
||||
strongSelf.loadingIndicator.stopAnimating()
|
||||
strongSelf.loadingIndicator.isHidden = true
|
||||
combinedState = state
|
||||
}
|
||||
|
||||
@ -877,7 +900,9 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
|
||||
self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate)
|
||||
}
|
||||
|
||||
self.reloadingState = false
|
||||
if isUpdated {
|
||||
self.reloadingState = false
|
||||
}
|
||||
|
||||
self.headerNode.timestamp = Int32(clamping: combinedState.timestamp)
|
||||
|
||||
@ -909,7 +934,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
|
||||
}
|
||||
}
|
||||
|
||||
self.transactionsLoaded(isReload: true, transactions: updatedTransactions, pendingTransactions: combinedState.pendingTransactions)
|
||||
self.transactionsLoaded(isReload: true, isEmpty: false, transactions: updatedTransactions, pendingTransactions: combinedState.pendingTransactions)
|
||||
|
||||
if isUpdated {
|
||||
self.headerNode.isRefreshing = false
|
||||
@ -918,17 +943,19 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
|
||||
if self.isReady, let (layout, navigationHeight) = self.validLayout {
|
||||
self.headerNode.update(size: self.headerNode.bounds.size, navigationHeight: navigationHeight, offset: self.listOffset ?? 0.0, transition: .animated(duration: 0.2, curve: .easeInOut), isScrolling: false)
|
||||
}
|
||||
|
||||
let wasReady = self.isReady
|
||||
self.isReady = self.combinedState != nil
|
||||
|
||||
if self.isReady && !wasReady {
|
||||
if let (layout, navigationHeight) = self.validLayout {
|
||||
self.headerNode.update(size: self.headerNode.bounds.size, navigationHeight: navigationHeight, offset: layout.size.height, transition: .immediate, isScrolling: false)
|
||||
}
|
||||
|
||||
self.becameReady(animated: self.didSetContentReady)
|
||||
} else {
|
||||
self.transactionsLoaded(isReload: true, isEmpty: true, transactions: [], pendingTransactions: [])
|
||||
}
|
||||
|
||||
let wasReady = self.isReady
|
||||
self.isReady = true
|
||||
|
||||
if self.isReady && !wasReady {
|
||||
if let (layout, navigationHeight) = self.validLayout {
|
||||
self.headerNode.update(size: self.headerNode.bounds.size, navigationHeight: navigationHeight, offset: layout.size.height, transition: .immediate, isScrolling: false)
|
||||
}
|
||||
|
||||
self.becameReady(animated: self.didSetContentReady)
|
||||
}
|
||||
|
||||
if !self.didSetContentReady {
|
||||
@ -961,7 +988,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.transactionsLoaded(isReload: false, transactions: transactions, pendingTransactions: [])
|
||||
strongSelf.transactionsLoaded(isReload: false, isEmpty: false, transactions: transactions, pendingTransactions: [])
|
||||
}, error: { [weak self] _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
@ -969,9 +996,11 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
|
||||
}))
|
||||
}
|
||||
|
||||
private func transactionsLoaded(isReload: Bool, transactions: [WalletTransaction], pendingTransactions: [PendingWalletTransaction]) {
|
||||
self.loadingMoreTransactions = false
|
||||
self.canLoadMoreTransactions = transactions.count > 2
|
||||
private func transactionsLoaded(isReload: Bool, isEmpty: Bool, transactions: [WalletTransaction], pendingTransactions: [PendingWalletTransaction]) {
|
||||
if !isEmpty {
|
||||
self.loadingMoreTransactions = false
|
||||
self.canLoadMoreTransactions = transactions.count > 2
|
||||
}
|
||||
|
||||
var updatedEntries: [WalletInfoListEntry] = []
|
||||
if isReload {
|
||||
@ -989,7 +1018,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
|
||||
}
|
||||
}
|
||||
if updatedEntries.isEmpty {
|
||||
updatedEntries.append(.empty(self.address))
|
||||
updatedEntries.append(.empty(self.address, isEmpty))
|
||||
}
|
||||
} else {
|
||||
updatedEntries = self.currentEntries ?? []
|
||||
@ -1016,7 +1045,7 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
|
||||
}
|
||||
}
|
||||
if updatedEntries.isEmpty {
|
||||
updatedEntries.append(.empty(self.address))
|
||||
updatedEntries.append(.empty(self.address, false))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1065,8 +1094,6 @@ private final class WalletInfoScreenNode: ViewControllerTracingNode {
|
||||
|
||||
private func becameReady(animated: Bool) {
|
||||
self.listNode.isHidden = false
|
||||
self.loadingIndicator.stopAnimating()
|
||||
self.loadingIndicator.isHidden = true
|
||||
self.headerNode.becameReady(animated: animated)
|
||||
if let (layout, navigationHeight) = self.validLayout {
|
||||
self.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: animated ? .animated(duration: 0.5, curve: .spring) : .immediate)
|
||||
|
@ -219,6 +219,7 @@ enum WalletThemeResourceKey: Int32 {
|
||||
case itemListCornersTop
|
||||
case itemListCornersBottom
|
||||
case itemListClearInputIcon
|
||||
case itemListDisclosureArrow
|
||||
case navigationShareIcon
|
||||
|
||||
case clockMin
|
||||
@ -269,7 +270,13 @@ func itemListClearInputIcon(_ theme: WalletTheme) -> UIImage? {
|
||||
|
||||
func navigationShareIcon(_ theme: WalletTheme) -> UIImage? {
|
||||
return theme.image(WalletThemeResourceKey.navigationShareIcon.rawValue, { theme in
|
||||
generateTintedImage(image: UIImage(bundleImageName: "Chat List/NavigationShare"), color: theme.navigationBar.buttonColor)
|
||||
generateTintedImage(image: UIImage(bundleImageName: "Wallet/NavigationShare"), color: theme.navigationBar.buttonColor)
|
||||
})
|
||||
}
|
||||
|
||||
func disclosureArrowImage(_ theme: WalletTheme) -> UIImage? {
|
||||
return theme.image(WalletThemeResourceKey.itemListDisclosureArrow.rawValue, { theme in
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Wallet/DisclosureArrow"), color: theme.list.itemSecondaryTextColor)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ public func walletSettingsController(context: WalletContext, walletInfo: WalletI
|
||||
var replaceAllWalletControllersImpl: ((ViewController) -> Void)?
|
||||
|
||||
let arguments = WalletSettingsControllerArguments(openConfiguration: {
|
||||
let _ = (context.storage.customWalletConfiguration()
|
||||
let _ = (context.storage.localWalletConfiguration()
|
||||
|> take(1)
|
||||
|> deliverOnMainQueue).start(next: { configuration in
|
||||
pushControllerImpl?(walletConfigurationScreen(context: context, currentConfiguration: configuration))
|
||||
|
@ -20,7 +20,7 @@ public enum WalletSecureStorageResetReason {
|
||||
public enum WalletSplashMode {
|
||||
case intro
|
||||
case created(WalletInfo, [String]?)
|
||||
case success(WalletInfo, Bool)
|
||||
case success(WalletInfo)
|
||||
case restoreFailed
|
||||
case sending(WalletInfo, String, Int64, Data, Int64, Data)
|
||||
case sent(WalletInfo, Int64)
|
||||
@ -58,7 +58,7 @@ public final class WalletSplashScreen: ViewController {
|
||||
return .single(nil)
|
||||
})
|
||||
}
|
||||
case let .success(walletInfo, _):
|
||||
case let .success(walletInfo):
|
||||
if let walletCreatedPreloadState = walletCreatedPreloadState {
|
||||
self.walletCreatedPreloadState = walletCreatedPreloadState
|
||||
} else {
|
||||
@ -397,78 +397,31 @@ public final class WalletSplashScreen: ViewController {
|
||||
}
|
||||
})
|
||||
}
|
||||
case let .success(walletInfo, _):
|
||||
case let .success(walletInfo):
|
||||
let _ = (walletAddress(publicKey: walletInfo.publicKey, tonInstance: strongSelf.context.tonInstance)
|
||||
|> deliverOnMainQueue).start(next: { address in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
var stateSignal: Signal<Bool, NoError>
|
||||
if let walletCreatedPreloadState = strongSelf.walletCreatedPreloadState {
|
||||
stateSignal = walletCreatedPreloadState.get()
|
||||
|> map { state -> Bool in
|
||||
if let state = state {
|
||||
if case .updated = state {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|> filter { $0 }
|
||||
} else {
|
||||
stateSignal = .single(true)
|
||||
}
|
||||
|
||||
let presentationData = strongSelf.presentationData
|
||||
let progressSignal = Signal<Never, NoError> { subscriber in
|
||||
let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil))
|
||||
self?.present(controller, in: .window(.root))
|
||||
return ActionDisposable { [weak controller] in
|
||||
Queue.mainQueue().async() {
|
||||
controller?.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|> runOn(Queue.mainQueue())
|
||||
|> delay(0.15, queue: Queue.mainQueue())
|
||||
let progressDisposable = progressSignal.start()
|
||||
|
||||
stateSignal = stateSignal
|
||||
|> afterDisposed {
|
||||
Queue.mainQueue().async {
|
||||
progressDisposable.dispose()
|
||||
}
|
||||
}
|
||||
let _ = (stateSignal
|
||||
|> deliverOnMainQueue).start(next: { _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
progressDisposable.dispose()
|
||||
|
||||
if let navigationController = strongSelf.navigationController as? NavigationController {
|
||||
var controllers = navigationController.viewControllers
|
||||
controllers = controllers.filter { controller in
|
||||
if controller is WalletSplashScreen {
|
||||
return false
|
||||
}
|
||||
if controller is WalletWordDisplayScreen {
|
||||
return false
|
||||
}
|
||||
if controller is WalletWordCheckScreen {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
if let navigationController = strongSelf.navigationController as? NavigationController {
|
||||
var controllers = navigationController.viewControllers
|
||||
controllers = controllers.filter { controller in
|
||||
if controller is WalletSplashScreen {
|
||||
return false
|
||||
}
|
||||
controllers.append(WalletInfoScreen(context: strongSelf.context, walletInfo: walletInfo, address: address, enableDebugActions: false))
|
||||
strongSelf.view.endEditing(true)
|
||||
navigationController.setViewControllers(controllers, animated: true)
|
||||
if controller is WalletWordDisplayScreen {
|
||||
return false
|
||||
}
|
||||
if controller is WalletWordCheckScreen {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
controllers.append(WalletInfoScreen(context: strongSelf.context, walletInfo: walletInfo, address: address, enableDebugActions: false))
|
||||
strongSelf.view.endEditing(true)
|
||||
navigationController.setViewControllers(controllers, animated: true)
|
||||
}
|
||||
})
|
||||
case let .sent(walletInfo, _):
|
||||
if let navigationController = strongSelf.navigationController as? NavigationController {
|
||||
@ -601,20 +554,8 @@ public final class WalletSplashScreen: ViewController {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
var url = strongSelf.presentationData.strings.Wallet_Intro_TermsUrl
|
||||
if url.isEmpty {
|
||||
url = "https://telegram.org/tos/wallet"
|
||||
}
|
||||
strongSelf.context.openUrl(url)
|
||||
}, replaceWithSynchronized: { [weak self] in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
switch strongSelf.mode {
|
||||
case let .success(walletInfo, _):
|
||||
(strongSelf.navigationController as? NavigationController)?.replaceTopController(WalletSplashScreen(context: strongSelf.context, mode: .success(walletInfo, true), walletCreatedPreloadState: strongSelf.walletCreatedPreloadState), animated: true)
|
||||
default:
|
||||
break
|
||||
if let url = strongSelf.context.termsUrl {
|
||||
strongSelf.context.openUrl(url)
|
||||
}
|
||||
})
|
||||
|
||||
@ -632,7 +573,6 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode {
|
||||
private var presentationData: WalletPresentationData
|
||||
private let mode: WalletSplashMode
|
||||
private let secondaryAction: () -> Void
|
||||
private let replaceWithSynchronized: () -> Void
|
||||
|
||||
private let iconNode: ASImageNode
|
||||
private var animationSize: CGSize = CGSize()
|
||||
@ -658,11 +598,10 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode {
|
||||
}
|
||||
}
|
||||
|
||||
init(context: WalletContext, walletCreatedPreloadState: Promise<CombinedWalletStateResult?>?, presentationData: WalletPresentationData, mode: WalletSplashMode, action: @escaping () -> Void, secondaryAction: @escaping () -> Void, openTerms: @escaping () -> Void, replaceWithSynchronized: @escaping () -> Void) {
|
||||
init(context: WalletContext, walletCreatedPreloadState: Promise<CombinedWalletStateResult?>?, presentationData: WalletPresentationData, mode: WalletSplashMode, action: @escaping () -> Void, secondaryAction: @escaping () -> Void, openTerms: @escaping () -> Void) {
|
||||
self.presentationData = presentationData
|
||||
self.mode = mode
|
||||
self.secondaryAction = secondaryAction
|
||||
self.replaceWithSynchronized = replaceWithSynchronized
|
||||
|
||||
self.iconNode = ASImageNode()
|
||||
self.iconNode.displayWithoutProcessing = true
|
||||
@ -688,10 +627,10 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode {
|
||||
buttonText = self.presentationData.strings.Wallet_Intro_CreateWallet
|
||||
let body = MarkdownAttributeSet(font: Font.regular(13.0), textColor: self.presentationData.theme.list.itemSecondaryTextColor, additionalAttributes: [:])
|
||||
let link = MarkdownAttributeSet(font: Font.regular(13.0), textColor: self.presentationData.theme.list.itemSecondaryTextColor, additionalAttributes: [NSAttributedString.Key.underlineStyle.rawValue: NSUnderlineStyle.single.rawValue as NSNumber])
|
||||
if context.supportsCustomConfigurations {
|
||||
termsText = NSAttributedString(string: "")
|
||||
} else {
|
||||
if let _ = context.termsUrl {
|
||||
termsText = parseMarkdownIntoAttributedString(self.presentationData.strings.Wallet_Intro_Terms, attributes: MarkdownAttributes(body: body, bold: body, link: link, linkAttribute: { _ in nil }), textAlignment: .center)
|
||||
} else {
|
||||
termsText = NSAttributedString(string: "")
|
||||
}
|
||||
self.iconNode.image = nil
|
||||
if let path = getAppBundle().path(forResource: "WalletIntroLoading", ofType: "tgs") {
|
||||
@ -712,35 +651,19 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode {
|
||||
self.animationNode.visibility = true
|
||||
}
|
||||
secondaryActionText = ""
|
||||
case let .success(_, synchronized):
|
||||
if synchronized {
|
||||
title = self.presentationData.strings.Wallet_Completed_Title
|
||||
text = NSAttributedString(string: self.presentationData.strings.Wallet_Completed_Text, font: textFont, textColor: textColor)
|
||||
buttonText = self.presentationData.strings.Wallet_Completed_ViewWallet
|
||||
termsText = NSAttributedString(string: "")
|
||||
self.iconNode.image = nil
|
||||
if let path = getAppBundle().path(forResource: "WalletDone", ofType: "tgs") {
|
||||
self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 260, height: 260, playbackMode: .loop, mode: .direct)
|
||||
self.animationSize = CGSize(width: 130.0, height: 130.0)
|
||||
self.animationOffset = CGPoint(x: 0.0, y: 0.0)
|
||||
self.animationNode.visibility = true
|
||||
}
|
||||
secondaryActionText = ""
|
||||
} else {
|
||||
title = self.presentationData.strings.Wallet_Completed_ProgressTitle
|
||||
text = NSAttributedString(string: self.presentationData.strings.Wallet_Completed_ProgressText, font: textFont, textColor: textColor)
|
||||
buttonText = self.presentationData.strings.Wallet_Completed_ViewWallet
|
||||
buttonHidden = true
|
||||
termsText = NSAttributedString(string: "")
|
||||
self.iconNode.image = nil
|
||||
if let path = getAppBundle().path(forResource: "WalletSynchronization", ofType: "tgs") {
|
||||
self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 220, height: 220, playbackMode: .loop, mode: .direct)
|
||||
self.animationSize = CGSize(width: 110.0, height: 110.0)
|
||||
self.animationOffset = CGPoint(x: -10.0, y: 0.0)
|
||||
self.animationNode.visibility = true
|
||||
}
|
||||
secondaryActionText = ""
|
||||
case .success:
|
||||
title = self.presentationData.strings.Wallet_Completed_Title
|
||||
text = NSAttributedString(string: self.presentationData.strings.Wallet_Completed_Text, font: textFont, textColor: textColor)
|
||||
buttonText = self.presentationData.strings.Wallet_Completed_ViewWallet
|
||||
termsText = NSAttributedString(string: "")
|
||||
self.iconNode.image = nil
|
||||
if let path = getAppBundle().path(forResource: "WalletDone", ofType: "tgs") {
|
||||
self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 260, height: 260, playbackMode: .loop, mode: .direct)
|
||||
self.animationSize = CGSize(width: 130.0, height: 130.0)
|
||||
self.animationOffset = CGPoint(x: 0.0, y: 0.0)
|
||||
self.animationNode.visibility = true
|
||||
}
|
||||
secondaryActionText = ""
|
||||
case .restoreFailed:
|
||||
title = self.presentationData.strings.Wallet_RestoreFailed_Title
|
||||
text = NSAttributedString(string: self.presentationData.strings.Wallet_RestoreFailed_Text, font: textFont, textColor: textColor)
|
||||
@ -912,97 +835,6 @@ private final class WalletSplashScreenNode: ViewControllerTracingNode {
|
||||
openTerms()
|
||||
}
|
||||
}
|
||||
|
||||
switch mode {
|
||||
case let .success(walletInfo, synchronized) where !synchronized:
|
||||
var stateSignal: Signal<Bool, NoError>
|
||||
if let walletCreatedPreloadState = walletCreatedPreloadState {
|
||||
stateSignal = walletCreatedPreloadState.get()
|
||||
|> map { state -> Bool in
|
||||
if let state = state {
|
||||
if case .updated = state {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|> filter { $0 }
|
||||
|> take(1)
|
||||
} else {
|
||||
stateSignal = .single(true)
|
||||
}
|
||||
self.stateDisposable = (stateSignal
|
||||
|> deliverOnMainQueue).start(next: { [weak self] _ in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
if strongSelf.validLayout != nil {
|
||||
strongSelf.replaceWithSynchronized()
|
||||
return
|
||||
}
|
||||
|
||||
strongSelf.buttonNode.isHidden = false
|
||||
|
||||
let title = strongSelf.presentationData.strings.Wallet_Completed_Title
|
||||
let text = NSAttributedString(string: strongSelf.presentationData.strings.Wallet_Completed_Text, font: textFont, textColor: textColor)
|
||||
|
||||
strongSelf.titleNode.attributedText = NSAttributedString(string: title, font: Font.bold(32.0), textColor: strongSelf.presentationData.theme.list.itemPrimaryTextColor)
|
||||
strongSelf.textNode.attributedText = text
|
||||
|
||||
if let path = getAppBundle().path(forResource: "WalletDone", ofType: "tgs") {
|
||||
let animateIn = !strongSelf.animationNode.frame.isEmpty
|
||||
var snapshotView: UIView?
|
||||
if animateIn {
|
||||
snapshotView = strongSelf.animationNode.view.snapshotContentTree()
|
||||
}
|
||||
|
||||
strongSelf.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(path: path), width: 260, height: 260, playbackMode: .once, mode: .direct)
|
||||
strongSelf.animationSize = CGSize(width: 130.0, height: 130.0)
|
||||
strongSelf.animationOffset = CGPoint(x: 14.0, y: 0.0)
|
||||
strongSelf.animationNode.visibility = true
|
||||
|
||||
if animateIn {
|
||||
if let snapshotView = snapshotView {
|
||||
strongSelf.view.insertSubview(snapshotView, belowSubview: strongSelf.animationNode.view)
|
||||
snapshotView.frame = strongSelf.animationNode.frame
|
||||
snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.1, removeOnCompletion: false, completion: { [weak snapshotView] _ in
|
||||
snapshotView?.removeFromSuperview()
|
||||
})
|
||||
snapshotView.layer.animateScale(from: 1.0, to: 0.7, duration: 0.18, removeOnCompletion: false)
|
||||
}
|
||||
strongSelf.animationNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.08)
|
||||
strongSelf.animationNode.layer.animateScale(from: 0.7, to: 1.0, duration: 0.2)
|
||||
}
|
||||
}
|
||||
|
||||
if let (layout, navigationHeight) = strongSelf.validLayout {
|
||||
strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate)
|
||||
}
|
||||
})
|
||||
|
||||
self.synchronizationProgressDisposable = (context.tonInstance.syncProgress
|
||||
|> deliverOnMainQueue).start(next: { [weak self] progress in
|
||||
guard let strongSelf = self, strongSelf.buttonNode.isHidden else {
|
||||
return
|
||||
}
|
||||
|
||||
let percent = Int(progress * 100.0)
|
||||
|
||||
let title = strongSelf.presentationData.strings.Wallet_Completed_ProgressTitle + " \(percent)%"
|
||||
|
||||
strongSelf.titleNode.attributedText = NSAttributedString(string: title, font: Font.bold(32.0), textColor: strongSelf.presentationData.theme.list.itemPrimaryTextColor)
|
||||
|
||||
if let (layout, navigationHeight) = strongSelf.validLayout {
|
||||
strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate)
|
||||
}
|
||||
})
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
@ -204,88 +204,88 @@ public final class WalletStrings: Equatable {
|
||||
public var Wallet_Month_ShortJune: String { return self._s[13]! }
|
||||
public var Wallet_TransactionInfo_StorageFeeInfo: String { return self._s[14]! }
|
||||
public var Wallet_Created_Title: String { return self._s[15]! }
|
||||
public var Wallet_Info_YourBalance: String { return self._s[16]! }
|
||||
public var Wallet_TransactionInfo_CommentHeader: String { return self._s[17]! }
|
||||
public var Wallet_TransactionInfo_OtherFeeHeader: String { return self._s[18]! }
|
||||
public var Wallet_Send_SyncInProgress: String { return self._s[16]! }
|
||||
public var Wallet_Info_YourBalance: String { return self._s[17]! }
|
||||
public var Wallet_TransactionInfo_CommentHeader: String { return self._s[18]! }
|
||||
public var Wallet_TransactionInfo_OtherFeeHeader: String { return self._s[19]! }
|
||||
public func Wallet_Time_PreciseDate_m3(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
|
||||
return formatWithArgumentRanges(self._s[19]!, self._r[19]!, [_1, _2, _3])
|
||||
return formatWithArgumentRanges(self._s[20]!, self._r[20]!, [_1, _2, _3])
|
||||
}
|
||||
public var Wallet_WordImport_IncorrectText: String { return self._s[20]! }
|
||||
public var Wallet_Month_GenJanuary: String { return self._s[21]! }
|
||||
public var Wallet_Send_OwnAddressAlertTitle: String { return self._s[22]! }
|
||||
public var Wallet_Receive_ShareAddress: String { return self._s[23]! }
|
||||
public var Wallet_WordImport_Title: String { return self._s[24]! }
|
||||
public var Wallet_TransactionInfo_Title: String { return self._s[25]! }
|
||||
public var Wallet_Words_NotDoneText: String { return self._s[27]! }
|
||||
public var Wallet_RestoreFailed_EnterWords: String { return self._s[28]! }
|
||||
public var Wallet_WordImport_Text: String { return self._s[29]! }
|
||||
public var Wallet_RestoreFailed_Text: String { return self._s[31]! }
|
||||
public var Wallet_TransactionInfo_NoAddress: String { return self._s[32]! }
|
||||
public var Wallet_Navigation_Back: String { return self._s[33]! }
|
||||
public var Wallet_Intro_Terms: String { return self._s[34]! }
|
||||
public var Wallet_WordImport_IncorrectText: String { return self._s[21]! }
|
||||
public var Wallet_Month_GenJanuary: String { return self._s[22]! }
|
||||
public var Wallet_Send_OwnAddressAlertTitle: String { return self._s[23]! }
|
||||
public var Wallet_Receive_ShareAddress: String { return self._s[24]! }
|
||||
public var Wallet_WordImport_Title: String { return self._s[25]! }
|
||||
public var Wallet_TransactionInfo_Title: String { return self._s[26]! }
|
||||
public var Wallet_Words_NotDoneText: String { return self._s[28]! }
|
||||
public var Wallet_RestoreFailed_EnterWords: String { return self._s[29]! }
|
||||
public var Wallet_WordImport_Text: String { return self._s[30]! }
|
||||
public var Wallet_RestoreFailed_Text: String { return self._s[32]! }
|
||||
public var Wallet_TransactionInfo_NoAddress: String { return self._s[33]! }
|
||||
public var Wallet_Navigation_Back: String { return self._s[34]! }
|
||||
public var Wallet_Intro_Terms: String { return self._s[35]! }
|
||||
public func Wallet_Send_Balance(_ _0: String) -> (String, [(Int, NSRange)]) {
|
||||
return formatWithArgumentRanges(self._s[35]!, self._r[35]!, [_0])
|
||||
return formatWithArgumentRanges(self._s[36]!, self._r[36]!, [_0])
|
||||
}
|
||||
public func Wallet_Time_PreciseDate_m8(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
|
||||
return formatWithArgumentRanges(self._s[36]!, self._r[36]!, [_1, _2, _3])
|
||||
return formatWithArgumentRanges(self._s[37]!, self._r[37]!, [_1, _2, _3])
|
||||
}
|
||||
public var Wallet_TransactionInfo_AddressCopied: String { return self._s[37]! }
|
||||
public var Wallet_TransactionInfo_AddressCopied: String { return self._s[38]! }
|
||||
public func Wallet_Info_TransactionDateHeaderYear(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
|
||||
return formatWithArgumentRanges(self._s[38]!, self._r[38]!, [_1, _2, _3])
|
||||
return formatWithArgumentRanges(self._s[39]!, self._r[39]!, [_1, _2, _3])
|
||||
}
|
||||
public var Wallet_Send_NetworkErrorText: String { return self._s[39]! }
|
||||
public var Wallet_VoiceOver_Editing_ClearText: String { return self._s[40]! }
|
||||
public var Wallet_Intro_ImportExisting: String { return self._s[41]! }
|
||||
public var Wallet_Receive_CommentInfo: String { return self._s[42]! }
|
||||
public var Wallet_WordCheck_Continue: String { return self._s[43]! }
|
||||
public var Wallet_Completed_ProgressText: String { return self._s[44]! }
|
||||
public var Wallet_Send_NetworkErrorText: String { return self._s[40]! }
|
||||
public var Wallet_VoiceOver_Editing_ClearText: String { return self._s[41]! }
|
||||
public var Wallet_Intro_ImportExisting: String { return self._s[42]! }
|
||||
public var Wallet_Receive_CommentInfo: String { return self._s[43]! }
|
||||
public var Wallet_WordCheck_Continue: String { return self._s[44]! }
|
||||
public var Wallet_Receive_InvoiceUrlCopied: String { return self._s[45]! }
|
||||
public var Wallet_Completed_Text: String { return self._s[46]! }
|
||||
public var Wallet_WordCheck_IncorrectHeader: String { return self._s[48]! }
|
||||
public var Wallet_Receive_Title: String { return self._s[49]! }
|
||||
public var Wallet_Info_WalletCreated: String { return self._s[50]! }
|
||||
public var Wallet_Navigation_Cancel: String { return self._s[51]! }
|
||||
public var Wallet_CreateInvoice_Title: String { return self._s[52]! }
|
||||
public var Wallet_TransactionInfo_StorageFeeInfoUrl: String { return self._s[49]! }
|
||||
public var Wallet_Receive_Title: String { return self._s[50]! }
|
||||
public var Wallet_Info_WalletCreated: String { return self._s[51]! }
|
||||
public var Wallet_Navigation_Cancel: String { return self._s[52]! }
|
||||
public var Wallet_CreateInvoice_Title: String { return self._s[53]! }
|
||||
public func Wallet_WordCheck_Text(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
|
||||
return formatWithArgumentRanges(self._s[53]!, self._r[53]!, [_1, _2, _3])
|
||||
return formatWithArgumentRanges(self._s[54]!, self._r[54]!, [_1, _2, _3])
|
||||
}
|
||||
public var Wallet_TransactionInfo_SenderHeader: String { return self._s[54]! }
|
||||
public var Wallet_TransactionInfo_SenderHeader: String { return self._s[55]! }
|
||||
public func Wallet_Time_PreciseDate_m4(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
|
||||
return formatWithArgumentRanges(self._s[55]!, self._r[55]!, [_1, _2, _3])
|
||||
return formatWithArgumentRanges(self._s[56]!, self._r[56]!, [_1, _2, _3])
|
||||
}
|
||||
public var Wallet_Month_GenAugust: String { return self._s[56]! }
|
||||
public var Wallet_Info_UnknownTransaction: String { return self._s[57]! }
|
||||
public var Wallet_Receive_CreateInvoice: String { return self._s[58]! }
|
||||
public var Wallet_Month_GenSeptember: String { return self._s[59]! }
|
||||
public var Wallet_Month_GenJuly: String { return self._s[60]! }
|
||||
public var Wallet_Receive_AddressHeader: String { return self._s[61]! }
|
||||
public var Wallet_Send_AmountText: String { return self._s[62]! }
|
||||
public var Wallet_SecureStorageNotAvailable_Text: String { return self._s[63]! }
|
||||
public var Wallet_Month_GenAugust: String { return self._s[57]! }
|
||||
public var Wallet_Info_UnknownTransaction: String { return self._s[58]! }
|
||||
public var Wallet_Receive_CreateInvoice: String { return self._s[59]! }
|
||||
public var Wallet_Month_GenSeptember: String { return self._s[60]! }
|
||||
public var Wallet_Month_GenJuly: String { return self._s[61]! }
|
||||
public var Wallet_Receive_AddressHeader: String { return self._s[62]! }
|
||||
public var Wallet_Send_AmountText: String { return self._s[63]! }
|
||||
public var Wallet_SecureStorageNotAvailable_Text: String { return self._s[64]! }
|
||||
public func Wallet_Time_PreciseDate_m12(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
|
||||
return formatWithArgumentRanges(self._s[64]!, self._r[64]!, [_1, _2, _3])
|
||||
return formatWithArgumentRanges(self._s[65]!, self._r[65]!, [_1, _2, _3])
|
||||
}
|
||||
public func Wallet_Updated_TodayAt(_ _0: String) -> (String, [(Int, NSRange)]) {
|
||||
return formatWithArgumentRanges(self._s[65]!, self._r[65]!, [_0])
|
||||
return formatWithArgumentRanges(self._s[66]!, self._r[66]!, [_0])
|
||||
}
|
||||
public var Wallet_Configuration_Title: String { return self._s[67]! }
|
||||
public var Wallet_Words_Title: String { return self._s[68]! }
|
||||
public var Wallet_Month_ShortMay: String { return self._s[69]! }
|
||||
public var Wallet_WordCheck_Title: String { return self._s[70]! }
|
||||
public var Wallet_Words_NotDoneResponse: String { return self._s[71]! }
|
||||
public var Wallet_Send_ErrorNotEnoughFundsText: String { return self._s[72]! }
|
||||
public var Wallet_Receive_CreateInvoiceInfo: String { return self._s[73]! }
|
||||
public var Wallet_Configuration_Title: String { return self._s[68]! }
|
||||
public var Wallet_Words_Title: String { return self._s[69]! }
|
||||
public var Wallet_Month_ShortMay: String { return self._s[70]! }
|
||||
public var Wallet_WordCheck_Title: String { return self._s[71]! }
|
||||
public var Wallet_Words_NotDoneResponse: String { return self._s[72]! }
|
||||
public var Wallet_Send_ErrorNotEnoughFundsText: String { return self._s[73]! }
|
||||
public var Wallet_Receive_CreateInvoiceInfo: String { return self._s[74]! }
|
||||
public func Wallet_Time_PreciseDate_m9(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
|
||||
return formatWithArgumentRanges(self._s[74]!, self._r[74]!, [_1, _2, _3])
|
||||
return formatWithArgumentRanges(self._s[75]!, self._r[75]!, [_1, _2, _3])
|
||||
}
|
||||
public var Wallet_Info_Address: String { return self._s[75]! }
|
||||
public var Wallet_Intro_CreateWallet: String { return self._s[76]! }
|
||||
public var Wallet_SecureStorageChanged_PasscodeText: String { return self._s[77]! }
|
||||
public var Wallet_Info_Address: String { return self._s[76]! }
|
||||
public var Wallet_Intro_CreateWallet: String { return self._s[77]! }
|
||||
public var Wallet_SecureStorageChanged_PasscodeText: String { return self._s[78]! }
|
||||
public func Wallet_SecureStorageReset_BiometryText(_ _0: String) -> (String, [(Int, NSRange)]) {
|
||||
return formatWithArgumentRanges(self._s[78]!, self._r[78]!, [_0])
|
||||
return formatWithArgumentRanges(self._s[79]!, self._r[79]!, [_0])
|
||||
}
|
||||
public var Wallet_Send_SendAnyway: String { return self._s[79]! }
|
||||
public var Wallet_UnknownError: String { return self._s[80]! }
|
||||
public var Wallet_Completed_ProgressTitle: String { return self._s[81]! }
|
||||
public var Wallet_Send_SendAnyway: String { return self._s[80]! }
|
||||
public var Wallet_UnknownError: String { return self._s[81]! }
|
||||
public var Wallet_SecureStorageChanged_ImportWallet: String { return self._s[82]! }
|
||||
public var Wallet_SecureStorageChanged_CreateWallet: String { return self._s[84]! }
|
||||
public var Wallet_Words_NotDoneOk: String { return self._s[85]! }
|
||||
@ -336,13 +336,13 @@ public final class WalletStrings: Equatable {
|
||||
public func Wallet_SecureStorageChanged_BiometryText(_ _0: String) -> (String, [(Int, NSRange)]) {
|
||||
return formatWithArgumentRanges(self._s[124]!, self._r[124]!, [_0])
|
||||
}
|
||||
public var Wallet_TransactionInfo_FeeInfoURL: String { return self._s[125]! }
|
||||
public func Wallet_Time_PreciseDate_m1(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
|
||||
return formatWithArgumentRanges(self._s[126]!, self._r[126]!, [_1, _2, _3])
|
||||
return formatWithArgumentRanges(self._s[125]!, self._r[125]!, [_1, _2, _3])
|
||||
}
|
||||
public var Wallet_RestoreFailed_CreateWallet: String { return self._s[127]! }
|
||||
public var Wallet_Weekday_Yesterday: String { return self._s[128]! }
|
||||
public var Wallet_Receive_AmountHeader: String { return self._s[129]! }
|
||||
public var Wallet_RestoreFailed_CreateWallet: String { return self._s[126]! }
|
||||
public var Wallet_Weekday_Yesterday: String { return self._s[127]! }
|
||||
public var Wallet_Receive_AmountHeader: String { return self._s[128]! }
|
||||
public var Wallet_TransactionInfo_OtherFeeInfoUrl: String { return self._s[129]! }
|
||||
public var Wallet_Month_ShortFebruary: String { return self._s[130]! }
|
||||
public var Wallet_Alert_Cancel: String { return self._s[131]! }
|
||||
public var Wallet_TransactionInfo_RecipientHeader: String { return self._s[132]! }
|
||||
@ -364,41 +364,41 @@ public final class WalletStrings: Equatable {
|
||||
return formatWithArgumentRanges(self._s[147]!, self._r[147]!, [_1, _2, _3])
|
||||
}
|
||||
public var Wallet_Info_Updating: String { return self._s[149]! }
|
||||
public var Wallet_Intro_TermsUrl: String { return self._s[150]! }
|
||||
public var Wallet_Created_ExportErrorTitle: String { return self._s[151]! }
|
||||
public var Wallet_SecureStorageNotAvailable_Title: String { return self._s[152]! }
|
||||
public var Wallet_Sending_Title: String { return self._s[153]! }
|
||||
public var Wallet_Navigation_Done: String { return self._s[154]! }
|
||||
public var Wallet_Settings_Title: String { return self._s[155]! }
|
||||
public var Wallet_Created_ExportErrorTitle: String { return self._s[150]! }
|
||||
public var Wallet_SecureStorageNotAvailable_Title: String { return self._s[151]! }
|
||||
public var Wallet_Sending_Title: String { return self._s[152]! }
|
||||
public var Wallet_Navigation_Done: String { return self._s[153]! }
|
||||
public var Wallet_Settings_Title: String { return self._s[154]! }
|
||||
public func Wallet_Receive_ShareInvoiceUrlInfo(_ _0: String) -> (String, [(Int, NSRange)]) {
|
||||
return formatWithArgumentRanges(self._s[156]!, self._r[156]!, [_0])
|
||||
return formatWithArgumentRanges(self._s[155]!, self._r[155]!, [_0])
|
||||
}
|
||||
public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[157]! }
|
||||
public var Wallet_Weekday_Today: String { return self._s[159]! }
|
||||
public var Wallet_Month_ShortDecember: String { return self._s[160]! }
|
||||
public var Wallet_Words_Text: String { return self._s[161]! }
|
||||
public var Wallet_WordCheck_ViewWords: String { return self._s[162]! }
|
||||
public var Wallet_Send_AddressInfo: String { return self._s[163]! }
|
||||
public var Wallet_Info_RefreshErrorNetworkText: String { return self._s[156]! }
|
||||
public var Wallet_Weekday_Today: String { return self._s[158]! }
|
||||
public var Wallet_Month_ShortDecember: String { return self._s[159]! }
|
||||
public var Wallet_Words_Text: String { return self._s[160]! }
|
||||
public var Wallet_WordCheck_ViewWords: String { return self._s[161]! }
|
||||
public var Wallet_Send_AddressInfo: String { return self._s[162]! }
|
||||
public func Wallet_Updated_AtDate(_ _0: String) -> (String, [(Int, NSRange)]) {
|
||||
return formatWithArgumentRanges(self._s[164]!, self._r[164]!, [_0])
|
||||
return formatWithArgumentRanges(self._s[163]!, self._r[163]!, [_0])
|
||||
}
|
||||
public var Wallet_Intro_NotNow: String { return self._s[165]! }
|
||||
public var Wallet_Send_OwnAddressAlertProceed: String { return self._s[166]! }
|
||||
public var Wallet_Navigation_Close: String { return self._s[167]! }
|
||||
public var Wallet_Month_GenDecember: String { return self._s[169]! }
|
||||
public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[170]! }
|
||||
public var Wallet_WordImport_IncorrectTitle: String { return self._s[171]! }
|
||||
public var Wallet_Send_AddressText: String { return self._s[172]! }
|
||||
public var Wallet_Receive_AmountInfo: String { return self._s[173]! }
|
||||
public var Wallet_Intro_NotNow: String { return self._s[164]! }
|
||||
public var Wallet_Send_OwnAddressAlertProceed: String { return self._s[165]! }
|
||||
public var Wallet_Navigation_Close: String { return self._s[166]! }
|
||||
public var Wallet_Month_GenDecember: String { return self._s[168]! }
|
||||
public var Wallet_Send_ErrorNotEnoughFundsTitle: String { return self._s[169]! }
|
||||
public var Wallet_WordImport_IncorrectTitle: String { return self._s[170]! }
|
||||
public var Wallet_Send_AddressText: String { return self._s[171]! }
|
||||
public var Wallet_Receive_AmountInfo: String { return self._s[172]! }
|
||||
public func Wallet_Time_PreciseDate_m2(_ _1: String, _ _2: String, _ _3: String) -> (String, [(Int, NSRange)]) {
|
||||
return formatWithArgumentRanges(self._s[174]!, self._r[174]!, [_1, _2, _3])
|
||||
return formatWithArgumentRanges(self._s[173]!, self._r[173]!, [_1, _2, _3])
|
||||
}
|
||||
public var Wallet_Month_ShortAugust: String { return self._s[175]! }
|
||||
public var Wallet_Qr_Title: String { return self._s[176]! }
|
||||
public var Wallet_Settings_Configuration: String { return self._s[177]! }
|
||||
public var Wallet_WordCheck_TryAgain: String { return self._s[178]! }
|
||||
public var Wallet_Info_TransactionPendingHeader: String { return self._s[179]! }
|
||||
public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[180]! }
|
||||
public var Wallet_Month_ShortAugust: String { return self._s[174]! }
|
||||
public var Wallet_Qr_Title: String { return self._s[175]! }
|
||||
public var Wallet_Settings_Configuration: String { return self._s[176]! }
|
||||
public var Wallet_WordCheck_TryAgain: String { return self._s[177]! }
|
||||
public var Wallet_Info_TransactionPendingHeader: String { return self._s[178]! }
|
||||
public var Wallet_Receive_InvoiceUrlHeader: String { return self._s[179]! }
|
||||
public var Wallet_Send_TransactionInProgress: String { return self._s[180]! }
|
||||
public var Wallet_Created_Text: String { return self._s[181]! }
|
||||
public var Wallet_Created_Proceed: String { return self._s[182]! }
|
||||
public var Wallet_Words_Done: String { return self._s[183]! }
|
||||
|
@ -8,6 +8,7 @@ import SwiftSignalKit
|
||||
import OverlayStatusController
|
||||
import WalletCore
|
||||
import AnimatedStickerNode
|
||||
import Markdown
|
||||
|
||||
private func stringForFullDate(timestamp: Int32, strings: WalletStrings, dateTimeFormat: WalletPresentationDateTimeFormat) -> String {
|
||||
var t: time_t = Int(timestamp)
|
||||
@ -200,12 +201,20 @@ final class WalletTransactionInfoScreen: ViewController {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
var string = NSMutableAttributedString(string: "Blockchain validators collect a tiny fee for storing information about your decentralized wallet and for processing your transactions. More info", font: Font.regular(14.0), textColor: .white, paragraphAlignment: .center)
|
||||
string.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor(rgb: 0x6bb2ff), range: NSMakeRange(string.string.count - 10, 10))
|
||||
let controller = TooltipController(content: .attributedText(string), timeout: 3.0, dismissByTapOutside: true, dismissByTapOutsideSource: false, dismissImmediatelyOnLayoutUpdate: false, arrowOnBottom: false)
|
||||
let text: NSAttributedString
|
||||
if let _ = strongSelf.context.feeInfoUrl {
|
||||
let body = MarkdownAttributeSet(font: Font.regular(14.0), textColor: .white, additionalAttributes: [:])
|
||||
let link = MarkdownAttributeSet(font: Font.regular(14.0), textColor: strongSelf.context.presentationData.theme.alert.accentColor, additionalAttributes: [:])
|
||||
text = parseMarkdownIntoAttributedString(strongSelf.context.presentationData.strings.Wallet_TransactionInfo_StorageFeeInfoUrl, attributes: MarkdownAttributes(body: body, bold: body, link: link, linkAttribute: { _ in nil }), textAlignment: .center)
|
||||
} else {
|
||||
text = NSAttributedString(string: strongSelf.context.presentationData.strings.Wallet_TransactionInfo_StorageFeeInfo, font: Font.regular(14.0), textColor: .white, paragraphAlignment: .center)
|
||||
}
|
||||
let controller = TooltipController(content: .attributedText(text), timeout: 3.0, dismissByTapOutside: true, dismissByTapOutsideSource: false, dismissImmediatelyOnLayoutUpdate: false, arrowOnBottom: false)
|
||||
controller.dismissed = { [weak self] tappedInside in
|
||||
if let strongSelf = self, tappedInside {
|
||||
strongSelf.context.openUrl(strongSelf.presentationData.strings.Wallet_TransactionInfo_FeeInfoURL)
|
||||
if let feeInfoUrl = strongSelf.context.feeInfoUrl {
|
||||
strongSelf.context.openUrl(feeInfoUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
strongSelf.present(controller, in: .window(.root), with: TooltipControllerPresentationArguments(sourceViewAndRect: {
|
||||
|
@ -2137,7 +2137,7 @@ public final class WalletWordCheckScreen: ViewController {
|
||||
return true
|
||||
}
|
||||
let _ = confirmWalletExported(storage: strongSelf.context.storage, publicKey: walletInfo.publicKey).start()
|
||||
controllers.append(WalletSplashScreen(context: strongSelf.context, mode: .success(walletInfo, false), walletCreatedPreloadState: strongSelf.walletCreatedPreloadState))
|
||||
controllers.append(WalletSplashScreen(context: strongSelf.context, mode: .success(walletInfo), walletCreatedPreloadState: strongSelf.walletCreatedPreloadState))
|
||||
strongSelf.view.endEditing(true)
|
||||
navigationController.setViewControllers(controllers, animated: true)
|
||||
}
|
||||
@ -2205,7 +2205,7 @@ public final class WalletWordCheckScreen: ViewController {
|
||||
}
|
||||
return true
|
||||
}
|
||||
controllers.append(WalletSplashScreen(context: strongSelf.context, mode: .success(walletInfo, false), walletCreatedPreloadState: strongSelf.walletCreatedPreloadState))
|
||||
controllers.append(WalletSplashScreen(context: strongSelf.context, mode: .success(walletInfo), walletCreatedPreloadState: strongSelf.walletCreatedPreloadState))
|
||||
strongSelf.view.endEditing(true)
|
||||
navigationController.setViewControllers(controllers, animated: true)
|
||||
}
|
||||
|
12
submodules/WalletUI/WalletImages.xcassets/Wallet/DisclosureArrow.imageset/Contents.json
vendored
Normal file
12
submodules/WalletUI/WalletImages.xcassets/Wallet/DisclosureArrow.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_open.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/WalletUI/WalletImages.xcassets/Wallet/DisclosureArrow.imageset/ic_open.pdf
vendored
Normal file
BIN
submodules/WalletUI/WalletImages.xcassets/Wallet/DisclosureArrow.imageset/ic_open.pdf
vendored
Normal file
Binary file not shown.
12
submodules/WalletUI/WalletImages.xcassets/Wallet/NavigationShare.imageset/Contents.json
vendored
Normal file
12
submodules/WalletUI/WalletImages.xcassets/Wallet/NavigationShare.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "ic_share.pdf"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
submodules/WalletUI/WalletImages.xcassets/Wallet/NavigationShare.imageset/ic_share.pdf
vendored
Normal file
BIN
submodules/WalletUI/WalletImages.xcassets/Wallet/NavigationShare.imageset/ic_share.pdf
vendored
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user