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

Commit 9a4988f

Browse files
authored
Merge pull request #772 from oxen-io/dev
Release 2.2.5
2 parents 8976ab5 + 41f1b14 commit 9a4988f

109 files changed

Lines changed: 726 additions & 186 deletions

File tree

Some content is hidden

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

Session.xcodeproj/project.pbxproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7212,7 +7212,7 @@
72127212
"$(SRCROOT)",
72137213
);
72147214
LLVM_LTO = NO;
7215-
MARKETING_VERSION = 2.2.4;
7215+
MARKETING_VERSION = 2.2.5;
72167216
OTHER_LDFLAGS = "$(inherited)";
72177217
OTHER_SWIFT_FLAGS = "$(inherited) \"-D\" \"COCOAPODS\" \"-DDEBUG\"";
72187218
PRODUCT_BUNDLE_IDENTIFIER = "com.loki-project.loki-messenger";
@@ -7284,7 +7284,7 @@
72847284
"$(SRCROOT)",
72857285
);
72867286
LLVM_LTO = NO;
7287-
MARKETING_VERSION = 2.2.4;
7287+
MARKETING_VERSION = 2.2.5;
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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ public final class SessionCall: CurrentCallProtocol, WebRTCSessionDelegate {
206206
let thread: SessionThread = try? SessionThread.fetchOne(db, id: sessionId)
207207
else { return }
208208

209-
let timestampMs: Int64 = Int64(floor(Date().timeIntervalSince1970 * 1000))
209+
let timestampMs: Int64 = SnodeAPI.currentOffsetTimestampMs()
210210
let message: CallMessage = CallMessage(
211211
uuid: self.uuid,
212212
kind: .preOffer,

Session/Calls/CallVC.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ final class CallVC: UIViewController, VideoPreviewDelegate {
112112

113113
private lazy var hangUpButton: UIButton = {
114114
let result = UIButton(type: .custom)
115+
result.accessibilityLabel = "End call button"
115116
result.setImage(
116117
UIImage(named: "EndCall")?
117118
.withRenderingMode(.alwaysTemplate),

Session/Closed Groups/EditClosedGroupVC.swift

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ final class EditClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegat
1313
let profileId: String
1414
let role: GroupMember.Role
1515
let profile: Profile?
16+
let accessibilityLabel: String?
17+
let accessibilityId: String?
1618
}
1719

1820
private let threadId: String
@@ -30,6 +32,8 @@ final class EditClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegat
3032

3133
private lazy var groupNameLabel: UILabel = {
3234
let result: UILabel = UILabel()
35+
result.accessibilityLabel = "Group name"
36+
result.isAccessibilityElement = true
3337
result.font = .boldSystemFont(ofSize: Values.veryLargeFontSize)
3438
result.themeTextColor = .textPrimary
3539
result.lineBreakMode = .byTruncatingTail
@@ -44,12 +48,16 @@ final class EditClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegat
4448
usesDefaultHeight: false
4549
)
4650
result.textAlignment = .center
51+
result.isAccessibilityElement = true
52+
result.accessibilityIdentifier = "Group name text field"
4753

4854
return result
4955
}()
5056

5157
private lazy var addMembersButton: SessionButton = {
5258
let result: SessionButton = SessionButton(style: .bordered, size: .medium)
59+
result.accessibilityLabel = "Add members"
60+
result.isAccessibilityElement = true
5361
result.setTitle("vc_conversation_settings_invite_button_title".localized(), for: .normal)
5462
result.addTarget(self, action: #selector(addMembers), for: UIControl.Event.touchUpInside)
5563
result.contentEdgeInsets = UIEdgeInsets(top: 0, leading: Values.mediumSpacing, bottom: 0, trailing: Values.mediumSpacing)
@@ -59,6 +67,9 @@ final class EditClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegat
5967

6068
@objc private lazy var tableView: UITableView = {
6169
let result: UITableView = UITableView()
70+
result.accessibilityLabel = "Contact"
71+
result.accessibilityIdentifier = "Contact"
72+
result.isAccessibilityElement = true
6273
result.dataSource = self
6374
result.delegate = self
6475
result.separatorStyle = .none
@@ -264,6 +275,12 @@ final class EditClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegat
264275
}
265276

266277
let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(handleDoneButtonTapped))
278+
if isEditingGroupName {
279+
doneButton.accessibilityLabel = "Accept name change"
280+
}
281+
else {
282+
doneButton.accessibilityLabel = "Apply changes"
283+
}
267284
doneButton.themeTintColor = .textPrimary
268285
navigationItem.rightBarButtonItem = doneButton
269286
}
@@ -343,7 +360,9 @@ final class EditClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegat
343360
GroupMemberDisplayInfo(
344361
profileId: profile.id,
345362
role: .standard,
346-
profile: profile
363+
profile: profile,
364+
accessibilityLabel: "Contact",
365+
accessibilityId: "Contact"
347366
)
348367
}
349368
self?.membersAndZombies = (self?.membersAndZombies ?? [])

Session/Closed Groups/NewClosedGroupVC.swift

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,17 @@ import SessionMessagingKit
99
import SignalUtilitiesKit
1010

1111
private protocol TableViewTouchDelegate {
12-
func tableViewWasTouched(_ tableView: TableView)
12+
func tableViewWasTouched(_ tableView: TableView, withView hitView: UIView?)
1313
}
1414

1515
private final class TableView: UITableView {
1616
var touchDelegate: TableViewTouchDelegate?
1717

1818
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
19-
touchDelegate?.tableViewWasTouched(self)
20-
return super.hitTest(point, with: event)
19+
let resultingView: UIView? = super.hitTest(point, with: event)
20+
touchDelegate?.tableViewWasTouched(self, withView: resultingView)
21+
22+
return resultingView
2123
}
2224
}
2325

@@ -48,6 +50,8 @@ final class NewClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegate
4850
result.themeBorderColor = .borderSeparator
4951
result.layer.cornerRadius = 13
5052
result.delegate = self
53+
result.accessibilityIdentifier = "Group name input"
54+
result.isAccessibilityElement = true
5155

5256
return result
5357
}()
@@ -133,6 +137,8 @@ final class NewClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegate
133137
result.translatesAutoresizingMaskIntoConstraints = false
134138
result.setTitle("CREATE_GROUP_BUTTON_TITLE".localized(), for: .normal)
135139
result.addTarget(self, action: #selector(createClosedGroup), for: .touchUpInside)
140+
result.accessibilityIdentifier = "Create group"
141+
result.isAccessibilityElement = true
136142
result.set(.width, to: 160)
137143

138144
return result
@@ -151,6 +157,8 @@ final class NewClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegate
151157
let closeButton = UIBarButtonItem(image: #imageLiteral(resourceName: "X"), style: .plain, target: self, action: #selector(close))
152158
closeButton.themeTintColor = .textPrimary
153159
navigationItem.rightBarButtonItem = closeButton
160+
navigationItem.leftBarButtonItem?.accessibilityIdentifier = "Cancel"
161+
navigationItem.leftBarButtonItem?.isAccessibilityElement = true
154162

155163
// Set up content
156164
setUpViewHierarchy()
@@ -204,8 +212,9 @@ final class NewClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegate
204212
title: profile.displayName(),
205213
rightAccessory: .radio(isSelected: { [weak self] in
206214
self?.selectedContacts.contains(profile.id) == true
207-
})
208-
),
215+
}),
216+
accessibilityIdentifier: "Contact"
217+
),
209218
style: .edgeToEdge,
210219
position: Position.with(indexPath.row, count: data[indexPath.section].elements.count)
211220
)
@@ -268,10 +277,23 @@ final class NewClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegate
268277
)
269278
}
270279

