Added disappearing messages support to updated groups

Added disappearing messages support to updated groups
Added the 10s & 60s debug disappearing message setting options to the DeveloperSettingsViewModel
Copy tweaks on the DeveloperSettingsViewModel
Removed some unused code
pull/941/head
Morgan Pretty 1 year ago
parent 988fa5c550
commit b7b7b4af6a

@ -85,15 +85,18 @@ class ThreadDisappearingMessagesSettingsViewModel: SessionTableViewModel, Naviga
let title: String = "DISAPPEARING_MESSAGES".localized() let title: String = "DISAPPEARING_MESSAGES".localized()
lazy var subtitle: String? = { lazy var subtitle: String? = {
guard dependencies[feature: .updatedDisappearingMessages] else { switch (threadVariant, isNoteToSelf) {
return (isNoteToSelf ? nil : "DISAPPERING_MESSAGES_SUBTITLE_CONTACTS".localized()) case (.contact, false): return "DISAPPERING_MESSAGES_SUBTITLE_CONTACTS".localized()
} case (.group, _): return "DISAPPERING_MESSAGES_SUBTITLE_GROUPS".localized()
case (.community, _): return nil
if threadVariant == .contact && !isNoteToSelf {
return "DISAPPERING_MESSAGES_SUBTITLE_CONTACTS".localized() case (.legacyGroup, _), (_, true):
guard dependencies[feature: .updatedDisappearingMessages] else {
return (isNoteToSelf ? nil : "DISAPPERING_MESSAGES_SUBTITLE_CONTACTS".localized())
}
return "DISAPPERING_MESSAGES_SUBTITLE_GROUPS".localized()
} }
return "DISAPPERING_MESSAGES_SUBTITLE_GROUPS".localized()
}() }()
lazy var footerButtonInfo: AnyPublisher<SessionButton.Info?, Never> = configSubject lazy var footerButtonInfo: AnyPublisher<SessionButton.Info?, Never> = configSubject
@ -272,7 +275,7 @@ class ThreadDisappearingMessagesSettingsViewModel: SessionTableViewModel, Naviga
} }
return (currentConfig.type ?? .disappearAfterSend) return (currentConfig.type ?? .disappearAfterSend)
}()) }(), using: dependencies)
.map { duration in .map { duration in
let title: String = duration.formatted(format: .long) let title: String = duration.formatted(format: .long)
@ -302,8 +305,77 @@ class ThreadDisappearingMessagesSettingsViewModel: SessionTableViewModel, Naviga
) )
) )
].compactMap { $0 } ].compactMap { $0 }
case (.group, _):
return [
SectionModel(
model: .group,
elements: [
SessionCell.Info(
id: "DISAPPEARING_MESSAGES_OFF".localized(),
title: "DISAPPEARING_MESSAGES_OFF".localized(),
trailingAccessory: .radio(
isSelected: !currentConfig.isEnabled
),
isEnabled: (currentUserIsClosedGroupAdmin == true),
accessibility: Accessibility(
identifier: "Disable disappearing messages (Off option)",
label: "Disable disappearing messages (Off option)"
),
onTap: {
self?.configSubject.send(
currentConfig.with(
isEnabled: false,
durationSeconds: DisappearingMessagesConfiguration.DefaultDuration.off.seconds,
lastChangeTimestampMs: SnodeAPI.currentOffsetTimestampMs()
)
)
}
)
]
.appending(
contentsOf: DisappearingMessagesConfiguration
.validDurationsSeconds(.disappearAfterSend, using: dependencies)
.map { duration in
let title: String = duration.formatted(format: .long)
case (.legacyGroup, _), (.group, _), (_, true): return SessionCell.Info(
id: title,
title: title,
trailingAccessory: .radio(
isSelected: (
currentConfig.isEnabled &&
currentConfig.durationSeconds == duration
)
),
isEnabled: (currentUserIsClosedGroupAdmin == true),
accessibility: Accessibility(
identifier: "Time option",
label: "Time option"
),
onTap: {
// If the new disappearing messages config feature flag isn't
// enabled then the 'isEnabled' and 'type' values are set via
// the first section so pass `nil` values to keep the existing
// setting
self?.configSubject.send(
currentConfig.with(
isEnabled: true,
durationSeconds: duration,
type: .disappearAfterSend,
lastChangeTimestampMs: SnodeAPI.currentOffsetTimestampMs(
using: dependencies
)
)
)
}
)
}
)
)
]
case (.legacyGroup, _), (_, true):
return [ return [
(dependencies[feature: .updatedDisappearingMessages] ? nil : (dependencies[feature: .updatedDisappearingMessages] ? nil :
SectionModel( SectionModel(
@ -415,7 +487,7 @@ class ThreadDisappearingMessagesSettingsViewModel: SessionTableViewModel, Naviga
.compactMap { $0 } .compactMap { $0 }
.appending( .appending(
contentsOf: DisappearingMessagesConfiguration contentsOf: DisappearingMessagesConfiguration
.validDurationsSeconds(.disappearAfterSend) .validDurationsSeconds(.disappearAfterSend, using: dependencies)
.map { duration in .map { duration in
let title: String = duration.formatted(format: .long) let title: String = duration.formatted(format: .long)
@ -483,7 +555,7 @@ class ThreadDisappearingMessagesSettingsViewModel: SessionTableViewModel, Naviga
.filter(Interaction.Columns.variant == Interaction.Variant.infoDisappearingMessagesUpdate) .filter(Interaction.Columns.variant == Interaction.Variant.infoDisappearingMessagesUpdate)
.deleteAll(db) .deleteAll(db)
let currentOffsetTimestampMs: Int64 = SnodeAPI.currentOffsetTimestampMs() let currentOffsetTimestampMs: Int64 = SnodeAPI.currentOffsetTimestampMs(using: dependencies)
let interaction: Interaction = try Interaction( let interaction: Interaction = try Interaction(
threadId: threadId, threadId: threadId,
@ -496,22 +568,46 @@ class ThreadDisappearingMessagesSettingsViewModel: SessionTableViewModel, Naviga
) )
.inserted(db) .inserted(db)
let duration: UInt32? = { // Send a control message that the disappearing messages setting changed
guard !dependencies[feature: .updatedDisappearingMessages] else { return nil } switch threadVariant {
return UInt32(floor(updatedConfig.isEnabled ? updatedConfig.durationSeconds : 0)) case .group:
}() try MessageSender.send(
db,
message: GroupUpdateInfoChangeMessage(
changeType: .disappearingMessages,
updatedExpiration: UInt32(updatedConfig.isEnabled ? updatedConfig.durationSeconds : 0),
sentTimestamp: UInt64(currentOffsetTimestampMs),
authMethod: try Authentication.with(
db,
sessionIdHexString: threadId,
using: dependencies
),
using: dependencies
),
interactionId: nil,
threadId: threadId,
threadVariant: .group,
using: dependencies
)
default:
let duration: UInt32? = {
guard !dependencies[feature: .updatedDisappearingMessages] else { return nil }
return UInt32(floor(updatedConfig.isEnabled ? updatedConfig.durationSeconds : 0))
}()
try MessageSender.send( try MessageSender.send(
db, db,
message: ExpirationTimerUpdate( message: ExpirationTimerUpdate(
syncTarget: nil, syncTarget: nil,
duration: duration duration: duration
), ),
interactionId: interaction.id, interactionId: interaction.id,
threadId: threadId, threadId: threadId,
threadVariant: threadVariant, threadVariant: threadVariant,
using: dependencies using: dependencies
) )
}
} }
// Contacts & legacy closed groups need to update the SessionUtil // Contacts & legacy closed groups need to update the SessionUtil

@ -13,8 +13,6 @@ import SessionUtilitiesKit
import SignalCoreKit import SignalCoreKit
class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder, ObservableTableSource { class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder, ObservableTableSource {
typealias TableItem = Section
public let dependencies: Dependencies public let dependencies: Dependencies
public let navigatableState: NavigatableState = NavigatableState() public let navigatableState: NavigatableState = NavigatableState()
public let state: TableDataState<Section, TableItem> = TableDataState() public let state: TableDataState<Section, TableItem> = TableDataState()
@ -30,29 +28,61 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
// MARK: - Section // MARK: - Section
public enum Section: SessionTableSection, CaseIterable { public enum Section: SessionTableSection {
case developerMode
case network
case disappearingMessages
case groups
case database
var title: String? {
switch self {
case .developerMode: return nil
case .network: return "Network"
case .disappearingMessages: return "Disappearing Messages"
case .groups: return "Groups"
case .database: return "Database"
}
}
//default: return .titleRoundedContent // .padding
var style: SessionTableSectionStyle {
switch self {
case .developerMode: return .padding
default: return .titleRoundedContent
}
}
}
public enum TableItem: Differentiable, CaseIterable {
case developerMode case developerMode
case serviceNetwork case serviceNetwork
case networkLayer case networkLayer
case updatedDisappearingMessages case updatedDisappearingMessages
case debugDisappearingMessageDurations
case updatedGroups case updatedGroups
case updatedGroupsRemoveMessagesOnKick case updatedGroupsRemoveMessagesOnKick
case updatedGroupsAllowHistoricAccessOnInvite case updatedGroupsAllowHistoricAccessOnInvite
case updatedGroupsAllowDisplayPicture case updatedGroupsAllowDisplayPicture
case updatedGroupsAllowDescriptionEditing case updatedGroupsAllowDescriptionEditing
case updatedGroupsAllowPromotions case updatedGroupsAllowPromotions
case exportDatabase
var style: SessionTableSectionStyle { .padding } case exportDatabase
} }
// MARK: - Content // MARK: - Content
private struct State: Equatable { private struct State: Equatable {
let developerMode: Bool let developerMode: Bool
let serviceNetwork: ServiceNetwork let serviceNetwork: ServiceNetwork
let networkLayer: Network.Layers let networkLayer: Network.Layers
let debugDisappearingMessageDurations: Bool
let updatedDisappearingMessages: Bool let updatedDisappearingMessages: Bool
let updatedGroups: Bool let updatedGroups: Bool
let updatedGroupsRemoveMessagesOnKick: Bool let updatedGroupsRemoveMessagesOnKick: Bool
let updatedGroupsAllowHistoricAccessOnInvite: Bool let updatedGroupsAllowHistoricAccessOnInvite: Bool
@ -69,6 +99,7 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
developerMode: dependencies[singleton: .storage, key: .developerModeEnabled], developerMode: dependencies[singleton: .storage, key: .developerModeEnabled],
serviceNetwork: dependencies[feature: .serviceNetwork], serviceNetwork: dependencies[feature: .serviceNetwork],
networkLayer: dependencies[feature: .networkLayers], networkLayer: dependencies[feature: .networkLayers],
debugDisappearingMessageDurations: dependencies[feature: .debugDisappearingMessageDurations],
updatedDisappearingMessages: dependencies[feature: .updatedDisappearingMessages], updatedDisappearingMessages: dependencies[feature: .updatedDisappearingMessages],
updatedGroups: dependencies[feature: .updatedGroups], updatedGroups: dependencies[feature: .updatedGroups],
updatedGroupsRemoveMessagesOnKick: dependencies[feature: .updatedGroupsRemoveMessagesOnKick], updatedGroupsRemoveMessagesOnKick: dependencies[feature: .updatedGroupsRemoveMessagesOnKick],
@ -87,9 +118,11 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
id: .developerMode, id: .developerMode,
title: "Developer Mode", title: "Developer Mode",
subtitle: """ subtitle: """
Developer Mode grants the device access to the settings on this screen. Grants access to this screen.
Disabling this setting will reset all of the below settings back to default (removing data as described below) and revoke access to this screen unless Developer Mode is re-enabled. Disabling this setting will:
Reset all the below settings to default (removing data as described below)
Revoke access to this screen unless Developer Mode is re-enabled
""", """,
trailingAccessory: .toggle( trailingAccessory: .toggle(
.boolValue(current.developerMode, oldValue: (previous ?? current).developerMode) .boolValue(current.developerMode, oldValue: (previous ?? current).developerMode)
@ -103,15 +136,16 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
] ]
), ),
SectionModel( SectionModel(
model: .serviceNetwork, model: .network,
elements: [ elements: [
SessionCell.Info( SessionCell.Info(
id: .serviceNetwork, id: .serviceNetwork,
title: "Network", title: "Environment",
subtitle: """ subtitle: """
The service network which should be used for sending requests and storing messages. The environment used for sending requests and storing messages.
<b>Warning:</b> These networks cannot communicate with each other so changing this network will result in all conversation and snode data being cleared and any pending network requests being cancelled. <b>Warning:</b>
Changing this setting will result in all conversation and snode data being cleared and any pending network requests being cancelled.
""", """,
trailingAccessory: .dropDown( trailingAccessory: .dropDown(
.dynamicString { current.serviceNetwork.title } .dynamicString { current.serviceNetwork.title }
@ -120,7 +154,7 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
self?.transitionToScreen( self?.transitionToScreen(
SessionTableViewController( SessionTableViewController(
viewModel: SessionListViewModel<ServiceNetwork>( viewModel: SessionListViewModel<ServiceNetwork>(
title: "Network", title: "Environment",
options: ServiceNetwork.allCases, options: ServiceNetwork.allCases,
behaviour: .autoDismiss( behaviour: .autoDismiss(
initialSelection: current.serviceNetwork, initialSelection: current.serviceNetwork,
@ -131,19 +165,17 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
) )
) )
} }
) ),
]
),
SectionModel(
model: .networkLayer,
elements: [
SessionCell.Info( SessionCell.Info(
id: .networkLayer, id: .networkLayer,
title: "Network Layer", title: "Routing",
subtitle: """ subtitle: """
The network layer which all network traffic should be routed through. We do support sending network traffic through multiple network layers, if multiple layers are selected then requests will wait for a response from all layers before completing with the first successful response. The network layer which all network traffic should be routed through.
We do support sending network traffic through multiple network layers, if multiple layers are selected then requests will wait for a response from all layers before completing with the first successful response.
<b>Warning:</b> Different network layers offer different levels of privacy, make sure to read the description of the network layers before making a selection. <b>Warning:</b>
Different network layers offer different levels of privacy, make sure to read the description of the network layers before making a selection.
""", """,
trailingAccessory: .dropDown( trailingAccessory: .dropDown(
.dynamicString { current.networkLayer.title } .dynamicString { current.networkLayer.title }
@ -152,7 +184,7 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
self?.transitionToScreen( self?.transitionToScreen(
SessionTableViewController( SessionTableViewController(
viewModel: SessionListViewModel<Network.Layers>( viewModel: SessionListViewModel<Network.Layers>(
title: "Network Layer", title: "Routing",
options: Network.Layers.allCases, options: Network.Layers.allCases,
behaviour: .singleSelect( behaviour: .singleSelect(
initialSelection: current.networkLayer, initialSelection: current.networkLayer,
@ -167,13 +199,34 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
] ]
), ),
SectionModel( SectionModel(
model: .updatedDisappearingMessages, model: .disappearingMessages,
elements: [ elements: [
SessionCell.Info(
id: .debugDisappearingMessageDurations,
title: "Debug Durations",
subtitle: """
Adds 10 and 60 second durations for Disappearing Message settings.
These should only be used for debugging purposes and can result in odd behaviours.
""",
trailingAccessory: .toggle(
.boolValue(
current.debugDisappearingMessageDurations,
oldValue: (previous ?? current).debugDisappearingMessageDurations
)
),
onTap: {
self?.updateFlag(
for: .debugDisappearingMessageDurations,
to: !current.debugDisappearingMessageDurations
)
}
),
SessionCell.Info( SessionCell.Info(
id: .updatedDisappearingMessages, id: .updatedDisappearingMessages,
title: "Updated Disappearing Messages", title: "Use Updated Disappearing Messages",
subtitle: """ subtitle: """
This setting controls whether legacy or updated disappearing messages should be used. Controls whether legacy or updated disappearing messages should be used.
""", """,
trailingAccessory: .toggle( trailingAccessory: .toggle(
.boolValue( .boolValue(
@ -191,29 +244,24 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
] ]
), ),
SectionModel( SectionModel(
model: .updatedGroups, model: .groups,
elements: [ elements: [
SessionCell.Info( SessionCell.Info(
id: .updatedGroups, id: .updatedGroups,
title: "Updated Groups", title: "Use Updated Groups",
subtitle: """ subtitle: """
This settings controls whether newly created groups should use the updated groups or legacy groups. Controls whether newly created groups are updated or legacy groups.
""", """,
trailingAccessory: .toggle( trailingAccessory: .toggle(
.boolValue(current.updatedGroups, oldValue: (previous ?? current).updatedGroups) .boolValue(current.updatedGroups, oldValue: (previous ?? current).updatedGroups)
), ),
onTap: { self?.updateFlag(for: .updatedGroups, to: !current.updatedGroups) } onTap: { self?.updateFlag(for: .updatedGroups, to: !current.updatedGroups) }
) ),
]
),
SectionModel(
model: .updatedGroupsRemoveMessagesOnKick,
elements: [
SessionCell.Info( SessionCell.Info(
id: .updatedGroupsRemoveMessagesOnKick, id: .updatedGroupsRemoveMessagesOnKick,
title: "Remove Messages when Kicking from Updated Groups", title: "Remove Messages on Kick",
subtitle: """ subtitle: """
This settings controls whether a group members messages should be removed when they are kicked from an updated group. Controls whether a group members messages should be removed when they are kicked from an updated group.
<b>Note:</b> In a future release we will offer this as an option when removing members but for the initial release it can be controlled via this flag for testing purposes. <b>Note:</b> In a future release we will offer this as an option when removing members but for the initial release it can be controlled via this flag for testing purposes.
""", """,
@ -229,17 +277,12 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
to: !current.updatedGroupsRemoveMessagesOnKick to: !current.updatedGroupsRemoveMessagesOnKick
) )
} }
) ),
]
),
SectionModel(
model: .updatedGroupsAllowHistoricAccessOnInvite,
elements: [
SessionCell.Info( SessionCell.Info(
id: .updatedGroupsAllowHistoricAccessOnInvite, id: .updatedGroupsAllowHistoricAccessOnInvite,
title: "Allow access to historic messages when inviting to an updated group", title: "Allow Historic Message Access",
subtitle: """ subtitle: """
This settings controls whether a group members should be granted access to hsitoric messages when invited to an updated group. Controls whether members should be granted access to historic messages when invited to an updated group.
<b>Note:</b> In a future release we will offer this as an option when inviting members but for the initial release it can be controlled via this flag for testing purposes. <b>Note:</b> In a future release we will offer this as an option when inviting members but for the initial release it can be controlled via this flag for testing purposes.
""", """,
@ -255,17 +298,12 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
to: !current.updatedGroupsAllowHistoricAccessOnInvite to: !current.updatedGroupsAllowHistoricAccessOnInvite
) )
} }
) ),
]
),
SectionModel(
model: .updatedGroupsAllowDisplayPicture,
elements: [
SessionCell.Info( SessionCell.Info(
id: .updatedGroupsAllowDisplayPicture, id: .updatedGroupsAllowDisplayPicture,
title: "Shows UI for setting updated group custom display pictures", title: "Custom Display Pictures",
subtitle: """ subtitle: """
This settings controls whether the UI allows group admins to set a custom display picture for a group. Controls whether the UI allows group admins to set a custom display picture for a group.
<b>Note:</b> In a future release we will offer this functionality but for the initial release it may not be fully supported across platforms so can be controlled via this flag for testing purposes. <b>Note:</b> In a future release we will offer this functionality but for the initial release it may not be fully supported across platforms so can be controlled via this flag for testing purposes.
""", """,
@ -281,17 +319,12 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
to: !current.updatedGroupsAllowDisplayPicture to: !current.updatedGroupsAllowDisplayPicture
) )
} }
) ),
]
),
SectionModel(
model: .updatedGroupsAllowDescriptionEditing,
elements: [
SessionCell.Info( SessionCell.Info(
id: .updatedGroupsAllowDescriptionEditing, id: .updatedGroupsAllowDescriptionEditing,
title: "Show UI for editing updated group descriptions", title: "Edit Group Descriptions",
subtitle: """ subtitle: """
This settings controls whether the UI allows group admins to modify the descriptions of updated groups. Controls whether the UI allows group admins to modify the descriptions of updated groups.
<b>Note:</b> In a future release we will offer this functionality but for the initial release it may not be fully supported across platforms so can be controlled via this flag for testing purposes. <b>Note:</b> In a future release we will offer this functionality but for the initial release it may not be fully supported across platforms so can be controlled via this flag for testing purposes.
""", """,
@ -307,17 +340,12 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
to: !current.updatedGroupsAllowDescriptionEditing to: !current.updatedGroupsAllowDescriptionEditing
) )
} }
) ),
]
),
SectionModel(
model: .updatedGroupsAllowPromotions,
elements: [
SessionCell.Info( SessionCell.Info(
id: .updatedGroupsAllowPromotions, id: .updatedGroupsAllowPromotions,
title: "Show UI for updated group promotions", title: "Allow Group Promotions",
subtitle: """ subtitle: """
This settings controls whether the UI allows group admins promote other group members to admin within an updated group. Controls whether the UI allows group admins promote other group members to admin within an updated group.
<b>Note:</b> In a future release we will offer this functionality but for the initial release it may not be fully supported across platforms so can be controlled via this flag for testing purposes. <b>Note:</b> In a future release we will offer this functionality but for the initial release it may not be fully supported across platforms so can be controlled via this flag for testing purposes.
""", """,
@ -337,7 +365,7 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
] ]
), ),
SectionModel( SectionModel(
model: .exportDatabase, model: .database,
elements: [ elements: [
SessionCell.Info( SessionCell.Info(
id: .exportDatabase, id: .exportDatabase,
@ -362,14 +390,18 @@ class DeveloperSettingsViewModel: SessionTableViewModel, NavigatableStateHolder,
private func disableDeveloperMode() { private func disableDeveloperMode() {
/// Loop through all of the sections and reset the features back to default for each one as needed (this way if a new section is added /// Loop through all of the sections and reset the features back to default for each one as needed (this way if a new section is added
/// then we will get a compile error if it doesn't get resetting instructions added) /// then we will get a compile error if it doesn't get resetting instructions added)
Section.allCases.forEach { section in TableItem.allCases.forEach { item in
switch section { switch item {
case .developerMode: break // Not a feature case .developerMode: break // Not a feature
case .exportDatabase: break // Not a feature case .exportDatabase: break // Not a feature
case .serviceNetwork: updateServiceNetwork(to: nil) case .serviceNetwork: updateServiceNetwork(to: nil)
case .networkLayer: updateNetworkLayers(to: nil) case .networkLayer: updateNetworkLayers(to: nil)
case .debugDisappearingMessageDurations:
updateFlag(for: .debugDisappearingMessageDurations, to: nil)
case .updatedDisappearingMessages: updateFlag(for: .updatedDisappearingMessages, to: nil) case .updatedDisappearingMessages: updateFlag(for: .updatedDisappearingMessages, to: nil)
case .updatedGroups: updateFlag(for: .updatedGroups, to: nil) case .updatedGroups: updateFlag(for: .updatedGroups, to: nil)
case .updatedGroupsRemoveMessagesOnKick: updateFlag(for: .updatedGroupsRemoveMessagesOnKick, to: nil) case .updatedGroupsRemoveMessagesOnKick: updateFlag(for: .updatedGroupsRemoveMessagesOnKick, to: nil)
case .updatedGroupsAllowHistoricAccessOnInvite: case .updatedGroupsAllowHistoricAccessOnInvite:

@ -247,32 +247,15 @@ public extension DisappearingMessagesConfiguration {
// MARK: - UI Constraints // MARK: - UI Constraints
extension DisappearingMessagesConfiguration { extension DisappearingMessagesConfiguration {
// TODO: Remove this when disappearing messages V2 is up and running public static func validDurationsSeconds(
public static var validDurationsSeconds: [TimeInterval] { _ type: DisappearingMessageType,
return [ using dependencies: Dependencies
5, ) -> [TimeInterval] {
10,
30,
(1 * 60),
(5 * 60),
(30 * 60),
(1 * 60 * 60),
(6 * 60 * 60),
(12 * 60 * 60),
(24 * 60 * 60),
(7 * 24 * 60 * 60)
]
}
public static var maxDurationSeconds: TimeInterval = {
return (validDurationsSeconds.max() ?? 0)
}()
public static func validDurationsSeconds(_ type: DisappearingMessageType) -> [TimeInterval] {
switch type { switch type {
case .disappearAfterRead: case .disappearAfterRead:
var result = [ return [
(dependencies[feature: .debugDisappearingMessageDurations] ? 10 : nil),
(dependencies[feature: .debugDisappearingMessageDurations] ? 60 : nil),
(5 * 60), (5 * 60),
(1 * 60 * 60), (1 * 60 * 60),
(12 * 60 * 60), (12 * 60 * 60),
@ -280,35 +263,19 @@ extension DisappearingMessagesConfiguration {
(7 * 24 * 60 * 60), (7 * 24 * 60 * 60),
(2 * 7 * 24 * 60 * 60) (2 * 7 * 24 * 60 * 60)
] ]
.map { TimeInterval($0) } .compactMap { duration in duration.map { TimeInterval($0) } }
#if targetEnvironment(simulator)
result.insert(
TimeInterval(60),
at: 0
)
result.insert(
TimeInterval(10),
at: 0
)
#endif
return result
case .disappearAfterSend: case .disappearAfterSend:
var result = [ return [
(dependencies[feature: .debugDisappearingMessageDurations] ? 10 : nil),
(12 * 60 * 60), (12 * 60 * 60),
(24 * 60 * 60), (24 * 60 * 60),
(7 * 24 * 60 * 60), (7 * 24 * 60 * 60),
(2 * 7 * 24 * 60 * 60) (2 * 7 * 24 * 60 * 60)
] ]
.map { TimeInterval($0) } .compactMap { duration in duration.map { TimeInterval($0) } }
#if targetEnvironment(simulator)
result.insert( default: return []
TimeInterval(10), }
at: 0
)
#endif
return result
default:
return []
}
} }
} }

@ -172,33 +172,6 @@ public extension Profile {
// MARK: - Protobuf // MARK: - Protobuf
public extension Profile { public extension Profile {
static func fromProto(_ proto: SNProtoDataMessage, id: String) -> Profile? {
guard let profileProto = proto.profile, let displayName = profileProto.displayName else { return nil }
var profileKey: Data?
var profilePictureUrl: String?
let sentTimestamp: TimeInterval = TimeInterval(proto.hasTimestamp ? (Double(proto.timestamp) / 1000) : 0)
// If we have both a `profileKey` and a `profilePicture` then the key MUST be valid
if let profileKeyData: Data = proto.profileKey, profileProto.profilePicture != nil {
profileKey = profileKeyData
profilePictureUrl = profileProto.profilePicture
}
return Profile(
id: id,
name: displayName,
lastNameUpdate: sentTimestamp,
nickname: nil,
profilePictureUrl: profilePictureUrl,
profilePictureFileName: nil,
profileEncryptionKey: profileKey,
lastProfilePictureUpdate: sentTimestamp,
blocksCommunityMessageRequests: (proto.hasBlocksCommunityMessageRequests ? proto.blocksCommunityMessageRequests : nil),
lastBlocksCommunityMessageRequests: (proto.hasBlocksCommunityMessageRequests ? sentTimestamp : nil)
)
}
func toProto() -> SNProtoDataMessage? { func toProto() -> SNProtoDataMessage? {
let dataMessageProto = SNProtoDataMessage.builder() let dataMessageProto = SNProtoDataMessage.builder()
let profileProto = SNProtoLokiProfile.builder() let profileProto = SNProtoLokiProfile.builder()

@ -74,12 +74,12 @@ public extension Network {
switch self { switch self {
case .onionRequest: case .onionRequest:
return """ return """
This network layer will send requests via the original Onion Request mechanism, requests will be routed between 3 service nodes before reaching their destination. Requests will be sent via the original Onion Request mechanism, they will be routed between 3 service nodes before reaching their destination.
""" """
case .direct: case .direct:
return """ return """
This network layer will send requests directly over HTTPS Requests will be sent directly over HTTPS.
<b>Warning:</b> This network layer offers no IP protections so should only be used for debugging purposes. <b>Warning:</b> This network layer offers no IP protections so should only be used for debugging purposes.
""" """

@ -9,6 +9,10 @@ public final class Features {
} }
public extension FeatureStorage { public extension FeatureStorage {
static let debugDisappearingMessageDurations: FeatureConfig<Bool> = Dependencies.create(
identifier: "debugDisappearingMessageDurations"
)
static let updatedDisappearingMessages: FeatureConfig<Bool> = Dependencies.create( static let updatedDisappearingMessages: FeatureConfig<Bool> = Dependencies.create(
identifier: "updatedDisappearingMessages", identifier: "updatedDisappearingMessages",
automaticChangeBehaviour: Feature<Bool>.ChangeBehaviour( automaticChangeBehaviour: Feature<Bool>.ChangeBehaviour(
@ -53,10 +57,15 @@ public protocol FeatureOption: RawRepresentable, CaseIterable, Equatable where R
static var defaultOption: Self { get } static var defaultOption: Self { get }
var isValidOption: Bool { get }
var title: String { get } var title: String { get }
var subtitle: String? { get } var subtitle: String? { get }
} }
public extension FeatureOption {
var isValidOption: Bool { true }
}
// MARK: - FeatureEvent // MARK: - FeatureEvent
public protocol FeatureEvent: Equatable, Hashable { public protocol FeatureEvent: Equatable, Hashable {
@ -116,7 +125,7 @@ public struct Feature<T: FeatureOption>: FeatureType {
/// If we have an explicitly set `selectedOption` then we should use that, otherwise we should check if any of the /// If we have an explicitly set `selectedOption` then we should use that, otherwise we should check if any of the
/// `automaticChangeBehaviour` conditions have been met, and if so use the specified value /// `automaticChangeBehaviour` conditions have been met, and if so use the specified value
guard let selectedOption: T = maybeSelectedOption else { guard let selectedOption: T = maybeSelectedOption, selectedOption.isValidOption else {
func automaticChangeConditionMet(_ condition: ChangeCondition) -> Bool { func automaticChangeConditionMet(_ condition: ChangeCondition) -> Bool {
switch condition { switch condition {
case .after(let timestamp): return (dependencies.dateNow.timeIntervalSince1970 >= timestamp) case .after(let timestamp): return (dependencies.dateNow.timeIntervalSince1970 >= timestamp)

Loading…
Cancel
Save