Skip to content

Commit

Permalink
Version 6.0b6063
Browse files Browse the repository at this point in the history
  • Loading branch information
Threema committed May 15, 2024
1 parent e69a515 commit 1e9da0c
Show file tree
Hide file tree
Showing 1,057 changed files with 30,966 additions and 11,411 deletions.
6 changes: 1 addition & 5 deletions BinUtils/BinUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -316,11 +316,7 @@ public func pack(
if c == "s" {
o = objectsQueue.remove(at: 0)

guard let stringData = (o as! String).data(using: .utf8) else {
assertionFailure()
return Data()
}
var bytes = stringData.bytes
var bytes = Data((o as! String).utf8).bytes

let expectedSize = max(1, n)

Expand Down
20 changes: 2 additions & 18 deletions GroupCalls/Sources/GroupCalls/GroupCall/CallID.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,27 +35,11 @@ struct GroupCallID: Sendable {
callStartData: GroupCallStartData,
dependencies: Dependencies
) throws {
guard let creatorID = groupIdentity.creator.string.data(using: .utf8) else {
let msg = "Could not encode group creator ID"
assertionFailure(msg)
DDLogError(msg)

throw GroupCallError.encryptionFailure
}

let creatorID = Data(groupIdentity.creator.string.utf8)
let groupID = groupIdentity.id

let protocolVersion = Data(repeating: UInt8(callStartData.protocolVersion), count: 1)

let gck = callStartData.gck

guard let baseURL = callStartData.sfuBaseURL.data(using: .utf8) else {
let msg = "Could not encode sfu base url"
assertionFailure(msg)
DDLogError(msg)

throw GroupCallError.encryptionFailure
}
let baseURL = Data(callStartData.sfuBaseURL.utf8)

let inputs = [creatorID, groupID, protocolVersion, gck, baseURL]

Expand Down
40 changes: 27 additions & 13 deletions GroupCalls/Sources/GroupCalls/GroupCall/GroupCallActor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,10 @@ actor GroupCallActor: Sendable {
}
}

/// The exact call start date of the call as determined by the SFU
/// The exact creation timestamp of the call as determined by the SFU
///
/// Use this for ordering calls by call creation time.
var exactCallStartDate: UInt64?
/// Use this for ordering calls by call start time.
private(set) var exactCreationTimestamp: UInt64?

let localContactModel: ContactModel
var localParticipant: LocalParticipant? = nil
Expand All @@ -121,7 +121,7 @@ actor GroupCallActor: Sendable {

private var startMessage: CspE2e_GroupCallStart?

private var numberOfParticipants = 0
private var sfuProvidedNumberOfParticipants = 0

private lazy var state: GroupCallState = UnJoined(groupCallActor: self) {
didSet {
Expand Down Expand Up @@ -324,7 +324,7 @@ actor GroupCallActor: Sendable {
func handle(peekResult: SFUHTTPConnection.PeekResponse) async throws -> PeekResult {
switch peekResult {
case let .running(peekResponse):
exactCallStartDate = peekResponse.startedAt
exactCreationTimestamp = peekResponse.startedAt
groupCallBaseState.maxParticipants = Int(peekResponse.maxParticipants)

if peekResponse.hasEncryptedCallState {
Expand All @@ -338,7 +338,7 @@ actor GroupCallActor: Sendable {
}

// We add one for the creator, which is not included in participants
numberOfParticipants = decryptedCallState.participants.count + 1
sfuProvidedNumberOfParticipants = decryptedCallState.participants.count + 1

await updateButtonAndBanner()

Expand Down Expand Up @@ -379,13 +379,13 @@ actor GroupCallActor: Sendable {

func joinState() -> GroupCallJoinState {
if state is Connected {
return .runningLocal
return .joined
}

if startJoining, state is Connecting || state is Joining {
return .joining
}
return .notRunningLocal
return .notJoined
}

func setIsChosenCall() -> Bool {
Expand Down Expand Up @@ -414,7 +414,25 @@ actor GroupCallActor: Sendable {
}

func setExactCallStartDate(_ exactCallStartDate: UInt64) {
self.exactCallStartDate = exactCallStartDate
exactCreationTimestamp = exactCallStartDate
}

/// Returns the the Date of`exactCreationTimestamp` or `.now` if it is nil
/// - Returns: Date of creation or now
func callStartDate() -> Date {
guard let millisecondsSinceStart = exactCreationTimestamp else {
return Date.now
}
return Date(timeIntervalSince1970: TimeInterval(millisecondsSinceStart / 1000))
}

func numberOfJoinedParticipants() -> Int {
if joinState() == .notJoined {
return sfuProvidedNumberOfParticipants
}
else {
return viewModel.numberOfParticipants
}
}

private func updateButtonAndBanner(hide: Bool = false) async {
Expand Down Expand Up @@ -509,10 +527,6 @@ extension GroupCallActor {
// MARK: View Model

extension GroupCallActor {

func getNumberOfParticipants() -> Int {
numberOfParticipants
}

func add(_ localParticipant: LocalParticipant) async {
self.localParticipant = localParticipant
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ extension GroupCallSessionDescription {
lines.append("a=rtcp-rsize")
}

// TODO: (IOS-4627) Investigate removing if below
// Add msid if remote participant
if type == .remote {
lines.append("a=msid:- \(mid)")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ struct Joining: GroupCallState {
return Ending(groupCallActor: groupCallActor)
}

// TODO: IOS-4090
await groupCallActor.setExactCallStartDate(joinResponse.startedAt)

DDLogNotice("[GroupCall] [JoinSteps] Start Connecting")
Expand Down
22 changes: 11 additions & 11 deletions GroupCalls/Sources/GroupCalls/GroupCallManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ extension GroupCallManager {
/// value (i.e. the most recently created call) as provided by the peek result.
for groupCall in thisGroupGroupCalls {
if currentlyChosenCall == nil {
if await groupCall.exactCallStartDate != nil {
if await groupCall.exactCreationTimestamp != nil {
currentlyChosenCall = groupCall
}
continue
Expand All @@ -586,34 +586,34 @@ extension GroupCallManager {
let msg =
"[GroupCall] This never happens because we always either set `currentlyChosenCall` above or call `continue`"
assertionFailure(msg)
DDLogError(msg)
DDLogError("\(msg)")
return nil
}

guard let currentStartDate = await innerChosenCall.exactCallStartDate else {
guard let currentCreationTimestamp = await innerChosenCall.exactCreationTimestamp else {
continue
}
guard let newStartDate = await groupCall.exactCallStartDate else {
guard let newStartCreationTimestamp = await groupCall.exactCreationTimestamp else {
continue
}

DDLogNotice(
"[GroupCall] [Periodic Refresh] [Peek Steps] Previously chosen call \(innerChosenCall.logIdentifier.prefix(5)) has start date \(currentStartDate)"
"[GroupCall] [Periodic Refresh] [Peek Steps] Previously chosen call \(innerChosenCall.logIdentifier.prefix(5)) has creation timestamp \(currentCreationTimestamp)"
)
DDLogNotice(
"[GroupCall] [Periodic Refresh] [Peek Steps] Potential new chosen call \(groupCall.logIdentifier.prefix(5)) has start date \(newStartDate)"
"[GroupCall] [Periodic Refresh] [Peek Steps] Potential new chosen call \(groupCall.logIdentifier.prefix(5)) has creation timestamp \(newStartCreationTimestamp)"
)

if currentStartDate < newStartDate {
if currentCreationTimestamp < newStartCreationTimestamp {
currentlyChosenCall = groupCall

DDLogNotice(
"[GroupCall] [Periodic Refresh] [Peek Steps] Choose call \(innerChosenCall.logIdentifier.prefix(5)) with start date \(newStartDate)"
"[GroupCall] [Periodic Refresh] [Peek Steps] Choose call \(innerChosenCall.logIdentifier.prefix(5)) with screation timestamp \(newStartCreationTimestamp)"
)
}
else {
DDLogNotice(
"[GroupCall] [Periodic Refresh] [Peek Steps] Choose call \(innerChosenCall.logIdentifier.prefix(5)) with start date \(currentStartDate)"
"[GroupCall] [Periodic Refresh] [Peek Steps] Choose call \(innerChosenCall.logIdentifier.prefix(5)) with creation timestamp \(currentCreationTimestamp)"
)
}
}
Expand Down Expand Up @@ -661,14 +661,14 @@ extension GroupCallManager {
currentlyJoiningOrJoinedCall = nil
DDLogNotice("[GroupCall] [Peek Steps] Stopping running call \(groupCall.logIdentifier.prefix(5))")

case .runningLocal:
case .joined:
wasParticipatingInCall = true
await groupCall.forceLeaveCall()
await remove(groupCall)
currentlyJoiningOrJoinedCall = nil
DDLogNotice("[GroupCall] [Peek Steps] Stopping joined call \(groupCall.logIdentifier.prefix(5))")

case .notRunningLocal:
case .notJoined:
continue
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ import ThreemaEssentials
public struct GroupCallBannerButtonUpdate: Sendable {
public let groupIdentity: GroupIdentity
public let numberOfParticipants: Int
// TODO: (IOS-4074) Make optional and possibly hide label in banner?
public let startDate: Date
public let joinState: GroupCallJoinState
public let hideComponent: Bool

init(actor: GroupCallActor, hideComponent: Bool) async {
self.groupIdentity = actor.group.groupIdentity
self.numberOfParticipants = await actor.viewModel.numberOfParticipants
self.startDate = await actor.viewModel.getCallStartDate()
self.numberOfParticipants = await actor.numberOfJoinedParticipants()
self.startDate = await actor.callStartDate() ?? .now
self.joinState = await actor.joinState()
self.hideComponent = hideComponent
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@

import Foundation

/// Simplified group call join state of local participant
public enum GroupCallJoinState: Sendable {
case notRunningLocal
/// ConnectionState is `Unjoined`, `Ending` or `Ended`
case notJoined
/// ConnectionState is `Connecting` or `Joining`
case joining
case runningLocal
/// ConnectionState is `Connected`
case joined
}
11 changes: 2 additions & 9 deletions GroupCalls/Sources/GroupCalls/UI/Models/GroupCallViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,6 @@ public final class GroupCallViewModel: Sendable {
}

// MARK: - Public functions

public func getCallStartDate() async -> Date {
guard let millisecondsSinceStart = await groupCallActor?.exactCallStartDate else {
return .now
}
return Date(timeIntervalSince1970: TimeInterval(millisecondsSinceStart / 1000))
}

func participant(for participantID: ParticipantID) -> ViewModelParticipant? {
participantsList.first { $0.participantID == participantID }
Expand Down Expand Up @@ -496,7 +489,7 @@ extension GroupCallViewModel {
return
}

guard await strongSelf.groupCallActor?.joinState() == .runningLocal else {
guard await strongSelf.groupCallActor?.joinState() == .joined else {
return
}

Expand All @@ -507,7 +500,7 @@ extension GroupCallViewModel {
}

let numberOfParticipants = strongSelf.numberOfParticipants
let timeInterval = await Date().timeIntervalSince(strongSelf.getCallStartDate())
let timeInterval = await Date().timeIntervalSince(strongSelf.groupCallActor?.callStartDate() ?? .now)

let update = GroupCallNavigationBarContentUpdate(
title: strongSelf.groupCallActor?.group.groupName,
Expand Down
8 changes: 4 additions & 4 deletions GroupCalls/Tests/GroupCallsTests/GroupCallManagerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -310,15 +310,15 @@ import XCTest
let chosenCall = try await groupCallManager.getCurrentlyChosenCall(from: groupCalls)

await print(
"Gold chosen call \(String(describing: goldChosenCall?.callID.bytes.hexEncodedString())) has start date \(String(describing: goldChosenCall?.exactCallStartDate))"
"Gold chosen call \(String(describing: goldChosenCall?.callID.bytes.hexEncodedString())) has start date \(String(describing: goldChosenCall?.exactCreationTimestamp))"
)
await print(
"Actual chosen call \(String(describing: chosenCall?.callID.bytes.hexEncodedString())) has start date \(String(describing: chosenCall?.exactCallStartDate))"
"Actual chosen call \(String(describing: chosenCall?.callID.bytes.hexEncodedString())) has start date \(String(describing: chosenCall?.exactCreationTimestamp))"
)

let chosenStartDate = await chosenCall!.exactCallStartDate!
let chosenStartDate = await chosenCall!.exactCreationTimestamp!
for groupCall in groupCalls {
let otherStartDate = await groupCall.exactCallStartDate!
let otherStartDate = await groupCall.exactCreationTimestamp!
print("\(otherStartDate) < \(chosenStartDate)")
let smaller = otherStartDate <= chosenStartDate
XCTAssertTrue(smaller)
Expand Down
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,10 @@ If you build the Threema OnPrem target, credentials from the [Threema OnPrem](ht
## <a name="schemes"></a>Schemes

- `Threema` builds and tests the consumer app. (recommended for local testing)
- `ThreemaWork` builds and tests the enterprise version of our app.
- `ThreemaOnPrem` builds and tests the OnPrem version of our app.
- `ThreemaRed` is only used for development and testing within Threema.
- `ThreemaRedWork` is only used for development and testing within Threema.
- `Threema Work` builds and tests the enterprise version of our app.
- `Threema OnPrem` builds and tests the OnPrem version of our app.
- `Threema Green` is only used for development and testing within Threema.
- `Threema Blue` is only used for development and testing within Threema.

## <a name="building"></a>Building

Expand Down Expand Up @@ -92,9 +92,9 @@ To get started you need a [Mac](https://www.apple.com/mac/), [Xcode](https://dev
rustup-init
```
(If you don't have [homebrew](https://brew.sh) see their [official install instructions](https://github.com/Carthage/Carthage#installing-carthage).)

(You might want to add $HOME/.cargo/bin to your PATH.)

4. Ensure that submodules are checked out

```sh
Expand All @@ -110,15 +110,15 @@ _Note_: These setups are for running in the simulator.
#### Threema (recommended)

1. Open `Threema.xcproject` in Xcode
2. Repeat these steps for the `Threema` and `ThreemaShareExtension` target
2. Repeat these steps for the `Threema` and `Threema ShareExtension` target
1. Check "Automatically manage signing" and confirm it ("Enable Automatic")
2. Set "Team" to the team of your developer account
3. Choose `Threema` as scheme and a simulator

#### Threema Work

1. Open `Threema.xcproject` in Xcode
2. Repeat these steps for the `Threema Work` and `ThreemaForWorkShareExtension` target
2. Repeat these steps for the `Threema Work` and `Threema Work ShareExtension` target
1. Check "Automatically manage signing" and confirm it ("Enable Automatic")
2. Set "Team" to the team of your developer account
3. Choose `Threema Work` as scheme and a simulator
Expand All @@ -135,7 +135,7 @@ See "Building" for setting up a running environment. Before running the tests ch

- Choose `Threema` as scheme to run the app tests.
- Choose `ThreemaFramework` as scheme to run the framework tests.
- Choose `ThreemaWork` as scheme to run Threema Work specific tests.
- Choose `Threema Work` as scheme to run Threema Work specific tests.


## <a name="reproducible-builds"></a>Reproducible Builds
Expand All @@ -151,7 +151,7 @@ These are the most important groups of the Xcode project:

- `ThreemaFramework`: Shared code between the main app and extensions
- `Threema`: Code of both apps (Threema and Threema Work)
- `ThreemaShareExtension`: Code of share extension
- `Threema ShareExtension`: Code of share extension
- `Threema{Framework}Tests`: Test files
- `GroupCalls`: Code of group calls

Expand All @@ -168,7 +168,7 @@ We accept GitHub pull requests. Please refer to <https://threema.ch/open-source/
Threema for iOS is licensed under the GNU Affero General Public License v3.

Copyright (c) 2012-2023 Threema GmbH

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License, version 3,
as published by the Free Software Foundation.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "Icon-App-iTunes 1.png",
"filename" : "icon-work-sandbox-1024-square.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "Threema OnPrem – WORK@1024.png",
"filename" : "icon-consumer-sandbox-1024-square.png",
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 1e9da0c

Please sign in to comment.