Fixed a couple of minor outgoing quote bugs

Added a nicer mechanism for using table aliases
Fixed a bug where the quote preview view close button could overlap the content
Fixed a bug where an outgoing quote wouldn't show it's thumbnail in some cases
Fixed a bug where quoting a link preview wouldn't show the link preview attachment
This commit is contained in:
Morgan Pretty 2023-08-17 11:28:03 +10:00
parent 968f50f2fc
commit 42853a08c9
9 changed files with 65 additions and 24 deletions

View File

@ -635,6 +635,7 @@
FD52090928B59411006098F6 /* ScreenLockUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD52090828B59411006098F6 /* ScreenLockUI.swift */; };
FD52090B28B59BB4006098F6 /* ScreenLockViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD52090A28B59BB4006098F6 /* ScreenLockViewController.swift */; };
FD559DF52A7368CB00C7C62A /* DispatchQueue+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD559DF42A7368CB00C7C62A /* DispatchQueue+Utilities.swift */; };
FD5931A72A8DA5DA0040147D /* SQLInterpolation+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD5931A62A8DA5DA0040147D /* SQLInterpolation+Utilities.swift */; };
FD5C72F7284F0E560029977D /* MessageReceiver+ReadReceipts.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD5C72F6284F0E560029977D /* MessageReceiver+ReadReceipts.swift */; };
FD5C72F9284F0E880029977D /* MessageReceiver+TypingIndicators.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD5C72F8284F0E880029977D /* MessageReceiver+TypingIndicators.swift */; };
FD5C72FB284F0EA10029977D /* MessageReceiver+DataExtractionNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD5C72FA284F0EA10029977D /* MessageReceiver+DataExtractionNotification.swift */; };
@ -1755,6 +1756,7 @@
FD52090828B59411006098F6 /* ScreenLockUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenLockUI.swift; sourceTree = "<group>"; };
FD52090A28B59BB4006098F6 /* ScreenLockViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenLockViewController.swift; sourceTree = "<group>"; };
FD559DF42A7368CB00C7C62A /* DispatchQueue+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DispatchQueue+Utilities.swift"; sourceTree = "<group>"; };
FD5931A62A8DA5DA0040147D /* SQLInterpolation+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SQLInterpolation+Utilities.swift"; sourceTree = "<group>"; };
FD5C72F6284F0E560029977D /* MessageReceiver+ReadReceipts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MessageReceiver+ReadReceipts.swift"; sourceTree = "<group>"; };
FD5C72F8284F0E880029977D /* MessageReceiver+TypingIndicators.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MessageReceiver+TypingIndicators.swift"; sourceTree = "<group>"; };
FD5C72FA284F0EA10029977D /* MessageReceiver+DataExtractionNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MessageReceiver+DataExtractionNotification.swift"; sourceTree = "<group>"; };
@ -3693,6 +3695,7 @@
FDDF074329C3E3D000E5E8B5 /* FetchRequest+Utilities.swift */,
FDF2220E281B55E6000A4995 /* QueryInterfaceRequest+Utilities.swift */,
FD1A94FA2900D1C2000D73D3 /* PersistableRecord+Utilities.swift */,
FD5931A62A8DA5DA0040147D /* SQLInterpolation+Utilities.swift */,
);
path = Utilities;
sourceTree = "<group>";
@ -5666,6 +5669,7 @@
C32C5DD2256DD9E5003C73A2 /* LRUCache.swift in Sources */,
FD71160228C8255900B47552 /* UIControl+Combine.swift in Sources */,
FDFBB74B2A1EFF4900CA7350 /* Bencode.swift in Sources */,
FD5931A72A8DA5DA0040147D /* SQLInterpolation+Utilities.swift in Sources */,
FD9004152818B46300ABAAF6 /* JobRunner.swift in Sources */,
FDF8487929405906007DCAE5 /* HTTPQueryParam.swift in Sources */,
FD17D7CA27F546D900122BE0 /* _001_InitialSetupMigration.swift in Sources */,

View File

