Signal-iOS/SignalUI/ViewModels/ThreadUtil+SignalUI.swift
Evan Hahn 370ff654e7
Change license to AGPL
Change license to AGPL

This commit:

- Updates the `LICENSE` file

- Start every file with something like:

      // Copyright YEAR_FIRST_PUBLISHED Signal Messenger, LLC
      // SPDX-License-Identifier: AGPL-3.0-only

---

First, I removed existing license headers with this Ruby 3.1.2 script:

    require 'set'

    EXTENSIONS_TO_CHECK = Set['.h', '.hpp', '.cpp', '.m', '.mm', '.pch', '.swift']

    same = 0
    different = 0

    all_files = `git ls-files`.lines.map { |line| line.strip }
    all_files.each do |relative_path|
      if relative_path == 'Pods'
        next
      end

      unless EXTENSIONS_TO_CHECK.include? File.extname(relative_path)
        next
      end

      path = File.expand_path(relative_path)

      contents = File.read(path)
      new_contents = contents.sub(/\/\/\n\/\/  Copyright .*\n\/\/\n\n/, '')

      if contents == new_contents
        same += 1
      else
        different += 1
      end

      File.write(path, new_contents)
    end

    puts "updated #{different} file(s), left #{same} untouched"

I'm sure this script could be improved, but it worked well enough.

Then, I created `Scripts/lint/lint-license-headers` and ran it to auto-
fix a lot of files. This changed the mode of some files, but I think
that's actually desirable. For example,
`SignalServiceKit/src/Util/AppContext.m` previously had a mode of
`0755/-rwxr-xr-x`, and it's now `0644/-rw-r--r--`.

Then I fixed some stragglers and updated the precommit script.

See [a similar change in the Desktop app][0].

[0]: 8bfaf598af
2022-10-13 08:25:37 -05:00

160 lines
6.9 KiB
Swift

//
// Copyright 2021 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
import Foundation
import SignalMessaging
@objc
public extension ThreadUtil {
// MARK: - Durable Message Enqueue
@discardableResult
class func enqueueMessage(body messageBody: MessageBody?,
mediaAttachments: [SignalAttachment] = [],
thread: TSThread,
quotedReplyModel: OWSQuotedReplyModel? = nil,
linkPreviewDraft: OWSLinkPreviewDraft? = nil,
persistenceCompletionHandler persistenceCompletion: PersistenceCompletion? = nil,
transaction readTransaction: SDSAnyReadTransaction) -> TSOutgoingMessage {
AssertIsOnMainThread()
let outgoingMessagePreparer = OutgoingMessagePreparer(messageBody: messageBody,
mediaAttachments: mediaAttachments,
thread: thread,
quotedReplyModel: quotedReplyModel,
transaction: readTransaction)
let message: TSOutgoingMessage = outgoingMessagePreparer.unpreparedMessage
BenchManager.startEvent(
title: "Send Message Milestone: Sending (\(message.timestamp))",
eventId: "sendMessageSending-\(message.timestamp)",
logInProduction: true
)
BenchManager.startEvent(
title: "Send Message Milestone: Sent (\(message.timestamp))",
eventId: "sendMessageSentSent-\(message.timestamp)",
logInProduction: true
)
BenchManager.startEvent(
title: "Send Message Milestone: Marked as Sent (\(message.timestamp))",
eventId: "sendMessageMarkedAsSent-\(message.timestamp)",
logInProduction: true
)
BenchManager.benchAsync(title: "Send Message Milestone: Enqueue \(message.timestamp)") { benchmarkCompletion in
Self.enqueueSendAsyncWrite { writeTransaction in
outgoingMessagePreparer.insertMessage(linkPreviewDraft: linkPreviewDraft,
transaction: writeTransaction)
Self.messageSenderJobQueue.add(message: outgoingMessagePreparer,
transaction: writeTransaction)
writeTransaction.addSyncCompletion {
benchmarkCompletion()
}
if let persistenceCompletion = persistenceCompletion {
writeTransaction.addAsyncCompletionOnMain {
persistenceCompletion()
}
}
}
}
if message.hasRenderableContent() {
thread.donateSendMessageIntent(for: message, transaction: readTransaction)
}
return message
}
class func createUnsentMessage(body messageBody: MessageBody?,
mediaAttachments: [SignalAttachment],
thread: TSThread,
quotedReplyModel: OWSQuotedReplyModel? = nil,
linkPreviewDraft: OWSLinkPreviewDraft? = nil,
transaction: SDSAnyWriteTransaction) throws -> TSOutgoingMessage {
let preparer = OutgoingMessagePreparer(messageBody: messageBody,
mediaAttachments: mediaAttachments,
thread: thread,
quotedReplyModel: quotedReplyModel,
transaction: transaction)
preparer.insertMessage(linkPreviewDraft: linkPreviewDraft, transaction: transaction)
return try preparer.prepareMessage(transaction: transaction)
}
}
// MARK: -
extension OutgoingMessagePreparer {
@objc
public convenience init(messageBody: MessageBody?,
mediaAttachments: [SignalAttachment] = [],
thread: TSThread,
quotedReplyModel: OWSQuotedReplyModel? = nil,
transaction: SDSAnyReadTransaction) {
var attachments = mediaAttachments
let truncatedText: String?
let bodyRanges: MessageBodyRanges?
if let messageBody = messageBody, !messageBody.text.isEmpty {
if messageBody.text.lengthOfBytes(using: .utf8) >= kOversizeTextMessageSizeThreshold {
truncatedText = messageBody.text.truncated(toByteCount: kOversizeTextMessageSizeThreshold)
bodyRanges = messageBody.ranges
if let dataSource = DataSourceValue.dataSource(withOversizeText: messageBody.text) {
let attachment = SignalAttachment.attachment(dataSource: dataSource,
dataUTI: kOversizeTextAttachmentUTI)
attachments.append(attachment)
} else {
owsFailDebug("dataSource was unexpectedly nil")
}
} else {
truncatedText = messageBody.text
bodyRanges = messageBody.ranges
}
} else {
truncatedText = nil
bodyRanges = nil
}
let expiresInSeconds = thread.disappearingMessagesDuration(with: transaction)
assert(attachments.allSatisfy { !$0.hasError && !$0.mimeType.isEmpty })
let isVoiceMessage = attachments.count == 1 && attachments.last?.isVoiceMessage == true
var isViewOnceMessage = false
for attachment in mediaAttachments {
if attachment.isViewOnceAttachment {
assert(mediaAttachments.count == 1)
isViewOnceMessage = true
break
}
if attachment.isBorderless {
assert(mediaAttachments.count == 1)
break
}
}
// Discard quoted reply for view-once messages.
let quotedMessage: TSQuotedMessage? = (isViewOnceMessage
? nil
: quotedReplyModel?.buildQuotedMessageForSending())
let message = TSOutgoingMessageBuilder(
thread: thread,
messageBody: truncatedText,
bodyRanges: bodyRanges,
expiresInSeconds: expiresInSeconds,
isVoiceMessage: isVoiceMessage,
quotedMessage: quotedMessage,
isViewOnceMessage: isViewOnceMessage
).build(transaction: transaction)
let attachmentInfos = attachments.map { $0.buildOutgoingAttachmentInfo(message: message) }
self.init(message, unsavedAttachmentInfos: attachmentInfos)
}
}