Skip to content

Commit 83ec937

Browse files
authored
Merge pull request #1021 from oxen-io/dev
Release 2.7.4
2 parents 78a33f1 + 7ff2368 commit 83ec937

File tree

72 files changed

+2202
-1432
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+2202
-1432
lines changed

Scripts/drone-static-upload.sh

+4-3
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,15 @@ else
3434
fi
3535

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

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

54-
upload_to="oxen.rocks/${DRONE_REPO// /_}/${DRONE_BRANCH// /_}"
55-
5657
# sftp doesn't have any equivalent to mkdir -p, so we have to split the above up into a chain of
5758
# -mkdir a/, -mkdir a/b/, -mkdir a/b/c/, ... commands. The leading `-` allows the command to fail
5859
# without error.

Session.xcodeproj/project.pbxproj

+59-26
Large diffs are not rendered by default.

Session.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"originHash" : "b77f342bc30b5d1971118f9ad70bf3af24442c4edb9a716222ad6bc0fb9b3f8e",
2+
"originHash" : "77d5fda90891573a263c0fefeb989f3f1bb56e612a09be32106558b6d5fb4564",
33
"pins" : [
44
{
55
"identity" : "cocoalumberjack",
@@ -85,10 +85,10 @@
8585
{
8686
"identity" : "session-grdb-swift",
8787
"kind" : "remoteSourceControl",
88-
"location" : "https://github.com/oxen-io/session-grdb-swift",
88+
"location" : "https://github.com/oxen-io/session-grdb-swift.git",
8989
"state" : {
90-
"revision" : "52043c998154b39ecd8e069ba22244bf36464c61",
91-
"version" : "106.27.1"
90+
"revision" : "426149dd868219517df20eebeca27ff385fee34a",
91+
"version" : "106.29.2"
9292
}
9393
},
9494
{

Session/Calls/Call Management/SessionCallManager.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ public final class SessionCallManager: NSObject, CallManagerProtocol {
205205
// Stop all jobs except for message sending and when completed suspend the database
206206
JobRunner.stopAndClearPendingJobs(exceptForVariant: .messageSend, using: dependencies) { _ in
207207
LibSession.suspendNetworkAccess()
208-
Storage.suspendDatabaseAccess(using: dependencies)
208+
dependencies.storage.suspendDatabaseAccess()
209209
Log.flush()
210210
}
211211
}

Session/Conversations/ConversationVC+Interaction.swift

+53-38
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ extension ConversationVC:
192192
threadVariant: SessionThread.Variant,
193193
messageText: String?
194194
) {
195-
sendMessage(text: (messageText ?? ""), attachments: attachments, using: viewModel.dependencies)
195+
sendMessage(text: (messageText ?? ""), attachments: attachments)
196196
resetMentions()
197197

198198
dismiss(animated: true) { [weak self] in
@@ -222,7 +222,7 @@ extension ConversationVC:
222222
threadVariant: SessionThread.Variant,
223223
messageText: String?
224224
) {
225-
sendMessage(text: (messageText ?? ""), attachments: attachments, using: viewModel.dependencies)
225+
sendMessage(text: (messageText ?? ""), attachments: attachments)
226226
resetMentions()
227227

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

301-
Permissions.requestLibraryPermissionIfNeeded { [weak self, dependencies = viewModel.dependencies] in
301+
Permissions.requestLibraryPermissionIfNeeded(isSavingMedia: false) { [weak self, dependencies = viewModel.dependencies] in
302302
DispatchQueue.main.async {
303303
let sendMediaNavController = SendMediaNavigationController.showingMediaLibraryFirst(
304304
threadId: threadId,
@@ -467,8 +467,7 @@ extension ConversationVC:
467467
attachments: [SignalAttachment] = [],
468468
linkPreviewDraft: LinkPreviewDraft? = nil,
469469
quoteModel: QuotedReplyModel? = nil,
470-
hasPermissionToSendSeed: Bool = false,
471-
using dependencies: Dependencies = Dependencies()
470+
hasPermissionToSendSeed: Bool = false
472471
) {
473472
guard !showBlockedModalIfNeeded() else { return }
474473

@@ -539,17 +538,14 @@ extension ConversationVC:
539538
quoteModel: quoteModel
540539
)
541540

542-
sendMessage(optimisticData: optimisticData, using: dependencies)
541+
sendMessage(optimisticData: optimisticData)
543542
}
544543

545-
private func sendMessage(
546-
optimisticData: ConversationViewModel.OptimisticMessageData,
547-
using dependencies: Dependencies
548-
) {
544+
private func sendMessage(optimisticData: ConversationViewModel.OptimisticMessageData) {
549545
let threadId: String = self.viewModel.threadData.threadId
550546
let threadVariant: SessionThread.Variant = self.viewModel.threadData.threadVariant
551547

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

903899
// For call info messages show the "call missed" modal
904900
guard cellViewModel.variant != .infoCall else {
905-
let callMissedTipsModal: CallMissedTipsModal = CallMissedTipsModal(caller: cellViewModel.authorName)
906-
present(callMissedTipsModal, animated: true, completion: nil)
901+
// If the failure was due to the mic permission being denied then we want to show the permission modal,
902+
// otherwise we want to show the call missed tips modal
903+
guard
904+
let infoMessageData: Data = (cellViewModel.rawBody ?? "").data(using: .utf8),
905+
let messageInfo: CallMessage.MessageInfo = try? JSONDecoder().decode(
906+
CallMessage.MessageInfo.self,
907+
from: infoMessageData
908+
),
909+
messageInfo.state == .permissionDeniedMicrophone
910+
else {
911+
let callMissedTipsModal: CallMissedTipsModal = CallMissedTipsModal(caller: cellViewModel.authorName)
912+
present(callMissedTipsModal, animated: true, completion: nil)
913+
return
914+
}
915+
916+
Permissions.requestMicrophonePermissionIfNeeded(presentingViewController: self)
907917
return
908918
}
909919

@@ -1891,7 +1901,7 @@ extension ConversationVC:
18911901
}
18921902

18931903
// Try to send the optimistic message again
1894-
sendMessage(optimisticData: optimisticMessageData, using: dependencies)
1904+
sendMessage(optimisticData: optimisticMessageData)
18951905
return
18961906
}
18971907

@@ -2326,30 +2336,35 @@ extension ConversationVC:
23262336

23272337
guard !mediaAttachments.isEmpty else { return }
23282338

2329-
mediaAttachments.forEach { attachment, originalFilePath in
2330-
PHPhotoLibrary.shared().performChanges(
2331-
{
2332-
if attachment.isImage || attachment.isAnimated {
2333-
PHAssetChangeRequest.creationRequestForAssetFromImage(
2334-
atFileURL: URL(fileURLWithPath: originalFilePath)
2335-
)
2336-
}
2337-
else if attachment.isVideo {
2338-
PHAssetChangeRequest.creationRequestForAssetFromVideo(
2339-
atFileURL: URL(fileURLWithPath: originalFilePath)
2340-
)
2341-
}
2342-
},
2343-
completionHandler: { _, _ in }
2344-
)
2345-
}
2346-
2347-
// Send a 'media saved' notification if needed
2348-
guard self.viewModel.threadData.threadVariant == .contact, cellViewModel.variant == .standardIncoming else {
2349-
return
2339+
Permissions.requestLibraryPermissionIfNeeded(
2340+
isSavingMedia: true,
2341+
presentingViewController: self
2342+
) { [weak self] in
2343+
mediaAttachments.forEach { attachment, originalFilePath in
2344+
PHPhotoLibrary.shared().performChanges(
2345+
{
2346+
if attachment.isImage || attachment.isAnimated {
2347+
PHAssetChangeRequest.creationRequestForAssetFromImage(
2348+
atFileURL: URL(fileURLWithPath: originalFilePath)
2349+
)
2350+
}
2351+
else if attachment.isVideo {
2352+
PHAssetChangeRequest.creationRequestForAssetFromVideo(
2353+
atFileURL: URL(fileURLWithPath: originalFilePath)
2354+
)
2355+
}
2356+
},
2357+
completionHandler: { _, _ in }
2358+
)
2359+
}
2360+
2361+
// Send a 'media saved' notification if needed
2362+
guard self?.viewModel.threadData.threadVariant == .contact, cellViewModel.variant == .standardIncoming else {
2363+
return
2364+
}
2365+
2366+
self?.sendDataExtraction(kind: .mediaSaved(timestamp: UInt64(cellViewModel.timestampMs)))
23502367
}
2351-
2352-
sendDataExtraction(kind: .mediaSaved(timestamp: UInt64(cellViewModel.timestampMs)))
23532368
}
23542369

23552370
func ban(_ cellViewModel: MessageViewModel, using dependencies: Dependencies) {
@@ -2598,7 +2613,7 @@ extension ConversationVC:
25982613
}
25992614

26002615
// Send attachment
2601-
sendMessage(text: "", attachments: [attachment], using: dependencies)
2616+
sendMessage(text: "", attachments: [attachment])
26022617
}
26032618

26042619
func cancelVoiceMessageRecording() {

Session/Conversations/Message Cells/CallMessageCell.swift

+20-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
22

33
import UIKit
4+
import AVFAudio
45
import SessionUIKit
56
import SessionMessagingKit
67
import SessionUtilitiesKit
@@ -147,23 +148,29 @@ final class CallMessageCell: MessageCell {
147148
switch messageInfo.state {
148149
case .outgoing: return UIImage(named: "CallOutgoing")?.withRenderingMode(.alwaysTemplate)
149150
case .incoming: return UIImage(named: "CallIncoming")?.withRenderingMode(.alwaysTemplate)
150-
case .missed, .permissionDenied: return UIImage(named: "CallMissed")?.withRenderingMode(.alwaysTemplate)
151+
case .missed, .permissionDenied, .permissionDeniedMicrophone:
152+
return UIImage(named: "CallMissed")?.withRenderingMode(.alwaysTemplate)
151153
default: return nil
152154
}
153155
}()
154156
iconImageView.themeTintColor = {
155157
switch messageInfo.state {
156158
case .outgoing, .incoming: return .textPrimary
157-
case .missed, .permissionDenied: return .danger
159+
case .missed, .permissionDenied, .permissionDeniedMicrophone: return .danger
158160
default: return nil
159161
}
160162
}()
161163
iconImageViewWidthConstraint.constant = (iconImageView.image != nil ? CallMessageCell.iconSize : 0)
162164
iconImageViewHeightConstraint.constant = (iconImageView.image != nil ? CallMessageCell.iconSize : 0)
163165

164166
let shouldShowInfoIcon: Bool = (
165-
messageInfo.state == .permissionDenied &&
166-
!Storage.shared[.areCallsEnabled]
167+
(
168+
messageInfo.state == .permissionDenied &&
169+
!Storage.shared[.areCallsEnabled]
170+
) || (
171+
messageInfo.state == .permissionDeniedMicrophone &&
172+
AVAudioSession.sharedInstance().recordPermission != .granted
173+
)
167174
)
168175
infoImageViewWidthConstraint.constant = (shouldShowInfoIcon ? CallMessageCell.iconSize : 0)
169176
infoImageViewHeightConstraint.constant = (shouldShowInfoIcon ? CallMessageCell.iconSize : 0)
@@ -217,7 +224,15 @@ final class CallMessageCell: MessageCell {
217224
else { return }
218225

219226
// Should only be tappable if the info icon is visible
220-
guard messageInfo.state == .permissionDenied && !Storage.shared[.areCallsEnabled] else { return }
227+
guard
228+
(
229+
messageInfo.state == .permissionDenied &&
230+
!Storage.shared[.areCallsEnabled]
231+
) || (
232+
messageInfo.state == .permissionDeniedMicrophone &&
233+
AVAudioSession.sharedInstance().recordPermission != .granted
234+
)
235+
else { return }
221236

222237
self.delegate?.handleItemTapped(cellViewModel, cell: self, cellLocation: gestureRecognizer.location(in: self))
223238
}

Session/Media Viewing & Editing/PhotoCapture.swift

+10-5
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,13 @@ class PhotoCapture: NSObject {
9292
self?.session.beginConfiguration()
9393
defer { self?.session.commitConfiguration() }
9494

95-
try self?.updateCurrentInput(position: .back)
95+
do { try self?.updateCurrentInput(position: .back) }
96+
catch { throw PhotoCaptureError.initializationFailed }
9697

9798
guard
9899
let photoOutput = self?.captureOutput.photoOutput,
99100
self?.session.canAddOutput(photoOutput) == true
100-
else {
101-
throw PhotoCaptureError.initializationFailed
102-
}
101+
else { throw PhotoCaptureError.initializationFailed }
103102

104103
if let connection = photoOutput.connection(with: .video) {
105104
if connection.isVideoStabilizationSupported {
@@ -610,7 +609,13 @@ class PhotoCaptureOutputAdaptee: NSObject, ImageCaptureOutput {
610609
}
611610

612611
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
613-
var data = photo.fileDataRepresentation()!
612+
guard var data: Data = photo.fileDataRepresentation() else {
613+
DispatchQueue.main.async {
614+
self.delegate?.captureOutputDidFinishProcessing(photoData: nil, error: error)
615+
}
616+
return
617+
}
618+
614619
// Call normalized here to fix the orientation
615620
if let srcImage = UIImage(data: data) {
616621
data = srcImage.normalizedImage().jpegData(compressionQuality: 1.0)!

Session/Media Viewing & Editing/PhotoCaptureViewController.swift

+2-4
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,12 @@ protocol PhotoCaptureViewControllerDelegate: AnyObject {
1212
func photoCaptureViewControllerDidCancel(_ photoCaptureViewController: PhotoCaptureViewController)
1313
}
1414

15-
enum PhotoCaptureError: Error {
15+
enum PhotoCaptureError: Error, CustomStringConvertible {
1616
case assertionError(description: String)
1717
case initializationFailed
1818
case captureFailed
19-
}
2019

21-
extension PhotoCaptureError: LocalizedError {
22-
var localizedDescription: String {
20+
var description: String {
2321
switch self {
2422
case .initializationFailed:
2523
return NSLocalizedString("PHOTO_CAPTURE_UNABLE_TO_INITIALIZE_CAMERA", comment: "alert title")

Session/Media Viewing & Editing/SendMediaNavigationController.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ class SendMediaNavigationController: UINavigationController {
154154
}
155155

156156
private func didTapMediaLibraryModeButton() {
157-
Permissions.requestLibraryPermissionIfNeeded { [weak self] in
157+
Permissions.requestLibraryPermissionIfNeeded(isSavingMedia: false) { [weak self] in
158158
DispatchQueue.main.async {
159159
self?.fadeTo(viewControllers: ((self?.mediaLibraryViewController).map { [$0] } ?? []))
160160
}

0 commit comments

Comments
 (0)