@ -156,7 +156,7 @@ final class QuoteView: UIView {
if attachment.isVisualMedia {
attachment.thumbnail(
size: .small,
success: { image, _ in
success: { [imageView] image, _ in
guard Thread.isMainThread else {
DispatchQueue.main.async {
imageView.image = image
@ -234,8 +234,6 @@ final class QuoteView: UIView {
}
// Label stack view
let bodyLabelSize = bodyLabel.systemLayoutSizeFitting(availableSpace)
let isCurrentUser: Bool = [
currentUserPublicKey,
currentUserBlinded15PublicKey,
@ -288,9 +286,8 @@ final class QuoteView: UIView {
cancelButton.set(.height, to: cancelButtonSize)
cancelButton.addTarget(self, action: #selector(cancel), for: UIControl.Event.touchUpInside)
addSubview(cancelButton)
mainStackView.addArrangedSubview(cancelButton)
cancelButton.center(.vertical, in: self)
cancelButton.pin(.right, to: .right, of: self)
}
}

View File

@ -522,7 +522,7 @@ extension Attachment {
\(interaction[.id]) = \(interactionAttachment[.interactionId]) OR
(
\(interaction[.linkPreviewUrl]) = \(linkPreview[.url]) AND
\(Interaction.linkPreviewFilterLiteral)
\(Interaction.linkPreviewFilterLiteral())
)
)
@ -568,7 +568,7 @@ extension Attachment {
\(interaction[.id]) = \(interactionAttachment[.interactionId]) OR
(
\(interaction[.linkPreviewUrl]) = \(linkPreview[.url]) AND
\(Interaction.linkPreviewFilterLiteral)
\(Interaction.linkPreviewFilterLiteral())
)
)

View File

@ -29,13 +29,14 @@ public struct Interaction: Codable, Identifiable, Equatable, FetchableRecord, Mu
/// Whenever using this `linkPreview` association make sure to filter the result using
/// `.filter(literal: Interaction.linkPreviewFilterLiteral)` to ensure the correct LinkPreview is returned
public static let linkPreview = hasOne(LinkPreview.self, using: LinkPreview.interactionForeignKey)
public static var linkPreviewFilterLiteral: SQL = {
let interaction: TypedTableAlias<Interaction> = TypedTableAlias()
let linkPreview: TypedTableAlias<LinkPreview> = TypedTableAlias()
public static func linkPreviewFilterLiteral(
interaction: TypedTableAlias<Interaction> = TypedTableAlias(),
linkPreview: TypedTableAlias<LinkPreview> = TypedTableAlias()
) -> SQL {
let halfResolution: Double = LinkPreview.timstampResolution
return "(\(interaction[.timestampMs]) BETWEEN (\(linkPreview[.timestamp]) - \(halfResolution)) * 1000 AND (\(linkPreview[.timestamp]) + \(halfResolution)) * 1000)"
}()
}
public static let recipientStates = hasMany(RecipientState.self, using: RecipientState.interactionForeignKey)
public typealias Columns = CodingKeys

View File

@ -143,7 +143,7 @@ public enum GarbageCollectionJob: JobExecutor {
FROM \(LinkPreview.self)
LEFT JOIN \(Interaction.self) ON (
\(interaction[.linkPreviewUrl]) = \(linkPreview[.url]) AND
\(Interaction.linkPreviewFilterLiteral)
\(Interaction.linkPreviewFilterLiteral())
)
WHERE \(interaction[.id]) IS NULL
)

View File

@ -777,10 +777,11 @@ public extension MessageViewModel {
let disappearingMessagesConfig: TypedTableAlias<DisappearingMessagesConfiguration> = TypedTableAlias()
let profile: TypedTableAlias<Profile> = TypedTableAlias()
let quote: TypedTableAlias<Quote> = TypedTableAlias()
let quoteInteraction: TypedTableAlias<Interaction> = TypedTableAlias(name: "quoteInteraction")
let quoteLinkPreview: TypedTableAlias<LinkPreview> = TypedTableAlias(name: "quoteLinkPreview")
let linkPreview: TypedTableAlias<LinkPreview> = TypedTableAlias()
let threadProfile: SQL = SQL(stringLiteral: "threadProfile")
let quoteInteraction: SQL = SQL(stringLiteral: "quoteInteraction")
let quoteInteractionAttachment: SQL = SQL(stringLiteral: "quoteInteractionAttachment")
let readReceipt: SQL = SQL(stringLiteral: "readReceipt")
let idColumn: SQL = SQL(stringLiteral: Interaction.Columns.id.name)
@ -845,7 +846,7 @@ public extension MessageViewModel {
\(quote[.interactionId]),
\(quote[.authorId]),
\(quote[.timestampMs]),
\(quoteInteraction).\(interactionBodyColumn) AS \(quoteBodyColumn),
\(quoteInteraction[.body]),
\(quoteInteractionAttachment).\(interactionAttachmentAttachmentIdColumn) AS \(quoteAttachmentIdColumn),
\(ViewModel.quoteAttachmentKey).*,
\(ViewModel.linkPreviewKey).*,
@ -873,12 +874,12 @@ public extension MessageViewModel {
LEFT JOIN \(OpenGroup.self) ON \(openGroup[.threadId]) = \(interaction[.threadId])
LEFT JOIN \(Profile.self) ON \(profile[.id]) = \(interaction[.authorId])
LEFT JOIN \(Quote.self) ON \(quote[.interactionId]) = \(interaction[.id])
LEFT JOIN \(Interaction.self) AS \(quoteInteraction) ON (
\(quoteInteraction).\(timestampMsColumn) = \(quote[.timestampMs]) AND (
\(quoteInteraction).\(authorIdColumn) = \(quote[.authorId]) OR (
LEFT JOIN \(quoteInteraction) ON (
\(quoteInteraction[.timestampMs]) = \(quote[.timestampMs]) AND (
\(quoteInteraction[.authorId]) = \(quote[.authorId]) OR (
-- A users outgoing message is stored in some cases using their standard id
-- but the quote will use their blinded id so handle that case
\(quoteInteraction).\(authorIdColumn) = \(userPublicKey) AND
\(quoteInteraction[.authorId]) = \(userPublicKey) AND
(
\(quote[.authorId]) = \(blinded15PublicKey ?? "''") OR
\(quote[.authorId]) = \(blinded25PublicKey ?? "''")
@ -887,14 +888,25 @@ public extension MessageViewModel {
)
)
LEFT JOIN \(InteractionAttachment.self) AS \(quoteInteractionAttachment) ON (
\(quoteInteractionAttachment).\(interactionAttachmentInteractionIdColumn) = \(quoteInteraction).\(idColumn) AND
\(quoteInteractionAttachment).\(interactionAttachmentInteractionIdColumn) = \(quoteInteraction[.id]) AND
\(quoteInteractionAttachment).\(interactionAttachmentAlbumIndexColumn) = 0
)
LEFT JOIN \(Attachment.self) AS \(ViewModel.quoteAttachmentKey) ON \(ViewModel.quoteAttachmentKey).\(attachmentIdColumn) = \(quoteInteractionAttachment).\(interactionAttachmentAttachmentIdColumn)
LEFT JOIN \(quoteLinkPreview) ON (
\(quoteLinkPreview[.url]) = \(quoteInteraction[.linkPreviewUrl]) AND
\(Interaction.linkPreviewFilterLiteral(
interaction: quoteInteraction,
linkPreview: quoteLinkPreview
))
)
LEFT JOIN \(Attachment.self) AS \(ViewModel.quoteAttachmentKey) ON (
\(ViewModel.quoteAttachmentKey).\(attachmentIdColumn) = \(quoteInteractionAttachment).\(interactionAttachmentAttachmentIdColumn) OR
\(ViewModel.quoteAttachmentKey).\(attachmentIdColumn) = \(quoteLinkPreview[.attachmentId]) OR
\(ViewModel.quoteAttachmentKey).\(attachmentIdColumn) = \(quote[.attachmentId])
)
LEFT JOIN \(LinkPreview.self) ON (
\(linkPreview[.url]) = \(interaction[.linkPreviewUrl]) AND
\(Interaction.linkPreviewFilterLiteral)
\(Interaction.linkPreviewFilterLiteral())
)
LEFT JOIN \(Attachment.self) AS \(ViewModel.linkPreviewAttachmentKey) ON \(ViewModel.linkPreviewAttachmentKey).\(attachmentIdColumn) = \(linkPreview[.attachmentId])
LEFT JOIN \(RecipientState.self) ON (

View File

@ -712,7 +712,7 @@ public extension SessionThreadViewModel {
)
LEFT JOIN \(LinkPreview.self) ON (
\(linkPreview[.url]) = \(interaction[.linkPreviewUrl]) AND
\(Interaction.linkPreviewFilterLiteral) AND
\(Interaction.linkPreviewFilterLiteral()) AND
\(SQL("\(linkPreview[.variant]) = \(LinkPreview.Variant.openGroupInvitation)"))
)
LEFT JOIN \(InteractionAttachment.self) AS \(firstInteractionAttachmentLiteral) ON (

View File

@ -4,9 +4,15 @@ import Foundation
import GRDB
public class TypedTableAlias<T> where T: TableRecord, T: ColumnExpressible {
public let alias: TableAlias = TableAlias(name: T.databaseTableName)
internal let name: String
internal let tableName: String
public let alias: TableAlias
public init() {}
public init(name: String = T.databaseTableName) {
self.name = name
self.tableName = T.databaseTableName
self.alias = TableAlias(name: name)
}
public subscript(_ column: T.Columns) -> SQLExpression {
return alias[column.name]

View File

@ -0,0 +1,21 @@
// Copyright © 2023 Rangeproof Pty Ltd. All rights reserved.
import Foundation
import GRDB
public extension SQLInterpolation {
/// Appends the table name of the record type.
///
/// // SELECT * FROM player
/// let player: TypedTableAlias<T> = TypedTableAlias()
/// let request: SQLRequest<Player> = "SELECT * FROM \(player)"
@_disfavoredOverload
mutating func appendInterpolation<T>(_ typedTableAlias: TypedTableAlias<T>) {
let name: String = typedTableAlias.name
let tableName: String = typedTableAlias.tableName
guard name != tableName else { return appendLiteral(tableName.quotedDatabaseIdentifier) }
appendLiteral("\(tableName.quotedDatabaseIdentifier) AS \(name.quotedDatabaseIdentifier)")
}
}