diff --git a/Kukai Mobile.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Kukai Mobile.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
index de385198..64b3ca4e 100644
--- a/Kukai Mobile.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/Kukai Mobile.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -63,22 +63,13 @@
"version" : "20.0.0"
}
},
- {
- "identity" : "kingfisher",
- "kind" : "remoteSourceControl",
- "location" : "https://github.com/simonmcl/Kingfisher.git",
- "state" : {
- "revision" : "292ab48438344320e7e9bcf3da46f766c30f7070",
- "version" : "1.0.0"
- }
- },
{
"identity" : "kukai-core-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/kukai-wallet/kukai-core-swift",
"state" : {
"branch" : "develop",
- "revision" : "3c5e492f50d062cdc199622d63e826e640baec25"
+ "revision" : "55c19abeb503e4e69c7a811d85e77d8199e74b9d"
}
},
{
@@ -99,6 +90,15 @@
"version" : "14.3.1"
}
},
+ {
+ "identity" : "sdwebimage",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/SDWebImage/SDWebImage.git",
+ "state" : {
+ "revision" : "59730af512c06fb569c119d737df4c1c499e001d",
+ "version" : "5.18.10"
+ }
+ },
{
"identity" : "secp256k1.swift",
"kind" : "remoteSourceControl",
@@ -135,15 +135,6 @@
"version" : "3.1.2"
}
},
- {
- "identity" : "svgkit",
- "kind" : "remoteSourceControl",
- "location" : "https://github.com/simonmcl/SVGKit",
- "state" : {
- "revision" : "3ca70eae8573b876e403be8a9bdbe784fd560c0b",
- "version" : "3.0.3"
- }
- },
{
"identity" : "swift-qrcode-generator",
"kind" : "remoteSourceControl",
diff --git a/Kukai Mobile/AppDelegate.swift b/Kukai Mobile/AppDelegate.swift
index 7d339a1b..4b356272 100644
--- a/Kukai Mobile/AppDelegate.swift
+++ b/Kukai Mobile/AppDelegate.swift
@@ -45,7 +45,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// Setup any necessary settings, such as RAM limits
- MediaProxyService.setupKingfisher()
+ MediaProxyService.setupImageLibrary()
// process special arguments coming from XCUITest to do things like show keyboard and reset app data
diff --git a/Kukai Mobile/Assets.xcassets/Icons/Masters/template/FavCorner.imageset/Contents.json b/Kukai Mobile/Assets.xcassets/Icons/Masters/template/FavCorner.imageset/Contents.json
new file mode 100644
index 00000000..265a38dd
--- /dev/null
+++ b/Kukai Mobile/Assets.xcassets/Icons/Masters/template/FavCorner.imageset/Contents.json
@@ -0,0 +1,16 @@
+{
+ "images" : [
+ {
+ "filename" : "FavCorner.svg",
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ },
+ "properties" : {
+ "preserves-vector-representation" : true,
+ "template-rendering-intent" : "template"
+ }
+}
diff --git a/Kukai Mobile/Assets.xcassets/Icons/Masters/template/FavCorner.imageset/FavCorner.svg b/Kukai Mobile/Assets.xcassets/Icons/Masters/template/FavCorner.imageset/FavCorner.svg
new file mode 100644
index 00000000..9cb42895
--- /dev/null
+++ b/Kukai Mobile/Assets.xcassets/Icons/Masters/template/FavCorner.imageset/FavCorner.svg
@@ -0,0 +1,3 @@
+
diff --git a/Kukai Mobile/Assets.xcassets/Icons/social/Social_Email_Outlined.imageset/Contents.json b/Kukai Mobile/Assets.xcassets/Icons/social/Social_Email_Outlined.imageset/Contents.json
index d0f1557e..7839d569 100644
--- a/Kukai Mobile/Assets.xcassets/Icons/social/Social_Email_Outlined.imageset/Contents.json
+++ b/Kukai Mobile/Assets.xcassets/Icons/social/Social_Email_Outlined.imageset/Contents.json
@@ -11,6 +11,6 @@
},
"properties" : {
"preserves-vector-representation" : true,
- "template-rendering-intent" : "template"
+ "template-rendering-intent" : "original"
}
}
diff --git a/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_1color.imageset/Contents.json b/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_1color.imageset/Contents.json
index 2cbddd6b..7f38b1ef 100644
--- a/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_1color.imageset/Contents.json
+++ b/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_1color.imageset/Contents.json
@@ -1,7 +1,7 @@
{
"images" : [
{
- "filename" : "Social_Twitter_1color.svg",
+ "filename" : "Social_Twitter_color.svg",
"idiom" : "universal"
}
],
diff --git a/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_1color.imageset/Social_Twitter_1color.svg b/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_1color.imageset/Social_Twitter_1color.svg
deleted file mode 100644
index 3b5c3c9e..00000000
--- a/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_1color.imageset/Social_Twitter_1color.svg
+++ /dev/null
@@ -1,10 +0,0 @@
-
diff --git a/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_1color.imageset/Social_Twitter_color.svg b/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_1color.imageset/Social_Twitter_color.svg
new file mode 100644
index 00000000..dc8ef14b
--- /dev/null
+++ b/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_1color.imageset/Social_Twitter_color.svg
@@ -0,0 +1,15 @@
+
diff --git a/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_color.imageset/Contents.json b/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_color.imageset/Contents.json
index 4c060d45..e4cbd805 100644
--- a/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_color.imageset/Contents.json
+++ b/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_color.imageset/Contents.json
@@ -1,7 +1,7 @@
{
"images" : [
{
- "filename" : "Social_Twitter_color.svg",
+ "filename" : "Social_Twitter_1color.svg",
"idiom" : "universal"
}
],
diff --git a/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_color.imageset/Social_Twitter_1color.svg b/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_color.imageset/Social_Twitter_1color.svg
new file mode 100644
index 00000000..3e840c96
--- /dev/null
+++ b/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_color.imageset/Social_Twitter_1color.svg
@@ -0,0 +1,15 @@
+
diff --git a/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_color.imageset/Social_Twitter_color.svg b/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_color.imageset/Social_Twitter_color.svg
deleted file mode 100644
index 976489e9..00000000
--- a/Kukai Mobile/Assets.xcassets/Icons/social/Social_Twitter_color.imageset/Social_Twitter_color.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/Kukai Mobile/Controls/ScanViewController.swift b/Kukai Mobile/Controls/ScanViewController.swift
index 330cd69c..6fbf5fcf 100644
--- a/Kukai Mobile/Controls/ScanViewController.swift
+++ b/Kukai Mobile/Controls/ScanViewController.swift
@@ -70,7 +70,7 @@ class ScanViewController: UIViewController, AVCaptureMetadataOutputObjectsDelega
}
@objc func textFieldDone() {
- found(code: textfield.text ?? "")
+ checkForBeaconAndReport(stringToCheck: textfield.text ?? "")
}
func setupNav() {
@@ -329,13 +329,23 @@ class ScanViewController: UIViewController, AVCaptureMetadataOutputObjectsDelega
}
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
- captureSession.stopRunning()
if let metadataObject = metadataObjects.first {
guard let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject else { return }
guard let stringValue = readableObject.stringValue else { return }
AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
- found(code: stringValue)
+ checkForBeaconAndReport(stringToCheck: stringValue)
+ }
+ }
+
+ private func checkForBeaconAndReport(stringToCheck: String) {
+ if let data = stringToCheck.base58CheckDecodedData, let json = try? JSONSerialization.jsonObject(with: data) as? [String: String], let _ = json["relayServer"], let _ = json["publicKey"] {
+ self.windowError(withTitle: "error".localized(), description: "error-beacon-not-supported".localized())
+ self.textfield.text = ""
+
+ } else {
+ captureSession.stopRunning()
+ found(code: stringToCheck)
}
}
diff --git a/Kukai Mobile/Controls/ThemeManager.swift b/Kukai Mobile/Controls/ThemeManager.swift
index 26d62984..639cd5ff 100644
--- a/Kukai Mobile/Controls/ThemeManager.swift
+++ b/Kukai Mobile/Controls/ThemeManager.swift
@@ -6,6 +6,7 @@
//
import UIKit
+import KukaiCoreSwift
import os.log
/**
@@ -507,7 +508,10 @@ public class ThemeManager {
}
public func updateSystemInterfaceStyle() {
- UIApplication.shared.currentWindow?.overrideUserInterfaceStyle = currentInterfaceStyle()
+ let current = currentInterfaceStyle()
+
+ UIApplication.shared.currentWindow?.overrideUserInterfaceStyle = current
+ MediaProxyService.isDarkMode = (current == .dark)
}
public func currentInterfaceStyle() -> UIUserInterfaceStyle {
diff --git a/Kukai Mobile/Extensions/UIImageView+extensions.swift b/Kukai Mobile/Extensions/UIImageView+extensions.swift
index c98c0871..0375b912 100644
--- a/Kukai Mobile/Extensions/UIImageView+extensions.swift
+++ b/Kukai Mobile/Extensions/UIImageView+extensions.swift
@@ -6,15 +6,10 @@
//
import UIKit
-import Kingfisher
import KukaiCoreSwift
extension UIImageView {
- func setImageToCurrentSize(url: URL?) {
- self.kf.setImage(with: url, options: [.processor( DownsamplingImageProcessor(size: CGSize(width: self.frame.width, height: self.frame.height)) )])
- }
-
func tint(color: UIColor) {
self.image = self.image?.withRenderingMode(.alwaysTemplate)
self.tintColor = color
diff --git a/Kukai Mobile/Extensions/UIView+extensions.swift b/Kukai Mobile/Extensions/UIView+extensions.swift
index c8d08eb3..f5cc7fff 100644
--- a/Kukai Mobile/Extensions/UIView+extensions.swift
+++ b/Kukai Mobile/Extensions/UIView+extensions.swift
@@ -100,7 +100,7 @@ extension UIView {
rotateAnimation.toValue = CGFloat(Double.pi * 2)
rotateAnimation.isRemovedOnCompletion = false
rotateAnimation.duration = duration
- rotateAnimation.repeatCount=Float.infinity
+ rotateAnimation.repeatCount = Float.infinity
self.layer.add(rotateAnimation, forKey: nil)
}
diff --git a/Kukai Mobile/Localization/en.lproj/Localizable.strings b/Kukai Mobile/Localization/en.lproj/Localizable.strings
index d2a54a2a..af7d7b97 100644
--- a/Kukai Mobile/Localization/en.lproj/Localizable.strings
+++ b/Kukai Mobile/Localization/en.lproj/Localizable.strings
@@ -50,3 +50,4 @@
"error-unsupported-sign"="Unsupported signature request";
"error-wc2-unrecoverable"="An unknown error occured with the connection. This operation can't continue. Please check the other application and try agian";
"error-wc2-cant-continue"="Unable to continue with this request due to system error";
+"error-beacon-not-supported"="Beacon QRCodes are not supported, only Wallet Connect. Please make sure you are using the kukai option. If you are, please contact the dApp support team and ask them to update their beacon version";
diff --git a/Kukai Mobile/Modules/Account/Account.storyboard b/Kukai Mobile/Modules/Account/Account.storyboard
index d84d3014..3ac0d113 100644
--- a/Kukai Mobile/Modules/Account/Account.storyboard
+++ b/Kukai Mobile/Modules/Account/Account.storyboard
@@ -1,9 +1,9 @@
-
+
-
+
@@ -60,13 +60,13 @@
-
+
@@ -453,200 +453,7 @@ for your Digital Assets
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -702,36 +509,27 @@ for your Digital Assets
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
@@ -759,59 +557,27 @@ for your Digital Assets
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
+
-
-
+
-
-
-
+
-
@@ -830,22 +596,14 @@ for your Digital Assets
-
-
-
-
-
-
-
-
@@ -2211,9 +1969,6 @@ Passcode must have at least 3 unique digits, and no more than 3 sequential digit
-
-
-
@@ -2223,15 +1978,9 @@ Passcode must have at least 3 unique digits, and no more than 3 sequential digit
-
-
-
-
-
-
@@ -2250,21 +1999,12 @@ Passcode must have at least 3 unique digits, and no more than 3 sequential digit
-
-
-
-
-
-
-
-
-
@@ -2300,14 +2040,10 @@ Passcode must have at least 3 unique digits, and no more than 3 sequential digit
-
-
-
-
-
+
diff --git a/Kukai Mobile/Modules/Onboarding/CreateWithSocialViewController.swift b/Kukai Mobile/Modules/Onboarding/CreateWithSocialViewController.swift
index 047345b7..cc58c74b 100644
--- a/Kukai Mobile/Modules/Onboarding/CreateWithSocialViewController.swift
+++ b/Kukai Mobile/Modules/Onboarding/CreateWithSocialViewController.swift
@@ -22,18 +22,7 @@ class CreateWithSocialViewController: UIViewController {
@IBOutlet var twitterButton: CustomisableButton!
@IBOutlet var redditButton: CustomisableButton!
- @IBOutlet var socialOptions2: UIStackView!
- @IBOutlet var discordButton: CustomisableButton!
- @IBOutlet var twitchButton: CustomisableButton!
- @IBOutlet var lineButton: CustomisableButton!
-
- @IBOutlet var socialOptions3: UIStackView!
- @IBOutlet var githubButton: CustomisableButton!
-
- @IBOutlet var emailTextField: ValidatorTextField!
@IBOutlet var continueWIthEmailButton: CustomisableButton!
- @IBOutlet var viewMoreOptionsButton: CustomisableButton!
-
private let cloudKitService = CloudKitService()
private var appleGradient = CAGradientLayer()
@@ -45,11 +34,6 @@ class CreateWithSocialViewController: UIViewController {
super.viewDidLoad()
let _ = self.view.addGradientBackgroundFull()
- scrollView.addGestureRecognizer(UITapGestureRecognizer(target: emailTextField, action: #selector(resignFirstResponder)))
-
- socialOptions2.isHidden = true
- socialOptions3.isHidden = true
-
appleButton.customButtonType = .primary
appleButton.configuration?.imagePadding = 8
googleButton.customButtonType = .tertiary
@@ -60,19 +44,8 @@ class CreateWithSocialViewController: UIViewController {
twitterButton.customButtonType = .secondary
redditButton.customButtonType = .secondary
- discordButton.customButtonType = .secondary
- twitchButton.customButtonType = .secondary
- lineButton.customButtonType = .secondary
-
- githubButton.customButtonType = .secondary
-
learnMoreButton.configuration?.imagePlacement = .trailing
learnMoreButton.configuration?.imagePadding = 8
- viewMoreOptionsButton.configuration?.imagePlacement = .trailing
- viewMoreOptionsButton.configuration?.imagePadding = 8
-
- emailTextField.validator = EmailValidator()
- emailTextField.validatorTextFieldDelegate = self
// Can't detect certain events from Torus presented modals (e.g. when a user clicks cancel). Adding a second listener to the notification they use so I can trigger a loading modal
@@ -123,70 +96,40 @@ class CreateWithSocialViewController: UIViewController {
return
}
- self.showLoadingView() // uses differetn callback structure to rest, need to pop loading here
+ self.showLoadingView() // uses different callback structure to rest, need to pop loading here
DependencyManager.shared.torusAuthService.createWallet(from: .apple, displayOver: self.presentedViewController) { [weak self] result in
self?.handleResult(result: result)
}
}
@IBAction func googleTapped(_ sender: Any) {
- guard DependencyManager.shared.torusVerifiers[.google] != nil else {
- self.windowError(withTitle: "error".localized(), description: "error-missing-verifier".localized())
- return
- }
-
- DependencyManager.shared.torusAuthService.createWallet(from: .google, displayOver: self) { [weak self] result in
- self?.handleResult(result: result)
- }
+ createWallet(withVerifier: .google)
}
@IBAction func facebookTapped(_ sender: Any) {
- self.windowError(withTitle: "Not yet supported", description: "This feature is not yet enabled. Please wait for another release")
+ createWallet(withVerifier: .facebook)
}
@IBAction func twitterTapped(_ sender: Any) {
- self.windowError(withTitle: "Not yet supported", description: "This feature is not yet enabled. Please wait for another release")
+ createWallet(withVerifier: .twitter)
}
@IBAction func redditTapped(_ sender: Any) {
- self.windowError(withTitle: "Not yet supported", description: "This feature is not yet enabled. Please wait for another release")
- }
-
- @IBAction func discordTapped(_ sender: Any) {
- self.windowError(withTitle: "Not yet supported", description: "This feature is not yet enabled. Please wait for another release")
- }
-
- @IBAction func twitchTapped(_ sender: Any) {
- self.windowError(withTitle: "Not yet supported", description: "This feature is not yet enabled. Please wait for another release")
- }
-
- @IBAction func lineTapped(_ sender: Any) {
- self.windowError(withTitle: "Not yet supported", description: "This feature is not yet enabled. Please wait for another release")
- }
-
- @IBAction func githubTapped(_ sender: Any) {
- self.windowError(withTitle: "Not yet supported", description: "This feature is not yet enabled. Please wait for another release")
+ createWallet(withVerifier: .reddit)
}
@IBAction func continueWithEmailTapped(_ sender: Any) {
- self.windowError(withTitle: "Not yet supported", description: "This feature is not yet enabled. Please wait for another release")
+ createWallet(withVerifier: .email)
}
- @IBAction func viewMoreOptionsTapped(_ sender: Any) {
-
- if socialOptions2.isHidden {
- socialOptions2.isHidden = false
- socialOptions3.isHidden = false
- viewMoreOptionsButton.imageView?.rotate(degrees: 180, duration: 0.3)
-
- } else {
- socialOptions2.isHidden = true
- socialOptions3.isHidden = true
- viewMoreOptionsButton.imageView?.rotateBack(duration: 0.3)
+ private func createWallet(withVerifier verifier: TorusAuthProvider) {
+ guard DependencyManager.shared.torusVerifiers[verifier] != nil else {
+ self.windowError(withTitle: "error".localized(), description: "error-missing-verifier".localized())
+ return
}
- UIView.animate(withDuration: 0.3) { [weak self] in
- self?.view.layoutIfNeeded()
+ DependencyManager.shared.torusAuthService.createWallet(from: verifier, displayOver: self) { [weak self] result in
+ self?.handleResult(result: result)
}
}
@@ -241,26 +184,3 @@ extension CreateWithSocialViewController: AutoScrollViewDelegate {
self.topSectionContainer.isUserInteractionEnabled = true
}
}
-
-extension CreateWithSocialViewController: ValidatorTextFieldDelegate {
-
- func textFieldDidBeginEditing(_ textField: UITextField) {
-
- }
-
- func textFieldDidEndEditing(_ textField: UITextField) {
-
- }
-
- func textFieldShouldClear(_ textField: UITextField) -> Bool {
- return true
- }
-
- func validated(_ validated: Bool, textfield: ValidatorTextField, forText text: String) {
- continueWIthEmailButton.isEnabled = validated
- }
-
- func doneOrReturnTapped(isValid: Bool, textfield: ValidatorTextField, forText text: String?) {
-
- }
-}
diff --git a/Kukai Mobile/Modules/Send/Base.lproj/Send.storyboard b/Kukai Mobile/Modules/Send/Base.lproj/Send.storyboard
index b63e569a..a5283d46 100644
--- a/Kukai Mobile/Modules/Send/Base.lproj/Send.storyboard
+++ b/Kukai Mobile/Modules/Send/Base.lproj/Send.storyboard
@@ -3555,7 +3555,7 @@
-
+
@@ -3740,172 +3740,36 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
+
+
+
+
+
+
-
+
@@ -3916,7 +3780,7 @@
-
+
@@ -4200,21 +4064,12 @@
-
-
-
-
-
-
-
-
-
@@ -4322,12 +4177,16 @@
+
+
+
+
diff --git a/Kukai Mobile/Modules/Send/SendCollectibleAmountViewController.swift b/Kukai Mobile/Modules/Send/SendCollectibleAmountViewController.swift
index 48df09a7..52a120cf 100644
--- a/Kukai Mobile/Modules/Send/SendCollectibleAmountViewController.swift
+++ b/Kukai Mobile/Modules/Send/SendCollectibleAmountViewController.swift
@@ -65,7 +65,7 @@ class SendCollectibleAmountViewController: UIViewController {
maxButton.setTitle("Max \(amountDisplay)", for: .normal)
}
- MediaProxyService.load(url: MediaProxyService.url(fromUri: selectedToken?.displayURI, ofFormat: .small), to: collectibleImage, withCacheType: .temporary, fallback: UIImage())
+ MediaProxyService.load(url: MediaProxyService.url(fromUri: selectedToken?.displayURI, ofFormat: MediaProxyService.Format.small.rawFormat()), to: collectibleImage, withCacheType: .temporary, fallback: UIImage())
collectibleName.text = selectedToken?.name ?? ""
diff --git a/Kukai Mobile/Modules/Send/SendCollectibleConfirmViewController.swift b/Kukai Mobile/Modules/Send/SendCollectibleConfirmViewController.swift
index 33f5651f..e0bd028a 100644
--- a/Kukai Mobile/Modules/Send/SendCollectibleConfirmViewController.swift
+++ b/Kukai Mobile/Modules/Send/SendCollectibleConfirmViewController.swift
@@ -85,7 +85,7 @@ class SendCollectibleConfirmViewController: SendAbstractConfirmViewController, S
self.connectedAppNameLabel.text = session.peer.name
if let iconString = session.peer.icons.first, let iconUrl = URL(string: iconString) {
- let smallIconURL = MediaProxyService.url(fromUri: iconUrl, ofFormat: .icon)
+ let smallIconURL = MediaProxyService.url(fromUri: iconUrl, ofFormat: MediaProxyService.Format.icon.rawFormat())
connectedAppURL = smallIconURL
}
@@ -170,7 +170,7 @@ class SendCollectibleConfirmViewController: SendAbstractConfirmViewController, S
}
feeValueLabel?.text = "0 tez"
- MediaProxyService.load(url: MediaProxyService.url(fromUri: token.displayURI, ofFormat: .small), to: collectibleImage, withCacheType: .temporary, fallback: UIImage())
+ MediaProxyService.load(url: MediaProxyService.url(fromUri: token.displayURI, ofFormat: MediaProxyService.Format.small.rawFormat()), to: collectibleImage, withCacheType: .temporary, fallback: UIImage())
}
override func viewDidAppear(_ animated: Bool) {
@@ -252,7 +252,7 @@ class SendCollectibleConfirmViewController: SendAbstractConfirmViewController, S
let destinationAlias = currentSendData.destinationAlias
let amount = currentSendData.chosenAmount ?? .zero()
- let mediaURL = MediaProxyService.thumbnailURL(forNFT: nft)
+ let mediaURL = MediaProxyService.smallURL(forNFT: nft)
let token = Token.placeholder(fromNFT: nft, amount: amount, thumbnailURL: mediaURL)
let currentOps = selectedOperationsAndFees()
diff --git a/Kukai Mobile/Modules/Send/SendContractConfirmViewController.swift b/Kukai Mobile/Modules/Send/SendContractConfirmViewController.swift
index d1bf30a1..f40fdb38 100644
--- a/Kukai Mobile/Modules/Send/SendContractConfirmViewController.swift
+++ b/Kukai Mobile/Modules/Send/SendContractConfirmViewController.swift
@@ -93,7 +93,7 @@ class SendContractConfirmViewController: SendAbstractConfirmViewController, Slid
self.connectedAppNameLabel.text = session.peer.name
if let iconString = session.peer.icons.first, let iconUrl = URL(string: iconString) {
- let smallIconURL = MediaProxyService.url(fromUri: iconUrl, ofFormat: .icon)
+ let smallIconURL = MediaProxyService.url(fromUri: iconUrl, ofFormat: MediaProxyService.Format.icon.rawFormat())
connectedAppURL = smallIconURL
}
diff --git a/Kukai Mobile/Modules/Send/SendGenericConfirmViewController.swift b/Kukai Mobile/Modules/Send/SendGenericConfirmViewController.swift
index f46dcc44..a95f40a7 100644
--- a/Kukai Mobile/Modules/Send/SendGenericConfirmViewController.swift
+++ b/Kukai Mobile/Modules/Send/SendGenericConfirmViewController.swift
@@ -86,7 +86,7 @@ class SendGenericConfirmViewController: SendAbstractConfirmViewController, Slide
self.connectedAppNameLabel.text = session.peer.name
if let iconString = session.peer.icons.first, let iconUrl = URL(string: iconString) {
- let smallIconURL = MediaProxyService.url(fromUri: iconUrl, ofFormat: .icon)
+ let smallIconURL = MediaProxyService.url(fromUri: iconUrl, ofFormat: MediaProxyService.Format.icon.rawFormat())
connectedAppURL = smallIconURL
}
@@ -113,7 +113,6 @@ class SendGenericConfirmViewController: SendAbstractConfirmViewController, Slide
// Display JSON
- updateAmountDisplay(withValue: currentSendData.chosenAmount ?? .zero())
updateOperationDisplay()
@@ -201,33 +200,6 @@ class SendGenericConfirmViewController: SendAbstractConfirmViewController, Slide
}
}
- func updateAmountDisplay(withValue value: TokenAmount) {
- guard let token = currentSendData.chosenToken else {
- largeDisplayStackView.isHidden = true
- smallDisplayIcon.image = UIImage.unknownToken()
- smallDisplayAmount.text = "0"
- smallDisplayFiat.text = DependencyManager.shared.balanceService.fiatAmountDisplayString(forToken: Token.xtz(), ofAmount: TokenAmount.zero())
- return
- }
-
- let amountText = value.normalisedRepresentation
- if amountText.count > Int(UIScreen.main.bounds.width / 4) {
- // small display
- largeDisplayStackView.isHidden = true
- smallDisplayIcon.addTokenIcon(token: token)
- smallDisplayAmount.text = amountText + token.symbol
- smallDisplayFiat.text = DependencyManager.shared.balanceService.fiatAmountDisplayString(forToken: token, ofAmount: value)
-
- } else {
- // large display
- smallDisplayStackView.isHidden = true
- largeDisplayIcon.addTokenIcon(token: token)
- largeDisplayAmount.text = amountText
- largeDisplaySymbol.text = token.symbol
- largeDisplayFiat.text = DependencyManager.shared.balanceService.fiatAmountDisplayString(forToken: token, ofAmount: value)
- }
- }
-
func updateOperationDisplay() {
let ops = selectedOperationsAndFees()
@@ -245,6 +217,7 @@ class SendGenericConfirmViewController: SendAbstractConfirmViewController, Slide
feeValueLabel.text = fee.normalisedRepresentation + " tez"
feeButton.setTitle(feesAndData.type.displayName(), for: .normal)
+ updateOperationDisplay()
}
@IBAction func closeTapped(_ sender: Any) {
diff --git a/Kukai Mobile/Modules/Send/SendTokenConfirmViewController.swift b/Kukai Mobile/Modules/Send/SendTokenConfirmViewController.swift
index 04eb4128..56e81e7d 100644
--- a/Kukai Mobile/Modules/Send/SendTokenConfirmViewController.swift
+++ b/Kukai Mobile/Modules/Send/SendTokenConfirmViewController.swift
@@ -93,7 +93,7 @@ class SendTokenConfirmViewController: SendAbstractConfirmViewController, SlideBu
self.connectedAppNameLabel.text = session.peer.name
if let iconString = session.peer.icons.first, let iconUrl = URL(string: iconString) {
- let smallIconURL = MediaProxyService.url(fromUri: iconUrl, ofFormat: .icon)
+ let smallIconURL = MediaProxyService.url(fromUri: iconUrl, ofFormat: MediaProxyService.Format.icon.rawFormat())
connectedAppURL = smallIconURL
}
diff --git a/Kukai Mobile/Modules/Side Menu/SideMenuResetViewController.swift b/Kukai Mobile/Modules/Side Menu/SideMenuResetViewController.swift
index 76ed4a23..73a7ea35 100644
--- a/Kukai Mobile/Modules/Side Menu/SideMenuResetViewController.swift
+++ b/Kukai Mobile/Modules/Side Menu/SideMenuResetViewController.swift
@@ -7,7 +7,6 @@
import UIKit
import KukaiCoreSwift
-import Kingfisher
class SideMenuResetViewController: UIViewController {
@@ -59,9 +58,7 @@ class SideMenuResetViewController: UIViewController {
DependencyManager.shared.setDefaultMainnetURLs(supressUpdateNotification: true)
- MediaProxyService.imageCache(forType: .temporary).clearCache {
- MediaProxyService.imageCache(forType: .permanent).clearCache(completion: completion)
- }
+ MediaProxyService.removeAllImages(completion: completion)
}
@IBAction func noButtonTapped(_ sender: Any) {
diff --git a/Kukai Mobile/Modules/Side Menu/WalletConnectViewModel.swift b/Kukai Mobile/Modules/Side Menu/WalletConnectViewModel.swift
index 2fec91d9..42453382 100644
--- a/Kukai Mobile/Modules/Side Menu/WalletConnectViewModel.swift
+++ b/Kukai Mobile/Modules/Side Menu/WalletConnectViewModel.swift
@@ -36,7 +36,7 @@ class WalletConnectViewModel: ViewModel, UITableViewDiffableDataSourceHandler {
return tableView.dequeueReusableCell(withIdentifier: "empty", for: indexPath)
} else if let obj = item as? PairObj, let cell = tableView.dequeueReusableCell(withIdentifier: "ConnectedApp", for: indexPath) as? ConnectedAppCell {
- let iconURL = MediaProxyService.url(fromUri: obj.icon, ofFormat: .icon)
+ let iconURL = MediaProxyService.url(fromUri: obj.icon, ofFormat: MediaProxyService.Format.icon.rawFormat())
MediaProxyService.load(url: iconURL, to: cell.iconView, withCacheType: .temporary, fallback: UIImage.unknownToken())
cell.siteLabel.text = obj.site
cell.networkLabel.text = obj.network
diff --git a/Kukai Mobile/Services/BalanceService.swift b/Kukai Mobile/Services/BalanceService.swift
index 114b8dc6..17a1a70d 100644
--- a/Kukai Mobile/Services/BalanceService.swift
+++ b/Kukai Mobile/Services/BalanceService.swift
@@ -540,7 +540,7 @@ public class BalanceService {
if let address = token.tokenContractAddress, let objktData = DependencyManager.shared.objktClient.collections[address] {
var url: URL? = nil
if let logo = objktData.logo {
- url = MediaProxyService.url(fromUri: URL(string: logo), ofFormat: .icon)
+ url = MediaProxyService.url(fromUri: URL(string: logo), ofFormat: MediaProxyService.Format.icon.rawFormat())
}
let token = Token(name: objktData.name, symbol: "", tokenType: .nonfungible, faVersion: .fa2, balance: token.balance, thumbnailURL: url, tokenContractAddress: address, tokenId: token.tokenId, nfts: token.nfts, mintingTool: token.mintingTool)
diff --git a/Kukai Mobile/Services/CloudKitService.swift b/Kukai Mobile/Services/CloudKitService.swift
index 98fc4f2f..41b3d901 100644
--- a/Kukai Mobile/Services/CloudKitService.swift
+++ b/Kukai Mobile/Services/CloudKitService.swift
@@ -45,53 +45,66 @@ public class CloudKitService {
for record in configItemRecords where record.stringForKey("serviceId") == "torus" {
- guard let networkStr = record.stringForKey("network"),
- let network = TezosNodeClientConfig.NetworkType(rawValue: networkStr),
- let config = record.doubleStringArrayToDict(key1: "keys", key2: "values"),
- let provider = config["loginProvider"],
- let type = config["loginType"],
- let authProvider = TorusAuthProvider(rawValue: provider) else {
- Logger.app.error("Skipping invalid torus config item: \(record.description)")
- continue
- }
+ // record.stringForKey returns nil, haven't got the slightest clue why. Can only get the `json` key value by fetching all values and parsing
+ var jsonString = (record.value(forKey: "values") as? [Any])?[0] as? String
+ jsonString = jsonString?.replacingOccurrences(of: "\n", with: "")
+ jsonString = jsonString?.replacingOccurrences(of: "\t", with: "")
- // Option 1:
- // Required: loginType, loginProvider, verifierName, redirectURL
- // Optional: aggregateVerifierName, clientId
- if let loginType = SubVerifierType(rawValue: type), let loginProvider = LoginProviders(rawValue: provider), let verifierName = config["verifierName"], let redirectURL = config["redirectURL"] {
- let details = SubVerifierDetails(loginType: loginType, loginProvider: loginProvider, clientId: config["clientId"] ?? "", verifier: verifierName, redirectURL: redirectURL)
- let wrapper = SubverifierWrapper(aggregateVerifierName: config["aggregateVerifierName"], networkType: network, subverifier: details)
- verifiers[authProvider] = wrapper
-
+ guard let jsonData = jsonString?.data(using: .utf8),
+ let jsonObject = try? JSONSerialization.jsonObject(with: jsonData) as? [String: Any],
+ let verifierTypeString = jsonObject["verifierType"] as? String,
+ let verifierType = verifierTypes(rawValue: verifierTypeString),
+ let networkString = record.stringForKey("network"),
+ let network = TezosNodeClientConfig.NetworkType(rawValue: networkString),
+ let loginProviderString = jsonObject["loginProvider"] as? String,
+ let loginProvider = LoginProviders(rawValue: loginProviderString),
+ let authProviderString = jsonObject["authProvider"] as? String,
+ let authProvider = TorusAuthProvider(rawValue: authProviderString),
+ let loginTypeString = jsonObject["loginType"] as? String,
+ let loginType = SubVerifierType(rawValue: loginTypeString),
+ let clientId = jsonObject["clientId"] as? String,
+ let verifierName = jsonObject["verifierName"] as? String,
+ let redirectURL = jsonObject["redirectURL"] as? String
+ else {
+ Logger.app.error("Skipping invalid torus config item: \(record.description)")
+ continue
+ }
+
+ var subVerifier: SubVerifierDetails? = nil
+ var wrapper: SubverifierWrapper? = nil
+
+
+ // Check if we have a jwt dictionary, to decide which subVerfier to create
+ if let jwtDict = jsonObject["jwt"] as? [String: String] {
+ subVerifier = SubVerifierDetails(loginType: loginType,
+ loginProvider: loginProvider,
+ clientId: clientId,
+ verifier: verifierName,
+ redirectURL: redirectURL,
+ browserRedirectURL: jsonObject["browserRedirectURL"] as? String, // Think this is unused, just adding in case its needed in the future
+ jwtParams: jwtDict)
+ } else {
+ subVerifier = SubVerifierDetails(loginType: loginType,
+ loginProvider: loginProvider,
+ clientId: clientId,
+ verifier: verifierName,
+ redirectURL: redirectURL)
}
- // Option 2:
- // Required: loginType, loginProvider, verifierName, redirectURL
- // Optional: aggregateVerifierName, clientId, browserRedirectURL, jwtDomain
- else if let loginType = SubVerifierType(rawValue: type), let loginProvider = LoginProviders(rawValue: provider), let verifierName = config["verifierName"], let redirectURL = config["redirectURL"] {
+
+ // Check what type of login is being requested, so we can decide what to do with the required aggregate param, that might not be needed
+ if let sub = subVerifier, verifierType == .singleLogin {
+ wrapper = SubverifierWrapper(aggregateVerifierName: verifierName, verifierType: verifierType, networkType: network, subverifier: sub) // Non-aggregate
- if let jwtDomain = config["jwtDomain"] {
- let details = SubVerifierDetails(loginType: loginType,
- loginProvider: loginProvider,
- clientId: config["clientId"] ?? "",
- verifier: verifierName,
- redirectURL: redirectURL,
- browserRedirectURL: config["browserRedirectURL"],
- jwtParams: ["domain": jwtDomain])
- let wrapper = SubverifierWrapper(aggregateVerifierName: config["aggregateVerifierName"], networkType: network, subverifier: details)
- verifiers[authProvider] = wrapper
-
- } else {
- let details = SubVerifierDetails(loginType: loginType,
- loginProvider: loginProvider,
- clientId: config["clientId"] ?? "",
- verifier: verifierName,
- redirectURL: redirectURL,
- browserRedirectURL: config["browserRedirectURL"])
- let wrapper = SubverifierWrapper(aggregateVerifierName: config["aggregateVerifierName"], networkType: network, subverifier: details)
- verifiers[authProvider] = wrapper
- }
+ } else if let sub = subVerifier, let aggregateVerfifier = jsonObject["aggregateVerifierName"] as? String {
+ wrapper = SubverifierWrapper(aggregateVerifierName: aggregateVerfifier, verifierType: verifierType, networkType: network, subverifier: sub) // Aggregate
+
+ } else {
+ Logger.app.error("Skipping invalid torus config item: \(record.description)")
+ continue
}
+
+ verifiers[authProvider] = wrapper
}
return verifiers
diff --git a/Kukai Mobile/Services/TokenStateService.swift b/Kukai Mobile/Services/TokenStateService.swift
index ff727687..62e8d4f7 100644
--- a/Kukai Mobile/Services/TokenStateService.swift
+++ b/Kukai Mobile/Services/TokenStateService.swift
@@ -137,11 +137,19 @@ public class TokenStateService {
}
public func removeFavourite(forAddress address: String, token: Token) -> Bool {
- favouriteBalances[address]?.removeValue(forKey: balanceId(from: token))
+ let balanceId = balanceId(from: token)
+ let currentSortIndex = favouriteBalances[address]?[balanceId] ?? -1
+ reduceSortIndex(afterIndex: currentSortIndex, inDict: &favouriteBalances, withAddress: address)
+
+ favouriteBalances[address]?.removeValue(forKey: balanceId)
return writeFavouriteBalances()
}
public func removeFavourite(forAddress address: String, nft: NFT) -> Bool {
+ let balanceId = nftId(from: nft)
+ let currentSortIndex = favouriteCollectibles[address]?[balanceId] ?? -1
+ reduceSortIndex(afterIndex: currentSortIndex, inDict: &favouriteCollectibles, withAddress: address)
+
favouriteCollectibles[address]?.removeValue(forKey: nftId(from: nft))
return writeFavouriteCollectibles()
}
@@ -151,32 +159,35 @@ public class TokenStateService {
// MARK: Reorder
public func moveFavouriteBalance(forAddress address: String, forToken token: Token, toIndex: Int) -> Bool {
- var account = favouriteBalances[address] ?? [:]
- let tokenId = balanceId(from: token)
- account[tokenId] = toIndex
+ let balanceId = balanceId(from: token)
+ let currentSortIndex = favouriteBalances[address]?[balanceId] ?? -1
- for key in account.keys {
- if key != tokenId, (account[key] ?? 1) >= toIndex {
- account[key] = ((account[key] ?? 1) + 1)
- }
+ if currentSortIndex < toIndex {
+ // moving down, decrease others
+ reduceSortIndex(afterIndex: currentSortIndex, inDict: &favouriteBalances, withAddress: address)
+ } else {
+ // moving up, increase others
+ increaseSortIndex(beforeIndex: currentSortIndex, inDict: &favouriteBalances, withAddress: address)
}
- favouriteBalances[address] = account
+ favouriteBalances[address]?[balanceId] = toIndex
return writeFavouriteBalances()
}
public func moveFavouriteCollectible(forAddress address: String, forNft nft: NFT, toIndex: Int) -> Bool {
- var account = favouriteCollectibles[address] ?? [:]
- account[nftId(from: nft)] = toIndex
+ let balanceId = nftId(from: nft)
+ let currentSortIndex = favouriteCollectibles[address]?[balanceId] ?? -1
- for key in account.keys {
- if (account[key] ?? 1) >= toIndex {
- account[key] = ((account[key] ?? 1) + 1)
- }
+ if currentSortIndex < toIndex {
+ // moving down, decrease others
+ reduceSortIndex(afterIndex: currentSortIndex, inDict: &favouriteCollectibles, withAddress: address)
+ } else {
+ // moving up, increase others
+ increaseSortIndex(beforeIndex: currentSortIndex, inDict: &favouriteCollectibles, withAddress: address)
}
- favouriteCollectibles[address] = account
- return writeHiddenCollectibles()
+ favouriteCollectibles[address]?[balanceId] = toIndex
+ return writeFavouriteCollectibles()
}
@@ -205,6 +216,30 @@ public class TokenStateService {
return DiskService.write(encodable: favouriteCollectibles, toFileName: TokenStateService.favouriteCollectiblesFilename)
}
+ private func reduceSortIndex(afterIndex: Int, inDict dict: inout [String: [String: Int]], withAddress address: String) {
+ var tempDict: [String: Int] = (dict[address] ?? [:])
+
+ for key in tempDict.keys {
+ if let val = tempDict[key], val > afterIndex {
+ tempDict[key] = val-1
+ }
+ }
+
+ dict[address] = tempDict
+ }
+
+ private func increaseSortIndex(beforeIndex: Int, inDict dict: inout [String: [String: Int]], withAddress address: String) {
+ var tempDict: [String: Int] = (dict[address] ?? [:])
+
+ for key in tempDict.keys {
+ if let val = tempDict[key], val < beforeIndex {
+ tempDict[key] = val+1
+ }
+ }
+
+ dict[address] = tempDict
+ }
+
// MARK: Delete
diff --git a/Kukai Mobile/Services/TransactionService.swift b/Kukai Mobile/Services/TransactionService.swift
index e7f8e24c..a16cb49b 100644
--- a/Kukai Mobile/Services/TransactionService.swift
+++ b/Kukai Mobile/Services/TransactionService.swift
@@ -367,11 +367,11 @@ public class TransactionService {
case .twitter:
let image = UIImage(named: "Social_Twitter_color")?.resizedImage(size: imageSize) ?? UIImage()
- return (image: image, title: metadata.socialUsername ?? "", subtitle: metadata.address.truncateTezosAddress())
+ return (image: image, title: metadata.socialUsername ?? metadata.socialUserId ?? "", subtitle: metadata.address.truncateTezosAddress())
case .google:
let image = UIImage(named: "Social_Google_color")?.resizedImage(size: imageSize) ?? UIImage()
- return (image: image, title: metadata.socialUsername ?? "", subtitle: metadata.address.truncateTezosAddress())
+ return (image: image, title: metadata.socialUserId ?? metadata.socialUsername ?? "", subtitle: metadata.address.truncateTezosAddress())
case .reddit:
let image = UIImage(named: "Social_Reddit_Color")?.resizedImage(size: imageSize) ?? UIImage()
@@ -394,7 +394,11 @@ public class TransactionService {
return (image: image, title: metadata.socialUsername ?? "", subtitle: metadata.address.truncateTezosAddress())
case .github:
- let image = UIImage(named: "Social_Github_color")?.resizedImage(size: imageSize) ?? UIImage()
+ let image = UIImage(named: "Social_Github_Color")?.resizedImage(size: imageSize) ?? UIImage()
+ return (image: image, title: metadata.socialUsername ?? "", subtitle: metadata.address.truncateTezosAddress())
+
+ case .email:
+ let image = UIImage(named: "Social_Email_Outlined")?.resizedImage(size: imageSize) ?? UIImage()
return (image: image, title: metadata.socialUsername ?? "", subtitle: metadata.address.truncateTezosAddress())
case .none: