Skip to content

Commit

Permalink
Merge pull request #1021 from oxen-io/dev
Browse files Browse the repository at this point in the history
Release 2.7.4
  • Loading branch information
mpretty-cyro authored Sep 13, 2024
2 parents 78a33f1 + 7ff2368 commit 83ec937
Show file tree
Hide file tree
Showing 72 changed files with 2,202 additions and 1,432 deletions.
7 changes: 4 additions & 3 deletions Scripts/drone-static-upload.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,15 @@ else
fi

if [ -n "$DRONE_TAG" ]; then
# For a tag build use something like `session-ios-v1.2.3`
# For a tag build use something like `session-ios-v1.2.3`, stored directly in the repo directory
base="session-ios-$DRONE_TAG-$suffix"
upload_to="oxen.rocks/${DRONE_REPO// /_}"
else
# Otherwise build a length name from the datetime and commit hash, such as:
# session-ios-20200522T212342Z-04d7dcc54
# stored in a branch directory for the repo
base="session-ios-$(date --date=@$DRONE_BUILD_CREATED +%Y%m%dT%H%M%SZ)-${DRONE_COMMIT:0:9}-$suffix"
upload_to="oxen.rocks/${DRONE_REPO// /_}/${DRONE_BRANCH// /_}"
fi

# Copy over the build products
Expand All @@ -51,8 +54,6 @@ cp -av $target_path "$base"
archive="$base.tar.xz"
tar cJvf "$archive" "$base"

upload_to="oxen.rocks/${DRONE_REPO// /_}/${DRONE_BRANCH// /_}"

