Skip to content
This repository was archived by the owner on Dec 2, 2025. It is now read-only.

Commit a53366d

Browse files
authored
Merge pull request #779 from oxen-io/dev
Release 2.2.6
2 parents 9a4988f + 617eae6 commit a53366d

14 files changed

Lines changed: 153 additions & 46 deletions

File tree

Session.xcodeproj/project.pbxproj

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6032,7 +6032,7 @@
60326032
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
60336033
CODE_SIGN_STYLE = Automatic;
60346034
COPY_PHASE_STRIP = NO;
6035-
CURRENT_PROJECT_VERSION = 389;
6035+
CURRENT_PROJECT_VERSION = 391;
60366036
DEBUG_INFORMATION_FORMAT = dwarf;
60376037
DEVELOPMENT_TEAM = SUQ8J2PCT7;
60386038
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@@ -6057,7 +6057,7 @@
60576057
"@executable_path/Frameworks",
60586058
"@executable_path/../../Frameworks",
60596059
);
6060-
MARKETING_VERSION = 2.2.4;
6060+
MARKETING_VERSION = 2.2.6;
60616061
MTL_ENABLE_DEBUG_INFO = YES;
60626062
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.ShareExtension";
60636063
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -6105,7 +6105,7 @@
61056105
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
61066106
CODE_SIGN_STYLE = Automatic;
61076107
COPY_PHASE_STRIP = NO;
6108-
CURRENT_PROJECT_VERSION = 389;
6108+
CURRENT_PROJECT_VERSION = 391;
61096109
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
61106110
DEVELOPMENT_TEAM = SUQ8J2PCT7;
61116111
ENABLE_NS_ASSERTIONS = NO;
@@ -6135,7 +6135,7 @@
61356135
"@executable_path/Frameworks",
61366136
"@executable_path/../../Frameworks",
61376137
);
6138-
MARKETING_VERSION = 2.2.4;
6138+
MARKETING_VERSION = 2.2.6;
61396139
MTL_ENABLE_DEBUG_INFO = NO;
61406140
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.ShareExtension";
61416141
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -6171,7 +6171,7 @@
61716171
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
61726172
CODE_SIGN_STYLE = Automatic;
61736173
COPY_PHASE_STRIP = NO;
6174-
CURRENT_PROJECT_VERSION = 389;
6174+
CURRENT_PROJECT_VERSION = 391;
61756175
DEBUG_INFORMATION_FORMAT = dwarf;
61766176
DEVELOPMENT_TEAM = SUQ8J2PCT7;
61776177
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@@ -6194,7 +6194,7 @@
61946194
"@executable_path/Frameworks",
61956195
"@executable_path/../../Frameworks",
61966196
);
6197-
MARKETING_VERSION = 2.2.4;
6197+
MARKETING_VERSION = 2.2.6;
61986198
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
61996199
MTL_FAST_MATH = YES;
62006200
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.NotificationServiceExtension";
@@ -6245,7 +6245,7 @@
62456245
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
62466246
CODE_SIGN_STYLE = Automatic;
62476247
COPY_PHASE_STRIP = NO;
6248-
CURRENT_PROJECT_VERSION = 389;
6248+
CURRENT_PROJECT_VERSION = 391;
62496249
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
62506250
DEVELOPMENT_TEAM = SUQ8J2PCT7;
62516251
ENABLE_NS_ASSERTIONS = NO;
@@ -6273,7 +6273,7 @@
62736273
"@executable_path/Frameworks",
62746274
"@executable_path/../../Frameworks",
62756275
);
6276-
MARKETING_VERSION = 2.2.4;
6276+
MARKETING_VERSION = 2.2.6;
62776277
MTL_ENABLE_DEBUG_INFO = NO;
62786278
MTL_FAST_MATH = YES;
62796279
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger.NotificationServiceExtension";
@@ -7173,7 +7173,7 @@
71737173
CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements;
71747174
CODE_SIGN_IDENTITY = "iPhone Developer";
71757175
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
7176-
CURRENT_PROJECT_VERSION = 389;
7176+
CURRENT_PROJECT_VERSION = 391;
71777177
DEVELOPMENT_TEAM = SUQ8J2PCT7;
71787178
FRAMEWORK_SEARCH_PATHS = (
71797179
"$(inherited)",
@@ -7212,7 +7212,7 @@
72127212
"$(SRCROOT)",
72137213
);
72147214
LLVM_LTO = NO;
7215-
MARKETING_VERSION = 2.2.5;
7215+
MARKETING_VERSION = 2.2.6;
72167216
OTHER_LDFLAGS = "$(inherited)";
72177217
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
72187218
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger";
@@ -7245,7 +7245,7 @@
72457245
CODE_SIGN_ENTITLEMENTS = Session/Meta/Signal.entitlements;
72467246
CODE_SIGN_IDENTITY = "iPhone Developer";
72477247
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
7248-
CURRENT_PROJECT_VERSION = 389;
7248+
CURRENT_PROJECT_VERSION = 391;
72497249
DEVELOPMENT_TEAM = SUQ8J2PCT7;
72507250
FRAMEWORK_SEARCH_PATHS = (
72517251
"$(inherited)",
@@ -7284,7 +7284,7 @@
72847284
"$(SRCROOT)",
72857285
);
72867286
LLVM_LTO = NO;
7287-
MARKETING_VERSION = 2.2.5;
7287+
MARKETING_VERSION = 2.2.6;
72887288
OTHER_LDFLAGS = "$(inherited)";
72897289
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger";
72907290
PRODUCT_NAME = Session;

