mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
ea32e407a9
Updated the HomeVC, SettingsVC and GlobalSearch UI to use theming Removed the "fade view" gradients from the various screens Added a simple log to the PagedDatabaseObserver to make debugging easier Updated the FullConversationCell to also show the "read" state for messages Updated the read receipt icons to use SFSymbols directly Updated the PlaceholderIcon to use the PrimaryColour's as it's colour options
617 lines
26 KiB
Swift
617 lines
26 KiB
Swift
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
|
|
|
import UIKit
|
|
import SessionUIKit
|
|
import SessionUtilitiesKit
|
|
import SessionMessagingKit
|
|
import SignalUtilitiesKit
|
|
|
|
final class SettingsVC: BaseVC, AvatarViewHelperDelegate {
|
|
private var displayNameToBeUploaded: String?
|
|
private var isEditingDisplayName = false { didSet { handleIsEditingDisplayNameChanged() } }
|
|
|
|
// MARK: - Components
|
|
|
|
private lazy var profilePictureView: ProfilePictureView = {
|
|
let result = ProfilePictureView()
|
|
let size = Values.largeProfilePictureSize
|
|
result.size = size
|
|
result.set(.width, to: size)
|
|
result.set(.height, to: size)
|
|
result.accessibilityLabel = "Edit profile picture button"
|
|
result.isAccessibilityElement = true
|
|
|
|
return result
|
|
}()
|
|
|
|
private lazy var profilePictureUtilities: AvatarViewHelper = {
|
|
let result = AvatarViewHelper()
|
|
result.delegate = self
|
|
|
|
return result
|
|
}()
|
|
|
|
private lazy var displayNameLabel: UILabel = {
|
|
let result = UILabel()
|
|
result.font = .boldSystemFont(ofSize: Values.veryLargeFontSize)
|
|
result.themeTextColor = .textPrimary
|
|
result.lineBreakMode = .byTruncatingTail
|
|
result.textAlignment = .center
|
|
|
|
return result
|
|
}()
|
|
|
|
private lazy var displayNameTextField: TextField = {
|
|
let result = TextField(
|
|
placeholder: "vc_settings_display_name_text_field_hint".localized(),
|
|
usesDefaultHeight: false
|
|
)
|
|
result.textAlignment = .center
|
|
result.accessibilityLabel = "Edit display name text field"
|
|
|
|
return result
|
|
}()
|
|
|
|
private lazy var publicKeyLabel: UILabel = {
|
|
let result = UILabel()
|
|
result.font = Fonts.spaceMono(ofSize: isIPhone5OrSmaller ? Values.mediumFontSize : Values.largeFontSize)
|
|
result.themeTextColor = .textPrimary
|
|
result.numberOfLines = 0
|
|
result.textAlignment = .center
|
|
result.lineBreakMode = .byCharWrapping
|
|
result.text = getUserHexEncodedPublicKey()
|
|
|
|
return result
|
|
}()
|
|
|
|
private lazy var copyButton: OutlineButton = {
|
|
let result = OutlineButton(style: .regular, size: .medium)
|
|
result.setTitle("copy".localized(), for: UIControl.State.normal)
|
|
result.addTarget(self, action: #selector(copyPublicKey), for: UIControl.Event.touchUpInside)
|
|
|
|
return result
|
|
}()
|
|
|
|
private lazy var shareButton: OutlineButton = {
|
|
let result = OutlineButton(style: .regular, size: .medium)
|
|
result.setTitle("share".localized(), for: UIControl.State.normal)
|
|
result.addTarget(self, action: #selector(sharePublicKey), for: UIControl.Event.touchUpInside)
|
|
|
|
return result
|
|
}()
|
|
|
|
private lazy var settingButtonsStackView: UIStackView = {
|
|
let result = UIStackView()
|
|
result.axis = .vertical
|
|
result.alignment = .fill
|
|
|
|
return result
|
|
}()
|
|
|
|
private lazy var logoImageView: UIImageView = {
|
|
let result = UIImageView(
|
|
image: UIImage(named: "OxenLightMode")?
|
|
.withRenderingMode(.alwaysTemplate)
|
|
)
|
|
result.themeTintColor = .textPrimary
|
|
result.contentMode = .scaleAspectFit
|
|
result.set(.height, to: 24)
|
|
|
|
return result
|
|
}()
|
|
|
|
private lazy var versionLabel: UILabel = {
|
|
let version: String = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String)
|
|
.defaulting(to: "0.0.0")
|
|
let buildNumber: String = (Bundle.main.infoDictionary?["CFBundleVersion"] as? String)
|
|
.defaulting(to: "0")
|
|
|
|
let result = UILabel()
|
|
result.font = .systemFont(ofSize: Values.verySmallFontSize)
|
|
result.text = "Version \(version) (\(buildNumber))"
|
|
result.themeTextColor = .textPrimary
|
|
result.numberOfLines = 0
|
|
result.textAlignment = .center
|
|
result.lineBreakMode = .byCharWrapping
|
|
result.alpha = Values.mediumOpacity
|
|
|
|
return result
|
|
}()
|
|
|
|
// MARK: - Settings
|
|
|
|
private static let buttonHeight = isIPhone5OrSmaller ? CGFloat(52) : CGFloat(75)
|
|
|
|
// MARK: - Lifecycle
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
|
|
setNavBarTitle("vc_settings_title".localized())
|
|
|
|
// Navigation bar buttons
|
|
updateNavigationBarButtons()
|
|
|
|
// Profile picture view
|
|
let profile: Profile = Profile.fetchOrCreateCurrentUser()
|
|
let profilePictureTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(showEditProfilePictureUI))
|
|
profilePictureView.addGestureRecognizer(profilePictureTapGestureRecognizer)
|
|
profilePictureView
|
|
.update(
|
|
publicKey: profile.id,
|
|
profile: profile,
|
|
threadVariant: .contact
|
|
)
|
|
// Display name label
|
|
displayNameLabel.text = profile.name
|
|
|
|
// Display name container
|
|
let displayNameContainer = UIView()
|
|
displayNameContainer.accessibilityLabel = "Edit display name text field"
|
|
displayNameContainer.isAccessibilityElement = true
|
|
displayNameContainer.addSubview(displayNameLabel)
|
|
displayNameLabel.pin(to: displayNameContainer)
|
|
displayNameContainer.addSubview(displayNameTextField)
|
|
displayNameTextField.pin(to: displayNameContainer)
|
|
displayNameContainer.set(.height, to: 40)
|
|
displayNameTextField.alpha = 0
|
|
let displayNameContainerTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(showEditDisplayNameUI))
|
|
displayNameContainer.addGestureRecognizer(displayNameContainerTapGestureRecognizer)
|
|
|
|
// Header view
|
|
let headerStackView = UIStackView(arrangedSubviews: [ profilePictureView, displayNameContainer ])
|
|
headerStackView.axis = .vertical
|
|
headerStackView.spacing = Values.smallSpacing
|
|
headerStackView.alignment = .center
|
|
|
|
// Separator
|
|
let separator = Separator(title: "your_session_id".localized())
|
|
|
|
// Button container
|
|
let buttonContainer = UIStackView(arrangedSubviews: [ copyButton, shareButton ])
|
|
buttonContainer.axis = .horizontal
|
|
buttonContainer.spacing = UIDevice.current.isIPad ? Values.iPadButtonSpacing : Values.mediumSpacing
|
|
buttonContainer.distribution = .fillEqually
|
|
|
|
if (UIDevice.current.isIPad) {
|
|
buttonContainer.layoutMargins = UIEdgeInsets(top: 0, left: Values.iPadButtonContainerMargin, bottom: 0, right: Values.iPadButtonContainerMargin)
|
|
buttonContainer.isLayoutMarginsRelativeArrangement = true
|
|
}
|
|
// User session id container
|
|
let userPublicKeyContainer = UIView(wrapping: publicKeyLabel, withInsets: .zero, shouldAdaptForIPadWithWidth: Values.iPadUserSessionIdContainerWidth)
|
|
|
|
// Top stack view
|
|
let topStackView = UIStackView(arrangedSubviews: [ headerStackView, separator, userPublicKeyContainer, buttonContainer ])
|
|
topStackView.axis = .vertical
|
|
topStackView.spacing = Values.largeSpacing
|
|
topStackView.alignment = .fill
|
|
topStackView.layoutMargins = UIEdgeInsets(top: 0, left: Values.largeSpacing, bottom: 0, right: Values.largeSpacing)
|
|
topStackView.isLayoutMarginsRelativeArrangement = true
|
|
|
|
// Setting buttons stack view
|
|
getSettingButtons().forEach { settingButtonOrSeparator in
|
|
settingButtonsStackView.addArrangedSubview(settingButtonOrSeparator)
|
|
}
|
|
|
|
// Oxen logo
|
|
let logoContainer = UIView()
|
|
logoContainer.addSubview(logoImageView)
|
|
logoImageView.pin(.top, to: .top, of: logoContainer)
|
|
logoContainer.pin(.bottom, to: .bottom, of: logoImageView)
|
|
logoImageView.centerXAnchor.constraint(equalTo: logoContainer.centerXAnchor, constant: -2).isActive = true
|
|
|
|
// Main stack view
|
|
let stackView = UIStackView(arrangedSubviews: [ topStackView, settingButtonsStackView, logoContainer, versionLabel ])
|
|
stackView.axis = .vertical
|
|
stackView.spacing = Values.largeSpacing
|
|
stackView.alignment = .fill
|
|
stackView.layoutMargins = UIEdgeInsets(top: Values.mediumSpacing, left: 0, bottom: Values.mediumSpacing, right: 0)
|
|
stackView.isLayoutMarginsRelativeArrangement = true
|
|
stackView.set(.width, to: UIScreen.main.bounds.width)
|
|
|
|
// Scroll view
|
|
let scrollView = UIScrollView()
|
|
scrollView.showsVerticalScrollIndicator = false
|
|
scrollView.addSubview(stackView)
|
|
stackView.pin(to: scrollView)
|
|
view.addSubview(scrollView)
|
|
scrollView.pin(to: view)
|
|
}
|
|
|
|
private func getSettingButtons() -> [UIView] {
|
|
func getSettingButton(
|
|
title: String,
|
|
color: ThemeValue = .textPrimary,
|
|
action selector: Selector
|
|
) -> UIButton {
|
|
let result: UIButton = UIButton()
|
|
result.setTitle(title, for: UIControl.State.normal)
|
|
result.setThemeTitleColor(color, for: UIControl.State.normal)
|
|
result.titleLabel?.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
|
result.titleLabel?.textAlignment = .center
|
|
result.setThemeBackgroundColor(.settings_tabBackground, for: .normal)
|
|
result.setThemeBackgroundColor(.settings_tabHighlight, for: .highlighted)
|
|
result.addTarget(self, action: selector, for: UIControl.Event.touchUpInside)
|
|
result.set(.height, to: SettingsVC.buttonHeight)
|
|
|
|
return result
|
|
}
|
|
|
|
let pathButton = getSettingButton(title: "vc_path_title".localized(), action: #selector(showPath))
|
|
let pathStatusView = PathStatusView()
|
|
pathStatusView.set(.width, to: PathStatusView.size)
|
|
pathStatusView.set(.height, to: PathStatusView.size)
|
|
|
|
pathButton.addSubview(pathStatusView)
|
|
pathStatusView.pin(.leading, to: .trailing, of: pathButton.titleLabel!, withInset: Values.smallSpacing)
|
|
pathStatusView.autoVCenterInSuperview()
|
|
|
|
return [
|
|
UIView.separator(),
|
|
pathButton,
|
|
UIView.separator(),
|
|
getSettingButton(title: "vc_settings_privacy_button_title".localized(), action: #selector(showPrivacySettings)),
|
|
UIView.separator(),
|
|
getSettingButton(title: "vc_settings_notifications_button_title".localized(), action: #selector(showNotificationSettings)),
|
|
UIView.separator(),
|
|
getSettingButton(title: "CONVERSATIONS_TITLE".localized(), action: #selector(showChatSettings)),
|
|
UIView.separator(),
|
|
getSettingButton(title: "MESSAGE_REQUESTS_TITLE".localized(), action: #selector(showMessageRequests)),
|
|
UIView.separator(),
|
|
getSettingButton(title: "APPEARANCE_TITLE".localized(), action: #selector(showAppearanceSettings)),
|
|
UIView.separator(),
|
|
getSettingButton(title: "vc_settings_invite_a_friend_button_title".localized(), action: #selector(sendInvitation)),
|
|
UIView.separator(),
|
|
getSettingButton(title: "vc_settings_recovery_phrase_button_title".localized(), action: #selector(showSeed)),
|
|
UIView.separator(),
|
|
getSettingButton(title: "HELP_TITLE".localized(), action: #selector(showHelp)),
|
|
UIView.separator(),
|
|
getSettingButton(title: "vc_settings_clear_all_data_button_title".localized(), color: .danger, action: #selector(clearAllData)),
|
|
UIView.separator()
|
|
]
|
|
}
|
|
|
|
// MARK: - General
|
|
|
|
@objc private func enableCopyButton() {
|
|
copyButton.isUserInteractionEnabled = true
|
|
|
|
UIView.transition(
|
|
with: copyButton,
|
|
duration: 0.25,
|
|
options: .transitionCrossDissolve,
|
|
animations: {
|
|
self.copyButton.setTitle("copy".localized(), for: .normal)
|
|
},
|
|
completion: nil
|
|
)
|
|
}
|
|
|
|
func avatarActionSheetTitle() -> String? { return "Update Profile Picture" }
|
|
func fromViewController() -> UIViewController { return self }
|
|
func hasClearAvatarAction() -> Bool { return false }
|
|
func clearAvatarActionLabel() -> String { return "Clear" }
|
|
|
|
// MARK: - Updating
|
|
|
|
private func handleIsEditingDisplayNameChanged() {
|
|
updateNavigationBarButtons()
|
|
|
|
UIView.animate(withDuration: 0.25) {
|
|
self.displayNameLabel.alpha = self.isEditingDisplayName ? 0 : 1
|
|
self.displayNameTextField.alpha = self.isEditingDisplayName ? 1 : 0
|
|
}
|
|
|
|
if isEditingDisplayName {
|
|
displayNameTextField.becomeFirstResponder()
|
|
}
|
|
else {
|
|
displayNameTextField.resignFirstResponder()
|
|
}
|
|
}
|
|
|
|
private func updateNavigationBarButtons() {
|
|
if isEditingDisplayName {
|
|
let cancelButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(handleCancelDisplayNameEditingButtonTapped))
|
|
cancelButton.themeTintColor = .textPrimary
|
|
cancelButton.accessibilityLabel = "Cancel button"
|
|
cancelButton.isAccessibilityElement = true
|
|
navigationItem.leftBarButtonItem = cancelButton
|
|
|
|
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(handleSaveDisplayNameButtonTapped))
|
|
doneButton.themeTintColor = .textPrimary
|
|
doneButton.accessibilityLabel = "Done button"
|
|
doneButton.isAccessibilityElement = true
|
|
navigationItem.rightBarButtonItem = doneButton
|
|
}
|
|
else {
|
|
let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close))
|
|
closeButton.themeTintColor = .textPrimary
|
|
closeButton.accessibilityLabel = "Close button"
|
|
closeButton.isAccessibilityElement = true
|
|
navigationItem.leftBarButtonItem = closeButton
|
|
|
|
let qrCodeButton = UIButton()
|
|
qrCodeButton.setImage(
|
|
UIImage(named: "QRCode")?
|
|
.withRenderingMode(.alwaysTemplate),
|
|
for: .normal
|
|
)
|
|
qrCodeButton.themeTintColor = .textPrimary
|
|
qrCodeButton.addTarget(self, action: #selector(showQRCode), for: UIControl.Event.touchUpInside)
|
|
qrCodeButton.accessibilityLabel = "Show QR code button"
|
|
|
|
let stackView = UIStackView(arrangedSubviews: [ qrCodeButton ])
|
|
stackView.axis = .horizontal
|
|
stackView.spacing = Values.mediumSpacing
|
|
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: stackView)
|
|
}
|
|
}
|
|
|
|
func avatarDidChange(_ image: UIImage?, filePath: String?) {
|
|
updateProfile(
|
|
profilePicture: image,
|
|
profilePictureFilePath: filePath,
|
|
isUpdatingDisplayName: false,
|
|
isUpdatingProfilePicture: true
|
|
)
|
|
}
|
|
|
|
func clearAvatar() {
|
|
updateProfile(
|
|
profilePicture: nil,
|
|
profilePictureFilePath: nil,
|
|
isUpdatingDisplayName: false,
|
|
isUpdatingProfilePicture: true
|
|
)
|
|
}
|
|
|
|
private func updateProfile(
|
|
profilePicture: UIImage?,
|
|
profilePictureFilePath: String?,
|
|
isUpdatingDisplayName: Bool,
|
|
isUpdatingProfilePicture: Bool
|
|
) {
|
|
let userDefaults = UserDefaults.standard
|
|
let name: String? = (displayNameToBeUploaded ?? Profile.fetchOrCreateCurrentUser().name)
|
|
let imageFilePath: String? = (profilePictureFilePath ?? ProfileManager.profileAvatarFilepath(id: getUserHexEncodedPublicKey()))
|
|
|
|
ModalActivityIndicatorViewController.present(fromViewController: navigationController!, canCancel: false) { [weak self, displayNameToBeUploaded] modalActivityIndicator in
|
|
ProfileManager.updateLocal(
|
|
queue: DispatchQueue.global(qos: .default),
|
|
profileName: (name ?? ""),
|
|
image: profilePicture,
|
|
imageFilePath: imageFilePath,
|
|
requiredSync: true,
|
|
success: { db, updatedProfile in
|
|
if displayNameToBeUploaded != nil {
|
|
userDefaults[.lastDisplayNameUpdate] = Date()
|
|
}
|
|
|
|
if isUpdatingProfilePicture {
|
|
userDefaults[.lastProfilePictureUpdate] = Date()
|
|
}
|
|
|
|
try MessageSender.syncConfiguration(db, forceSyncNow: true).retainUntilComplete()
|
|
|
|
// Wait for the database transaction to complete before updating the UI
|
|
db.afterNextTransactionCommit { _ in
|
|
DispatchQueue.main.async {
|
|
modalActivityIndicator.dismiss {
|
|
self?.profilePictureView.update(
|
|
publicKey: updatedProfile.id,
|
|
profile: updatedProfile,
|
|
threadVariant: .contact
|
|
)
|
|
self?.displayNameLabel.text = name
|
|
self?.displayNameToBeUploaded = nil
|
|
}
|
|
}
|
|
}
|
|
},
|
|
failure: { error in
|
|
DispatchQueue.main.async {
|
|
modalActivityIndicator.dismiss {
|
|
let isMaxFileSizeExceeded = (error == .avatarUploadMaxFileSizeExceeded)
|
|
let title = isMaxFileSizeExceeded ? "Maximum File Size Exceeded" : "Couldn't Update Profile"
|
|
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)
|
|
alert.addAction(UIAlertAction(title: "BUTTON_OK".localized(), style: .default, handler: nil))
|
|
self?.present(alert, animated: true, completion: nil)
|
|
}
|
|
}
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
@objc override internal func handleAppModeChangedNotification(_ notification: Notification) {
|
|
super.handleAppModeChangedNotification(notification)
|
|
|
|
updateNavigationBarButtons()
|
|
settingButtonsStackView.arrangedSubviews.forEach { settingButton in
|
|
settingButtonsStackView.removeArrangedSubview(settingButton)
|
|
settingButton.removeFromSuperview()
|
|
}
|
|
getSettingButtons().forEach { settingButtonOrSeparator in
|
|
settingButtonsStackView.addArrangedSubview(settingButtonOrSeparator) // Re-do the setting buttons
|
|
}
|
|
updateLogo()
|
|
}
|
|
|
|
private func updateLogo() {
|
|
let logoName = isLightMode ? "OxenLightMode" : "OxenDarkMode"
|
|
logoImageView.image = UIImage(named: logoName)!
|
|
}
|
|
|
|
// MARK: - Interaction
|
|
|
|
@objc private func close() {
|
|
dismiss(animated: true, completion: nil)
|
|
}
|
|
|
|
@objc private func switchAppMode() {
|
|
let alertVC = UIAlertController.init(title: nil, message: nil, preferredStyle: .actionSheet)
|
|
let systemModeAction = UIAlertAction.init(title: NSLocalizedString("system_mode_theme", comment: ""), style: .default) { _ in
|
|
AppModeManager.shared.setAppModeToSystemDefault()
|
|
}
|
|
alertVC.addAction(systemModeAction)
|
|
|
|
let darkModeAction = UIAlertAction.init(title: NSLocalizedString("dark_mode_theme", comment: ""), style: .default) { _ in
|
|
AppModeManager.shared.setCurrentAppMode(to: .dark)
|
|
}
|
|
alertVC.addAction(darkModeAction)
|
|
|
|
let lightModeAction = UIAlertAction.init(title: NSLocalizedString("light_mode_theme", comment: ""), style: .default) { _ in
|
|
AppModeManager.shared.setCurrentAppMode(to: .light)
|
|
}
|
|
alertVC.addAction(lightModeAction)
|
|
|
|
let cancelAction = UIAlertAction.init(title: NSLocalizedString("TXT_CANCEL_TITLE", comment: ""), style: .cancel) {_ in }
|
|
alertVC.addAction(cancelAction)
|
|
|
|
self.presentAlert(alertVC)
|
|
}
|
|
|
|
@objc private func showQRCode() {
|
|
let qrCodeVC = QRCodeVC()
|
|
navigationController!.pushViewController(qrCodeVC, animated: true)
|
|
}
|
|
|
|
@objc private func handleCancelDisplayNameEditingButtonTapped() {
|
|
isEditingDisplayName = false
|
|
}
|
|
|
|
@objc private func handleSaveDisplayNameButtonTapped() {
|
|
func showError(title: String, message: String = "") {
|
|
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
|
alert.addAction(UIAlertAction(title: NSLocalizedString("BUTTON_OK", comment: ""), style: .default, handler: nil))
|
|
presentAlert(alert)
|
|
}
|
|
let displayName = displayNameTextField.text!.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
|
|
guard !displayName.isEmpty else {
|
|
return showError(title: NSLocalizedString("vc_settings_display_name_missing_error", comment: ""))
|
|
}
|
|
guard !ProfileManager.isToLong(profileName: displayName) else {
|
|
return showError(title: NSLocalizedString("vc_settings_display_name_too_long_error", comment: ""))
|
|
}
|
|
isEditingDisplayName = false
|
|
displayNameToBeUploaded = displayName
|
|
updateProfile(
|
|
profilePicture: nil,
|
|
profilePictureFilePath: nil,
|
|
isUpdatingDisplayName: true,
|
|
isUpdatingProfilePicture: false
|
|
)
|
|
}
|
|
|
|
@objc private func showEditProfilePictureUI() {
|
|
profilePictureUtilities.showChangeAvatarUI()
|
|
}
|
|
|
|
@objc private func showEditDisplayNameUI() {
|
|
isEditingDisplayName = true
|
|
}
|
|
|
|
@objc private func copyPublicKey() {
|
|
UIPasteboard.general.string = getUserHexEncodedPublicKey()
|
|
copyButton.isUserInteractionEnabled = false
|
|
UIView.transition(with: copyButton, duration: 0.25, options: .transitionCrossDissolve, animations: {
|
|
self.copyButton.setTitle(NSLocalizedString("copied", comment: ""), for: UIControl.State.normal)
|
|
}, completion: nil)
|
|
Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(enableCopyButton), userInfo: nil, repeats: false)
|
|
}
|
|
|
|
@objc private func sharePublicKey() {
|
|
let shareVC = UIActivityViewController(activityItems: [ getUserHexEncodedPublicKey() ], applicationActivities: nil)
|
|
if UIDevice.current.isIPad {
|
|
shareVC.excludedActivityTypes = []
|
|
shareVC.popoverPresentationController?.permittedArrowDirections = []
|
|
shareVC.popoverPresentationController?.sourceView = self.view
|
|
shareVC.popoverPresentationController?.sourceRect = self.view.bounds
|
|
}
|
|
navigationController!.present(shareVC, animated: true, completion: nil)
|
|
}
|
|
|
|
@objc private func showPath() {
|
|
let pathVC = PathVC()
|
|
self.navigationController?.pushViewController(pathVC, animated: true)
|
|
}
|
|
|
|
@objc private func showPrivacySettings() {
|
|
let privacySettingsVC = PrivacySettingsTableViewController()
|
|
self.navigationController?.pushViewController(privacySettingsVC, animated: true)
|
|
}
|
|
|
|
@objc private func showNotificationSettings() {
|
|
let notificationSettingsVC = NotificationSettingsViewController()
|
|
self.navigationController?.pushViewController(notificationSettingsVC, animated: true)
|
|
}
|
|
|
|
@objc private func showMessageRequests() {
|
|
let viewController: MessageRequestsViewController = MessageRequestsViewController()
|
|
self.navigationController?.pushViewController(viewController, animated: true)
|
|
}
|
|
|
|
@objc private func showChatSettings() {
|
|
let chatSettingsVC = ChatSettingsViewController()
|
|
self.navigationController?.pushViewController(chatSettingsVC, animated: true)
|
|
}
|
|
|
|
@objc private func showAppearanceSettings() {
|
|
let appearanceViewController: AppearanceViewController = AppearanceViewController()
|
|
self.navigationController?.pushViewController(appearanceViewController, animated: true)
|
|
}
|
|
|
|
@objc private func showSeed() {
|
|
let seedModal = SeedModal()
|
|
seedModal.modalPresentationStyle = .overFullScreen
|
|
seedModal.modalTransitionStyle = .crossDissolve
|
|
present(seedModal, animated: true, completion: nil)
|
|
}
|
|
|
|
@objc private func showHelp() {
|
|
|
|
}
|
|
|
|
@objc private func clearAllData() {
|
|
let nukeDataModal = NukeDataModal()
|
|
nukeDataModal.modalPresentationStyle = .overFullScreen
|
|
nukeDataModal.modalTransitionStyle = .crossDissolve
|
|
present(nukeDataModal, animated: true, completion: nil)
|
|
}
|
|
|
|
@objc private func sendInvitation() {
|
|
let invitation = "Hey, I've been using Session to chat with complete privacy and security. Come join me! Download it at https://getsession.org/. My Session ID is \(getUserHexEncodedPublicKey()) !"
|
|
let shareVC = UIActivityViewController(activityItems: [ invitation ], applicationActivities: nil)
|
|
if UIDevice.current.isIPad {
|
|
shareVC.excludedActivityTypes = []
|
|
shareVC.popoverPresentationController?.permittedArrowDirections = []
|
|
shareVC.popoverPresentationController?.sourceView = self.view
|
|
shareVC.popoverPresentationController?.sourceRect = self.view.bounds
|
|
}
|
|
navigationController!.present(shareVC, animated: true, completion: nil)
|
|
}
|
|
|
|
@objc private func openFAQ() {
|
|
let url = URL(string: "https://getsession.org/faq")!
|
|
UIApplication.shared.open(url)
|
|
}
|
|
|
|
@objc private func openSurvey() {
|
|
let url = URL(string: "https://getsession.org/survey")!
|
|
UIApplication.shared.open(url)
|
|
}
|
|
|
|
@objc private func shareLogs() {
|
|
let shareLogsModal = ShareLogsModal()
|
|
shareLogsModal.modalPresentationStyle = .overFullScreen
|
|
shareLogsModal.modalTransitionStyle = .crossDissolve
|
|
present(shareLogsModal, animated: true, completion: nil)
|
|
}
|
|
|
|
@objc private func helpTranslate() {
|
|
let url = URL(string: "https://crowdin.com/project/session-ios")!
|
|
UIApplication.shared.open(url)
|
|
}
|
|
}
|