# sftp doesn't have any equivalent to mkdir -p, so we have to split the above up into a chain of
# -mkdir a/, -mkdir a/b/, -mkdir a/b/c/, ... commands. The leading `-` allows the command to fail
# without error.
Expand Down
85 changes: 59 additions & 26 deletions Session.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"originHash" : "b77f342bc30b5d1971118f9ad70bf3af24442c4edb9a716222ad6bc0fb9b3f8e",
"originHash" : "77d5fda90891573a263c0fefeb989f3f1bb56e612a09be32106558b6d5fb4564",
"pins" : [
{
"identity" : "cocoalumberjack",
Expand Down Expand Up @@ -85,10 +85,10 @@
{
"identity" : "session-grdb-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/oxen-io/session-grdb-swift",
"location" : "https://github.com/oxen-io/session-grdb-swift.git",
"state" : {
"revision" : "52043c998154b39ecd8e069ba22244bf36464c61",
"version" : "106.27.1"
"revision" : "426149dd868219517df20eebeca27ff385fee34a",
"version" : "106.29.2"
}
},
{
Expand Down
2 changes: 1 addition & 1 deletion Session/Calls/Call Management/SessionCallManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ public final class SessionCallManager: NSObject, CallManagerProtocol {
// Stop all jobs except for message sending and when completed suspend the database
JobRunner.stopAndClearPendingJobs(exceptForVariant: .messageSend, using: dependencies) { _ in
LibSession.suspendNetworkAccess()
Storage.suspendDatabaseAccess(using: dependencies)
dependencies.storage.suspendDatabaseAccess()
Log.flush()
}
}
Expand Down
91 changes: 53 additions & 38 deletions Session/Conversations/ConversationVC+Interaction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ extension ConversationVC:
threadVariant: SessionThread.Variant,
messageText: String?
) {
sendMessage(text: (messageText ?? ""), attachments: attachments, using: viewModel.dependencies)
sendMessage(text: (messageText ?? ""), attachments: attachments)
resetMentions()

dismiss(animated: true) { [weak self] in
Expand Down Expand Up @@ -222,7 +222,7 @@ extension ConversationVC:
threadVariant: SessionThread.Variant,
messageText: String?
) {
sendMessage(text: (messageText ?? ""), attachments: attachments, using: viewModel.dependencies)
sendMessage(text: (messageText ?? ""), attachments: attachments)
resetMentions()

dismiss(animated: true) { [weak self] in
Expand Down Expand Up @@ -298,7 +298,7 @@ extension ConversationVC:
let threadId: String = self.viewModel.threadData.threadId
let threadVariant: SessionThread.Variant = self.viewModel.threadData.threadVariant

Permissions.requestLibraryPermissionIfNeeded { [weak self, dependencies = viewModel.dependencies] in
Permissions.requestLibraryPermissionIfNeeded(isSavingMedia: false) { [weak self, dependencies = viewModel.dependencies] in
DispatchQueue.main.async {
let sendMediaNavController = SendMediaNavigationController.showingMediaLibraryFirst(
threadId: threadId,
Expand Down Expand Up @@ -467,8 +467,7 @@ extension ConversationVC:
attachments: [SignalAttachment] = [],
linkPreviewDraft: LinkPreviewDraft? = nil,
quoteModel: QuotedReplyModel? = nil,
hasPermissionToSendSeed: Bool = false,
using dependencies: Dependencies = Dependencies()
hasPermissionToSendSeed: Bool = false
) {
guard !showBlockedModalIfNeeded() else { return }

Expand Down Expand Up @@ -539,17 +538,14 @@ extension ConversationVC:
quoteModel: quoteModel
)

sendMessage(optimisticData: optimisticData, using: dependencies)
sendMessage(optimisticData: optimisticData)
}

private func sendMessage(
optimisticData: ConversationViewModel.OptimisticMessageData,
using dependencies: Dependencies
) {
private func sendMessage(optimisticData: ConversationViewModel.OptimisticMessageData) {
let threadId: String = self.viewModel.threadData.threadId
let threadVariant: SessionThread.Variant = self.viewModel.threadData.threadVariant

DispatchQueue.global(qos:.userInitiated).async(using: dependencies) {
DispatchQueue.global(qos:.userInitiated).async(using: viewModel.dependencies) { [dependencies = viewModel.dependencies] in
// Generate the quote thumbnail if needed (want this to happen outside of the DBWrite thread as
// this can take up to 0.5s
let quoteThumbnailAttachment: Attachment? = optimisticData.quoteModel?.attachment?.cloneAsQuoteThumbnail()
Expand Down Expand Up @@ -902,8 +898,22 @@ extension ConversationVC:

// For call info messages show the "call missed" modal
guard cellViewModel.variant != .infoCall else {
let callMissedTipsModal: CallMissedTipsModal = CallMissedTipsModal(caller: cellViewModel.authorName)
present(callMissedTipsModal, animated: true, completion: nil)
// If the failure was due to the mic permission being denied then we want to show the permission modal,
// otherwise we want to show the call missed tips modal
guard
let infoMessageData: Data = (cellViewModel.rawBody ?? "").data(using: .utf8),
let messageInfo: CallMessage.MessageInfo = try? JSONDecoder().decode(
CallMessage.MessageInfo.self,
from: infoMessageData
),
messageInfo.state == .permissionDeniedMicrophone
else {
let callMissedTipsModal: CallMissedTipsModal = CallMissedTipsModal(caller: cellViewModel.authorName)
present(callMissedTipsModal, animated: true, completion: nil)
return
}

Permissions.requestMicrophonePermissionIfNeeded(presentingViewController: self)
return
}

Expand Down Expand Up @@ -1891,7 +1901,7 @@ extension ConversationVC:
}

// Try to send the optimistic message again
sendMessage(optimisticData: optimisticMessageData, using: dependencies)
sendMessage(optimisticData: optimisticMessageData)
return
}

Expand Down Expand Up @@ -2326,30 +2336,35 @@ extension ConversationVC:

guard !mediaAttachments.isEmpty else { return }

mediaAttachments.forEach { attachment, originalFilePath in
PHPhotoLibrary.shared().performChanges(
{
if attachment.isImage || attachment.isAnimated {
PHAssetChangeRequest.creationRequestForAssetFromImage(
atFileURL: URL(fileURLWithPath: originalFilePath)
)
}
else if attachment.isVideo {
PHAssetChangeRequest.creationRequestForAssetFromVideo(
atFileURL: URL(fileURLWithPath: originalFilePath)
)
}
},
completionHandler: { _, _ in }
)
}

// Send a 'media saved' notification if needed
guard self.viewModel.threadData.threadVariant == .contact, cellViewModel.variant == .standardIncoming else {
return
Permissions.requestLibraryPermissionIfNeeded(
isSavingMedia: true,
presentingViewController: self
) { [weak self] in
mediaAttachments.forEach { attachment, originalFilePath in
PHPhotoLibrary.shared().performChanges(
{
if attachment.isImage || attachment.isAnimated {
PHAssetChangeRequest.creationRequestForAssetFromImage(
atFileURL: URL(fileURLWithPath: originalFilePath)
)
}
else if attachment.isVideo {
PHAssetChangeRequest.creationRequestForAssetFromVideo(
atFileURL: URL(fileURLWithPath: originalFilePath)
)
}
},
completionHandler: { _, _ in }
)
}

// Send a 'media saved' notification if needed
guard self?.viewModel.threadData.threadVariant == .contact, cellViewModel.variant == .standardIncoming else {
return
}

self?.sendDataExtraction(kind: .mediaSaved(timestamp: UInt64(cellViewModel.timestampMs)))
}

sendDataExtraction(kind: .mediaSaved(timestamp: UInt64(cellViewModel.timestampMs)))
}

func ban(_ cellViewModel: MessageViewModel, using dependencies: Dependencies) {
Expand Down Expand Up @@ -2598,7 +2613,7 @@ extension ConversationVC:
}

// Send attachment
sendMessage(text: "", attachments: [attachment], using: dependencies)
sendMessage(text: "", attachments: [attachment])
}

func cancelVoiceMessageRecording() {
Expand Down
25 changes: 20 additions & 5 deletions Session/Conversations/Message Cells/CallMessageCell.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.

import UIKit
import AVFAudio
import SessionUIKit
import SessionMessagingKit
import SessionUtilitiesKit
Expand Down Expand Up @@ -147,23 +148,29 @@ final class CallMessageCell: MessageCell {
switch messageInfo.state {
case .outgoing: return UIImage(named: "CallOutgoing")?.withRenderingMode(.alwaysTemplate)
case .incoming: return UIImage(named: "CallIncoming")?.withRenderingMode(.alwaysTemplate)
case .missed, .permissionDenied: return UIImage(named: "CallMissed")?.withRenderingMode(.alwaysTemplate)
case .missed, .permissionDenied, .permissionDeniedMicrophone:
return UIImage(named: "CallMissed")?.withRenderingMode(.alwaysTemplate)
default: return nil
}
}()
iconImageView.themeTintColor = {
switch messageInfo.state {
case .outgoing, .incoming: return .textPrimary
case .missed, .permissionDenied: return .danger
case .missed, .permissionDenied, .permissionDeniedMicrophone: return .danger
default: return nil
}
}()
iconImageViewWidthConstraint.constant = (iconImageView.image != nil ? CallMessageCell.iconSize : 0)
iconImageViewHeightConstraint.constant = (iconImageView.image != nil ? CallMessageCell.iconSize : 0)

let shouldShowInfoIcon: Bool = (
messageInfo.state == .permissionDenied &&
!Storage.shared[.areCallsEnabled]
(
messageInfo.state == .permissionDenied &&
!Storage.shared[.areCallsEnabled]
) || (
messageInfo.state == .permissionDeniedMicrophone &&
AVAudioSession.sharedInstance().recordPermission != .granted
)
)
infoImageViewWidthConstraint.constant = (shouldShowInfoIcon ? CallMessageCell.iconSize : 0)
infoImageViewHeightConstraint.constant = (shouldShowInfoIcon ? CallMessageCell.iconSize : 0)
Expand Down Expand Up @@ -217,7 +224,15 @@ final class CallMessageCell: MessageCell {
else { return }

// Should only be tappable if the info icon is visible
guard messageInfo.state == .permissionDenied && !Storage.shared[.areCallsEnabled] else { return }
guard
(
messageInfo.state == .permissionDenied &&
!Storage.shared[.areCallsEnabled]
) || (
messageInfo.state == .permissionDeniedMicrophone &&
AVAudioSession.sharedInstance().recordPermission != .granted
)
else { return }

self.delegate?.handleItemTapped(cellViewModel, cell: self, cellLocation: gestureRecognizer.location(in: self))
}
Expand Down
15 changes: 10 additions & 5 deletions Session/Media Viewing & Editing/PhotoCapture.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,13 @@ class PhotoCapture: NSObject {
self?.session.beginConfiguration()
defer { self?.session.commitConfiguration() }

try self?.updateCurrentInput(position: .back)
do { try self?.updateCurrentInput(position: .back) }
catch { throw PhotoCaptureError.initializationFailed }

guard
let photoOutput = self?.captureOutput.photoOutput,
self?.session.canAddOutput(photoOutput) == true
else {
throw PhotoCaptureError.initializationFailed
}
else { throw PhotoCaptureError.initializationFailed }

if let connection = photoOutput.connection(with: .video) {
if connection.isVideoStabilizationSupported {
Expand Down Expand Up @@ -610,7 +609,13 @@ class PhotoCaptureOutputAdaptee: NSObject, ImageCaptureOutput {
}

func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
var data = photo.fileDataRepresentation()!
guard var data: Data = photo.fileDataRepresentation() else {
DispatchQueue.main.async {
self.delegate?.captureOutputDidFinishProcessing(photoData: nil, error: error)
}
return
}

// Call normalized here to fix the orientation
if let srcImage = UIImage(data: data) {
data = srcImage.normalizedImage().jpegData(compressionQuality: 1.0)!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,12 @@ protocol PhotoCaptureViewControllerDelegate: AnyObject {
func photoCaptureViewControllerDidCancel(_ photoCaptureViewController: PhotoCaptureViewController)
}

enum PhotoCaptureError: Error {
enum PhotoCaptureError: Error, CustomStringConvertible {
case assertionError(description: String)
case initializationFailed
case captureFailed
}

extension PhotoCaptureError: LocalizedError {
var localizedDescription: String {
var description: String {
switch self {
case .initializationFailed:
return NSLocalizedString("PHOTO_CAPTURE_UNABLE_TO_INITIALIZE_CAMERA", comment: "alert title")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ class SendMediaNavigationController: UINavigationController {
}

private func didTapMediaLibraryModeButton() {
Permissions.requestLibraryPermissionIfNeeded { [weak self] in
Permissions.requestLibraryPermissionIfNeeded(isSavingMedia: false) { [weak self] in
DispatchQueue.main.async {
self?.fadeTo(viewControllers: ((self?.mediaLibraryViewController).map { [$0] } ?? []))
}
Expand Down
Loading

0 comments on commit 83ec937

Please sign in to comment.