mirror of
https://github.com/lux-tel/session-ios.git
synced 2026-10-30 20:38:32 +00:00
• Added the ability to set the custom file server via env variables for testing • Disable image editing on the share extension if there isn't enough RAM available to edit the image (ie. prevent crashes due to insufficient memory) • Tweaked image loading to avoid pre-decoding large static images to reduce memory spikes (was crashing the share extension on some devices) • Updated link previews to load images using the ImageDataManager • Fixed an issue where the file id on the message info screen would include extra info • Fixed an issue where sharing a file wouldn't show the preview correctly • Fixed an issue where the re-upload job could run when a display picture file was missing • Fixed an issue where deleting messages across all devices in Note to Self was using the wrong deletion function • Fixed an issue where an invalid database value could result in no attachments being able to be loaded in a conversation • Fixed an issue where images with orientation metadata would be incorrectly rotated and letterboxed
106 lines
4.7 KiB
Swift
106 lines
4.7 KiB
Swift
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
|
|
|
import Foundation
|
|
import GRDB
|
|
import SessionNetworkingKit
|
|
import SessionUtilitiesKit
|
|
|
|
extension MessageReceiver {
|
|
public static func handleUnsendRequest(
|
|
_ db: ObservingDatabase,
|
|
threadId: String,
|
|
threadVariant: SessionThread.Variant,
|
|
message: UnsendRequest,
|
|
using dependencies: Dependencies
|
|
) throws {
|
|
let userSessionId: SessionId = dependencies[cache: .general].sessionId
|
|
let senderIsLegacyGroupAdmin: Bool = {
|
|
switch (message.sender, threadVariant) {
|
|
case (.some(let sender), .legacyGroup):
|
|
return GroupMember
|
|
.filter(GroupMember.Columns.groupId == threadId)
|
|
.filter(GroupMember.Columns.profileId == sender)
|
|
.filter(GroupMember.Columns.role == GroupMember.Role.admin)
|
|
.isNotEmpty(db)
|
|
|
|
default: return false
|
|
}
|
|
}()
|
|
|
|
guard
|
|
senderIsLegacyGroupAdmin ||
|
|
message.sender == message.author ||
|
|
userSessionId.hexString == message.sender
|
|
else { return }
|
|
guard
|
|
let author: String = message.author,
|
|
let timestampMs: UInt64 = message.timestamp,
|
|
let interactionInfo: Interaction.ThreadInfo = try Interaction
|
|
.select(.id, .threadId)
|
|
.filter(Interaction.Columns.timestampMs == Int64(timestampMs))
|
|
.filter(Interaction.Columns.authorId == author)
|
|
.asRequest(of: Interaction.ThreadInfo.self)
|
|
.fetchOne(db)
|
|
else { return }
|
|
|
|
/// Retrieve the hashes which should be deleted first (these will be removed from the local
|
|
/// device in the `markAsDeleted` function) then call `markAsDeleted` to remove
|
|
/// message content
|
|
let hashes: Set<String> = try Interaction.serverHashesForDeletion(
|
|
db,
|
|
interactionIds: [interactionInfo.id]
|
|
)
|
|
try Interaction.markAsDeleted(
|
|
db,
|
|
threadId: interactionInfo.threadId, /// Can't use `threadId` as that may be the current users
|
|
threadVariant: threadVariant,
|
|
interactionIds: [interactionInfo.id],
|
|
options: [.local, .network],
|
|
using: dependencies
|
|
)
|
|
|
|
/// If it's the `Note to Self` conversation then we want to just delete the interaction
|
|
if userSessionId.hexString == interactionInfo.threadId {
|
|
try Interaction.deleteWhere(db, .filter(Interaction.Columns.id == interactionInfo.id))
|
|
}
|
|
|
|
/// Can't delete from the legacy group swarm so only bother for contact conversations
|
|
switch threadVariant {
|
|
case .legacyGroup, .group, .community: break
|
|
case .contact:
|
|
dependencies[singleton: .storage]
|
|
.readPublisher { db in
|
|
try Network.SnodeAPI.preparedDeleteMessages(
|
|
serverHashes: Array(hashes),
|
|
requireSuccessfulDeletion: false,
|
|
authMethod: try Authentication.with(
|
|
db,
|
|
swarmPublicKey: dependencies[cache: .general].sessionId.hexString,
|
|
using: dependencies
|
|
),
|
|
using: dependencies
|
|
)
|
|
}
|
|
.flatMap { $0.send(using: dependencies) }
|
|
.subscribe(on: DispatchQueue.global(qos: .background), using: dependencies)
|
|
.sinkUntilComplete(
|
|
receiveCompletion: { result in
|
|
switch result {
|
|
case .failure: break
|
|
case .finished:
|
|
/// Since the server deletion was successful we should also flag the `SnodeReceivedMessageInfo`
|
|
/// entries for the hashes as invalud (otherwise we might try to poll for a hash which no longer exists,
|
|
/// resulting in fetching the last 14 days of messages)
|
|
dependencies[singleton: .storage].writeAsync { db in
|
|
try SnodeReceivedMessageInfo.handlePotentialDeletedOrInvalidHash(
|
|
db,
|
|
potentiallyInvalidHashes: Array(hashes)
|
|
)
|
|
}
|
|
}
|
|
}
|
|
)
|
|
}
|
|
}
|
|
}
|