Commit c433b384 authored by Dariusz Rybicki's avatar Dariusz Rybicki
Browse files

Merge branch 'development' into 'main'

Release 1.0.0

See merge request !102
parents 0204cd87 f267e537
Pipeline #205536 passed with stage
in 3 minutes and 53 seconds
......@@ -7,3 +7,4 @@ DerivedData/
.swiftpm/config/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
/.build-bindings
before_script:
- echo $CI_BUILD_REF
- echo $CI_PROJECT_DIR
- echo $PWD
- swift --version
- xcodebuild -version
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- ssh-keyscan -t rsa $GITLAB_SERVER > ~/.ssh/known_hosts
stages:
- test
test-package-macos:
stage: test
tags:
- ios
script:
- ./run-tests.sh macos
retry: 1
test-package-ios:
stage: test
tags:
- ios
script:
- ./run-tests.sh ios
retry: 1
test-examples-ios:
stage: test
tags:
- ios
script:
- ./run-tests.sh examples-ios
retry: 1
......@@ -14,9 +14,9 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "ErrorFeature"
BuildableName = "ErrorFeature"
BlueprintName = "ErrorFeature"
BlueprintIdentifier = "XXClient"
BuildableName = "XXClient"
BlueprintName = "XXClient"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
......@@ -33,9 +33,9 @@
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "ErrorFeatureTests"
BuildableName = "ErrorFeatureTests"
BlueprintName = "ErrorFeatureTests"
BlueprintIdentifier = "XXClientTests"
BuildableName = "XXClientTests"
BlueprintName = "XXClientTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
......@@ -61,9 +61,9 @@
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "ErrorFeature"
BuildableName = "ErrorFeature"
BlueprintName = "ErrorFeature"
BlueprintIdentifier = "XXClient"
BuildableName = "XXClient"
BlueprintName = "XXClient"
ReferencedContainer = "container:">
</BuildableReference>
</MacroExpansion>
......
......@@ -14,9 +14,9 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "MyIdentityFeature"
BuildableName = "MyIdentityFeature"
BlueprintName = "MyIdentityFeature"
BlueprintIdentifier = "XXMessengerClient"
BuildableName = "XXMessengerClient"
BlueprintName = "XXMessengerClient"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
......@@ -33,9 +33,9 @@
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "MyIdentityFeatureTests"
BuildableName = "MyIdentityFeatureTests"
BlueprintName = "MyIdentityFeatureTests"
BlueprintIdentifier = "XXMessengerClientTests"
BuildableName = "XXMessengerClientTests"
BlueprintName = "XXMessengerClientTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
......@@ -61,9 +61,9 @@
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "MyIdentityFeature"
BuildableName = "MyIdentityFeature"
BlueprintName = "MyIdentityFeature"
BlueprintIdentifier = "XXMessengerClient"
BuildableName = "XXMessengerClient"
BlueprintName = "XXMessengerClient"
ReferencedContainer = "container:">
</BuildableReference>
</MacroExpansion>
......
......@@ -14,23 +14,51 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "ElixxirDAppsSDK"
BuildableName = "ElixxirDAppsSDK"
BlueprintName = "ElixxirDAppsSDK"
BlueprintIdentifier = "XXClient"
BuildableName = "XXClient"
BlueprintName = "XXClient"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "XXMessengerClient"
BuildableName = "XXMessengerClient"
BlueprintName = "XXMessengerClient"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "NO"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
buildForAnalyzing = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "ElixxirDAppsSDKTests"
BuildableName = "ElixxirDAppsSDKTests"
BlueprintName = "ElixxirDAppsSDKTests"
BlueprintIdentifier = "XXClientTests"
BuildableName = "XXClientTests"
BlueprintName = "XXClientTests"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "NO"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "XXMessengerClientTests"
BuildableName = "XXMessengerClientTests"
BlueprintName = "XXMessengerClientTests"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
......@@ -47,9 +75,19 @@
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "ElixxirDAppsSDKTests"
BuildableName = "ElixxirDAppsSDKTests"
BlueprintName = "ElixxirDAppsSDKTests"
BlueprintIdentifier = "XXClientTests"
BuildableName = "XXClientTests"
BlueprintName = "XXClientTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "XXMessengerClientTests"
BuildableName = "XXMessengerClientTests"
BlueprintName = "XXMessengerClientTests"
ReferencedContainer = "container:">
</BuildableReference>
</TestableReference>
......@@ -75,9 +113,9 @@
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "ElixxirDAppsSDK"
BuildableName = "ElixxirDAppsSDK"
BlueprintName = "ElixxirDAppsSDK"
BlueprintIdentifier = "XXClient"
BuildableName = "XXClient"
BlueprintName = "XXClient"
ReferencedContainer = "container:">
</BuildableReference>
</MacroExpansion>
......
# XXClient Quick Start Guide
Add `XXClient` library as a dependency to your project using Swift Package Manager.
## ▶️ Instantiating cMix
You can use a convenient `CMixManager` wrapper to manage cMix stored on disk:
```swift
let cMixManager: CMixManager = .live(
passwordStorage: .init(
save: { password in
// securely save provided password
},
load: {
// load securely stored password
}
)
)
let cMix: CMix
if cMixManager.hasStorage() {
cMix = try cMixManager.load()
} else {
cMix = try cMixManager.create()
}
```
Check out included example iOS application for the `PasswordStorage` implementation that uses the iOS keychain.
## ▶️ Connecting to the network
Start network follower:
```swift
try cMix.startNetworkFollower(timeoutMS: 10_000)
```
Wait until connected:
```swift
let isNetworkHealthy = try cMix.waitForNetwork(timeoutMS: 30_000)
```
## ▶️ Making a new reception identity
Use the cMix to make a new reception identity:
```swift
let myIdentity = try cMix.makeReceptionIdentity()
```
## ▶️ Create new E2E
```swift
let login: Login = .live
let e2e = try login(
cMixId: cMix.getId(),
identity: myIdentity
)
```
## ▶️ Connecting to remote
Perform auth key negotiation with the given recipient to get the `Connection`:
```swift
let connection = try cMix.connect(
withAuthentication: false,
e2eId: e2e.getId(),
recipientContact: ...
)
```
Pass `true` for the `withAuthentication` parameter if you want to prove id ownership to remote as well.
## ▶️ Sending messages
Send a message to the connection's partner:
```swift
let sendReport = try connection.send(
messageType: 1,
payload: ...
)
```
Check if the round succeeded:
```swift
try cMix.waitForRoundResult(
roundList: try sendReport.encode(),
timeoutMS: 30_000,
callback: .init { result in
switch result {
case .delivered(let roundResults):
...
case .notDelivered(let timedOut):
...
}
}
)
```
## ▶️ Receiving messages
Use connection's message listener to receive messages from partner:
```swift
try connection.registerListener(
messageType: 1,
listener: .init { message in
...
}
)
```
\ No newline at end of file
# XXMessengerClient
`XXMessengerClient` is a client wrapper library for use in xx-messenger application.
## ▶️ Instantiate messenger
### Example
```swift
// setup environment:
var environment: MessengerEnvironment = .live()
// change cMix NDF environment if needed:
environment.ndfEnvironment = ...
// use alternative user-discovery if needed:
environment.udAddress = ...
environment.udCert = ...
environment.udContact = ...
// instantiate messenger:
let messenger: Messenger = .live(environment)
```
## 🚀 Start messenger
### Example
```swift
// allow cancellation of callbacks:
var authCallbacksCancellable: Cancellable?
var messageListenerCancellable: Cancellable?
func start(messenger: Messenger) throws {
// check if messenger is loaded:
if messenger.isLoaded() == false {
// check if messenger is created and stored on disk:
if messenger.isCreated() == false {
// create new messenger and store it on disk:
try messenger.create()
}
// load messenger stored on disk:
try messenger.load()
}
// start messenger's network follower:
try messenger.start()
// register auth callbacks before connecting:
authCallbacksCancellable = messenger.registerAuthCallbacks(
AuthCallbacks(handle: { callback in
// implement auth callbacks handling
})
)
// register message listener before connecting:
messageListenerCancellable = messenger.registerMessageListener(
Listener(handle: { message in
// handle incoming message
})
)
// check if messenger is connected:
if messenger.isConnected() == false {
// start end-to-end connection:
try messenger.connect()
// start listening for messanges:
try messener.listenForMessages()
}
// check if messenger is logged in with user-discovery:
if messenger.isLoggedIn() == false {
// check if messenger is registered with user-discovery:
if try messenger.isRegistered() == false {
// register new user with user-discovery:
try messenger.register(username: "new-username")
} else {
// login previously registered user with user-discovery:
try messenger.logIn()
}
}
}
```
## 🛠 Use client components directly
### Example
```swift
// get cMix:
let cMix = messenger.cMix()
// get E2E:
let e2e = messenger.e2e()
// get UserDicovery:
let ud = messenger.ud()
// get Backup:
let backup = messenger.backup()
// get GroupChat
let groupChat = messenger.groupChat()
```
## 💾 Backup
### Make backup
```swift
// start receiving backup data before starting or resuming backup:
let cancellable = messenger.registerBackupCallback(.init { data in
// handle backup data, save on disk, upload to cloud, etc.
})
// check if backup is already running:
if messenger.isBackupRunning() == false {
do {
// try to resume previous backup:
try messenger.resumeBackup()
} catch {
// try to start a new backup:
let params: BackupParams = ...
try messenger.startBackup(
password: "backup-passphrase",
params: params
)
}
}
// update params in the backup:
let params: BackupParams = ...
try messenger.backupParams(params)
// stop the backup:
try messenger.stopBackup()
// optionally stop receiving backup data
cancellable.cancel()
```
When starting a new backup you must provide `BackupParams` to prevent creating backups that does not contain it.
The registered backup callback can be reused later when a new backup is started. There is no need to cancel it and register a new callback in such a case.
### Restore from backup
```swift
let result = try messenger.restoreBackup(
backupData: ...,
backupPassphrase: "backup-passphrase"
)
// handle restoration result:
let restoredUsername = result.restoredParams.username
let facts = try messenger.ud.tryGet().getFacts()
let restoredEmail = facts.get(.email)?.value
let restoredPhone = facts.get(.phone)?.value
```
If no error was thrown during restoration, the `Messenger` is already loaded, started, connected, and logged in.
## 🚢 File transfers
### Setup for receiving files
```swift
// register receive file callback before starting file transfer manager:
let cancellable = messenger.registerReceiveFileCallback(.init { result in
switch result {
case .success(let receivedFile):
// handle file metadata...
// start receiving file data:
try! messenger.receiveFile(.init(transferId: receivedFile.transferId)) { info in
switch info {
case .progress(let transmitted, let total):
// handle progress...
case .finished(let data):
// handle received file data...
case .failed(let error):
// handle error...
}
}
case .failure(let error):
// handle error...
}
})
// start file transfer manager:
try messenger.startFileTransfer()
```
### Send files
Make sure to call `messenger.startFileTransfer` before sending files.
```swift
let file = FileSend(
name: ...,
type: ...,
preview: ...,
contents: ...
)
// send file:
let transferId = try messenger.sendFile(.init(file: file, recipientId: ...)) { info in
switch info {
case .progress(let transferId, let transmitted, let total):
// handle progress...
case .finished(let transferId):
// handle completion...
case .failed(let transferId, let error):
// handle error...
}
}
```
## 💬 Group Chat
### Setup
```swift
// register callbacks:
let groupRequestsCancellable = messenger.registerGroupRequestHandler(.init { group in
// handle group request...
})
let groupChatProcessorCancellable = messenger.registerGroupChatProcessor(.init { result in
switch result {
case .success(let callback):
// handle group chat processor callback...
case .failure(let error):
// handle error...
}
})
// start group chat manager:
try messenger.startGroupChat()
```
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key>
<false/>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1340"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "312C371528475E62003E9E39"
BuildableName = "dApps Example.app"
BlueprintName = "ExampleApp (iOS)"
ReferencedContainer = "container:Example.xcodeproj">
</BuildableReference>
</BuildActionEntry>