Session/Calls/Call Management/SessionCall.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,12 +318,20 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate {
318318
}
319319
}()
320320

321-
guard shouldMarkAsRead else { return }
321+
guard
322+
shouldMarkAsRead,
323+
let threadVariant: SessionThread.Variant = try? SessionThread
324+
.filter(id: interaction.threadId)
325+
.select(.variant)
326+
.asRequest(of: SessionThread.Variant.self)
327+
.fetchOne(db)
328+
else { return }
322329

323330
try Interaction.markAsRead(
324331
db,
325332
interactionId: interaction.id,
326333
threadId: interaction.threadId,
334+
threadVariant: threadVariant,
327335
includingOlder: false,
328336
trySendReadReceipt: false
329337
)

Session/Conversations/Context Menu/ContextMenuVC+Action.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ extension ContextMenuVC {
110110
static func actions(
111111
for cellViewModel: MessageViewModel,
112112
recentEmojis: [EmojiWithSkinTones],
113+
currentUserPublicKey: String,
113114
currentUserIsOpenGroupModerator: Bool,
114115
currentThreadIsMessageRequest: Bool,
115116
delegate: ContextMenuActionDelegate?
@@ -163,6 +164,7 @@ extension ContextMenuVC {
163164
let canDelete: Bool = (
164165
cellViewModel.threadVariant != .openGroup ||
165166
currentUserIsOpenGroupModerator ||
167+
cellViewModel.authorId == currentUserPublicKey ||
166168
cellViewModel.state == .failed
167169
)
168170
let canBan: Bool = (

Session/Conversations/ConversationVC+Interaction.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,7 @@ extension ConversationVC:
777777
let actions: [ContextMenuVC.Action] = ContextMenuVC.actions(
778778
for: cellViewModel,
779779
recentEmojis: (self.viewModel.threadData.recentReactionEmoji ?? []).compactMap { EmojiWithSkinTones(rawValue: $0) },
780+
currentUserPublicKey: self.viewModel.threadData.currentUserPublicKey,
780781
currentUserIsOpenGroupModerator: OpenGroupManager.isUserModeratorOrAdmin(
781782
self.viewModel.threadData.currentUserPublicKey,
782783
for: self.viewModel.threadData.openGroupRoomToken,

Session/Conversations/ConversationVC.swift

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -737,11 +737,17 @@ final class ConversationVC: BaseVC, ConversationSearchControllerDelegate, UITabl
737737

738738
// Store the 'sentMessageBeforeUpdate' state locally
739739
let didSendMessageBeforeUpdate: Bool = self.viewModel.sentMessageBeforeUpdate
740+
let wasOnlyUpdates: Bool = (
741+
changeset.count == 1 &&
742+
changeset[0].elementUpdated.count == changeset[0].changeCount
743+
)
740744
self.viewModel.sentMessageBeforeUpdate = false
741745

742-
// When sending a message we want to reload the UI instantly (with any form of animation the message
743-
// sending feels somewhat unresponsive but an instant update feels snappy)
744-
guard !didSendMessageBeforeUpdate else {
746+
// When sending a message, or if there were only cell updates (ie. read status changes) we want to
747+
// reload the UI instantly (with any form of animation the message sending feels somewhat unresponsive
748+
// but an instant update feels snappy and without the instant update there is some overlap of the read
749+
// status text change even though there shouldn't be any animations)
750+
guard !didSendMessageBeforeUpdate && !wasOnlyUpdates else {
745751
self.viewModel.updateInteractionData(updatedData)
746752
self.tableView.reloadData()
747753

Session/Conversations/ConversationViewModel.swift

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,17 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
197197

198198
return SQL("LEFT JOIN \(Profile.self) ON \(profile[.id]) = \(interaction[.authorId])")
199199
}()
200-
)
200+
),
201+
PagedData.ObservedChanges(
202+
table: RecipientState.self,
203+
columns: [.state, .mostRecentFailureText],
204+
joinToPagedType: {
205+
let interaction: TypedTableAlias<Interaction> = TypedTableAlias()
206+
let recipientState: TypedTableAlias<RecipientState> = TypedTableAlias()
207+
208+
return SQL("LEFT JOIN \(RecipientState.self) ON \(recipientState[.interactionId]) = \(interaction[.id])")
209+
}()
210+
),
201211
],
202212
filterSQL: MessageViewModel.filterSQL(threadId: threadId),
203213
groupSQL: MessageViewModel.groupSQL,
@@ -405,6 +415,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
405415
else { return }
406416

407417
let threadId: String = self.threadData.threadId
418+
let threadVariant: SessionThread.Variant = self.threadData.threadVariant
408419
let trySendReadReceipt: Bool = (self.threadData.threadIsMessageRequest == false)
409420
self.lastInteractionIdMarkedAsRead = targetInteractionId
410421

@@ -413,6 +424,7 @@ public class ConversationViewModel: OWSAudioPlayerDelegate {
413424
db,
414425
interactionId: targetInteractionId,
415426
threadId: threadId,
427+
threadVariant: threadVariant,
416428
includingOlder: true,
417429
trySendReadReceipt: trySendReadReceipt
418430
)

Session/Conversations/Message Cells/VisibleMessageCell.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
165165

166166
return result
167167
}()
168+
169+
internal lazy var messageStatusLabelPaddingView: UIView = UIView()
168170

169171
// MARK: - Settings
170172

@@ -252,6 +254,7 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
252254

253255
underBubbleStackView.addArrangedSubview(reactionContainerView)
254256
underBubbleStackView.addArrangedSubview(messageStatusContainerView)
257+
underBubbleStackView.addArrangedSubview(messageStatusLabelPaddingView)
255258

256259
messageStatusContainerView.addSubview(messageStatusLabel)
257260
messageStatusContainerView.addSubview(messageStatusImageView)
@@ -267,6 +270,8 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
267270
messageStatusLabel.center(.vertical, in: messageStatusContainerView)
268271
messageStatusLabel.pin(.leading, to: .leading, of: messageStatusContainerView)
269272
messageStatusLabel.pin(.trailing, to: .leading, of: messageStatusImageView, withInset: -2)
273+
messageStatusLabelPaddingView.pin(.leading, to: .leading, of: messageStatusContainerView)
274+
messageStatusLabelPaddingView.pin(.trailing, to: .trailing, of: messageStatusContainerView)
270275
}
271276

272277
override func setUpGestureRecognizers() {
@@ -429,6 +434,10 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
429434
!cellViewModel.isLast
430435
)
431436
)
437+
messageStatusLabelPaddingView.isHidden = (
438+
messageStatusContainerView.isHidden ||
439+
cellViewModel.isLast
440+
)
432441

433442
// Set the height of the underBubbleStackView to 0 if it has no content (need to do this
434443
// otherwise it can randomly stretch)
@@ -1121,11 +1130,15 @@ final class VisibleMessageCell: MessageCell, TappableLabelDelegate {
11211130
return [:]
11221131
}
11231132

1133+
// Note: The 'String.count' value is based on actual character counts whereas
1134+
// NSAttributedString and NSRange are both based on UTF-16 encoded lengths, so
1135+
// in order to avoid strings which contain emojis breaking strings which end
1136+
// with URLs we need to use the 'String.utf16.count' value when creating the range
11241137
return detector
11251138
.matches(
11261139
in: attributedText.string,
11271140
options: [],
1128-
range: NSRange(location: 0, length: attributedText.string.count)
1141+
range: NSRange(location: 0, length: attributedText.string.utf16.count)
11291142
)
11301143
.reduce(into: [:]) { result, match in
11311144
guard

Session/Notifications/AppNotifications.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,7 @@ class NotificationActionHandler {
546546
db,
547547
interactionId: interaction.id,
548548
threadId: thread.id,
549+
threadVariant: thread.variant,
549550
includingOlder: true,
550551
trySendReadReceipt: true
551552
)
@@ -600,6 +601,7 @@ class NotificationActionHandler {
600601
.asRequest(of: Int64.self)
601602
.fetchOne(db),
602603
threadId: thread.id,
604+
threadVariant: thread.variant,
603605
includingOlder: true,
604606
trySendReadReceipt: true
605607
)

Session/Path/PathStatusView.swift

Lines changed: 49 additions & 4 deletions
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 Reachability
45
import SessionUIKit
56

67
final class PathStatusView: UIView {
@@ -42,6 +43,7 @@ final class PathStatusView: UIView {
4243
// MARK: - Initialization
4344

4445
private let size: Size
46+
private let reachability: Reachability = Reachability.forInternetConnection()
4547

4648
init(size: Size = .small) {
4749
self.size = size
@@ -73,15 +75,34 @@ final class PathStatusView: UIView {
7375
self.set(.width, to: self.size.pointSize)
7476
self.set(.height, to: self.size.pointSize)
7577

76-
setStatus(to: (!OnionRequestAPI.paths.isEmpty ? .connected : .connecting))
78+
switch (reachability.isReachable(), OnionRequestAPI.paths.isEmpty) {
79+
case (false, _): setStatus(to: .error)
80+
case (true, true): setStatus(to: .connecting)
81+
case (true, false): setStatus(to: .connected)
82+
}
7783
}
7884

7985
// MARK: - Functions
8086

8187
private func registerObservers() {
82-
let notificationCenter = NotificationCenter.default
83-
notificationCenter.addObserver(self, selector: #selector(handleBuildingPathsNotification), name: .buildingPaths, object: nil)
84-
notificationCenter.addObserver(self, selector: #selector(handlePathsBuiltNotification), name: .pathsBuilt, object: nil)
88+
NotificationCenter.default.addObserver(
89+
self,
90+
selector: #selector(handleBuildingPathsNotification),
91+
name: .buildingPaths,
92+
object: nil
93+
)
94+
NotificationCenter.default.addObserver(
95+
self,
96+
selector: #selector(handlePathsBuiltNotification),
97+
name: .pathsBuilt,
98+
object: nil
99+
)
100+
NotificationCenter.default.addObserver(
101+
self,
102+
selector: #selector(reachabilityChanged),
103+
name: .reachabilityChanged,
104+
object: nil
105+
)
85106
}
86107

87108
private func setStatus(to status: Status) {
@@ -102,10 +123,34 @@ final class PathStatusView: UIView {
102123
}
103124

104125
@objc private func handleBuildingPathsNotification() {
126+
guard reachability.isReachable() else {
127+
setStatus(to: .error)
128+
return
129+
}
130+
105131
setStatus(to: .connecting)
106132
}
107133

108134
@objc private func handlePathsBuiltNotification() {
135+
guard reachability.isReachable() else {
136+
setStatus(to: .error)
137+
return
138+
}
139+
109140
setStatus(to: .connected)
110141
}
142+
143+
@objc private func reachabilityChanged() {
144+
guard Thread.isMainThread else {
145+
DispatchQueue.main.async { [weak self] in self?.reachabilityChanged() }
146+
return
147+
}
148+
149+
guard reachability.isReachable() else {
150+
setStatus(to: .error)
151+
return
152+
}
153+
154+
setStatus(to: (!OnionRequestAPI.paths.isEmpty ? .connected : .connecting))
155+
}
111156
}

0 commit comments

Comments
 (0)