Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/stranger transfer hint #811

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions Mixin.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,8 @@
7BFE47E52284530200FC4379 /* PeerHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BFE47E42284530200FC4379 /* PeerHeaderView.swift */; };
7BFE47E722845DE100FC4379 /* MessageReceiver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BFE47E622845DE100FC4379 /* MessageReceiver.swift */; };
7C0D997F26CA62CD00356655 /* StaticAudioMessagePlayingManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C0D997E26CA62CD00356655 /* StaticAudioMessagePlayingManager.swift */; };
7C0E16A127016301002FC718 /* StrangerTransferHintWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C0E16A027016301002FC718 /* StrangerTransferHintWindow.swift */; };
7C0E16A3270163EB002FC718 /* StrangerTransferHintWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7C0E16A2270163EB002FC718 /* StrangerTransferHintWindow.xib */; };
7C14CFC126CA35CF0094AF4A /* StaticMessagesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C14CFBF26CA35CF0094AF4A /* StaticMessagesViewController.swift */; };
7C14CFC226CA35CF0094AF4A /* StaticMessagesView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7C14CFC026CA35CF0094AF4A /* StaticMessagesView.xib */; };
7C5823D5268966A1003AA142 /* HomeAppsFolderViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C5823D4268966A1003AA142 /* HomeAppsFolderViewController.swift */; };
Expand Down Expand Up @@ -1538,6 +1540,8 @@
7BFE47E42284530200FC4379 /* PeerHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeerHeaderView.swift; sourceTree = "<group>"; };
7BFE47E622845DE100FC4379 /* MessageReceiver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageReceiver.swift; sourceTree = "<group>"; };
7C0D997E26CA62CD00356655 /* StaticAudioMessagePlayingManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticAudioMessagePlayingManager.swift; sourceTree = "<group>"; };
7C0E16A027016301002FC718 /* StrangerTransferHintWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StrangerTransferHintWindow.swift; sourceTree = "<group>"; };
7C0E16A2270163EB002FC718 /* StrangerTransferHintWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = StrangerTransferHintWindow.xib; sourceTree = "<group>"; };
7C14CFBF26CA35CF0094AF4A /* StaticMessagesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticMessagesViewController.swift; sourceTree = "<group>"; };
7C14CFC026CA35CF0094AF4A /* StaticMessagesView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = StaticMessagesView.xib; sourceTree = "<group>"; };
7C5823D4268966A1003AA142 /* HomeAppsFolderViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeAppsFolderViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2819,6 +2823,8 @@
DFDD89E822C4B8E600128991 /* DepositTipWindow.xib */,
DF846CD823694A2E00AA1197 /* MultisigUsersWindow.swift */,
DF846CDA23694A4900AA1197 /* MultisigUsersWindow.xib */,
7C0E16A027016301002FC718 /* StrangerTransferHintWindow.swift */,
7C0E16A2270163EB002FC718 /* StrangerTransferHintWindow.xib */,
);
path = Windows;
sourceTree = "<group>";
Expand Down Expand Up @@ -3814,6 +3820,7 @@
7BF19C20241D40FA00B192D5 /* LocationSearchView.xib in Resources */,
7B8BB590234F36C000991ACB /* Colors.xcassets in Resources */,
94B8D18A266E41D300F43CBB /* DatabaseDiagnosticView.xib in Resources */,
7C0E16A3270163EB002FC718 /* StrangerTransferHintWindow.xib in Resources */,
7BFCB7762419FC5B00E7BC43 /* LocationCell.xib in Resources */,
DFD294491FA7145F00FADAAD /* Contact.storyboard in Resources */,
94E8913925C019F000F1E5D4 /* Pods-Mixin-acknowledgements.plist in Resources */,
Expand Down Expand Up @@ -4056,7 +4063,7 @@
outputFileListPaths = (
);
outputPaths = (
"$SRCROOT/MixinNotificationService/R.generated.swift",
$SRCROOT/MixinNotificationService/R.generated.swift,
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
Expand Down Expand Up @@ -4153,7 +4160,7 @@
outputFileListPaths = (
);
outputPaths = (
"$SRCROOT/MixinShare/R.generated.swift",
$SRCROOT/MixinShare/R.generated.swift,
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
Expand All @@ -4173,7 +4180,7 @@
outputFileListPaths = (
);
outputPaths = (
"$SRCROOT/R.generated.swift",
$SRCROOT/R.generated.swift,
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
Expand Down Expand Up @@ -4702,6 +4709,7 @@
7BB5250324160F3D0060DAE1 /* LocationPreviewViewController.swift in Sources */,
7BDEE5C71FA72EB9004CB189 /* SearchViewController.swift in Sources */,
7BF4047B2048F008004C54E4 /* VerifyPinNavigationController.swift in Sources */,
7C0E16A127016301002FC718 /* StrangerTransferHintWindow.swift in Sources */,
DF2A245E1FCC5D15003A8C1E /* GroupAddMemberCell.swift in Sources */,
DFB6CE1E23C4805B00FB6615 /* KeychainExtension.swift in Sources */,
7B2E3E5A1FA0816D00DDDDEB /* LoginContinueButton.swift in Sources */,
Expand Down
3 changes: 3 additions & 0 deletions Mixin/Resources/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@
"wallet_face_id" = "Face ID";
"wallet_header_recent_searches" = "Recent searches";
"wallet_header_trending" = "Trending";
"wallet_transfer_stranger_hint" = "Mixin ID %@ is not in your contacts, please check if the payee is correct. If you transfer to the wrong person, assets will not be recovered!";

// Transaction
"transaction_title" = "Transaction";
Expand Down Expand Up @@ -838,6 +839,8 @@
"setting_transfer_large_summary" = "Display confirmation dialog when transfer greater than or equal to %@.";
"setting_duplicate_transfer_title" = "Duplicate Transfer Confirmation";
"setting_duplicate_transfer_summary" = "Display confirmation dialog when you transfer the same amount to the same person within 6 hours.";
"setting_stranger_transfer_title" = "Stranger Transfer Confirmation";
"setting_stranger_transfer_summary" = "Display confirmation dialog when you transfer to a stranger";
"setting_backup_title" = "Chat Backup";
"setting_backup_now" = "Back Up Now";
"setting_backing" = "Backing Up...";
Expand Down
3 changes: 3 additions & 0 deletions Mixin/Resources/zh-Hans.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,7 @@
"wallet_store_encrypted_pin_tip" = "启用%@支付?";
"wallet_touch_id" = "指纹";
"wallet_face_id" = "面容";
"wallet_transfer_stranger_hint" = "Mixin ID %@ 不是你的联系人,请确认收款人是否正确。如果您转错人,资产将无法追回!";

// Transaction
"transaction_title" = "交易详情";
Expand Down Expand Up @@ -839,6 +840,8 @@
"setting_transfer_large_summary" = "当转账金额大于或等于 %@ 时显示确认弹窗";
"setting_duplicate_transfer_title" = "重复转账确认";
"setting_duplicate_transfer_summary" = "当你在 6 个小时内给相同的人转相同的金额时显示确认弹窗";
"setting_stranger_transfer_title" = "陌生人转账确认";
"setting_stranger_transfer_summary" = "当你给陌生人转账时显示确认弹窗";
"setting_backup_title" = "聊天记录备份";
"setting_backup_now" = "立即备份";
"setting_backing" = "正在备份...";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class KeyboardBasedLayoutViewController: UIViewController {
layout(for: frame)
} else {
UIView.performWithoutAnimation {
view.layoutIfNeeded()
layout(for: frame)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ class NotificationAndConfirmationSettingsViewController: SettingsTableViewContro
accessory: .switch(isOn: showsMessagePreview))
private lazy var duplicateTransferRow = SettingsRow(title: R.string.localizable.setting_duplicate_transfer_title(),
accessory: .switch(isOn: duplicateTransferConfirmation))
private lazy var strangerTransferRow = SettingsRow(title: R.string.localizable.setting_stranger_transfer_title(),
accessory: .switch(isOn: strangerTransferConfirmation))

private lazy var dataSource = SettingsDataSource(sections: [
SettingsSection(footer: R.string.localizable.setting_notification_message_preview_description(), rows: [
Expand All @@ -16,6 +18,9 @@ class NotificationAndConfirmationSettingsViewController: SettingsTableViewContro
makeTransferConfirmationThresholdSection(),
SettingsSection(footer: R.string.localizable.setting_duplicate_transfer_summary(), rows: [
duplicateTransferRow
]),
SettingsSection(footer: R.string.localizable.setting_stranger_transfer_summary(), rows: [
strangerTransferRow
])
])

Expand All @@ -33,6 +38,10 @@ class NotificationAndConfirmationSettingsViewController: SettingsTableViewContro
AppGroupUserDefaults.User.duplicateTransferConfirmation
}

private var strangerTransferConfirmation: Bool {
AppGroupUserDefaults.User.strangerTransferConfirmation
}

private var transferNotificationThreshold: String {
let threshold = LoginManager.shared.account?.transfer_notification_threshold ?? 0
return NumberFormatter.localizedString(from: NSNumber(value: threshold), number: .decimal)
Expand Down Expand Up @@ -69,6 +78,8 @@ class NotificationAndConfirmationSettingsViewController: SettingsTableViewContro
AppGroupUserDefaults.User.showMessagePreviewInNotification = isOn
} else if row == duplicateTransferRow {
AppGroupUserDefaults.User.duplicateTransferConfirmation = isOn
} else if row == strangerTransferRow {
AppGroupUserDefaults.User.strangerTransferConfirmation = isOn
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class TransferOutViewController: KeyboardBasedLayoutViewController {
private var chainAsset: AssetItem?
private var isInputAssetAmount = true
private var adjustBottomConstraintWhenKeyboardFrameChanges = true
private var ignoreStrangerTransferConfirmation = true

private weak var payWindowIfLoaded: PayWindow?

Expand Down Expand Up @@ -210,25 +211,41 @@ class TransferOutViewController: KeyboardBasedLayoutViewController {

switch opponent! {
case .contact(let user):
DispatchQueue.global().async { [weak self] in
let action: PayWindow.PinAction = .transfer(trackId: traceId, user: user, fromWeb: false)
PayWindow.checkPay(traceId: traceId, asset: asset, action: action, opponentId: user.userId, amount: amount, fiatMoneyAmount: fiatMoneyAmount, memo: memo, fromWeb: false) { (canPay, errorMsg) in
DispatchQueue.main.async {
guard let weakSelf = self else {
return
}
weakSelf.continueButton.isBusy = false
if canPay {
payWindow.render(asset: asset, action: action, amount: amount, memo: memo, fiatMoneyAmount: fiatMoneyAmount, textfield: weakSelf.amountTextField).presentPopupControllerAnimated()
} else {
weakSelf.amountTextField.becomeFirstResponder()
if let error = errorMsg {
showAutoHiddenHud(style: .error, text: error)
let checkPay = {
DispatchQueue.global().async { [weak self] in
let action: PayWindow.PinAction = .transfer(trackId: traceId, user: user, fromWeb: false)
PayWindow.checkPay(traceId: traceId, asset: asset, action: action, opponentId: user.userId, amount: amount, fiatMoneyAmount: fiatMoneyAmount, memo: memo, fromWeb: false) { (canPay, errorMsg) in
DispatchQueue.main.async {
guard let weakSelf = self else {
return
}
weakSelf.continueButton.isBusy = false
if canPay {
payWindow.render(asset: asset, action: action, amount: amount, memo: memo, fiatMoneyAmount: fiatMoneyAmount, textfield: weakSelf.amountTextField).presentPopupControllerAnimated()
} else {
weakSelf.amountTextField.becomeFirstResponder()
if let error = errorMsg {
showAutoHiddenHud(style: .error, text: error)
}
}
}
}
}
}
let isStranger = user.relationship == Relationship.STRANGER.rawValue
let strangerTransferConfirmation = AppGroupUserDefaults.User.strangerTransferConfirmation
let transferOverTenDollars = asset.priceUsd.doubleValue * amount.doubleValue >= 10
if !ignoreStrangerTransferConfirmation && isStranger && strangerTransferConfirmation && transferOverTenDollars {
let window = StrangerTransferHintWindow.instance(userItem: user)
window.onContinue = checkPay
window.onCancel = {
self.continueButton.isBusy = false
self.amountTextField.becomeFirstResponder()
}
window.presentPopupControllerAnimated()
} else {
checkPay()
}
case .address(let address):
DispatchQueue.global().async { [weak self] in
guard let chainAsset = chainAsset ?? AssetDAO.shared.getAsset(assetId: asset.chainId) else {
Expand Down Expand Up @@ -411,10 +428,11 @@ class TransferOutViewController: KeyboardBasedLayoutViewController {
amountTextField.reloadInputViews()
}

class func instance(asset: AssetItem?, type: Opponent) -> UIViewController {
class func instance(asset: AssetItem?, type: Opponent, ignoreStrangerTransferConfirmation: Bool = false) -> UIViewController {
let vc = R.storyboard.wallet.send()!
vc.opponent = type
vc.asset = asset
vc.ignoreStrangerTransferConfirmation = ignoreStrangerTransferConfirmation
let container = ContainerViewController.instance(viewController: vc, title: "")
return container
}
Expand Down
44 changes: 44 additions & 0 deletions Mixin/UserInterface/Windows/StrangerTransferHintWindow.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import UIKit
import MixinServices

final class StrangerTransferHintWindow: BottomSheetView {

@IBOutlet weak var avatarImageView: AvatarImageView!
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var idLabel: UILabel!
@IBOutlet weak var hintLabel: LineHeightLabel!

var onContinue: (() -> Void)?
var onCancel: (() -> Void)?

private var canDismiss = false

override func dismissPopupControllerAnimated() {
guard canDismiss else {
return
}
super.dismissPopupControllerAnimated()
}

class func instance(userItem: UserItem) -> StrangerTransferHintWindow {
let window = R.nib.strangerTransferHintWindow(owner: self)!
window.avatarImageView.setImage(with: userItem)
window.nameLabel.text = userItem.fullName
window.idLabel.text = R.string.localizable.contact_identity_number(userItem.identityNumber)
window.hintLabel.text = R.string.localizable.wallet_transfer_stranger_hint(userItem.identityNumber)
return window
}

@IBAction func continueAction(_ sender: Any) {
canDismiss = true
onContinue?()
dismissPopupControllerAnimated()
}

@IBAction func cancelAction(_ sender: Any) {
canDismiss = true
onCancel?()
dismissPopupControllerAnimated()
}

}
Loading