271-
fileprivate func tableViewWasTouched(_ tableView: TableView) {
280+
fileprivate func tableViewWasTouched(_ tableView: TableView, withView hitView: UIView?) {
272281
if nameTextField.isFirstResponder {
273282
nameTextField.resignFirstResponder()
274283
}
284+
else if searchBar.isFirstResponder {
285+
var hitSuperview: UIView? = hitView?.superview
286+
287+
while hitSuperview != nil && hitSuperview != searchBar {
288+
hitSuperview = hitSuperview?.superview
289+
}
290+
291+
// If the user hit the cancel button then do nothing (we want to let the cancel
292+
// button remove the focus or it will instantly refocus)
293+
if hitSuperview == searchBar { return }
294+
295+
searchBar.resignFirstResponder()
296+
}
275297
}
276298

277299
@objc private func close() {
@@ -286,6 +308,7 @@ final class NewClosedGroupVC: BaseVC, UITableViewDataSource, UITableViewDelegate
286308
explanation: message,
287309
cancelTitle: "BUTTON_OK".localized(),
288310
cancelStyle: .alert_text
311+
289312
)
290313
)
291314
present(modal, animated: true)

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ extension ContextMenuVC {
1010
let isEmojiAction: Bool
1111
let isEmojiPlus: Bool
1212
let isDismissAction: Bool
13+
let accessibilityLabel: String?
1314
let work: () -> Void
1415

1516
// MARK: - Initialization
@@ -20,13 +21,15 @@ extension ContextMenuVC {
2021
isEmojiAction: Bool = false,
2122
isEmojiPlus: Bool = false,
2223
isDismissAction: Bool = false,
24+
accessibilityLabel: String? = nil,
2325
work: @escaping () -> Void
2426
) {
2527
self.icon = icon
2628
self.title = title
2729
self.isEmojiAction = isEmojiAction
2830
self.isEmojiPlus = isEmojiPlus
2931
self.isDismissAction = isDismissAction
32+
self.accessibilityLabel = accessibilityLabel
3033
self.work = work
3134
}
3235

@@ -35,7 +38,8 @@ extension ContextMenuVC {
3538
static func reply(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
3639
return Action(
3740
icon: UIImage(named: "ic_reply"),
38-
title: "context_menu_reply".localized()
41+
title: "context_menu_reply".localized(),
42+
accessibilityLabel: "Reply to message"
3943
) { delegate?.reply(cellViewModel) }
4044
}
4145

@@ -56,14 +60,16 @@ extension ContextMenuVC {
5660
static func delete(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
5761
return Action(
5862
icon: UIImage(named: "ic_trash"),
59-
title: "TXT_DELETE_TITLE".localized()
63+
title: "TXT_DELETE_TITLE".localized(),
64+
accessibilityLabel: "Delete message"
6065
) { delegate?.delete(cellViewModel) }
6166
}
6267

6368
static func save(_ cellViewModel: MessageViewModel, _ delegate: ContextMenuActionDelegate?) -> Action {
6469
return Action(
6570
icon: UIImage(named: "ic_download"),
66-
title: "context_menu_save".localized()
71+
title: "context_menu_save".localized(),
72+
accessibilityLabel: "Save attachment"
6773
) { delegate?.save(cellViewModel) }
6874
}
6975

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ extension ContextMenuVC {
4040
self.dismiss = dismiss
4141

4242
super.init(frame: CGRect.zero)
43-
43+
self.accessibilityLabel = action.accessibilityLabel
4444
setUpViewHierarchy()
4545
}
4646

Session/Conversations/ConversationVC+Interaction.swift

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ extension ConversationVC:
6969
title: "modal_call_permission_request_title".localized(),
7070
explanation: "modal_call_permission_request_explanation".localized(),
7171
confirmTitle: "vc_settings_title".localized(),
72+
confirmAccessibilityLabel: "Settings",
73+
cancelAccessibilityLabel: "Cancel",
7274
dismissOnConfirm: false // Custom dismissal logic
7375
) { [weak self] _ in
7476
self?.dismiss(animated: true) {
@@ -135,6 +137,8 @@ extension ConversationVC:
135137
range: (message as NSString).range(of: self.viewModel.threadData.displayName)
136138
),
137139
confirmTitle: "modal_blocked_button_title".localized(),
140+
confirmAccessibilityLabel: "Confirm block",
141+
cancelAccessibilityLabel: "Cancel block",
138142
dismissOnConfirm: false // Custom dismissal logic
139143
) { [weak self] _ in
140144
self?.viewModel.unblockContact()
@@ -405,7 +409,7 @@ extension ConversationVC:
405409
// flags appropriately
406410
let threadId: String = self.viewModel.threadData.threadId
407411
let oldThreadShouldBeVisible: Bool = (self.viewModel.threadData.threadShouldBeVisible == true)
408-
let sentTimestampMs: Int64 = Int64(floor((Date().timeIntervalSince1970 * 1000)))
412+
let sentTimestampMs: Int64 = SnodeAPI.currentOffsetTimestampMs()
409413
let linkPreviewDraft: LinkPreviewDraft? = snInputView.linkPreviewInfo?.draft
410414
let quoteModel: QuotedReplyModel? = snInputView.quoteDraftInfo?.model
411415

@@ -530,7 +534,7 @@ extension ConversationVC:
530534
// flags appropriately
531535
let threadId: String = self.viewModel.threadData.threadId
532536
let oldThreadShouldBeVisible: Bool = (self.viewModel.threadData.threadShouldBeVisible == true)
533-
let sentTimestampMs: Int64 = Int64(floor((Date().timeIntervalSince1970 * 1000)))
537+
let sentTimestampMs: Int64 = SnodeAPI.currentOffsetTimestampMs()
534538

535539
// If this was a message request then approve it
536540
approveMessageRequestIfNeeded(
@@ -636,7 +640,7 @@ extension ConversationVC:
636640
threadVariant: threadVariant,
637641
threadIsMessageRequest: threadIsMessageRequest,
638642
direction: .outgoing,
639-
timestampMs: Int64(floor(Date().timeIntervalSince1970 * 1000))
643+
timestampMs: SnodeAPI.currentOffsetTimestampMs()
640644
)
641645

642646
if needsToStartTypingIndicator {
@@ -854,6 +858,8 @@ extension ConversationVC:
854858
range: (message as NSString).range(of: cellViewModel.authorName)
855859
),
856860
confirmTitle: "modal_download_button_title".localized(),
861+
confirmAccessibilityLabel: "Download media",
862+
cancelAccessibilityLabel: "Don't download media",
857863
dismissOnConfirm: false // Custom dismissal logic
858864
) { [weak self] _ in
859865
self?.viewModel.trustContact()
@@ -1213,7 +1219,7 @@ extension ConversationVC:
12131219
guard !threadIsMessageRequest else { return }
12141220

12151221
// Perform local rate limiting (don't allow more than 20 reactions within 60 seconds)
1216-
let sentTimestamp: Int64 = Int64(floor(Date().timeIntervalSince1970 * 1000))
1222+
let sentTimestamp: Int64 = SnodeAPI.currentOffsetTimestampMs()
12171223
let recentReactionTimestamps: [Int64] = General.cache.wrappedValue.recentReactionTimestamps
12181224

12191225
guard
@@ -2038,7 +2044,7 @@ extension ConversationVC:
20382044

20392045
// Create URL
20402046
let directory: String = OWSTemporaryDirectory()
2041-
let fileName: String = "\(Int64(floor(Date().timeIntervalSince1970 * 1000))).m4a"
2047+
let fileName: String = "\(SnodeAPI.currentOffsetTimestampMs()).m4a"
20422048
let url: URL = URL(fileURLWithPath: directory).appendingPathComponent(fileName)
20432049

20442050
// Set up audio session
@@ -2279,7 +2285,7 @@ extension ConversationVC {
22792285
for: self.viewModel.threadData.threadId,
22802286
threadVariant: self.viewModel.threadData.threadVariant,
22812287
isNewThread: false,
2282-
timestampMs: Int64(floor(Date().timeIntervalSince1970 * 1000))
2288+
timestampMs: SnodeAPI.currentOffsetTimestampMs()
22832289
)
22842290
}
22852291

0 commit comments

Comments
 (0)