Implement multi device UI
This commit is contained in:
parent
079fb3f165
commit
28e3705f7e
|
@ -537,6 +537,9 @@
|
||||||
C3548F0624456447009433A8 /* PNModeVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3548F0524456447009433A8 /* PNModeVC.swift */; };
|
C3548F0624456447009433A8 /* PNModeVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3548F0524456447009433A8 /* PNModeVC.swift */; };
|
||||||
C3548F0824456AB6009433A8 /* UIView+Wrapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3548F0724456AB6009433A8 /* UIView+Wrapping.swift */; };
|
C3548F0824456AB6009433A8 /* UIView+Wrapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3548F0724456AB6009433A8 /* UIView+Wrapping.swift */; };
|
||||||
C354E75A23FE2A7600CE22E3 /* BaseVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C354E75923FE2A7600CE22E3 /* BaseVC.swift */; };
|
C354E75A23FE2A7600CE22E3 /* BaseVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C354E75923FE2A7600CE22E3 /* BaseVC.swift */; };
|
||||||
|
C35D0DA125AE582D00B6BF49 /* MultiDeviceVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C35D0DA025AE582D00B6BF49 /* MultiDeviceVC.swift */; };
|
||||||
|
C35D0DAB25AE5BDE00B6BF49 /* SettingRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = C35D0DAA25AE5BDE00B6BF49 /* SettingRow.swift */; };
|
||||||
|
C35D0DB525AE5F1200B6BF49 /* UIEdgeInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = C35D0DB425AE5F1200B6BF49 /* UIEdgeInsets.swift */; };
|
||||||
C35E8AA82485C85800ACB629 /* GeoLite2-Country-Locations-English.csv in Resources */ = {isa = PBXBuildFile; fileRef = C35E8AA52485C85400ACB629 /* GeoLite2-Country-Locations-English.csv */; };
|
C35E8AA82485C85800ACB629 /* GeoLite2-Country-Locations-English.csv in Resources */ = {isa = PBXBuildFile; fileRef = C35E8AA52485C85400ACB629 /* GeoLite2-Country-Locations-English.csv */; };
|
||||||
C35E8AA92485C85800ACB629 /* GeoLite2-Country-Blocks-IPv4.csv in Resources */ = {isa = PBXBuildFile; fileRef = C35E8AA62485C85600ACB629 /* GeoLite2-Country-Blocks-IPv4.csv */; };
|
C35E8AA92485C85800ACB629 /* GeoLite2-Country-Blocks-IPv4.csv in Resources */ = {isa = PBXBuildFile; fileRef = C35E8AA62485C85600ACB629 /* GeoLite2-Country-Blocks-IPv4.csv */; };
|
||||||
C35E8AAE2485E51D00ACB629 /* IP2Country.swift in Sources */ = {isa = PBXBuildFile; fileRef = C35E8AAD2485E51D00ACB629 /* IP2Country.swift */; };
|
C35E8AAE2485E51D00ACB629 /* IP2Country.swift in Sources */ = {isa = PBXBuildFile; fileRef = C35E8AAD2485E51D00ACB629 /* IP2Country.swift */; };
|
||||||
|
@ -1537,6 +1540,9 @@
|
||||||
C3548F0524456447009433A8 /* PNModeVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PNModeVC.swift; sourceTree = "<group>"; };
|
C3548F0524456447009433A8 /* PNModeVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PNModeVC.swift; sourceTree = "<group>"; };
|
||||||
C3548F0724456AB6009433A8 /* UIView+Wrapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Wrapping.swift"; sourceTree = "<group>"; };
|
C3548F0724456AB6009433A8 /* UIView+Wrapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Wrapping.swift"; sourceTree = "<group>"; };
|
||||||
C354E75923FE2A7600CE22E3 /* BaseVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseVC.swift; sourceTree = "<group>"; };
|
C354E75923FE2A7600CE22E3 /* BaseVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseVC.swift; sourceTree = "<group>"; };
|
||||||
|
C35D0DA025AE582D00B6BF49 /* MultiDeviceVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultiDeviceVC.swift; sourceTree = "<group>"; };
|
||||||
|
C35D0DAA25AE5BDE00B6BF49 /* SettingRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingRow.swift; sourceTree = "<group>"; };
|
||||||
|
C35D0DB425AE5F1200B6BF49 /* UIEdgeInsets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIEdgeInsets.swift; sourceTree = "<group>"; };
|
||||||
C35E8AA22485C72300ACB629 /* SwiftCSV.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftCSV.framework; path = ThirdParty/Carthage/Build/iOS/SwiftCSV.framework; sourceTree = "<group>"; };
|
C35E8AA22485C72300ACB629 /* SwiftCSV.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftCSV.framework; path = ThirdParty/Carthage/Build/iOS/SwiftCSV.framework; sourceTree = "<group>"; };
|
||||||
C35E8AA52485C85400ACB629 /* GeoLite2-Country-Locations-English.csv */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "GeoLite2-Country-Locations-English.csv"; sourceTree = "<group>"; };
|
C35E8AA52485C85400ACB629 /* GeoLite2-Country-Locations-English.csv */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "GeoLite2-Country-Locations-English.csv"; sourceTree = "<group>"; };
|
||||||
C35E8AA62485C85600ACB629 /* GeoLite2-Country-Blocks-IPv4.csv */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "GeoLite2-Country-Blocks-IPv4.csv"; sourceTree = "<group>"; };
|
C35E8AA62485C85600ACB629 /* GeoLite2-Country-Blocks-IPv4.csv */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "GeoLite2-Country-Blocks-IPv4.csv"; sourceTree = "<group>"; };
|
||||||
|
@ -2271,6 +2277,7 @@
|
||||||
C33FDB3F255A580C00E217F9 /* String+SSK.swift */,
|
C33FDB3F255A580C00E217F9 /* String+SSK.swift */,
|
||||||
C3C2AC2D2553CBEB00C340D1 /* String+Trimming.swift */,
|
C3C2AC2D2553CBEB00C340D1 /* String+Trimming.swift */,
|
||||||
C38EF237255B6D65007E1867 /* UIDevice+featureSupport.swift */,
|
C38EF237255B6D65007E1867 /* UIDevice+featureSupport.swift */,
|
||||||
|
C35D0DB425AE5F1200B6BF49 /* UIEdgeInsets.swift */,
|
||||||
C38EF23D255B6D66007E1867 /* UIView+OWS.h */,
|
C38EF23D255B6D66007E1867 /* UIView+OWS.h */,
|
||||||
C38EF23E255B6D66007E1867 /* UIView+OWS.m */,
|
C38EF23E255B6D66007E1867 /* UIView+OWS.m */,
|
||||||
C38EF2EF255B6DBB007E1867 /* Weak.swift */,
|
C38EF2EF255B6DBB007E1867 /* Weak.swift */,
|
||||||
|
@ -2319,6 +2326,7 @@
|
||||||
C31D1DE22521718E005D4DA8 /* UserSelectionVC.swift */,
|
C31D1DE22521718E005D4DA8 /* UserSelectionVC.swift */,
|
||||||
34D2CCD82062E7D000CB1A14 /* OWSScreenLockUI.h */,
|
34D2CCD82062E7D000CB1A14 /* OWSScreenLockUI.h */,
|
||||||
34D2CCD92062E7D000CB1A14 /* OWSScreenLockUI.m */,
|
34D2CCD92062E7D000CB1A14 /* OWSScreenLockUI.m */,
|
||||||
|
C35D0DAA25AE5BDE00B6BF49 /* SettingRow.swift */,
|
||||||
);
|
);
|
||||||
path = Shared;
|
path = Shared;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -2742,6 +2750,7 @@
|
||||||
B886B4A62398B23E00211ABE /* QRCodeVC.swift */,
|
B886B4A62398B23E00211ABE /* QRCodeVC.swift */,
|
||||||
B86BD08523399CEF000F5AE3 /* SeedModal.swift */,
|
B86BD08523399CEF000F5AE3 /* SeedModal.swift */,
|
||||||
B8CCF6422397711F0091D419 /* SettingsVC.swift */,
|
B8CCF6422397711F0091D419 /* SettingsVC.swift */,
|
||||||
|
C35D0DA025AE582D00B6BF49 /* MultiDeviceVC.swift */,
|
||||||
);
|
);
|
||||||
path = Settings;
|
path = Settings;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -4812,6 +4821,7 @@
|
||||||
C3D9E41F25676C870040E4F3 /* OWSPrimaryStorageProtocol.swift in Sources */,
|
C3D9E41F25676C870040E4F3 /* OWSPrimaryStorageProtocol.swift in Sources */,
|
||||||
C3BBE0A72554D4DE0050F1E3 /* Promise+Retrying.swift in Sources */,
|
C3BBE0A72554D4DE0050F1E3 /* Promise+Retrying.swift in Sources */,
|
||||||
B8856D7B256F14F4001CE70E /* UIView+OWS.m in Sources */,
|
B8856D7B256F14F4001CE70E /* UIView+OWS.m in Sources */,
|
||||||
|
C35D0DB525AE5F1200B6BF49 /* UIEdgeInsets.swift in Sources */,
|
||||||
C3D9E4F4256778AF0040E4F3 /* NSData+Image.m in Sources */,
|
C3D9E4F4256778AF0040E4F3 /* NSData+Image.m in Sources */,
|
||||||
C32C5E0C256DDAFA003C73A2 /* NSRegularExpression+SSK.swift in Sources */,
|
C32C5E0C256DDAFA003C73A2 /* NSRegularExpression+SSK.swift in Sources */,
|
||||||
C3BBE0A92554D4DE0050F1E3 /* HTTP.swift in Sources */,
|
C3BBE0A92554D4DE0050F1E3 /* HTTP.swift in Sources */,
|
||||||
|
@ -5037,6 +5047,7 @@
|
||||||
B80A579F23DFF1F300876683 /* NewClosedGroupVC.swift in Sources */,
|
B80A579F23DFF1F300876683 /* NewClosedGroupVC.swift in Sources */,
|
||||||
D221A09A169C9E5E00537ABF /* main.m in Sources */,
|
D221A09A169C9E5E00537ABF /* main.m in Sources */,
|
||||||
3496957221A301A100DCFE74 /* OWSBackup.m in Sources */,
|
3496957221A301A100DCFE74 /* OWSBackup.m in Sources */,
|
||||||
|
C35D0DA125AE582D00B6BF49 /* MultiDeviceVC.swift in Sources */,
|
||||||
B86BD08623399CEF000F5AE3 /* SeedModal.swift in Sources */,
|
B86BD08623399CEF000F5AE3 /* SeedModal.swift in Sources */,
|
||||||
34E3E5681EC4B19400495BAC /* AudioProgressView.swift in Sources */,
|
34E3E5681EC4B19400495BAC /* AudioProgressView.swift in Sources */,
|
||||||
34D1F0521F7E8EA30066283D /* GiphyDownloader.swift in Sources */,
|
34D1F0521F7E8EA30066283D /* GiphyDownloader.swift in Sources */,
|
||||||
|
@ -5045,6 +5056,7 @@
|
||||||
B82B408C239A068800A248E7 /* RegisterVC.swift in Sources */,
|
B82B408C239A068800A248E7 /* RegisterVC.swift in Sources */,
|
||||||
346129991FD1E4DA00532771 /* SignalApp.m in Sources */,
|
346129991FD1E4DA00532771 /* SignalApp.m in Sources */,
|
||||||
3496957121A301A100DCFE74 /* OWSBackupImportJob.m in Sources */,
|
3496957121A301A100DCFE74 /* OWSBackupImportJob.m in Sources */,
|
||||||
|
C35D0DAB25AE5BDE00B6BF49 /* SettingRow.swift in Sources */,
|
||||||
34BECE301F7ABCF800D7438D /* GifPickerLayout.swift in Sources */,
|
34BECE301F7ABCF800D7438D /* GifPickerLayout.swift in Sources */,
|
||||||
C331FFFE2558FF3B00070591 /* ConversationCell.swift in Sources */,
|
C331FFFE2558FF3B00070591 /* ConversationCell.swift in Sources */,
|
||||||
C3DFFAC623E96F0D0058DAF8 /* Sheet.swift in Sources */,
|
C3DFFAC623E96F0D0058DAF8 /* Sheet.swift in Sources */,
|
||||||
|
|
|
@ -0,0 +1,161 @@
|
||||||
|
|
||||||
|
final class MultiDeviceVC : BaseVC {
|
||||||
|
|
||||||
|
private let mnemonic: String = {
|
||||||
|
let collection = OWSPrimaryStorageIdentityKeyStoreCollection
|
||||||
|
let hexEncodedSeed: String! = OWSIdentityManager.shared().dbConnection.object(forKey: "LKLokiSeed", inCollection: collection) as! String?
|
||||||
|
return Mnemonic.encode(hexEncodedString: hexEncodedSeed)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// MARK: UI Components
|
||||||
|
private lazy var toggleLabel: UILabel = {
|
||||||
|
let result = UILabel()
|
||||||
|
result.textColor = Colors.text
|
||||||
|
result.font = .systemFont(ofSize: Values.mediumFontSize)
|
||||||
|
result.text = "Enable multi device"
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var toggle: UISwitch = {
|
||||||
|
let result = UISwitch()
|
||||||
|
result.onTintColor = Colors.accent
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var stepsRow: SettingRow = {
|
||||||
|
let result = SettingRow(autoSize: true)
|
||||||
|
result.isHidden = true
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var stepsLabel1: UILabel = {
|
||||||
|
let result = UILabel()
|
||||||
|
result.textColor = Colors.text
|
||||||
|
result.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
|
result.text = """
|
||||||
|
1. Clear your other device if it currently has an account on it (Settings > Clear Data).
|
||||||
|
|
||||||
|
2. On the landing page, click "Continue your Session".
|
||||||
|
|
||||||
|
3. Enter the following words when prompted:
|
||||||
|
"""
|
||||||
|
result.numberOfLines = 0
|
||||||
|
result.lineBreakMode = .byWordWrapping
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var mnemonicLabel: UILabel = {
|
||||||
|
let result = UILabel()
|
||||||
|
result.textColor = Colors.text
|
||||||
|
result.font = Fonts.spaceMono(ofSize: Values.smallFontSize)
|
||||||
|
result.text = mnemonic
|
||||||
|
result.numberOfLines = 0
|
||||||
|
result.lineBreakMode = .byWordWrapping
|
||||||
|
result.textAlignment = .center
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var copyButton: Button = {
|
||||||
|
let result = Button(style: .prominentOutline, size: .medium)
|
||||||
|
result.setTitle(NSLocalizedString("copy", comment: ""), for: UIControl.State.normal)
|
||||||
|
result.addTarget(self, action: #selector(copyMnemonic), for: UIControl.Event.touchUpInside)
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var stepsLabel2: UILabel = {
|
||||||
|
let result = UILabel()
|
||||||
|
result.textColor = Colors.text
|
||||||
|
result.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
|
result.text = """
|
||||||
|
4. Enter your display name.
|
||||||
|
|
||||||
|
5. That's it!
|
||||||
|
"""
|
||||||
|
result.numberOfLines = 0
|
||||||
|
result.lineBreakMode = .byWordWrapping
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
// MARK: Initialization
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
setUpUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setUpUI() {
|
||||||
|
setUpGradientBackground()
|
||||||
|
setUpNavBarStyle()
|
||||||
|
setNavBarTitle("Multi Device (Beta)")
|
||||||
|
// Back button
|
||||||
|
let backButton = UIBarButtonItem(title: "Back", style: .plain, target: nil, action: nil)
|
||||||
|
backButton.tintColor = Colors.text
|
||||||
|
navigationItem.backBarButtonItem = backButton
|
||||||
|
// Toggle
|
||||||
|
toggle.addTarget(self, action: #selector(handleToggle), for: UIControl.Event.valueChanged)
|
||||||
|
let toggleStackView = UIStackView(arrangedSubviews: [ toggleLabel, toggle ])
|
||||||
|
toggleStackView.axis = .horizontal
|
||||||
|
toggleStackView.spacing = Values.mediumSpacing
|
||||||
|
toggleStackView.alignment = .center
|
||||||
|
let toggleRow = SettingRow()
|
||||||
|
toggleRow.contentView.addSubview(toggleStackView)
|
||||||
|
toggleStackView.pin(to: toggleRow.contentView, withInset: Values.mediumSpacing)
|
||||||
|
// Steps
|
||||||
|
let mnemonicLabelContainer = UIView()
|
||||||
|
mnemonicLabelContainer.addSubview(mnemonicLabel)
|
||||||
|
mnemonicLabel.pin(to: mnemonicLabelContainer, withInset: isIPhone6OrSmaller ? 4 : Values.smallSpacing)
|
||||||
|
mnemonicLabelContainer.layer.cornerRadius = Values.textFieldCornerRadius
|
||||||
|
mnemonicLabelContainer.layer.borderWidth = Values.borderThickness
|
||||||
|
mnemonicLabelContainer.layer.borderColor = Colors.text.cgColor
|
||||||
|
let stepsLabel1Container = UIView()
|
||||||
|
stepsLabel1Container.addSubview(stepsLabel1)
|
||||||
|
stepsLabel1.pin(.leading, to: .leading, of: stepsLabel1Container, withInset: Values.smallSpacing)
|
||||||
|
stepsLabel1Container.pin(.trailing, to: .trailing, of: stepsLabel1, withInset: Values.smallSpacing)
|
||||||
|
stepsLabel1.pin([ UIView.VerticalEdge.top, UIView.VerticalEdge.bottom ], to: stepsLabel1Container)
|
||||||
|
let stepsLabel2Container = UIView()
|
||||||
|
stepsLabel2Container.addSubview(stepsLabel2)
|
||||||
|
stepsLabel2.pin(.leading, to: .leading, of: stepsLabel2Container, withInset: Values.smallSpacing)
|
||||||
|
stepsLabel2Container.pin(.trailing, to: .trailing, of: stepsLabel2, withInset: Values.smallSpacing)
|
||||||
|
stepsLabel2.pin([ UIView.VerticalEdge.top, UIView.VerticalEdge.bottom ], to: stepsLabel2Container)
|
||||||
|
let stepsStackView = UIStackView(arrangedSubviews: [ stepsLabel1Container, mnemonicLabelContainer, copyButton, stepsLabel2Container ])
|
||||||
|
stepsStackView.axis = .vertical
|
||||||
|
stepsStackView.spacing = Values.mediumSpacing
|
||||||
|
stepsRow.contentView.addSubview(stepsStackView)
|
||||||
|
stepsStackView.pin(to: stepsRow.contentView, withInset: Values.mediumSpacing)
|
||||||
|
// Main stack view
|
||||||
|
let mainStackView = UIStackView(arrangedSubviews: [ toggleRow, stepsRow ])
|
||||||
|
mainStackView.axis = .vertical
|
||||||
|
mainStackView.spacing = Values.mediumSpacing
|
||||||
|
mainStackView.isLayoutMarginsRelativeArrangement = true
|
||||||
|
mainStackView.layoutMargins = UIEdgeInsets(uniform: Values.mediumSpacing)
|
||||||
|
mainStackView.set(.width, to: UIScreen.main.bounds.width)
|
||||||
|
// Scroll view
|
||||||
|
let scrollView = UIScrollView()
|
||||||
|
scrollView.showsVerticalScrollIndicator = false
|
||||||
|
scrollView.addSubview(mainStackView)
|
||||||
|
mainStackView.pin(to: scrollView)
|
||||||
|
view.addSubview(scrollView)
|
||||||
|
scrollView.pin(to: view)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Updating
|
||||||
|
@objc private func enableCopyButton() {
|
||||||
|
copyButton.isUserInteractionEnabled = true
|
||||||
|
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
||||||
|
self.copyButton.setTitle(NSLocalizedString("copy", comment: ""), for: UIControl.State.normal)
|
||||||
|
}, completion: nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Interaction
|
||||||
|
@objc private func handleToggle() {
|
||||||
|
stepsRow.isHidden = !toggle.isOn
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func copyMnemonic() {
|
||||||
|
UIPasteboard.general.string = mnemonic
|
||||||
|
copyButton.isUserInteractionEnabled = false
|
||||||
|
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
||||||
|
self.copyButton.setTitle("Copied", for: UIControl.State.normal)
|
||||||
|
}, completion: nil)
|
||||||
|
Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(enableCopyButton), userInfo: nil, repeats: false)
|
||||||
|
}
|
||||||
|
}
|
|
@ -59,16 +59,8 @@ final class SeedModal : Modal {
|
||||||
buttonStackView.axis = .horizontal
|
buttonStackView.axis = .horizontal
|
||||||
buttonStackView.spacing = Values.mediumSpacing
|
buttonStackView.spacing = Values.mediumSpacing
|
||||||
buttonStackView.distribution = .fillEqually
|
buttonStackView.distribution = .fillEqually
|
||||||
// Set up explanation label
|
|
||||||
let disclaimerLabel = UILabel()
|
|
||||||
disclaimerLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
|
|
||||||
disclaimerLabel.font = .systemFont(ofSize: 10)
|
|
||||||
disclaimerLabel.text = "It is not possible to use the same Session ID on multiple devices simultaneously"
|
|
||||||
disclaimerLabel.numberOfLines = 0
|
|
||||||
disclaimerLabel.lineBreakMode = .byWordWrapping
|
|
||||||
disclaimerLabel.textAlignment = .center
|
|
||||||
// Set up stack view
|
// Set up stack view
|
||||||
let stackView = UIStackView(arrangedSubviews: [ titleLabel, mnemonicLabelContainer, explanationLabel, buttonStackView, disclaimerLabel ])
|
let stackView = UIStackView(arrangedSubviews: [ titleLabel, mnemonicLabelContainer, explanationLabel, buttonStackView ])
|
||||||
stackView.axis = .vertical
|
stackView.axis = .vertical
|
||||||
stackView.spacing = Values.largeSpacing
|
stackView.spacing = Values.largeSpacing
|
||||||
contentView.addSubview(stackView)
|
contentView.addSubview(stackView)
|
||||||
|
|
|
@ -181,6 +181,8 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
|
||||||
getSeparator(),
|
getSeparator(),
|
||||||
getSettingButton(withTitle: NSLocalizedString("vc_settings_notifications_button_title", comment: ""), color: Colors.text, action: #selector(showNotificationSettings)),
|
getSettingButton(withTitle: NSLocalizedString("vc_settings_notifications_button_title", comment: ""), color: Colors.text, action: #selector(showNotificationSettings)),
|
||||||
getSeparator(),
|
getSeparator(),
|
||||||
|
getSettingButton(withTitle: "Multi Device (Beta)", color: Colors.text, action: #selector(showMultiDeviceOptions)),
|
||||||
|
getSeparator(),
|
||||||
getSettingButton(withTitle: "Invite", color: Colors.text, action: #selector(sendInvitation)),
|
getSettingButton(withTitle: "Invite", color: Colors.text, action: #selector(sendInvitation)),
|
||||||
getSeparator()
|
getSeparator()
|
||||||
]
|
]
|
||||||
|
@ -405,6 +407,11 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
|
||||||
navigationController!.pushViewController(notificationSettingsVC, animated: true)
|
navigationController!.pushViewController(notificationSettingsVC, animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc private func showMultiDeviceOptions() {
|
||||||
|
let multiDeviceVC = MultiDeviceVC()
|
||||||
|
navigationController!.pushViewController(multiDeviceVC, animated: true)
|
||||||
|
}
|
||||||
|
|
||||||
@objc private func sendInvitation() {
|
@objc private func sendInvitation() {
|
||||||
let invitation = "Hey, I've been using Session to chat with complete privacy and security. Come join me! Download it at https://getsession.org/. My Session ID is \(getUserHexEncodedPublicKey())!"
|
let invitation = "Hey, I've been using Session to chat with complete privacy and security. Come join me! Download it at https://getsession.org/. My Session ID is \(getUserHexEncodedPublicKey())!"
|
||||||
let shareVC = UIActivityViewController(activityItems: [ invitation ], applicationActivities: nil)
|
let shareVC = UIActivityViewController(activityItems: [ invitation ], applicationActivities: nil)
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
|
||||||
|
final class SettingRow : UIView {
|
||||||
|
private let autoSize: Bool
|
||||||
|
|
||||||
|
lazy var contentView: UIView = {
|
||||||
|
let result = UIView()
|
||||||
|
result.backgroundColor = Colors.buttonBackground
|
||||||
|
result.layer.cornerRadius = 8
|
||||||
|
result.layer.masksToBounds = true
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
init(autoSize: Bool) {
|
||||||
|
self.autoSize = autoSize
|
||||||
|
super.init(frame: CGRect.zero)
|
||||||
|
setUpUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
autoSize = false
|
||||||
|
super.init(frame: frame)
|
||||||
|
setUpUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
autoSize = false
|
||||||
|
super.init(coder: coder)
|
||||||
|
setUpUI()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setUpUI() {
|
||||||
|
// Height
|
||||||
|
if !autoSize {
|
||||||
|
let height = Values.defaultSettingRowHeight
|
||||||
|
set(.height, to: height)
|
||||||
|
}
|
||||||
|
// Shadow
|
||||||
|
layer.shadowColor = UIColor.black.cgColor
|
||||||
|
layer.shadowOffset = CGSize.zero
|
||||||
|
layer.shadowOpacity = 0.4
|
||||||
|
layer.shadowRadius = 4
|
||||||
|
// Content view
|
||||||
|
addSubview(contentView)
|
||||||
|
contentView.pin(to: self)
|
||||||
|
}
|
||||||
|
|
||||||
|
override func layoutSubviews() {
|
||||||
|
super.layoutSubviews()
|
||||||
|
layer.shadowPath = UIBezierPath(roundedRect: bounds, cornerRadius: 8).cgPath
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,6 +39,7 @@ public final class Values : NSObject {
|
||||||
@objc public static var separatorThickness: CGFloat { return 1 / UIScreen.main.scale }
|
@objc public static var separatorThickness: CGFloat { return 1 / UIScreen.main.scale }
|
||||||
@objc public static let tabBarHeight = isIPhone5OrSmaller ? CGFloat(32) : CGFloat(48)
|
@objc public static let tabBarHeight = isIPhone5OrSmaller ? CGFloat(32) : CGFloat(48)
|
||||||
@objc public static let settingButtonHeight = isIPhone5OrSmaller ? CGFloat(52) : CGFloat(75)
|
@objc public static let settingButtonHeight = isIPhone5OrSmaller ? CGFloat(52) : CGFloat(75)
|
||||||
|
@objc public static let defaultSettingRowHeight = CGFloat(60)
|
||||||
@objc public static let modalCornerRadius = CGFloat(10)
|
@objc public static let modalCornerRadius = CGFloat(10)
|
||||||
@objc public static let modalButtonCornerRadius = CGFloat(5)
|
@objc public static let modalButtonCornerRadius = CGFloat(5)
|
||||||
@objc public static let fakeChatBubbleWidth = CGFloat(224)
|
@objc public static let fakeChatBubbleWidth = CGFloat(224)
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension UIEdgeInsets {
|
||||||
|
|
||||||
|
public init(uniform value: CGFloat) {
|
||||||
|
self.init(top: value, left: value, bottom: value, right: value)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue