Make string naming scheme (almost) match Android
This way we can drop in existing Android translations
This commit is contained in:
parent
11d4add8f9
commit
cfade8b0b8
|
@ -212,7 +212,7 @@ final class ConversationCell : UITableViewCell {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if threadViewModel.threadRecord.isNoteToSelf() {
|
if threadViewModel.threadRecord.isNoteToSelf() {
|
||||||
return NSLocalizedString("Note to Self", comment: "")
|
return NSLocalizedString("NOTE_TO_SELF", comment: "")
|
||||||
} else {
|
} else {
|
||||||
let hexEncodedPublicKey = threadViewModel.contactIdentifier!
|
let hexEncodedPublicKey = threadViewModel.contactIdentifier!
|
||||||
return UserDisplayNameUtilities.getPrivateChatDisplayName(for: hexEncodedPublicKey) ?? hexEncodedPublicKey
|
return UserDisplayNameUtilities.getPrivateChatDisplayName(for: hexEncodedPublicKey) ?? hexEncodedPublicKey
|
||||||
|
|
|
@ -8,11 +8,11 @@ final class FakeChatView : UIView {
|
||||||
}
|
}
|
||||||
|
|
||||||
private lazy var chatBubbles = [
|
private lazy var chatBubbles = [
|
||||||
getChatBubble(withText: NSLocalizedString("What's Session?", comment: ""), wasSentByCurrentUser: true),
|
getChatBubble(withText: NSLocalizedString("view_fake_chat_bubble_1", comment: ""), wasSentByCurrentUser: true),
|
||||||
getChatBubble(withText: NSLocalizedString("It's a decentralized, encrypted messaging app.", comment: ""), wasSentByCurrentUser: false),
|
getChatBubble(withText: NSLocalizedString("view_fake_chat_bubble_2", comment: ""), wasSentByCurrentUser: false),
|
||||||
getChatBubble(withText: NSLocalizedString("So it doesn't collect my personal information or my conversation metadata? How does it work?", comment: ""), wasSentByCurrentUser: true),
|
getChatBubble(withText: NSLocalizedString("view_fake_chat_bubble_3", comment: ""), wasSentByCurrentUser: true),
|
||||||
getChatBubble(withText: NSLocalizedString("Using a combination of advanced anonymous routing and end-to-end encryption technologies.", comment: ""), wasSentByCurrentUser: false),
|
getChatBubble(withText: NSLocalizedString("view_fake_chat_bubble_4", comment: ""), wasSentByCurrentUser: false),
|
||||||
getChatBubble(withText: NSLocalizedString("Friends don't let friends use compromised messengers. You're welcome.", comment: ""), wasSentByCurrentUser: false)
|
getChatBubble(withText: NSLocalizedString("view_fake_chat_bubble_5", comment: ""), wasSentByCurrentUser: false)
|
||||||
]
|
]
|
||||||
|
|
||||||
private lazy var scrollView: UIScrollView = {
|
private lazy var scrollView: UIScrollView = {
|
||||||
|
|
|
@ -64,7 +64,7 @@ final class OptionView : UIView {
|
||||||
let recommendedLabel = UILabel()
|
let recommendedLabel = UILabel()
|
||||||
recommendedLabel.textColor = Colors.accent
|
recommendedLabel.textColor = Colors.accent
|
||||||
recommendedLabel.font = .boldSystemFont(ofSize: Values.verySmallFontSize)
|
recommendedLabel.font = .boldSystemFont(ofSize: Values.verySmallFontSize)
|
||||||
recommendedLabel.text = NSLocalizedString("Recommended", comment: "")
|
recommendedLabel.text = NSLocalizedString("vc_pn_mode_recommended_option_tag", comment: "")
|
||||||
stackView.addArrangedSubview(recommendedLabel)
|
stackView.addArrangedSubview(recommendedLabel)
|
||||||
}
|
}
|
||||||
// Set up tap gesture recognizer
|
// Set up tap gesture recognizer
|
||||||
|
|
|
@ -56,7 +56,7 @@ final class SeedReminderView : UIView {
|
||||||
labelStackView.spacing = 4
|
labelStackView.spacing = 4
|
||||||
// Set up button
|
// Set up button
|
||||||
let button = Button(style: .prominentOutline, size: .small)
|
let button = Button(style: .prominentOutline, size: .small)
|
||||||
button.setTitle(NSLocalizedString("Continue", comment: ""), for: UIControl.State.normal)
|
button.setTitle(NSLocalizedString("continue_2", comment: ""), for: UIControl.State.normal)
|
||||||
button.set(.width, to: 80)
|
button.set(.width, to: 80)
|
||||||
button.addTarget(self, action: #selector(handleContinueButtonTapped), for: UIControl.Event.touchUpInside)
|
button.addTarget(self, action: #selector(handleContinueButtonTapped), for: UIControl.Event.touchUpInside)
|
||||||
// Set up content stack view
|
// Set up content stack view
|
||||||
|
|
|
@ -29,7 +29,7 @@ final class SessionRestorationView : UIView {
|
||||||
let titleLabel = UILabel()
|
let titleLabel = UILabel()
|
||||||
titleLabel.textColor = Colors.text
|
titleLabel.textColor = Colors.text
|
||||||
titleLabel.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
titleLabel.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
||||||
titleLabel.text = NSLocalizedString("Session Out of Sync", comment: "")
|
titleLabel.text = "Session Out of Sync"
|
||||||
titleLabel.numberOfLines = 0
|
titleLabel.numberOfLines = 0
|
||||||
titleLabel.lineBreakMode = .byWordWrapping
|
titleLabel.lineBreakMode = .byWordWrapping
|
||||||
titleLabel.textAlignment = .center
|
titleLabel.textAlignment = .center
|
||||||
|
@ -37,7 +37,7 @@ final class SessionRestorationView : UIView {
|
||||||
let explanationLabel = UILabel()
|
let explanationLabel = UILabel()
|
||||||
explanationLabel.textColor = Colors.text
|
explanationLabel.textColor = Colors.text
|
||||||
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
explanationLabel.text = NSLocalizedString("Would you like to restore your session? This can help resolve issues. Your messages will be preserved.", comment: "")
|
explanationLabel.text = "Would you like to restore your session? This can help resolve issues. Your messages will be preserved."
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.textAlignment = .center
|
explanationLabel.textAlignment = .center
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
|
@ -48,7 +48,7 @@ final class SessionRestorationView : UIView {
|
||||||
restoreButton.backgroundColor = Colors.accent
|
restoreButton.backgroundColor = Colors.accent
|
||||||
restoreButton.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
|
restoreButton.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
restoreButton.setTitleColor(Colors.text, for: UIControl.State.normal)
|
restoreButton.setTitleColor(Colors.text, for: UIControl.State.normal)
|
||||||
restoreButton.setTitle(NSLocalizedString("Restore", comment: ""), for: UIControl.State.normal)
|
restoreButton.setTitle(NSLocalizedString("session_reset_banner_restore_button_title", comment: ""), for: UIControl.State.normal)
|
||||||
restoreButton.addTarget(self, action: #selector(restore), for: UIControl.Event.touchUpInside)
|
restoreButton.addTarget(self, action: #selector(restore), for: UIControl.Event.touchUpInside)
|
||||||
// Set up dismiss button
|
// Set up dismiss button
|
||||||
let dismissButton = UIButton()
|
let dismissButton = UIButton()
|
||||||
|
@ -57,7 +57,7 @@ final class SessionRestorationView : UIView {
|
||||||
dismissButton.backgroundColor = Colors.buttonBackground
|
dismissButton.backgroundColor = Colors.buttonBackground
|
||||||
dismissButton.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
|
dismissButton.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
dismissButton.setTitleColor(Colors.text, for: UIControl.State.normal)
|
dismissButton.setTitleColor(Colors.text, for: UIControl.State.normal)
|
||||||
dismissButton.setTitle(NSLocalizedString("Dismiss", comment: ""), for: UIControl.State.normal)
|
dismissButton.setTitle(NSLocalizedString("session_reset_banner_dismiss_button_title", comment: ""), for: UIControl.State.normal)
|
||||||
dismissButton.addTarget(self, action: #selector(dismiss), for: UIControl.Event.touchUpInside)
|
dismissButton.addTarget(self, action: #selector(dismiss), for: UIControl.Event.touchUpInside)
|
||||||
// Set up button stack view
|
// Set up button stack view
|
||||||
let buttonStackView = UIStackView(arrangedSubviews: [ dismissButton, restoreButton ])
|
let buttonStackView = UIStackView(arrangedSubviews: [ dismissButton, restoreButton ])
|
||||||
|
@ -73,7 +73,7 @@ final class SessionRestorationView : UIView {
|
||||||
// Update explanation label if possible
|
// Update explanation label if possible
|
||||||
if let contactID = thread.contactIdentifier() {
|
if let contactID = thread.contactIdentifier() {
|
||||||
let displayName = UserDisplayNameUtilities.getPrivateChatDisplayName(for: contactID) ?? contactID
|
let displayName = UserDisplayNameUtilities.getPrivateChatDisplayName(for: contactID) ?? contactID
|
||||||
explanationLabel.text = String(format: NSLocalizedString("Would you like to restore your session with %@? This can help resolve issues. Your messages will be preserved.", comment: ""), displayName)
|
explanationLabel.text = String(format: "Would you like to restore your session with %@? This can help resolve issues. Your messages will be preserved.", displayName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ class BaseVC : UIViewController {
|
||||||
guard DeviceLinkingUtilities.shouldShowUnexpectedDeviceLinkRequestReceivedAlert else { return }
|
guard DeviceLinkingUtilities.shouldShowUnexpectedDeviceLinkRequestReceivedAlert else { return }
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
let alert = UIAlertController(title: "Device Link Request Received", message: "Open the device link screen by going to \"Settings\" > \"Devices\" > \"Link a Device\" to link your devices.", preferredStyle: .alert)
|
let alert = UIAlertController(title: "Device Link Request Received", message: "Open the device link screen by going to \"Settings\" > \"Devices\" > \"Link a Device\" to link your devices.", preferredStyle: .alert)
|
||||||
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
|
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
||||||
self.present(alert, animated: true, completion: nil)
|
self.present(alert, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate {
|
||||||
result.backgroundColor = Colors.accent
|
result.backgroundColor = Colors.accent
|
||||||
result.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
|
result.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
result.setTitleColor(Colors.text, for: UIControl.State.normal)
|
result.setTitleColor(Colors.text, for: UIControl.State.normal)
|
||||||
result.setTitle(NSLocalizedString("Authorize", comment: ""), for: UIControl.State.normal)
|
result.setTitle(NSLocalizedString("modal_link_device_master_mode_authorize_button_title", comment: ""), for: UIControl.State.normal)
|
||||||
return result
|
return result
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -130,14 +130,14 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate {
|
||||||
}
|
}
|
||||||
titleLabel.text = {
|
titleLabel.text = {
|
||||||
switch mode {
|
switch mode {
|
||||||
case .master: return NSLocalizedString("Waiting for Device", comment: "")
|
case .master: return NSLocalizedString("modal_link_device_master_mode_title_1", comment: "")
|
||||||
case .slave: return NSLocalizedString("Waiting for Authorization", comment: "")
|
case .slave: return NSLocalizedString("modal_link_device_slave_mode_title_1", comment: "")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
subtitleLabel.text = {
|
subtitleLabel.text = {
|
||||||
switch mode {
|
switch mode {
|
||||||
case .master: return NSLocalizedString("Download Session on your other device and tap \"Link to an existing account\" at the bottom of the landing screen. If you have an existing account on your other device already you will have to delete that account first.", comment: "")
|
case .master: return NSLocalizedString("modal_link_device_master_mode_explanation_1", comment: "")
|
||||||
case .slave: return NSLocalizedString("Please check that the words below match those shown on your other device", comment: "")
|
case .slave: return NSLocalizedString("modal_link_device_slave_mode_explanation_1", comment: "")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
mnemonicLabel.isHidden = (mode == .master)
|
mnemonicLabel.isHidden = (mode == .master)
|
||||||
|
@ -157,8 +157,8 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate {
|
||||||
func requestUserAuthorization(for deviceLink: DeviceLink) {
|
func requestUserAuthorization(for deviceLink: DeviceLink) {
|
||||||
self.deviceLink = deviceLink
|
self.deviceLink = deviceLink
|
||||||
qrCodeImageViewContainer.isHidden = true
|
qrCodeImageViewContainer.isHidden = true
|
||||||
titleLabel.text = NSLocalizedString("Linking Request Received", comment: "")
|
titleLabel.text = NSLocalizedString("modal_link_device_master_mode_title_2", comment: "")
|
||||||
subtitleLabel.text = NSLocalizedString("Please check that the words below match those shown on your other device", comment: "")
|
subtitleLabel.text = NSLocalizedString("modal_link_device_master_mode_explanation_2", comment: "")
|
||||||
let hexEncodedPublicKey = deviceLink.slave.publicKey.removing05PrefixIfNeeded()
|
let hexEncodedPublicKey = deviceLink.slave.publicKey.removing05PrefixIfNeeded()
|
||||||
mnemonicLabel.text = Mnemonic.hash(hexEncodedString: hexEncodedPublicKey)
|
mnemonicLabel.text = Mnemonic.hash(hexEncodedString: hexEncodedPublicKey)
|
||||||
mnemonicLabel.isHidden = false
|
mnemonicLabel.isHidden = false
|
||||||
|
@ -172,8 +172,8 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate {
|
||||||
mainStackView.insertArrangedSubview(spinner, at: 0)
|
mainStackView.insertArrangedSubview(spinner, at: 0)
|
||||||
spinner.set(.height, to: 64)
|
spinner.set(.height, to: 64)
|
||||||
spinner.startAnimating()
|
spinner.startAnimating()
|
||||||
titleLabel.text = NSLocalizedString("Authorizing Device Link", comment: "")
|
titleLabel.text = NSLocalizedString("modal_link_device_master_mode_title_3", comment: "")
|
||||||
subtitleLabel.text = NSLocalizedString("Please wait while the device link is created. This can take up to a minute.", comment: "")
|
subtitleLabel.text = NSLocalizedString("modal_link_device_master_mode_explanation_3", comment: "")
|
||||||
mnemonicLabel.isHidden = true
|
mnemonicLabel.isHidden = true
|
||||||
buttonStackView.isHidden = true
|
buttonStackView.isHidden = true
|
||||||
let deviceLink = self.deviceLink!
|
let deviceLink = self.deviceLink!
|
||||||
|
@ -204,7 +204,7 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate {
|
||||||
let _ = FileServerAPI.removeDeviceLink(signedDeviceLink) // Attempt to roll back
|
let _ = FileServerAPI.removeDeviceLink(signedDeviceLink) // Attempt to roll back
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self?.close()
|
self?.close()
|
||||||
let alert = UIAlertController(title: NSLocalizedString("Device Linking Failed", comment: ""), message: NSLocalizedString("Please check your internet connection and try again", comment: ""), preferredStyle: .alert)
|
let alert = UIAlertController(title: "Device Linking Failed", message: "Please check your internet connection and try again", preferredStyle: .alert)
|
||||||
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
||||||
self?.presentingViewController?.present(alert, animated: true, completion: nil)
|
self?.presentingViewController?.present(alert, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
@ -213,7 +213,7 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate {
|
||||||
print("[Loki] Failed to add device link due to error: \(error).")
|
print("[Loki] Failed to add device link due to error: \(error).")
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self?.close() // TODO: Show a message to the user
|
self?.close() // TODO: Show a message to the user
|
||||||
let alert = UIAlertController(title: NSLocalizedString("Device Linking Failed", comment: ""), message: NSLocalizedString("Please check your internet connection and try again", comment: ""), preferredStyle: .alert)
|
let alert = UIAlertController(title: "Device Linking Failed", message: "Please check your internet connection and try again", preferredStyle: .alert)
|
||||||
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
||||||
self?.presentingViewController?.present(alert, animated: true, completion: nil)
|
self?.presentingViewController?.present(alert, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
@ -225,8 +225,8 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate {
|
||||||
session.stopListeningForLinkingAuthorization()
|
session.stopListeningForLinkingAuthorization()
|
||||||
spinner.stopAnimating()
|
spinner.stopAnimating()
|
||||||
spinner.isHidden = true
|
spinner.isHidden = true
|
||||||
titleLabel.text = NSLocalizedString("Device Link Authorized", comment: "")
|
titleLabel.text = NSLocalizedString("modal_link_device_slave_mode_title_2", comment: "")
|
||||||
subtitleLabel.text = NSLocalizedString("Your device has been linked successfully", comment: "")
|
subtitleLabel.text = NSLocalizedString("modal_link_device_slave_mode_explanation_2", comment: "")
|
||||||
mnemonicLabel.isHidden = true
|
mnemonicLabel.isHidden = true
|
||||||
buttonStackView.isHidden = true
|
buttonStackView.isHidden = true
|
||||||
FileServerAPI.addDeviceLink(deviceLink).catch { error in
|
FileServerAPI.addDeviceLink(deviceLink).catch { error in
|
||||||
|
|
|
@ -23,9 +23,9 @@ final class DeviceLinksVC : BaseVC, UITableViewDataSource, UITableViewDelegate,
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
explanationLabel.textAlignment = .center
|
explanationLabel.textAlignment = .center
|
||||||
explanationLabel.text = NSLocalizedString("You haven't linked any devices yet", comment: "")
|
explanationLabel.text = NSLocalizedString("vc_linked_devices_empty_state_message", comment: "")
|
||||||
let linkNewDeviceButton = Button(style: .prominentOutline, size: .large)
|
let linkNewDeviceButton = Button(style: .prominentOutline, size: .large)
|
||||||
linkNewDeviceButton.setTitle(NSLocalizedString("Link a Device (Beta)", comment: ""), for: UIControl.State.normal)
|
linkNewDeviceButton.setTitle(NSLocalizedString("vc_linked_devices_empty_state_button_title", comment: ""), for: UIControl.State.normal)
|
||||||
linkNewDeviceButton.addTarget(self, action: #selector(linkNewDevice), for: UIControl.Event.touchUpInside)
|
linkNewDeviceButton.addTarget(self, action: #selector(linkNewDevice), for: UIControl.Event.touchUpInside)
|
||||||
linkNewDeviceButton.set(.width, to: 180)
|
linkNewDeviceButton.set(.width, to: 180)
|
||||||
let result = UIStackView(arrangedSubviews: [ explanationLabel, linkNewDeviceButton ])
|
let result = UIStackView(arrangedSubviews: [ explanationLabel, linkNewDeviceButton ])
|
||||||
|
@ -40,7 +40,7 @@ final class DeviceLinksVC : BaseVC, UITableViewDataSource, UITableViewDelegate,
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
setUpGradientBackground()
|
setUpGradientBackground()
|
||||||
setUpNavBarStyle()
|
setUpNavBarStyle()
|
||||||
setNavBarTitle(NSLocalizedString("Devices", comment: ""))
|
setNavBarTitle(NSLocalizedString("vc_linked_devices_title", comment: ""))
|
||||||
// Set up link new device button
|
// Set up link new device button
|
||||||
let linkNewDeviceButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(linkNewDevice))
|
let linkNewDeviceButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(linkNewDevice))
|
||||||
linkNewDeviceButton.tintColor = Colors.text
|
linkNewDeviceButton.tintColor = Colors.text
|
||||||
|
@ -108,7 +108,7 @@ final class DeviceLinksVC : BaseVC, UITableViewDataSource, UITableViewDelegate,
|
||||||
deviceLinkingModal.modalTransitionStyle = .crossDissolve
|
deviceLinkingModal.modalTransitionStyle = .crossDissolve
|
||||||
present(deviceLinkingModal, animated: true, completion: nil)
|
present(deviceLinkingModal, animated: true, completion: nil)
|
||||||
} else {
|
} else {
|
||||||
let alert = UIAlertController(title: NSLocalizedString("Multi Device Limit Reached", comment: ""), message: NSLocalizedString("It's currently not allowed to link more than one device.", comment: ""), preferredStyle: .alert)
|
let alert = UIAlertController(title: NSLocalizedString("vc_linked_devices_multi_device_limit_reached_modal_title", comment: ""), message: NSLocalizedString("It's currently not allowed to link more than one device.", comment: ""), preferredStyle: .alert)
|
||||||
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
||||||
present(alert, animated: true, completion: nil)
|
present(alert, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ final class DeviceLinksVC : BaseVC, UITableViewDataSource, UITableViewDelegate,
|
||||||
defer { tableView.deselectRow(at: indexPath, animated: true) }
|
defer { tableView.deselectRow(at: indexPath, animated: true) }
|
||||||
let deviceLink = deviceLinks[indexPath.row]
|
let deviceLink = deviceLinks[indexPath.row]
|
||||||
let sheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
let sheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
|
||||||
sheet.addAction(UIAlertAction(title: NSLocalizedString("Change Name", comment: ""), style: .default) { [weak self] _ in
|
sheet.addAction(UIAlertAction(title: NSLocalizedString("vc_device_list_bottom_sheet_change_name_button_title", comment: ""), style: .default) { [weak self] _ in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
let deviceNameModal = DeviceNameModal()
|
let deviceNameModal = DeviceNameModal()
|
||||||
deviceNameModal.device = deviceLink.other
|
deviceNameModal.device = deviceLink.other
|
||||||
|
@ -127,10 +127,10 @@ final class DeviceLinksVC : BaseVC, UITableViewDataSource, UITableViewDelegate,
|
||||||
deviceNameModal.modalTransitionStyle = .crossDissolve
|
deviceNameModal.modalTransitionStyle = .crossDissolve
|
||||||
self.present(deviceNameModal, animated: true, completion: nil)
|
self.present(deviceNameModal, animated: true, completion: nil)
|
||||||
})
|
})
|
||||||
sheet.addAction(UIAlertAction(title: NSLocalizedString("Unlink", comment: ""), style: .destructive) { [weak self] _ in
|
sheet.addAction(UIAlertAction(title: NSLocalizedString("vc_device_list_bottom_sheet_unlink_device_button_title", comment: ""), style: .destructive) { [weak self] _ in
|
||||||
self?.removeDeviceLink(deviceLink)
|
self?.removeDeviceLink(deviceLink)
|
||||||
})
|
})
|
||||||
sheet.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel) { _ in })
|
sheet.addAction(UIAlertAction(title: NSLocalizedString("cancel", comment: ""), style: .cancel) { _ in })
|
||||||
present(sheet, animated: true, completion: nil)
|
present(sheet, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ final class DeviceLinksVC : BaseVC, UITableViewDataSource, UITableViewDelegate,
|
||||||
})
|
})
|
||||||
self?.updateDeviceLinks()
|
self?.updateDeviceLinks()
|
||||||
}.catch { [weak self] _ in
|
}.catch { [weak self] _ in
|
||||||
let alert = UIAlertController(title: NSLocalizedString("Couldn't Unlink Device", comment: ""), message: NSLocalizedString("Please check your internet connection and try again", comment: ""), preferredStyle: .alert)
|
let alert = UIAlertController(title: "Couldn't Unlink Device", message: "Please check your internet connection and try again", preferredStyle: .alert)
|
||||||
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), accessibilityIdentifier: nil, style: .default, handler: nil))
|
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), accessibilityIdentifier: nil, style: .default, handler: nil))
|
||||||
self?.present(alert, animated: true, completion: nil)
|
self?.present(alert, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ final class DeviceNameModal : Modal {
|
||||||
result.textColor = Colors.text
|
result.textColor = Colors.text
|
||||||
result.font = .systemFont(ofSize: Values.mediumFontSize)
|
result.font = .systemFont(ofSize: Values.mediumFontSize)
|
||||||
result.textAlignment = .center
|
result.textAlignment = .center
|
||||||
let placeholder = NSMutableAttributedString(string: NSLocalizedString("Enter a Name", comment: ""))
|
let placeholder = NSMutableAttributedString(string: NSLocalizedString("modal_edit_device_name_text_field_hint", comment: ""))
|
||||||
placeholder.addAttribute(.foregroundColor, value: Colors.text.withAlphaComponent(Values.unimportantElementOpacity), range: NSRange(location: 0, length: placeholder.length))
|
placeholder.addAttribute(.foregroundColor, value: Colors.text.withAlphaComponent(Values.unimportantElementOpacity), range: NSRange(location: 0, length: placeholder.length))
|
||||||
result.attributedPlaceholder = placeholder
|
result.attributedPlaceholder = placeholder
|
||||||
result.tintColor = Colors.accent
|
result.tintColor = Colors.accent
|
||||||
|
@ -31,7 +31,7 @@ final class DeviceNameModal : Modal {
|
||||||
let titleLabel = UILabel()
|
let titleLabel = UILabel()
|
||||||
titleLabel.textColor = Colors.text
|
titleLabel.textColor = Colors.text
|
||||||
titleLabel.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
titleLabel.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
||||||
titleLabel.text = NSLocalizedString("Change Device Name", comment: "")
|
titleLabel.text = "Change Device Name"
|
||||||
titleLabel.numberOfLines = 0
|
titleLabel.numberOfLines = 0
|
||||||
titleLabel.lineBreakMode = .byWordWrapping
|
titleLabel.lineBreakMode = .byWordWrapping
|
||||||
titleLabel.textAlignment = .center
|
titleLabel.textAlignment = .center
|
||||||
|
@ -39,7 +39,7 @@ final class DeviceNameModal : Modal {
|
||||||
let explanationLabel = UILabel()
|
let explanationLabel = UILabel()
|
||||||
explanationLabel.textColor = Colors.text
|
explanationLabel.textColor = Colors.text
|
||||||
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
explanationLabel.text = NSLocalizedString("Enter the new display name for your device below", comment: "")
|
explanationLabel.text = "Enter the new display name for your device below"
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.textAlignment = .center
|
explanationLabel.textAlignment = .center
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
|
@ -95,7 +95,7 @@ final class DeviceNameModal : Modal {
|
||||||
UserDefaults.standard[.slaveDeviceName(device.publicKey)] = name
|
UserDefaults.standard[.slaveDeviceName(device.publicKey)] = name
|
||||||
delegate?.handleDeviceNameChanged(to: name, for: device)
|
delegate?.handleDeviceNameChanged(to: name, for: device)
|
||||||
} else {
|
} else {
|
||||||
let alert = UIAlertController(title: NSLocalizedString("Error", comment: ""), message: NSLocalizedString("Please pick a name", comment: ""), preferredStyle: .alert)
|
let alert = UIAlertController(title: "Error", message: "Please pick a name", preferredStyle: .alert)
|
||||||
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), accessibilityIdentifier: nil, style: .default, handler: nil))
|
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), accessibilityIdentifier: nil, style: .default, handler: nil))
|
||||||
present(alert, animated: true, completion: nil)
|
present(alert, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ final class DisplayNameVC : BaseVC {
|
||||||
|
|
||||||
// MARK: Components
|
// MARK: Components
|
||||||
private lazy var displayNameTextField: TextField = {
|
private lazy var displayNameTextField: TextField = {
|
||||||
let result = TextField(placeholder: NSLocalizedString("Enter a display name", comment: ""))
|
let result = TextField(placeholder: NSLocalizedString("vc_display_name_text_field_hint", comment: ""))
|
||||||
result.layer.borderColor = Colors.text.cgColor
|
result.layer.borderColor = Colors.text.cgColor
|
||||||
return result
|
return result
|
||||||
}()
|
}()
|
||||||
|
@ -22,14 +22,14 @@ final class DisplayNameVC : BaseVC {
|
||||||
let titleLabel = UILabel()
|
let titleLabel = UILabel()
|
||||||
titleLabel.textColor = Colors.text
|
titleLabel.textColor = Colors.text
|
||||||
titleLabel.font = .boldSystemFont(ofSize: isIPhone5OrSmaller ? Values.largeFontSize : Values.veryLargeFontSize)
|
titleLabel.font = .boldSystemFont(ofSize: isIPhone5OrSmaller ? Values.largeFontSize : Values.veryLargeFontSize)
|
||||||
titleLabel.text = NSLocalizedString("Pick your display name", comment: "")
|
titleLabel.text = NSLocalizedString("vc_display_name_title_2", comment: "")
|
||||||
titleLabel.numberOfLines = 0
|
titleLabel.numberOfLines = 0
|
||||||
titleLabel.lineBreakMode = .byWordWrapping
|
titleLabel.lineBreakMode = .byWordWrapping
|
||||||
// Set up explanation label
|
// Set up explanation label
|
||||||
let explanationLabel = UILabel()
|
let explanationLabel = UILabel()
|
||||||
explanationLabel.textColor = Colors.text
|
explanationLabel.textColor = Colors.text
|
||||||
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
explanationLabel.text = "This will be your name when you use Session. It can be your real name, an alias, or anything else you like."
|
explanationLabel.text = NSLocalizedString("vc_display_name_explanation", comment: "")
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
// Set up spacers
|
// Set up spacers
|
||||||
|
@ -43,7 +43,7 @@ final class DisplayNameVC : BaseVC {
|
||||||
registerButtonBottomOffsetConstraint = registerButtonBottomOffsetSpacer.set(.height, to: Values.onboardingButtonBottomOffset)
|
registerButtonBottomOffsetConstraint = registerButtonBottomOffsetSpacer.set(.height, to: Values.onboardingButtonBottomOffset)
|
||||||
// Set up register button
|
// Set up register button
|
||||||
let registerButton = Button(style: .prominentFilled, size: .large)
|
let registerButton = Button(style: .prominentFilled, size: .large)
|
||||||
registerButton.setTitle(NSLocalizedString("Continue", comment: ""), for: UIControl.State.normal)
|
registerButton.setTitle(NSLocalizedString("continue_2", comment: ""), for: UIControl.State.normal)
|
||||||
registerButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
registerButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
||||||
registerButton.addTarget(self, action: #selector(register), for: UIControl.Event.touchUpInside)
|
registerButton.addTarget(self, action: #selector(register), for: UIControl.Event.touchUpInside)
|
||||||
// Set up register button container
|
// Set up register button container
|
||||||
|
@ -128,15 +128,15 @@ final class DisplayNameVC : BaseVC {
|
||||||
}
|
}
|
||||||
let displayName = displayNameTextField.text!.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
|
let displayName = displayNameTextField.text!.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
|
||||||
guard !displayName.isEmpty else {
|
guard !displayName.isEmpty else {
|
||||||
return showError(title: NSLocalizedString("Please pick a display name", comment: ""))
|
return showError(title: NSLocalizedString("vc_display_name_display_name_missing_error", comment: ""))
|
||||||
}
|
}
|
||||||
let allowedCharacters = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_ ")
|
let allowedCharacters = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_ ")
|
||||||
let hasInvalidCharacters = !displayName.allSatisfy { $0.unicodeScalars.allSatisfy { allowedCharacters.contains($0) } }
|
let hasInvalidCharacters = !displayName.allSatisfy { $0.unicodeScalars.allSatisfy { allowedCharacters.contains($0) } }
|
||||||
guard !hasInvalidCharacters else {
|
guard !hasInvalidCharacters else {
|
||||||
return showError(title: NSLocalizedString("Please pick a display name that consists of only a-z, A-Z, 0-9 and _ characters", comment: ""))
|
return showError(title: NSLocalizedString("vc_display_name_display_name_invalid_error", comment: ""))
|
||||||
}
|
}
|
||||||
guard !OWSProfileManager.shared().isProfileNameTooLong(displayName) else {
|
guard !OWSProfileManager.shared().isProfileNameTooLong(displayName) else {
|
||||||
return showError(title: NSLocalizedString("Please pick a shorter display name", comment: ""))
|
return showError(title: NSLocalizedString("vc_display_name_display_name_too_long_error", comment: ""))
|
||||||
}
|
}
|
||||||
OWSProfileManager.shared().updateLocalProfileName(displayName, avatarImage: nil, success: { }, failure: { _ in }, requiresSync: false) // Try to save the user name but ignore the result
|
OWSProfileManager.shared().updateLocalProfileName(displayName, avatarImage: nil, success: { }, failure: { _ in }, requiresSync: false) // Try to save the user name but ignore the result
|
||||||
let pnModeVC = PNModeVC()
|
let pnModeVC = PNModeVC()
|
||||||
|
|
|
@ -35,12 +35,12 @@ final class GroupMembersVC : BaseVC, UITableViewDataSource {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
setUpGradientBackground()
|
setUpGradientBackground()
|
||||||
setUpNavBarStyle()
|
setUpNavBarStyle()
|
||||||
setNavBarTitle(NSLocalizedString("Group Members", comment: ""))
|
setNavBarTitle("Group Members")
|
||||||
// Set up explanation label
|
// Set up explanation label
|
||||||
let explanationLabel = UILabel()
|
let explanationLabel = UILabel()
|
||||||
explanationLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
|
explanationLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
|
||||||
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
explanationLabel.text = NSLocalizedString("The ability to add members to a closed group is coming soon.", comment: "")
|
explanationLabel.text = "The ability to add members to a closed group is coming soon."
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.textAlignment = .center
|
explanationLabel.textAlignment = .center
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
|
|
|
@ -30,7 +30,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, UIScrol
|
||||||
let attributedTitle = NSMutableAttributedString(string: title)
|
let attributedTitle = NSMutableAttributedString(string: title)
|
||||||
attributedTitle.addAttribute(.foregroundColor, value: Colors.accent, range: (title as NSString).range(of: "80%"))
|
attributedTitle.addAttribute(.foregroundColor, value: Colors.accent, range: (title as NSString).range(of: "80%"))
|
||||||
result.title = attributedTitle
|
result.title = attributedTitle
|
||||||
result.subtitle = NSLocalizedString("Secure your account by saving your recovery phrase", comment: "")
|
result.subtitle = NSLocalizedString("view_seed_reminder_subtitle_1", comment: "")
|
||||||
result.setProgress(0.8, animated: false)
|
result.setProgress(0.8, animated: false)
|
||||||
result.delegate = self
|
result.delegate = self
|
||||||
return result
|
return result
|
||||||
|
@ -70,9 +70,9 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, UIScrol
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
explanationLabel.textAlignment = .center
|
explanationLabel.textAlignment = .center
|
||||||
explanationLabel.text = NSLocalizedString("You don't have any contacts yet", comment: "")
|
explanationLabel.text = NSLocalizedString("vc_home_empty_state_message", comment: "")
|
||||||
let createNewPrivateChatButton = Button(style: .prominentOutline, size: .large)
|
let createNewPrivateChatButton = Button(style: .prominentOutline, size: .large)
|
||||||
createNewPrivateChatButton.setTitle(NSLocalizedString("Start a Session", comment: ""), for: UIControl.State.normal)
|
createNewPrivateChatButton.setTitle(NSLocalizedString("vc_home_empty_state_button_title", comment: ""), for: UIControl.State.normal)
|
||||||
createNewPrivateChatButton.addTarget(self, action: #selector(createNewPrivateChat), for: UIControl.Event.touchUpInside)
|
createNewPrivateChatButton.addTarget(self, action: #selector(createNewPrivateChat), for: UIControl.Event.touchUpInside)
|
||||||
createNewPrivateChatButton.set(.width, to: 180)
|
createNewPrivateChatButton.set(.width, to: 180)
|
||||||
let result = UIStackView(arrangedSubviews: [ explanationLabel, createNewPrivateChatButton ])
|
let result = UIStackView(arrangedSubviews: [ explanationLabel, createNewPrivateChatButton ])
|
||||||
|
@ -91,7 +91,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, UIScrol
|
||||||
setUpNavBarStyle()
|
setUpNavBarStyle()
|
||||||
}
|
}
|
||||||
updateNavigationBarButtons()
|
updateNavigationBarButtons()
|
||||||
setNavBarTitle(NSLocalizedString("Messages", comment: ""))
|
setNavBarTitle("Messages")
|
||||||
// Set up seed reminder view if needed
|
// Set up seed reminder view if needed
|
||||||
let userDefaults = UserDefaults.standard
|
let userDefaults = UserDefaults.standard
|
||||||
let hasViewedSeed = userDefaults[.hasViewedSeed]
|
let hasViewedSeed = userDefaults[.hasViewedSeed]
|
||||||
|
@ -372,7 +372,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, UIScrol
|
||||||
OWSPrimaryStorage.shared().dbReadConnection.read { transaction in
|
OWSPrimaryStorage.shared().dbReadConnection.read { transaction in
|
||||||
publicChat = LokiDatabaseUtilities.getPublicChat(for: thread.uniqueId!, in: transaction)
|
publicChat = LokiDatabaseUtilities.getPublicChat(for: thread.uniqueId!, in: transaction)
|
||||||
}
|
}
|
||||||
let delete = UITableViewRowAction(style: .destructive, title: NSLocalizedString("Delete", comment: "")) { [weak self] _, _ in
|
let delete = UITableViewRowAction(style: .destructive, title: NSLocalizedString("TXT_DELETE_TITLE", comment: "")) { [weak self] _, _ in
|
||||||
let alert = UIAlertController(title: NSLocalizedString("CONVERSATION_DELETE_CONFIRMATION_ALERT_TITLE", comment: ""), message: NSLocalizedString("CONVERSATION_DELETE_CONFIRMATION_ALERT_MESSAGE", comment: ""), preferredStyle: .alert)
|
let alert = UIAlertController(title: NSLocalizedString("CONVERSATION_DELETE_CONFIRMATION_ALERT_TITLE", comment: ""), message: NSLocalizedString("CONVERSATION_DELETE_CONFIRMATION_ALERT_MESSAGE", comment: ""), preferredStyle: .alert)
|
||||||
alert.addAction(UIAlertAction(title: NSLocalizedString("TXT_DELETE_TITLE", comment: ""), style: .destructive) { _ in
|
alert.addAction(UIAlertAction(title: NSLocalizedString("TXT_DELETE_TITLE", comment: ""), style: .destructive) { _ in
|
||||||
try! Storage.writeSync { transaction in
|
try! Storage.writeSync { transaction in
|
||||||
|
|
|
@ -8,11 +8,11 @@ final class JoinPublicChatVC : BaseVC, UIPageViewControllerDataSource, UIPageVie
|
||||||
// MARK: Components
|
// MARK: Components
|
||||||
private lazy var tabBar: TabBar = {
|
private lazy var tabBar: TabBar = {
|
||||||
let tabs = [
|
let tabs = [
|
||||||
TabBar.Tab(title: NSLocalizedString("Open Group URL", comment: "")) { [weak self] in
|
TabBar.Tab(title: NSLocalizedString("vc_join_public_chat_enter_group_url_tab_title", comment: "")) { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.pageVC.setViewControllers([ self.pages[0] ], direction: .forward, animated: false, completion: nil)
|
self.pageVC.setViewControllers([ self.pages[0] ], direction: .forward, animated: false, completion: nil)
|
||||||
},
|
},
|
||||||
TabBar.Tab(title: NSLocalizedString("Scan QR Code", comment: "")) { [weak self] in
|
TabBar.Tab(title: NSLocalizedString("vc_join_public_chat_scan_qr_code_tab_title", comment: "")) { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.pageVC.setViewControllers([ self.pages[1] ], direction: .forward, animated: false, completion: nil)
|
self.pageVC.setViewControllers([ self.pages[1] ], direction: .forward, animated: false, completion: nil)
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ final class JoinPublicChatVC : BaseVC, UIPageViewControllerDataSource, UIPageVie
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private lazy var scanQRCodeWrapperVC: ScanQRCodeWrapperVC = {
|
private lazy var scanQRCodeWrapperVC: ScanQRCodeWrapperVC = {
|
||||||
let message = NSLocalizedString("Scan the QR code of the open group you'd like to join", comment: "")
|
let message = NSLocalizedString("vc_join_public_chat_scan_qr_code_explanation", comment: "")
|
||||||
let result = ScanQRCodeWrapperVC(message: message)
|
let result = ScanQRCodeWrapperVC(message: message)
|
||||||
result.delegate = self
|
result.delegate = self
|
||||||
return result
|
return result
|
||||||
|
@ -44,7 +44,7 @@ final class JoinPublicChatVC : BaseVC, UIPageViewControllerDataSource, UIPageVie
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
setUpGradientBackground()
|
setUpGradientBackground()
|
||||||
setUpNavBarStyle()
|
setUpNavBarStyle()
|
||||||
setNavBarTitle(NSLocalizedString("Join Open Group", comment: ""))
|
setNavBarTitle(NSLocalizedString("vc_join_public_chat_title", comment: ""))
|
||||||
let navigationBar = navigationController!.navigationBar
|
let navigationBar = navigationController!.navigationBar
|
||||||
// Set up navigation bar buttons
|
// Set up navigation bar buttons
|
||||||
let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close))
|
let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close))
|
||||||
|
@ -128,7 +128,7 @@ final class JoinPublicChatVC : BaseVC, UIPageViewControllerDataSource, UIPageVie
|
||||||
fileprivate func joinPublicChatIfPossible(with chatURL: String) {
|
fileprivate func joinPublicChatIfPossible(with chatURL: String) {
|
||||||
guard !isJoining else { return }
|
guard !isJoining else { return }
|
||||||
guard let url = URL(string: chatURL), let scheme = url.scheme, scheme == "https", url.host != nil else {
|
guard let url = URL(string: chatURL), let scheme = url.scheme, scheme == "https", url.host != nil else {
|
||||||
return showError(title: NSLocalizedString("Invalid URL", comment: ""), message: NSLocalizedString("Please check the URL you entered and try again", comment: ""))
|
return showError(title: NSLocalizedString("invalid_url", comment: ""), message: "Please check the URL you entered and try again")
|
||||||
}
|
}
|
||||||
isJoining = true
|
isJoining = true
|
||||||
let channelID: UInt64 = 1
|
let channelID: UInt64 = 1
|
||||||
|
@ -154,11 +154,11 @@ final class JoinPublicChatVC : BaseVC, UIPageViewControllerDataSource, UIPageVie
|
||||||
}
|
}
|
||||||
.catch(on: DispatchQueue.main) { [weak self] error in
|
.catch(on: DispatchQueue.main) { [weak self] error in
|
||||||
self?.dismiss(animated: true, completion: nil) // Dismiss the loader
|
self?.dismiss(animated: true, completion: nil) // Dismiss the loader
|
||||||
var title = NSLocalizedString("Couldn't Join", comment: "")
|
var title = "Couldn't Join"
|
||||||
var message = ""
|
var message = ""
|
||||||
if case HTTP.Error.httpRequestFailed(let statusCode, _) = error, statusCode == 401 || statusCode == 403 {
|
if case HTTP.Error.httpRequestFailed(let statusCode, _) = error, statusCode == 401 || statusCode == 403 {
|
||||||
title = NSLocalizedString("Unauthorized", comment: "")
|
title = "Unauthorized"
|
||||||
message = NSLocalizedString("Please ask the open group operator to add you to the group.", comment: "")
|
message = "Please ask the open group operator to add you to the group."
|
||||||
}
|
}
|
||||||
self?.isJoining = false
|
self?.isJoining = false
|
||||||
self?.showError(title: title, message: message)
|
self?.showError(title: title, message: message)
|
||||||
|
@ -180,7 +180,7 @@ private final class EnterChatURLVC : UIViewController {
|
||||||
|
|
||||||
// MARK: Components
|
// MARK: Components
|
||||||
private lazy var chatURLTextField: TextField = {
|
private lazy var chatURLTextField: TextField = {
|
||||||
let result = TextField(placeholder: "Enter an open group URL")
|
let result = TextField(placeholder: "vc_enter_chat_url_text_field_hint")
|
||||||
result.keyboardType = .URL
|
result.keyboardType = .URL
|
||||||
result.autocapitalizationType = .none
|
result.autocapitalizationType = .none
|
||||||
return result
|
return result
|
||||||
|
@ -194,13 +194,13 @@ private final class EnterChatURLVC : UIViewController {
|
||||||
let explanationLabel = UILabel()
|
let explanationLabel = UILabel()
|
||||||
explanationLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
|
explanationLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
|
||||||
explanationLabel.font = .systemFont(ofSize: Values.verySmallFontSize)
|
explanationLabel.font = .systemFont(ofSize: Values.verySmallFontSize)
|
||||||
explanationLabel.text = NSLocalizedString("Open groups can be joined by anyone and do not provide full privacy protection", comment: "")
|
explanationLabel.text = NSLocalizedString("vc_enter_chat_url_privacy_warning", comment: "")
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.textAlignment = .center
|
explanationLabel.textAlignment = .center
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
// Next button
|
// Next button
|
||||||
let nextButton = Button(style: .prominentOutline, size: .large)
|
let nextButton = Button(style: .prominentOutline, size: .large)
|
||||||
nextButton.setTitle(NSLocalizedString("Next", comment: ""), for: UIControl.State.normal)
|
nextButton.setTitle(NSLocalizedString("next", comment: ""), for: UIControl.State.normal)
|
||||||
nextButton.addTarget(self, action: #selector(joinPublicChatIfPossible), for: UIControl.Event.touchUpInside)
|
nextButton.addTarget(self, action: #selector(joinPublicChatIfPossible), for: UIControl.Event.touchUpInside)
|
||||||
let nextButtonContainer = UIView()
|
let nextButtonContainer = UIView()
|
||||||
nextButtonContainer.addSubview(nextButton)
|
nextButtonContainer.addSubview(nextButton)
|
||||||
|
@ -280,7 +280,7 @@ private final class ScanQRCodePlaceholderVC : UIViewController {
|
||||||
let explanationLabel = UILabel()
|
let explanationLabel = UILabel()
|
||||||
explanationLabel.textColor = Colors.text
|
explanationLabel.textColor = Colors.text
|
||||||
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
explanationLabel.text = NSLocalizedString("Session needs camera access to scan QR codes", comment: "")
|
explanationLabel.text = NSLocalizedString("vc_scan_qr_code_camera_access_explanation", comment: "")
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.textAlignment = .center
|
explanationLabel.textAlignment = .center
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
|
@ -288,7 +288,7 @@ private final class ScanQRCodePlaceholderVC : UIViewController {
|
||||||
let callToActionButton = UIButton()
|
let callToActionButton = UIButton()
|
||||||
callToActionButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
callToActionButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
||||||
callToActionButton.setTitleColor(Colors.accent, for: UIControl.State.normal)
|
callToActionButton.setTitleColor(Colors.accent, for: UIControl.State.normal)
|
||||||
callToActionButton.setTitle(NSLocalizedString("Enable Camera Access", comment: ""), for: UIControl.State.normal)
|
callToActionButton.setTitle(NSLocalizedString("vc_scan_qr_code_grant_camera_access_button_title", comment: ""), for: UIControl.State.normal)
|
||||||
callToActionButton.addTarget(self, action: #selector(requestCameraAccess), for: UIControl.Event.touchUpInside)
|
callToActionButton.addTarget(self, action: #selector(requestCameraAccess), for: UIControl.Event.touchUpInside)
|
||||||
// Set up stack view
|
// Set up stack view
|
||||||
let stackView = UIStackView(arrangedSubviews: [ explanationLabel, callToActionButton ])
|
let stackView = UIStackView(arrangedSubviews: [ explanationLabel, callToActionButton ])
|
||||||
|
|
|
@ -11,7 +11,7 @@ final class LandingVC : BaseVC, LinkDeviceVCDelegate, DeviceLinkingModalDelegate
|
||||||
|
|
||||||
private lazy var registerButton: Button = {
|
private lazy var registerButton: Button = {
|
||||||
let result = Button(style: .prominentFilled, size: .large)
|
let result = Button(style: .prominentFilled, size: .large)
|
||||||
result.setTitle(NSLocalizedString("Create Session ID", comment: ""), for: UIControl.State.normal)
|
result.setTitle(NSLocalizedString("vc_landing_register_button_title", comment: ""), for: UIControl.State.normal)
|
||||||
result.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
result.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
||||||
result.addTarget(self, action: #selector(register), for: UIControl.Event.touchUpInside)
|
result.addTarget(self, action: #selector(register), for: UIControl.Event.touchUpInside)
|
||||||
return result
|
return result
|
||||||
|
@ -19,7 +19,7 @@ final class LandingVC : BaseVC, LinkDeviceVCDelegate, DeviceLinkingModalDelegate
|
||||||
|
|
||||||
private lazy var restoreButton: Button = {
|
private lazy var restoreButton: Button = {
|
||||||
let result = Button(style: .prominentOutline, size: .large)
|
let result = Button(style: .prominentOutline, size: .large)
|
||||||
result.setTitle(NSLocalizedString("Continue your Session", comment: ""), for: UIControl.State.normal)
|
result.setTitle(NSLocalizedString("vc_landing_restore_button_title", comment: ""), for: UIControl.State.normal)
|
||||||
result.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
result.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
||||||
result.addTarget(self, action: #selector(restore), for: UIControl.Event.touchUpInside)
|
result.addTarget(self, action: #selector(restore), for: UIControl.Event.touchUpInside)
|
||||||
return result
|
return result
|
||||||
|
@ -27,7 +27,7 @@ final class LandingVC : BaseVC, LinkDeviceVCDelegate, DeviceLinkingModalDelegate
|
||||||
|
|
||||||
private lazy var linkButton: Button = {
|
private lazy var linkButton: Button = {
|
||||||
let result = Button(style: .regularBorderless, size: .small)
|
let result = Button(style: .regularBorderless, size: .small)
|
||||||
result.setTitle(NSLocalizedString("Link to an existing account", comment: ""), for: UIControl.State.normal)
|
result.setTitle(NSLocalizedString("vc_landing_link_button_title", comment: ""), for: UIControl.State.normal)
|
||||||
result.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
|
result.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
result.addTarget(self, action: #selector(linkDevice), for: UIControl.Event.touchUpInside)
|
result.addTarget(self, action: #selector(linkDevice), for: UIControl.Event.touchUpInside)
|
||||||
return result
|
return result
|
||||||
|
@ -43,7 +43,7 @@ final class LandingVC : BaseVC, LinkDeviceVCDelegate, DeviceLinkingModalDelegate
|
||||||
let titleLabel = UILabel()
|
let titleLabel = UILabel()
|
||||||
titleLabel.textColor = Colors.text
|
titleLabel.textColor = Colors.text
|
||||||
titleLabel.font = .boldSystemFont(ofSize: isIPhone5OrSmaller ? Values.largeFontSize : Values.veryLargeFontSize)
|
titleLabel.font = .boldSystemFont(ofSize: isIPhone5OrSmaller ? Values.largeFontSize : Values.veryLargeFontSize)
|
||||||
titleLabel.text = NSLocalizedString("Your Session begins here...", comment: "")
|
titleLabel.text = NSLocalizedString("vc_landing_title_2", comment: "")
|
||||||
titleLabel.numberOfLines = 0
|
titleLabel.numberOfLines = 0
|
||||||
titleLabel.lineBreakMode = .byWordWrapping
|
titleLabel.lineBreakMode = .byWordWrapping
|
||||||
// Set up title label container
|
// Set up title label container
|
||||||
|
@ -85,7 +85,7 @@ final class LandingVC : BaseVC, LinkDeviceVCDelegate, DeviceLinkingModalDelegate
|
||||||
topSpacer.heightAnchor.constraint(equalTo: bottomSpacer.heightAnchor, multiplier: 1).isActive = true
|
topSpacer.heightAnchor.constraint(equalTo: bottomSpacer.heightAnchor, multiplier: 1).isActive = true
|
||||||
// Show device unlinked alert if needed
|
// Show device unlinked alert if needed
|
||||||
if UserDefaults.standard[.wasUnlinked] {
|
if UserDefaults.standard[.wasUnlinked] {
|
||||||
let alert = UIAlertController(title: NSLocalizedString("Device Unlinked", comment: ""), message: NSLocalizedString("Your device was unlinked successfully", comment: ""), preferredStyle: .alert)
|
let alert = UIAlertController(title: "Device Unlinked", message: NSLocalizedString("vc_landing_device_unlinked_dialog_title", comment: ""), preferredStyle: .alert)
|
||||||
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), accessibilityIdentifier: nil, style: .default, handler: nil))
|
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), accessibilityIdentifier: nil, style: .default, handler: nil))
|
||||||
present(alert, animated: true, completion: nil)
|
present(alert, animated: true, completion: nil)
|
||||||
UserDefaults.removeAll()
|
UserDefaults.removeAll()
|
||||||
|
@ -128,7 +128,7 @@ final class LandingVC : BaseVC, LinkDeviceVCDelegate, DeviceLinkingModalDelegate
|
||||||
// MARK: Device Linking
|
// MARK: Device Linking
|
||||||
func requestDeviceLink(with hexEncodedPublicKey: String) {
|
func requestDeviceLink(with hexEncodedPublicKey: String) {
|
||||||
guard ECKeyPair.isValidHexEncodedPublicKey(candidate: hexEncodedPublicKey) else {
|
guard ECKeyPair.isValidHexEncodedPublicKey(candidate: hexEncodedPublicKey) else {
|
||||||
let alert = UIAlertController(title: NSLocalizedString("Invalid Session ID", comment: ""), message: NSLocalizedString("Please make sure the Session ID you entered is correct and try again.", comment: ""), preferredStyle: .alert)
|
let alert = UIAlertController(title: NSLocalizedString("invalid_session_id", comment: ""), message: "Please make sure the Session ID you entered is correct and try again.", preferredStyle: .alert)
|
||||||
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), accessibilityIdentifier: nil, style: .default, handler: nil))
|
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), accessibilityIdentifier: nil, style: .default, handler: nil))
|
||||||
return present(alert, animated: true, completion: nil)
|
return present(alert, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,11 @@ final class LinkDeviceVC : BaseVC, UIPageViewControllerDataSource, UIPageViewCon
|
||||||
// MARK: Components
|
// MARK: Components
|
||||||
private lazy var tabBar: TabBar = {
|
private lazy var tabBar: TabBar = {
|
||||||
let tabs = [
|
let tabs = [
|
||||||
TabBar.Tab(title: NSLocalizedString("Enter Session ID", comment: "")) { [weak self] in
|
TabBar.Tab(title: NSLocalizedString("vc_link_device_enter_session_id_tab_title", comment: "")) { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.pageVC.setViewControllers([ self.pages[0] ], direction: .forward, animated: false, completion: nil)
|
self.pageVC.setViewControllers([ self.pages[0] ], direction: .forward, animated: false, completion: nil)
|
||||||
},
|
},
|
||||||
TabBar.Tab(title: NSLocalizedString("Scan QR Code", comment: "")) { [weak self] in
|
TabBar.Tab(title: NSLocalizedString("vc_link_device_scan_qr_code_tab_title", comment: "")) { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.pageVC.setViewControllers([ self.pages[1] ], direction: .forward, animated: false, completion: nil)
|
self.pageVC.setViewControllers([ self.pages[1] ], direction: .forward, animated: false, completion: nil)
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ final class LinkDeviceVC : BaseVC, UIPageViewControllerDataSource, UIPageViewCon
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private lazy var scanQRCodeWrapperVC: ScanQRCodeWrapperVC = {
|
private lazy var scanQRCodeWrapperVC: ScanQRCodeWrapperVC = {
|
||||||
let message = NSLocalizedString("Navigate to \"Settings\" > \"Devices\" > \"Link a Device\" on your other device and then scan the QR code that comes up to start the linking process.", comment: "")
|
let message = NSLocalizedString("vc_link_device_scan_qr_code_explanation", comment: "")
|
||||||
let result = ScanQRCodeWrapperVC(message: message)
|
let result = ScanQRCodeWrapperVC(message: message)
|
||||||
result.delegate = self
|
result.delegate = self
|
||||||
return result
|
return result
|
||||||
|
@ -44,7 +44,7 @@ final class LinkDeviceVC : BaseVC, UIPageViewControllerDataSource, UIPageViewCon
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
setUpGradientBackground()
|
setUpGradientBackground()
|
||||||
setUpNavBarStyle()
|
setUpNavBarStyle()
|
||||||
setNavBarTitle(NSLocalizedString("Link Device", comment: ""))
|
setNavBarTitle(NSLocalizedString("vc_link_device_title", comment: ""))
|
||||||
let navigationBar = navigationController!.navigationBar
|
let navigationBar = navigationController!.navigationBar
|
||||||
// Set up navigation bar buttons
|
// Set up navigation bar buttons
|
||||||
let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close))
|
let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close))
|
||||||
|
@ -143,9 +143,9 @@ private final class EnterPublicKeyVC : UIViewController {
|
||||||
// MARK: Components
|
// MARK: Components
|
||||||
private lazy var publicKeyTextField: TextField = {
|
private lazy var publicKeyTextField: TextField = {
|
||||||
if isIPhone6OrSmaller {
|
if isIPhone6OrSmaller {
|
||||||
return TextField(placeholder: NSLocalizedString("Enter your Session ID", comment: ""), customHeight: 56, customVerticalInset: 12)
|
return TextField(placeholder: NSLocalizedString("vc_enter_session_id_text_field_hint", comment: ""), customHeight: 56, customVerticalInset: 12)
|
||||||
} else {
|
} else {
|
||||||
return TextField(placeholder: NSLocalizedString("Enter your Session ID", comment: ""))
|
return TextField(placeholder: NSLocalizedString("vc_enter_session_id_text_field_hint", comment: ""))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -157,19 +157,19 @@ private final class EnterPublicKeyVC : UIViewController {
|
||||||
let titleLabel = UILabel()
|
let titleLabel = UILabel()
|
||||||
titleLabel.textColor = Colors.text
|
titleLabel.textColor = Colors.text
|
||||||
titleLabel.font = .boldSystemFont(ofSize: isIPhone6OrSmaller ? Values.largeFontSize : Values.veryLargeFontSize)
|
titleLabel.font = .boldSystemFont(ofSize: isIPhone6OrSmaller ? Values.largeFontSize : Values.veryLargeFontSize)
|
||||||
titleLabel.text = NSLocalizedString("Link your device", comment: "")
|
titleLabel.text = NSLocalizedString("vc_enter_session_id_title", comment: "")
|
||||||
titleLabel.numberOfLines = 0
|
titleLabel.numberOfLines = 0
|
||||||
titleLabel.lineBreakMode = .byWordWrapping
|
titleLabel.lineBreakMode = .byWordWrapping
|
||||||
// Set up explanation label
|
// Set up explanation label
|
||||||
let explanationLabel = UILabel()
|
let explanationLabel = UILabel()
|
||||||
explanationLabel.textColor = Colors.text
|
explanationLabel.textColor = Colors.text
|
||||||
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
explanationLabel.text = "Navigate to \"Settings\" > \"Devices\" > \"Link a Device\" on your other device and then enter your Session ID here to start the linking process."
|
explanationLabel.text = "vc_enter_session_id_explanation"
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
// Link button
|
// Link button
|
||||||
let linkButton = Button(style: .prominentOutline, size: .large)
|
let linkButton = Button(style: .prominentOutline, size: .large)
|
||||||
linkButton.setTitle(NSLocalizedString("Continue", comment: ""), for: UIControl.State.normal)
|
linkButton.setTitle(NSLocalizedString("continue_2", comment: ""), for: UIControl.State.normal)
|
||||||
linkButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
linkButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
||||||
linkButton.addTarget(self, action: #selector(requestDeviceLink), for: UIControl.Event.touchUpInside)
|
linkButton.addTarget(self, action: #selector(requestDeviceLink), for: UIControl.Event.touchUpInside)
|
||||||
let linkButtonContainer = UIView()
|
let linkButtonContainer = UIView()
|
||||||
|
@ -270,7 +270,7 @@ private final class ScanQRCodePlaceholderVC : UIViewController {
|
||||||
let explanationLabel = UILabel()
|
let explanationLabel = UILabel()
|
||||||
explanationLabel.textColor = Colors.text
|
explanationLabel.textColor = Colors.text
|
||||||
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
explanationLabel.text = NSLocalizedString("Session needs camera access to scan QR codes", comment: "")
|
explanationLabel.text = NSLocalizedString("vc_scan_qr_code_camera_access_explanation", comment: "")
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.textAlignment = .center
|
explanationLabel.textAlignment = .center
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
|
@ -278,7 +278,7 @@ private final class ScanQRCodePlaceholderVC : UIViewController {
|
||||||
let callToActionButton = UIButton()
|
let callToActionButton = UIButton()
|
||||||
callToActionButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
callToActionButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
||||||
callToActionButton.setTitleColor(Colors.accent, for: UIControl.State.normal)
|
callToActionButton.setTitleColor(Colors.accent, for: UIControl.State.normal)
|
||||||
callToActionButton.setTitle(NSLocalizedString("Enable Camera Access", comment: ""), for: UIControl.State.normal)
|
callToActionButton.setTitle(NSLocalizedString("vc_scan_qr_code_grant_camera_access_button_title", comment: ""), for: UIControl.State.normal)
|
||||||
callToActionButton.addTarget(self, action: #selector(requestCameraAccess), for: UIControl.Event.touchUpInside)
|
callToActionButton.addTarget(self, action: #selector(requestCameraAccess), for: UIControl.Event.touchUpInside)
|
||||||
// Set up stack view
|
// Set up stack view
|
||||||
let stackView = UIStackView(arrangedSubviews: [ explanationLabel, callToActionButton ])
|
let stackView = UIStackView(arrangedSubviews: [ explanationLabel, callToActionButton ])
|
||||||
|
|
|
@ -24,7 +24,7 @@ class Modal : BaseVC {
|
||||||
result.backgroundColor = Colors.buttonBackground
|
result.backgroundColor = Colors.buttonBackground
|
||||||
result.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
|
result.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
result.setTitleColor(Colors.text, for: UIControl.State.normal)
|
result.setTitleColor(Colors.text, for: UIControl.State.normal)
|
||||||
result.setTitle(NSLocalizedString("Cancel", comment: ""), for: UIControl.State.normal)
|
result.setTitle(NSLocalizedString("cancel", comment: ""), for: UIControl.State.normal)
|
||||||
return result
|
return result
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ final class NewClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelegat
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// MARK: Components
|
// MARK: Components
|
||||||
private lazy var nameTextField = TextField(placeholder: NSLocalizedString("Enter a group name", comment: ""))
|
private lazy var nameTextField = TextField(placeholder: NSLocalizedString("vc_create_closed_group_text_field_hint", comment: ""))
|
||||||
|
|
||||||
private lazy var tableView: UITableView = {
|
private lazy var tableView: UITableView = {
|
||||||
let result = UITableView()
|
let result = UITableView()
|
||||||
|
@ -49,7 +49,7 @@ final class NewClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelegat
|
||||||
setUpGradientBackground()
|
setUpGradientBackground()
|
||||||
setUpNavBarStyle()
|
setUpNavBarStyle()
|
||||||
let customTitleFontSize = Values.largeFontSize
|
let customTitleFontSize = Values.largeFontSize
|
||||||
setNavBarTitle(NSLocalizedString("New Closed Group", comment: ""), customFontSize: customTitleFontSize)
|
setNavBarTitle(NSLocalizedString("vc_create_closed_group_title", comment: ""), customFontSize: customTitleFontSize)
|
||||||
// Set up navigation bar buttons
|
// Set up navigation bar buttons
|
||||||
let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close))
|
let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close))
|
||||||
closeButton.tintColor = Colors.text
|
closeButton.tintColor = Colors.text
|
||||||
|
@ -89,9 +89,9 @@ final class NewClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelegat
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
explanationLabel.textAlignment = .center
|
explanationLabel.textAlignment = .center
|
||||||
explanationLabel.text = NSLocalizedString("You don't have any contacts yet", comment: "")
|
explanationLabel.text = NSLocalizedString("vc_create_closed_group_empty_state_message", comment: "")
|
||||||
let createNewPrivateChatButton = Button(style: .prominentOutline, size: .large)
|
let createNewPrivateChatButton = Button(style: .prominentOutline, size: .large)
|
||||||
createNewPrivateChatButton.setTitle(NSLocalizedString("Start a Session", comment: ""), for: UIControl.State.normal)
|
createNewPrivateChatButton.setTitle(NSLocalizedString("vc_create_closed_group_empty_state_button_title", comment: ""), for: UIControl.State.normal)
|
||||||
createNewPrivateChatButton.addTarget(self, action: #selector(createNewPrivateChat), for: UIControl.Event.touchUpInside)
|
createNewPrivateChatButton.addTarget(self, action: #selector(createNewPrivateChat), for: UIControl.Event.touchUpInside)
|
||||||
createNewPrivateChatButton.set(.width, to: 180)
|
createNewPrivateChatButton.set(.width, to: 180)
|
||||||
let stackView = UIStackView(arrangedSubviews: [ explanationLabel, createNewPrivateChatButton ])
|
let stackView = UIStackView(arrangedSubviews: [ explanationLabel, createNewPrivateChatButton ])
|
||||||
|
@ -120,7 +120,7 @@ final class NewClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelegat
|
||||||
|
|
||||||
// MARK: Interaction
|
// MARK: Interaction
|
||||||
func textFieldDidEndEditing(_ textField: UITextField) {
|
func textFieldDidEndEditing(_ textField: UITextField) {
|
||||||
crossfadeLabel.text = textField.text!.isEmpty ? NSLocalizedString("New Closed Group", comment: "") : textField.text!
|
crossfadeLabel.text = textField.text!.isEmpty ? NSLocalizedString("vc_create_closed_group_title", comment: "") : textField.text!
|
||||||
}
|
}
|
||||||
|
|
||||||
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||||
|
@ -166,16 +166,16 @@ final class NewClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelegat
|
||||||
presentAlert(alert)
|
presentAlert(alert)
|
||||||
}
|
}
|
||||||
guard let name = nameTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines), name.count > 0 else {
|
guard let name = nameTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines), name.count > 0 else {
|
||||||
return showError(title: NSLocalizedString("Please enter a group name", comment: ""))
|
return showError(title: NSLocalizedString("vc_create_closed_group_group_name_missing_error", comment: ""))
|
||||||
}
|
}
|
||||||
guard name.count < 64 else {
|
guard name.count < 64 else {
|
||||||
return showError(title: NSLocalizedString("Please enter a shorter group name", comment: ""))
|
return showError(title: NSLocalizedString("vc_create_closed_group_group_name_too_long_error", comment: ""))
|
||||||
}
|
}
|
||||||
guard selectedContacts.count >= 2 else {
|
guard selectedContacts.count >= 2 else {
|
||||||
return showError(title: NSLocalizedString("Please pick at least 2 group members", comment: ""))
|
return showError(title: NSLocalizedString("vc_create_closed_group_not_enough_group_members_error", comment: ""))
|
||||||
}
|
}
|
||||||
guard selectedContacts.count < 50 else { // Minus one because we're going to include self later
|
guard selectedContacts.count < 50 else { // Minus one because we're going to include self later
|
||||||
return showError(title: NSLocalizedString("A closed group cannot have more than 50 members", comment: ""))
|
return showError(title: NSLocalizedString("vc_create_closed_group_too_many_group_members_error", comment: ""))
|
||||||
}
|
}
|
||||||
let selectedContacts = self.selectedContacts
|
let selectedContacts = self.selectedContacts
|
||||||
ModalActivityIndicatorViewController.present(fromViewController: navigationController!, canCancel: false) { [weak self] _ in
|
ModalActivityIndicatorViewController.present(fromViewController: navigationController!, canCancel: false) { [weak self] _ in
|
||||||
|
@ -190,8 +190,8 @@ final class NewClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelegat
|
||||||
SignalApp.shared().presentConversation(for: thread, action: .compose, animated: false)
|
SignalApp.shared().presentConversation(for: thread, action: .compose, animated: false)
|
||||||
}.catch(on: DispatchQueue.main) { _ in
|
}.catch(on: DispatchQueue.main) { _ in
|
||||||
self?.dismiss(animated: true, completion: nil) // Dismiss the loader
|
self?.dismiss(animated: true, completion: nil) // Dismiss the loader
|
||||||
let title = NSLocalizedString("Couldn't Create Group", comment: "")
|
let title = "Couldn't Create Group"
|
||||||
let message = NSLocalizedString("Please check your internet connection and try again.", comment: "")
|
let message = "Please check your internet connection and try again."
|
||||||
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||||
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
||||||
self?.presentAlert(alert)
|
self?.presentAlert(alert)
|
||||||
|
@ -206,16 +206,16 @@ final class NewClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelegat
|
||||||
presentAlert(alert)
|
presentAlert(alert)
|
||||||
}
|
}
|
||||||
guard let name = nameTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines), name.count > 0 else {
|
guard let name = nameTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines), name.count > 0 else {
|
||||||
return showError(title: NSLocalizedString("Please enter a group name", comment: ""))
|
return showError(title: NSLocalizedString("vc_create_closed_group_group_name_missing_error", comment: ""))
|
||||||
}
|
}
|
||||||
guard name.count < 64 else {
|
guard name.count < 64 else {
|
||||||
return showError(title: NSLocalizedString("Please enter a shorter group name", comment: ""))
|
return showError(title: NSLocalizedString("vc_create_closed_group_group_name_too_long_error", comment: ""))
|
||||||
}
|
}
|
||||||
guard selectedContacts.count >= 2 else {
|
guard selectedContacts.count >= 2 else {
|
||||||
return showError(title: NSLocalizedString("Please pick at least 2 group members", comment: ""))
|
return showError(title: NSLocalizedString("vc_create_closed_group_not_enough_group_members_error", comment: ""))
|
||||||
}
|
}
|
||||||
guard selectedContacts.count < 10 else { // Minus one because we're going to include self later
|
guard selectedContacts.count < 10 else { // Minus one because we're going to include self later
|
||||||
return showError(title: NSLocalizedString("A closed group cannot have more than 10 members", comment: ""))
|
return showError(title: NSLocalizedString("vc_create_closed_group_too_many_group_members_error", comment: ""))
|
||||||
}
|
}
|
||||||
let userPublicKey = getUserHexEncodedPublicKey()
|
let userPublicKey = getUserHexEncodedPublicKey()
|
||||||
let storage = OWSPrimaryStorage.shared()
|
let storage = OWSPrimaryStorage.shared()
|
||||||
|
|
|
@ -7,11 +7,11 @@ final class NewPrivateChatVC : BaseVC, UIPageViewControllerDataSource, UIPageVie
|
||||||
// MARK: Components
|
// MARK: Components
|
||||||
private lazy var tabBar: TabBar = {
|
private lazy var tabBar: TabBar = {
|
||||||
let tabs = [
|
let tabs = [
|
||||||
TabBar.Tab(title: NSLocalizedString("Enter Session ID", comment: "")) { [weak self] in
|
TabBar.Tab(title: NSLocalizedString("vc_create_private_chat_enter_session_id_tab_title", comment: "")) { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.pageVC.setViewControllers([ self.pages[0] ], direction: .forward, animated: false, completion: nil)
|
self.pageVC.setViewControllers([ self.pages[0] ], direction: .forward, animated: false, completion: nil)
|
||||||
},
|
},
|
||||||
TabBar.Tab(title: NSLocalizedString("Scan QR Code", comment: "")) { [weak self] in
|
TabBar.Tab(title: NSLocalizedString("vc_create_private_chat_scan_qr_code_tab_title", comment: "")) { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.pageVC.setViewControllers([ self.pages[1] ], direction: .forward, animated: false, completion: nil)
|
self.pageVC.setViewControllers([ self.pages[1] ], direction: .forward, animated: false, completion: nil)
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ final class NewPrivateChatVC : BaseVC, UIPageViewControllerDataSource, UIPageVie
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private lazy var scanQRCodeWrapperVC: ScanQRCodeWrapperVC = {
|
private lazy var scanQRCodeWrapperVC: ScanQRCodeWrapperVC = {
|
||||||
let message = NSLocalizedString("Scan a user’s QR code to start a session. QR codes can be found by tapping the QR code icon in account settings.", comment: "")
|
let message = NSLocalizedString("vc_create_private_chat_scan_qr_code_explanation", comment: "")
|
||||||
let result = ScanQRCodeWrapperVC(message: message)
|
let result = ScanQRCodeWrapperVC(message: message)
|
||||||
result.delegate = self
|
result.delegate = self
|
||||||
return result
|
return result
|
||||||
|
@ -43,7 +43,7 @@ final class NewPrivateChatVC : BaseVC, UIPageViewControllerDataSource, UIPageVie
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
setUpGradientBackground()
|
setUpGradientBackground()
|
||||||
setUpNavBarStyle()
|
setUpNavBarStyle()
|
||||||
setNavBarTitle(NSLocalizedString("New Session", comment: ""))
|
setNavBarTitle(NSLocalizedString("vc_create_private_chat_title", comment: ""))
|
||||||
let navigationBar = navigationController!.navigationBar
|
let navigationBar = navigationController!.navigationBar
|
||||||
// Set up navigation bar buttons
|
// Set up navigation bar buttons
|
||||||
let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close))
|
let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close))
|
||||||
|
@ -126,7 +126,7 @@ final class NewPrivateChatVC : BaseVC, UIPageViewControllerDataSource, UIPageVie
|
||||||
|
|
||||||
fileprivate func startNewPrivateChatIfPossible(with hexEncodedPublicKey: String) {
|
fileprivate func startNewPrivateChatIfPossible(with hexEncodedPublicKey: String) {
|
||||||
if !ECKeyPair.isValidHexEncodedPublicKey(candidate: hexEncodedPublicKey) {
|
if !ECKeyPair.isValidHexEncodedPublicKey(candidate: hexEncodedPublicKey) {
|
||||||
let alert = UIAlertController(title: NSLocalizedString("Invalid Session ID", comment: ""), message: NSLocalizedString("Please check the Session ID and try again", comment: ""), preferredStyle: .alert)
|
let alert = UIAlertController(title: NSLocalizedString("invalid_session_id", comment: ""), message: NSLocalizedString("Please check the Session ID and try again", comment: ""), preferredStyle: .alert)
|
||||||
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
||||||
presentAlert(alert)
|
presentAlert(alert)
|
||||||
} else {
|
} else {
|
||||||
|
@ -149,11 +149,11 @@ private final class EnterPublicKeyVC : UIViewController {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// MARK: Components
|
// MARK: Components
|
||||||
private lazy var publicKeyTextField = TextField(placeholder: NSLocalizedString("Enter a Session ID", comment: ""))
|
private lazy var publicKeyTextField = TextField(placeholder: NSLocalizedString("vc_enter_public_key_text_field_hint", comment: ""))
|
||||||
|
|
||||||
private lazy var copyButton: Button = {
|
private lazy var copyButton: Button = {
|
||||||
let result = Button(style: .unimportant, size: .medium)
|
let result = Button(style: .unimportant, size: .medium)
|
||||||
result.setTitle(NSLocalizedString("Copy", comment: ""), for: UIControl.State.normal)
|
result.setTitle(NSLocalizedString("copy", comment: ""), for: UIControl.State.normal)
|
||||||
result.addTarget(self, action: #selector(copyPublicKey), for: UIControl.Event.touchUpInside)
|
result.addTarget(self, action: #selector(copyPublicKey), for: UIControl.Event.touchUpInside)
|
||||||
return result
|
return result
|
||||||
}()
|
}()
|
||||||
|
@ -166,12 +166,12 @@ private final class EnterPublicKeyVC : UIViewController {
|
||||||
let explanationLabel = UILabel()
|
let explanationLabel = UILabel()
|
||||||
explanationLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
|
explanationLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
|
||||||
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
explanationLabel.text = NSLocalizedString("Users can share their Session ID from their account settings, or by sharing their QR code.", comment: "")
|
explanationLabel.text = NSLocalizedString("vc_enter_public_key_explanation", comment: "")
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.textAlignment = .center
|
explanationLabel.textAlignment = .center
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
// Set up separator
|
// Set up separator
|
||||||
let separator = Separator(title: NSLocalizedString("Your Session ID", comment: ""))
|
let separator = Separator(title: NSLocalizedString("your_session_id", comment: ""))
|
||||||
// Set up user public key label
|
// Set up user public key label
|
||||||
let userPublicKeyLabel = UILabel()
|
let userPublicKeyLabel = UILabel()
|
||||||
userPublicKeyLabel.textColor = Colors.text
|
userPublicKeyLabel.textColor = Colors.text
|
||||||
|
@ -182,7 +182,7 @@ private final class EnterPublicKeyVC : UIViewController {
|
||||||
userPublicKeyLabel.text = userHexEncodedPublicKey
|
userPublicKeyLabel.text = userHexEncodedPublicKey
|
||||||
// Set up share button
|
// Set up share button
|
||||||
let shareButton = Button(style: .unimportant, size: .medium)
|
let shareButton = Button(style: .unimportant, size: .medium)
|
||||||
shareButton.setTitle(NSLocalizedString("Share", comment: ""), for: UIControl.State.normal)
|
shareButton.setTitle(NSLocalizedString("share", comment: ""), for: UIControl.State.normal)
|
||||||
shareButton.addTarget(self, action: #selector(sharePublicKey), for: UIControl.Event.touchUpInside)
|
shareButton.addTarget(self, action: #selector(sharePublicKey), for: UIControl.Event.touchUpInside)
|
||||||
// Set up button container
|
// Set up button container
|
||||||
let buttonContainer = UIStackView(arrangedSubviews: [ copyButton, shareButton ])
|
let buttonContainer = UIStackView(arrangedSubviews: [ copyButton, shareButton ])
|
||||||
|
@ -191,7 +191,7 @@ private final class EnterPublicKeyVC : UIViewController {
|
||||||
buttonContainer.distribution = .fillEqually
|
buttonContainer.distribution = .fillEqually
|
||||||
// Next button
|
// Next button
|
||||||
let nextButton = Button(style: .prominentOutline, size: .large)
|
let nextButton = Button(style: .prominentOutline, size: .large)
|
||||||
nextButton.setTitle(NSLocalizedString("Next", comment: ""), for: UIControl.State.normal)
|
nextButton.setTitle(NSLocalizedString("next", comment: ""), for: UIControl.State.normal)
|
||||||
nextButton.addTarget(self, action: #selector(startNewPrivateChatIfPossible), for: UIControl.Event.touchUpInside)
|
nextButton.addTarget(self, action: #selector(startNewPrivateChatIfPossible), for: UIControl.Event.touchUpInside)
|
||||||
let nextButtonContainer = UIView()
|
let nextButtonContainer = UIView()
|
||||||
nextButtonContainer.addSubview(nextButton)
|
nextButtonContainer.addSubview(nextButton)
|
||||||
|
@ -226,7 +226,7 @@ private final class EnterPublicKeyVC : UIViewController {
|
||||||
@objc private func enableCopyButton() {
|
@objc private func enableCopyButton() {
|
||||||
copyButton.isUserInteractionEnabled = true
|
copyButton.isUserInteractionEnabled = true
|
||||||
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
||||||
self.copyButton.setTitle(NSLocalizedString("Copy", comment: ""), for: UIControl.State.normal)
|
self.copyButton.setTitle(NSLocalizedString("copy", comment: ""), for: UIControl.State.normal)
|
||||||
}, completion: nil)
|
}, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ private final class EnterPublicKeyVC : UIViewController {
|
||||||
UIPasteboard.general.string = userHexEncodedPublicKey
|
UIPasteboard.general.string = userHexEncodedPublicKey
|
||||||
copyButton.isUserInteractionEnabled = false
|
copyButton.isUserInteractionEnabled = false
|
||||||
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
||||||
self.copyButton.setTitle(NSLocalizedString("Copied", comment: ""), for: UIControl.State.normal)
|
self.copyButton.setTitle("Copied", for: UIControl.State.normal)
|
||||||
}, completion: nil)
|
}, completion: nil)
|
||||||
Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(enableCopyButton), userInfo: nil, repeats: false)
|
Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(enableCopyButton), userInfo: nil, repeats: false)
|
||||||
}
|
}
|
||||||
|
@ -261,7 +261,7 @@ private final class ScanQRCodePlaceholderVC : UIViewController {
|
||||||
let explanationLabel = UILabel()
|
let explanationLabel = UILabel()
|
||||||
explanationLabel.textColor = Colors.text
|
explanationLabel.textColor = Colors.text
|
||||||
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
explanationLabel.text = NSLocalizedString("Session needs camera access to scan QR codes", comment: "")
|
explanationLabel.text = NSLocalizedString("vc_scan_qr_code_camera_access_explanation", comment: "")
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.textAlignment = .center
|
explanationLabel.textAlignment = .center
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
|
@ -269,7 +269,7 @@ private final class ScanQRCodePlaceholderVC : UIViewController {
|
||||||
let callToActionButton = UIButton()
|
let callToActionButton = UIButton()
|
||||||
callToActionButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
callToActionButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
||||||
callToActionButton.setTitleColor(Colors.accent, for: UIControl.State.normal)
|
callToActionButton.setTitleColor(Colors.accent, for: UIControl.State.normal)
|
||||||
callToActionButton.setTitle(NSLocalizedString("Enable Camera Access", comment: ""), for: UIControl.State.normal)
|
callToActionButton.setTitle(NSLocalizedString("vc_scan_qr_code_grant_camera_access_button_title", comment: ""), for: UIControl.State.normal)
|
||||||
callToActionButton.addTarget(self, action: #selector(requestCameraAccess), for: UIControl.Event.touchUpInside)
|
callToActionButton.addTarget(self, action: #selector(requestCameraAccess), for: UIControl.Event.touchUpInside)
|
||||||
// Set up stack view
|
// Set up stack view
|
||||||
let stackView = UIStackView(arrangedSubviews: [ explanationLabel, callToActionButton ])
|
let stackView = UIStackView(arrangedSubviews: [ explanationLabel, callToActionButton ])
|
||||||
|
|
|
@ -8,7 +8,7 @@ final class NukeDataModal : Modal {
|
||||||
let titleLabel = UILabel()
|
let titleLabel = UILabel()
|
||||||
titleLabel.textColor = Colors.text
|
titleLabel.textColor = Colors.text
|
||||||
titleLabel.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
titleLabel.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
||||||
titleLabel.text = NSLocalizedString("Clear All Data", comment: "")
|
titleLabel.text = NSLocalizedString("modal_clear_all_data_title", comment: "")
|
||||||
titleLabel.numberOfLines = 0
|
titleLabel.numberOfLines = 0
|
||||||
titleLabel.lineBreakMode = .byWordWrapping
|
titleLabel.lineBreakMode = .byWordWrapping
|
||||||
titleLabel.textAlignment = .center
|
titleLabel.textAlignment = .center
|
||||||
|
@ -16,7 +16,7 @@ final class NukeDataModal : Modal {
|
||||||
let explanationLabel = UILabel()
|
let explanationLabel = UILabel()
|
||||||
explanationLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
|
explanationLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
|
||||||
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
explanationLabel.text = NSLocalizedString("This will permanently delete your messages, sessions, and contacts.", comment: "")
|
explanationLabel.text = NSLocalizedString("modal_clear_all_data_explanation", comment: "")
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.textAlignment = .center
|
explanationLabel.textAlignment = .center
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
|
@ -29,7 +29,7 @@ final class NukeDataModal : Modal {
|
||||||
}
|
}
|
||||||
nukeDataButton.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
|
nukeDataButton.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
nukeDataButton.setTitleColor(isLightMode ? Colors.destructive : Colors.text, for: UIControl.State.normal)
|
nukeDataButton.setTitleColor(isLightMode ? Colors.destructive : Colors.text, for: UIControl.State.normal)
|
||||||
nukeDataButton.setTitle(NSLocalizedString("Delete", comment: ""), for: UIControl.State.normal)
|
nukeDataButton.setTitle(NSLocalizedString("TXT_DELETE_TITLE", comment: ""), for: UIControl.State.normal)
|
||||||
nukeDataButton.addTarget(self, action: #selector(nuke), for: UIControl.Event.touchUpInside)
|
nukeDataButton.addTarget(self, action: #selector(nuke), for: UIControl.Event.touchUpInside)
|
||||||
// Set up button stack view
|
// Set up button stack view
|
||||||
let buttonStackView = UIStackView(arrangedSubviews: [ cancelButton, nukeDataButton ])
|
let buttonStackView = UIStackView(arrangedSubviews: [ cancelButton, nukeDataButton ])
|
||||||
|
|
|
@ -11,8 +11,8 @@ final class PNModeVC : BaseVC, OptionViewDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Components
|
// MARK: Components
|
||||||
private lazy var apnsOptionView = OptionView(title: NSLocalizedString("Apple Push Notification Service", comment: ""), explanation: NSLocalizedString("Session will use the Apple Push Notification service to receive push notifications. You'll be notified of new messages reliably and immediately. Using APNs means that your IP address and device token will be exposed to Apple. If you use push notifications for other apps, this will already be the case. Your IP address and device token will also be exposed to Loki, but your messages will still be onion-routed and end-to-end encrypted, so the contents of your messages will remain completely private.", comment: ""), delegate: self, isRecommended: true)
|
private lazy var apnsOptionView = OptionView(title: NSLocalizedString("vc_pn_mode_apns_option_title", comment: ""), explanation: NSLocalizedString("vc_pn_mode_apns_option_explanation", comment: ""), delegate: self, isRecommended: true)
|
||||||
private lazy var backgroundPollingOptionView = OptionView(title: NSLocalizedString("Background Polling", comment: ""), explanation: NSLocalizedString("Session will occasionally check for new messages in the background. This guarantees full metadata protection, but message notifications may be significantly delayed.", comment: ""), delegate: self)
|
private lazy var backgroundPollingOptionView = OptionView(title: NSLocalizedString("vc_pn_mode_background_polling_option_title", comment: ""), explanation: NSLocalizedString("vc_pn_mode_background_polling_option_explanation", comment: ""), delegate: self)
|
||||||
|
|
||||||
// MARK: Lifecycle
|
// MARK: Lifecycle
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
|
@ -24,14 +24,14 @@ final class PNModeVC : BaseVC, OptionViewDelegate {
|
||||||
let titleLabel = UILabel()
|
let titleLabel = UILabel()
|
||||||
titleLabel.textColor = Colors.text
|
titleLabel.textColor = Colors.text
|
||||||
titleLabel.font = .boldSystemFont(ofSize: isIPhone5OrSmaller ? Values.largeFontSize : Values.veryLargeFontSize)
|
titleLabel.font = .boldSystemFont(ofSize: isIPhone5OrSmaller ? Values.largeFontSize : Values.veryLargeFontSize)
|
||||||
titleLabel.text = NSLocalizedString("Push Notifications", comment: "")
|
titleLabel.text = NSLocalizedString("vc_pn_mode_title", comment: "")
|
||||||
titleLabel.numberOfLines = 0
|
titleLabel.numberOfLines = 0
|
||||||
titleLabel.lineBreakMode = .byWordWrapping
|
titleLabel.lineBreakMode = .byWordWrapping
|
||||||
// Set up explanation label
|
// Set up explanation label
|
||||||
let explanationLabel = UILabel()
|
let explanationLabel = UILabel()
|
||||||
explanationLabel.textColor = Colors.text
|
explanationLabel.textColor = Colors.text
|
||||||
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
explanationLabel.text = NSLocalizedString("There are two ways Session can handle push notifications. Make sure to read the descriptions carefully before you choose.", comment: "")
|
explanationLabel.text = NSLocalizedString("vc_pn_mode_explanation", comment: "")
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
// Set up spacers
|
// Set up spacers
|
||||||
|
@ -41,7 +41,7 @@ final class PNModeVC : BaseVC, OptionViewDelegate {
|
||||||
registerButtonBottomOffsetSpacer.set(.height, to: isIPhone5OrSmaller ? CGFloat(16) : Values.onboardingButtonBottomOffset)
|
registerButtonBottomOffsetSpacer.set(.height, to: isIPhone5OrSmaller ? CGFloat(16) : Values.onboardingButtonBottomOffset)
|
||||||
// Set up register button
|
// Set up register button
|
||||||
let registerButton = Button(style: .prominentFilled, size: .large)
|
let registerButton = Button(style: .prominentFilled, size: .large)
|
||||||
registerButton.setTitle(NSLocalizedString("Continue", comment: ""), for: UIControl.State.normal)
|
registerButton.setTitle(NSLocalizedString("continue_2", comment: ""), for: UIControl.State.normal)
|
||||||
registerButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
registerButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
||||||
registerButton.addTarget(self, action: #selector(register), for: UIControl.Event.touchUpInside)
|
registerButton.addTarget(self, action: #selector(register), for: UIControl.Event.touchUpInside)
|
||||||
// Set up register button container
|
// Set up register button container
|
||||||
|
@ -75,7 +75,7 @@ final class PNModeVC : BaseVC, OptionViewDelegate {
|
||||||
|
|
||||||
@objc private func register() {
|
@objc private func register() {
|
||||||
guard selectedOptionView != nil else {
|
guard selectedOptionView != nil else {
|
||||||
let title = NSLocalizedString("Please Pick an Option", comment: "")
|
let title = NSLocalizedString("vc_pn_mode_no_option_picked_dialog_title", comment: "")
|
||||||
let alert = UIAlertController(title: title, message: nil, preferredStyle: .alert)
|
let alert = UIAlertController(title: title, message: nil, preferredStyle: .alert)
|
||||||
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
||||||
return present(alert, animated: true, completion: nil)
|
return present(alert, animated: true, completion: nil)
|
||||||
|
|
|
@ -19,7 +19,7 @@ final class PathVC : BaseVC {
|
||||||
|
|
||||||
private lazy var learnMoreButton: Button = {
|
private lazy var learnMoreButton: Button = {
|
||||||
let result = Button(style: .prominentOutline, size: .large)
|
let result = Button(style: .prominentOutline, size: .large)
|
||||||
result.setTitle(NSLocalizedString("Learn More", comment: ""), for: UIControl.State.normal)
|
result.setTitle(NSLocalizedString("vc_path_learn_more_button_title", comment: ""), for: UIControl.State.normal)
|
||||||
result.addTarget(self, action: #selector(learnMore), for: UIControl.Event.touchUpInside)
|
result.addTarget(self, action: #selector(learnMore), for: UIControl.Event.touchUpInside)
|
||||||
return result
|
return result
|
||||||
}()
|
}()
|
||||||
|
@ -35,7 +35,7 @@ final class PathVC : BaseVC {
|
||||||
|
|
||||||
private func setUpNavBar() {
|
private func setUpNavBar() {
|
||||||
setUpNavBarStyle()
|
setUpNavBarStyle()
|
||||||
setNavBarTitle(NSLocalizedString("Path", comment: ""))
|
setNavBarTitle(NSLocalizedString("vc_path_title", comment: ""))
|
||||||
// Set up close button
|
// Set up close button
|
||||||
let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close))
|
let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close))
|
||||||
closeButton.tintColor = Colors.text
|
closeButton.tintColor = Colors.text
|
||||||
|
@ -47,7 +47,7 @@ final class PathVC : BaseVC {
|
||||||
let explanationLabel = UILabel()
|
let explanationLabel = UILabel()
|
||||||
explanationLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
|
explanationLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
|
||||||
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
explanationLabel.text = NSLocalizedString("Session hides your IP by bouncing your messages through several Service Nodes in Session’s decentralized network. These are the countries your connection is currently being bounced through:", comment: "")
|
explanationLabel.text = NSLocalizedString("vc_path_explanation", comment: "")
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.textAlignment = .center
|
explanationLabel.textAlignment = .center
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
|
@ -113,8 +113,8 @@ final class PathVC : BaseVC {
|
||||||
let isGuardSnode = (snode == pathToDisplay.first!)
|
let isGuardSnode = (snode == pathToDisplay.first!)
|
||||||
return getPathRow(snode: snode, location: .middle, dotAnimationStartDelay: Double(index) + 2, dotAnimationRepeatInterval: dotAnimationRepeatInterval, isGuardSnode: isGuardSnode)
|
return getPathRow(snode: snode, location: .middle, dotAnimationStartDelay: Double(index) + 2, dotAnimationRepeatInterval: dotAnimationRepeatInterval, isGuardSnode: isGuardSnode)
|
||||||
}
|
}
|
||||||
let youRow = getPathRow(title: NSLocalizedString("You", comment: ""), subtitle: nil, location: .top, dotAnimationStartDelay: 1, dotAnimationRepeatInterval: dotAnimationRepeatInterval)
|
let youRow = getPathRow(title: NSLocalizedString("vc_path_device_row_title", comment: ""), subtitle: nil, location: .top, dotAnimationStartDelay: 1, dotAnimationRepeatInterval: dotAnimationRepeatInterval)
|
||||||
let destinationRow = getPathRow(title: NSLocalizedString("Destination", comment: ""), subtitle: nil, location: .bottom, dotAnimationStartDelay: Double(pathToDisplay.count) + 2, dotAnimationRepeatInterval: dotAnimationRepeatInterval)
|
let destinationRow = getPathRow(title: NSLocalizedString("vc_path_destination_row_title", comment: ""), subtitle: nil, location: .bottom, dotAnimationStartDelay: Double(pathToDisplay.count) + 2, dotAnimationRepeatInterval: dotAnimationRepeatInterval)
|
||||||
let rows = [ youRow ] + snodeRows + [ destinationRow ]
|
let rows = [ youRow ] + snodeRows + [ destinationRow ]
|
||||||
rows.forEach { pathStackView.addArrangedSubview($0) }
|
rows.forEach { pathStackView.addArrangedSubview($0) }
|
||||||
spinner.stopAnimating()
|
spinner.stopAnimating()
|
||||||
|
@ -158,7 +158,7 @@ final class PathVC : BaseVC {
|
||||||
|
|
||||||
private func getPathRow(snode: Snode, location: LineView.Location, dotAnimationStartDelay: Double, dotAnimationRepeatInterval: Double, isGuardSnode: Bool) -> UIStackView {
|
private func getPathRow(snode: Snode, location: LineView.Location, dotAnimationStartDelay: Double, dotAnimationRepeatInterval: Double, isGuardSnode: Bool) -> UIStackView {
|
||||||
let country = IP2Country.isInitialized ? (IP2Country.shared.countryNamesCache[snode.ip] ?? "Resolving...") : "Resolving..."
|
let country = IP2Country.isInitialized ? (IP2Country.shared.countryNamesCache[snode.ip] ?? "Resolving...") : "Resolving..."
|
||||||
let title = isGuardSnode ? NSLocalizedString("Entry Node", comment: "") : NSLocalizedString("Service Node", comment: "")
|
let title = isGuardSnode ? NSLocalizedString("vc_path_guard_node_row_title", comment: "") : NSLocalizedString("vc_path_service_node_row_title", comment: "")
|
||||||
return getPathRow(title: title, subtitle: country, location: location, dotAnimationStartDelay: dotAnimationStartDelay, dotAnimationRepeatInterval: dotAnimationRepeatInterval)
|
return getPathRow(title: title, subtitle: country, location: location, dotAnimationStartDelay: dotAnimationStartDelay, dotAnimationRepeatInterval: dotAnimationRepeatInterval)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,11 @@ final class QRCodeVC : BaseVC, UIPageViewControllerDataSource, UIPageViewControl
|
||||||
// MARK: Components
|
// MARK: Components
|
||||||
private lazy var tabBar: TabBar = {
|
private lazy var tabBar: TabBar = {
|
||||||
let tabs = [
|
let tabs = [
|
||||||
TabBar.Tab(title: NSLocalizedString("View My QR Code", comment: "")) { [weak self] in
|
TabBar.Tab(title: NSLocalizedString("vc_qr_code_view_my_qr_code_tab_title", comment: "")) { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.pageVC.setViewControllers([ self.pages[0] ], direction: .forward, animated: false, completion: nil)
|
self.pageVC.setViewControllers([ self.pages[0] ], direction: .forward, animated: false, completion: nil)
|
||||||
},
|
},
|
||||||
TabBar.Tab(title: NSLocalizedString("Scan QR Code", comment: "")) { [weak self] in
|
TabBar.Tab(title: NSLocalizedString("vc_qr_code_view_scan_qr_code_tab_title", comment: "")) { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.pageVC.setViewControllers([ self.pages[1] ], direction: .forward, animated: false, completion: nil)
|
self.pageVC.setViewControllers([ self.pages[1] ], direction: .forward, animated: false, completion: nil)
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ final class QRCodeVC : BaseVC, UIPageViewControllerDataSource, UIPageViewControl
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private lazy var scanQRCodeWrapperVC: ScanQRCodeWrapperVC = {
|
private lazy var scanQRCodeWrapperVC: ScanQRCodeWrapperVC = {
|
||||||
let message = NSLocalizedString("Scan someone's QR code to start a conversation with them", comment: "")
|
let message = NSLocalizedString("vc_qr_code_view_scan_qr_code_explanation", comment: "")
|
||||||
let result = ScanQRCodeWrapperVC(message: message)
|
let result = ScanQRCodeWrapperVC(message: message)
|
||||||
result.delegate = self
|
result.delegate = self
|
||||||
return result
|
return result
|
||||||
|
@ -44,7 +44,7 @@ final class QRCodeVC : BaseVC, UIPageViewControllerDataSource, UIPageViewControl
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
setUpGradientBackground()
|
setUpGradientBackground()
|
||||||
setUpNavBarStyle()
|
setUpNavBarStyle()
|
||||||
setNavBarTitle(NSLocalizedString("QR Code", comment: ""))
|
setNavBarTitle(NSLocalizedString("vc_qr_code_title", comment: ""))
|
||||||
let navigationBar = navigationController!.navigationBar
|
let navigationBar = navigationController!.navigationBar
|
||||||
// Set up page VC
|
// Set up page VC
|
||||||
let hasCameraAccess = (AVCaptureDevice.authorizationStatus(for: .video) == .authorized)
|
let hasCameraAccess = (AVCaptureDevice.authorizationStatus(for: .video) == .authorized)
|
||||||
|
@ -122,7 +122,7 @@ final class QRCodeVC : BaseVC, UIPageViewControllerDataSource, UIPageViewControl
|
||||||
|
|
||||||
fileprivate func startNewPrivateChatIfPossible(with hexEncodedPublicKey: String) {
|
fileprivate func startNewPrivateChatIfPossible(with hexEncodedPublicKey: String) {
|
||||||
if !ECKeyPair.isValidHexEncodedPublicKey(candidate: hexEncodedPublicKey) {
|
if !ECKeyPair.isValidHexEncodedPublicKey(candidate: hexEncodedPublicKey) {
|
||||||
let alert = UIAlertController(title: NSLocalizedString("Invalid Session ID", comment: ""), message: NSLocalizedString("Please check the Session ID and try again.", comment: ""), preferredStyle: .alert)
|
let alert = UIAlertController(title: NSLocalizedString("invalid_session_id", comment: ""), message: NSLocalizedString("Please check the Session ID and try again.", comment: ""), preferredStyle: .alert)
|
||||||
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
||||||
presentAlert(alert)
|
presentAlert(alert)
|
||||||
} else {
|
} else {
|
||||||
|
@ -153,7 +153,7 @@ private final class ViewMyQRCodeVC : UIViewController {
|
||||||
let titleLabel = UILabel()
|
let titleLabel = UILabel()
|
||||||
titleLabel.textColor = Colors.text
|
titleLabel.textColor = Colors.text
|
||||||
titleLabel.font = .boldSystemFont(ofSize: isIPhone5OrSmaller ? CGFloat(40) : Values.massiveFontSize)
|
titleLabel.font = .boldSystemFont(ofSize: isIPhone5OrSmaller ? CGFloat(40) : Values.massiveFontSize)
|
||||||
titleLabel.text = NSLocalizedString("Scan Me", comment: "")
|
titleLabel.text = "Scan Me"
|
||||||
titleLabel.numberOfLines = 0
|
titleLabel.numberOfLines = 0
|
||||||
titleLabel.textAlignment = .center
|
titleLabel.textAlignment = .center
|
||||||
titleLabel.lineBreakMode = .byWordWrapping
|
titleLabel.lineBreakMode = .byWordWrapping
|
||||||
|
@ -178,13 +178,13 @@ private final class ViewMyQRCodeVC : UIViewController {
|
||||||
// let attributedText = NSMutableAttributedString(string: text)
|
// let attributedText = NSMutableAttributedString(string: text)
|
||||||
// attributedText.addAttribute(.font, value: UIFont.boldSystemFont(ofSize: Values.mediumFontSize), range: (text as NSString).range(of: "your unique public QR code"))
|
// attributedText.addAttribute(.font, value: UIFont.boldSystemFont(ofSize: Values.mediumFontSize), range: (text as NSString).range(of: "your unique public QR code"))
|
||||||
// explanationLabel.attributedText = attributedText
|
// explanationLabel.attributedText = attributedText
|
||||||
explanationLabel.text = NSLocalizedString("This is your QR code. Other users can scan it to start a session with you.", comment: "")
|
explanationLabel.text = NSLocalizedString("vc_view_my_qr_code_explanation", comment: "")
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.textAlignment = .center
|
explanationLabel.textAlignment = .center
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
// Set up share button
|
// Set up share button
|
||||||
let shareButton = Button(style: .regular, size: .large)
|
let shareButton = Button(style: .regular, size: .large)
|
||||||
shareButton.setTitle(NSLocalizedString("Share", comment: ""), for: UIControl.State.normal)
|
shareButton.setTitle(NSLocalizedString("share", comment: ""), for: UIControl.State.normal)
|
||||||
shareButton.addTarget(self, action: #selector(shareQRCode), for: UIControl.Event.touchUpInside)
|
shareButton.addTarget(self, action: #selector(shareQRCode), for: UIControl.Event.touchUpInside)
|
||||||
// Set up share button container
|
// Set up share button container
|
||||||
let shareButtonContainer = UIView()
|
let shareButtonContainer = UIView()
|
||||||
|
@ -232,7 +232,7 @@ private final class ScanQRCodePlaceholderVC : UIViewController {
|
||||||
let explanationLabel = UILabel()
|
let explanationLabel = UILabel()
|
||||||
explanationLabel.textColor = Colors.text
|
explanationLabel.textColor = Colors.text
|
||||||
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
explanationLabel.text = NSLocalizedString("Session needs camera access to scan QR codes", comment: "")
|
explanationLabel.text = NSLocalizedString("vc_scan_qr_code_camera_access_explanation", comment: "")
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.textAlignment = .center
|
explanationLabel.textAlignment = .center
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
|
@ -240,7 +240,7 @@ private final class ScanQRCodePlaceholderVC : UIViewController {
|
||||||
let callToActionButton = UIButton()
|
let callToActionButton = UIButton()
|
||||||
callToActionButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
callToActionButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
||||||
callToActionButton.setTitleColor(Colors.accent, for: UIControl.State.normal)
|
callToActionButton.setTitleColor(Colors.accent, for: UIControl.State.normal)
|
||||||
callToActionButton.setTitle(NSLocalizedString("Enable Camera Access", comment: ""), for: UIControl.State.normal)
|
callToActionButton.setTitle(NSLocalizedString("vc_scan_qr_code_grant_camera_access_button_title", comment: ""), for: UIControl.State.normal)
|
||||||
callToActionButton.addTarget(self, action: #selector(requestCameraAccess), for: UIControl.Event.touchUpInside)
|
callToActionButton.addTarget(self, action: #selector(requestCameraAccess), for: UIControl.Event.touchUpInside)
|
||||||
// Set up stack view
|
// Set up stack view
|
||||||
let stackView = UIStackView(arrangedSubviews: [ explanationLabel, callToActionButton ])
|
let stackView = UIStackView(arrangedSubviews: [ explanationLabel, callToActionButton ])
|
||||||
|
|
|
@ -15,7 +15,7 @@ final class RegisterVC : BaseVC {
|
||||||
|
|
||||||
private lazy var copyPublicKeyButton: Button = {
|
private lazy var copyPublicKeyButton: Button = {
|
||||||
let result = Button(style: .prominentOutline, size: .large)
|
let result = Button(style: .prominentOutline, size: .large)
|
||||||
result.setTitle(NSLocalizedString("Copy", comment: ""), for: UIControl.State.normal)
|
result.setTitle(NSLocalizedString("copy", comment: ""), for: UIControl.State.normal)
|
||||||
result.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
result.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
||||||
result.addTarget(self, action: #selector(copyPublicKey), for: UIControl.Event.touchUpInside)
|
result.addTarget(self, action: #selector(copyPublicKey), for: UIControl.Event.touchUpInside)
|
||||||
return result
|
return result
|
||||||
|
@ -47,14 +47,14 @@ final class RegisterVC : BaseVC {
|
||||||
let titleLabel = UILabel()
|
let titleLabel = UILabel()
|
||||||
titleLabel.textColor = Colors.text
|
titleLabel.textColor = Colors.text
|
||||||
titleLabel.font = .boldSystemFont(ofSize: isIPhone5OrSmaller ? Values.largeFontSize : Values.veryLargeFontSize)
|
titleLabel.font = .boldSystemFont(ofSize: isIPhone5OrSmaller ? Values.largeFontSize : Values.veryLargeFontSize)
|
||||||
titleLabel.text = NSLocalizedString("Say hello to your Session ID", comment: "")
|
titleLabel.text = NSLocalizedString("vc_register_title", comment: "")
|
||||||
titleLabel.numberOfLines = 0
|
titleLabel.numberOfLines = 0
|
||||||
titleLabel.lineBreakMode = .byWordWrapping
|
titleLabel.lineBreakMode = .byWordWrapping
|
||||||
// Set up explanation label
|
// Set up explanation label
|
||||||
let explanationLabel = UILabel()
|
let explanationLabel = UILabel()
|
||||||
explanationLabel.textColor = Colors.text
|
explanationLabel.textColor = Colors.text
|
||||||
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
explanationLabel.text = NSLocalizedString("Your Session ID is the unique address people can use to contact you on Session. With no connection to your real identity, your Session ID is totally anonymous and private by design.", comment: "")
|
explanationLabel.text = NSLocalizedString("vc_register_explanation", comment: "")
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
// Set up public key label container
|
// Set up public key label container
|
||||||
|
@ -69,7 +69,7 @@ final class RegisterVC : BaseVC {
|
||||||
let bottomSpacer = UIView.vStretchingSpacer()
|
let bottomSpacer = UIView.vStretchingSpacer()
|
||||||
// Set up register button
|
// Set up register button
|
||||||
let registerButton = Button(style: .prominentFilled, size: .large)
|
let registerButton = Button(style: .prominentFilled, size: .large)
|
||||||
registerButton.setTitle(NSLocalizedString("Continue", comment: ""), for: UIControl.State.normal)
|
registerButton.setTitle(NSLocalizedString("continue_2", comment: ""), for: UIControl.State.normal)
|
||||||
registerButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
registerButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
||||||
registerButton.addTarget(self, action: #selector(register), for: UIControl.Event.touchUpInside)
|
registerButton.addTarget(self, action: #selector(register), for: UIControl.Event.touchUpInside)
|
||||||
// Set up button stack view
|
// Set up button stack view
|
||||||
|
@ -123,7 +123,7 @@ final class RegisterVC : BaseVC {
|
||||||
@objc private func enableCopyButton() {
|
@objc private func enableCopyButton() {
|
||||||
copyPublicKeyButton.isUserInteractionEnabled = true
|
copyPublicKeyButton.isUserInteractionEnabled = true
|
||||||
UIView.transition(with: copyPublicKeyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
UIView.transition(with: copyPublicKeyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
||||||
self.copyPublicKeyButton.setTitle(NSLocalizedString("Copy", comment: ""), for: UIControl.State.normal)
|
self.copyPublicKeyButton.setTitle(NSLocalizedString("copy", comment: ""), for: UIControl.State.normal)
|
||||||
}, completion: nil)
|
}, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ final class RegisterVC : BaseVC {
|
||||||
UIPasteboard.general.string = keyPair.hexEncodedPublicKey
|
UIPasteboard.general.string = keyPair.hexEncodedPublicKey
|
||||||
copyPublicKeyButton.isUserInteractionEnabled = false
|
copyPublicKeyButton.isUserInteractionEnabled = false
|
||||||
UIView.transition(with: copyPublicKeyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
UIView.transition(with: copyPublicKeyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
||||||
self.copyPublicKeyButton.setTitle(NSLocalizedString("Copied", comment: ""), for: UIControl.State.normal)
|
self.copyPublicKeyButton.setTitle("Copied", for: UIControl.State.normal)
|
||||||
}, completion: nil)
|
}, completion: nil)
|
||||||
Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(enableCopyButton), userInfo: nil, repeats: false)
|
Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(enableCopyButton), userInfo: nil, repeats: false)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ final class RestoreVC : BaseVC {
|
||||||
|
|
||||||
// MARK: Components
|
// MARK: Components
|
||||||
private lazy var mnemonicTextField: TextField = {
|
private lazy var mnemonicTextField: TextField = {
|
||||||
let result = TextField(placeholder: NSLocalizedString("Enter your recovery phrase", comment: ""))
|
let result = TextField(placeholder: NSLocalizedString("vc_restore_seed_text_field_hint", comment: ""))
|
||||||
result.layer.borderColor = Colors.text.cgColor
|
result.layer.borderColor = Colors.text.cgColor
|
||||||
return result
|
return result
|
||||||
}()
|
}()
|
||||||
|
@ -39,14 +39,14 @@ final class RestoreVC : BaseVC {
|
||||||
let titleLabel = UILabel()
|
let titleLabel = UILabel()
|
||||||
titleLabel.textColor = Colors.text
|
titleLabel.textColor = Colors.text
|
||||||
titleLabel.font = .boldSystemFont(ofSize: isIPhone5OrSmaller ? Values.largeFontSize : Values.veryLargeFontSize)
|
titleLabel.font = .boldSystemFont(ofSize: isIPhone5OrSmaller ? Values.largeFontSize : Values.veryLargeFontSize)
|
||||||
titleLabel.text = NSLocalizedString("Restore your account", comment: "")
|
titleLabel.text = NSLocalizedString("vc_restore_title", comment: "")
|
||||||
titleLabel.numberOfLines = 0
|
titleLabel.numberOfLines = 0
|
||||||
titleLabel.lineBreakMode = .byWordWrapping
|
titleLabel.lineBreakMode = .byWordWrapping
|
||||||
// Set up explanation label
|
// Set up explanation label
|
||||||
let explanationLabel = UILabel()
|
let explanationLabel = UILabel()
|
||||||
explanationLabel.textColor = Colors.text
|
explanationLabel.textColor = Colors.text
|
||||||
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
explanationLabel.text = "Enter the recovery phrase that was given to you when you signed up to restore your account."
|
explanationLabel.text = "vc_restore_explanation"
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
// Set up legal label
|
// Set up legal label
|
||||||
|
@ -66,7 +66,7 @@ final class RestoreVC : BaseVC {
|
||||||
restoreButtonBottomOffsetConstraint = restoreButtonBottomOffsetSpacer.set(.height, to: Values.onboardingButtonBottomOffset)
|
restoreButtonBottomOffsetConstraint = restoreButtonBottomOffsetSpacer.set(.height, to: Values.onboardingButtonBottomOffset)
|
||||||
// Set up restore button
|
// Set up restore button
|
||||||
let restoreButton = Button(style: .prominentFilled, size: .large)
|
let restoreButton = Button(style: .prominentFilled, size: .large)
|
||||||
restoreButton.setTitle(NSLocalizedString("Continue", comment: ""), for: UIControl.State.normal)
|
restoreButton.setTitle(NSLocalizedString("continue_2", comment: ""), for: UIControl.State.normal)
|
||||||
restoreButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
restoreButton.titleLabel!.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
||||||
restoreButton.addTarget(self, action: #selector(restore), for: UIControl.Event.touchUpInside)
|
restoreButton.addTarget(self, action: #selector(restore), for: UIControl.Event.touchUpInside)
|
||||||
// Set up restore button container
|
// Set up restore button container
|
||||||
|
|
|
@ -18,7 +18,7 @@ final class SeedModal : Modal {
|
||||||
let titleLabel = UILabel()
|
let titleLabel = UILabel()
|
||||||
titleLabel.textColor = Colors.text
|
titleLabel.textColor = Colors.text
|
||||||
titleLabel.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
titleLabel.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
||||||
titleLabel.text = NSLocalizedString("Your Recovery Phrase", comment: "")
|
titleLabel.text = NSLocalizedString("modal_seed_title", comment: "")
|
||||||
titleLabel.numberOfLines = 0
|
titleLabel.numberOfLines = 0
|
||||||
titleLabel.lineBreakMode = .byWordWrapping
|
titleLabel.lineBreakMode = .byWordWrapping
|
||||||
titleLabel.textAlignment = .center
|
titleLabel.textAlignment = .center
|
||||||
|
@ -34,7 +34,7 @@ final class SeedModal : Modal {
|
||||||
let explanationLabel = UILabel()
|
let explanationLabel = UILabel()
|
||||||
explanationLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
|
explanationLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
|
||||||
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
explanationLabel.text = NSLocalizedString("This is your recovery phrase. With it, you can restore or migrate your Session ID to a new device.", comment: "")
|
explanationLabel.text = NSLocalizedString("modal_seed_explanation", comment: "")
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
explanationLabel.textAlignment = .center
|
explanationLabel.textAlignment = .center
|
||||||
|
@ -45,7 +45,7 @@ final class SeedModal : Modal {
|
||||||
copyButton.backgroundColor = Colors.buttonBackground
|
copyButton.backgroundColor = Colors.buttonBackground
|
||||||
copyButton.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
|
copyButton.titleLabel!.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
copyButton.setTitleColor(Colors.text, for: UIControl.State.normal)
|
copyButton.setTitleColor(Colors.text, for: UIControl.State.normal)
|
||||||
copyButton.setTitle(NSLocalizedString("Copy", comment: ""), for: UIControl.State.normal)
|
copyButton.setTitle(NSLocalizedString("copy", comment: ""), for: UIControl.State.normal)
|
||||||
copyButton.addTarget(self, action: #selector(copySeed), for: UIControl.Event.touchUpInside)
|
copyButton.addTarget(self, action: #selector(copySeed), for: UIControl.Event.touchUpInside)
|
||||||
// Set up button stack view
|
// Set up button stack view
|
||||||
let buttonStackView = UIStackView(arrangedSubviews: [ cancelButton, copyButton ])
|
let buttonStackView = UIStackView(arrangedSubviews: [ cancelButton, copyButton ])
|
||||||
|
|
|
@ -30,7 +30,7 @@ final class SeedVC : BaseVC {
|
||||||
let attributedTitle = NSMutableAttributedString(string: title)
|
let attributedTitle = NSMutableAttributedString(string: title)
|
||||||
attributedTitle.addAttribute(.foregroundColor, value: Colors.accent, range: (title as NSString).range(of: "90%"))
|
attributedTitle.addAttribute(.foregroundColor, value: Colors.accent, range: (title as NSString).range(of: "90%"))
|
||||||
result.title = attributedTitle
|
result.title = attributedTitle
|
||||||
result.subtitle = NSLocalizedString("Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.", comment: "")
|
result.subtitle = NSLocalizedString("view_seed_reminder_subtitle_2", comment: "")
|
||||||
result.setProgress(0.9, animated: false)
|
result.setProgress(0.9, animated: false)
|
||||||
return result
|
return result
|
||||||
}()
|
}()
|
||||||
|
@ -47,7 +47,7 @@ final class SeedVC : BaseVC {
|
||||||
|
|
||||||
private lazy var copyButton: Button = {
|
private lazy var copyButton: Button = {
|
||||||
let result = Button(style: .prominentOutline, size: .large)
|
let result = Button(style: .prominentOutline, size: .large)
|
||||||
result.setTitle(NSLocalizedString("Copy", comment: ""), for: UIControl.State.normal)
|
result.setTitle(NSLocalizedString("copy", comment: ""), for: UIControl.State.normal)
|
||||||
result.addTarget(self, action: #selector(copyMnemonic), for: UIControl.Event.touchUpInside)
|
result.addTarget(self, action: #selector(copyMnemonic), for: UIControl.Event.touchUpInside)
|
||||||
return result
|
return result
|
||||||
}()
|
}()
|
||||||
|
@ -57,7 +57,7 @@ final class SeedVC : BaseVC {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
setUpGradientBackground()
|
setUpGradientBackground()
|
||||||
setUpNavBarStyle()
|
setUpNavBarStyle()
|
||||||
setNavBarTitle(NSLocalizedString("Your Recovery Phrase", comment: ""))
|
setNavBarTitle(NSLocalizedString("vc_seed_title", comment: ""))
|
||||||
// Set up navigation bar buttons
|
// Set up navigation bar buttons
|
||||||
let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close))
|
let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close))
|
||||||
closeButton.tintColor = Colors.text
|
closeButton.tintColor = Colors.text
|
||||||
|
@ -66,14 +66,14 @@ final class SeedVC : BaseVC {
|
||||||
let titleLabel = UILabel()
|
let titleLabel = UILabel()
|
||||||
titleLabel.textColor = Colors.text
|
titleLabel.textColor = Colors.text
|
||||||
titleLabel.font = .boldSystemFont(ofSize: isIPhone5OrSmaller ? Values.largeFontSize : Values.veryLargeFontSize)
|
titleLabel.font = .boldSystemFont(ofSize: isIPhone5OrSmaller ? Values.largeFontSize : Values.veryLargeFontSize)
|
||||||
titleLabel.text = NSLocalizedString("Meet your recovery phrase", comment: "")
|
titleLabel.text = NSLocalizedString("vc_seed_title_2", comment: "")
|
||||||
titleLabel.numberOfLines = 0
|
titleLabel.numberOfLines = 0
|
||||||
titleLabel.lineBreakMode = .byWordWrapping
|
titleLabel.lineBreakMode = .byWordWrapping
|
||||||
// Set up explanation label
|
// Set up explanation label
|
||||||
let explanationLabel = UILabel()
|
let explanationLabel = UILabel()
|
||||||
explanationLabel.textColor = Colors.text
|
explanationLabel.textColor = Colors.text
|
||||||
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
explanationLabel.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
explanationLabel.text = NSLocalizedString("Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don’t give it to anyone.", comment: "")
|
explanationLabel.text = NSLocalizedString("vc_seed_explanation", comment: "")
|
||||||
explanationLabel.numberOfLines = 0
|
explanationLabel.numberOfLines = 0
|
||||||
explanationLabel.lineBreakMode = .byWordWrapping
|
explanationLabel.lineBreakMode = .byWordWrapping
|
||||||
// Set up mnemonic label
|
// Set up mnemonic label
|
||||||
|
@ -93,7 +93,7 @@ final class SeedVC : BaseVC {
|
||||||
let callToActionLabel = UILabel()
|
let callToActionLabel = UILabel()
|
||||||
callToActionLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
|
callToActionLabel.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
|
||||||
callToActionLabel.font = .systemFont(ofSize: isIPhone5OrSmaller ? Values.smallFontSize : Values.mediumFontSize)
|
callToActionLabel.font = .systemFont(ofSize: isIPhone5OrSmaller ? Values.smallFontSize : Values.mediumFontSize)
|
||||||
callToActionLabel.text = NSLocalizedString("Hold to reveal", comment: "")
|
callToActionLabel.text = NSLocalizedString("vc_seed_reveal_button_title", comment: "")
|
||||||
callToActionLabel.textAlignment = .center
|
callToActionLabel.textAlignment = .center
|
||||||
let callToActionLabelGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(revealMnemonic))
|
let callToActionLabelGestureRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(revealMnemonic))
|
||||||
callToActionLabel.addGestureRecognizer(callToActionLabelGestureRecognizer)
|
callToActionLabel.addGestureRecognizer(callToActionLabelGestureRecognizer)
|
||||||
|
@ -144,7 +144,7 @@ final class SeedVC : BaseVC {
|
||||||
@objc private func enableCopyButton() {
|
@objc private func enableCopyButton() {
|
||||||
copyButton.isUserInteractionEnabled = true
|
copyButton.isUserInteractionEnabled = true
|
||||||
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
||||||
self.copyButton.setTitle(NSLocalizedString("Copy", comment: ""), for: UIControl.State.normal)
|
self.copyButton.setTitle(NSLocalizedString("copy", comment: ""), for: UIControl.State.normal)
|
||||||
}, completion: nil)
|
}, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ final class SeedVC : BaseVC {
|
||||||
self.seedReminderView.title = attributedTitle
|
self.seedReminderView.title = attributedTitle
|
||||||
}, completion: nil)
|
}, completion: nil)
|
||||||
UIView.transition(with: seedReminderView.subtitleLabel, duration: 1, options: .transitionCrossDissolve, animations: {
|
UIView.transition(with: seedReminderView.subtitleLabel, duration: 1, options: .transitionCrossDissolve, animations: {
|
||||||
self.seedReminderView.subtitle = NSLocalizedString("Make sure to store your recovery phrase in a safe place", comment: "")
|
self.seedReminderView.subtitle = NSLocalizedString("view_seed_reminder_subtitle_3", comment: "")
|
||||||
}, completion: nil)
|
}, completion: nil)
|
||||||
seedReminderView.setProgress(1, animated: true)
|
seedReminderView.setProgress(1, animated: true)
|
||||||
UserDefaults.standard[.hasViewedSeed] = true
|
UserDefaults.standard[.hasViewedSeed] = true
|
||||||
|
@ -176,7 +176,7 @@ final class SeedVC : BaseVC {
|
||||||
UIPasteboard.general.string = mnemonic
|
UIPasteboard.general.string = mnemonic
|
||||||
copyButton.isUserInteractionEnabled = false
|
copyButton.isUserInteractionEnabled = false
|
||||||
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
||||||
self.copyButton.setTitle(NSLocalizedString("Copied", comment: ""), for: UIControl.State.normal)
|
self.copyButton.setTitle("Copied", for: UIControl.State.normal)
|
||||||
}, completion: nil)
|
}, completion: nil)
|
||||||
Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(enableCopyButton), userInfo: nil, repeats: false)
|
Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(enableCopyButton), userInfo: nil, repeats: false)
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,14 +38,14 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private lazy var displayNameTextField: TextField = {
|
private lazy var displayNameTextField: TextField = {
|
||||||
let result = TextField(placeholder: NSLocalizedString("Enter a display name", comment: ""), usesDefaultHeight: false)
|
let result = TextField(placeholder: NSLocalizedString("vc_settings_display_name_text_field_hint", comment: ""), usesDefaultHeight: false)
|
||||||
result.textAlignment = .center
|
result.textAlignment = .center
|
||||||
return result
|
return result
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private lazy var copyButton: Button = {
|
private lazy var copyButton: Button = {
|
||||||
let result = Button(style: .prominentOutline, size: .medium)
|
let result = Button(style: .prominentOutline, size: .medium)
|
||||||
result.setTitle(NSLocalizedString("Copy", comment: ""), for: UIControl.State.normal)
|
result.setTitle(NSLocalizedString("copy", comment: ""), for: UIControl.State.normal)
|
||||||
result.addTarget(self, action: #selector(copyPublicKey), for: UIControl.Event.touchUpInside)
|
result.addTarget(self, action: #selector(copyPublicKey), for: UIControl.Event.touchUpInside)
|
||||||
return result
|
return result
|
||||||
}()
|
}()
|
||||||
|
@ -55,9 +55,9 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
setUpGradientBackground()
|
setUpGradientBackground()
|
||||||
setUpNavBarStyle()
|
setUpNavBarStyle()
|
||||||
setNavBarTitle(NSLocalizedString("Settings", comment: ""))
|
setNavBarTitle(NSLocalizedString("vc_settings_title", comment: ""))
|
||||||
// Set up navigation bar buttons
|
// Set up navigation bar buttons
|
||||||
let backButton = UIBarButtonItem(title: NSLocalizedString("Back", comment: ""), style: .plain, target: nil, action: nil)
|
let backButton = UIBarButtonItem(title: "Back", style: .plain, target: nil, action: nil)
|
||||||
backButton.tintColor = Colors.text
|
backButton.tintColor = Colors.text
|
||||||
navigationItem.backBarButtonItem = backButton
|
navigationItem.backBarButtonItem = backButton
|
||||||
updateNavigationBarButtons()
|
updateNavigationBarButtons()
|
||||||
|
@ -84,7 +84,7 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
|
||||||
headerStackView.spacing = Values.smallSpacing
|
headerStackView.spacing = Values.smallSpacing
|
||||||
headerStackView.alignment = .center
|
headerStackView.alignment = .center
|
||||||
// Set up separator
|
// Set up separator
|
||||||
let separator = Separator(title: NSLocalizedString("Your Session ID", comment: ""))
|
let separator = Separator(title: NSLocalizedString("your_session_id", comment: ""))
|
||||||
// Set up public key label
|
// Set up public key label
|
||||||
let publicKeyLabel = UILabel()
|
let publicKeyLabel = UILabel()
|
||||||
publicKeyLabel.textColor = Colors.text
|
publicKeyLabel.textColor = Colors.text
|
||||||
|
@ -95,7 +95,7 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
|
||||||
publicKeyLabel.text = userHexEncodedPublicKey
|
publicKeyLabel.text = userHexEncodedPublicKey
|
||||||
// Set up share button
|
// Set up share button
|
||||||
let shareButton = Button(style: .regular, size: .medium)
|
let shareButton = Button(style: .regular, size: .medium)
|
||||||
shareButton.setTitle(NSLocalizedString("Share", comment: ""), for: UIControl.State.normal)
|
shareButton.setTitle(NSLocalizedString("share", comment: ""), for: UIControl.State.normal)
|
||||||
shareButton.addTarget(self, action: #selector(sharePublicKey), for: UIControl.Event.touchUpInside)
|
shareButton.addTarget(self, action: #selector(sharePublicKey), for: UIControl.Event.touchUpInside)
|
||||||
// Set up button container
|
// Set up button container
|
||||||
let buttonContainer = UIStackView(arrangedSubviews: [ copyButton, shareButton ])
|
let buttonContainer = UIStackView(arrangedSubviews: [ copyButton, shareButton ])
|
||||||
|
@ -161,19 +161,19 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
|
||||||
}
|
}
|
||||||
var result = [
|
var result = [
|
||||||
getSeparator(),
|
getSeparator(),
|
||||||
getSettingButton(withTitle: NSLocalizedString("Privacy", comment: ""), color: Colors.text, action: #selector(showPrivacySettings)),
|
getSettingButton(withTitle: NSLocalizedString("vc_settings_privacy_button_title", comment: ""), color: Colors.text, action: #selector(showPrivacySettings)),
|
||||||
getSeparator(),
|
getSeparator(),
|
||||||
getSettingButton(withTitle: NSLocalizedString("Notifications", comment: ""), color: Colors.text, action: #selector(showNotificationSettings))
|
getSettingButton(withTitle: NSLocalizedString("vc_settings_notifications_button_title", comment: ""), color: Colors.text, action: #selector(showNotificationSettings))
|
||||||
]
|
]
|
||||||
let isMasterDevice = UserDefaults.standard.isMasterDevice
|
let isMasterDevice = UserDefaults.standard.isMasterDevice
|
||||||
if isMasterDevice {
|
if isMasterDevice {
|
||||||
result.append(getSeparator())
|
result.append(getSeparator())
|
||||||
result.append(getSettingButton(withTitle: NSLocalizedString("Devices", comment: ""), color: Colors.text, action: #selector(showLinkedDevices)))
|
result.append(getSettingButton(withTitle: NSLocalizedString("vc_settings_devices_button_title", comment: ""), color: Colors.text, action: #selector(showLinkedDevices)))
|
||||||
result.append(getSeparator())
|
result.append(getSeparator())
|
||||||
result.append(getSettingButton(withTitle: NSLocalizedString("Recovery Phrase", comment: ""), color: Colors.text, action: #selector(showSeed)))
|
result.append(getSettingButton(withTitle: NSLocalizedString("vc_settings_recovery_phrase_button_title", comment: ""), color: Colors.text, action: #selector(showSeed)))
|
||||||
}
|
}
|
||||||
result.append(getSeparator())
|
result.append(getSeparator())
|
||||||
result.append(getSettingButton(withTitle: NSLocalizedString("Clear All Data", comment: ""), color: Colors.destructive, action: #selector(clearAllData)))
|
result.append(getSettingButton(withTitle: NSLocalizedString("vc_settings_clear_all_data_button_title", comment: ""), color: Colors.destructive, action: #selector(clearAllData)))
|
||||||
result.append(getSeparator())
|
result.append(getSeparator())
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -182,12 +182,12 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
|
||||||
@objc private func enableCopyButton() {
|
@objc private func enableCopyButton() {
|
||||||
copyButton.isUserInteractionEnabled = true
|
copyButton.isUserInteractionEnabled = true
|
||||||
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
||||||
self.copyButton.setTitle(NSLocalizedString("Copy", comment: ""), for: UIControl.State.normal)
|
self.copyButton.setTitle(NSLocalizedString("copy", comment: ""), for: UIControl.State.normal)
|
||||||
}, completion: nil)
|
}, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func avatarActionSheetTitle() -> String? {
|
func avatarActionSheetTitle() -> String? {
|
||||||
return NSLocalizedString("Update Profile Picture", comment: "")
|
return "Update Profile Picture"
|
||||||
}
|
}
|
||||||
|
|
||||||
func fromViewController() -> UIViewController {
|
func fromViewController() -> UIViewController {
|
||||||
|
@ -199,7 +199,7 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
func clearAvatarActionLabel() -> String {
|
func clearAvatarActionLabel() -> String {
|
||||||
return NSLocalizedString("Clear", comment: "")
|
return "Clear"
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Updating
|
// MARK: Updating
|
||||||
|
@ -266,8 +266,8 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
|
||||||
if let error = error as? DotNetAPI.DotNetAPIError {
|
if let error = error as? DotNetAPI.DotNetAPIError {
|
||||||
isMaxFileSizeExceeded = (error == .maxFileSizeExceeded)
|
isMaxFileSizeExceeded = (error == .maxFileSizeExceeded)
|
||||||
}
|
}
|
||||||
let title = isMaxFileSizeExceeded ? "Maximum File Size Exceeded" : NSLocalizedString("Couldn't Update Profile", comment: "")
|
let title = isMaxFileSizeExceeded ? "Maximum File Size Exceeded" : "Couldn't Update Profile"
|
||||||
let message = isMaxFileSizeExceeded ? "Please select a smaller photo and try again" : NSLocalizedString("Please check your internet connection and try again", comment: "")
|
let message = isMaxFileSizeExceeded ? "Please select a smaller photo and try again" : "Please check your internet connection and try again"
|
||||||
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||||
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
alert.addAction(UIAlertAction(title: NSLocalizedString("OK", comment: ""), style: .default, handler: nil))
|
||||||
self?.present(alert, animated: true, completion: nil)
|
self?.present(alert, animated: true, completion: nil)
|
||||||
|
@ -299,15 +299,15 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
|
||||||
}
|
}
|
||||||
let displayName = displayNameTextField.text!.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
|
let displayName = displayNameTextField.text!.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
|
||||||
guard !displayName.isEmpty else {
|
guard !displayName.isEmpty else {
|
||||||
return showError(title: NSLocalizedString("Please pick a display name", comment: ""))
|
return showError(title: NSLocalizedString("vc_settings_display_name_missing_error", comment: ""))
|
||||||
}
|
}
|
||||||
let allowedCharacters = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_ ")
|
let allowedCharacters = CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_ ")
|
||||||
let hasInvalidCharacters = !displayName.allSatisfy { $0.unicodeScalars.allSatisfy { allowedCharacters.contains($0) } }
|
let hasInvalidCharacters = !displayName.allSatisfy { $0.unicodeScalars.allSatisfy { allowedCharacters.contains($0) } }
|
||||||
guard !hasInvalidCharacters else {
|
guard !hasInvalidCharacters else {
|
||||||
return showError(title: NSLocalizedString("Please pick a display name that consists of only a-z, A-Z, 0-9 and _ characters", comment: ""))
|
return showError(title: NSLocalizedString("vc_settings_invalid_display_name_error", comment: ""))
|
||||||
}
|
}
|
||||||
guard !OWSProfileManager.shared().isProfileNameTooLong(displayName) else {
|
guard !OWSProfileManager.shared().isProfileNameTooLong(displayName) else {
|
||||||
return showError(title: NSLocalizedString("Please pick a shorter display name", comment: ""))
|
return showError(title: NSLocalizedString("vc_settings_display_name_too_long_error", comment: ""))
|
||||||
}
|
}
|
||||||
isEditingDisplayName = false
|
isEditingDisplayName = false
|
||||||
displayNameToBeUploaded = displayName
|
displayNameToBeUploaded = displayName
|
||||||
|
@ -326,7 +326,7 @@ final class SettingsVC : BaseVC, AvatarViewHelperDelegate {
|
||||||
UIPasteboard.general.string = userHexEncodedPublicKey
|
UIPasteboard.general.string = userHexEncodedPublicKey
|
||||||
copyButton.isUserInteractionEnabled = false
|
copyButton.isUserInteractionEnabled = false
|
||||||
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
||||||
self.copyButton.setTitle(NSLocalizedString("Copied", comment: ""), for: UIControl.State.normal)
|
self.copyButton.setTitle("Copied", for: UIControl.State.normal)
|
||||||
}, completion: nil)
|
}, completion: nil)
|
||||||
Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(enableCopyButton), userInfo: nil, repeats: false)
|
Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(enableCopyButton), userInfo: nil, repeats: false)
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,13 +36,13 @@
|
||||||
|
|
||||||
// Loki: Customize title
|
// Loki: Customize title
|
||||||
UILabel *titleLabel = [UILabel new];
|
UILabel *titleLabel = [UILabel new];
|
||||||
titleLabel.text = NSLocalizedString(@"Notifications", @"");
|
titleLabel.text = NSLocalizedString(@"vc_notification_settings_title", @"");
|
||||||
titleLabel.textColor = LKColors.text;
|
titleLabel.textColor = LKColors.text;
|
||||||
titleLabel.font = [UIFont boldSystemFontOfSize:LKValues.veryLargeFontSize];
|
titleLabel.font = [UIFont boldSystemFontOfSize:LKValues.veryLargeFontSize];
|
||||||
self.navigationItem.titleView = titleLabel;
|
self.navigationItem.titleView = titleLabel;
|
||||||
|
|
||||||
// Loki: Set up back button
|
// Loki: Set up back button
|
||||||
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Back", "") style:UIBarButtonItemStylePlain target:nil action:nil];
|
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStylePlain target:nil action:nil];
|
||||||
backButton.tintColor = LKColors.text;
|
backButton.tintColor = LKColors.text;
|
||||||
self.navigationItem.backBarButtonItem = backButton;
|
self.navigationItem.backBarButtonItem = backButton;
|
||||||
}
|
}
|
||||||
|
@ -65,8 +65,8 @@
|
||||||
OWSPreferences *prefs = Environment.shared.preferences;
|
OWSPreferences *prefs = Environment.shared.preferences;
|
||||||
|
|
||||||
OWSTableSection *strategySection = [OWSTableSection new];
|
OWSTableSection *strategySection = [OWSTableSection new];
|
||||||
strategySection.headerTitle = NSLocalizedString(@"Notification Strategy", @"");
|
strategySection.headerTitle = NSLocalizedString(@"preferences_notifications_strategy_category_title", @"");
|
||||||
[strategySection addItem:[OWSTableItem switchItemWithText:NSLocalizedString(@"Use APNs", @"")
|
[strategySection addItem:[OWSTableItem switchItemWithText:NSLocalizedString(@"preferences_notifications_use_apns_option_title", @"")
|
||||||
accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, @"push_notification_strategy")
|
accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, @"push_notification_strategy")
|
||||||
isOnBlock:^{
|
isOnBlock:^{
|
||||||
return [NSUserDefaults.standardUserDefaults boolForKey:@"isUsingFullAPNs"];
|
return [NSUserDefaults.standardUserDefaults boolForKey:@"isUsingFullAPNs"];
|
||||||
|
@ -76,7 +76,7 @@
|
||||||
}
|
}
|
||||||
target:weakSelf
|
target:weakSelf
|
||||||
selector:@selector(didToggleAPNsSwitch:)]];
|
selector:@selector(didToggleAPNsSwitch:)]];
|
||||||
strategySection.footerTitle = NSLocalizedString(@"Session will use the Apple Push Notification service to receive push notifications. You'll be notified of new messages reliably and immediately. Using APNs means that your IP address and device token will be exposed to Apple. If you use push notifications for other apps, this will already be the case. Your IP address and device token will also be exposed to Loki, but your messages will still be onion-routed and end-to-end encrypted, so the contents of your messages will remain completely private.", @"");
|
strategySection.footerTitle = NSLocalizedString(@"preferences_notifications_use_apns_option_explanation", @"");
|
||||||
[contents addSection:strategySection];
|
[contents addSection:strategySection];
|
||||||
|
|
||||||
// Sounds section.
|
// Sounds section.
|
||||||
|
|
|
@ -43,7 +43,7 @@ static NSString *const kSealedSenderInfoURL = @"https://signal.org/blog/sealed-s
|
||||||
|
|
||||||
// Loki: Customize title
|
// Loki: Customize title
|
||||||
UILabel *titleLabel = [UILabel new];
|
UILabel *titleLabel = [UILabel new];
|
||||||
titleLabel.text = NSLocalizedString(@"Privacy", @"");
|
titleLabel.text = NSLocalizedString(@"vc_privacy_settings_title", @"");
|
||||||
titleLabel.textColor = LKColors.text;
|
titleLabel.textColor = LKColors.text;
|
||||||
titleLabel.font = [UIFont boldSystemFontOfSize:LKValues.veryLargeFontSize];
|
titleLabel.font = [UIFont boldSystemFontOfSize:LKValues.veryLargeFontSize];
|
||||||
self.navigationItem.titleView = titleLabel;
|
self.navigationItem.titleView = titleLabel;
|
||||||
|
@ -538,11 +538,11 @@ static NSString *const kSealedSenderInfoURL = @"https://signal.org/blog/sealed-s
|
||||||
{
|
{
|
||||||
BOOL isOn = sender.isOn;
|
BOOL isOn = sender.isOn;
|
||||||
if (isOn) {
|
if (isOn) {
|
||||||
NSString *title = NSLocalizedString(@"Enable Link Previews?", @"");
|
NSString *title = @"Enable Link Previews?";
|
||||||
NSString *message = NSLocalizedString(@"You will not have full metadata protection when sending or receiving link previews.", @"");
|
NSString *message = @"You will not have full metadata protection when sending or receiving link previews.";
|
||||||
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
|
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"") style:UIAlertActionStyleDefault handler:nil]];
|
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"") style:UIAlertActionStyleDefault handler:nil]];
|
||||||
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", @"") style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"cancel", @"") style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
|
||||||
[sender setOn:NO animated:YES];
|
[sender setOn:NO animated:YES];
|
||||||
SSKPreferences.areLinkPreviewsEnabled = NO;
|
SSKPreferences.areLinkPreviewsEnabled = NO;
|
||||||
}]];
|
}]];
|
||||||
|
|
|
@ -2554,296 +2554,208 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// MARK: - Loki Messenger:
|
|
||||||
"Session can let you know when you get a message (and who it is from)" = "Session can let you know when you get a message (and who it is from)";
|
|
||||||
"Create Your Session Account" = "Create Your Session Account";
|
|
||||||
"Enter a name to be shown to your contacts" = "Enter a name to be shown to your contacts";
|
|
||||||
"Display Name" = "Display Name";
|
|
||||||
"Type an optional password for added security" = "Type an optional password for added security";
|
|
||||||
"Password (Optional)" = "Password (Optional)";
|
|
||||||
"Next" = "Next";
|
|
||||||
"Add" = "Add";
|
|
||||||
"Please save the seed below in a safe location. It can be used to restore your account if you lose access, or to migrate your account to a new device." = "Please save the seed below in a safe location. It can be used to restore your account if you lose access, or to migrate your account to a new device.";
|
|
||||||
"Restore your account by entering your seed below." = "Restore your account by entering your seed below.";
|
|
||||||
"Copy" = "Copy";
|
|
||||||
"Copied ✓" = "Copied ✓";
|
|
||||||
"Restore Using Seed" = "Restore Using Seed";
|
|
||||||
"Register" = "Register";
|
|
||||||
"Enter Your Seed" = "Enter Your Seed";
|
|
||||||
"Register a New Account" = "Register a New Account";
|
|
||||||
"Restore" = "Restore";
|
|
||||||
"Something went wrong. Please check your seed and try again." = "Something went wrong. Please check your seed and try again.";
|
|
||||||
"Looks like you didn't enter enough words. Please check your seed and try again." = "Looks like you didn't enter enough words. Please check your seed and try again.";
|
|
||||||
"You seem to be missing the last word of your seed. Please check what you entered and try again." = "You seem to be missing the last word of your seed. Please check what you entered and try again.";
|
|
||||||
"There appears to be an invalid word in your seed. Please check what you entered and try again." = "There appears to be an invalid word in your seed. Please check what you entered and try again.";
|
|
||||||
"Your seed couldn't be verified. Please check what you entered and try again." = "Your seed couldn't be verified. Please check what you entered and try again.";
|
|
||||||
"Search by public key" = "Search by public key";
|
|
||||||
"Start a Conversation" = "Start a Conversation";
|
|
||||||
"Invalid Session ID" = "Invalid Session ID";
|
|
||||||
"No search results" = "No search results";
|
|
||||||
"Calculating proof of work" = "Calculating proof of work";
|
|
||||||
"Failed to calculate proof of work." = "Failed to calculate proof of work.";
|
|
||||||
"Share Public Key" = "Share Public Key";
|
|
||||||
"%@ sent you a session request" = "%@ sent you a session request";
|
|
||||||
"Accept" = "Accept";
|
|
||||||
"Decline" = "Decline";
|
|
||||||
"Pending session request" = "Pending session request";
|
|
||||||
"New Message" = "New Message";
|
|
||||||
"Secure session reset in progress" = "Secure session reset in progress";
|
|
||||||
"Secure session reset done" = "Secure session reset done";
|
|
||||||
"Session" = "Session";
|
|
||||||
"You've sent %@ a session request" = "You've sent %@ a session request";
|
|
||||||
"You've declined %@'s session request" = "You've declined %@'s session request";
|
|
||||||
"You've accepted %@'s session request" = "You've accepted %@'s session request";
|
|
||||||
"%@ accepted your session request" = "%@ accepted your session request";
|
|
||||||
"%@'s session request has expired" = "%@'s session request has expired";
|
|
||||||
"Your session request to %@ has expired" = "Your session request to %@ has expired";
|
|
||||||
"Show Seed" = "Show Seed";
|
|
||||||
"Your Seed" = "Your Seed";
|
|
||||||
"Require Touch ID, Face ID or your device passcode to unlock Session’s screen. You can still receive notifications when Screen Lock is enabled. Use Session’s notification settings to customise the information displayed in notifications." = "Require Touch ID, Face ID or your device passcode to unlock Session’s screen. You can still receive notifications when Screen Lock is enabled. Use Session’s notification settings to customise the information displayed in notifications.";
|
|
||||||
"Prevent Session previews from appearing in the app switcher." = "Prevent Session previews from appearing in the app switcher.";
|
|
||||||
"Session" = "Session";
|
|
||||||
"Privacy Policy" = "Privacy Policy";
|
|
||||||
"New Session" = "New Session";
|
|
||||||
"Add Public Chat Server" = "Add Public Chat Server";
|
|
||||||
"Enter a Public Key" = "Enter a Public Key";
|
|
||||||
"Enter a Server URL" = "Enter a Server URL";
|
|
||||||
"For example: 059abcf223aa8c10e3dc2d623688b75dd25896794717e4a9c486772664fc95e41e." = "For example: 059abcf223aa8c10e3dc2d623688b75dd25896794717e4a9c486772664fc95e41e.";
|
|
||||||
"Invalid Session ID" = "Invalid Session ID";
|
|
||||||
"Please check the Session ID and try again" = "Please check the Session ID and try again";
|
|
||||||
"Looks like you don't have any conversations yet. Get started by messaging a friend." = "Looks like you don't have any conversations yet. Get started by messaging a friend.";
|
|
||||||
"Enter the public key of the person you'd like to securely message. They can share their public key with you by going into Session's in-app settings and clicking \"Share Public Key\"." = "Enter the public key of the person you'd like to securely message. They can share their public key with you by going into Session's in-app settings and clicking \"Share Public Key\".";
|
|
||||||
"Unlock Session" = "Unlock Session";
|
|
||||||
"Clear All Data" = "Clear All Data";
|
|
||||||
"Are you sure you want to clear all your data? This will delete your entire account, including all conversations and your personal key pair." = "Are you sure you want to clear all your data? This will delete your entire account, including all conversations and your personal key pair.";
|
|
||||||
"Cancel" = "Cancel";
|
|
||||||
"Update Required" = "Update Required";
|
|
||||||
"This version of Session is no longer supported. Please press OK to reset your account and migrate to the latest version." = "This version of Session is no longer supported. Please press OK to reset your account and migrate to the latest version.";
|
|
||||||
"Loki Public Chat" = "Loki Public Chat";
|
|
||||||
"Loki News" = "Loki News";
|
|
||||||
"Session Updates" = "Session Updates";
|
|
||||||
"Show QR Code" = "Show QR Code";
|
|
||||||
"This is your QR code. Other people can scan it to start a secure conversation with you." = "This is your QR code. Other people can scan it to start a secure conversation with you.";
|
|
||||||
"Scan a QR Code Instead" = "Scan a QR Code Instead";
|
|
||||||
"Session needs camera access to scan QR codes." = "Session needs camera access to scan QR codes.";
|
|
||||||
"You can enable camera access in your device settings." = "You can enable camera access in your device settings.";
|
|
||||||
"Scan QR Code" = "Scan QR Code";
|
|
||||||
"Loki" = "Loki";
|
|
||||||
"Can't Start Conversation" = "Can't Start Conversation";
|
|
||||||
"Please enter the public key of the person you'd like to message." = "Please enter the public key of the person you'd like to message.";
|
|
||||||
"Session is currently in beta. For development purposes the beta version collects basic usage statistics and crash logs. In addition, the beta version doesn't yet provide full privacy and shouldn't be used to transmit sensitive information." = "Session is currently in beta. For development purposes the beta version collects basic usage statistics and crash logs. In addition, the beta version doesn't yet provide full privacy and shouldn't be used to transmit sensitive information.";
|
|
||||||
"Copy Public Key" = "Copy Public Key";
|
|
||||||
"Link Device" = "Link Device";
|
|
||||||
"Waiting for Device" = "Waiting for Device";
|
|
||||||
"Waiting for Authorization" = "Waiting for Authorization";
|
|
||||||
"Create a new account on your other device and click \"Link Device\" when you're at the \"Create Your Session Account\" step to start the linking process" = "Create a new account on your other device and click \"Link Device\" when you're at the \"Create Your Session Account\" step to start the linking process";
|
|
||||||
"Linking Request Received" = "Linking Request Received";
|
|
||||||
"Invalid Session ID" = "Invalid Session ID";
|
|
||||||
"Please check that the words below match those shown on your other device" = "Please check that the words below match those shown on your other device";
|
|
||||||
"Link to an existing device by going into its in-app settings and clicking \"Link Device\"." = "Link to an existing device by going into its in-app settings and clicking \"Link Device\".";
|
|
||||||
"Authorize" = "Authorize";
|
|
||||||
"Enter the Other Device's Public Key" = "Enter the Other Device's Public Key";
|
|
||||||
"This is your personal secret. It can be used to restore your account if you lose access, or to migrate your account to a new device." = "This is your personal secret. It can be used to restore your account if you lose access, or to migrate your account to a new device.";
|
|
||||||
"Device Link Authorized" = "Device Link Authorized";
|
|
||||||
"Your device has been linked successfully" = "Your device has been linked successfully";
|
|
||||||
"Link" = "Link";
|
|
||||||
"Anonymous" = "Anonymous";
|
|
||||||
"Invalid URL" = "Invalid URL";
|
|
||||||
"Please check the URL you entered and try again." = "Please check the URL you entered and try again.";
|
|
||||||
"Please pick a shorter display name" = "Please pick a shorter display name";
|
|
||||||
"Please pick a display name" = "Please pick a display name";
|
|
||||||
"Add Public Chat" = "Add Public Chat";
|
|
||||||
"Enter a URL" = "Enter a URL";
|
|
||||||
"Enter the URL of the public chat you'd like to join. The Loki Public Chat URL is https://chat.lokinet.org." = "Enter the URL of the public chat you'd like to join. The Loki Public Chat URL is https://chat.lokinet.org.";
|
|
||||||
"Connecting..." = "Connecting...";
|
|
||||||
"Couldn't Connect" = "Couldn't Connect";
|
|
||||||
"Please pick a display name that consists of only a-z, A-Z, 0-9 and _ characters" = "Please pick a display name that consists of only a-z, A-Z, 0-9 and _ characters";
|
|
||||||
"Multi Device Limit Reached" = "Multi Device Limit Reached";
|
|
||||||
"It's currently not allowed to link more than one device." = "It's currently not allowed to link more than one device.";
|
|
||||||
"Profile Picture" = "Profile Picture";
|
|
||||||
"Set Profile Picture" = "Set Profile Picture";
|
|
||||||
"Clear Profile Picture" = "Clear Profile Picture";
|
|
||||||
"Invalid QR Code" = "Invalid QR Code";
|
|
||||||
"Please make sure the QR code you scanned is correct and try again." = "Please make sure the QR code you scanned is correct and try again.";
|
|
||||||
"Devices" = "Devices";
|
|
||||||
"You haven't linked any devices yet" = "You haven't linked any devices yet";
|
|
||||||
"Link a Device (Beta)" = "Link a Device (Beta)";
|
|
||||||
"Unlink" = "Unlink";
|
|
||||||
"Change Name" = "Change Name";
|
|
||||||
"Change Device Name" = "Change Device Name";
|
|
||||||
"Enter the new display name for your device below" = "Enter the new display name for your device below";
|
|
||||||
"Enter a Name" = "Enter a Name";
|
|
||||||
"Error" = "Error";
|
|
||||||
"Please pick a name" = "Please pick a name";
|
|
||||||
"Couldn't Link Device" = "Couldn't Link Device";
|
|
||||||
"Couldn't Unlink Device" = "Couldn't Unlink Device";
|
|
||||||
"Please check your internet connection and try again" = "Please check your internet connection and try again";
|
|
||||||
"Device Unlinked" = "Device Unlinked";
|
|
||||||
"Your device was unlinked successfully" = "Your device was unlinked successfully";
|
|
||||||
"Unnamed Device" = "Unnamed Device";
|
|
||||||
"Linked device (%@)" = "Linked device (%@)";
|
|
||||||
"Restore session" = "Restore session";
|
|
||||||
"Would you like to start a new session with %@?" = "Would you like to start a new session with %@?";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// MARK: - Session
|
// MARK: - Session
|
||||||
"Messages" = "Messages";
|
"continue_2" = "Continue";
|
||||||
"Note to Self" = "Note to Self";
|
"copy" = "Copy";
|
||||||
"New Group" = "New Group";
|
"invalid_url" = "Invalid URL";
|
||||||
"Delete" = "Delete";
|
"copied_to_clipboard" = "Copied to clipboard";
|
||||||
"Search" = "Search";
|
"device_linking_failed" = "Couldn't link device.";
|
||||||
"New Session" = "New Session";
|
"next" = "Next";
|
||||||
"Enter a Session ID" = "Enter a Session ID";
|
"share" = "Share";
|
||||||
"Users can share their Session ID from their account settings, or by sharing their QR code." = "Users can share their Session ID from their account settings, or by sharing their QR code.";
|
"invalid_session_id" = "Invalid Session ID";
|
||||||
"Scan a user’s QR code to start a session. QR codes can be found by tapping the QR code icon in account settings." = "Scan a user’s QR code to start a session. QR codes can be found by tapping the QR code icon in account settings.";
|
"cancel" = "Cancel";
|
||||||
"Your Session ID" = "Your Session ID";
|
"your_session_id" = "Your Session ID";
|
||||||
"Copy" = "Copy";
|
|
||||||
"Copied" = "Copied";
|
"vc_landing_title_2" = "Your Session begins here...";
|
||||||
"Share" = "Share";
|
"vc_landing_register_button_title" = "Create Session ID";
|
||||||
"Next" = "Next";
|
"vc_landing_restore_button_title" = "Continue Your Session";
|
||||||
"Session needs camera access to scan QR codes" = "Session needs camera access to scan QR codes";
|
"vc_landing_link_button_title" = "Link to an existing account";
|
||||||
"Enable Camera Access" = "Enable Camera Access";
|
"vc_landing_device_unlinked_modal_title" = "Your device was unlinked successfully";
|
||||||
"Scan the QR code of the person you'd like to securely message. They can find their QR code by going into Session's in-app settings and tapping \"Show QR Code\"." = "Scan the QR code of the person you'd like to securely message. They can find their QR code by going into Session's in-app settings and tapping \"Show QR Code\".";
|
|
||||||
"Enter Session ID" = "Enter Session ID";
|
"view_fake_chat_bubble_1" = "What's Session?";
|
||||||
"Open Group URL" = "Open Group URL";
|
"view_fake_chat_bubble_2" = "It's a decentralized, encrypted messaging app";
|
||||||
"Scan QR Code" = "Scan QR Code";
|
"view_fake_chat_bubble_3" = "So it doesn't collect my personal information or my conversation metadata? How does it work?";
|
||||||
"Scan the QR code of the open group you'd like to join" = "Scan the QR code of the open group you'd like to join";
|
"view_fake_chat_bubble_4" = "Using a combination of advanced anonymous routing and end-to-end encryption technologies.";
|
||||||
"Join Open Group" = "Join Open Group";
|
"view_fake_chat_bubble_5" = "Friends don't let friends use compromised messengers. You're welcome.";
|
||||||
"Enter an open group URL" = "Enter an open group URL";
|
|
||||||
"Invalid URL" = "Invalid URL";
|
"vc_register_title" = "Say hello to your Session ID";
|
||||||
"Please check the URL you entered and try again" = "Please check the URL you entered and try again";
|
"vc_register_explanation" = "Your Session ID is the unique address people can use to contact you on Session. With no connection to your real identity, your Session ID is totally anonymous and private by design.";
|
||||||
"Couldn't Join" = "Couldn't Join";
|
"vc_register_public_key_copied_message" = "Copied to clipboard";
|
||||||
"Settings" = "Settings";
|
|
||||||
"Privacy" = "Privacy";
|
"vc_restore_title" = "Restore your account";
|
||||||
"Notifications" = "Notifications";
|
"vc_restore_explanation" = "Enter the recovery phrase that was given to you when you signed up to restore your account.";
|
||||||
"Devices" = "Devices";
|
"vc_restore_seed_text_field_hint" = "Enter your recovery phrase";
|
||||||
"Recovery Phrase" = "Recovery Phrase";
|
|
||||||
"Clear All Data" = "Clear All Data";
|
"vc_link_device_title" = "Link Device";
|
||||||
"This will permanently delete your messages, sessions, and contacts." = "This will permanently delete your messages, sessions, and contacts.";
|
"vc_link_device_enter_session_id_tab_title" = "Enter Session ID";
|
||||||
"Delete" = "Delete";
|
"vc_link_device_scan_qr_code_tab_title" = "Scan QR Code";
|
||||||
"This is your recovery phrase. With it, you can restore or migrate your Session ID to a new device." = "This is your recovery phrase. With it, you can restore or migrate your Session ID to a new device.";
|
"vc_link_device_scan_qr_code_explanation" = "Navigate to \"Settings\" > \"Devices\" > \"Link a Device\" on your other device and then scan the QR code that comes up to start the linking process.";
|
||||||
"The information shown in notifications when your phone is locked." = "The information shown in notifications when your phone is locked.";
|
|
||||||
"Notifications" = "Notifications";
|
"vc_enter_session_id_title" = "Link your device";
|
||||||
"Back" = "Back";
|
"vc_enter_session_id_explanation" = "Navigate to \"Settings\" > \"Devices\" > \"Link a Device\" on your other device and then enter your Session ID here to start the linking process.";
|
||||||
"View My QR Code" = "View My QR Code";
|
"vc_enter_session_id_text_field_hint" = "Enter your Session ID";
|
||||||
"Scan someone's QR code to start a conversation with them" = "Scan someone's QR code to start a conversation with them";
|
|
||||||
"QR Code" = "QR Code";
|
"vc_display_name_title_2" = "Pick your display name";
|
||||||
"Scan Me" = "Scan Me";
|
"vc_display_name_explanation" = "This will be your name when you use Session. It can be your real name, an alias, or anything else you like.";
|
||||||
"This is your QR code. Other users can scan it to start a session with you." = "This is your QR code. Other users can scan it to start a session with you.";
|
"vc_display_name_text_field_hint" = "Enter a display name";
|
||||||
"Privacy" = "Privacy";
|
"vc_display_name_display_name_missing_error" = "Please pick a display name";
|
||||||
"Unlock Session's screen using Touch ID, Face ID, or your iOS device passcode. You can still receive message notifications while Screen Lock is enabled. Session's notification settings allow you to customize the information that is displayed." = "Unlock Session's screen using Touch ID, Face ID, or your iOS device passcode. You can still receive message notifications while Screen Lock is enabled. Session's notification settings allow you to customize the information that is displayed.";
|
"vc_display_name_display_name_invalid_error" = "Please pick a display name that consists of only a-z, A-Z, 0-9 and _ characters";
|
||||||
"Sound" = "Sound";
|
"vc_display_name_display_name_too_long_error" = "Please pick a shorter display name";
|
||||||
"Content" = "Content";
|
|
||||||
"Update Profile Picture" = "Update Profile Picture";
|
"vc_pn_mode_title" = "Push Notifications";
|
||||||
"Couldn't Update Profile Picture" = "Couldn't Update Profile Picture";
|
"vc_pn_mode_explanation" = "There are two ways Session can handle push notifications. Make sure to read the descriptions carefully before you choose.";
|
||||||
"Clear" = "Clear";
|
"vc_pn_mode_apns_option_title" = "Apple Push Notification Service";
|
||||||
"Enter a display name" = "Enter a display name";
|
"vc_pn_mode_apns_option_explanation" = "Session will use the Apple Push Notification Service service to receive push notifications. You'll be notified of new messages reliably and immediately. Using APNs means that your IP address and device token will be exposed to Apple. If you use push notifications for other apps, this will already be the case. Your IP address and device token will also be exposed to Loki, but your messages will still be onion-routed and end-to-end encrypted, so the contents of your messages will remain completely private.";
|
||||||
"Your Session begins here..." = "Your Session begins here...";
|
"vc_pn_mode_background_polling_option_title" = "Background Polling";
|
||||||
"What's Session?" = "What's Session?";
|
"vc_pn_mode_background_polling_option_explanation" = "Session will occasionally check for new messages in the background. This guarantees full metadata protection, but message notifications may be significantly delayed.";
|
||||||
"It's a decentralized, encrypted messaging app." = "It's a decentralized, encrypted messaging app.";
|
"vc_pn_mode_recommended_option_tag" = "Recommended";
|
||||||
"So it doesn't collect my personal information or my conversation metadata? How does it work?" = "So it doesn't collect my personal information or my conversation metadata? How does it work?";
|
"vc_pn_mode_no_option_picked_modal_title" = "Please Pick an Option";
|
||||||
"Using a combination of advanced anonymous routing and end-to-end encryption technologies." = "Using a combination of advanced anonymous routing and end-to-end encryption technologies.";
|
|
||||||
"Friends don't let friends use compromised messengers. You're welcome." = "Friends don't let friends use compromised messengers. You're welcome.";
|
"vc_home_empty_state_message" = "You don't have any contacts yet";
|
||||||
"Create Session ID" = "Create Session ID";
|
"vc_home_empty_state_button_title" = "Start a Session";
|
||||||
"Continue your Session" = "Continue your Session";
|
"vc_home_leave_group_modal_message" = "Are you sure you want to leave this group?";
|
||||||
"Say hello to your Session ID" = "Say hello to your Session ID";
|
"vc_home_leaving_group_failed_message" = "Couldn't leave group";
|
||||||
"Continue" = "Continue";
|
"vc_home_delete_conversation_modal_message" = "Are you sure you want to delete this conversation?";
|
||||||
"Copy Session ID" = "Copy Session ID";
|
"vc_home_conversation_deleted_message" = "Conversation deleted";
|
||||||
"Pick your display name" = "Pick your display name";
|
|
||||||
"Enter a display name" = "Enter a display name";
|
"sheet_pn_mode_title" = "Push Notifications";
|
||||||
"Restore your account" = "Restore your account";
|
"sheet_pn_mode_explanation" = "Session now features two ways to handle push notifications. Make sure to read the descriptions carefully before you choose.";
|
||||||
"Enter your recovery phrase" = "Enter your recovery phrase";
|
"sheet_pn_mode_apns_option_title" = "Apple Push Notification Service";
|
||||||
"Message" = "Message";
|
"sheet_pn_mode_apns_option_explanation" = "Session will use the Apple Push Notification Service service to receive push notifications. You'll be notified of new messages reliably and immediately. Using APNs means that your IP address and device token will be exposed to Apple. If you use push notifications for other apps, this will already be the case. Your IP address and device token will also be exposed to Loki, but your messages will still be onion-routed and end-to-end encrypted, so the contents of your messages will remain completely private.";
|
||||||
"You" = "You";
|
"sheet_pn_mode_background_polling_option_title" = "Background Polling";
|
||||||
"Encrypting message" = "Encrypting message";
|
"sheet_pn_mode_background_polling_option_explanation" = "Session will occasionally check for new messages in the background. This guarantees full metadata protection, but message notifications may be significantly delayed.";
|
||||||
"Tracing a path" = "Tracing a path";
|
"sheet_pn_mode_recommended_option_tag" = "Recommended";
|
||||||
"Sending message" = "Sending message";
|
"sheet_pn_mode_no_option_picked_modal_title" = "Please Pick an Option";
|
||||||
"Message sent securely" = "Message sent securely";
|
"sheet_pn_mode_confirm_button_title" = "Confirm";
|
||||||
"Message failed to send" = "Message failed to send";
|
"sheet_pn_mode_skip_button_title" = "Skip";
|
||||||
"Secure your account by saving your recovery phrase" = "Secure your account by saving your recovery phrase";
|
|
||||||
"Continue" = "Continue";
|
"vc_seed_title" = "Your Recovery Phrase";
|
||||||
"Your Recovery Phrase" = "Your Recovery Phrase";
|
"vc_seed_title_2" = "Meet your recovery phrase";
|
||||||
"Meet your recovery phrase" = "Meet your recovery phrase";
|
"vc_seed_explanation" = "Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don’t give it to anyone.";
|
||||||
"Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don’t give it to anyone." = "Your recovery phrase is the master key to your Session ID — you can use it to restore your Session ID if you lose access to your device. Store your recovery phrase in a safe place, and don’t give it to anyone.";
|
"vc_seed_reveal_button_title" = "Hold to reveal";
|
||||||
"Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID." = "Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.";
|
|
||||||
"Hold to reveal" = "Hold to reveal";
|
"view_seed_reminder_subtitle_1" = "Secure your account by saving your recovery phrase";
|
||||||
"Make sure to store your recovery phrase in a safe place" = "Make sure to store your recovery phrase in a safe place";
|
"view_seed_reminder_subtitle_2" = "Tap and hold the redacted words to reveal your recovery phrase, then store it safely to secure your Session ID.";
|
||||||
"Link to an existing account" = "Link to an existing account";
|
"view_seed_reminder_subtitle_3" = "Make sure to store your recovery phrase in a safe place";
|
||||||
"Enter your public key" = "Enter your public key";
|
|
||||||
"Link to your existing account by going into your in-app settings and clicking \"Devices\"." = "Link to your existing account by going into your in-app settings and clicking \"Devices\".";
|
"vc_path_title" = "Path";
|
||||||
"Download Session on your other device and tap \"Link to an existing account\" at the bottom of the landing screen. If you have an existing account on your other device already you will have to delete that account first." = "Download Session on your other device and tap \"Link to an existing account\" at the bottom of the landing screen. If you have an existing account on your other device already you will have to delete that account first.";
|
"vc_path_explanation" = "Session hides your IP by bouncing your messages through several Service Nodes in Session's decentralized network. These are the countries your connection is currently being bounced through:";
|
||||||
"Group Settings" = "Group Settings";
|
"vc_path_device_row_title" = "You";
|
||||||
"Your Session ID is the unique address people can use to contact you on Session. With no connection to your real identity, your Session ID is totally anonymous and private by design." = "Your Session ID is the unique address people can use to contact you on Session. With no connection to your real identity, your Session ID is totally anonymous and private by design.";
|
"vc_path_guard_node_row_title" = "Entry Node";
|
||||||
"Enter the recovery phrase that was given to you when you signed up to restore your account." = "Enter the recovery phrase that was given to you when you signed up to restore your account.";
|
"vc_path_service_node_row_title" = "Service Node";
|
||||||
"Enter Session ID" = "Enter Session ID";
|
"vc_path_destination_row_title" = "Destination";
|
||||||
"Link your device" = "Link your device";
|
"vc_path_learn_more_button_title" = "Learn More";
|
||||||
"Enter your Session ID to start the linking process." = "Enter your Session ID to start the linking process.";
|
|
||||||
"Enter your Session ID" = "Enter your Session ID";
|
"vc_create_private_chat_title" = "New Session";
|
||||||
"Recent Chats" = "Recent Chats";
|
"vc_create_private_chat_enter_session_id_tab_title" = "Enter Session ID";
|
||||||
"Other Chats" = "Other Chats";
|
"vc_create_private_chat_scan_qr_code_tab_title" = "Scan QR Code";
|
||||||
"See and share when messages are being typed (applies to all sessions)." = "See and share when messages are being typed (applies to all sessions).";
|
"vc_create_private_chat_scan_qr_code_explanation" = "Scan a user’s QR code to start a session. QR codes can be found by tapping the QR code icon in account settings.";
|
||||||
"Disable Preview in App Switcher" = "Disable Preview in App Switcher";
|
|
||||||
"Are you sure? This cannot be undone." = "Are you sure? This cannot be undone.";
|
"vc_enter_public_key_text_field_hint" = "Enter Session ID of recipient";
|
||||||
"When enabled, messages between you and %@ will disappear after they have been seen." = "When enabled, messages between you and %@ will disappear after they have been seen.";
|
"vc_enter_public_key_explanation" = "Users can share their Session ID by going into their account settings and tapping \"Share Session ID\", or by sharing their QR code.";
|
||||||
"This will be your name when you use Session. It can be your real name, an alias, or anything else you like." = "This will be your name when you use Session. It can be your real name, an alias, or anything else you like.";
|
|
||||||
"Session Out of Sync" = "Session Out of Sync";
|
"vc_scan_qr_code_camera_access_explanation" = "Session needs camera access to scan QR codes";
|
||||||
"Would you like to restore your session? This can help resolve issues. Your messages will be preserved." = "Would you like to restore your session? This can help resolve issues. Your messages will be preserved.";
|
"vc_scan_qr_code_grant_camera_access_button_title" = "Grant Camera Access";
|
||||||
"Would you like to restore your session with %@? This can help resolve issues. Your messages will be preserved." = "Would you like to restore your session with %@? This can help resolve issues. Your messages will be preserved.";
|
|
||||||
"Restore" = "Restore";
|
"vc_create_closed_group_title" = "New Closed Group";
|
||||||
"Dismiss" = "Dismiss";
|
"vc_create_closed_group_text_field_hint" = "Enter a group name";
|
||||||
"New Closed Group" = "New Closed Group";
|
"vc_create_closed_group_explanation" = "Closed groups support up to 10 members and provide the same privacy protections as one-on-one sessions.";
|
||||||
"Group Members" = "Group Members";
|
"vc_create_closed_group_empty_state_message" = "You don't have any contacts yet";
|
||||||
"You don't have any contacts yet" = "You don't have any contacts yet";
|
"vc_create_closed_group_empty_state_button_title" = "Start a Session";
|
||||||
"Start a Session" = "Start a Session";
|
"vc_create_closed_group_group_name_missing_error" = "Please enter a group name";
|
||||||
"Enter a group name" = "Enter a group name";
|
"vc_create_closed_group_group_name_too_long_error" = "Please enter a shorter group name";
|
||||||
"Please enter a group name" = "Please enter a group name";
|
"vc_create_closed_group_not_enough_group_members_error" = "Please pick at least 2 group members";
|
||||||
"Please enter a shorter group name" = "Please enter a shorter group name";
|
"vc_create_closed_group_too_many_group_members_error" = "A closed group cannot have more than 10 members";
|
||||||
"Please pick at least 2 group members" = "Please pick at least 2 group members";
|
"vc_create_closed_group_invalid_session_id_error" = "One of the members of your group has an invalid Session ID";
|
||||||
"Enable Link Previews?" = "Enable Link Previews?";
|
|
||||||
"You will not have full metadata protection when sending or receiving link previews." = "You will not have full metadata protection when sending or receiving link previews.";
|
"vc_join_public_chat_title" = "Join Open Group";
|
||||||
"Open groups can be joined by anyone and do not provide full privacy protection" = "Open groups can be joined by anyone and do not provide full privacy protection";
|
"vc_join_public_chat_error" = "Couldn't join group";
|
||||||
"Search GIFs?" = "Search GIFs?";
|
"vc_join_public_chat_enter_group_url_tab_title" = "Open Group URL";
|
||||||
"You will not have full metadata protection when sending GIFs." = "You will not have full metadata protection when sending GIFs.";
|
"vc_join_public_chat_scan_qr_code_tab_title" = "Scan QR Code";
|
||||||
"The ability to add members to a closed group is coming soon." = "The ability to add members to a closed group is coming soon.";
|
"vc_join_public_chat_scan_qr_code_explanation" = "Scan the QR code of the open group you'd like to join";
|
||||||
"A closed group cannot have more than 10 members" = "A closed group cannot have more than 10 members";
|
|
||||||
"A closed group cannot have more than 50 members" = "A closed group cannot have more than 50 members";
|
"vc_enter_chat_url_text_field_hint" = "Enter an open group URL";
|
||||||
"Closed groups support up to 10 members" = "Closed groups support up to 10 members";
|
"vc_enter_chat_url_privacy_warning" = "Open groups can be joined by anyone and do not provide full privacy protection";
|
||||||
"Closed groups support up to 50 members" = "Closed groups support up to 50 members";
|
|
||||||
"No messages yet" = "No messages yet";
|
"vc_settings_title" = "Settings";
|
||||||
"Would you like to join the Session Public Chat?" = "Would you like to join the Session Public Chat?";
|
"vc_settings_display_name_text_field_hint" = "Enter a display name";
|
||||||
"Join Public Chat" = "Join Public Chat";
|
"vc_settings_display_name_missing_error" = "Please pick a display name";
|
||||||
"No, thank you" = "No, thank you";
|
"vc_settings_invalid_display_name_error" = "Please pick a display name that consists of only a-z, A-Z, 0-9 and _ characters";
|
||||||
"Report" = "Report";
|
"vc_settings_display_name_too_long_error" = "Please pick a shorter display name";
|
||||||
"Please Pick an Option" = "Please Pick an Option";
|
"vc_settings_privacy_button_title" = "Privacy";
|
||||||
"There are two ways Session can handle push notifications. Make sure to read the descriptions carefully before you choose." = "There are two ways Session can handle push notifications. Make sure to read the descriptions carefully before you choose.";
|
"vc_settings_notifications_button_title" = "Notifications";
|
||||||
"Apple Push Notification Service" = "Apple Push Notification Service";
|
"vc_settings_chats_button_title" = "Chats";
|
||||||
"Session will use the Apple Push Notification service to receive push notifications. You'll be notified of new messages reliably and immediately. Using APNs means that your IP address and device token will be exposed to Apple. If you use push notifications for other apps, this will already be the case. Your IP address and device token will also be exposed to Loki, but your messages will still be onion-routed and end-to-end encrypted, so the contents of your messages will remain completely private." = "Session will use the Apple Push Notification service to receive push notifications. You'll be notified of new messages reliably and immediately. Using APNs means that your IP address and device token will be exposed to Apple. If you use push notifications for other apps, this will already be the case. Your IP address and device token will also be exposed to Loki, but your messages will still be onion-routed and end-to-end encrypted, so the contents of your messages will remain completely private.";
|
"vc_settings_devices_button_title" = "Devices";
|
||||||
"Background Polling" = "Background Polling";
|
"vc_settings_recovery_phrase_button_title" = "Recovery Phrase";
|
||||||
"Session will occasionally check for new messages in the background. This guarantees full metadata protection, but message notifications may be significantly delayed." = "Session will occasionally check for new messages in the background. This guarantees full metadata protection, but message notifications may be significantly delayed.";
|
"vc_settings_clear_all_data_button_title" = "Clear Data";
|
||||||
"Use APNs" = "Use APNs";
|
|
||||||
"Recommended" = "Recommended";
|
"vc_notification_settings_title" = "Notifications";
|
||||||
"Notification Strategy" = "Notification Strategy";
|
"vc_notification_settings_style_section_title" = "Notification Style";
|
||||||
"Session now features two ways to handle push notifications. Make sure to read the descriptions carefully before you choose." = "Session now features two ways to handle push notifications. Make sure to read the descriptions carefully before you choose.";
|
"vc_notification_settings_content_section_title" = "Notification Content";
|
||||||
"Push Notifications" = "Push Notifications";
|
|
||||||
"Confirm" = "Confirm";
|
"vc_privacy_settings_title" = "Privacy";
|
||||||
"Skip" = "Skip";
|
|
||||||
"Link Previews" = "Link Previews";
|
"vc_chat_settings_title" = "Chats";
|
||||||
"Invalid Session ID" = "Invalid Session ID";
|
|
||||||
"Please make sure the Session ID you entered is correct and try again." = "Please make sure the Session ID you entered is correct and try again.";
|
"vc_linked_devices_title" = "Devices";
|
||||||
"Device Linking Failed" = "Device Linking Failed";
|
"vc_linked_devices_multi_device_limit_reached_modal_title" = "Device Limit Reached";
|
||||||
"Please check your internet connection and try again" = "Please check your internet connection and try again";
|
"vc_linked_devices_multi_device_limit_reached_modal_explanation" = "It's currently not allowed to link more than one device.";
|
||||||
"Authorizing Device Link" = "Authorizing Device Link";
|
"vc_linked_devices_unlinking_failed_message" = "Couldn't unlink device.";
|
||||||
"Please wait while the device link is created. This can take up to a minute." = "Please wait while the device link is created. This can take up to a minute.";
|
"vc_linked_devices_unlinking_successful_message" = "Your device was unlinked successfully";
|
||||||
"Path" = "Path";
|
"vc_linked_devices_linking_failed_message" = "Couldn't link device.";
|
||||||
"Session hides your IP by bouncing your messages through several Service Nodes in Session’s decentralized network. These are the countries your connection is currently being bounced through:" = "Session hides your IP by bouncing your messages through several Service Nodes in Session’s decentralized network. These are the countries your connection is currently being bounced through:";
|
"vc_linked_devices_empty_state_message" = "You haven't linked any devices yet";
|
||||||
"Entry Node" = "Entry Node";
|
"vc_linked_devices_empty_state_button_title" = "Link a Device (Beta)";
|
||||||
"Service Node" = "Service Node";
|
|
||||||
"You" = "You";
|
"preferences_notifications_strategy_category_title" = "Notification Strategy";
|
||||||
"Destination" = "Destination";
|
"preferences_notifications_use_apns_option_title" = "Use APNs";
|
||||||
"Learn More" = "Learn More";
|
"preferences_notifications_use_apns_option_explanation" = "Using Apple Push Notification Service allows for more reliable push notifications, but exposes your IP and device token to Apple and Loki.";
|
||||||
"Please ask the open group operator to add you to the group." = "Please ask the open group operator to add you to the group.";
|
|
||||||
"Unauthorized" = "Unauthorized";
|
"modal_link_device_slave_mode_title_1" = "Waiting for Authorization";
|
||||||
"Closed group created" = "Closed group created";
|
"modal_link_device_slave_mode_title_2" = "Device Link Authorized";
|
||||||
"Couldn't Create Group" = "Couldn't Create Group";
|
"modal_link_device_slave_mode_explanation_1" = "Please check that the words below match those shown on your other device.";
|
||||||
"Please check your internet connection and try again." = "Please check your internet connection and try again.";
|
"modal_link_device_slave_mode_explanation_2" = "Your device has been linked successfully";
|
||||||
|
|
||||||
|
"modal_link_device_master_mode_title_1" = "Waiting for Device";
|
||||||
|
"modal_link_device_master_mode_title_2" = "Linking Request Received";
|
||||||
|
"modal_link_device_master_mode_title_3" = "Authorizing Device Link";
|
||||||
|
"modal_link_device_master_mode_explanation_1" = "Download Session on your other device and tap \"Link to an existing account\" at the bottom of the landing screen. If you have an existing account on your other device already you will have to delete that account first.";
|
||||||
|
"modal_link_device_master_mode_explanation_2" = "Please check that the words below match those shown on your other device.";
|
||||||
|
"modal_link_device_master_mode_explanation_3" = "Please wait while the device link is created. This can take up to a minute.";
|
||||||
|
"modal_link_device_master_mode_authorize_button_title" = "Authorize";
|
||||||
|
|
||||||
|
"vc_device_list_bottom_sheet_change_name_button_title" = "Change name";
|
||||||
|
"vc_device_list_bottom_sheet_unlink_device_button_title" = "Unlink device";
|
||||||
|
|
||||||
|
"modal_edit_device_name_text_field_hint" = "Enter a name";
|
||||||
|
|
||||||
|
"modal_seed_title" = "Your Recovery Phrase";
|
||||||
|
"modal_seed_explanation" = "This is your recovery phrase. With it, you can restore or migrate your Session ID to a new device.";
|
||||||
|
|
||||||
|
"modal_clear_all_data_title" = "Clear All Data";
|
||||||
|
"modal_clear_all_data_explanation" = "This will permanently delete your messages, sessions, and contacts.";
|
||||||
|
|
||||||
|
"vc_qr_code_title" = "QR Code";
|
||||||
|
"vc_qr_code_view_my_qr_code_tab_title" = "View My QR Code";
|
||||||
|
"vc_qr_code_view_scan_qr_code_tab_title" = "Scan QR Code";
|
||||||
|
"vc_qr_code_view_scan_qr_code_explanation" = "Scan someone's QR code to start a conversation with them";
|
||||||
|
|
||||||
|
"vc_view_my_qr_code_explanation" = "This is your QR code. Other users can scan it to start a session with you.";
|
||||||
|
"vc_view_my_qr_code_share_title" = "Share QR Code";
|
||||||
|
|
||||||
|
"view_friend_request_accept_button_title" = "Accept";
|
||||||
|
"view_friend_request_reject_button_title" = "Decline";
|
||||||
|
"view_friend_request_incoming_pending_message" = "%@ sent you a session request";
|
||||||
|
"view_friend_request_incoming_accepted_message" = "You've accepted %@'s session request";
|
||||||
|
"view_friend_request_incoming_declined_message" = "You've declined %@'s session request";
|
||||||
|
"view_friend_request_incoming_expired_message" = "%@'s session request has expired";
|
||||||
|
"view_friend_request_outgoing_pending_message" = "You've sent %@ a session request";
|
||||||
|
"view_friend_request_outgoing_accepted_message" = "%@ accepted your session request";
|
||||||
|
"view_friend_request_outgoing_expired_message" = "Your session request to %@ has expired";
|
||||||
|
|
||||||
|
"session_reset_banner_message" = "Would you like to restore your session with %@?";
|
||||||
|
"session_reset_banner_dismiss_button_title" = "Dismiss";
|
||||||
|
"session_reset_banner_restore_button_title" = "Restore";
|
||||||
|
|
||||||
|
"vc_contact_selection_contacts_title" = "Contacts";
|
||||||
|
"vc_contact_selection_closed_groups_title" = "Closed Groups";
|
||||||
|
"vc_contact_selection_open_groups_title" = "Open Groups";
|
||||||
|
|
|
@ -201,7 +201,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
// Existing threads are listed first, ordered by most recently active
|
// Existing threads are listed first, ordered by most recently active
|
||||||
OWSTableSection *recentChatsSection = [OWSTableSection new];
|
OWSTableSection *recentChatsSection = [OWSTableSection new];
|
||||||
recentChatsSection.headerTitle = NSLocalizedString(@"Recent Chats", @"");
|
recentChatsSection.headerTitle = NSLocalizedString(@"SELECT_THREAD_TABLE_RECENT_CHATS_TITLE", @"");
|
||||||
for (TSThread *thread in [self filteredThreadsWithSearchText]) {
|
for (TSThread *thread in [self filteredThreadsWithSearchText]) {
|
||||||
[recentChatsSection
|
[recentChatsSection
|
||||||
addItem:[OWSTableItem
|
addItem:[OWSTableItem
|
||||||
|
@ -277,7 +277,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
// Contacts who don't yet have a thread are listed last
|
// Contacts who don't yet have a thread are listed last
|
||||||
OWSTableSection *otherContactsSection = [OWSTableSection new];
|
OWSTableSection *otherContactsSection = [OWSTableSection new];
|
||||||
otherContactsSection.headerTitle = NSLocalizedString(@"Other Chats", @"");
|
otherContactsSection.headerTitle = @"Other Chats";
|
||||||
NSArray<SignalAccount *> *filteredSignalAccounts = [self filteredSignalAccountsWithSearchText];
|
NSArray<SignalAccount *> *filteredSignalAccounts = [self filteredSignalAccountsWithSearchText];
|
||||||
for (SignalAccount *signalAccount in filteredSignalAccounts) {
|
for (SignalAccount *signalAccount in filteredSignalAccounts) {
|
||||||
[otherContactsSection
|
[otherContactsSection
|
||||||
|
|
Loading…
Reference in New Issue