mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Fixed a bug where the legacy group invitation was getting sent to the wrong location Fixed a bug where outgoing typing indicators would be sent to blocked contacts Fixed a bug where the call button was visible for blocked contacts Fixed a bug where read receipts could be sent to blocked contacts Fixed a bug where the conversation nav buttons wouldn't get updated correctly in some cases Fixed a bug where we could incorrectly include the current user in the contacts syncing Fixed a bug where the initial state of the Note to Self conversation wasn't getting synced Fixed a bug where the Note to Self conversation could get removed Fixed a bug with where the conversation title would be misaligned in some cases Fixed a bug where link previews and quotes with images weren't getting sent correctly Fixed a crash when removing a user from a legacy group Added some missing accessibility info Updated the code to ensure the user is kicked from the conversation if it's deletion gets synced while it's open Updated the conversation empty state copy
204 lines
8 KiB
Swift
204 lines
8 KiB
Swift
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
|
|
|
|
import Foundation
|
|
import GRDB
|
|
import SessionUtil
|
|
import SessionUtilitiesKit
|
|
|
|
/// This migration goes through the current state of the database and generates config dumps for the user config types
|
|
///
|
|
/// **Note:** This migration won't be run until the `useSharedUtilForUserConfig` feature flag is enabled
|
|
enum _014_GenerateInitialUserConfigDumps: Migration {
|
|
static let target: TargetMigrations.Identifier = .messagingKit
|
|
static let identifier: String = "GenerateInitialUserConfigDumps"
|
|
static let needsConfigSync: Bool = true
|
|
static let minExpectedRunDuration: TimeInterval = 0.1 // TODO: Need to test this
|
|
|
|
static func migrate(_ db: Database) throws {
|
|
// If we have no ed25519 key then there is no need to create cached dump data
|
|
guard let secretKey: [UInt8] = Identity.fetchUserEd25519KeyPair(db)?.secretKey else { return }
|
|
|
|
// Load the initial config state if needed
|
|
let userPublicKey: String = getUserHexEncodedPublicKey(db)
|
|
|
|
SessionUtil.loadState(db, userPublicKey: userPublicKey, ed25519SecretKey: secretKey)
|
|
|
|
// Retrieve all threads (we are going to base the config dump data on the active
|
|
// threads rather than anything else in the database)
|
|
let allThreads: [String: SessionThread] = try SessionThread
|
|
.fetchAll(db)
|
|
.reduce(into: [:]) { result, next in result[next.id] = next }
|
|
|
|
// MARK: - UserProfile Config Dump
|
|
|
|
try SessionUtil
|
|
.config(for: .userProfile, publicKey: userPublicKey)
|
|
.mutate { conf in
|
|
try SessionUtil.update(
|
|
profile: Profile.fetchOrCreateCurrentUser(db),
|
|
in: conf
|
|
)
|
|
|
|
try SessionUtil.updateNoteToSelf(
|
|
hidden: (allThreads[userPublicKey]?.shouldBeVisible == true),
|
|
priority: Int32(allThreads[userPublicKey]?.pinnedPriority ?? 0),
|
|
in: conf
|
|
)
|
|
|
|
if config_needs_dump(conf) {
|
|
try SessionUtil
|
|
.createDump(
|
|
conf: conf,
|
|
for: .userProfile,
|
|
publicKey: userPublicKey
|
|
)?
|
|
.save(db)
|
|
}
|
|
}
|
|
|
|
// MARK: - Contact Config Dump
|
|
|
|
try SessionUtil
|
|
.config(for: .contacts, publicKey: userPublicKey)
|
|
.mutate { conf in
|
|
// Exclude Note to Self, community, group and outgoing blinded message requests
|
|
let validContactIds: [String] = allThreads
|
|
.values
|
|
.filter { thread in
|
|
thread.variant == .contact &&
|
|
thread.id != userPublicKey &&
|
|
SessionId(from: thread.id)?.prefix == .standard
|
|
}
|
|
.map { $0.id }
|
|
let contactsData: [ContactInfo] = try Contact
|
|
.filter(
|
|
Contact.Columns.isBlocked == true ||
|
|
validContactIds.contains(Contact.Columns.id)
|
|
)
|
|
.including(optional: Contact.profile)
|
|
.asRequest(of: ContactInfo.self)
|
|
.fetchAll(db)
|
|
|
|
try SessionUtil.upsert(
|
|
contactData: contactsData
|
|
.map { data in
|
|
SessionUtil.SyncedContactInfo(
|
|
id: data.contact.id,
|
|
contact: data.contact,
|
|
profile: data.profile,
|
|
hidden: (allThreads[data.contact.id]?.shouldBeVisible == true),
|
|
priority: Int32(allThreads[data.contact.id]?.pinnedPriority ?? 0)
|
|
)
|
|
},
|
|
in: conf
|
|
)
|
|
|
|
if config_needs_dump(conf) {
|
|
try SessionUtil
|
|
.createDump(
|
|
conf: conf,
|
|
for: .contacts,
|
|
publicKey: userPublicKey
|
|
)?
|
|
.save(db)
|
|
}
|
|
}
|
|
|
|
// MARK: - ConvoInfoVolatile Config Dump
|
|
|
|
try SessionUtil
|
|
.config(for: .convoInfoVolatile, publicKey: userPublicKey)
|
|
.mutate { conf in
|
|
let volatileThreadInfo: [SessionUtil.VolatileThreadInfo] = SessionUtil.VolatileThreadInfo
|
|
.fetchAll(db, ids: Array(allThreads.keys))
|
|
|
|
try SessionUtil.upsert(
|
|
convoInfoVolatileChanges: volatileThreadInfo,
|
|
in: conf
|
|
)
|
|
|
|
if config_needs_dump(conf) {
|
|
try SessionUtil
|
|
.createDump(
|
|
conf: conf,
|
|
for: .convoInfoVolatile,
|
|
publicKey: userPublicKey
|
|
)?
|
|
.save(db)
|
|
}
|
|
}
|
|
|
|
// MARK: - UserGroups Config Dump
|
|
|
|
try SessionUtil
|
|
.config(for: .userGroups, publicKey: userPublicKey)
|
|
.mutate { conf in
|
|
let legacyGroupData: [SessionUtil.LegacyGroupInfo] = try SessionUtil.LegacyGroupInfo.fetchAll(db)
|
|
let communityData: [SessionUtil.OpenGroupUrlInfo] = try SessionUtil.OpenGroupUrlInfo
|
|
.fetchAll(db, ids: Array(allThreads.keys))
|
|
|
|
try SessionUtil.upsert(
|
|
legacyGroups: legacyGroupData,
|
|
in: conf
|
|
)
|
|
try SessionUtil.upsert(
|
|
communities: communityData
|
|
.map { urlInfo in
|
|
SessionUtil.CommunityInfo(
|
|
urlInfo: urlInfo,
|
|
priority: Int32(allThreads[urlInfo.threadId]?.pinnedPriority ?? 0)
|
|
)
|
|
},
|
|
in: conf
|
|
)
|
|
|
|
if config_needs_dump(conf) {
|
|
try SessionUtil
|
|
.createDump(
|
|
conf: conf,
|
|
for: .userGroups,
|
|
publicKey: userPublicKey
|
|
)?
|
|
.save(db)
|
|
}
|
|
}
|
|
|
|
// MARK: - Threads
|
|
|
|
try SessionUtil.updatingThreads(db, Array(allThreads.values))
|
|
|
|
// MARK: - Syncing
|
|
|
|
// Enqueue a config sync job to ensure the generated configs get synced
|
|
db.afterNextTransactionNestedOnce(dedupeId: SessionUtil.syncDedupeId(userPublicKey)) { db in
|
|
ConfigurationSyncJob.enqueue(db, publicKey: userPublicKey)
|
|
}
|
|
|
|
Storage.update(progress: 1, for: self, in: target) // In case this is the last migration
|
|
}
|
|
|
|
struct ContactInfo: FetchableRecord, Decodable, ColumnExpressible {
|
|
typealias Columns = CodingKeys
|
|
enum CodingKeys: String, CodingKey, ColumnExpression, CaseIterable {
|
|
case contact
|
|
case profile
|
|
}
|
|
|
|
let contact: Contact
|
|
let profile: Profile?
|
|
}
|
|
|
|
struct GroupInfo: FetchableRecord, Decodable, ColumnExpressible {
|
|
typealias Columns = CodingKeys
|
|
enum CodingKeys: String, CodingKey, ColumnExpression, CaseIterable {
|
|
case closedGroup
|
|
case disappearingMessagesConfiguration
|
|
case groupMembers
|
|
}
|
|
|
|
let closedGroup: ClosedGroup
|
|
let disappearingMessagesConfiguration: DisappearingMessagesConfiguration?
|
|
let groupMembers: [GroupMember]
|
|
}
|
|
}
|