diff --git a/Session.xcodeproj/project.pbxproj b/Session.xcodeproj/project.pbxproj index d81ae483c..f04880c15 100644 --- a/Session.xcodeproj/project.pbxproj +++ b/Session.xcodeproj/project.pbxproj @@ -250,7 +250,6 @@ B8856ED7256F1EB4001CE70E /* OWSPreferences.h in Headers */ = {isa = PBXBuildFile; fileRef = C38EF2F1255B6DBB007E1867 /* OWSPreferences.h */; settings = {ATTRIBUTES = (Public, ); }; }; B886B4A72398B23E00211ABE /* QRCodeVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B886B4A62398B23E00211ABE /* QRCodeVC.swift */; }; B886B4A92398BA1500211ABE /* QRCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = B886B4A82398BA1500211ABE /* QRCode.swift */; }; - B88847BC23E10BC6009836D2 /* GroupMembersVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B88847BB23E10BC6009836D2 /* GroupMembersVC.swift */; }; B88A1AC725C90A4700E6D421 /* TypingIndicatorInteraction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34B6A904218B4C90007C4606 /* TypingIndicatorInteraction.swift */; }; B893063F2383961A005EAA8E /* ScanQRCodeWrapperVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B893063E2383961A005EAA8E /* ScanQRCodeWrapperVC.swift */; }; B894D0752339EDCF00B4D94D /* NukeDataModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B894D0742339EDCF00B4D94D /* NukeDataModal.swift */; }; @@ -270,7 +269,7 @@ B8C2B3442563782400551B4D /* ThreadUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = B8C2B33B2563770800551B4D /* ThreadUtil.h */; settings = {ATTRIBUTES = (Public, ); }; }; B8CADAE925AFADF400AAFA15 /* OpenGroupManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3AAFFCB25AE92150089E6DD /* OpenGroupManager.swift */; }; B8CCF6352396005F0091D419 /* SpaceMono-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = B8CCF6342396005F0091D419 /* SpaceMono-Regular.ttf */; }; - B8CCF63723961D6D0091D419 /* NewPrivateChatVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8CCF63623961D6D0091D419 /* NewPrivateChatVC.swift */; }; + B8CCF63723961D6D0091D419 /* NewDMVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8CCF63623961D6D0091D419 /* NewDMVC.swift */; }; B8CCF63F23975CFB0091D419 /* JoinOpenGroupVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8CCF63E23975CFB0091D419 /* JoinOpenGroupVC.swift */; }; B8CCF6432397711F0091D419 /* SettingsVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8CCF6422397711F0091D419 /* SettingsVC.swift */; }; B8D0A25025E3678700C1835E /* LinkDeviceVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8D0A24F25E3678700C1835E /* LinkDeviceVC.swift */; }; @@ -391,7 +390,6 @@ C32C5D24256DD4C0003C73A2 /* MentionsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDA81255A57FC00E217F9 /* MentionsManager.swift */; }; C32C5D2E256DD4EA003C73A2 /* TSUnreadIndicatorInteraction.m in Sources */ = {isa = PBXBuildFile; fileRef = C38EF2C1255B6DA6007E1867 /* TSUnreadIndicatorInteraction.m */; }; C32C5D37256DD4ED003C73A2 /* TSUnreadIndicatorInteraction.h in Headers */ = {isa = PBXBuildFile; fileRef = C38EF2BE255B6DA6007E1867 /* TSUnreadIndicatorInteraction.h */; settings = {ATTRIBUTES = (Public, ); }; }; - C32C5D40256DD51E003C73A2 /* Storage+VolumeSamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31F812525258FB000DD9FD9 /* Storage+VolumeSamples.swift */; }; C32C5D83256DD5B6003C73A2 /* SSKKeychainStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33FDBBC255A581600E217F9 /* SSKKeychainStorage.swift */; }; C32C5D9C256DD6DC003C73A2 /* OWSOutgoingReceiptManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C33FDB6F255A580F00E217F9 /* OWSOutgoingReceiptManager.m */; }; C32C5DA5256DD6E5003C73A2 /* OWSOutgoingReceiptManager.h in Headers */ = {isa = PBXBuildFile; fileRef = C33FDABD255A580100E217F9 /* OWSOutgoingReceiptManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -536,7 +534,6 @@ C354E75A23FE2A7600CE22E3 /* BaseVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = C354E75923FE2A7600CE22E3 /* BaseVC.swift */; }; C35D0DB525AE5F1200B6BF49 /* UIEdgeInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = C35D0DB425AE5F1200B6BF49 /* UIEdgeInsets.swift */; }; C35E8AAE2485E51D00ACB629 /* IP2Country.swift in Sources */ = {isa = PBXBuildFile; fileRef = C35E8AAD2485E51D00ACB629 /* IP2Country.swift */; }; - C364535C252467900045C478 /* AudioUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = C364535B252467900045C478 /* AudioUtilities.swift */; }; C374EEE225DA26740073A857 /* LinkPreviewModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = C374EEE125DA26740073A857 /* LinkPreviewModal.swift */; }; C374EEEB25DA3CA70073A857 /* ConversationTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C374EEEA25DA3CA70073A857 /* ConversationTitleView.swift */; }; C374EEF425DB31D40073A857 /* VoiceMessageRecordingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C374EEF325DB31D40073A857 /* VoiceMessageRecordingView.swift */; }; @@ -1237,7 +1234,6 @@ B885D5F52334A32100EE0D8E /* UIView+Constraints.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Constraints.swift"; sourceTree = ""; }; B886B4A62398B23E00211ABE /* QRCodeVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeVC.swift; sourceTree = ""; }; B886B4A82398BA1500211ABE /* QRCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCode.swift; sourceTree = ""; }; - B88847BB23E10BC6009836D2 /* GroupMembersVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupMembersVC.swift; sourceTree = ""; }; B893063E2383961A005EAA8E /* ScanQRCodeWrapperVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanQRCodeWrapperVC.swift; sourceTree = ""; }; B894D0742339EDCF00B4D94D /* NukeDataModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NukeDataModal.swift; sourceTree = ""; }; B897621B25D201F7004F83B2 /* ScrollToBottomButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollToBottomButton.swift; sourceTree = ""; }; @@ -1265,7 +1261,7 @@ B8C2B33B2563770800551B4D /* ThreadUtil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ThreadUtil.h; sourceTree = ""; }; B8C9689023FA1401005F64E0 /* AppMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppMode.swift; sourceTree = ""; }; B8CCF6342396005F0091D419 /* SpaceMono-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "SpaceMono-Regular.ttf"; sourceTree = ""; }; - B8CCF63623961D6D0091D419 /* NewPrivateChatVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewPrivateChatVC.swift; sourceTree = ""; }; + B8CCF63623961D6D0091D419 /* NewDMVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewDMVC.swift; sourceTree = ""; }; B8CCF638239721E20091D419 /* TabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBar.swift; sourceTree = ""; }; B8CCF63E23975CFB0091D419 /* JoinOpenGroupVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoinOpenGroupVC.swift; sourceTree = ""; }; B8CCF6422397711F0091D419 /* SettingsVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsVC.swift; sourceTree = ""; }; @@ -1309,7 +1305,6 @@ C31D1DDC25217014005D4DA8 /* UserCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserCell.swift; sourceTree = ""; }; C31D1DE22521718E005D4DA8 /* UserSelectionVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserSelectionVC.swift; sourceTree = ""; }; C31D1DE8252172D4005D4DA8 /* ContactUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactUtilities.swift; sourceTree = ""; }; - C31F812525258FB000DD9FD9 /* Storage+VolumeSamples.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Storage+VolumeSamples.swift"; sourceTree = ""; }; C31FFE56254A5FFE00F19441 /* KeyPairUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyPairUtilities.swift; sourceTree = ""; }; C328250E25CA06020062D0A7 /* VoiceMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageView.swift; sourceTree = ""; }; C328251E25CA3A900062D0A7 /* QuoteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuoteView.swift; sourceTree = ""; }; @@ -1536,7 +1531,6 @@ C35D0DB425AE5F1200B6BF49 /* UIEdgeInsets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIEdgeInsets.swift; sourceTree = ""; }; C35E8AA22485C72300ACB629 /* SwiftCSV.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftCSV.framework; path = ThirdParty/Carthage/Build/iOS/SwiftCSV.framework; sourceTree = ""; }; C35E8AAD2485E51D00ACB629 /* IP2Country.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IP2Country.swift; sourceTree = ""; }; - C364535B252467900045C478 /* AudioUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioUtilities.swift; sourceTree = ""; }; C374EEE125DA26740073A857 /* LinkPreviewModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkPreviewModal.swift; sourceTree = ""; }; C374EEEA25DA3CA70073A857 /* ConversationTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationTitleView.swift; sourceTree = ""; }; C374EEF325DB31D40073A857 /* VoiceMessageRecordingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VoiceMessageRecordingView.swift; sourceTree = ""; }; @@ -2048,7 +2042,6 @@ 4521C3BF1F59F3BA00B4C582 /* TextFieldHelper.swift */, 34D1F0BF1F8EC1760066283D /* MessageRecipientStatusUtils.swift */, B8544E3223D50E4900299F14 /* SNAppearance.swift */, - C364535B252467900045C478 /* AudioUtilities.swift */, C3D0972A2510499C00F6E3E4 /* BackgroundPoller.swift */, C31A6C5B247F2CF3001123EF /* CGRect+Utilities.swift */, C31D1DE8252172D4005D4DA8 /* ContactUtilities.swift */, @@ -2692,7 +2685,6 @@ isa = PBXGroup; children = ( B85A68B02587141A008CC492 /* Storage+Resetting.swift */, - C31F812525258FB000DD9FD9 /* Storage+VolumeSamples.swift */, ); path = Database; sourceTree = ""; @@ -2866,18 +2858,17 @@ isa = PBXGroup; children = ( C3E5C2F9251DBABB0040DFFC /* EditClosedGroupVC.swift */, - B88847BB23E10BC6009836D2 /* GroupMembersVC.swift */, B80A579E23DFF1F300876683 /* NewClosedGroupVC.swift */, ); path = "Closed Groups"; sourceTree = ""; }; - C36096A525AD18D7008B62B2 /* Basic Chats */ = { + C36096A525AD18D7008B62B2 /* DMs */ = { isa = PBXGroup; children = ( - B8CCF63623961D6D0091D419 /* NewPrivateChatVC.swift */, + B8CCF63623961D6D0091D419 /* NewDMVC.swift */, ); - path = "Basic Chats"; + path = DMs; sourceTree = ""; }; C36096AF25AD1932008B62B2 /* Sheets & Modals */ = { @@ -3589,11 +3580,11 @@ children = ( C3F0A58F255C8E3D007BE2A3 /* Meta */, C36096BC25AD1C3E008B62B2 /* Backups */, - C36096A525AD18D7008B62B2 /* Basic Chats */, C360969C25AD18BA008B62B2 /* Closed Groups */, B835246C25C38AA20089A44F /* Conversations */, C32C5D49256DD522003C73A2 /* Database */, C32B405424A961E1001117B5 /* Dependencies */, + C36096A525AD18D7008B62B2 /* DMs */, C360968E25AD16E8008B62B2 /* Home */, C36096BA25AD1B14008B62B2 /* Media Viewing & Editing */, C36096BB25AD1BBB008B62B2 /* Notifications */, @@ -4869,7 +4860,7 @@ buildActionMask = 2147483647; files = ( B8041AA725C90927003C2166 /* TypingIndicatorCell.swift in Sources */, - B8CCF63723961D6D0091D419 /* NewPrivateChatVC.swift in Sources */, + B8CCF63723961D6D0091D419 /* NewDMVC.swift in Sources */, 452EC6DF205E9E30000E787C /* MediaGalleryViewController.swift in Sources */, 3496956E21A301A100DCFE74 /* OWSBackupExportJob.m in Sources */, 4C1885D2218F8E1C00B67051 /* PhotoGridViewCell.swift in Sources */, @@ -4880,7 +4871,6 @@ B893063F2383961A005EAA8E /* ScanQRCodeWrapperVC.swift in Sources */, B879D449247E1BE300DB3608 /* PathVC.swift in Sources */, 454A84042059C787008B8C75 /* MediaTileViewController.swift in Sources */, - C364535C252467900045C478 /* AudioUtilities.swift in Sources */, 340FC8B4204DAC8D007AEB0F /* OWSBackupSettingsViewController.m in Sources */, 34D1F0871F8678AA0066283D /* ConversationViewItem.m in Sources */, 451A13B11E13DED2000A50FD /* AppNotifications.swift in Sources */, @@ -4968,7 +4958,6 @@ B8D84ECF25E3108A005A043E /* ExpandingAttachmentsButton.swift in Sources */, B8CCF6432397711F0091D419 /* SettingsVC.swift in Sources */, C354E75A23FE2A7600CE22E3 /* BaseVC.swift in Sources */, - C32C5D40256DD51E003C73A2 /* Storage+VolumeSamples.swift in Sources */, 3441FD9F21A3604F00BB9542 /* BackupRestoreViewController.swift in Sources */, 45C0DC1B1E68FE9000E04C47 /* UIApplication+OWS.swift in Sources */, 4539B5861F79348F007141FF /* PushRegistrationManager.swift in Sources */, @@ -5004,7 +4993,6 @@ 4521C3C01F59F3BA00B4C582 /* TextFieldHelper.swift in Sources */, 340FC8AC204DAC8D007AEB0F /* PrivacySettingsTableViewController.m in Sources */, B8569AE325CBB19A00DBA3DB /* DocumentView.swift in Sources */, - B88847BC23E10BC6009836D2 /* GroupMembersVC.swift in Sources */, B85357BF23A1AE0800AAF6CD /* SeedReminderView.swift in Sources */, B83786802586D296003CE78E /* KeyPairMigrationSheet.swift in Sources */, B821494F25D4E163009C0F2A /* BodyTextView.swift in Sources */, diff --git a/Session/Closed Groups/EditClosedGroupVC.swift b/Session/Closed Groups/EditClosedGroupVC.swift index 718ed683d..e3e65740c 100644 --- a/Session/Closed Groups/EditClosedGroupVC.swift +++ b/Session/Closed Groups/EditClosedGroupVC.swift @@ -1,5 +1,5 @@ -@objc(LKEditClosedGroupVC) +@objc(SNEditClosedGroupVC) final class EditClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelegate { private let thread: TSGroupThread private var name = "" @@ -271,9 +271,9 @@ final class EditClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelega Storage.write(with: { [weak self] transaction in do { if !members.contains(getUserHexEncodedPublicKey()) { - try MessageSender.v2_leave(groupPublicKey, using: transaction) + try MessageSender.leave(groupPublicKey, using: transaction) } else { - try MessageSender.v2_update(groupPublicKey, with: members, name: name, transaction: transaction) + try MessageSender.update(groupPublicKey, with: members, name: name, transaction: transaction) } } catch { DispatchQueue.main.async { diff --git a/Session/Closed Groups/GroupMembersVC.swift b/Session/Closed Groups/GroupMembersVC.swift deleted file mode 100644 index 2937f11e7..000000000 --- a/Session/Closed Groups/GroupMembersVC.swift +++ /dev/null @@ -1,156 +0,0 @@ - -@objc(LKGroupMembersVC) -final class GroupMembersVC : BaseVC, UITableViewDataSource { - private let thread: TSGroupThread - - private lazy var members: [String] = { - func getDisplayName(for hexEncodedPublicKey: String) -> String { - return Storage.shared.getContact(with: hexEncodedPublicKey)?.displayName(for: .regular) ?? hexEncodedPublicKey - } - return GroupUtilities.getClosedGroupMembers(thread).sorted { getDisplayName(for: $0) < getDisplayName(for: $1) } - }() - - // MARK: Components - @objc private lazy var tableView: UITableView = { - let result = UITableView() - result.dataSource = self - result.register(Cell.self, forCellReuseIdentifier: "Cell") - result.separatorStyle = .none - result.backgroundColor = .clear - result.showsVerticalScrollIndicator = false - result.alwaysBounceVertical = false - return result - }() - - // MARK: Lifecycle - @objc init(thread: TSGroupThread) { - self.thread = thread - super.init(nibName: nil, bundle: nil) - } - - required init?(coder: NSCoder) { fatalError("Using GroupMembersVC.init(nibName:bundle:) isn't allowed. Use GroupMembersVC.init(thread:) instead.") } - override init(nibName: String?, bundle: Bundle?) { fatalError("Using GroupMembersVC.init(nibName:bundle:) isn't allowed. Use GroupMembersVC.init(thread:) instead.") } - - override func viewDidLoad() { - super.viewDidLoad() - setUpGradientBackground() - setUpNavBarStyle() - setNavBarTitle("Group Members") - // Set up explanation label - let explanationLabel = UILabel() - explanationLabel.textColor = Colors.text.withAlphaComponent(Values.mediumOpacity) - explanationLabel.font = .systemFont(ofSize: Values.smallFontSize) - explanationLabel.text = "The ability to add members to a closed group is coming soon." - explanationLabel.numberOfLines = 0 - explanationLabel.textAlignment = .center - explanationLabel.lineBreakMode = .byWordWrapping - // Set up view hierarchy - view.addSubview(explanationLabel) - explanationLabel.pin(.leading, to: .leading, of: view, withInset: Values.largeSpacing) - explanationLabel.pin(.top, to: .top, of: view, withInset: Values.mediumSpacing) - explanationLabel.pin(.trailing, to: .trailing, of: view, withInset: -Values.largeSpacing) - let separator = UIView() - separator.backgroundColor = Colors.separator - separator.set(.height, to: Values.separatorThickness) - view.addSubview(separator) - separator.pin(.leading, to: .leading, of: view) - separator.pin(.top, to: .bottom, of: explanationLabel, withInset: Values.mediumSpacing) - separator.pin(.trailing, to: .trailing, of: view) - view.addSubview(tableView) - tableView.pin(.leading, to: .leading, of: view) - tableView.pin(.top, to: .bottom, of: separator) - tableView.pin(.trailing, to: .trailing, of: view) - tableView.pin(.bottom, to: .bottom, of: view) - } - - // MARK: Data - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return members.count - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! Cell - let contact = members[indexPath.row] - cell.hexEncodedPublicKey = contact - return cell - } - - @objc private func close() { - dismiss(animated: true, completion: nil) - } -} - -// MARK: - Cell - -private extension GroupMembersVC { - - final class Cell : UITableViewCell { - var hexEncodedPublicKey = "" { didSet { update() } } - - // MARK: Components - private lazy var profilePictureView = ProfilePictureView() - - private lazy var displayNameLabel: UILabel = { - let result = UILabel() - result.textColor = Colors.text - result.font = .boldSystemFont(ofSize: Values.mediumFontSize) - result.lineBreakMode = .byTruncatingTail - return result - }() - - private lazy var separator: UIView = { - let result = UIView() - result.backgroundColor = Colors.separator - result.set(.height, to: Values.separatorThickness) - return result - }() - - // MARK: Initialization - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - setUpViewHierarchy() - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - setUpViewHierarchy() - } - - private func setUpViewHierarchy() { - // Set the cell background color - backgroundColor = Colors.cellBackground - // Set up the highlight color - let selectedBackgroundView = UIView() - selectedBackgroundView.backgroundColor = .clear // Disabled for now - self.selectedBackgroundView = selectedBackgroundView - // Set up the profile picture image view - let profilePictureViewSize = Values.smallProfilePictureSize - profilePictureView.set(.width, to: profilePictureViewSize) - profilePictureView.set(.height, to: profilePictureViewSize) - profilePictureView.size = profilePictureViewSize - // Set up the main stack view - let stackView = UIStackView(arrangedSubviews: [ profilePictureView, displayNameLabel ]) - stackView.axis = .horizontal - stackView.alignment = .center - stackView.spacing = Values.mediumSpacing - stackView.set(.height, to: profilePictureViewSize) - contentView.addSubview(stackView) - stackView.pin(.leading, to: .leading, of: contentView, withInset: Values.mediumSpacing) - stackView.pin(.top, to: .top, of: contentView, withInset: Values.mediumSpacing) - contentView.pin(.bottom, to: .bottom, of: stackView, withInset: Values.mediumSpacing) - stackView.set(.width, to: UIScreen.main.bounds.width - 2 * Values.mediumSpacing) - // Set up the separator - addSubview(separator) - separator.pin(.leading, to: .leading, of: self) - separator.pin(.bottom, to: .bottom, of: self) - separator.set(.width, to: UIScreen.main.bounds.width) - } - - // MARK: Updating - private func update() { - profilePictureView.publicKey = hexEncodedPublicKey - profilePictureView.update() - displayNameLabel.text = Storage.shared.getContact(with: hexEncodedPublicKey)?.displayName(for: .regular) ?? hexEncodedPublicKey - } - } -} diff --git a/Session/Closed Groups/NewClosedGroupVC.swift b/Session/Closed Groups/NewClosedGroupVC.swift index 7b04f2a07..0489b556f 100644 --- a/Session/Closed Groups/NewClosedGroupVC.swift +++ b/Session/Closed Groups/NewClosedGroupVC.swift @@ -86,7 +86,7 @@ final class NewClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelegat explanationLabel.text = NSLocalizedString("vc_create_closed_group_empty_state_message", comment: "") let createNewPrivateChatButton = Button(style: .prominentOutline, size: .large) 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(createNewDM), for: UIControl.Event.touchUpInside) createNewPrivateChatButton.set(.width, to: 196) let stackView = UIStackView(arrangedSubviews: [ explanationLabel, createNewPrivateChatButton ]) stackView.axis = .vertical @@ -190,8 +190,8 @@ final class NewClosedGroupVC : BaseVC, UITableViewDataSource, UITableViewDelegat } } - @objc private func createNewPrivateChat() { + @objc private func createNewDM() { presentingViewController?.dismiss(animated: true, completion: nil) - SignalApp.shared().homeViewController!.createNewPrivateChat() + SignalApp.shared().homeViewController!.createNewDM() } } diff --git a/Session/Conversations/Settings/OWSConversationSettingsViewController.m b/Session/Conversations/Settings/OWSConversationSettingsViewController.m index f8ac191fb..cf9fe6a4f 100644 --- a/Session/Conversations/Settings/OWSConversationSettingsViewController.m +++ b/Session/Conversations/Settings/OWSConversationSettingsViewController.m @@ -809,7 +809,7 @@ CGFloat kIconViewLength = 24; - (void)editGroup { - LKEditClosedGroupVC *editClosedGroupVC = [[LKEditClosedGroupVC alloc] initWithThreadID:self.thread.uniqueId]; + SNEditClosedGroupVC *editClosedGroupVC = [[SNEditClosedGroupVC alloc] initWithThreadID:self.thread.uniqueId]; [self.navigationController pushViewController:editClosedGroupVC animated:YES completion:nil]; } @@ -858,7 +858,7 @@ CGFloat kIconViewLength = 24; if (gThread.isClosedGroup) { NSString *groupPublicKey = [LKGroupUtilities getDecodedGroupID:gThread.groupModel.groupId]; [LKStorage writeSyncWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { - [SNMessageSender v2_leaveClosedGroupWithPublicKey:groupPublicKey using:transaction error:nil]; + [SNMessageSender leaveClosedGroupWithPublicKey:groupPublicKey using:transaction error:nil]; }]; } diff --git a/Session/Basic Chats/NewPrivateChatVC.swift b/Session/DMs/NewDMVC.swift similarity index 94% rename from Session/Basic Chats/NewPrivateChatVC.swift rename to Session/DMs/NewDMVC.swift index 13d768444..d3254b47d 100644 --- a/Session/Basic Chats/NewPrivateChatVC.swift +++ b/Session/DMs/NewDMVC.swift @@ -1,5 +1,5 @@ -final class NewPrivateChatVC : BaseVC, UIPageViewControllerDataSource, UIPageViewControllerDelegate, OWSQRScannerDelegate { +final class NewDMVC : BaseVC, UIPageViewControllerDataSource, UIPageViewControllerDelegate, OWSQRScannerDelegate { private let pageVC = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil) private var pages: [UIViewController] = [] private var targetVCIndex: Int? @@ -21,13 +21,13 @@ final class NewPrivateChatVC : BaseVC, UIPageViewControllerDataSource, UIPageVie private lazy var enterPublicKeyVC: EnterPublicKeyVC = { let result = EnterPublicKeyVC() - result.newPrivateChatVC = self + result.NewDMVC = self return result }() private lazy var scanQRCodePlaceholderVC: ScanQRCodePlaceholderVC = { let result = ScanQRCodePlaceholderVC() - result.newPrivateChatVC = self + result.NewDMVC = self return result }() @@ -121,18 +121,18 @@ final class NewPrivateChatVC : BaseVC, UIPageViewControllerDataSource, UIPageVie func controller(_ controller: OWSQRCodeScanningViewController, didDetectQRCodeWith string: String) { let hexEncodedPublicKey = string - startNewPrivateChatIfPossible(with: hexEncodedPublicKey) + startNewDMIfPossible(with: hexEncodedPublicKey) } - fileprivate func startNewPrivateChatIfPossible(with onsNameOrPublicKey: String) { + fileprivate func startNewDMIfPossible(with onsNameOrPublicKey: String) { if ECKeyPair.isValidHexEncodedPublicKey(candidate: onsNameOrPublicKey) { - startNewPrivateChat(with: onsNameOrPublicKey) + startNewDM(with: onsNameOrPublicKey) } else { // This could be an ONS name ModalActivityIndicatorViewController.present(fromViewController: navigationController!, canCancel: false) { [weak self] modalActivityIndicator in SnodeAPI.getSessionID(for: onsNameOrPublicKey).done { sessionID in modalActivityIndicator.dismiss { - self?.startNewPrivateChat(with: sessionID) + self?.startNewDM(with: sessionID) } }.catch { error in modalActivityIndicator.dismiss { @@ -153,7 +153,7 @@ final class NewPrivateChatVC : BaseVC, UIPageViewControllerDataSource, UIPageVie } } - private func startNewPrivateChat(with sessionID: String) { + private func startNewDM(with sessionID: String) { let thread = TSContactThread.getOrCreateThread(contactId: sessionID) presentingViewController?.dismiss(animated: true, completion: nil) SignalApp.shared().presentConversation(for: thread, action: .compose, animated: false) @@ -161,7 +161,7 @@ final class NewPrivateChatVC : BaseVC, UIPageViewControllerDataSource, UIPageVie } private final class EnterPublicKeyVC : UIViewController { - weak var newPrivateChatVC: NewPrivateChatVC! + weak var NewDMVC: NewDMVC! private var isKeyboardShowing = false private var bottomConstraint: NSLayoutConstraint! @@ -226,7 +226,7 @@ private final class EnterPublicKeyVC : UIViewController { // Next button let nextButton = Button(style: .prominentOutline, size: .large) nextButton.setTitle(NSLocalizedString("next", comment: ""), for: UIControl.State.normal) - nextButton.addTarget(self, action: #selector(startNewPrivateChatIfPossible), for: UIControl.Event.touchUpInside) + nextButton.addTarget(self, action: #selector(startNewDMIfPossible), for: UIControl.Event.touchUpInside) let nextButtonContainer = UIView() nextButtonContainer.addSubview(nextButton) nextButton.pin(.leading, to: .leading, of: nextButtonContainer, withInset: 80) @@ -315,17 +315,17 @@ private final class EnterPublicKeyVC : UIViewController { @objc private func sharePublicKey() { let shareVC = UIActivityViewController(activityItems: [ getUserHexEncodedPublicKey() ], applicationActivities: nil) - newPrivateChatVC.navigationController!.present(shareVC, animated: true, completion: nil) + NewDMVC.navigationController!.present(shareVC, animated: true, completion: nil) } - @objc fileprivate func startNewPrivateChatIfPossible() { + @objc fileprivate func startNewDMIfPossible() { let text = publicKeyTextView.text?.trimmingCharacters(in: .whitespaces) ?? "" - newPrivateChatVC.startNewPrivateChatIfPossible(with: text) + NewDMVC.startNewDMIfPossible(with: text) } } private final class ScanQRCodePlaceholderVC : UIViewController { - weak var newPrivateChatVC: NewPrivateChatVC! + weak var NewDMVC: NewDMVC! override func viewDidLoad() { // Remove background color @@ -365,7 +365,7 @@ private final class ScanQRCodePlaceholderVC : UIViewController { @objc private func requestCameraAccess() { ows_ask(forCameraPermissions: { [weak self] hasCameraAccess in if hasCameraAccess { - self?.newPrivateChatVC.handleCameraAccessGranted() + self?.NewDMVC.handleCameraAccessGranted() } else { // Do nothing } diff --git a/Session/Database/Storage+VolumeSamples.swift b/Session/Database/Storage+VolumeSamples.swift deleted file mode 100644 index de82d4e5c..000000000 --- a/Session/Database/Storage+VolumeSamples.swift +++ /dev/null @@ -1,17 +0,0 @@ - -extension Storage { - - private static let volumeSamplesCollection = "LokiVolumeSamplesCollection" - - public func getVolumeSamples(for attachment: String) -> [Float]? { - var result: [Float]? - Storage.read { transaction in - result = transaction.object(forKey: attachment, inCollection: Storage.volumeSamplesCollection) as? [Float] - } - return result - } - - public func setVolumeSamples(for attachment: String, to volumeSamples: [Float], using transaction: Any) { - (transaction as! YapDatabaseReadWriteTransaction).setObject(volumeSamples, forKey: attachment, inCollection: Storage.volumeSamplesCollection) - } -} diff --git a/Session/Home/HomeVC.swift b/Session/Home/HomeVC.swift index 541429213..9fcff03ca 100644 --- a/Session/Home/HomeVC.swift +++ b/Session/Home/HomeVC.swift @@ -66,7 +66,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv explanationLabel.text = NSLocalizedString("vc_home_empty_state_message", comment: "") let createNewPrivateChatButton = Button(style: .prominentOutline, size: .large) 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(createNewDM), for: UIControl.Event.touchUpInside) createNewPrivateChatButton.set(.width, to: 196) let result = UIStackView(arrangedSubviews: [ explanationLabel, createNewPrivateChatButton ]) result.axis = .vertical @@ -138,7 +138,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv dbConnection.read { transaction in self.threads.update(with: transaction) // Perform the initial update } - // Pollers + // Start polling if needed (i.e. if the user just created or restored their Session ID) if OWSIdentityManager.shared().identityKeyPair() != nil { let appDelegate = UIApplication.shared.delegate as! AppDelegate appDelegate.startPollerIfNeeded() @@ -188,6 +188,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv } @objc private func handleYapDatabaseModifiedNotification(_ yapDatabase: YapDatabase) { + // This code is very finicky and crashes easily AssertIsOnMainThread() let notifications = dbConnection.beginLongLivedReadTransaction() // Jump to the latest commit guard !notifications.isEmpty else { return } @@ -360,7 +361,7 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv let groupID = thread.groupModel.groupId let groupPublicKey = LKGroupUtilities.getDecodedGroupID(groupID) do { - try MessageSender.v2_leave(groupPublicKey, using: transaction) + try MessageSender.leave(groupPublicKey, using: transaction) } catch { // TODO: Handle } @@ -391,13 +392,13 @@ final class HomeVC : BaseVC, UITableViewDataSource, UITableViewDelegate, NewConv present(navigationController, animated: true, completion: nil) } - @objc func createNewPrivateChat() { - let newPrivateChatVC = NewPrivateChatVC() - let navigationController = OWSNavigationController(rootViewController: newPrivateChatVC) + @objc func createNewDM() { + let newDMVC = NewDMVC() + let navigationController = OWSNavigationController(rootViewController: newDMVC) present(navigationController, animated: true, completion: nil) } - @objc func createNewClosedGroup() { + @objc func createClosedGroup() { let newClosedGroupVC = NewClosedGroupVC() let navigationController = OWSNavigationController(rootViewController: newClosedGroupVC) present(navigationController, animated: true, completion: nil) diff --git a/Session/Home/NewConversationButtonSet.swift b/Session/Home/NewConversationButtonSet.swift index b6f03a221..61ba617e8 100644 --- a/Session/Home/NewConversationButtonSet.swift +++ b/Session/Home/NewConversationButtonSet.swift @@ -17,8 +17,8 @@ final class NewConversationButtonSet : UIView { // MARK: Components private lazy var mainButton = NewConversationButton(isMainButton: true, icon: #imageLiteral(resourceName: "Plus").scaled(to: CGSize(width: iconSize, height: iconSize))) - private lazy var createNewPrivateChatButton = NewConversationButton(isMainButton: false, icon: #imageLiteral(resourceName: "Message").scaled(to: CGSize(width: iconSize, height: iconSize))) - private lazy var createNewClosedGroupButton = NewConversationButton(isMainButton: false, icon: #imageLiteral(resourceName: "Group").scaled(to: CGSize(width: iconSize, height: iconSize))) + private lazy var newDMButton = NewConversationButton(isMainButton: false, icon: #imageLiteral(resourceName: "Message").scaled(to: CGSize(width: iconSize, height: iconSize))) + private lazy var createClosedGroupButton = NewConversationButton(isMainButton: false, icon: #imageLiteral(resourceName: "Group").scaled(to: CGSize(width: iconSize, height: iconSize))) private lazy var joinOpenGroupButton = NewConversationButton(isMainButton: false, icon: #imageLiteral(resourceName: "Globe").scaled(to: CGSize(width: iconSize, height: iconSize))) // MARK: Initialization @@ -35,22 +35,22 @@ final class NewConversationButtonSet : UIView { private func setUpViewHierarchy() { mainButton.accessibilityLabel = "Toggle conversation options button" mainButton.isAccessibilityElement = true - createNewPrivateChatButton.accessibilityLabel = "Start new one-on-one conversation button" - createNewPrivateChatButton.isAccessibilityElement = true - createNewClosedGroupButton.accessibilityLabel = "Start new closed group button" - createNewClosedGroupButton.isAccessibilityElement = true + newDMButton.accessibilityLabel = "Start new one-on-one conversation button" + newDMButton.isAccessibilityElement = true + createClosedGroupButton.accessibilityLabel = "Start new closed group button" + createClosedGroupButton.isAccessibilityElement = true joinOpenGroupButton.accessibilityLabel = "Join open group button" joinOpenGroupButton.isAccessibilityElement = true let inset = (NewConversationButtonSet.expandedButtonSize - NewConversationButtonSet.collapsedButtonSize) / 2 addSubview(joinOpenGroupButton) horizontalButtonConstraints[joinOpenGroupButton] = joinOpenGroupButton.pin(.left, to: .left, of: self, withInset: inset) verticalButtonConstraints[joinOpenGroupButton] = joinOpenGroupButton.pin(.bottom, to: .bottom, of: self, withInset: -inset) - addSubview(createNewPrivateChatButton) - createNewPrivateChatButton.center(.horizontal, in: self) - verticalButtonConstraints[createNewPrivateChatButton] = createNewPrivateChatButton.pin(.top, to: .top, of: self, withInset: inset) - addSubview(createNewClosedGroupButton) - horizontalButtonConstraints[createNewClosedGroupButton] = createNewClosedGroupButton.pin(.right, to: .right, of: self, withInset: -inset) - verticalButtonConstraints[createNewClosedGroupButton] = createNewClosedGroupButton.pin(.bottom, to: .bottom, of: self, withInset: -inset) + addSubview(newDMButton) + newDMButton.center(.horizontal, in: self) + verticalButtonConstraints[newDMButton] = newDMButton.pin(.top, to: .top, of: self, withInset: inset) + addSubview(createClosedGroupButton) + horizontalButtonConstraints[createClosedGroupButton] = createClosedGroupButton.pin(.right, to: .right, of: self, withInset: -inset) + verticalButtonConstraints[createClosedGroupButton] = createClosedGroupButton.pin(.bottom, to: .bottom, of: self, withInset: -inset) addSubview(mainButton) mainButton.center(.horizontal, in: self) mainButton.pin(.bottom, to: .bottom, of: self, withInset: -inset) @@ -63,25 +63,25 @@ final class NewConversationButtonSet : UIView { let joinOpenGroupButtonTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleJoinOpenGroupButtonTapped)) joinOpenGroupButton.addGestureRecognizer(joinOpenGroupButtonTapGestureRecognizer) let createNewPrivateChatButtonTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleCreateNewPrivateChatButtonTapped)) - createNewPrivateChatButton.addGestureRecognizer(createNewPrivateChatButtonTapGestureRecognizer) + newDMButton.addGestureRecognizer(createNewPrivateChatButtonTapGestureRecognizer) let createNewClosedGroupButtonTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleCreateNewClosedGroupButtonTapped)) - createNewClosedGroupButton.addGestureRecognizer(createNewClosedGroupButtonTapGestureRecognizer) + createClosedGroupButton.addGestureRecognizer(createNewClosedGroupButtonTapGestureRecognizer) } // MARK: Interaction @objc private func handleJoinOpenGroupButtonTapped() { delegate?.joinOpenGroup() } - @objc private func handleCreateNewPrivateChatButtonTapped() { delegate?.createNewPrivateChat() } - @objc private func handleCreateNewClosedGroupButtonTapped() { delegate?.createNewClosedGroup() } + @objc private func handleCreateNewPrivateChatButtonTapped() { delegate?.createNewDM() } + @objc private func handleCreateNewClosedGroupButtonTapped() { delegate?.createClosedGroup() } private func expand(isUserDragging: Bool) { - let buttons = [ joinOpenGroupButton, createNewPrivateChatButton, createNewClosedGroupButton ] + let buttons = [ joinOpenGroupButton, newDMButton, createClosedGroupButton ] UIView.animate(withDuration: 0.25, animations: { buttons.forEach { $0.alpha = 1 } let inset = (NewConversationButtonSet.expandedButtonSize - NewConversationButtonSet.collapsedButtonSize) / 2 let size = NewConversationButtonSet.collapsedButtonSize self.joinOpenGroupButton.frame = CGRect(origin: CGPoint(x: inset, y: self.height() - size - inset), size: CGSize(width: size, height: size)) - self.createNewPrivateChatButton.frame = CGRect(center: CGPoint(x: self.bounds.center.x, y: inset + size / 2), size: CGSize(width: size, height: size)) - self.createNewClosedGroupButton.frame = CGRect(origin: CGPoint(x: self.width() - size - inset, y: self.height() - size - inset), size: CGSize(width: size, height: size)) + self.newDMButton.frame = CGRect(center: CGPoint(x: self.bounds.center.x, y: inset + size / 2), size: CGSize(width: size, height: size)) + self.createClosedGroupButton.frame = CGRect(origin: CGPoint(x: self.width() - size - inset, y: self.height() - size - inset), size: CGSize(width: size, height: size)) }, completion: { _ in self.isUserDragging = isUserDragging }) @@ -89,7 +89,7 @@ final class NewConversationButtonSet : UIView { private func collapse(withAnimation isAnimated: Bool) { isUserDragging = false - let buttons = [ joinOpenGroupButton, createNewPrivateChatButton, createNewClosedGroupButton ] + let buttons = [ joinOpenGroupButton, newDMButton, createClosedGroupButton ] UIView.animate(withDuration: isAnimated ? 0.25 : 0) { buttons.forEach { button in button.alpha = 0 @@ -126,12 +126,12 @@ final class NewConversationButtonSet : UIView { let touchLocationInSelfCoordinates = touch.location(in: self) mainButton.frame = CGRect(center: touchLocationInSelfCoordinates, size: mainButtonSize) mainButton.alpha = 1 - (touchLocationInSelfCoordinates.distance(to: mainButtonLocationInSelfCoordinates) / maxDragDistance) - let buttons = [ joinOpenGroupButton, createNewPrivateChatButton, createNewClosedGroupButton ] + let buttons = [ joinOpenGroupButton, newDMButton, createClosedGroupButton ] let buttonToExpand = buttons.first { button in var hasUserDraggedBeyondButton = false if button == joinOpenGroupButton && touch.isLeft(of: joinOpenGroupButton, with: dragMargin) { hasUserDraggedBeyondButton = true } - if button == createNewPrivateChatButton && touch.isAbove(createNewPrivateChatButton, with: dragMargin) { hasUserDraggedBeyondButton = true } - if button == createNewClosedGroupButton && touch.isRight(of: createNewClosedGroupButton, with: dragMargin) { hasUserDraggedBeyondButton = true } + if button == newDMButton && touch.isAbove(newDMButton, with: dragMargin) { hasUserDraggedBeyondButton = true } + if button == createClosedGroupButton && touch.isRight(of: createClosedGroupButton, with: dragMargin) { hasUserDraggedBeyondButton = true } return button.contains(touch) || hasUserDraggedBeyondButton } if let buttonToExpand = buttonToExpand { @@ -148,8 +148,8 @@ final class NewConversationButtonSet : UIView { override func touchesEnded(_ touches: Set, with event: UIEvent?) { guard let touch = touches.first, isUserDragging else { return } if joinOpenGroupButton.contains(touch) || touch.isLeft(of: joinOpenGroupButton, with: dragMargin) { delegate?.joinOpenGroup() } - else if createNewPrivateChatButton.contains(touch) || touch.isAbove(createNewPrivateChatButton, with: dragMargin) { delegate?.createNewPrivateChat() } - else if createNewClosedGroupButton.contains(touch) || touch.isRight(of: createNewClosedGroupButton, with: dragMargin) { delegate?.createNewClosedGroup() } + else if newDMButton.contains(touch) || touch.isAbove(newDMButton, with: dragMargin) { delegate?.createNewDM() } + else if createClosedGroupButton.contains(touch) || touch.isRight(of: createClosedGroupButton, with: dragMargin) { delegate?.createClosedGroup() } reset() } @@ -181,11 +181,11 @@ final class NewConversationButtonSet : UIView { if joinOpenGroupButton == expandedButton { horizontalButtonConstraints[joinOpenGroupButton]!.constant = inset verticalButtonConstraints[joinOpenGroupButton]!.constant = -inset - } else if createNewPrivateChatButton == expandedButton { - verticalButtonConstraints[createNewPrivateChatButton]!.constant = inset - } else if createNewClosedGroupButton == expandedButton { - horizontalButtonConstraints[createNewClosedGroupButton]!.constant = -inset - verticalButtonConstraints[createNewClosedGroupButton]!.constant = -inset + } else if newDMButton == expandedButton { + verticalButtonConstraints[newDMButton]!.constant = inset + } else if createClosedGroupButton == expandedButton { + horizontalButtonConstraints[createClosedGroupButton]!.constant = -inset + verticalButtonConstraints[createClosedGroupButton]!.constant = -inset } let size = NewConversationButtonSet.collapsedButtonSize let frame = CGRect(center: button.center, size: CGSize(width: size, height: size)) @@ -203,7 +203,7 @@ final class NewConversationButtonSet : UIView { } override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { - let allButtons = [ mainButton, joinOpenGroupButton, createNewPrivateChatButton, createNewClosedGroupButton ] + let allButtons = [ mainButton, joinOpenGroupButton, newDMButton, createClosedGroupButton ] if allButtons.contains(where: { $0.frame.contains(point) }) { return super.hitTest(point, with: event) } else { @@ -217,8 +217,8 @@ final class NewConversationButtonSet : UIView { protocol NewConversationButtonSetDelegate { func joinOpenGroup() - func createNewPrivateChat() - func createNewClosedGroup() + func createNewDM() + func createClosedGroup() } // MARK: Button diff --git a/Session/Meta/AppDelegate.m b/Session/Meta/AppDelegate.m index 921d0b0ac..65bbc43f8 100644 --- a/Session/Meta/AppDelegate.m +++ b/Session/Meta/AppDelegate.m @@ -658,7 +658,7 @@ static NSTimeInterval launchStartedAt; [AppReadiness runNowOrWhenAppDidBecomeReady:^{ if (![self.tsAccountManager isRegisteredAndReady]) { return; } - [SignalApp.sharedApp.homeViewController createNewPrivateChat]; + [SignalApp.sharedApp.homeViewController createNewDM]; completionHandler(YES); }]; } diff --git a/Session/Onboarding/Onboarding.swift b/Session/Onboarding/Onboarding.swift index 779975497..2166affe7 100644 --- a/Session/Onboarding/Onboarding.swift +++ b/Session/Onboarding/Onboarding.swift @@ -12,13 +12,19 @@ enum Onboarding { switch self { case .register: userDefaults[.hasViewedSeed] = false + // Set hasSyncedInitialConfiguration to true so that when we hit the home screen a configuration sync + // is triggered (yes, the logic is a bit weird). This is needed so that if the user registers and + // immediately links a device, there'll be a configuration in their swarm. userDefaults[.hasSyncedInitialConfiguration] = true case .recover, .link: - userDefaults[.hasViewedSeed] = true + userDefaults[.hasViewedSeed] = true // No need to show it again if the user is restoring or linking userDefaults[.hasSyncedInitialConfiguration] = false } switch self { case .register, .recover: + // Set both lastDisplayNameUpdate and lastProfilePictureUpdate to the current date, so that + // we don't overwrite what the user set in the display name step with whatever we find in + // their swarm. userDefaults[.lastDisplayNameUpdate] = Date() userDefaults[.lastProfilePictureUpdate] = Date() case .link: break diff --git a/Session/Utilities/AudioUtilities.swift b/Session/Utilities/AudioUtilities.swift deleted file mode 100644 index 858fc5b8f..000000000 --- a/Session/Utilities/AudioUtilities.swift +++ /dev/null @@ -1,190 +0,0 @@ -import Accelerate -import PromiseKit - -enum AudioUtilities { - private static let noiseFloor: Float = -80 - - private struct FileInfo { - let sampleCount: Int - let asset: AVAsset - let track: AVAssetTrack - } - - enum Error : LocalizedError { - case noAudioTrack - case noAudioFormatDescription - case loadingFailed - case parsingFailed - - var errorDescription: String? { - switch self { - case .noAudioTrack: return "No audio track." - case .noAudioFormatDescription: return "No audio format description." - case .loadingFailed: return "Couldn't load asset." - case .parsingFailed: return "Couldn't parse asset." - } - } - } - - static func getVolumeSamples(for audioFileURL: URL, targetSampleCount: Int) -> Promise<[Float]> { - return loadFile(audioFileURL).then { fileInfo in - AudioUtilities.parseSamples(from: fileInfo, with: targetSampleCount) - } - } - - private static func loadFile(_ audioFileURL: URL, isRetry: Bool = false) -> Promise { - let asset = AVURLAsset(url: audioFileURL) - guard let track = asset.tracks(withMediaType: AVMediaType.audio).first else { - if isRetry { - return Promise(error: Error.loadingFailed) - } else { - // Workaround for issue where MP3 files sent by Android get saved as M4A - var newAudioFileURL = audioFileURL.deletingPathExtension() - let fileName = newAudioFileURL.lastPathComponent - newAudioFileURL = newAudioFileURL.deletingLastPathComponent() - newAudioFileURL = newAudioFileURL.appendingPathComponent("\(fileName).mp3") - let fileManager = FileManager.default - if fileManager.fileExists(atPath: newAudioFileURL.path) { - return loadFile(newAudioFileURL, isRetry: true) - } else { - do { - try FileManager.default.copyItem(at: audioFileURL, to: newAudioFileURL) - } catch { - return Promise(error: Error.loadingFailed) - } - return loadFile(newAudioFileURL, isRetry: true) - } - } - } - let (promise, seal) = Promise.pending() - asset.loadValuesAsynchronously(forKeys: [ #keyPath(AVAsset.duration) ]) { - var nsError: NSError? - let status = asset.statusOfValue(forKey: #keyPath(AVAsset.duration), error: &nsError) - switch status { - case .loaded: - guard let formatDescriptions = track.formatDescriptions as? [CMAudioFormatDescription], - let audioFormatDescription = formatDescriptions.first, - let asbd = CMAudioFormatDescriptionGetStreamBasicDescription(audioFormatDescription) - else { return seal.reject(Error.noAudioFormatDescription) } - let sampleCount = Int((asbd.pointee.mSampleRate) * Float64(asset.duration.value) / Float64(asset.duration.timescale)) - let fileInfo = FileInfo(sampleCount: sampleCount, asset: asset, track: track) - seal.fulfill(fileInfo) - default: - print("Couldn't load asset due to error: \(nsError?.localizedDescription ?? "no description provided").") - seal.reject(Error.loadingFailed) - } - } - return promise - } - - private static func parseSamples(from fileInfo: FileInfo, with targetSampleCount: Int) -> Promise<[Float]> { - // Prepare the reader - guard let reader = try? AVAssetReader(asset: fileInfo.asset) else { return Promise(error: Error.parsingFailed) } - let range = 0..? - CMBlockBufferGetDataPointer(readBuffer, - atOffset: 0, - lengthAtOffsetOut: &readBufferLength, - totalLengthOut: nil, - dataPointerOut: &readBufferPointer) - sampleBuffer.append(UnsafeBufferPointer(start: readBufferPointer, count: readBufferLength)) - CMSampleBufferInvalidate(readSampleBuffer) - let sampleCount = sampleBuffer.count / MemoryLayout.size - let downSampledLength = sampleCount / samplesPerPixel - let samplesToProcess = downSampledLength * samplesPerPixel - guard samplesToProcess > 0 else { continue } - processSamples(from: &sampleBuffer, - outputSamples: &result, - samplesToProcess: samplesToProcess, - downSampledLength: downSampledLength, - samplesPerPixel: samplesPerPixel, - filter: filter) - } - // Process any remaining samples - let samplesToProcess = sampleBuffer.count / MemoryLayout.size - if samplesToProcess > 0 { - let downSampledLength = 1 - let samplesPerPixel = samplesToProcess - let filter = [Float](repeating: 1.0 / Float(samplesPerPixel), count: samplesPerPixel) - processSamples(from: &sampleBuffer, - outputSamples: &result, - samplesToProcess: samplesToProcess, - downSampledLength: downSampledLength, - samplesPerPixel: samplesPerPixel, - filter: filter) - } - guard reader.status == .completed else { return Promise(error: Error.parsingFailed) } - // Return - return Promise { $0.fulfill(result) } - } - - private static func processSamples(from sampleBuffer: inout Data, outputSamples: inout [Float], samplesToProcess: Int, - downSampledLength: Int, samplesPerPixel: Int, filter: [Float]) { - sampleBuffer.withUnsafeBytes { (samples: UnsafeRawBufferPointer) in - var processingBuffer = [Float](repeating: 0, count: samplesToProcess) - let sampleCount = vDSP_Length(samplesToProcess) - // Create an UnsafePointer from the samples - let unsafeBufferPointer = samples.bindMemory(to: Int16.self) - let unsafePointer = unsafeBufferPointer.baseAddress! - // Convert 16 bit int samples to floats - vDSP_vflt16(unsafePointer, 1, &processingBuffer, 1, sampleCount) - // Take the absolute values to get the amplitude - vDSP_vabs(processingBuffer, 1, &processingBuffer, 1, sampleCount) - // Get the corresponding dB values and clip the results - getdB(from: &processingBuffer) - // Downsample and average - var downSampledData = [Float](repeating: 0, count: downSampledLength) - vDSP_desamp(processingBuffer, - vDSP_Stride(samplesPerPixel), - filter, - &downSampledData, - vDSP_Length(downSampledLength), - vDSP_Length(samplesPerPixel)) - // Remove the processed samples - sampleBuffer.removeFirst(samplesToProcess * MemoryLayout.size) - // Update the output samples - outputSamples += downSampledData - } - } - - static func getdB(from normalizedSamples: inout [Float]) { - // Convert samples to a log scale - var zero: Float = 32768.0 - vDSP_vdbcon(normalizedSamples, 1, &zero, &normalizedSamples, 1, vDSP_Length(normalizedSamples.count), 1) - // Clip to [noiseFloor, 0] - var ceil: Float = 0.0 - var noiseFloorMutable = AudioUtilities.noiseFloor - vDSP_vclip(normalizedSamples, 1, &noiseFloorMutable, &ceil, &normalizedSamples, 1, vDSP_Length(normalizedSamples.count)) - } -} diff --git a/SessionMessagingKit/Sending & Receiving/MessageSender+ClosedGroups.swift b/SessionMessagingKit/Sending & Receiving/MessageSender+ClosedGroups.swift index 976476f38..71ed19990 100644 --- a/SessionMessagingKit/Sending & Receiving/MessageSender+ClosedGroups.swift +++ b/SessionMessagingKit/Sending & Receiving/MessageSender+ClosedGroups.swift @@ -85,7 +85,7 @@ extension MessageSender { } } - public static func v2_update(_ groupPublicKey: String, with members: Set, name: String, transaction: YapDatabaseReadWriteTransaction) throws { + public static func update(_ groupPublicKey: String, with members: Set, name: String, transaction: YapDatabaseReadWriteTransaction) throws { // Get the group, check preconditions & prepare let groupID = LKGroupUtilities.getEncodedClosedGroupIDAsData(groupPublicKey) let threadID = TSGroupThread.threadId(fromGroupId: groupID) @@ -208,8 +208,8 @@ extension MessageSender { infoMessage.save(with: transaction) } - @objc(v2_leaveClosedGroupWithPublicKey:using:error:) - public static func v2_leave(_ groupPublicKey: String, using transaction: YapDatabaseReadWriteTransaction) throws { + @objc(leaveClosedGroupWithPublicKey:using:error:) + public static func leave(_ groupPublicKey: String, using transaction: YapDatabaseReadWriteTransaction) throws { // Get the group, check preconditions & prepare let groupID = LKGroupUtilities.getEncodedClosedGroupIDAsData(groupPublicKey) let threadID = TSGroupThread.threadId(fromGroupId: groupID)