Fixed a few more QA issues, added a minor feature
Updated the document download UI Minor font tweaks to match settings more closely Added profile data to the MessageRequestResponse Fixed the broken tests
This commit is contained in:
parent
93e12a3fcb
commit
0c09f2bfc5
|
@ -671,7 +671,6 @@
|
|||
FD71160028C8253500B47552 /* UIView+Combine.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD7115FF28C8253500B47552 /* UIView+Combine.swift */; };
|
||||
FD71160228C8255900B47552 /* UIControl+Combine.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD71160128C8255900B47552 /* UIControl+Combine.swift */; };
|
||||
FD71160428C95B5600B47552 /* PhotoCollectionPickerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD71160328C95B5600B47552 /* PhotoCollectionPickerViewModel.swift */; };
|
||||
FD71160C28D00BAE00B47552 /* SessionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD71160B28D00BAE00B47552 /* SessionTests.swift */; };
|
||||
FD71161528D00D6700B47552 /* ThreadDisappearingMessagesViewModelSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD71161428D00D6700B47552 /* ThreadDisappearingMessagesViewModelSpec.swift */; };
|
||||
FD71161728D00DA400B47552 /* ThreadSettingsViewModelSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD71161628D00DA400B47552 /* ThreadSettingsViewModelSpec.swift */; };
|
||||
FD71161A28D00E1100B47552 /* NotificationContentViewModelSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD71161928D00E1100B47552 /* NotificationContentViewModelSpec.swift */; };
|
||||
|
@ -1756,7 +1755,6 @@
|
|||
FD71160128C8255900B47552 /* UIControl+Combine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIControl+Combine.swift"; sourceTree = "<group>"; };
|
||||
FD71160328C95B5600B47552 /* PhotoCollectionPickerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoCollectionPickerViewModel.swift; sourceTree = "<group>"; };
|
||||
FD71160928D00BAE00B47552 /* SessionTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SessionTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
FD71160B28D00BAE00B47552 /* SessionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionTests.swift; sourceTree = "<group>"; };
|
||||
FD71161428D00D6700B47552 /* ThreadDisappearingMessagesViewModelSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadDisappearingMessagesViewModelSpec.swift; sourceTree = "<group>"; };
|
||||
FD71161628D00DA400B47552 /* ThreadSettingsViewModelSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadSettingsViewModelSpec.swift; sourceTree = "<group>"; };
|
||||
FD71161928D00E1100B47552 /* NotificationContentViewModelSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationContentViewModelSpec.swift; sourceTree = "<group>"; };
|
||||
|
@ -3788,7 +3786,6 @@
|
|||
children = (
|
||||
FD71161228D00D5300B47552 /* Conversations */,
|
||||
FD71161828D00E0100B47552 /* Settings */,
|
||||
FD71160B28D00BAE00B47552 /* SessionTests.swift */,
|
||||
);
|
||||
path = SessionTests;
|
||||
sourceTree = "<group>";
|
||||
|
@ -5758,7 +5755,6 @@
|
|||
FD71161728D00DA400B47552 /* ThreadSettingsViewModelSpec.swift in Sources */,
|
||||
FD71161528D00D6700B47552 /* ThreadDisappearingMessagesViewModelSpec.swift in Sources */,
|
||||
FD71161A28D00E1100B47552 /* NotificationContentViewModelSpec.swift in Sources */,
|
||||
FD71160C28D00BAE00B47552 /* SessionTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -5,8 +5,6 @@ import SessionUIKit
|
|||
import SessionMessagingKit
|
||||
|
||||
final class DocumentView: UIView {
|
||||
private static let iconImageViewSize: CGSize = CGSize(width: 31, height: 40)
|
||||
|
||||
// MARK: - Lifecycle
|
||||
|
||||
init(attachment: Attachment, textColor: ThemeValue) {
|
||||
|
@ -24,18 +22,23 @@ final class DocumentView: UIView {
|
|||
}
|
||||
|
||||
private func setUpViewHierarchy(attachment: Attachment, textColor: ThemeValue) {
|
||||
// Image view
|
||||
let imageView = UIImageView(image: UIImage(named: "File")?.withRenderingMode(.alwaysTemplate))
|
||||
imageView.themeTintColor = textColor
|
||||
imageView.contentMode = .center
|
||||
let imageBackgroundView: UIView = UIView()
|
||||
imageBackgroundView.themeBackgroundColor = .messageBubble_overlay
|
||||
addSubview(imageBackgroundView)
|
||||
|
||||
let iconImageViewSize = DocumentView.iconImageViewSize
|
||||
imageView.set(.width, to: iconImageViewSize.width)
|
||||
imageView.set(.height, to: iconImageViewSize.height)
|
||||
// Image view
|
||||
let imageView = UIImageView(
|
||||
image: UIImage(systemName: "doc")?
|
||||
.withRenderingMode(.alwaysTemplate)
|
||||
)
|
||||
imageView.setContentCompressionResistancePriority(.required, for: .horizontal)
|
||||
imageView.setContentHuggingPriority(.required, for: .horizontal)
|
||||
imageView.themeTintColor = textColor
|
||||
imageView.set(.height, to: 22)
|
||||
|
||||
// Body label
|
||||
let titleLabel = UILabel()
|
||||
titleLabel.font = .systemFont(ofSize: Values.smallFontSize, weight: .light)
|
||||
titleLabel.font = .systemFont(ofSize: Values.mediumFontSize)
|
||||
titleLabel.text = (attachment.sourceFilename ?? "File")
|
||||
titleLabel.themeTextColor = textColor
|
||||
titleLabel.lineBreakMode = .byTruncatingTail
|
||||
|
@ -51,12 +54,41 @@ final class DocumentView: UIView {
|
|||
let labelStackView = UIStackView(arrangedSubviews: [ titleLabel, sizeLabel ])
|
||||
labelStackView.axis = .vertical
|
||||
|
||||
// Download image view
|
||||
let downloadImageView = UIImageView(
|
||||
image: UIImage(systemName: "arrow.down")?
|
||||
.withRenderingMode(.alwaysTemplate)
|
||||
)
|
||||
downloadImageView.setContentCompressionResistancePriority(.required, for: .horizontal)
|
||||
downloadImageView.setContentHuggingPriority(.required, for: .horizontal)
|
||||
downloadImageView.themeTintColor = textColor
|
||||
downloadImageView.set(.height, to: 16)
|
||||
|
||||
// Stack view
|
||||
let stackView = UIStackView(arrangedSubviews: [ imageView, labelStackView ])
|
||||
let stackView = UIStackView(
|
||||
arrangedSubviews: [
|
||||
imageView,
|
||||
UIView.spacer(withWidth: 0),
|
||||
labelStackView,
|
||||
downloadImageView
|
||||
]
|
||||
)
|
||||
stackView.axis = .horizontal
|
||||
stackView.spacing = Values.verySmallSpacing
|
||||
stackView.spacing = Values.mediumSpacing
|
||||
stackView.alignment = .center
|
||||
stackView.layoutMargins = UIEdgeInsets(
|
||||
top: Values.smallSpacing,
|
||||
leading: Values.mediumSpacing,
|
||||
bottom: Values.smallSpacing,
|
||||
trailing: Values.mediumSpacing
|
||||
)
|
||||
stackView.isLayoutMarginsRelativeArrangement = true
|
||||
addSubview(stackView)
|
||||
stackView.pin(to: self)
|
||||
|
||||
imageBackgroundView.pin(.top, to: .top, of: self)
|
||||
imageBackgroundView.pin(.leading, to: .leading, of: self)
|
||||
imageBackgroundView.pin(.trailing, to: .trailing, of: imageView, withInset: Values.mediumSpacing)
|
||||
imageBackgroundView.pin(.bottom, to: .bottom, of: self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -589,7 +589,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
|
|||
|
||||
let inset: CGFloat = 12
|
||||
let maxWidth = (VisibleMessageCell.getMaxWidth(for: cellViewModel) - 2 * inset)
|
||||
|
||||
|
||||
// Stack view
|
||||
let stackView = UIStackView(arrangedSubviews: [])
|
||||
stackView.axis = .vertical
|
||||
|
@ -601,6 +601,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
|
|||
|
||||
// Body text view
|
||||
if let body: String = cellViewModel.body, !body.isEmpty { // delegate should always be set at this point
|
||||
let bodyContainerView: UIView = UIView()
|
||||
let bodyTappableLabel = VisibleMessageCell.getBodyTappableLabel(
|
||||
for: cellViewModel,
|
||||
with: maxWidth,
|
||||
|
@ -610,11 +611,16 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
|
|||
)
|
||||
|
||||
self.bodyTappableLabel = bodyTappableLabel
|
||||
stackView.addArrangedSubview(bodyTappableLabel)
|
||||
bodyContainerView.addSubview(bodyTappableLabel)
|
||||
bodyTappableLabel.pin(.top, to: .top, of: bodyContainerView)
|
||||
bodyTappableLabel.pin(.leading, to: .leading, of: bodyContainerView, withInset: 12)
|
||||
bodyTappableLabel.pin(.trailing, to: .trailing, of: bodyContainerView, withInset: -12)
|
||||
bodyTappableLabel.pin(.bottom, to: .bottom, of: bodyContainerView, withInset: -12)
|
||||
stackView.addArrangedSubview(bodyContainerView)
|
||||
}
|
||||
|
||||
bubbleView.addSubview(stackView)
|
||||
stackView.pin(to: bubbleView, withInset: inset)
|
||||
stackView.pin(to: bubbleView)
|
||||
snContentView.addArrangedSubview(bubbleBackgroundView)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ class ThreadDisappearingMessagesViewModel: SessionTableViewModel<ThreadDisappear
|
|||
|
||||
// MARK: - Variables
|
||||
|
||||
private let storage: Storage
|
||||
private let scheduler: ValueObservationScheduler
|
||||
private let threadId: String
|
||||
private let config: DisappearingMessagesConfiguration
|
||||
private var storedSelection: TimeInterval
|
||||
|
@ -35,7 +37,14 @@ class ThreadDisappearingMessagesViewModel: SessionTableViewModel<ThreadDisappear
|
|||
|
||||
// MARK: - Initialization
|
||||
|
||||
init(threadId: String, config: DisappearingMessagesConfiguration) {
|
||||
init(
|
||||
storage: Storage = Storage.shared,
|
||||
scheduling scheduler: ValueObservationScheduler = Storage.defaultPublisherScheduler,
|
||||
threadId: String,
|
||||
config: DisappearingMessagesConfiguration
|
||||
) {
|
||||
self.storage = storage
|
||||
self.scheduler = scheduler
|
||||
self.threadId = threadId
|
||||
self.config = config
|
||||
self.storedSelection = (config.isEnabled ? config.durationSeconds : 0)
|
||||
|
@ -92,7 +101,7 @@ class ThreadDisappearingMessagesViewModel: SessionTableViewModel<ThreadDisappear
|
|||
/// fetch (after the ones in `ValueConcurrentObserver.asyncStart`/`ValueConcurrentObserver.syncStart`)
|
||||
/// just in case the database has changed between the two reads - unfortunately it doesn't look like there is a way to prevent this
|
||||
private lazy var _observableSettingsData: ObservableData = ValueObservation
|
||||
.trackingConstantRegion { [weak self, config = self.config] db -> [SectionModel] in
|
||||
.trackingConstantRegion { [weak self, config] db -> [SectionModel] in
|
||||
return [
|
||||
SectionModel(
|
||||
model: .content,
|
||||
|
@ -127,7 +136,7 @@ class ThreadDisappearingMessagesViewModel: SessionTableViewModel<ThreadDisappear
|
|||
]
|
||||
}
|
||||
.removeDuplicates()
|
||||
.publisher(in: Storage.shared)
|
||||
.publisher(in: storage, scheduling: scheduler)
|
||||
|
||||
// MARK: - Functions
|
||||
|
||||
|
@ -146,7 +155,7 @@ class ThreadDisappearingMessagesViewModel: SessionTableViewModel<ThreadDisappear
|
|||
|
||||
guard self.config != updatedConfig else { return }
|
||||
|
||||
Storage.shared.writeAsync { db in
|
||||
storage.writeAsync { db in
|
||||
guard let thread: SessionThread = try SessionThread.fetchOne(db, id: threadId) else {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -319,7 +319,6 @@
|
|||
"vc_settings_notifications_button_title" = "اعلانها";
|
||||
"vc_settings_recovery_phrase_button_title" = "عبارت بازیابی";
|
||||
"vc_settings_clear_all_data_button_title" = "پاک کردن اطلاعات";
|
||||
"NOTIFICATIONS_TITLE" = "Notifiche";
|
||||
"vc_qr_code_title" = "کد QR";
|
||||
"vc_qr_code_view_my_qr_code_tab_title" = "مشاهده کد QR من";
|
||||
"vc_qr_code_view_scan_qr_code_tab_title" = "اسکن کد QR";
|
||||
|
|
|
@ -9,11 +9,16 @@ import SessionUtilitiesKit
|
|||
|
||||
class NotificationContentViewModel: SessionTableViewModel<NoNav, NotificationSettingsViewModel.Section, Preferences.NotificationPreviewType> {
|
||||
private let storage: Storage
|
||||
private let scheduler: ValueObservationScheduler
|
||||
|
||||
// MARK: - Initialization
|
||||
|
||||
init(storage: Storage = Storage.shared) {
|
||||
init(
|
||||
storage: Storage = Storage.shared,
|
||||
scheduling scheduler: ValueObservationScheduler = Storage.defaultPublisherScheduler
|
||||
) {
|
||||
self.storage = storage
|
||||
self.scheduler = scheduler
|
||||
}
|
||||
|
||||
// MARK: - Section
|
||||
|
@ -67,7 +72,7 @@ class NotificationContentViewModel: SessionTableViewModel<NoNav, NotificationSet
|
|||
]
|
||||
}
|
||||
.removeDuplicates()
|
||||
.publisher(in: storage)
|
||||
.publisher(in: storage, scheduling: scheduler)
|
||||
|
||||
// MARK: - Functions
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import SessionUtilitiesKit
|
|||
public enum NoNav: Equatable {}
|
||||
|
||||
extension SessionTableViewModel {
|
||||
public struct NavItem {
|
||||
public struct NavItem: Equatable {
|
||||
let id: NavItemId
|
||||
let image: UIImage?
|
||||
let style: UIBarButtonItem.Style
|
||||
|
@ -65,5 +65,20 @@ extension SessionTableViewModel {
|
|||
accessibilityIdentifier: accessibilityIdentifier
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - Conformance
|
||||
|
||||
public static func == (
|
||||
lhs: SessionTableViewModel<NavItemId, Section, SettingItem>.NavItem,
|
||||
rhs: SessionTableViewModel<NavItemId, Section, SettingItem>.NavItem
|
||||
) -> Bool {
|
||||
return (
|
||||
lhs.id == rhs.id &&
|
||||
lhs.image == rhs.image &&
|
||||
lhs.style == rhs.style &&
|
||||
lhs.systemItem == rhs.systemItem &&
|
||||
lhs.accessibilityIdentifier == rhs.accessibilityIdentifier
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ public class SessionCell: UITableViewCell {
|
|||
private let titleLabel: UILabel = {
|
||||
let result: UILabel = UILabel()
|
||||
result.translatesAutoresizingMaskIntoConstraints = false
|
||||
result.font = .boldSystemFont(ofSize: Values.mediumFontSize)
|
||||
result.font = .boldSystemFont(ofSize: 15)
|
||||
result.themeTextColor = .textPrimary
|
||||
result.numberOfLines = 0
|
||||
result.setCompressionResistanceHorizontalLow()
|
||||
|
@ -104,7 +104,7 @@ public class SessionCell: UITableViewCell {
|
|||
private let subtitleLabel: UILabel = {
|
||||
let result: UILabel = UILabel()
|
||||
result.translatesAutoresizingMaskIntoConstraints = false
|
||||
result.font = .systemFont(ofSize: Values.smallFontSize)
|
||||
result.font = .systemFont(ofSize: 13)
|
||||
result.themeTextColor = .textPrimary
|
||||
result.numberOfLines = 0
|
||||
result.isHidden = true
|
||||
|
|
|
@ -238,8 +238,8 @@ extension OpenGroup: CustomStringConvertible, CustomDebugStringConvertible {
|
|||
"sequenceNumber: \(sequenceNumber)",
|
||||
"inboxLatestMessageId: \(inboxLatestMessageId)",
|
||||
"outboxLatestMessageId: \(outboxLatestMessageId)",
|
||||
"pollFailureCount: \(pollFailureCount))",
|
||||
"permissions: \(permissions?.toString() ?? "---")"
|
||||
"pollFailureCount: \(pollFailureCount)",
|
||||
"permissions: \(permissions?.toString() ?? "---"))"
|
||||
].joined(separator: ", ")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -152,7 +152,7 @@ public extension Profile {
|
|||
|
||||
func toProto() -> SNProtoDataMessage? {
|
||||
let dataMessageProto = SNProtoDataMessage.builder()
|
||||
let profileProto = SNProtoDataMessageLokiProfile.builder()
|
||||
let profileProto = SNProtoLokiProfile.builder()
|
||||
profileProto.setDisplayName(name)
|
||||
|
||||
if let profileKey: OWSAES256Key = profileEncryptionKey, let profilePictureUrl: String = profilePictureUrl {
|
||||
|
|
|
@ -7,17 +7,21 @@ import SessionUtilitiesKit
|
|||
public final class MessageRequestResponse: ControlMessage {
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case isApproved
|
||||
case profile
|
||||
}
|
||||
|
||||
public var isApproved: Bool
|
||||
public var profile: VisibleMessage.VMProfile?
|
||||
|
||||
// MARK: - Initialization
|
||||
|
||||
public init(
|
||||
isApproved: Bool,
|
||||
profile: VisibleMessage.VMProfile? = nil,
|
||||
sentTimestampMs: UInt64? = nil
|
||||
) {
|
||||
self.isApproved = isApproved
|
||||
self.profile = profile
|
||||
|
||||
super.init(
|
||||
sentTimestamp: sentTimestampMs
|
||||
|
@ -30,6 +34,7 @@ public final class MessageRequestResponse: ControlMessage {
|
|||
let container: KeyedDecodingContainer<CodingKeys> = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
isApproved = try container.decode(Bool.self, forKey: .isApproved)
|
||||
profile = try? container.decode(VisibleMessage.VMProfile.self, forKey: .profile)
|
||||
|
||||
try super.init(from: decoder)
|
||||
}
|
||||
|
@ -40,6 +45,7 @@ public final class MessageRequestResponse: ControlMessage {
|
|||
var container: KeyedEncodingContainer<CodingKeys> = encoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
try container.encodeIfPresent(isApproved, forKey: .isApproved)
|
||||
try container.encodeIfPresent(profile, forKey: .profile)
|
||||
}
|
||||
|
||||
// MARK: - Proto Conversion
|
||||
|
@ -47,11 +53,23 @@ public final class MessageRequestResponse: ControlMessage {
|
|||
public override class func fromProto(_ proto: SNProtoContent, sender: String) -> MessageRequestResponse? {
|
||||
guard let messageRequestResponseProto = proto.messageRequestResponse else { return nil }
|
||||
|
||||
return MessageRequestResponse(isApproved: messageRequestResponseProto.isApproved)
|
||||
return MessageRequestResponse(
|
||||
isApproved: messageRequestResponseProto.isApproved,
|
||||
profile: VisibleMessage.VMProfile.fromProto(messageRequestResponseProto)
|
||||
)
|
||||
}
|
||||
|
||||
public override func toProto(_ db: Database) -> SNProtoContent? {
|
||||
let messageRequestResponseProto = SNProtoMessageRequestResponse.builder(isApproved: isApproved)
|
||||
let messageRequestResponseProto: SNProtoMessageRequestResponse.SNProtoMessageRequestResponseBuilder
|
||||
|
||||
// Profile
|
||||
if let profile = profile, let profileProto: SNProtoMessageRequestResponse = profile.toProto(isApproved: isApproved) {
|
||||
messageRequestResponseProto = profileProto.asBuilder()
|
||||
}
|
||||
else {
|
||||
messageRequestResponseProto = SNProtoMessageRequestResponse.builder(isApproved: isApproved)
|
||||
}
|
||||
|
||||
let contentProto = SNProtoContent.builder()
|
||||
|
||||
do {
|
||||
|
@ -68,7 +86,8 @@ public final class MessageRequestResponse: ControlMessage {
|
|||
public var description: String {
|
||||
"""
|
||||
MessageRequestResponse(
|
||||
isApproved: \(isApproved)
|
||||
isApproved: \(isApproved),
|
||||
profile: \(profile?.description ?? "null")
|
||||
)
|
||||
"""
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
import Foundation
|
||||
import SessionUtilitiesKit
|
||||
|
||||
// MARK: - VisibleMessage.VMProfile
|
||||
|
||||
public extension VisibleMessage {
|
||||
struct VMProfile: Codable {
|
||||
public let displayName: String?
|
||||
|
@ -40,7 +42,7 @@ public extension VisibleMessage {
|
|||
return nil
|
||||
}
|
||||
let dataMessageProto = SNProtoDataMessage.builder()
|
||||
let profileProto = SNProtoDataMessageLokiProfile.builder()
|
||||
let profileProto = SNProtoLokiProfile.builder()
|
||||
profileProto.setDisplayName(displayName)
|
||||
|
||||
if let profileKey = profileKey, let profilePictureUrl = profilePictureUrl {
|
||||
|
@ -56,6 +58,43 @@ public extension VisibleMessage {
|
|||
}
|
||||
}
|
||||
|
||||
public static func fromProto(_ proto: SNProtoMessageRequestResponse) -> VMProfile? {
|
||||
guard
|
||||
let profileProto = proto.profile,
|
||||
let displayName = profileProto.displayName
|
||||
else { return nil }
|
||||
|
||||
return VMProfile(
|
||||
displayName: displayName,
|
||||
profileKey: proto.profileKey,
|
||||
profilePictureUrl: profileProto.profilePicture
|
||||
)
|
||||
}
|
||||
|
||||
public func toProto(isApproved: Bool) -> SNProtoMessageRequestResponse? {
|
||||
guard let displayName = displayName else {
|
||||
SNLog("Couldn't construct profile proto from: \(self).")
|
||||
return nil
|
||||
}
|
||||
let messageRequestResponseProto = SNProtoMessageRequestResponse.builder(
|
||||
isApproved: isApproved
|
||||
)
|
||||
let profileProto = SNProtoLokiProfile.builder()
|
||||
profileProto.setDisplayName(displayName)
|
||||
|
||||
if let profileKey = profileKey, let profilePictureUrl = profilePictureUrl {
|
||||
messageRequestResponseProto.setProfileKey(profileKey)
|
||||
profileProto.setProfilePicture(profilePictureUrl)
|
||||
}
|
||||
do {
|
||||
messageRequestResponseProto.setProfile(try profileProto.build())
|
||||
return try messageRequestResponseProto.build()
|
||||
} catch {
|
||||
SNLog("Couldn't construct profile proto from: \(self).")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Description
|
||||
|
||||
public var description: String {
|
||||
|
@ -79,3 +118,12 @@ extension VisibleMessage.VMProfile {
|
|||
self.profilePictureUrl = profile.profilePictureUrl
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - MessageWithProfile
|
||||
|
||||
public protocol MessageWithProfile {
|
||||
var profile: VisibleMessage.VMProfile? { get set }
|
||||
}
|
||||
|
||||
extension VisibleMessage: MessageWithProfile {}
|
||||
extension MessageRequestResponse: MessageWithProfile {}
|
||||
|
|
|
@ -127,7 +127,7 @@ public final class VisibleMessage: Message {
|
|||
let dataMessage: SNProtoDataMessage.SNProtoDataMessageBuilder
|
||||
|
||||
// Profile
|
||||
if let profile = profile, let profileProto = profile.toProto() {
|
||||
if let profile = profile, let profileProto: SNProtoDataMessage = profile.toProto() {
|
||||
dataMessage = profileProto.asBuilder()
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -463,6 +463,12 @@ extension SNProtoUnsendRequest.SNProtoUnsendRequestBuilder {
|
|||
// asBuilder() constructs a builder that reflects the proto's contents.
|
||||
@objc public func asBuilder() -> SNProtoMessageRequestResponseBuilder {
|
||||
let builder = SNProtoMessageRequestResponseBuilder(isApproved: isApproved)
|
||||
if let _value = profileKey {
|
||||
builder.setProfileKey(_value)
|
||||
}
|
||||
if let _value = profile {
|
||||
builder.setProfile(_value)
|
||||
}
|
||||
return builder
|
||||
}
|
||||
|
||||
|
@ -482,6 +488,14 @@ extension SNProtoUnsendRequest.SNProtoUnsendRequestBuilder {
|
|||
proto.isApproved = valueParam
|
||||
}
|
||||
|
||||
@objc public func setProfileKey(_ valueParam: Data) {
|
||||
proto.profileKey = valueParam
|
||||
}
|
||||
|
||||
@objc public func setProfile(_ valueParam: SNProtoLokiProfile) {
|
||||
proto.profile = valueParam.proto
|
||||
}
|
||||
|
||||
@objc public func build() throws -> SNProtoMessageRequestResponse {
|
||||
return try SNProtoMessageRequestResponse.parseProto(proto)
|
||||
}
|
||||
|
@ -495,10 +509,24 @@ extension SNProtoUnsendRequest.SNProtoUnsendRequestBuilder {
|
|||
|
||||
@objc public let isApproved: Bool
|
||||
|
||||
@objc public let profile: SNProtoLokiProfile?
|
||||
|
||||
@objc public var profileKey: Data? {
|
||||
guard proto.hasProfileKey else {
|
||||
return nil
|
||||
}
|
||||
return proto.profileKey
|
||||
}
|
||||
@objc public var hasProfileKey: Bool {
|
||||
return proto.hasProfileKey
|
||||
}
|
||||
|
||||
private init(proto: SessionProtos_MessageRequestResponse,
|
||||
isApproved: Bool) {
|
||||
isApproved: Bool,
|
||||
profile: SNProtoLokiProfile?) {
|
||||
self.proto = proto
|
||||
self.isApproved = isApproved
|
||||
self.profile = profile
|
||||
}
|
||||
|
||||
@objc
|
||||
|
@ -517,12 +545,18 @@ extension SNProtoUnsendRequest.SNProtoUnsendRequestBuilder {
|
|||
}
|
||||
let isApproved = proto.isApproved
|
||||
|
||||
var profile: SNProtoLokiProfile? = nil
|
||||
if proto.hasProfile {
|
||||
profile = try SNProtoLokiProfile.parseProto(proto.profile)
|
||||
}
|
||||
|
||||
// MARK: - Begin Validation Logic for SNProtoMessageRequestResponse -
|
||||
|
||||
// MARK: - End Validation Logic for SNProtoMessageRequestResponse -
|
||||
|
||||
let result = SNProtoMessageRequestResponse(proto: proto,
|
||||
isApproved: isApproved)
|
||||
isApproved: isApproved,
|
||||
profile: profile)
|
||||
return result
|
||||
}
|
||||
|
||||
|
@ -1194,6 +1228,117 @@ extension SNProtoDataExtractionNotification.SNProtoDataExtractionNotificationBui
|
|||
|
||||
#endif
|
||||
|
||||
// MARK: - SNProtoLokiProfile
|
||||
|
||||
@objc public class SNProtoLokiProfile: NSObject {
|
||||
|
||||
// MARK: - SNProtoLokiProfileBuilder
|
||||
|
||||
@objc public class func builder() -> SNProtoLokiProfileBuilder {
|
||||
return SNProtoLokiProfileBuilder()
|
||||
}
|
||||
|
||||
// asBuilder() constructs a builder that reflects the proto's contents.
|
||||
@objc public func asBuilder() -> SNProtoLokiProfileBuilder {
|
||||
let builder = SNProtoLokiProfileBuilder()
|
||||
if let _value = displayName {
|
||||
builder.setDisplayName(_value)
|
||||
}
|
||||
if let _value = profilePicture {
|
||||
builder.setProfilePicture(_value)
|
||||
}
|
||||
return builder
|
||||
}
|
||||
|
||||
@objc public class SNProtoLokiProfileBuilder: NSObject {
|
||||
|
||||
private var proto = SessionProtos_LokiProfile()
|
||||
|
||||
@objc fileprivate override init() {}
|
||||
|
||||
@objc public func setDisplayName(_ valueParam: String) {
|
||||
proto.displayName = valueParam
|
||||
}
|
||||
|
||||
@objc public func setProfilePicture(_ valueParam: String) {
|
||||
proto.profilePicture = valueParam
|
||||
}
|
||||
|
||||
@objc public func build() throws -> SNProtoLokiProfile {
|
||||
return try SNProtoLokiProfile.parseProto(proto)
|
||||
}
|
||||
|
||||
@objc public func buildSerializedData() throws -> Data {
|
||||
return try SNProtoLokiProfile.parseProto(proto).serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate let proto: SessionProtos_LokiProfile
|
||||
|
||||
@objc public var displayName: String? {
|
||||
guard proto.hasDisplayName else {
|
||||
return nil
|
||||
}
|
||||
return proto.displayName
|
||||
}
|
||||
@objc public var hasDisplayName: Bool {
|
||||
return proto.hasDisplayName
|
||||
}
|
||||
|
||||
@objc public var profilePicture: String? {
|
||||
guard proto.hasProfilePicture else {
|
||||
return nil
|
||||
}
|
||||
return proto.profilePicture
|
||||
}
|
||||
@objc public var hasProfilePicture: Bool {
|
||||
return proto.hasProfilePicture
|
||||
}
|
||||
|
||||
private init(proto: SessionProtos_LokiProfile) {
|
||||
self.proto = proto
|
||||
}
|
||||
|
||||
@objc
|
||||
public func serializedData() throws -> Data {
|
||||
return try self.proto.serializedData()
|
||||
}
|
||||
|
||||
@objc public class func parseData(_ serializedData: Data) throws -> SNProtoLokiProfile {
|
||||
let proto = try SessionProtos_LokiProfile(serializedData: serializedData)
|
||||
return try parseProto(proto)
|
||||
}
|
||||
|
||||
fileprivate class func parseProto(_ proto: SessionProtos_LokiProfile) throws -> SNProtoLokiProfile {
|
||||
// MARK: - Begin Validation Logic for SNProtoLokiProfile -
|
||||
|
||||
// MARK: - End Validation Logic for SNProtoLokiProfile -
|
||||
|
||||
let result = SNProtoLokiProfile(proto: proto)
|
||||
return result
|
||||
}
|
||||
|
||||
@objc public override var debugDescription: String {
|
||||
return "\(proto)"
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
extension SNProtoLokiProfile {
|
||||
@objc public func serializedDataIgnoringErrors() -> Data? {
|
||||
return try! self.serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
extension SNProtoLokiProfile.SNProtoLokiProfileBuilder {
|
||||
@objc public func buildIgnoringErrors() -> SNProtoLokiProfile? {
|
||||
return try! self.build()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// MARK: - SNProtoDataMessageQuoteQuotedAttachment
|
||||
|
||||
@objc public class SNProtoDataMessageQuoteQuotedAttachment: NSObject {
|
||||
|
@ -1798,117 +1943,6 @@ extension SNProtoDataMessageReaction.SNProtoDataMessageReactionBuilder {
|
|||
|
||||
#endif
|
||||
|
||||
// MARK: - SNProtoDataMessageLokiProfile
|
||||
|
||||
@objc public class SNProtoDataMessageLokiProfile: NSObject {
|
||||
|
||||
// MARK: - SNProtoDataMessageLokiProfileBuilder
|
||||
|
||||
@objc public class func builder() -> SNProtoDataMessageLokiProfileBuilder {
|
||||
return SNProtoDataMessageLokiProfileBuilder()
|
||||
}
|
||||
|
||||
// asBuilder() constructs a builder that reflects the proto's contents.
|
||||
@objc public func asBuilder() -> SNProtoDataMessageLokiProfileBuilder {
|
||||
let builder = SNProtoDataMessageLokiProfileBuilder()
|
||||
if let _value = displayName {
|
||||
builder.setDisplayName(_value)
|
||||
}
|
||||
if let _value = profilePicture {
|
||||
builder.setProfilePicture(_value)
|
||||
}
|
||||
return builder
|
||||
}
|
||||
|
||||
@objc public class SNProtoDataMessageLokiProfileBuilder: NSObject {
|
||||
|
||||
private var proto = SessionProtos_DataMessage.LokiProfile()
|
||||
|
||||
@objc fileprivate override init() {}
|
||||
|
||||
@objc public func setDisplayName(_ valueParam: String) {
|
||||
proto.displayName = valueParam
|
||||
}
|
||||
|
||||
@objc public func setProfilePicture(_ valueParam: String) {
|
||||
proto.profilePicture = valueParam
|
||||
}
|
||||
|
||||
@objc public func build() throws -> SNProtoDataMessageLokiProfile {
|
||||
return try SNProtoDataMessageLokiProfile.parseProto(proto)
|
||||
}
|
||||
|
||||
@objc public func buildSerializedData() throws -> Data {
|
||||
return try SNProtoDataMessageLokiProfile.parseProto(proto).serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate let proto: SessionProtos_DataMessage.LokiProfile
|
||||
|
||||
@objc public var displayName: String? {
|
||||
guard proto.hasDisplayName else {
|
||||
return nil
|
||||
}
|
||||
return proto.displayName
|
||||
}
|
||||
@objc public var hasDisplayName: Bool {
|
||||
return proto.hasDisplayName
|
||||
}
|
||||
|
||||
@objc public var profilePicture: String? {
|
||||
guard proto.hasProfilePicture else {
|
||||
return nil
|
||||
}
|
||||
return proto.profilePicture
|
||||
}
|
||||
@objc public var hasProfilePicture: Bool {
|
||||
return proto.hasProfilePicture
|
||||
}
|
||||
|
||||
private init(proto: SessionProtos_DataMessage.LokiProfile) {
|
||||
self.proto = proto
|
||||
}
|
||||
|
||||
@objc
|
||||
public func serializedData() throws -> Data {
|
||||
return try self.proto.serializedData()
|
||||
}
|
||||
|
||||
@objc public class func parseData(_ serializedData: Data) throws -> SNProtoDataMessageLokiProfile {
|
||||
let proto = try SessionProtos_DataMessage.LokiProfile(serializedData: serializedData)
|
||||
return try parseProto(proto)
|
||||
}
|
||||
|
||||
fileprivate class func parseProto(_ proto: SessionProtos_DataMessage.LokiProfile) throws -> SNProtoDataMessageLokiProfile {
|
||||
// MARK: - Begin Validation Logic for SNProtoDataMessageLokiProfile -
|
||||
|
||||
// MARK: - End Validation Logic for SNProtoDataMessageLokiProfile -
|
||||
|
||||
let result = SNProtoDataMessageLokiProfile(proto: proto)
|
||||
return result
|
||||
}
|
||||
|
||||
@objc public override var debugDescription: String {
|
||||
return "\(proto)"
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
extension SNProtoDataMessageLokiProfile {
|
||||
@objc public func serializedDataIgnoringErrors() -> Data? {
|
||||
return try! self.serializedData()
|
||||
}
|
||||
}
|
||||
|
||||
extension SNProtoDataMessageLokiProfile.SNProtoDataMessageLokiProfileBuilder {
|
||||
@objc public func buildIgnoringErrors() -> SNProtoDataMessageLokiProfile? {
|
||||
return try! self.build()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// MARK: - SNProtoDataMessageOpenGroupInvitation
|
||||
|
||||
@objc public class SNProtoDataMessageOpenGroupInvitation: NSObject {
|
||||
|
@ -2510,7 +2544,7 @@ extension SNProtoDataMessageClosedGroupControlMessage.SNProtoDataMessageClosedGr
|
|||
proto.reaction = valueParam.proto
|
||||
}
|
||||
|
||||
@objc public func setProfile(_ valueParam: SNProtoDataMessageLokiProfile) {
|
||||
@objc public func setProfile(_ valueParam: SNProtoLokiProfile) {
|
||||
proto.profile = valueParam.proto
|
||||
}
|
||||
|
||||
|
@ -2547,7 +2581,7 @@ extension SNProtoDataMessageClosedGroupControlMessage.SNProtoDataMessageClosedGr
|
|||
|
||||
@objc public let reaction: SNProtoDataMessageReaction?
|
||||
|
||||
@objc public let profile: SNProtoDataMessageLokiProfile?
|
||||
@objc public let profile: SNProtoLokiProfile?
|
||||
|
||||
@objc public let openGroupInvitation: SNProtoDataMessageOpenGroupInvitation?
|
||||
|
||||
|
@ -2610,7 +2644,7 @@ extension SNProtoDataMessageClosedGroupControlMessage.SNProtoDataMessageClosedGr
|
|||
quote: SNProtoDataMessageQuote?,
|
||||
preview: [SNProtoDataMessagePreview],
|
||||
reaction: SNProtoDataMessageReaction?,
|
||||
profile: SNProtoDataMessageLokiProfile?,
|
||||
profile: SNProtoLokiProfile?,
|
||||
openGroupInvitation: SNProtoDataMessageOpenGroupInvitation?,
|
||||
closedGroupControlMessage: SNProtoDataMessageClosedGroupControlMessage?) {
|
||||
self.proto = proto
|
||||
|
@ -2656,9 +2690,9 @@ extension SNProtoDataMessageClosedGroupControlMessage.SNProtoDataMessageClosedGr
|
|||
reaction = try SNProtoDataMessageReaction.parseProto(proto.reaction)
|
||||
}
|
||||
|
||||
var profile: SNProtoDataMessageLokiProfile? = nil
|
||||
var profile: SNProtoLokiProfile? = nil
|
||||
if proto.hasProfile {
|
||||
profile = try SNProtoDataMessageLokiProfile.parseProto(proto.profile)
|
||||
profile = try SNProtoLokiProfile.parseProto(proto.profile)
|
||||
}
|
||||
|
||||
var openGroupInvitation: SNProtoDataMessageOpenGroupInvitation? = nil
|
||||
|
|
|
@ -244,11 +244,31 @@ struct SessionProtos_MessageRequestResponse {
|
|||
/// Clears the value of `isApproved`. Subsequent reads from it will return its default value.
|
||||
mutating func clearIsApproved() {self._isApproved = nil}
|
||||
|
||||
var profileKey: Data {
|
||||
get {return _profileKey ?? Data()}
|
||||
set {_profileKey = newValue}
|
||||
}
|
||||
/// Returns true if `profileKey` has been explicitly set.
|
||||
var hasProfileKey: Bool {return self._profileKey != nil}
|
||||
/// Clears the value of `profileKey`. Subsequent reads from it will return its default value.
|
||||
mutating func clearProfileKey() {self._profileKey = nil}
|
||||
|
||||
var profile: SessionProtos_LokiProfile {
|
||||
get {return _profile ?? SessionProtos_LokiProfile()}
|
||||
set {_profile = newValue}
|
||||
}
|
||||
/// Returns true if `profile` has been explicitly set.
|
||||
var hasProfile: Bool {return self._profile != nil}
|
||||
/// Clears the value of `profile`. Subsequent reads from it will return its default value.
|
||||
mutating func clearProfile() {self._profile = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _isApproved: Bool? = nil
|
||||
fileprivate var _profileKey: Data? = nil
|
||||
fileprivate var _profile: SessionProtos_LokiProfile? = nil
|
||||
}
|
||||
|
||||
struct SessionProtos_Content {
|
||||
|
@ -521,6 +541,37 @@ extension SessionProtos_DataExtractionNotification.TypeEnum: CaseIterable {
|
|||
|
||||
#endif // swift(>=4.2)
|
||||
|
||||
struct SessionProtos_LokiProfile {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
var displayName: String {
|
||||
get {return _displayName ?? String()}
|
||||
set {_displayName = newValue}
|
||||
}
|
||||
/// Returns true if `displayName` has been explicitly set.
|
||||
var hasDisplayName: Bool {return self._displayName != nil}
|
||||
/// Clears the value of `displayName`. Subsequent reads from it will return its default value.
|
||||
mutating func clearDisplayName() {self._displayName = nil}
|
||||
|
||||
var profilePicture: String {
|
||||
get {return _profilePicture ?? String()}
|
||||
set {_profilePicture = newValue}
|
||||
}
|
||||
/// Returns true if `profilePicture` has been explicitly set.
|
||||
var hasProfilePicture: Bool {return self._profilePicture != nil}
|
||||
/// Clears the value of `profilePicture`. Subsequent reads from it will return its default value.
|
||||
mutating func clearProfilePicture() {self._profilePicture = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _displayName: String? = nil
|
||||
fileprivate var _profilePicture: String? = nil
|
||||
}
|
||||
|
||||
struct SessionProtos_DataMessage {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
|
@ -608,8 +659,8 @@ struct SessionProtos_DataMessage {
|
|||
/// Clears the value of `reaction`. Subsequent reads from it will return its default value.
|
||||
mutating func clearReaction() {_uniqueStorage()._reaction = nil}
|
||||
|
||||
var profile: SessionProtos_DataMessage.LokiProfile {
|
||||
get {return _storage._profile ?? SessionProtos_DataMessage.LokiProfile()}
|
||||
var profile: SessionProtos_LokiProfile {
|
||||
get {return _storage._profile ?? SessionProtos_LokiProfile()}
|
||||
set {_uniqueStorage()._profile = newValue}
|
||||
}
|
||||
/// Returns true if `profile` has been explicitly set.
|
||||
|
@ -910,37 +961,6 @@ struct SessionProtos_DataMessage {
|
|||
fileprivate var _action: SessionProtos_DataMessage.Reaction.Action? = nil
|
||||
}
|
||||
|
||||
struct LokiProfile {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
// methods supported on all messages.
|
||||
|
||||
var displayName: String {
|
||||
get {return _displayName ?? String()}
|
||||
set {_displayName = newValue}
|
||||
}
|
||||
/// Returns true if `displayName` has been explicitly set.
|
||||
var hasDisplayName: Bool {return self._displayName != nil}
|
||||
/// Clears the value of `displayName`. Subsequent reads from it will return its default value.
|
||||
mutating func clearDisplayName() {self._displayName = nil}
|
||||
|
||||
var profilePicture: String {
|
||||
get {return _profilePicture ?? String()}
|
||||
set {_profilePicture = newValue}
|
||||
}
|
||||
/// Returns true if `profilePicture` has been explicitly set.
|
||||
var hasProfilePicture: Bool {return self._profilePicture != nil}
|
||||
/// Clears the value of `profilePicture`. Subsequent reads from it will return its default value.
|
||||
mutating func clearProfilePicture() {self._profilePicture = nil}
|
||||
|
||||
var unknownFields = SwiftProtobuf.UnknownStorage()
|
||||
|
||||
init() {}
|
||||
|
||||
fileprivate var _displayName: String? = nil
|
||||
fileprivate var _profilePicture: String? = nil
|
||||
}
|
||||
|
||||
struct OpenGroupInvitation {
|
||||
// SwiftProtobuf.Message conformance is added in an extension below. See the
|
||||
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
|
||||
|
@ -1702,24 +1722,28 @@ extension SessionProtos_Envelope: SwiftProtobuf.Message, SwiftProtobuf._MessageI
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._type {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._type {
|
||||
try visitor.visitSingularEnumField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._source {
|
||||
} }()
|
||||
try { if let v = self._source {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 2)
|
||||
}
|
||||
if let v = self._timestamp {
|
||||
} }()
|
||||
try { if let v = self._timestamp {
|
||||
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 5)
|
||||
}
|
||||
if let v = self._sourceDevice {
|
||||
} }()
|
||||
try { if let v = self._sourceDevice {
|
||||
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 7)
|
||||
}
|
||||
if let v = self._content {
|
||||
} }()
|
||||
try { if let v = self._content {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 8)
|
||||
}
|
||||
if let v = self._serverTimestamp {
|
||||
} }()
|
||||
try { if let v = self._serverTimestamp {
|
||||
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 10)
|
||||
}
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
@ -1769,12 +1793,16 @@ extension SessionProtos_TypingMessage: SwiftProtobuf.Message, SwiftProtobuf._Mes
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._timestamp {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._timestamp {
|
||||
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._action {
|
||||
} }()
|
||||
try { if let v = self._action {
|
||||
try visitor.visitSingularEnumField(value: v, fieldNumber: 2)
|
||||
}
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
@ -1820,12 +1848,16 @@ extension SessionProtos_UnsendRequest: SwiftProtobuf.Message, SwiftProtobuf._Mes
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._timestamp {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._timestamp {
|
||||
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._author {
|
||||
} }()
|
||||
try { if let v = self._author {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 2)
|
||||
}
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
@ -1841,6 +1873,8 @@ extension SessionProtos_MessageRequestResponse: SwiftProtobuf.Message, SwiftProt
|
|||
static let protoMessageName: String = _protobuf_package + ".MessageRequestResponse"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "isApproved"),
|
||||
2: .same(proto: "profileKey"),
|
||||
3: .same(proto: "profile"),
|
||||
]
|
||||
|
||||
public var isInitialized: Bool {
|
||||
|
@ -1855,20 +1889,34 @@ extension SessionProtos_MessageRequestResponse: SwiftProtobuf.Message, SwiftProt
|
|||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularBoolField(value: &self._isApproved) }()
|
||||
case 2: try { try decoder.decodeSingularBytesField(value: &self._profileKey) }()
|
||||
case 3: try { try decoder.decodeSingularMessageField(value: &self._profile) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._isApproved {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._isApproved {
|
||||
try visitor.visitSingularBoolField(value: v, fieldNumber: 1)
|
||||
}
|
||||
} }()
|
||||
try { if let v = self._profileKey {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try { if let v = self._profile {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: SessionProtos_MessageRequestResponse, rhs: SessionProtos_MessageRequestResponse) -> Bool {
|
||||
if lhs._isApproved != rhs._isApproved {return false}
|
||||
if lhs._profileKey != rhs._profileKey {return false}
|
||||
if lhs._profile != rhs._profile {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
|
@ -1958,30 +2006,34 @@ extension SessionProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
|
|||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
if let v = _storage._dataMessage {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = _storage._dataMessage {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = _storage._callMessage {
|
||||
} }()
|
||||
try { if let v = _storage._callMessage {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
|
||||
}
|
||||
if let v = _storage._receiptMessage {
|
||||
} }()
|
||||
try { if let v = _storage._receiptMessage {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 5)
|
||||
}
|
||||
if let v = _storage._typingMessage {
|
||||
} }()
|
||||
try { if let v = _storage._typingMessage {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 6)
|
||||
}
|
||||
if let v = _storage._configurationMessage {
|
||||
} }()
|
||||
try { if let v = _storage._configurationMessage {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 7)
|
||||
}
|
||||
if let v = _storage._dataExtractionNotification {
|
||||
} }()
|
||||
try { if let v = _storage._dataExtractionNotification {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 8)
|
||||
}
|
||||
if let v = _storage._unsendRequest {
|
||||
} }()
|
||||
try { if let v = _storage._unsendRequest {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 9)
|
||||
}
|
||||
if let v = _storage._messageRequestResponse {
|
||||
} }()
|
||||
try { if let v = _storage._messageRequestResponse {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 10)
|
||||
}
|
||||
} }()
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
@ -2041,9 +2093,13 @@ extension SessionProtos_CallMessage: SwiftProtobuf.Message, SwiftProtobuf._Messa
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._type {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._type {
|
||||
try visitor.visitSingularEnumField(value: v, fieldNumber: 1)
|
||||
}
|
||||
} }()
|
||||
if !self.sdps.isEmpty {
|
||||
try visitor.visitRepeatedStringField(value: self.sdps, fieldNumber: 2)
|
||||
}
|
||||
|
@ -2053,9 +2109,9 @@ extension SessionProtos_CallMessage: SwiftProtobuf.Message, SwiftProtobuf._Messa
|
|||
if !self.sdpMids.isEmpty {
|
||||
try visitor.visitRepeatedStringField(value: self.sdpMids, fieldNumber: 4)
|
||||
}
|
||||
if let v = self._uuid {
|
||||
try { if let v = self._uuid {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 5)
|
||||
}
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
@ -2108,12 +2164,16 @@ extension SessionProtos_KeyPair: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._publicKey {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._publicKey {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._privateKey {
|
||||
} }()
|
||||
try { if let v = self._privateKey {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 2)
|
||||
}
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
@ -2151,12 +2211,16 @@ extension SessionProtos_DataExtractionNotification: SwiftProtobuf.Message, Swift
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._type {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._type {
|
||||
try visitor.visitSingularEnumField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._timestamp {
|
||||
} }()
|
||||
try { if let v = self._timestamp {
|
||||
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 2)
|
||||
}
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
@ -2175,6 +2239,48 @@ extension SessionProtos_DataExtractionNotification.TypeEnum: SwiftProtobuf._Prot
|
|||
]
|
||||
}
|
||||
|
||||
extension SessionProtos_LokiProfile: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".LokiProfile"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "displayName"),
|
||||
2: .same(proto: "profilePicture"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularStringField(value: &self._displayName) }()
|
||||
case 2: try { try decoder.decodeSingularStringField(value: &self._profilePicture) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._displayName {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 1)
|
||||
} }()
|
||||
try { if let v = self._profilePicture {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 2)
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: SessionProtos_LokiProfile, rhs: SessionProtos_LokiProfile) -> Bool {
|
||||
if lhs._displayName != rhs._displayName {return false}
|
||||
if lhs._profilePicture != rhs._profilePicture {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension SessionProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = _protobuf_package + ".DataMessage"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
|
@ -2205,7 +2311,7 @@ extension SessionProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf._Messa
|
|||
var _quote: SessionProtos_DataMessage.Quote? = nil
|
||||
var _preview: [SessionProtos_DataMessage.Preview] = []
|
||||
var _reaction: SessionProtos_DataMessage.Reaction? = nil
|
||||
var _profile: SessionProtos_DataMessage.LokiProfile? = nil
|
||||
var _profile: SessionProtos_LokiProfile? = nil
|
||||
var _openGroupInvitation: SessionProtos_DataMessage.OpenGroupInvitation? = nil
|
||||
var _closedGroupControlMessage: SessionProtos_DataMessage.ClosedGroupControlMessage? = nil
|
||||
var _syncTarget: String? = nil
|
||||
|
@ -2282,48 +2388,52 @@ extension SessionProtos_DataMessage: SwiftProtobuf.Message, SwiftProtobuf._Messa
|
|||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
if let v = _storage._body {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = _storage._body {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 1)
|
||||
}
|
||||
} }()
|
||||
if !_storage._attachments.isEmpty {
|
||||
try visitor.visitRepeatedMessageField(value: _storage._attachments, fieldNumber: 2)
|
||||
}
|
||||
if let v = _storage._group {
|
||||
try { if let v = _storage._group {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
|
||||
}
|
||||
if let v = _storage._flags {
|
||||
} }()
|
||||
try { if let v = _storage._flags {
|
||||
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 4)
|
||||
}
|
||||
if let v = _storage._expireTimer {
|
||||
} }()
|
||||
try { if let v = _storage._expireTimer {
|
||||
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 5)
|
||||
}
|
||||
if let v = _storage._profileKey {
|
||||
} }()
|
||||
try { if let v = _storage._profileKey {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 6)
|
||||
}
|
||||
if let v = _storage._timestamp {
|
||||
} }()
|
||||
try { if let v = _storage._timestamp {
|
||||
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 7)
|
||||
}
|
||||
if let v = _storage._quote {
|
||||
} }()
|
||||
try { if let v = _storage._quote {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 8)
|
||||
}
|
||||
} }()
|
||||
if !_storage._preview.isEmpty {
|
||||
try visitor.visitRepeatedMessageField(value: _storage._preview, fieldNumber: 10)
|
||||
}
|
||||
if let v = _storage._reaction {
|
||||
try { if let v = _storage._reaction {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 11)
|
||||
}
|
||||
if let v = _storage._profile {
|
||||
} }()
|
||||
try { if let v = _storage._profile {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 101)
|
||||
}
|
||||
if let v = _storage._openGroupInvitation {
|
||||
} }()
|
||||
try { if let v = _storage._openGroupInvitation {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 102)
|
||||
}
|
||||
if let v = _storage._closedGroupControlMessage {
|
||||
} }()
|
||||
try { if let v = _storage._closedGroupControlMessage {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 104)
|
||||
}
|
||||
if let v = _storage._syncTarget {
|
||||
} }()
|
||||
try { if let v = _storage._syncTarget {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 105)
|
||||
}
|
||||
} }()
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
@ -2394,15 +2504,19 @@ extension SessionProtos_DataMessage.Quote: SwiftProtobuf.Message, SwiftProtobuf.
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._id {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._id {
|
||||
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._author {
|
||||
} }()
|
||||
try { if let v = self._author {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 2)
|
||||
}
|
||||
if let v = self._text {
|
||||
} }()
|
||||
try { if let v = self._text {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 3)
|
||||
}
|
||||
} }()
|
||||
if !self.attachments.isEmpty {
|
||||
try visitor.visitRepeatedMessageField(value: self.attachments, fieldNumber: 4)
|
||||
}
|
||||
|
@ -2449,18 +2563,22 @@ extension SessionProtos_DataMessage.Quote.QuotedAttachment: SwiftProtobuf.Messag
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._contentType {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._contentType {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._fileName {
|
||||
} }()
|
||||
try { if let v = self._fileName {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 2)
|
||||
}
|
||||
if let v = self._thumbnail {
|
||||
} }()
|
||||
try { if let v = self._thumbnail {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
|
||||
}
|
||||
if let v = self._flags {
|
||||
} }()
|
||||
try { if let v = self._flags {
|
||||
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 4)
|
||||
}
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
@ -2509,15 +2627,19 @@ extension SessionProtos_DataMessage.Preview: SwiftProtobuf.Message, SwiftProtobu
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._url {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._url {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._title {
|
||||
} }()
|
||||
try { if let v = self._title {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 2)
|
||||
}
|
||||
if let v = self._image {
|
||||
} }()
|
||||
try { if let v = self._image {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
|
||||
}
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
@ -2562,18 +2684,22 @@ extension SessionProtos_DataMessage.Reaction: SwiftProtobuf.Message, SwiftProtob
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._id {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._id {
|
||||
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._author {
|
||||
} }()
|
||||
try { if let v = self._author {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 2)
|
||||
}
|
||||
if let v = self._emoji {
|
||||
} }()
|
||||
try { if let v = self._emoji {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 3)
|
||||
}
|
||||
if let v = self._action {
|
||||
} }()
|
||||
try { if let v = self._action {
|
||||
try visitor.visitSingularEnumField(value: v, fieldNumber: 4)
|
||||
}
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
@ -2594,44 +2720,6 @@ extension SessionProtos_DataMessage.Reaction.Action: SwiftProtobuf._ProtoNamePro
|
|||
]
|
||||
}
|
||||
|
||||
extension SessionProtos_DataMessage.LokiProfile: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = SessionProtos_DataMessage.protoMessageName + ".LokiProfile"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
1: .same(proto: "displayName"),
|
||||
2: .same(proto: "profilePicture"),
|
||||
]
|
||||
|
||||
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
|
||||
while let fieldNumber = try decoder.nextFieldNumber() {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every case branch when no optimizations are
|
||||
// enabled. https://github.com/apple/swift-protobuf/issues/1034
|
||||
switch fieldNumber {
|
||||
case 1: try { try decoder.decodeSingularStringField(value: &self._displayName) }()
|
||||
case 2: try { try decoder.decodeSingularStringField(value: &self._profilePicture) }()
|
||||
default: break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._displayName {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._profilePicture {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 2)
|
||||
}
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
static func ==(lhs: SessionProtos_DataMessage.LokiProfile, rhs: SessionProtos_DataMessage.LokiProfile) -> Bool {
|
||||
if lhs._displayName != rhs._displayName {return false}
|
||||
if lhs._profilePicture != rhs._profilePicture {return false}
|
||||
if lhs.unknownFields != rhs.unknownFields {return false}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension SessionProtos_DataMessage.OpenGroupInvitation: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
|
||||
static let protoMessageName: String = SessionProtos_DataMessage.protoMessageName + ".OpenGroupInvitation"
|
||||
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
|
||||
|
@ -2659,12 +2747,16 @@ extension SessionProtos_DataMessage.OpenGroupInvitation: SwiftProtobuf.Message,
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._url {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._url {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._name {
|
||||
} }()
|
||||
try { if let v = self._name {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 3)
|
||||
}
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
@ -2716,18 +2808,22 @@ extension SessionProtos_DataMessage.ClosedGroupControlMessage: SwiftProtobuf.Mes
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._type {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._type {
|
||||
try visitor.visitSingularEnumField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._publicKey {
|
||||
} }()
|
||||
try { if let v = self._publicKey {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 2)
|
||||
}
|
||||
if let v = self._name {
|
||||
} }()
|
||||
try { if let v = self._name {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 3)
|
||||
}
|
||||
if let v = self._encryptionKeyPair {
|
||||
} }()
|
||||
try { if let v = self._encryptionKeyPair {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 4)
|
||||
}
|
||||
} }()
|
||||
if !self.members.isEmpty {
|
||||
try visitor.visitRepeatedBytesField(value: self.members, fieldNumber: 5)
|
||||
}
|
||||
|
@ -2737,9 +2833,9 @@ extension SessionProtos_DataMessage.ClosedGroupControlMessage: SwiftProtobuf.Mes
|
|||
if !self.wrappers.isEmpty {
|
||||
try visitor.visitRepeatedMessageField(value: self.wrappers, fieldNumber: 7)
|
||||
}
|
||||
if let v = self._expirationTimer {
|
||||
try { if let v = self._expirationTimer {
|
||||
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 8)
|
||||
}
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
@ -2796,12 +2892,16 @@ extension SessionProtos_DataMessage.ClosedGroupControlMessage.KeyPairWrapper: Sw
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._publicKey {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._publicKey {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._encryptedKeyPair {
|
||||
} }()
|
||||
try { if let v = self._encryptedKeyPair {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 2)
|
||||
}
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
@ -2848,21 +2948,25 @@ extension SessionProtos_ConfigurationMessage: SwiftProtobuf.Message, SwiftProtob
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
if !self.closedGroups.isEmpty {
|
||||
try visitor.visitRepeatedMessageField(value: self.closedGroups, fieldNumber: 1)
|
||||
}
|
||||
if !self.openGroups.isEmpty {
|
||||
try visitor.visitRepeatedStringField(value: self.openGroups, fieldNumber: 2)
|
||||
}
|
||||
if let v = self._displayName {
|
||||
try { if let v = self._displayName {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 3)
|
||||
}
|
||||
if let v = self._profilePicture {
|
||||
} }()
|
||||
try { if let v = self._profilePicture {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 4)
|
||||
}
|
||||
if let v = self._profileKey {
|
||||
} }()
|
||||
try { if let v = self._profileKey {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 5)
|
||||
}
|
||||
} }()
|
||||
if !self.contacts.isEmpty {
|
||||
try visitor.visitRepeatedMessageField(value: self.contacts, fieldNumber: 6)
|
||||
}
|
||||
|
@ -2915,24 +3019,28 @@ extension SessionProtos_ConfigurationMessage.ClosedGroup: SwiftProtobuf.Message,
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._publicKey {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._publicKey {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._name {
|
||||
} }()
|
||||
try { if let v = self._name {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 2)
|
||||
}
|
||||
if let v = self._encryptionKeyPair {
|
||||
} }()
|
||||
try { if let v = self._encryptionKeyPair {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
|
||||
}
|
||||
} }()
|
||||
if !self.members.isEmpty {
|
||||
try visitor.visitRepeatedBytesField(value: self.members, fieldNumber: 4)
|
||||
}
|
||||
if !self.admins.isEmpty {
|
||||
try visitor.visitRepeatedBytesField(value: self.admins, fieldNumber: 5)
|
||||
}
|
||||
if let v = self._expirationTimer {
|
||||
try { if let v = self._expirationTimer {
|
||||
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 6)
|
||||
}
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
@ -2985,27 +3093,31 @@ extension SessionProtos_ConfigurationMessage.Contact: SwiftProtobuf.Message, Swi
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._publicKey {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._publicKey {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._name {
|
||||
} }()
|
||||
try { if let v = self._name {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 2)
|
||||
}
|
||||
if let v = self._profilePicture {
|
||||
} }()
|
||||
try { if let v = self._profilePicture {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 3)
|
||||
}
|
||||
if let v = self._profileKey {
|
||||
} }()
|
||||
try { if let v = self._profileKey {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 4)
|
||||
}
|
||||
if let v = self._isApproved {
|
||||
} }()
|
||||
try { if let v = self._isApproved {
|
||||
try visitor.visitSingularBoolField(value: v, fieldNumber: 5)
|
||||
}
|
||||
if let v = self._isBlocked {
|
||||
} }()
|
||||
try { if let v = self._isBlocked {
|
||||
try visitor.visitSingularBoolField(value: v, fieldNumber: 6)
|
||||
}
|
||||
if let v = self._didApproveMe {
|
||||
} }()
|
||||
try { if let v = self._didApproveMe {
|
||||
try visitor.visitSingularBoolField(value: v, fieldNumber: 7)
|
||||
}
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
@ -3048,9 +3160,13 @@ extension SessionProtos_ReceiptMessage: SwiftProtobuf.Message, SwiftProtobuf._Me
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._type {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._type {
|
||||
try visitor.visitSingularEnumField(value: v, fieldNumber: 1)
|
||||
}
|
||||
} }()
|
||||
if !self.timestamp.isEmpty {
|
||||
try visitor.visitRepeatedUInt64Field(value: self.timestamp, fieldNumber: 2)
|
||||
}
|
||||
|
@ -3118,42 +3234,46 @@ extension SessionProtos_AttachmentPointer: SwiftProtobuf.Message, SwiftProtobuf.
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._id {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._id {
|
||||
try visitor.visitSingularFixed64Field(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._contentType {
|
||||
} }()
|
||||
try { if let v = self._contentType {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 2)
|
||||
}
|
||||
if let v = self._key {
|
||||
} }()
|
||||
try { if let v = self._key {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 3)
|
||||
}
|
||||
if let v = self._size {
|
||||
} }()
|
||||
try { if let v = self._size {
|
||||
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 4)
|
||||
}
|
||||
if let v = self._thumbnail {
|
||||
} }()
|
||||
try { if let v = self._thumbnail {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 5)
|
||||
}
|
||||
if let v = self._digest {
|
||||
} }()
|
||||
try { if let v = self._digest {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 6)
|
||||
}
|
||||
if let v = self._fileName {
|
||||
} }()
|
||||
try { if let v = self._fileName {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 7)
|
||||
}
|
||||
if let v = self._flags {
|
||||
} }()
|
||||
try { if let v = self._flags {
|
||||
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 8)
|
||||
}
|
||||
if let v = self._width {
|
||||
} }()
|
||||
try { if let v = self._width {
|
||||
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 9)
|
||||
}
|
||||
if let v = self._height {
|
||||
} }()
|
||||
try { if let v = self._height {
|
||||
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 10)
|
||||
}
|
||||
if let v = self._caption {
|
||||
} }()
|
||||
try { if let v = self._caption {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 11)
|
||||
}
|
||||
if let v = self._url {
|
||||
} }()
|
||||
try { if let v = self._url {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 101)
|
||||
}
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
@ -3250,21 +3370,25 @@ extension SessionProtos_GroupContext: SwiftProtobuf.Message, SwiftProtobuf._Mess
|
|||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
try withExtendedLifetime(_storage) { (_storage: _StorageClass) in
|
||||
if let v = _storage._id {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = _storage._id {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = _storage._type {
|
||||
} }()
|
||||
try { if let v = _storage._type {
|
||||
try visitor.visitSingularEnumField(value: v, fieldNumber: 2)
|
||||
}
|
||||
if let v = _storage._name {
|
||||
} }()
|
||||
try { if let v = _storage._name {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 3)
|
||||
}
|
||||
} }()
|
||||
if !_storage._members.isEmpty {
|
||||
try visitor.visitRepeatedStringField(value: _storage._members, fieldNumber: 4)
|
||||
}
|
||||
if let v = _storage._avatar {
|
||||
try { if let v = _storage._avatar {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 5)
|
||||
}
|
||||
} }()
|
||||
if !_storage._admins.isEmpty {
|
||||
try visitor.visitRepeatedStringField(value: _storage._admins, fieldNumber: 6)
|
||||
}
|
||||
|
|
|
@ -249,18 +249,22 @@ extension WebSocketProtos_WebSocketRequestMessage: SwiftProtobuf.Message, SwiftP
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._verb {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._verb {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._path {
|
||||
} }()
|
||||
try { if let v = self._path {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 2)
|
||||
}
|
||||
if let v = self._body {
|
||||
} }()
|
||||
try { if let v = self._body {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 3)
|
||||
}
|
||||
if let v = self._requestID {
|
||||
} }()
|
||||
try { if let v = self._requestID {
|
||||
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 4)
|
||||
}
|
||||
} }()
|
||||
if !self.headers.isEmpty {
|
||||
try visitor.visitRepeatedStringField(value: self.headers, fieldNumber: 5)
|
||||
}
|
||||
|
@ -305,18 +309,22 @@ extension WebSocketProtos_WebSocketResponseMessage: SwiftProtobuf.Message, Swift
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._requestID {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._requestID {
|
||||
try visitor.visitSingularUInt64Field(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._status {
|
||||
} }()
|
||||
try { if let v = self._status {
|
||||
try visitor.visitSingularUInt32Field(value: v, fieldNumber: 2)
|
||||
}
|
||||
if let v = self._message {
|
||||
} }()
|
||||
try { if let v = self._message {
|
||||
try visitor.visitSingularStringField(value: v, fieldNumber: 3)
|
||||
}
|
||||
if let v = self._body {
|
||||
} }()
|
||||
try { if let v = self._body {
|
||||
try visitor.visitSingularBytesField(value: v, fieldNumber: 4)
|
||||
}
|
||||
} }()
|
||||
if !self.headers.isEmpty {
|
||||
try visitor.visitRepeatedStringField(value: self.headers, fieldNumber: 5)
|
||||
}
|
||||
|
@ -357,15 +365,19 @@ extension WebSocketProtos_WebSocketMessage: SwiftProtobuf.Message, SwiftProtobuf
|
|||
}
|
||||
|
||||
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
|
||||
if let v = self._type {
|
||||
// The use of inline closures is to circumvent an issue where the compiler
|
||||
// allocates stack space for every if/case branch local when no optimizations
|
||||
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
|
||||
// https://github.com/apple/swift-protobuf/issues/1182
|
||||
try { if let v = self._type {
|
||||
try visitor.visitSingularEnumField(value: v, fieldNumber: 1)
|
||||
}
|
||||
if let v = self._request {
|
||||
} }()
|
||||
try { if let v = self._request {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
|
||||
}
|
||||
if let v = self._response {
|
||||
} }()
|
||||
try { if let v = self._response {
|
||||
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
|
||||
}
|
||||
} }()
|
||||
try unknownFields.traverse(visitor: &visitor)
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,9 @@ message UnsendRequest {
|
|||
|
||||
message MessageRequestResponse {
|
||||
// @required
|
||||
required bool isApproved = 1; // Whether the request was approved
|
||||
required bool isApproved = 1; // Whether the request was approved
|
||||
optional bytes profileKey = 2;
|
||||
optional LokiProfile profile = 3;
|
||||
}
|
||||
|
||||
message Content {
|
||||
|
@ -98,6 +100,11 @@ message DataExtractionNotification {
|
|||
optional uint64 timestamp = 2;
|
||||
}
|
||||
|
||||
message LokiProfile {
|
||||
optional string displayName = 1;
|
||||
optional string profilePicture = 2;
|
||||
}
|
||||
|
||||
message DataMessage {
|
||||
|
||||
enum Flags {
|
||||
|
@ -147,11 +154,6 @@ message DataMessage {
|
|||
required Action action = 4;
|
||||
}
|
||||
|
||||
message LokiProfile {
|
||||
optional string displayName = 1;
|
||||
optional string profilePicture = 2;
|
||||
}
|
||||
|
||||
message OpenGroupInvitation {
|
||||
// @required
|
||||
required string url = 1;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import Foundation
|
||||
import GRDB
|
||||
import SignalCoreKit
|
||||
import SessionUtilitiesKit
|
||||
|
||||
extension MessageReceiver {
|
||||
|
@ -17,6 +18,24 @@ extension MessageReceiver {
|
|||
guard message.sender != userPublicKey else { return }
|
||||
guard let senderId: String = message.sender else { return }
|
||||
|
||||
// Update profile if needed (want to do this regardless of whether the message exists or
|
||||
// not to ensure the profile info gets sync between a users devices at every chance)
|
||||
if let profile = message.profile {
|
||||
var contactProfileKey: OWSAES256Key? = nil
|
||||
let messageSentTimestamp: TimeInterval = (TimeInterval(message.sentTimestamp ?? 0) / 1000)
|
||||
|
||||
if let profileKey = profile.profileKey { contactProfileKey = OWSAES256Key(data: profileKey) }
|
||||
|
||||
try MessageReceiver.updateProfileIfNeeded(
|
||||
db,
|
||||
publicKey: senderId,
|
||||
name: profile.displayName,
|
||||
profilePictureUrl: profile.profilePictureUrl,
|
||||
profileKey: contactProfileKey,
|
||||
sentTimestamp: messageSentTimestamp
|
||||
)
|
||||
}
|
||||
|
||||
// Prep the unblinded thread
|
||||
let unblindedThread: SessionThread = try SessionThread.fetchOrCreate(db, id: senderId, variant: .contact)
|
||||
|
||||
|
|
|
@ -109,18 +109,18 @@ public final class MessageSender {
|
|||
}
|
||||
|
||||
// Attach the user's profile if needed
|
||||
if let message: VisibleMessage = message as? VisibleMessage {
|
||||
if var messageWithProfile: MessageWithProfile = message as? MessageWithProfile {
|
||||
let profile: Profile = Profile.fetchOrCreateCurrentUser(db)
|
||||
|
||||
if let profileKey: Data = profile.profileEncryptionKey?.keyData, let profilePictureUrl: String = profile.profilePictureUrl {
|
||||
message.profile = VisibleMessage.VMProfile(
|
||||
messageWithProfile.profile = VisibleMessage.VMProfile(
|
||||
displayName: profile.name,
|
||||
profileKey: profileKey,
|
||||
profilePictureUrl: profilePictureUrl
|
||||
)
|
||||
}
|
||||
else {
|
||||
message.profile = VisibleMessage.VMProfile(displayName: profile.name)
|
||||
messageWithProfile.profile = VisibleMessage.VMProfile(displayName: profile.name)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ class OpenGroupSpec: QuickSpec {
|
|||
)
|
||||
|
||||
expect(openGroup.debugDescription)
|
||||
.to(equal("OpenGroup(server: \"server\", roomToken: \"room\", id: \"server.room\", publicKey: \"1234\", isActive: true, name: \"name\", roomDescription: null, imageId: null, userCount: 0, infoUpdates: 0, sequenceNumber: 0, inboxLatestMessageId: 0, outboxLatestMessageId: 0, pollFailureCount: 0)"))
|
||||
.to(equal("OpenGroup(server: \"server\", roomToken: \"room\", id: \"server.room\", publicKey: \"1234\", isActive: true, name: \"name\", roomDescription: null, imageId: null, userCount: 0, infoUpdates: 0, sequenceNumber: 0, inboxLatestMessageId: 0, outboxLatestMessageId: 0, pollFailureCount: 0, permissions: ---)"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,427 +1,253 @@
|
|||
//// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
//
|
||||
//import Combine
|
||||
//import Quick
|
||||
//import Nimble
|
||||
//
|
||||
//@testable import Session
|
||||
//
|
||||
//class ThreadDisappearingMessagesViewModelSpec: import Combine {
|
||||
// typealias Item = ConversationDisappearingMessagesViewModel.Item
|
||||
//
|
||||
// var disposables: Set<AnyCancellable>!
|
||||
// var dataChangedCallbackTriggered: Bool = false
|
||||
// var thread: TSThread!
|
||||
// var config: OWSDisappearingMessagesConfiguration!
|
||||
// var contact: Contact!
|
||||
// var defaultItems: [ConversationDisappearingMessagesViewModel.Item]!
|
||||
// var defaultItems: [Item]!
|
||||
// var viewModel: ConversationDisappearingMessagesViewModel!
|
||||
//
|
||||
// // MARK: - Configuration
|
||||
//
|
||||
// override func setUpWithError() throws {
|
||||
// dataChangedCallbackTriggered = false
|
||||
//
|
||||
// disposables = Set()
|
||||
// thread = TSContactThread(uniqueId: "TestId")
|
||||
// config = OWSDisappearingMessagesConfiguration(defaultWithThreadId: "TestId")
|
||||
// contact = Contact(sessionID: "TestContactId")
|
||||
// defaultItems = [
|
||||
// ConversationDisappearingMessagesViewModel.Item(id: 0, title: "Off", isActive: true),
|
||||
// ConversationDisappearingMessagesViewModel.Item(id: 1, title: "5 seconds", isActive: false),
|
||||
// ConversationDisappearingMessagesViewModel.Item(id: 2, title: "10 seconds", isActive: false),
|
||||
// ConversationDisappearingMessagesViewModel.Item(id: 3, title: "30 seconds", isActive: false),
|
||||
// ConversationDisappearingMessagesViewModel.Item(id: 4, title: "1 minute", isActive: false),
|
||||
// ConversationDisappearingMessagesViewModel.Item(id: 5, title: "5 minutes", isActive: false),
|
||||
// ConversationDisappearingMessagesViewModel.Item(id: 6, title: "30 minutes", isActive: false),
|
||||
// ConversationDisappearingMessagesViewModel.Item(id: 7, title: "1 hour", isActive: false),
|
||||
// ConversationDisappearingMessagesViewModel.Item(id: 8, title: "6 hours", isActive: false),
|
||||
// ConversationDisappearingMessagesViewModel.Item(id: 9, title: "12 hours", isActive: false),
|
||||
// ConversationDisappearingMessagesViewModel.Item(id: 10, title: "1 day", isActive: false),
|
||||
// ConversationDisappearingMessagesViewModel.Item(id: 11, title: "1 week", isActive: false)
|
||||
// Item(id: 0, title: "Off", isActive: true),
|
||||
// Item(id: 1, title: "5 seconds", isActive: false),
|
||||
// Item(id: 2, title: "10 seconds", isActive: false),
|
||||
// Item(id: 3, title: "30 seconds", isActive: false),
|
||||
// Item(id: 4, title: "1 minute", isActive: false),
|
||||
// Item(id: 5, title: "5 minutes", isActive: false),
|
||||
// Item(id: 6, title: "30 minutes", isActive: false),
|
||||
// Item(id: 7, title: "1 hour", isActive: false),
|
||||
// Item(id: 8, title: "6 hours", isActive: false),
|
||||
// Item(id: 9, title: "12 hours", isActive: false),
|
||||
// Item(id: 10, title: "1 day", isActive: false),
|
||||
// Item(id: 11, title: "1 week", isActive: false)
|
||||
// ]
|
||||
//
|
||||
// viewModel = ConversationDisappearingMessagesViewModel(thread: thread, disappearingMessagesConfiguration: config) { [weak self] in
|
||||
// self?.dataChangedCallbackTriggered = true
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override func tearDownWithError() throws {
|
||||
// disposables = nil
|
||||
// dataChangedCallbackTriggered = false
|
||||
// thread = nil
|
||||
// config = nil
|
||||
// contact = nil
|
||||
// defaultItems = nil
|
||||
// viewModel = nil
|
||||
// }
|
||||
//
|
||||
// // MARK: - ConversationDisappearingMessagesViewModel.Item
|
||||
//
|
||||
// func testItDefaultsToTheExistingValuesWhenUpdatedWithNullValues() throws {
|
||||
// var item: ConversationDisappearingMessagesViewModel.Item = ConversationDisappearingMessagesViewModel.Item(
|
||||
// id: 1,
|
||||
// title: "Test",
|
||||
// isActive: true
|
||||
// )
|
||||
//
|
||||
// expect(item.isActive).to(beTrue())
|
||||
//
|
||||
// item = item.with(isActive: nil)
|
||||
// expect(item.isActive).to(beTrue())
|
||||
//
|
||||
// item = item.with(isActive: false)
|
||||
// expect(item.isActive).to(beFalse())
|
||||
// }
|
||||
//
|
||||
// // MARK: - Basic Tests
|
||||
//
|
||||
// func testItHasTheCorrectTitle() throws {
|
||||
// expect(self.viewModel.title).to(equal("DISAPPEARING_MESSAGES_SETTINGS_TITLE".localized()))
|
||||
// }
|
||||
//
|
||||
// func testItHasTheCorrectDescriptionForAGroup() throws {
|
||||
// thread = TSGroupThread(uniqueId: "TestId1")
|
||||
// config = OWSDisappearingMessagesConfiguration(defaultWithThreadId: "TestId1")
|
||||
// viewModel = ConversationDisappearingMessagesViewModel(thread: thread, disappearingMessagesConfiguration: config) { [weak self] in
|
||||
// self?.dataChangedCallbackTriggered = true
|
||||
// }
|
||||
//
|
||||
// expect(self.viewModel.description)
|
||||
// .to(equal(
|
||||
// String(format: NSLocalizedString("When enabled, messages between you and %@ will disappear after they have been seen.", comment: ""), arguments: ["the group"])
|
||||
// ))
|
||||
// }
|
||||
//
|
||||
// func testItHasTheCorrectDescriptionForAKnownContact() throws {
|
||||
// var hasWrittenToStorage: Bool = false
|
||||
//
|
||||
// // TODO: Mock storage
|
||||
// Storage.write { [weak self] transaction in
|
||||
// guard let strongSelf = self else { return }
|
||||
//
|
||||
// Storage.shared.setContact(strongSelf.contact, using: transaction)
|
||||
//
|
||||
// // Need to do these after setting the contact to ensure it's picked up correctly
|
||||
// strongSelf.thread = TSContactThread(contactSessionID: "TestContactId")
|
||||
// strongSelf.config = OWSDisappearingMessagesConfiguration(defaultWithThreadId: (strongSelf.thread.uniqueId ?? "TestContactId"))
|
||||
// strongSelf.viewModel = ConversationDisappearingMessagesViewModel(thread: strongSelf.thread, disappearingMessagesConfiguration: strongSelf.config) {
|
||||
// self?.dataChangedCallbackTriggered = true
|
||||
// }
|
||||
// hasWrittenToStorage = true
|
||||
// }
|
||||
//
|
||||
// // Note: We need this to ensure the test doesn't run before the subsequent 'expect' doesn't
|
||||
// // run before the viewModel gets recreated in the 'Storage.write'
|
||||
// expect(hasWrittenToStorage)
|
||||
// .toEventually(
|
||||
// beTrue(),
|
||||
// timeout: .milliseconds(100)
|
||||
// )
|
||||
// expect(self.viewModel.description)
|
||||
// .toEventually(
|
||||
// equal(
|
||||
// String(format: NSLocalizedString("When enabled, messages between you and %@ will disappear after they have been seen.", comment: ""), arguments: ["anonymous"])
|
||||
// ),
|
||||
// timeout: .milliseconds(100)
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// func testItHasTheCorrectDescriptionForAKnownContactWithADisplayName() throws {
|
||||
// var hasWrittenToStorage: Bool = false
|
||||
// contact.nickname = "TestName"
|
||||
//
|
||||
// // TODO: Mock storage
|
||||
// Storage.write { [weak self] transaction in
|
||||
// guard let strongSelf = self else { return }
|
||||
//
|
||||
// Storage.shared.setContact(strongSelf.contact, using: transaction)
|
||||
//
|
||||
// // Need to do these after setting the contact to ensure it's picked up correctly
|
||||
// strongSelf.thread = TSContactThread(contactSessionID: "TestContactId")
|
||||
// strongSelf.config = OWSDisappearingMessagesConfiguration(defaultWithThreadId: (strongSelf.thread.uniqueId ?? "TestContactId"))
|
||||
// strongSelf.viewModel = ConversationDisappearingMessagesViewModel(thread: strongSelf.thread, disappearingMessagesConfiguration: strongSelf.config) {
|
||||
// self?.dataChangedCallbackTriggered = true
|
||||
// }
|
||||
// hasWrittenToStorage = true
|
||||
// }
|
||||
//
|
||||
// // Note: We need this to ensure the test doesn't run before the subsequent 'expect' doesn't
|
||||
// // run before the viewModel gets recreated in the 'Storage.write'
|
||||
// expect(hasWrittenToStorage)
|
||||
// .toEventually(
|
||||
// beTrue(),
|
||||
// timeout: .milliseconds(100)
|
||||
// )
|
||||
// expect(self.viewModel.description)
|
||||
// .toEventually(equal(
|
||||
// String(format: NSLocalizedString("When enabled, messages between you and %@ will disappear after they have been seen.", comment: ""), arguments: ["TestName"])
|
||||
// ))
|
||||
// }
|
||||
//
|
||||
// func testItHasTheCorrectDescriptionForAnUnexpectedThreadType() throws {
|
||||
// var hasWrittenToStorage: Bool = false
|
||||
// contact.nickname = "TestName"
|
||||
//
|
||||
// // TODO: Mock storage
|
||||
// Storage.write { [weak self] transaction in
|
||||
// guard let strongSelf = self else { return }
|
||||
//
|
||||
// Storage.shared.setContact(strongSelf.contact, using: transaction)
|
||||
//
|
||||
// // Need to do these after setting the contact to ensure it's picked up correctly
|
||||
// strongSelf.thread = TSThread(uniqueId: "TestId1")
|
||||
// strongSelf.config = OWSDisappearingMessagesConfiguration(defaultWithThreadId: (strongSelf.thread.uniqueId ?? "TestId1"))
|
||||
// strongSelf.viewModel = ConversationDisappearingMessagesViewModel(thread: strongSelf.thread, disappearingMessagesConfiguration: strongSelf.config) {
|
||||
// self?.dataChangedCallbackTriggered = true
|
||||
// }
|
||||
// hasWrittenToStorage = true
|
||||
// }
|
||||
//
|
||||
// // Note: We need this to ensure the test doesn't run before the subsequent 'expect' doesn't
|
||||
// // run before the viewModel gets recreated in the 'Storage.write'
|
||||
// expect(hasWrittenToStorage)
|
||||
// .toEventually(
|
||||
// beTrue(),
|
||||
// timeout: .milliseconds(100)
|
||||
// )
|
||||
// expect(self.viewModel.description)
|
||||
// .toEventually(equal(
|
||||
// String(format: NSLocalizedString("When enabled, messages between you and %@ will disappear after they have been seen.", comment: ""), arguments: ["anonymous"])
|
||||
// ))
|
||||
// }
|
||||
//
|
||||
// func testItHasTheCorrectNumberOfItems() throws {
|
||||
// expect(self.viewModel.items.value.count).to(equal(12))
|
||||
// expect(self.viewModel.items.newest)
|
||||
// .toEventually(
|
||||
// haveCount(12),
|
||||
// timeout: .milliseconds(100)
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// func testItHasTheCorrectDefaultState() throws {
|
||||
// expect(self.viewModel.items.value).to(equal(defaultItems))
|
||||
// expect(self.viewModel.items.newest)
|
||||
// .toEventually(
|
||||
// equal(defaultItems),
|
||||
// timeout: .milliseconds(100)
|
||||
// )
|
||||
// }
|
||||
//
|
||||
//
|
||||
// func testItStartsWithTheCorrectItemActiveIfNotDefault() throws {
|
||||
// config = OWSDisappearingMessagesConfiguration(defaultWithThreadId: "TestId1")
|
||||
// config.isEnabled = true
|
||||
// config.durationSeconds = 30
|
||||
// viewModel = ConversationDisappearingMessagesViewModel(thread: thread, disappearingMessagesConfiguration: config) { [weak self] in
|
||||
// self?.dataChangedCallbackTriggered = true
|
||||
// }
|
||||
//
|
||||
// var nonDefaultItems: [ConversationDisappearingMessagesViewModel.Item] = defaultItems
|
||||
// nonDefaultItems[0] = nonDefaultItems[0].with(isActive: false)
|
||||
// nonDefaultItems[3] = nonDefaultItems[3].with(isActive: true)
|
||||
// expect(self.viewModel.items.value).to(equal(nonDefaultItems))
|
||||
// }
|
||||
//
|
||||
// // MARK: - Interactions
|
||||
//
|
||||
// func testItProvidesTheThreadAndGivenDataWhenAnInteractionOccurs() throws {
|
||||
// var interactionThread: TSThread? = nil
|
||||
//
|
||||
// self.viewModel.interaction.on(0) { thread in
|
||||
// interactionThread = thread
|
||||
// }
|
||||
//
|
||||
// self.viewModel.interaction.tap(0)
|
||||
//
|
||||
// expect(interactionThread).to(equal(self.thread))
|
||||
// }
|
||||
//
|
||||
// func testItRefreshesTheDataCorrectly() throws {
|
||||
// expect(self.viewModel.items.value.count).to(beGreaterThan(3))
|
||||
// expect(self.viewModel.items.value[3].id).to(equal(3))
|
||||
// expect(self.viewModel.items.value[3].isActive).to(beFalse())
|
||||
//
|
||||
// config.isEnabled = true
|
||||
// config.durationSeconds = 30
|
||||
//
|
||||
// viewModel.tryRefreshData(for: 3)
|
||||
//
|
||||
// expect(self.viewModel.items.value[3].id).to(equal(3))
|
||||
// expect(self.viewModel.items.value[3].isActive).to(beTrue())
|
||||
// }
|
||||
//
|
||||
// func testItDoesNotSetAnItemToActiveIfTheConfigIsNotEnabled() throws {
|
||||
// expect(self.viewModel.items.value.count).to(beGreaterThan(3))
|
||||
// expect(self.viewModel.items.value[3].id).to(equal(3))
|
||||
// expect(self.viewModel.items.value[3].isActive).to(beFalse())
|
||||
// var nonDefaultItems: [Item] = defaultItems
|
||||
// nonDefaultItems[0] = Item(id: nonDefaultItems[0].id, title: nonDefaultItems[0].title, isActive: false)
|
||||
// nonDefaultItems[3] = Item(id: nonDefaultItems[3].id, title: nonDefaultItems[3].title, isActive: true)
|
||||
//
|
||||
// config.durationSeconds = 30
|
||||
//
|
||||
// viewModel.tryRefreshData(for: 3)
|
||||
//
|
||||
// expect(self.viewModel.items.value[3].id).to(equal(3))
|
||||
// expect(self.viewModel.items.value[3].isActive).to(beFalse())
|
||||
// expect(self.viewModel.items.newest)
|
||||
// .toEventually(
|
||||
// equal(nonDefaultItems),
|
||||
// timeout: .milliseconds(100)
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// func testItUpdatesToADifferentValue() throws {
|
||||
// expect(self.viewModel.items.value.count).to(beGreaterThan(3))
|
||||
// expect(self.viewModel.items.value[0].id).to(equal(0))
|
||||
// expect(self.viewModel.items.value[0].isActive).to(beTrue())
|
||||
//
|
||||
// viewModel.interaction.tap(3)
|
||||
// // MARK: - Interactions
|
||||
//
|
||||
// expect(self.viewModel.items.value[0].id)
|
||||
// func testItSelectsTheItemCorrectly() throws {
|
||||
// expect(self.viewModel.items.newest)
|
||||
// .toEventually(
|
||||
// equal(0),
|
||||
// satisfyAllOf(
|
||||
// haveCountGreaterThan(3),
|
||||
// valueFor(\.id, at: 3, to: equal(3)),
|
||||
// valueFor(\.isActive, at: 3, to: beFalse())
|
||||
// ),
|
||||
// timeout: .milliseconds(100)
|
||||
// )
|
||||
// expect(self.viewModel.items.value[0].isActive)
|
||||
//
|
||||
// viewModel.itemSelected.send(3)
|
||||
//
|
||||
// expect(self.viewModel.items.newest)
|
||||
// .toEventually(
|
||||
// beFalse(),
|
||||
// satisfyAllOf(
|
||||
// valueFor(\.id, at: 3, to: equal(3)),
|
||||
// valueFor(\.isActive, at: 3, to: beTrue())
|
||||
// ),
|
||||
// timeout: .milliseconds(100)
|
||||
// )
|
||||
// expect(self.viewModel.items.value[3].id)
|
||||
// }
|
||||
//
|
||||
// func testItUpdatesToADifferentValue() throws {
|
||||
// expect(self.viewModel.items.newest)
|
||||
// .toEventually(
|
||||
// equal(3),
|
||||
// satisfyAllOf(
|
||||
// haveCountGreaterThan(3),
|
||||
// valueFor(\.id, at: 0, to: equal(0)),
|
||||
// valueFor(\.isActive, at: 0, to: beTrue())
|
||||
// ),
|
||||
// timeout: .milliseconds(100)
|
||||
// )
|
||||
// expect(self.viewModel.items.value[3].isActive)
|
||||
//
|
||||
// viewModel.itemSelected.send(3)
|
||||
//
|
||||
// expect(self.viewModel.items.newest)
|
||||
// .toEventually(
|
||||
// beTrue(),
|
||||
// satisfyAllOf(
|
||||
// valueFor(\.id, at: 0, to: equal(0)),
|
||||
// valueFor(\.isActive, at: 0, to: beFalse()),
|
||||
// valueFor(\.id, at: 3, to: equal(3)),
|
||||
// valueFor(\.isActive, at: 3, to: beTrue())
|
||||
// ),
|
||||
// timeout: .milliseconds(100)
|
||||
// )
|
||||
// }
|
||||
//
|
||||
//
|
||||
// func testItUpdatesTheConfigWhenChangingValue() throws {
|
||||
// // Note: Default for 'durationSectionds' is OWSDisappearingMessagesConfigurationDefaultExpirationDuration
|
||||
// // currently set to 86400
|
||||
// expect(self.config.isEnabled).to(beFalse())
|
||||
// expect(self.config.durationSeconds).to(equal(86400))
|
||||
//
|
||||
// viewModel.interaction.tap(3)
|
||||
//
|
||||
// viewModel.items.sink(receiveValue: { _ in }).store(in: &disposables)
|
||||
// viewModel.itemSelected.send(3)
|
||||
//
|
||||
// expect(self.config.isEnabled)
|
||||
// .toEventually(
|
||||
// beTrue(),
|
||||
// timeout: .milliseconds(100)
|
||||
// )
|
||||
// expect(self.config.durationSeconds)
|
||||
// .toEventually(
|
||||
// equal(30),
|
||||
// timeout: .milliseconds(100)
|
||||
// )
|
||||
// }
|
||||
//
|
||||
//
|
||||
// func testItDisablesTheConfigWhenSetToZero() throws {
|
||||
// config.isEnabled = true
|
||||
//
|
||||
// viewModel.interaction.tap(0)
|
||||
//
|
||||
// viewModel.items.sink(receiveValue: { _ in }).store(in: &disposables)
|
||||
// viewModel.itemSelected.send(0)
|
||||
//
|
||||
// expect(self.config.isEnabled)
|
||||
// .toEventually(
|
||||
// beFalse(),
|
||||
// timeout: .milliseconds(100)
|
||||
// )
|
||||
// expect(self.config.durationSeconds)
|
||||
// .toEventually(
|
||||
// equal(0),
|
||||
// timeout: .milliseconds(100)
|
||||
// )
|
||||
// }
|
||||
//
|
||||
//
|
||||
// func testItDoesNotSaveChangesIfTheConfigHasNotChangedFromItsDefaultState() {
|
||||
// viewModel.trySaveChanges()
|
||||
//
|
||||
//
|
||||
// // TODO: Mock out Storage.write
|
||||
// expect(self.dataChangedCallbackTriggered)
|
||||
// .toEventually(
|
||||
// beFalse(),
|
||||
// timeout: .milliseconds(100)
|
||||
// )
|
||||
// }
|
||||
//
|
||||
//
|
||||
// func testItDoesSaveChangesIfTheConfigHasChanged() {
|
||||
// config.isEnabled = true
|
||||
// config.durationSeconds = 30
|
||||
//
|
||||
//
|
||||
// viewModel.trySaveChanges()
|
||||
//
|
||||
//
|
||||
// // TODO: Mock out Storage.write
|
||||
// expect(self.dataChangedCallbackTriggered)
|
||||
// .toEventually(
|
||||
// beTrue(),
|
||||
// timeout: .milliseconds(100)
|
||||
// )
|
||||
// }
|
||||
//}
|
||||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
|
||||
import Combine
|
||||
import GRDB
|
||||
import Quick
|
||||
import Nimble
|
||||
|
||||
@testable import Session
|
||||
|
||||
class ThreadDisappearingMessagesViewModelSpec: QuickSpec {
|
||||
typealias ParentType = SessionTableViewModel<ThreadDisappearingMessagesViewModel.NavButton, ThreadDisappearingMessagesViewModel.Section, ThreadDisappearingMessagesViewModel.Item>
|
||||
|
||||
// MARK: - Spec
|
||||
|
||||
override func spec() {
|
||||
var mockStorage: Storage!
|
||||
var dataChangeCancellable: AnyCancellable?
|
||||
var otherCancellables: [AnyCancellable] = []
|
||||
var viewModel: ThreadDisappearingMessagesViewModel!
|
||||
|
||||
describe("a ThreadDisappearingMessagesViewModel") {
|
||||
// MARK: - Configuration
|
||||
|
||||
beforeEach {
|
||||
mockStorage = Storage(
|
||||
customWriter: DatabaseQueue(),
|
||||
customMigrations: [
|
||||
SNUtilitiesKit.migrations(),
|
||||
SNSnodeKit.migrations(),
|
||||
SNMessagingKit.migrations(),
|
||||
SNUIKit.migrations()
|
||||
]
|
||||
)
|
||||
mockStorage.write { db in
|
||||
try SessionThread(
|
||||
id: "TestId",
|
||||
variant: .contact
|
||||
).insert(db)
|
||||
}
|
||||
viewModel = ThreadDisappearingMessagesViewModel(
|
||||
storage: mockStorage,
|
||||
scheduling: .immediate,
|
||||
threadId: "TestId",
|
||||
config: DisappearingMessagesConfiguration.defaultWith("TestId")
|
||||
)
|
||||
dataChangeCancellable = viewModel.observableSettingsData
|
||||
.receiveOnMain(immediately: true)
|
||||
.sink(
|
||||
receiveCompletion: { _ in },
|
||||
receiveValue: { viewModel.updateSettings($0) }
|
||||
)
|
||||
}
|
||||
|
||||
afterEach {
|
||||
dataChangeCancellable?.cancel()
|
||||
otherCancellables.forEach { $0.cancel() }
|
||||
|
||||
mockStorage = nil
|
||||
dataChangeCancellable = nil
|
||||
otherCancellables = []
|
||||
viewModel = nil
|
||||
}
|
||||
|
||||
// MARK: - Basic Tests
|
||||
|
||||
it("has the correct title") {
|
||||
expect(viewModel.title).to(equal("DISAPPEARING_MESSAGES".localized()))
|
||||
}
|
||||
|
||||
it("has the correct number of items") {
|
||||
expect(viewModel.settingsData.count)
|
||||
.to(equal(1))
|
||||
expect(viewModel.settingsData.first?.elements.count)
|
||||
.to(equal(12))
|
||||
}
|
||||
|
||||
it("has the correct default state") {
|
||||
expect(viewModel.settingsData.first?.elements.first)
|
||||
.to(
|
||||
equal(
|
||||
SessionCell.Info(
|
||||
id: ThreadDisappearingMessagesViewModel.Item(
|
||||
title: "DISAPPEARING_MESSAGES_OFF".localized()
|
||||
),
|
||||
title: "DISAPPEARING_MESSAGES_OFF".localized(),
|
||||
rightAccessory: .radio(
|
||||
isSelected: { true }
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
let title: String = NSString.formatDurationSeconds(
|
||||
UInt32(DisappearingMessagesConfiguration.validDurationsSeconds.last ?? -1),
|
||||
useShortFormat: false
|
||||
)
|
||||
expect(viewModel.settingsData.first?.elements.last)
|
||||
.to(
|
||||
equal(
|
||||
SessionCell.Info(
|
||||
id: ThreadDisappearingMessagesViewModel.Item(title: title),
|
||||
title: title,
|
||||
rightAccessory: .radio(
|
||||
isSelected: { false }
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
it("starts with the correct item active if not default") {
|
||||
let config: DisappearingMessagesConfiguration = DisappearingMessagesConfiguration
|
||||
.defaultWith("TestId")
|
||||
.with(
|
||||
isEnabled: true,
|
||||
durationSeconds: DisappearingMessagesConfiguration.validDurationsSeconds.last
|
||||
)
|
||||
mockStorage.write { db in
|
||||
_ = try config.saved(db)
|
||||
}
|
||||
viewModel = ThreadDisappearingMessagesViewModel(
|
||||
storage: mockStorage,
|
||||
scheduling: .immediate,
|
||||
threadId: "TestId",
|
||||
config: config
|
||||
)
|
||||
dataChangeCancellable = viewModel.observableSettingsData
|
||||
.receiveOnMain(immediately: true)
|
||||
.sink(
|
||||
receiveCompletion: { _ in },
|
||||
receiveValue: { viewModel.updateSettings($0) }
|
||||
)
|
||||
|
||||
expect(viewModel.settingsData.first?.elements.first)
|
||||
.to(
|
||||
equal(
|
||||
SessionCell.Info(
|
||||
id: ThreadDisappearingMessagesViewModel.Item(
|
||||
title: "DISAPPEARING_MESSAGES_OFF".localized()
|
||||
),
|
||||
title: "DISAPPEARING_MESSAGES_OFF".localized(),
|
||||
rightAccessory: .radio(
|
||||
isSelected: { false }
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
let title: String = NSString.formatDurationSeconds(
|
||||
UInt32(DisappearingMessagesConfiguration.validDurationsSeconds.last ?? -1),
|
||||
useShortFormat: false
|
||||
)
|
||||
expect(viewModel.settingsData.first?.elements.last)
|
||||
.to(
|
||||
equal(
|
||||
SessionCell.Info(
|
||||
id: ThreadDisappearingMessagesViewModel.Item(title: title),
|
||||
title: title,
|
||||
rightAccessory: .radio(
|
||||
isSelected: { true }
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
it("has no right bar button") {
|
||||
var items: [ParentType.NavItem]?
|
||||
|
||||
otherCancellables.append(
|
||||
viewModel.rightNavItems
|
||||
.receiveOnMain(immediately: true)
|
||||
.sink(
|
||||
receiveCompletion: { _ in },
|
||||
receiveValue: { navItems in items = navItems }
|
||||
)
|
||||
)
|
||||
|
||||
expect(items).to(equal([]))
|
||||
}
|
||||
|
||||
context("when changed from the previous setting") {
|
||||
var items: [ParentType.NavItem]?
|
||||
|
||||
beforeEach {
|
||||
otherCancellables.append(
|
||||
viewModel.rightNavItems
|
||||
.receiveOnMain(immediately: true)
|
||||
.sink(
|
||||
receiveCompletion: { _ in },
|
||||
receiveValue: { navItems in items = navItems }
|
||||
)
|
||||
)
|
||||
|
||||
viewModel.settingsData.first?.elements.last?.onTap?(nil)
|
||||
}
|
||||
|
||||
it("shows the save button") {
|
||||
expect(items)
|
||||
.to(equal([
|
||||
ParentType.NavItem(
|
||||
id: .save,
|
||||
systemItem: .save,
|
||||
accessibilityIdentifier: "Save button"
|
||||
)
|
||||
]))
|
||||
}
|
||||
|
||||
context("and saving") {
|
||||
it("dismisses the screen") {
|
||||
var didDismissScreen: Bool = false
|
||||
|
||||
otherCancellables.append(
|
||||
viewModel.dismissScreen
|
||||
.receiveOnMain(immediately: true)
|
||||
.sink(
|
||||
receiveCompletion: { _ in },
|
||||
receiveValue: { _ in didDismissScreen = true }
|
||||
)
|
||||
)
|
||||
|
||||
items?.first?.action?()
|
||||
|
||||
expect(didDismissScreen)
|
||||
.toEventually(
|
||||
beTrue(),
|
||||
timeout: .milliseconds(100)
|
||||
)
|
||||
}
|
||||
|
||||
it("saves the updated config") {
|
||||
items?.first?.action?()
|
||||
|
||||
let updatedConfig: DisappearingMessagesConfiguration? = mockStorage.read { db in
|
||||
try DisappearingMessagesConfiguration.fetchOne(db, id: "TestId")
|
||||
}
|
||||
|
||||
expect(updatedConfig?.isEnabled)
|
||||
.toEventually(
|
||||
beTrue(),
|
||||
timeout: .milliseconds(100)
|
||||
)
|
||||
expect(updatedConfig?.durationSeconds)
|
||||
.toEventually(
|
||||
equal(DisappearingMessagesConfiguration.validDurationsSeconds.last ?? -1),
|
||||
timeout: .milliseconds(100)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
|
||||
import XCTest
|
||||
|
||||
class SessionTests: XCTestCase {
|
||||
|
||||
override func setUpWithError() throws {
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
}
|
||||
|
||||
override func tearDownWithError() throws {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
}
|
||||
|
||||
func testExample() throws {
|
||||
// This is an example of a functional test case.
|
||||
// Use XCTAssert and related functions to verify your tests produce the correct results.
|
||||
// Any test you write for XCTest can be annotated as throws and async.
|
||||
// Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
|
||||
// Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
|
||||
}
|
||||
|
||||
func testPerformanceExample() throws {
|
||||
// This is an example of a performance test case.
|
||||
measure {
|
||||
// Put the code you want to measure the time of here.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -13,6 +13,7 @@ class NotificationContentViewModelSpec: QuickSpec {
|
|||
override func spec() {
|
||||
var mockStorage: Storage!
|
||||
var dataChangeCancellable: AnyCancellable?
|
||||
var dismissCancellable: AnyCancellable?
|
||||
var viewModel: NotificationContentViewModel!
|
||||
|
||||
describe("a NotificationContentViewModel") {
|
||||
|
@ -28,7 +29,7 @@ class NotificationContentViewModelSpec: QuickSpec {
|
|||
SNUIKit.migrations()
|
||||
]
|
||||
)
|
||||
viewModel = NotificationContentViewModel(storage: mockStorage)
|
||||
viewModel = NotificationContentViewModel(storage: mockStorage, scheduling: .immediate)
|
||||
dataChangeCancellable = viewModel.observableSettingsData
|
||||
.receiveOnMain(immediately: true)
|
||||
.sink(
|
||||
|
@ -39,9 +40,11 @@ class NotificationContentViewModelSpec: QuickSpec {
|
|||
|
||||
afterEach {
|
||||
dataChangeCancellable?.cancel()
|
||||
dismissCancellable?.cancel()
|
||||
|
||||
mockStorage = nil
|
||||
dataChangeCancellable = nil
|
||||
dismissCancellable = nil
|
||||
viewModel = nil
|
||||
}
|
||||
|
||||
|
@ -53,53 +56,37 @@ class NotificationContentViewModelSpec: QuickSpec {
|
|||
|
||||
it("has the correct number of items") {
|
||||
expect(viewModel.settingsData.count)
|
||||
.toEventually(
|
||||
equal(1),
|
||||
timeout: .milliseconds(10)
|
||||
)
|
||||
.to(equal(1))
|
||||
expect(viewModel.settingsData.first?.elements.count)
|
||||
.toEventually(
|
||||
equal(3),
|
||||
timeout: .milliseconds(10)
|
||||
)
|
||||
.to(equal(3))
|
||||
}
|
||||
|
||||
it("has the correct default state") {
|
||||
expect(viewModel.settingsData.first?.elements )
|
||||
.toEventually(
|
||||
expect(viewModel.settingsData.first?.elements)
|
||||
.to(
|
||||
equal([
|
||||
SettingInfo(
|
||||
SessionCell.Info(
|
||||
id: Preferences.NotificationPreviewType.nameAndPreview,
|
||||
title: "NOTIFICATIONS_SENDER_AND_MESSAGE".localized(),
|
||||
action: .listSelection(
|
||||
isSelected: { true },
|
||||
storedSelection: true,
|
||||
shouldAutoSave: true,
|
||||
selectValue: {}
|
||||
title: "NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT".localized(),
|
||||
rightAccessory: .radio(
|
||||
isSelected: { true }
|
||||
)
|
||||
),
|
||||
SettingInfo(
|
||||
SessionCell.Info(
|
||||
id: Preferences.NotificationPreviewType.nameNoPreview,
|
||||
title: "NOTIFICATIONS_SENDER_ONLY".localized(),
|
||||
action: .listSelection(
|
||||
isSelected: { false },
|
||||
storedSelection: false,
|
||||
shouldAutoSave: true,
|
||||
selectValue: {}
|
||||
title: "NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY".localized(),
|
||||
rightAccessory: .radio(
|
||||
isSelected: { false }
|
||||
)
|
||||
),
|
||||
SettingInfo(
|
||||
SessionCell.Info(
|
||||
id: Preferences.NotificationPreviewType.noNameNoPreview,
|
||||
title: "NOTIFICATIONS_NONE".localized(),
|
||||
action: .listSelection(
|
||||
isSelected: { false },
|
||||
storedSelection: false,
|
||||
shouldAutoSave: true,
|
||||
selectValue: {}
|
||||
title: "NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT".localized(),
|
||||
rightAccessory: .radio(
|
||||
isSelected: { false }
|
||||
)
|
||||
)
|
||||
]),
|
||||
timeout: .milliseconds(10)
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -107,7 +94,7 @@ class NotificationContentViewModelSpec: QuickSpec {
|
|||
mockStorage.write { db in
|
||||
db[.preferencesNotificationPreviewType] = Preferences.NotificationPreviewType.nameNoPreview
|
||||
}
|
||||
viewModel = NotificationContentViewModel(storage: mockStorage)
|
||||
viewModel = NotificationContentViewModel(storage: mockStorage, scheduling: .immediate)
|
||||
dataChangeCancellable = viewModel.observableSettingsData
|
||||
.receiveOnMain(immediately: true)
|
||||
.sink(
|
||||
|
@ -115,43 +102,56 @@ class NotificationContentViewModelSpec: QuickSpec {
|
|||
receiveValue: { viewModel.updateSettings($0) }
|
||||
)
|
||||
|
||||
expect(viewModel.settingsData.first?.elements )
|
||||
.toEventually(
|
||||
expect(viewModel.settingsData.first?.elements)
|
||||
.to(
|
||||
equal([
|
||||
SettingInfo(
|
||||
SessionCell.Info(
|
||||
id: Preferences.NotificationPreviewType.nameAndPreview,
|
||||
title: "NOTIFICATIONS_SENDER_AND_MESSAGE".localized(),
|
||||
action: .listSelection(
|
||||
isSelected: { false },
|
||||
storedSelection: false,
|
||||
shouldAutoSave: true,
|
||||
selectValue: {}
|
||||
title: "NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_AND_CONTENT".localized(),
|
||||
rightAccessory: .radio(
|
||||
isSelected: { false }
|
||||
)
|
||||
),
|
||||
SettingInfo(
|
||||
SessionCell.Info(
|
||||
id: Preferences.NotificationPreviewType.nameNoPreview,
|
||||
title: "NOTIFICATIONS_SENDER_ONLY".localized(),
|
||||
action: .listSelection(
|
||||
isSelected: { true },
|
||||
storedSelection: true,
|
||||
shouldAutoSave: true,
|
||||
selectValue: {}
|
||||
title: "NOTIFICATIONS_STYLE_CONTENT_OPTION_NAME_ONLY".localized(),
|
||||
rightAccessory: .radio(
|
||||
isSelected: { true }
|
||||
)
|
||||
),
|
||||
SettingInfo(
|
||||
SessionCell.Info(
|
||||
id: Preferences.NotificationPreviewType.noNameNoPreview,
|
||||
title: "NOTIFICATIONS_NONE".localized(),
|
||||
action: .listSelection(
|
||||
isSelected: { false },
|
||||
storedSelection: false,
|
||||
shouldAutoSave: true,
|
||||
selectValue: {}
|
||||
title: "NOTIFICATIONS_STYLE_CONTENT_OPTION_NO_NAME_OR_CONTENT".localized(),
|
||||
rightAccessory: .radio(
|
||||
isSelected: { false }
|
||||
)
|
||||
)
|
||||
]),
|
||||
timeout: .milliseconds(10)
|
||||
])
|
||||
)
|
||||
}
|
||||
|
||||
context("when tapping an item") {
|
||||
it("updates the saved preference") {
|
||||
viewModel.settingsData.first?.elements.last?.onTap?(nil)
|
||||
|
||||
expect(mockStorage[.preferencesNotificationPreviewType])
|
||||
.to(equal(Preferences.NotificationPreviewType.noNameNoPreview))
|
||||
}
|
||||
|
||||
it("dismisses the screen") {
|
||||
var didDismissScreen: Bool = false
|
||||
|
||||
dismissCancellable = viewModel.dismissScreen
|
||||
.receiveOnMain(immediately: true)
|
||||
.sink(
|
||||
receiveCompletion: { _ in },
|
||||
receiveValue: { _ in didDismissScreen = true }
|
||||
)
|
||||
viewModel.settingsData.first?.elements.last?.onTap?(nil)
|
||||
|
||||
expect(didDismissScreen).to(beTrue())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ public final class Storage {
|
|||
public static let shared: Storage = Storage()
|
||||
public private(set) var isValid: Bool = false
|
||||
public private(set) var hasCompletedMigrations: Bool = false
|
||||
public static let defaultPublisherScheduler: ValueObservationScheduler = .async(onQueue: .main)
|
||||
|
||||
fileprivate var dbWriter: DatabaseWriter?
|
||||
private var migrator: DatabaseMigrator?
|
||||
|
@ -429,12 +430,15 @@ public extension Storage {
|
|||
// MARK: - Combine Extensions
|
||||
|
||||
public extension ValueObservation {
|
||||
func publisher(in storage: Storage) -> AnyPublisher<Reducer.Value, Error> {
|
||||
func publisher(
|
||||
in storage: Storage,
|
||||
scheduling scheduler: ValueObservationScheduler = Storage.defaultPublisherScheduler
|
||||
) -> AnyPublisher<Reducer.Value, Error> {
|
||||
guard storage.isValid, let dbWriter: DatabaseWriter = storage.dbWriter else {
|
||||
return Fail(error: StorageError.databaseInvalid).eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
return self.publisher(in: dbWriter)
|
||||
|
||||
return self.publisher(in: dbWriter, scheduling: scheduler)
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue