mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-28 23:32:41 +00:00
Merge branch 'release/1.9.16/master'
This commit is contained in:
commit
ae87624614
184 changed files with 2523 additions and 690 deletions
16
.github/workflows/release-alpha.yml
vendored
16
.github/workflows/release-alpha.yml
vendored
|
@ -13,22 +13,10 @@ env:
|
||||||
MX_GIT_BRANCH: ${{ github.event.pull_request.head.ref }}
|
MX_GIT_BRANCH: ${{ github.event.pull_request.head.ref }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-secret:
|
|
||||||
runs-on: macos-12
|
|
||||||
outputs:
|
|
||||||
out-key: ${{ steps.out-key.outputs.defined }}
|
|
||||||
steps:
|
|
||||||
- id: out-key
|
|
||||||
env:
|
|
||||||
P12_KEY: ${{ secrets.ALPHA_CERTIFICATES_P12 }}
|
|
||||||
P12_PASSWORD_KEY: ${{ secrets.ALPHA_CERTIFICATES_P12 }}
|
|
||||||
if: "${{ env.P12_KEY != '' || env.P12_PASSWORD_KEY != '' }}"
|
|
||||||
run: echo "::set-output name=defined::true"
|
|
||||||
build:
|
build:
|
||||||
# Run job if secrets are available (not available for forks).
|
# Don't run for forks as secrets are unavailable.
|
||||||
needs: [check-secret]
|
|
||||||
if: |
|
if: |
|
||||||
needs.check-secret.outputs.out-key == 'true' &&
|
github.event.pull_request.head.repo.full_name == github.repository &&
|
||||||
(github.event_name == 'push' ||
|
(github.event_name == 'push' ||
|
||||||
(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'Trigger-PR-Build')))
|
(github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'Trigger-PR-Build')))
|
||||||
|
|
||||||
|
|
40
CHANGES.md
40
CHANGES.md
|
@ -1,3 +1,43 @@
|
||||||
|
## Changes in 1.9.16 (2023-01-24)
|
||||||
|
|
||||||
|
✨ Features
|
||||||
|
|
||||||
|
- Rich Text Composer: Enable bulleted/numbered lists support ([#7238](https://github.com/vector-im/element-ios/issues/7238))
|
||||||
|
- Rich Text Composer: Enable quote & code blocks support ([#7271](https://github.com/vector-im/element-ios/issues/7271))
|
||||||
|
- Voice Broadcast: When deleting a voice broadcast, all data is now deleted on server side (MSC3912 implementation). ([#7283](https://github.com/vector-im/element-ios/issues/7283))
|
||||||
|
|
||||||
|
🙌 Improvements
|
||||||
|
|
||||||
|
- Labs: VoiceBroadcast: Handle VoIP buttons when VB is used ([#7225](https://github.com/vector-im/element-ios/pull/7225))
|
||||||
|
- Polls: add UI for active poll history. ([#7267](https://github.com/vector-im/element-ios/pull/7267))
|
||||||
|
- CryptoSDK: Add labs settings to enable Crypto SDK ([#7272](https://github.com/vector-im/element-ios/pull/7272))
|
||||||
|
- Voice Broadcast: Improved detection of voice broadcast completion during playback. ([#7273](https://github.com/vector-im/element-ios/pull/7273))
|
||||||
|
- Remove "Leave" button on Room details screen ([#7275](https://github.com/vector-im/element-ios/pull/7275))
|
||||||
|
- Polls: poll history UI for past polls. ([#7278](https://github.com/vector-im/element-ios/pull/7278))
|
||||||
|
- Polls: render replies to poll events better. ([#7284](https://github.com/vector-im/element-ios/pull/7284))
|
||||||
|
- CryptoV2: Display migration progress during startup ([#7286](https://github.com/vector-im/element-ios/pull/7286))
|
||||||
|
- Upgrade MatrixSDK version ([v0.24.8](https://github.com/matrix-org/matrix-ios-sdk/releases/tag/v0.24.8)).
|
||||||
|
- Voice broadcast connection error handling while recording. ([#7229](https://github.com/vector-im/element-ios/issues/7229))
|
||||||
|
- Handle a connection issue when we try to start a new voice broadcast. ([#7234](https://github.com/vector-im/element-ios/issues/7234))
|
||||||
|
- Rich Text Editor: https:// or mailto: scheme is automatically added when creating a link if no scheme is specified. ([#7279](https://github.com/vector-im/element-ios/issues/7279))
|
||||||
|
- Rich Text Editor: Adding a link over a blank selection, prompts the user to create a new link with new text to replace such selection. ([#7280](https://github.com/vector-im/element-ios/issues/7280))
|
||||||
|
- Voice Broadcast: handle the lost of connectivity with the homeserver while recording. ([#7285](https://github.com/vector-im/element-ios/issues/7285))
|
||||||
|
|
||||||
|
🐛 Bugfixes
|
||||||
|
|
||||||
|
- Voice Broadcast: The Now Playing Info Center now displays a voice broadcast instead of a voice message when a user is listening to a voice broadcast. ([#7257](https://github.com/vector-im/element-ios/pull/7257))
|
||||||
|
- Fix a crash caused by the missing Avatar Service dependency. ([#7268](https://github.com/vector-im/element-ios/pull/7268))
|
||||||
|
- The (edited) tag for messages is now light grey like on web and Android. ([#5148](https://github.com/vector-im/element-ios/issues/5148))
|
||||||
|
- Live Location Sharing does not work on first selection after granting "Allow always" location permission. ([#7222](https://github.com/vector-im/element-ios/issues/7222))
|
||||||
|
- Voice Broadcast: Fixed an issue where the voice broadcast audio player progress bar behaved unexpectedly. ([#7252](https://github.com/vector-im/element-ios/issues/7252))
|
||||||
|
- Voice Broadcast: VoiceBroadcast chunks are no longer resent as voice messages ([#7261](https://github.com/vector-im/element-ios/issues/7261))
|
||||||
|
- Timeline's links and hyperlinks match now the blue colour of Android and Web. ([#7263](https://github.com/vector-im/element-ios/issues/7263))
|
||||||
|
|
||||||
|
🧱 Build
|
||||||
|
|
||||||
|
- Fix Element Alpha workflow not being able to run. ([#7256](https://github.com/vector-im/element-ios/pull/7256))
|
||||||
|
|
||||||
|
|
||||||
## Changes in 1.9.15 (2023-01-10)
|
## Changes in 1.9.15 (2023-01-10)
|
||||||
|
|
||||||
✨ Features
|
✨ Features
|
||||||
|
|
|
@ -15,5 +15,5 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
// Version
|
// Version
|
||||||
MARKETING_VERSION = 1.9.15
|
MARKETING_VERSION = 1.9.16
|
||||||
CURRENT_PROJECT_VERSION = 1.9.15
|
CURRENT_PROJECT_VERSION = 1.9.16
|
||||||
|
|
|
@ -399,6 +399,7 @@ final class BuildSettings: NSObject {
|
||||||
// MARK: - Polls
|
// MARK: - Polls
|
||||||
|
|
||||||
static let pollsEnabled = true
|
static let pollsEnabled = true
|
||||||
|
static var pollsHistoryEnabled: Bool = false
|
||||||
|
|
||||||
// MARK: - Location Sharing
|
// MARK: - Location Sharing
|
||||||
|
|
||||||
|
|
|
@ -91,6 +91,12 @@ class CommonConfiguration: NSObject, Configurable {
|
||||||
MXKeyProvider.sharedInstance().delegate = EncryptionKeyManager.shared
|
MXKeyProvider.sharedInstance().delegate = EncryptionKeyManager.shared
|
||||||
|
|
||||||
sdkOptions.enableNewClientInformationFeature = RiotSettings.shared.enableClientInformationFeature
|
sdkOptions.enableNewClientInformationFeature = RiotSettings.shared.enableClientInformationFeature
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
if sdkOptions.isCryptoSDKAvailable {
|
||||||
|
sdkOptions.enableCryptoSDK = RiotSettings.shared.enableCryptoSDK
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private func makeASCIIUserAgent() -> String? {
|
private func makeASCIIUserAgent() -> String? {
|
||||||
|
|
|
@ -48,5 +48,7 @@ public struct ColorValues: Colors {
|
||||||
|
|
||||||
public let ems: UIColor
|
public let ems: UIColor
|
||||||
|
|
||||||
|
public let links: UIColor
|
||||||
|
|
||||||
public let namesAndAvatars: [UIColor]
|
public let namesAndAvatars: [UIColor]
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,10 @@ public protocol Colors {
|
||||||
/// Global color: The EMS brand's purple colour.
|
/// Global color: The EMS brand's purple colour.
|
||||||
var ems: ColorType { get }
|
var ems: ColorType { get }
|
||||||
|
|
||||||
|
/// - Links
|
||||||
|
/// - Hyperlinks
|
||||||
|
var links: ColorType { get }
|
||||||
|
|
||||||
/// - Names in chat timeline
|
/// - Names in chat timeline
|
||||||
/// - Avatars default states that include first name letter
|
/// - Avatars default states that include first name letter
|
||||||
var namesAndAvatars: [ColorType] { get }
|
var namesAndAvatars: [ColorType] { get }
|
||||||
|
|
|
@ -21,7 +21,7 @@ import SwiftUI
|
||||||
Struct for holding colors for use in SwiftUI.
|
Struct for holding colors for use in SwiftUI.
|
||||||
*/
|
*/
|
||||||
public struct ColorSwiftUI: Colors {
|
public struct ColorSwiftUI: Colors {
|
||||||
|
|
||||||
public let accent: Color
|
public let accent: Color
|
||||||
|
|
||||||
public let alert: Color
|
public let alert: Color
|
||||||
|
@ -48,8 +48,10 @@ public struct ColorSwiftUI: Colors {
|
||||||
|
|
||||||
public var ems: Color
|
public var ems: Color
|
||||||
|
|
||||||
public let namesAndAvatars: [Color]
|
public let links: Color
|
||||||
|
|
||||||
|
public let namesAndAvatars: [Color]
|
||||||
|
|
||||||
init(values: ColorValues) {
|
init(values: ColorValues) {
|
||||||
accent = Color(values.accent)
|
accent = Color(values.accent)
|
||||||
alert = Color(values.alert)
|
alert = Color(values.alert)
|
||||||
|
@ -64,6 +66,7 @@ public struct ColorSwiftUI: Colors {
|
||||||
navigation = Color(values.navigation)
|
navigation = Color(values.navigation)
|
||||||
background = Color(values.background)
|
background = Color(values.background)
|
||||||
ems = Color(values.ems)
|
ems = Color(values.ems)
|
||||||
|
links = Color(values.links)
|
||||||
namesAndAvatars = values.namesAndAvatars.map({ Color($0) })
|
namesAndAvatars = values.namesAndAvatars.map({ Color($0) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,8 @@ import UIKit
|
||||||
public let navigation: UIColor
|
public let navigation: UIColor
|
||||||
|
|
||||||
public let background: UIColor
|
public let background: UIColor
|
||||||
|
|
||||||
|
public let links: UIColor
|
||||||
|
|
||||||
public let namesAndAvatars: [UIColor]
|
public let namesAndAvatars: [UIColor]
|
||||||
|
|
||||||
|
@ -61,6 +63,7 @@ import UIKit
|
||||||
tile = values.tile
|
tile = values.tile
|
||||||
navigation = values.navigation
|
navigation = values.navigation
|
||||||
background = values.background
|
background = values.background
|
||||||
|
links = values.links
|
||||||
namesAndAvatars = values.namesAndAvatars
|
namesAndAvatars = values.namesAndAvatars
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ public class DarkColors {
|
||||||
navigation: UIColor(rgb:0x21262C),
|
navigation: UIColor(rgb:0x21262C),
|
||||||
background: UIColor(rgb:0x15191E),
|
background: UIColor(rgb:0x15191E),
|
||||||
ems: UIColor(rgb: 0x7E69FF),
|
ems: UIColor(rgb: 0x7E69FF),
|
||||||
|
links: UIColor(rgb: 0x0086E6),
|
||||||
namesAndAvatars: [
|
namesAndAvatars: [
|
||||||
UIColor(rgb:0x368BD6),
|
UIColor(rgb:0x368BD6),
|
||||||
UIColor(rgb:0xAC3BA8),
|
UIColor(rgb:0xAC3BA8),
|
||||||
|
|
|
@ -35,6 +35,7 @@ public class LightColors {
|
||||||
navigation: UIColor(rgb:0xF4F6FA),
|
navigation: UIColor(rgb:0xF4F6FA),
|
||||||
background: UIColor(rgb:0xFFFFFF),
|
background: UIColor(rgb:0xFFFFFF),
|
||||||
ems: UIColor(rgb: 0x7E69FF),
|
ems: UIColor(rgb: 0x7E69FF),
|
||||||
|
links: UIColor(rgb: 0x0086E6),
|
||||||
namesAndAvatars: [
|
namesAndAvatars: [
|
||||||
UIColor(rgb:0x368BD6),
|
UIColor(rgb:0x368BD6),
|
||||||
UIColor(rgb:0xAC3BA8),
|
UIColor(rgb:0xAC3BA8),
|
||||||
|
|
2
Podfile
2
Podfile
|
@ -16,7 +16,7 @@ use_frameworks!
|
||||||
# - `{ :specHash => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for MatrixSDK repo. Used by Fastfile during CI
|
# - `{ :specHash => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for MatrixSDK repo. Used by Fastfile during CI
|
||||||
#
|
#
|
||||||
# Warning: our internal tooling depends on the name of this variable name, so be sure not to change it
|
# Warning: our internal tooling depends on the name of this variable name, so be sure not to change it
|
||||||
$matrixSDKVersion = '= 0.24.7'
|
$matrixSDKVersion = '= 0.24.8'
|
||||||
# $matrixSDKVersion = :local
|
# $matrixSDKVersion = :local
|
||||||
# $matrixSDKVersion = { :branch => 'develop'}
|
# $matrixSDKVersion = { :branch => 'develop'}
|
||||||
# $matrixSDKVersion = { :specHash => { git: 'https://git.io/fork123', branch: 'fix' } }
|
# $matrixSDKVersion = { :specHash => { git: 'https://git.io/fork123', branch: 'fix' } }
|
||||||
|
|
26
Podfile.lock
26
Podfile.lock
|
@ -55,9 +55,9 @@ PODS:
|
||||||
- LoggerAPI (1.9.200):
|
- LoggerAPI (1.9.200):
|
||||||
- Logging (~> 1.1)
|
- Logging (~> 1.1)
|
||||||
- Logging (1.4.0)
|
- Logging (1.4.0)
|
||||||
- MatrixSDK (0.24.7):
|
- MatrixSDK (0.24.8):
|
||||||
- MatrixSDK/Core (= 0.24.7)
|
- MatrixSDK/Core (= 0.24.8)
|
||||||
- MatrixSDK/Core (0.24.7):
|
- MatrixSDK/Core (0.24.8):
|
||||||
- AFNetworking (~> 4.0.0)
|
- AFNetworking (~> 4.0.0)
|
||||||
- GZIP (~> 1.3.0)
|
- GZIP (~> 1.3.0)
|
||||||
- libbase58 (~> 0.1.4)
|
- libbase58 (~> 0.1.4)
|
||||||
|
@ -65,12 +65,12 @@ PODS:
|
||||||
- OLMKit (~> 3.2.5)
|
- OLMKit (~> 3.2.5)
|
||||||
- Realm (= 10.27.0)
|
- Realm (= 10.27.0)
|
||||||
- SwiftyBeaver (= 1.9.5)
|
- SwiftyBeaver (= 1.9.5)
|
||||||
- MatrixSDK/CryptoSDK (0.24.7):
|
- MatrixSDK/CryptoSDK (0.24.8):
|
||||||
- MatrixSDKCrypto (= 0.1.7)
|
- MatrixSDKCrypto (= 0.1.8)
|
||||||
- MatrixSDK/JingleCallStack (0.24.7):
|
- MatrixSDK/JingleCallStack (0.24.8):
|
||||||
- JitsiMeetSDK (= 5.0.2)
|
- JitsiMeetSDK (= 5.0.2)
|
||||||
- MatrixSDK/Core
|
- MatrixSDK/Core
|
||||||
- MatrixSDKCrypto (0.1.7)
|
- MatrixSDKCrypto (0.1.8)
|
||||||
- OLMKit (3.2.12):
|
- OLMKit (3.2.12):
|
||||||
- OLMKit/olmc (= 3.2.12)
|
- OLMKit/olmc (= 3.2.12)
|
||||||
- OLMKit/olmcpp (= 3.2.12)
|
- OLMKit/olmcpp (= 3.2.12)
|
||||||
|
@ -122,8 +122,8 @@ DEPENDENCIES:
|
||||||
- KeychainAccess (~> 4.2.2)
|
- KeychainAccess (~> 4.2.2)
|
||||||
- KTCenterFlowLayout (~> 1.3.1)
|
- KTCenterFlowLayout (~> 1.3.1)
|
||||||
- libPhoneNumber-iOS (~> 0.9.13)
|
- libPhoneNumber-iOS (~> 0.9.13)
|
||||||
- MatrixSDK (= 0.24.7)
|
- MatrixSDK (= 0.24.8)
|
||||||
- MatrixSDK/JingleCallStack (= 0.24.7)
|
- MatrixSDK/JingleCallStack (= 0.24.8)
|
||||||
- OLMKit
|
- OLMKit
|
||||||
- PostHog (~> 1.4.4)
|
- PostHog (~> 1.4.4)
|
||||||
- ReadMoreTextView (~> 3.0.1)
|
- ReadMoreTextView (~> 3.0.1)
|
||||||
|
@ -197,7 +197,7 @@ CHECKOUT OPTIONS:
|
||||||
:git: https://github.com/matrix-org/matrix-analytics-events.git
|
:git: https://github.com/matrix-org/matrix-analytics-events.git
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
AFNetworking: 7864c38297c79aaca1500c33288e429c3451fdce
|
AFNetworking: 3bd23d814e976cd148d7d44c3ab78017b744cd58
|
||||||
AnalyticsEvents: 0cc8cf52da2fd464a2f39b788a295988151116ce
|
AnalyticsEvents: 0cc8cf52da2fd464a2f39b788a295988151116ce
|
||||||
BlueCryptor: b0aee3d9b8f367b49b30de11cda90e1735571c24
|
BlueCryptor: b0aee3d9b8f367b49b30de11cda90e1735571c24
|
||||||
BlueECC: 0d18e93347d3ec6d41416de21c1ffa4d4cd3c2cc
|
BlueECC: 0d18e93347d3ec6d41416de21c1ffa4d4cd3c2cc
|
||||||
|
@ -220,8 +220,8 @@ SPEC CHECKSUMS:
|
||||||
libPhoneNumber-iOS: 0a32a9525cf8744fe02c5206eb30d571e38f7d75
|
libPhoneNumber-iOS: 0a32a9525cf8744fe02c5206eb30d571e38f7d75
|
||||||
LoggerAPI: ad9c4a6f1e32f518fdb43a1347ac14d765ab5e3d
|
LoggerAPI: ad9c4a6f1e32f518fdb43a1347ac14d765ab5e3d
|
||||||
Logging: beeb016c9c80cf77042d62e83495816847ef108b
|
Logging: beeb016c9c80cf77042d62e83495816847ef108b
|
||||||
MatrixSDK: 895929fad10b7ec9aa96d557403b44c5e3522211
|
MatrixSDK: cf1c1b2a9742f7f4fad21e94bd94cd8f13c47369
|
||||||
MatrixSDKCrypto: 2bd9ca41b2c644839f4e680a64897d56b3f95392
|
MatrixSDKCrypto: 862d9b4dbb6861da030943f5a18c39258ed7345b
|
||||||
OLMKit: da115f16582e47626616874e20f7bb92222c7a51
|
OLMKit: da115f16582e47626616874e20f7bb92222c7a51
|
||||||
PostHog: 4b6321b521569092d4ef3a02238d9435dbaeb99f
|
PostHog: 4b6321b521569092d4ef3a02238d9435dbaeb99f
|
||||||
ReadMoreTextView: 19147adf93abce6d7271e14031a00303fe28720d
|
ReadMoreTextView: 19147adf93abce6d7271e14031a00303fe28720d
|
||||||
|
@ -241,6 +241,6 @@ SPEC CHECKSUMS:
|
||||||
zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c
|
zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c
|
||||||
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb
|
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb
|
||||||
|
|
||||||
PODFILE CHECKSUM: 56782e2abd382278b3c5b23824ca74994fd0a97e
|
PODFILE CHECKSUM: 079b57b800c666ad864e1f059ae69e150a98a4f0
|
||||||
|
|
||||||
COCOAPODS: 1.11.3
|
COCOAPODS: 1.11.3
|
||||||
|
|
|
@ -23,7 +23,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/matrix-org/matrix-wysiwyg-composer-swift",
|
"location" : "https://github.com/matrix-org/matrix-wysiwyg-composer-swift",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "534ee5bae5e8de69ed398937b5edb7b5f21551d2"
|
"revision" : "6927cb878376136c4a03d919b689af8dfbdad080",
|
||||||
|
"version" : "0.19.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
23
Riot/Assets/Images.xcassets/Composer/code_block.imageset/Contents.json
vendored
Normal file
23
Riot/Assets/Images.xcassets/Composer/code_block.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "code_block.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "code_block@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "code_block@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
Riot/Assets/Images.xcassets/Composer/code_block.imageset/code_block.png
vendored
Normal file
BIN
Riot/Assets/Images.xcassets/Composer/code_block.imageset/code_block.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 493 B |
BIN
Riot/Assets/Images.xcassets/Composer/code_block.imageset/code_block@2x.png
vendored
Normal file
BIN
Riot/Assets/Images.xcassets/Composer/code_block.imageset/code_block@2x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 649 B |
BIN
Riot/Assets/Images.xcassets/Composer/code_block.imageset/code_block@3x.png
vendored
Normal file
BIN
Riot/Assets/Images.xcassets/Composer/code_block.imageset/code_block@3x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 953 B |
12
Riot/Assets/Images.xcassets/Room/pollHistory.imageset/Contents.json
vendored
Normal file
12
Riot/Assets/Images.xcassets/Room/pollHistory.imageset/Contents.json
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "pollHistory.svg",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
3
Riot/Assets/Images.xcassets/Room/pollHistory.imageset/pollHistory.svg
vendored
Normal file
3
Riot/Assets/Images.xcassets/Room/pollHistory.imageset/pollHistory.svg
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.5 2C10.2239 2 10 2.22386 10 2.5V22H14V2.5C14 2.22386 13.7761 2 13.5 2H10.5ZM3 9.5C3 9.22386 3.22386 9 3.5 9H6.5C6.77614 9 7 9.22386 7 9.5V22H3V9.5ZM17 13.5C17 13.2239 17.2239 13 17.5 13H20.5C20.7761 13 21 13.2239 21 13.5V22H17V13.5Z" fill="#8D97A5"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 407 B |
|
@ -455,7 +455,7 @@
|
||||||
"sign_up" = "الاِشتِراك";
|
"sign_up" = "الاِشتِراك";
|
||||||
"dismiss" = "إبعَاد";
|
"dismiss" = "إبعَاد";
|
||||||
"discard" = "اِستِبعاد";
|
"discard" = "اِستِبعاد";
|
||||||
"abort" = "إِجهَاض";
|
"abort" = "إنهاء";
|
||||||
"yes" = "نَعَم";
|
"yes" = "نَعَم";
|
||||||
|
|
||||||
// Action
|
// Action
|
||||||
|
@ -1078,3 +1078,8 @@
|
||||||
/* The placeholder will show the email address that was entered. */
|
/* The placeholder will show the email address that was entered. */
|
||||||
"authentication_verify_email_waiting_message" = "اتبع التعليمات المرسلة إلى %@";
|
"authentication_verify_email_waiting_message" = "اتبع التعليمات المرسلة إلى %@";
|
||||||
"invite_to" = "الدعوة إلى %@";
|
"invite_to" = "الدعوة إلى %@";
|
||||||
|
"password_policy_pwd_in_dict_error" = "تم العثور على كلمة المرور هذه في القاموس لدينا، وهي كلمة مرور غير مسموح في استخدامها.";
|
||||||
|
|
||||||
|
// Others
|
||||||
|
"or" = "أو";
|
||||||
|
"accessibility_selected" = "تم تحديده";
|
||||||
|
|
|
@ -2700,5 +2700,34 @@
|
||||||
"notice_voice_broadcast_live" = "Echtzeitübertragung";
|
"notice_voice_broadcast_live" = "Echtzeitübertragung";
|
||||||
"user_other_session_security_recommendation_title" = "Andere Sitzungen";
|
"user_other_session_security_recommendation_title" = "Andere Sitzungen";
|
||||||
"voice_message_broadcast_in_progress_title" = "Kann Sprachnachricht nicht beginnen";
|
"voice_message_broadcast_in_progress_title" = "Kann Sprachnachricht nicht beginnen";
|
||||||
"poll_timeline_decryption_error" = "Aufgrund von Entschlüsselungsfehlern könnten einige Stimmen nicht gezählt werden";
|
"poll_timeline_decryption_error" = "Evtl. werden infolge von Entschlüsselungsfehlern einige Stimmen nicht gezählt";
|
||||||
"voice_message_broadcast_in_progress_message" = "Du kannst kein Gespräch beginnen, da du im Moment eine Sprachübertragung aufzeichnest. Bitte beende deine Sprachübertragung, um ein Gespräch zu beginnen";
|
"voice_message_broadcast_in_progress_message" = "Du kannst keine Sprachnachricht beginnen, da du im Moment eine Echtzeitübertragung aufzeichnest. Bitte beende deine Sprachübertragung, um ein Gespräch zu beginnen";
|
||||||
|
"poll_timeline_ended_text" = "Umfrage beendet";
|
||||||
|
"voice_broadcast_voip_cannot_start_description" = "Du kannst keinen Anruf beginnen, da du im Moment eine Sprachübertragung aufzeichnest. Bitte beende deine Sprachübertragung, um ein Gespräch zu beginnen.";
|
||||||
|
"voice_broadcast_voip_cannot_start_title" = "Kann keinen Anruf beginnen";
|
||||||
|
"poll_history_no_past_poll_text" = "In diesem Raum gibt es keine abgeschlossenen Umfragen";
|
||||||
|
"poll_history_no_active_poll_text" = "In diesem Raum gibt es keine aktiven Umfragen";
|
||||||
|
"poll_history_past_segment_title" = "Vergangene Umfragen";
|
||||||
|
"poll_history_active_segment_title" = "Aktive Umfragen";
|
||||||
|
|
||||||
|
// MARK: - Polls history
|
||||||
|
|
||||||
|
"poll_history_title" = "Umfrageverlauf";
|
||||||
|
"room_details_polls" = "Umfrageverlauf";
|
||||||
|
"accessibility_selected" = "ausgewählt";
|
||||||
|
"voice_broadcast_playback_lock_screen_placeholder" = "Sprachübertragung";
|
||||||
|
"voice_broadcast_connection_error_message" = "Leider ist es aktuell nicht möglich, eine Aufnahme zu beginnen. Bitte versuche es später erneut.";
|
||||||
|
"voice_broadcast_connection_error_title" = "Verbindungsfehler";
|
||||||
|
"wysiwyg_composer_format_action_code_block" = "Quelltextblock umschalten";
|
||||||
|
"wysiwyg_composer_format_action_quote" = "Zitat umschalten";
|
||||||
|
"wysiwyg_composer_format_action_ordered_list" = "Nummerierte Liste umschalten";
|
||||||
|
"wysiwyg_composer_format_action_unordered_list" = "Unsortierte Liste umschalten";
|
||||||
|
"voice_broadcast_recorder_connection_error" = "Verbindungsfehler – Aufzeichnung pausiert";
|
||||||
|
"poll_timeline_reply_ended_poll" = "Beendete Umfrage";
|
||||||
|
|
||||||
|
// MARK: - Launch loading
|
||||||
|
|
||||||
|
"launch_loading_migrating_data" = "Migriere Daten\n%@ %%";
|
||||||
|
"settings_labs_disable_crypto_sdk" = "Krypto-SDK ist aktiviert. Zum Deaktivieren, bitte die App neu installieren";
|
||||||
|
"settings_labs_confirm_crypto_sdk" = "Dies kann nicht rückgängig gemacht werden";
|
||||||
|
"settings_labs_enable_crypto_sdk" = "Rust-basiertes Krypto-SDK aktivieren";
|
||||||
|
|
|
@ -96,6 +96,7 @@
|
||||||
// Accessibility
|
// Accessibility
|
||||||
"accessibility_checkbox_label" = "checkbox";
|
"accessibility_checkbox_label" = "checkbox";
|
||||||
"accessibility_button_label" = "button";
|
"accessibility_button_label" = "button";
|
||||||
|
"accessibility_selected" = "selected";
|
||||||
|
|
||||||
// MARK: Onboarding
|
// MARK: Onboarding
|
||||||
"onboarding_splash_register_button_title" = "Create account";
|
"onboarding_splash_register_button_title" = "Create account";
|
||||||
|
@ -803,6 +804,9 @@ Tap the + to start adding people.";
|
||||||
"settings_labs_enable_new_app_layout" = "New Application Layout";
|
"settings_labs_enable_new_app_layout" = "New Application Layout";
|
||||||
"settings_labs_enable_wysiwyg_composer" = "Try out the rich text editor";
|
"settings_labs_enable_wysiwyg_composer" = "Try out the rich text editor";
|
||||||
"settings_labs_enable_voice_broadcast" = "Voice broadcast";
|
"settings_labs_enable_voice_broadcast" = "Voice broadcast";
|
||||||
|
"settings_labs_enable_crypto_sdk" = "Enable new rust-based Crypto SDK";
|
||||||
|
"settings_labs_confirm_crypto_sdk" = "This action cannot be undone";
|
||||||
|
"settings_labs_disable_crypto_sdk" = "Crypto SDK is enabled. To disable please reinstall the app";
|
||||||
|
|
||||||
"settings_version" = "Version %@";
|
"settings_version" = "Version %@";
|
||||||
"settings_olm_version" = "Olm Version %@";
|
"settings_olm_version" = "Olm Version %@";
|
||||||
|
@ -982,6 +986,7 @@ Tap the + to start adding people.";
|
||||||
"room_details_title_for_dm" = "Details";
|
"room_details_title_for_dm" = "Details";
|
||||||
"room_details_people" = "Members";
|
"room_details_people" = "Members";
|
||||||
"room_details_files" = "Uploads";
|
"room_details_files" = "Uploads";
|
||||||
|
"room_details_polls" = "Poll history";
|
||||||
"room_details_search" = "Search room";
|
"room_details_search" = "Search room";
|
||||||
"room_details_integrations" = "Integrations";
|
"room_details_integrations" = "Integrations";
|
||||||
"room_details_settings" = "Settings";
|
"room_details_settings" = "Settings";
|
||||||
|
@ -1522,7 +1527,7 @@ Tap the + to start adding people.";
|
||||||
"device_verification_cancelled_by_me" = "The verification has been cancelled. Reason: %@";
|
"device_verification_cancelled_by_me" = "The verification has been cancelled. Reason: %@";
|
||||||
"device_verification_error_cannot_load_device" = "Cannot load session information.";
|
"device_verification_error_cannot_load_device" = "Cannot load session information.";
|
||||||
|
|
||||||
// Mark: Incoming
|
// MARK: Incoming
|
||||||
"device_verification_incoming_title" = "Incoming Verification Request";
|
"device_verification_incoming_title" = "Incoming Verification Request";
|
||||||
"device_verification_incoming_description_1" = "Verify this session to mark it as trusted. Trusting sessions of partners gives you extra peace of mind when using end-to-end encrypted messages.";
|
"device_verification_incoming_description_1" = "Verify this session to mark it as trusted. Trusting sessions of partners gives you extra peace of mind when using end-to-end encrypted messages.";
|
||||||
"device_verification_incoming_description_2" = "Verifying this session will mark it as trusted, and also mark your session as trusted to the partner.";
|
"device_verification_incoming_description_2" = "Verifying this session will mark it as trusted, and also mark your session as trusted to the partner.";
|
||||||
|
@ -1974,6 +1979,7 @@ Tap the + to start adding people.";
|
||||||
|
|
||||||
// MARK: - Launch loading
|
// MARK: - Launch loading
|
||||||
|
|
||||||
|
"launch_loading_migrating_data" = "Migrating data\n%@ %%";
|
||||||
"launch_loading_server_syncing" = "Syncing with the server";
|
"launch_loading_server_syncing" = "Syncing with the server";
|
||||||
"launch_loading_server_syncing_nth_attempt" = "Syncing with the server\n(%@ attempt)";
|
"launch_loading_server_syncing_nth_attempt" = "Syncing with the server\n(%@ attempt)";
|
||||||
"launch_loading_processing_response" = "Processing data\n%@ %%";
|
"launch_loading_processing_response" = "Processing data\n%@ %%";
|
||||||
|
@ -2011,12 +2017,12 @@ Tap the + to start adding people.";
|
||||||
"share_invite_link_room_text" = "Hey, join this room on %@";
|
"share_invite_link_room_text" = "Hey, join this room on %@";
|
||||||
"share_invite_link_space_text" = "Hey, join this space on %@";
|
"share_invite_link_space_text" = "Hey, join this space on %@";
|
||||||
|
|
||||||
// Mark: - Room avatar view
|
// MARK: - Room avatar view
|
||||||
|
|
||||||
"room_avatar_view_accessibility_label" = "avatar";
|
"room_avatar_view_accessibility_label" = "avatar";
|
||||||
"room_avatar_view_accessibility_hint" = "Change room avatar";
|
"room_avatar_view_accessibility_hint" = "Change room avatar";
|
||||||
|
|
||||||
// Mark: - Room creation introduction cell
|
// MARK: - Room creation introduction cell
|
||||||
|
|
||||||
"room_intro_cell_add_participants_action" = "Add people";
|
"room_intro_cell_add_participants_action" = "Add people";
|
||||||
|
|
||||||
|
@ -2033,7 +2039,7 @@ Tap the + to start adding people.";
|
||||||
"room_intro_cell_information_dm_sentence2" = "Only the two of you are in this conversation, no one else can join.";
|
"room_intro_cell_information_dm_sentence2" = "Only the two of you are in this conversation, no one else can join.";
|
||||||
"room_intro_cell_information_multiple_dm_sentence2" = "Only you are in this conversation, unless any of you invites someone to join.";
|
"room_intro_cell_information_multiple_dm_sentence2" = "Only you are in this conversation, unless any of you invites someone to join.";
|
||||||
|
|
||||||
// Mark: - Room invite
|
// MARK: - Room invite
|
||||||
|
|
||||||
"room_invite_to_space_option_title" = "To %@";
|
"room_invite_to_space_option_title" = "To %@";
|
||||||
"room_invite_to_space_option_detail" = "They can explore %@, but won’t be a member of %@.";
|
"room_invite_to_space_option_detail" = "They can explore %@, but won’t be a member of %@.";
|
||||||
|
@ -2042,7 +2048,7 @@ Tap the + to start adding people.";
|
||||||
"room_invite_not_enough_permission" = "You do not have permission to invite people to this room";
|
"room_invite_not_enough_permission" = "You do not have permission to invite people to this room";
|
||||||
"space_invite_not_enough_permission" = "You do not have permission to invite people to this space";
|
"space_invite_not_enough_permission" = "You do not have permission to invite people to this space";
|
||||||
|
|
||||||
// Mark: - Spaces
|
// MARK: - Spaces
|
||||||
|
|
||||||
"space_feature_unavailable_title" = "Spaces aren’t here yet";
|
"space_feature_unavailable_title" = "Spaces aren’t here yet";
|
||||||
"space_feature_unavailable_subtitle" = "Spaces aren't on iOS yet, but you can use them now on Web and Desktop";
|
"space_feature_unavailable_subtitle" = "Spaces aren't on iOS yet, but you can use them now on Web and Desktop";
|
||||||
|
@ -2099,7 +2105,7 @@ Tap the + to start adding people.";
|
||||||
|
|
||||||
"spaces_feature_not_available" = "This feature isn't available here. For now, you can do this with %@ on your computer.";
|
"spaces_feature_not_available" = "This feature isn't available here. For now, you can do this with %@ on your computer.";
|
||||||
|
|
||||||
// Mark: - Space Creation
|
// MARK: - Space Creation
|
||||||
|
|
||||||
"spaces_creation_hint" = "Spaces are a new way to group rooms and people.";
|
"spaces_creation_hint" = "Spaces are a new way to group rooms and people.";
|
||||||
"spaces_creation_visibility_title" = "What type of space do you want to create?";
|
"spaces_creation_visibility_title" = "What type of space do you want to create?";
|
||||||
|
@ -2158,7 +2164,7 @@ Tap the + to start adding people.";
|
||||||
|
|
||||||
"spaces_add_room_missing_permission_message" = "You do not have permissions to add rooms to this space.";
|
"spaces_add_room_missing_permission_message" = "You do not have permissions to add rooms to this space.";
|
||||||
|
|
||||||
// Mark: Leave space
|
// MARK: Leave space
|
||||||
|
|
||||||
"leave_space_action" = "Leave space";
|
"leave_space_action" = "Leave space";
|
||||||
"leave_space_and_one_room" = "Leave space and 1 room";
|
"leave_space_and_one_room" = "Leave space and 1 room";
|
||||||
|
@ -2171,17 +2177,17 @@ Tap the + to start adding people.";
|
||||||
|
|
||||||
"room_event_action_reaction_more" = "%@ more";
|
"room_event_action_reaction_more" = "%@ more";
|
||||||
|
|
||||||
// Mark: Avatar
|
// MARK: Avatar
|
||||||
|
|
||||||
"space_avatar_view_accessibility_label" = "avatar";
|
"space_avatar_view_accessibility_label" = "avatar";
|
||||||
"space_avatar_view_accessibility_hint" = "Change space avatar";
|
"space_avatar_view_accessibility_hint" = "Change space avatar";
|
||||||
|
|
||||||
// Mark: - User avatar view
|
// MARK: - User avatar view
|
||||||
|
|
||||||
"user_avatar_view_accessibility_label" = "avatar";
|
"user_avatar_view_accessibility_label" = "avatar";
|
||||||
"user_avatar_view_accessibility_hint" = "Change user avatar";
|
"user_avatar_view_accessibility_hint" = "Change user avatar";
|
||||||
|
|
||||||
// Mark: - Side menu
|
// MARK: - Side menu
|
||||||
|
|
||||||
"side_menu_reveal_action_accessibility_label" = "Left panel";
|
"side_menu_reveal_action_accessibility_label" = "Left panel";
|
||||||
"side_menu_action_invite_friends" = "Invite friends";
|
"side_menu_action_invite_friends" = "Invite friends";
|
||||||
|
@ -2191,7 +2197,7 @@ Tap the + to start adding people.";
|
||||||
"side_menu_app_version" = "Version %@";
|
"side_menu_app_version" = "Version %@";
|
||||||
"side_menu_coach_message" = "Swipe right or tap to see all rooms";
|
"side_menu_coach_message" = "Swipe right or tap to see all rooms";
|
||||||
|
|
||||||
// Mark: - Voice Messages
|
// MARK: - Voice Messages
|
||||||
|
|
||||||
"voice_message_release_to_send" = "Hold to record, release to send";
|
"voice_message_release_to_send" = "Hold to record, release to send";
|
||||||
"voice_message_remaining_recording_time" = "%@s left";
|
"voice_message_remaining_recording_time" = "%@s left";
|
||||||
|
@ -2200,12 +2206,13 @@ Tap the + to start adding people.";
|
||||||
"voice_message_broadcast_in_progress_title" = "Can't start voice message";
|
"voice_message_broadcast_in_progress_title" = "Can't start voice message";
|
||||||
"voice_message_broadcast_in_progress_message" = "You can't start a voice message as you are currently recording a live broadcast. Please end your live broadcast in order to start recording a voice message";
|
"voice_message_broadcast_in_progress_message" = "You can't start a voice message as you are currently recording a live broadcast. Please end your live broadcast in order to start recording a voice message";
|
||||||
|
|
||||||
// Mark: - Voice broadcast
|
// MARK: - Voice Broadcast
|
||||||
"voice_broadcast_unauthorized_title" = "Can't start a new voice broadcast";
|
"voice_broadcast_unauthorized_title" = "Can't start a new voice broadcast";
|
||||||
"voice_broadcast_permission_denied_message" = "You don't have the required permissions to start a voice broadcast in this room. Contact a room administrator to upgrade your permissions.";
|
"voice_broadcast_permission_denied_message" = "You don't have the required permissions to start a voice broadcast in this room. Contact a room administrator to upgrade your permissions.";
|
||||||
"voice_broadcast_blocked_by_someone_else_message" = "Someone else is already recording a voice broadcast. Wait for their voice broadcast to end to start a new one.";
|
"voice_broadcast_blocked_by_someone_else_message" = "Someone else is already recording a voice broadcast. Wait for their voice broadcast to end to start a new one.";
|
||||||
"voice_broadcast_already_in_progress_message" = "You are already recording a voice broadcast. Please end your current voice broadcast to start a new one.";
|
"voice_broadcast_already_in_progress_message" = "You are already recording a voice broadcast. Please end your current voice broadcast to start a new one.";
|
||||||
"voice_broadcast_playback_loading_error" = "Unable to play this voice broadcast.";
|
"voice_broadcast_playback_loading_error" = "Unable to play this voice broadcast.";
|
||||||
|
"voice_broadcast_playback_lock_screen_placeholder" = "Voice broadcast";
|
||||||
"voice_broadcast_live" = "Live";
|
"voice_broadcast_live" = "Live";
|
||||||
"voice_broadcast_tile" = "Voice broadcast";
|
"voice_broadcast_tile" = "Voice broadcast";
|
||||||
"voice_broadcast_time_left" = "%@ left";
|
"voice_broadcast_time_left" = "%@ left";
|
||||||
|
@ -2213,8 +2220,13 @@ Tap the + to start adding people.";
|
||||||
"voice_broadcast_stop_alert_title" = "Stop live broadcasting?";
|
"voice_broadcast_stop_alert_title" = "Stop live broadcasting?";
|
||||||
"voice_broadcast_stop_alert_description" = "Are you sure you want to stop your live broadcast? This will end the broadcast, and the full recording will be available in the room.";
|
"voice_broadcast_stop_alert_description" = "Are you sure you want to stop your live broadcast? This will end the broadcast, and the full recording will be available in the room.";
|
||||||
"voice_broadcast_stop_alert_agree_button" = "Yes, stop";
|
"voice_broadcast_stop_alert_agree_button" = "Yes, stop";
|
||||||
|
"voice_broadcast_voip_cannot_start_title" = "Can’t start a call";
|
||||||
|
"voice_broadcast_voip_cannot_start_description" = "You can’t start a call as you are currently recording a live broadcast. Please end your live broadcast in order to start a call.";
|
||||||
|
"voice_broadcast_connection_error_title" = "Connection error";
|
||||||
|
"voice_broadcast_connection_error_message" = "Unfortunately we’re unable to start a recording right now. Please try again later.";
|
||||||
|
"voice_broadcast_recorder_connection_error" = "Connection error - Recording paused";
|
||||||
|
|
||||||
// Mark: - Version check
|
// MARK: - Version check
|
||||||
|
|
||||||
"version_check_banner_title_supported" = "We’re ending support for iOS %@";
|
"version_check_banner_title_supported" = "We’re ending support for iOS %@";
|
||||||
"version_check_banner_subtitle_supported" = "We will soon be ending support for %@ on iOS %@. To continue using %@ to its full potential, we advise you to upgrade your version of iOS.";
|
"version_check_banner_subtitle_supported" = "We will soon be ending support for %@ on iOS %@. To continue using %@ to its full potential, we advise you to upgrade your version of iOS.";
|
||||||
|
@ -2230,7 +2242,7 @@ Tap the + to start adding people.";
|
||||||
"version_check_modal_subtitle_deprecated" = "We've been working on enhancing %@ for a faster and more polished experience. Unfortunately your current version of iOS is not compatible with some of those fixes and is no longer supported.\nWe're advising you to upgrade your operating system to use %@ to its full potential.";
|
"version_check_modal_subtitle_deprecated" = "We've been working on enhancing %@ for a faster and more polished experience. Unfortunately your current version of iOS is not compatible with some of those fixes and is no longer supported.\nWe're advising you to upgrade your operating system to use %@ to its full potential.";
|
||||||
"version_check_modal_action_title_deprecated" = "Find out how";
|
"version_check_modal_action_title_deprecated" = "Find out how";
|
||||||
|
|
||||||
// Mark: - All Chats
|
// MARK: - All Chats
|
||||||
|
|
||||||
"all_chats_title" = "All chats";
|
"all_chats_title" = "All chats";
|
||||||
"all_chats_section_title" = "Chats";
|
"all_chats_section_title" = "Chats";
|
||||||
|
@ -2274,12 +2286,12 @@ Tap the + to start adding people.";
|
||||||
"all_chats_onboarding_title" = "What's new";
|
"all_chats_onboarding_title" = "What's new";
|
||||||
"all_chats_onboarding_try_it" = "Try it out";
|
"all_chats_onboarding_try_it" = "Try it out";
|
||||||
|
|
||||||
// Mark: - Room invites
|
// MARK: - Room invites
|
||||||
|
|
||||||
"room_invites_empty_view_title" = "Nothing new.";
|
"room_invites_empty_view_title" = "Nothing new.";
|
||||||
"room_invites_empty_view_information" = "This is where your invites appear.";
|
"room_invites_empty_view_information" = "This is where your invites appear.";
|
||||||
|
|
||||||
// Mark: - Space Selector
|
// MARK: - Space Selector
|
||||||
|
|
||||||
"space_selector_title" = "My spaces";
|
"space_selector_title" = "My spaces";
|
||||||
"space_selector_empty_view_title" = "No spaces yet.";
|
"space_selector_empty_view_title" = "No spaces yet.";
|
||||||
|
@ -2289,7 +2301,15 @@ Tap the + to start adding people.";
|
||||||
"space_detail_nav_title" = "Space detail";
|
"space_detail_nav_title" = "Space detail";
|
||||||
"space_invite_nav_title" = "Space invite";
|
"space_invite_nav_title" = "Space invite";
|
||||||
|
|
||||||
// Mark: - Polls
|
// MARK: - Polls history
|
||||||
|
|
||||||
|
"poll_history_title" = "Poll history";
|
||||||
|
"poll_history_active_segment_title" = "Active polls";
|
||||||
|
"poll_history_past_segment_title" = "Past polls";
|
||||||
|
"poll_history_no_active_poll_text" = "There are no active polls in this room";
|
||||||
|
"poll_history_no_past_poll_text" = "There are no past polls in this room";
|
||||||
|
|
||||||
|
// MARK: - Polls
|
||||||
|
|
||||||
"poll_edit_form_create_poll" = "Create poll";
|
"poll_edit_form_create_poll" = "Create poll";
|
||||||
|
|
||||||
|
@ -2353,6 +2373,8 @@ Tap the + to start adding people.";
|
||||||
|
|
||||||
"poll_timeline_ended_text" = "Ended the poll";
|
"poll_timeline_ended_text" = "Ended the poll";
|
||||||
|
|
||||||
|
"poll_timeline_reply_ended_poll" = "Ended poll";
|
||||||
|
|
||||||
// MARK: - Location sharing
|
// MARK: - Location sharing
|
||||||
|
|
||||||
"location_sharing_title" = "Location";
|
"location_sharing_title" = "Location";
|
||||||
|
@ -2538,7 +2560,7 @@ To enable access, tap Settings> Location and select Always";
|
||||||
"user_session_overview_session_details_button_title" = "Session details";
|
"user_session_overview_session_details_button_title" = "Session details";
|
||||||
|
|
||||||
|
|
||||||
// Mark: - WYSIWYG Composer
|
// MARK: - WYSIWYG Composer
|
||||||
|
|
||||||
// Send Media Actions
|
// Send Media Actions
|
||||||
"wysiwyg_composer_start_action_media_picker" = "Photo Library";
|
"wysiwyg_composer_start_action_media_picker" = "Photo Library";
|
||||||
|
@ -2557,6 +2579,12 @@ To enable access, tap Settings> Location and select Always";
|
||||||
"wysiwyg_composer_format_action_strikethrough" = "Apply underline format";
|
"wysiwyg_composer_format_action_strikethrough" = "Apply underline format";
|
||||||
"wysiwyg_composer_format_action_link" = "Apply link format";
|
"wysiwyg_composer_format_action_link" = "Apply link format";
|
||||||
"wysiwyg_composer_format_action_inline_code" = "Apply inline code format";
|
"wysiwyg_composer_format_action_inline_code" = "Apply inline code format";
|
||||||
|
"wysiwyg_composer_format_action_unordered_list" = "Toggle bulleted list";
|
||||||
|
"wysiwyg_composer_format_action_ordered_list" = "Toggle numbered list";
|
||||||
|
"wysiwyg_composer_format_action_code_block" = "Toggle code block";
|
||||||
|
"wysiwyg_composer_format_action_quote" = "Toggle quote";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Links
|
// Links
|
||||||
"wysiwyg_composer_link_action_text" = "Text";
|
"wysiwyg_composer_link_action_text" = "Text";
|
||||||
|
|
|
@ -118,3 +118,6 @@
|
||||||
|
|
||||||
/* New file message from a specific person, not referencing a room. */
|
/* New file message from a specific person, not referencing a room. */
|
||||||
"LOCATION_FROM_USER" = "%@ jagas oma asukohta";
|
"LOCATION_FROM_USER" = "%@ jagas oma asukohta";
|
||||||
|
|
||||||
|
/* New voice broadcast from a specific person, not referencing a room. */
|
||||||
|
"VOICE_BROADCAST_FROM_USER" = "%@ alustas ringhäälingukõnet";
|
||||||
|
|
|
@ -2640,3 +2640,32 @@
|
||||||
"poll_timeline_decryption_error" = "Krüptimisvigade tõttu jääb osa hääli lugemata";
|
"poll_timeline_decryption_error" = "Krüptimisvigade tõttu jääb osa hääli lugemata";
|
||||||
"voice_message_broadcast_in_progress_title" = "Häälsõnumi salvestamine või esitamine ei õnnestu";
|
"voice_message_broadcast_in_progress_title" = "Häälsõnumi salvestamine või esitamine ei õnnestu";
|
||||||
"voice_message_broadcast_in_progress_message" = "Kuna sa hetkel salvestad ringhäälingukõnet, siis häälsõnumi salvestamine või esitamine ei õnnestu. Selleks palun lõpeta ringhäälingukõne";
|
"voice_message_broadcast_in_progress_message" = "Kuna sa hetkel salvestad ringhäälingukõnet, siis häälsõnumi salvestamine või esitamine ei õnnestu. Selleks palun lõpeta ringhäälingukõne";
|
||||||
|
"poll_timeline_ended_text" = "Küsitlus on lõppenud";
|
||||||
|
"voice_broadcast_voip_cannot_start_description" = "Kuna sa hetkel salvestad ringhäälingukõnet, siis tavakõne algatamine ei õnnestu. Kõne alustamiseks palun lõpeta ringhäälingukõne.";
|
||||||
|
"voice_broadcast_voip_cannot_start_title" = "Kõne algatamine ei õnnestu";
|
||||||
|
"poll_history_no_past_poll_text" = "Selles jututoas pole varasemaid küsitlusi";
|
||||||
|
"poll_history_no_active_poll_text" = "Selles jututoas pole käimasolevaid küsitlusi";
|
||||||
|
"poll_history_past_segment_title" = "Varasemad küsitlused";
|
||||||
|
"poll_history_active_segment_title" = "Käimasolevad küsitlused";
|
||||||
|
|
||||||
|
// MARK: - Polls history
|
||||||
|
|
||||||
|
"poll_history_title" = "Küsitluste ajalugu";
|
||||||
|
"room_details_polls" = "Küsitluste ajalugu";
|
||||||
|
"accessibility_selected" = "valitud";
|
||||||
|
"voice_broadcast_playback_lock_screen_placeholder" = "Ringhäälingukõne";
|
||||||
|
"voice_broadcast_connection_error_message" = "Kahjuks me ei saa hetkel salvestamist alustada. Palun proovi hiljem uuesti.";
|
||||||
|
"voice_broadcast_connection_error_title" = "Ühenduse viga";
|
||||||
|
"wysiwyg_composer_format_action_quote" = "Lülita tsiteerimine sisse/välja";
|
||||||
|
"wysiwyg_composer_format_action_code_block" = "Lülita koodiblokk sisse/välja";
|
||||||
|
"wysiwyg_composer_format_action_ordered_list" = "Lülita nummerdatud loend sisse/välja";
|
||||||
|
"wysiwyg_composer_format_action_unordered_list" = "Lülita täpploend sisse/välja";
|
||||||
|
"voice_broadcast_recorder_connection_error" = "Viga võrguühenduses - salvestamine on peatatud";
|
||||||
|
"poll_timeline_reply_ended_poll" = "Lõppenud küsitlus";
|
||||||
|
|
||||||
|
// MARK: - Launch loading
|
||||||
|
|
||||||
|
"launch_loading_migrating_data" = "Tõstame andmeid ümber\n%@ %%";
|
||||||
|
"settings_labs_disable_crypto_sdk" = "Uus Crypto SDK on kasutusel. Tema väljalülitamiseks palun paigalda rakendus uuesti";
|
||||||
|
"settings_labs_confirm_crypto_sdk" = "Seda toimingut ei saa tagasi pöörata";
|
||||||
|
"settings_labs_enable_crypto_sdk" = "Võta kasutusele uus Rust-keelel põhinev Crypto SDK";
|
||||||
|
|
|
@ -120,3 +120,6 @@
|
||||||
|
|
||||||
/* New video message from a specific person, not referencing a room. */
|
/* New video message from a specific person, not referencing a room. */
|
||||||
"VIDEO_FROM_USER" = "%@ videót küldött";
|
"VIDEO_FROM_USER" = "%@ videót küldött";
|
||||||
|
|
||||||
|
/* New voice broadcast from a specific person, not referencing a room. */
|
||||||
|
"VOICE_BROADCAST_FROM_USER" = "%@ hang közvetítést indított";
|
||||||
|
|
|
@ -2688,3 +2688,25 @@
|
||||||
"poll_timeline_decryption_error" = "Visszafejtési hibák miatt néhány szavazat nem kerül beszámításra";
|
"poll_timeline_decryption_error" = "Visszafejtési hibák miatt néhány szavazat nem kerül beszámításra";
|
||||||
"voice_message_broadcast_in_progress_message" = "Nem lehet hang üzenetet indítani élő közvetítés felvétele közben. Az élő közvetítés bejezése szükséges a hang üzenet indításához";
|
"voice_message_broadcast_in_progress_message" = "Nem lehet hang üzenetet indítani élő közvetítés felvétele közben. Az élő közvetítés bejezése szükséges a hang üzenet indításához";
|
||||||
"voice_message_broadcast_in_progress_title" = "Hang üzenetet nem lehet elindítani";
|
"voice_message_broadcast_in_progress_title" = "Hang üzenetet nem lehet elindítani";
|
||||||
|
"poll_timeline_ended_text" = "Szavazás vége";
|
||||||
|
"voice_broadcast_voip_cannot_start_description" = "Nem lehet hívást kezdeményezni élő közvetítés felvétele közben. Az élő közvetítés bejezése szükséges a hívás indításához.";
|
||||||
|
"voice_broadcast_voip_cannot_start_title" = "Nem sikerült hívást indítani";
|
||||||
|
"poll_history_no_past_poll_text" = "Nincsenek régi szavazások ebben a szobában";
|
||||||
|
"poll_history_no_active_poll_text" = "Nincsenek aktív szavazások ebben a szobában";
|
||||||
|
"poll_history_past_segment_title" = "Régi szavazások";
|
||||||
|
"poll_history_active_segment_title" = "Aktív szavazások";
|
||||||
|
|
||||||
|
// MARK: - Polls history
|
||||||
|
|
||||||
|
"poll_history_title" = "Szavazás alakulása";
|
||||||
|
"room_details_polls" = "Szavazás alakulása";
|
||||||
|
"accessibility_selected" = "kiválasztva";
|
||||||
|
"wysiwyg_composer_format_action_quote" = "Idézet be/ki";
|
||||||
|
"wysiwyg_composer_format_action_code_block" = "Kód blokk be/ki";
|
||||||
|
"wysiwyg_composer_format_action_ordered_list" = "Számozott lista ki-,bekapcsolása";
|
||||||
|
"wysiwyg_composer_format_action_unordered_list" = "Lista ki-,bekapcsolása";
|
||||||
|
"poll_timeline_reply_ended_poll" = "Lezárt szavazások";
|
||||||
|
"voice_broadcast_recorder_connection_error" = "Kapcsolódási hiba – Felvétel szüneteltetve";
|
||||||
|
"voice_broadcast_connection_error_message" = "Sajnos most nem lehet elindítani a felvételt. Próbálja meg később.";
|
||||||
|
"voice_broadcast_connection_error_title" = "Kapcsolat hiba";
|
||||||
|
"voice_broadcast_playback_lock_screen_placeholder" = "Hang közvetítés";
|
||||||
|
|
|
@ -2893,5 +2893,34 @@
|
||||||
"notice_voice_broadcast_live" = "Siaran langsung";
|
"notice_voice_broadcast_live" = "Siaran langsung";
|
||||||
"user_other_session_security_recommendation_title" = "Sesi lainnya";
|
"user_other_session_security_recommendation_title" = "Sesi lainnya";
|
||||||
"poll_timeline_decryption_error" = "Karena kesalahan enkripsi, beberapa suara mungkin tidak terhitung";
|
"poll_timeline_decryption_error" = "Karena kesalahan enkripsi, beberapa suara mungkin tidak terhitung";
|
||||||
"voice_message_broadcast_in_progress_message" = "Anda tidak dapat memulai sebuah pesan suara selagi Anda merekam sebuah siaran langsung. Silakan mengakhiri siaran langsung Anda untuk memulai merekam sebuah pesan suara";
|
"voice_message_broadcast_in_progress_message" = "Anda tidak dapat memulai sebuah pesan suara karena Anda saat ini merekam sebuah siaran langsung. Silakan mengakhiri siaran langsung Anda untuk memulai merekam sebuah pesan suara";
|
||||||
"voice_message_broadcast_in_progress_title" = "Tidak dapat memulai pesan suara";
|
"voice_message_broadcast_in_progress_title" = "Tidak dapat memulai pesan suara";
|
||||||
|
"poll_timeline_ended_text" = "Mengakhiri pemungutan suara";
|
||||||
|
"voice_broadcast_voip_cannot_start_description" = "Anda tidak dapat memulai sebuah panggilan karena Anda saat ini merekam sebuah siaran langsung. Mohon akhiri siaran langsung Anda untuk memulai sebuah panggilan.";
|
||||||
|
"voice_broadcast_voip_cannot_start_title" = "Tidak dapat memulai sebuah panggilan";
|
||||||
|
"poll_history_no_past_poll_text" = "Tidak ada pemungutan suara masa lalu di ruangan ini";
|
||||||
|
"poll_history_no_active_poll_text" = "Tidak ada pemungutan suara yang aktifk di ruangan ini";
|
||||||
|
"poll_history_past_segment_title" = "Pemungutan suara sebelumnya";
|
||||||
|
"poll_history_active_segment_title" = "Pemungutan suara aktif";
|
||||||
|
|
||||||
|
// MARK: - Polls history
|
||||||
|
|
||||||
|
"poll_history_title" = "Riwayat pemungutan suara";
|
||||||
|
"room_details_polls" = "Riwayat pemungutan suara";
|
||||||
|
"accessibility_selected" = "dipilih";
|
||||||
|
"voice_broadcast_playback_lock_screen_placeholder" = "Siaran suara";
|
||||||
|
"wysiwyg_composer_format_action_quote" = "Saklar kutipan";
|
||||||
|
"wysiwyg_composer_format_action_code_block" = "Saklar blok kode";
|
||||||
|
"wysiwyg_composer_format_action_ordered_list" = "Saklar daftar bernomor";
|
||||||
|
"wysiwyg_composer_format_action_unordered_list" = "Saklar daftar bulat";
|
||||||
|
"voice_broadcast_connection_error_message" = "Sayangnya kami tidak dapat memulai sebuah rekaman saat ini. Silakan coba lagi nanti.";
|
||||||
|
"voice_broadcast_connection_error_title" = "Kesalahan koneksi";
|
||||||
|
"voice_broadcast_recorder_connection_error" = "Kesalahan koneksi - Perekaman dijeda";
|
||||||
|
"poll_timeline_reply_ended_poll" = "Pemungutan suara berakhir";
|
||||||
|
|
||||||
|
// MARK: - Launch loading
|
||||||
|
|
||||||
|
"launch_loading_migrating_data" = "Memigrasikan data\n%@ %%";
|
||||||
|
"settings_labs_disable_crypto_sdk" = "SDK Kripto diaktifkan. Untuk menonaktifkan, mohon memasang ulang aplikasi";
|
||||||
|
"settings_labs_confirm_crypto_sdk" = "Tindakan ini tidak dapat diurungkan";
|
||||||
|
"settings_labs_enable_crypto_sdk" = "Aktifkan SDK Kripto baru berbasis Rust";
|
||||||
|
|
|
@ -170,3 +170,6 @@
|
||||||
|
|
||||||
/* Look, stuff's happened, alright? Just open the app. */
|
/* Look, stuff's happened, alright? Just open the app. */
|
||||||
"MSGS_IN_TWO_PLUS_ROOMS" = "%@ ný skilaboð í %@, %@ og fleirum";
|
"MSGS_IN_TWO_PLUS_ROOMS" = "%@ ný skilaboð í %@, %@ og fleirum";
|
||||||
|
|
||||||
|
/* New voice broadcast from a specific person, not referencing a room. */
|
||||||
|
"VOICE_BROADCAST_FROM_USER" = "%@ byrjaði talútsendingu";
|
||||||
|
|
|
@ -1283,7 +1283,7 @@
|
||||||
"settings_add_3pid_invalid_password_message" = "Ógild auðkenni";
|
"settings_add_3pid_invalid_password_message" = "Ógild auðkenni";
|
||||||
"settings_add_3pid_password_title_msidsn" = "Bæta við símanúmeri";
|
"settings_add_3pid_password_title_msidsn" = "Bæta við símanúmeri";
|
||||||
"settings_add_3pid_password_title_email" = "Bæta við tölvupóstfangi";
|
"settings_add_3pid_password_title_email" = "Bæta við tölvupóstfangi";
|
||||||
"settings_labs_enable_threads" = "Skilaboð í spjallþráðum";
|
"settings_labs_enable_threads" = "Spjallþræðir skilaboða";
|
||||||
"settings_labs_enabled_polls" = "Kannanir";
|
"settings_labs_enabled_polls" = "Kannanir";
|
||||||
"settings_integrations_allow_button" = "Sýsla með samþættingar";
|
"settings_integrations_allow_button" = "Sýsla með samþættingar";
|
||||||
"settings_new_keyword" = "Bæta við nýju stikkorði";
|
"settings_new_keyword" = "Bæta við nýju stikkorði";
|
||||||
|
@ -2317,7 +2317,7 @@
|
||||||
"device_name_mobile" = "%@ fyrir farsíma";
|
"device_name_mobile" = "%@ fyrir farsíma";
|
||||||
"device_name_web" = "%@ á vefnum";
|
"device_name_web" = "%@ á vefnum";
|
||||||
"device_name_desktop" = "%@ fyrir einkatölvur";
|
"device_name_desktop" = "%@ fyrir einkatölvur";
|
||||||
"user_session_item_details" = "%@ · Síðasta virkni %@";
|
"user_session_item_details" = "%1$@ · %2$@";
|
||||||
"location_sharing_live_loading" = "Hleð inn rauntímastaðsetningu...";
|
"location_sharing_live_loading" = "Hleð inn rauntímastaðsetningu...";
|
||||||
"location_sharing_live_list_item_time_left" = "%@ fór";
|
"location_sharing_live_list_item_time_left" = "%@ fór";
|
||||||
"location_sharing_map_credits_title" = "© Höfundarréttur";
|
"location_sharing_map_credits_title" = "© Höfundarréttur";
|
||||||
|
@ -2368,3 +2368,119 @@
|
||||||
|
|
||||||
// MARK: Authentication
|
// MARK: Authentication
|
||||||
"authentication_registration_title" = "Búðu til aðganginn þinn";
|
"authentication_registration_title" = "Búðu til aðganginn þinn";
|
||||||
|
"notice_voice_broadcast_ended_by_you" = "Þú endaðir talútsendingu.";
|
||||||
|
"notice_voice_broadcast_ended" = "%@ endaði talútsendingu.";
|
||||||
|
"notice_voice_broadcast_live" = "Bein útsending";
|
||||||
|
"deselect_all" = "Afvelja allt";
|
||||||
|
"wysiwyg_composer_link_action_edit_title" = "Breyta tengli";
|
||||||
|
"wysiwyg_composer_link_action_create_title" = "Búa til tengil";
|
||||||
|
"wysiwyg_composer_link_action_link" = "Tengill";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Links
|
||||||
|
"wysiwyg_composer_link_action_text" = "Texti";
|
||||||
|
"wysiwyg_composer_start_action_voice_broadcast" = "Útvörpun tals";
|
||||||
|
"wysiwyg_composer_start_action_text_formatting" = "Sníðing texta";
|
||||||
|
"wysiwyg_composer_start_action_camera" = "Myndavél";
|
||||||
|
"wysiwyg_composer_start_action_location" = "Staðsetning";
|
||||||
|
"wysiwyg_composer_start_action_polls" = "Kannanir";
|
||||||
|
"wysiwyg_composer_start_action_attachments" = "Viðhengi";
|
||||||
|
"wysiwyg_composer_start_action_stickers" = "Límmerki";
|
||||||
|
|
||||||
|
|
||||||
|
// MARK: - WYSIWYG Composer
|
||||||
|
|
||||||
|
// Send Media Actions
|
||||||
|
"wysiwyg_composer_start_action_media_picker" = "Ljósmyndasafn";
|
||||||
|
"user_session_overview_session_details_button_title" = "Nánar um setuna";
|
||||||
|
"user_session_overview_session_title" = "Seta";
|
||||||
|
"user_session_overview_current_session_title" = "Núverandi seta";
|
||||||
|
"user_session_details_application_url" = "Slóð (URL)";
|
||||||
|
"user_session_details_application_version" = "Útgáfa";
|
||||||
|
"user_session_details_application_name" = "Heiti";
|
||||||
|
"user_session_details_device_os" = "Stýrikerfi";
|
||||||
|
"user_session_details_device_browser" = "Vafri";
|
||||||
|
"user_session_details_device_model" = "Gerð";
|
||||||
|
"user_session_details_device_ip_location" = "Staðsetning IP-vistfangs";
|
||||||
|
"user_session_details_device_ip_address" = "IP-vistfang";
|
||||||
|
"user_session_details_last_activity" = "Síðasta virkni";
|
||||||
|
"user_session_details_session_id" = "Auðkenni setu";
|
||||||
|
"user_session_details_session_name" = "Nafn á setu";
|
||||||
|
"user_session_details_device_section_header" = "Tæki";
|
||||||
|
"user_session_details_application_section_header" = "Forrit";
|
||||||
|
"user_session_details_session_section_header" = "Seta";
|
||||||
|
"user_session_details_title" = "Nánar um setuna";
|
||||||
|
"device_type_name_unknown" = "Óþekkt";
|
||||||
|
"device_type_name_mobile" = "Farsími";
|
||||||
|
"device_type_name_web" = "Vefur";
|
||||||
|
"device_type_name_desktop" = "Borðtölva";
|
||||||
|
"user_other_session_selected_count" = "%@ valið";
|
||||||
|
"user_other_session_clear_filter" = "Hreinsa síu";
|
||||||
|
"user_other_session_no_unverified_sessions" = "Engar óstaðfestar setur fundust.";
|
||||||
|
"user_other_session_no_verified_sessions" = "Engar staðfestar setur fundust.";
|
||||||
|
"user_other_session_no_inactive_sessions" = "Engar óvirkar setur fundust.";
|
||||||
|
"user_other_session_filter_menu_inactive" = "Óvirkt";
|
||||||
|
"user_other_session_filter_menu_unverified" = "Óstaðfestar";
|
||||||
|
"user_other_session_filter_menu_verified" = "Staðfestar";
|
||||||
|
"user_other_session_filter_menu_all" = "Allar setur";
|
||||||
|
"user_other_session_filter" = "Sía";
|
||||||
|
"user_other_session_security_recommendation_title" = "Aðrar setur";
|
||||||
|
"user_session_inactive_session_title" = "Óvirkar setur";
|
||||||
|
"user_session_unverified_session_title" = "Óstaðfest seta";
|
||||||
|
"user_session_verified_session_title" = "Sannreyndar setur";
|
||||||
|
"user_session_got_it" = "Náði því";
|
||||||
|
"user_session_push_notifications" = "Ýti-tilkynningar";
|
||||||
|
"user_session_verification_unknown_short" = "Óþekkt";
|
||||||
|
"user_session_verification_unknown" = "Óþekkt staða sannvottunar";
|
||||||
|
"user_sessions_view_all_action" = "Skoða öll (%d)";
|
||||||
|
"user_sessions_overview_link_device" = "Tengja tæki";
|
||||||
|
"user_sessions_overview_current_session_section_title" = "Núverandi seta";
|
||||||
|
"user_sessions_hide_location_info" = "Fela IP-vistfang";
|
||||||
|
"user_sessions_show_location_info" = "Birta IP-vistfang";
|
||||||
|
"user_sessions_overview_other_sessions_section_title" = "Aðrar setur";
|
||||||
|
"user_sessions_overview_security_recommendations_inactive_title" = "Óvirkar setur";
|
||||||
|
"user_sessions_overview_security_recommendations_unverified_title" = "Óstaðfestar setur";
|
||||||
|
"user_sessions_overview_security_recommendations_section_title" = "Ráðleggingar varðandi öryggi";
|
||||||
|
|
||||||
|
// MARK: User sessions management
|
||||||
|
|
||||||
|
// Parameter is the application display name (e.g. "Element")
|
||||||
|
"user_sessions_default_session_display_name" = "%@ iOS";
|
||||||
|
"location_sharing_live_lab_promotion_activation" = "Virkja deilingu rauntímastaðsetninga";
|
||||||
|
"location_sharing_live_timer_incoming" = "Í beinni til %@";
|
||||||
|
"poll_timeline_reply_ended_poll" = "Lauk könnun";
|
||||||
|
"poll_timeline_ended_text" = "Lauk könnuninni";
|
||||||
|
"poll_history_past_segment_title" = "Fyrri kannanir";
|
||||||
|
"poll_history_active_segment_title" = "Virkar kannanir";
|
||||||
|
|
||||||
|
// MARK: - Polls history
|
||||||
|
|
||||||
|
"poll_history_title" = "Breytingaskrá könnunar";
|
||||||
|
"all_chats_user_menu_accessibility_label" = "Valmynd notandans";
|
||||||
|
"voice_broadcast_connection_error_title" = "Villa í tengingu";
|
||||||
|
"voice_broadcast_voip_cannot_start_title" = "Get ekki hafið símtal";
|
||||||
|
"voice_broadcast_stop_alert_agree_button" = "Já, stöðva";
|
||||||
|
"voice_broadcast_buffering" = "Hleð í biðminni...";
|
||||||
|
"voice_broadcast_time_left" = "%@ eftir";
|
||||||
|
"voice_broadcast_tile" = "Útvörpun tals";
|
||||||
|
"voice_broadcast_live" = "Beint";
|
||||||
|
"voice_broadcast_playback_lock_screen_placeholder" = "Útvörpun tals";
|
||||||
|
|
||||||
|
// Unverified sessions
|
||||||
|
"key_verification_alert_title" = "Þú ert með óstaðfestar setur";
|
||||||
|
"sign_out_confirmation_message" = "Ertu viss um að þú viljir skrá þig út?";
|
||||||
|
|
||||||
|
// MARK: Sign out warning
|
||||||
|
|
||||||
|
"sign_out" = "Skrá út";
|
||||||
|
"secure_key_backup_setup_cancel_alert_message" = "Ef þú hættir við núna, geturðu tapað dulrituðum skilaboðum og gögnum ef þú missir aðgang að innskráningum þínum.\n\nÞú getur víka sett upp örugga afritun og sýslað með dulritunarlyklana þína í stillingunum.";
|
||||||
|
"room_details_polls" = "Breytingaskrá könnunar";
|
||||||
|
"manage_session_sign_out_other_sessions" = "Skrá út úr öllum öðrum setum";
|
||||||
|
"manage_session_rename" = "Endurnefna setu";
|
||||||
|
"settings_labs_enable_voice_broadcast" = "Útvörpun tals";
|
||||||
|
"authentication_qr_login_failure_retry" = "Reyna aftur";
|
||||||
|
"authentication_qr_login_loading_connecting_device" = "Tengist við tæki";
|
||||||
|
"authentication_qr_login_scan_title" = "Skanna QR-kóða";
|
||||||
|
"authentication_qr_login_start_title" = "Skanna QR-kóða";
|
||||||
|
"authentication_login_with_qr" = "Skrá inn með QR-kóða";
|
||||||
|
|
|
@ -118,3 +118,6 @@
|
||||||
|
|
||||||
/* New file message from a specific person, not referencing a room. */
|
/* New file message from a specific person, not referencing a room. */
|
||||||
"LOCATION_FROM_USER" = "%@ ha condiviso la sua posizione";
|
"LOCATION_FROM_USER" = "%@ ha condiviso la sua posizione";
|
||||||
|
|
||||||
|
/* New voice broadcast from a specific person, not referencing a room. */
|
||||||
|
"VOICE_BROADCAST_FROM_USER" = "%@ ha iniziato una trasmissione vocale";
|
||||||
|
|
|
@ -2665,3 +2665,28 @@
|
||||||
"notice_voice_broadcast_live" = "Trasmissione in diretta";
|
"notice_voice_broadcast_live" = "Trasmissione in diretta";
|
||||||
"wysiwyg_composer_format_action_inline_code" = "Applica formato codice interlinea";
|
"wysiwyg_composer_format_action_inline_code" = "Applica formato codice interlinea";
|
||||||
"user_other_session_security_recommendation_title" = "Altre sessioni";
|
"user_other_session_security_recommendation_title" = "Altre sessioni";
|
||||||
|
"poll_timeline_ended_text" = "Sondaggio terminato";
|
||||||
|
"poll_timeline_decryption_error" = "A causa di errori di decifrazione, alcuni voti potrebbero non venire contati";
|
||||||
|
"voice_broadcast_voip_cannot_start_description" = "Non puoi avviare una chiamata perché stai registrando una trasmissione in diretta. Termina la trasmissione per potere iniziare una chiamata.";
|
||||||
|
"voice_broadcast_voip_cannot_start_title" = "Impossibile avviare una chiamata";
|
||||||
|
"voice_message_broadcast_in_progress_title" = "Impossibile iniziare il messaggio vocale";
|
||||||
|
"voice_message_broadcast_in_progress_message" = "Non puoi iniziare un messaggio vocale perché stai registrando una trasmissione in diretta. Termina la trasmissione per potere iniziare un messaggio vocale";
|
||||||
|
"poll_history_no_past_poll_text" = "In questa stanza non ci sono sondaggi passati";
|
||||||
|
"poll_history_no_active_poll_text" = "In questa stanza non ci sono sondaggi attivi";
|
||||||
|
"poll_history_past_segment_title" = "Sondaggi passati";
|
||||||
|
"poll_history_active_segment_title" = "Sondaggi attivi";
|
||||||
|
|
||||||
|
// MARK: - Polls history
|
||||||
|
|
||||||
|
"poll_history_title" = "Cronologia sondaggi";
|
||||||
|
"voice_broadcast_playback_lock_screen_placeholder" = "Trasmissione vocale";
|
||||||
|
"room_details_polls" = "Cronologia sondaggi";
|
||||||
|
"accessibility_selected" = "selezionato";
|
||||||
|
"wysiwyg_composer_format_action_quote" = "Attiva/disattiva citazione";
|
||||||
|
"wysiwyg_composer_format_action_code_block" = "Attiva/disattiva blocco di codice";
|
||||||
|
"wysiwyg_composer_format_action_ordered_list" = "Attiva/disattiva elenco numerato";
|
||||||
|
"wysiwyg_composer_format_action_unordered_list" = "Attiva/disattiva elenco puntato";
|
||||||
|
"poll_timeline_reply_ended_poll" = "Sondaggio terminato";
|
||||||
|
"voice_broadcast_recorder_connection_error" = "Errore di connessione - Registrazione in pausa";
|
||||||
|
"voice_broadcast_connection_error_message" = "Sfortunatamente non riusciamo ad iniziare una registrazione al momento. Riprova più tardi.";
|
||||||
|
"voice_broadcast_connection_error_title" = "Errore di connessione";
|
||||||
|
|
|
@ -1720,7 +1720,7 @@
|
||||||
"pin_protection_reset_alert_action_reset" = "リセット";
|
"pin_protection_reset_alert_action_reset" = "リセット";
|
||||||
"authentication_recaptcha_title" = "あなたは人間ですか?";
|
"authentication_recaptcha_title" = "あなたは人間ですか?";
|
||||||
"authentication_verify_msisdn_waiting_button" = "コードを再送信";
|
"authentication_verify_msisdn_waiting_button" = "コードを再送信";
|
||||||
"authentication_choose_password_submit_button" = "パスワードをリセット";
|
"authentication_choose_password_submit_button" = "パスワードを再設定";
|
||||||
"authentication_choose_password_signout_all_devices" = "全ての端末からサインアウト";
|
"authentication_choose_password_signout_all_devices" = "全ての端末からサインアウト";
|
||||||
"authentication_choose_password_text_field_placeholder" = "新しいパスワード";
|
"authentication_choose_password_text_field_placeholder" = "新しいパスワード";
|
||||||
"authentication_terms_title" = "プライバシーポリシー";
|
"authentication_terms_title" = "プライバシーポリシー";
|
||||||
|
@ -1763,13 +1763,13 @@
|
||||||
"home_context_menu_favourite" = "お気に入り";
|
"home_context_menu_favourite" = "お気に入り";
|
||||||
"all_chats_user_menu_settings" = "ユーザー設定";
|
"all_chats_user_menu_settings" = "ユーザー設定";
|
||||||
"all_chats_edit_layout_show_filters" = "フィルターを表示";
|
"all_chats_edit_layout_show_filters" = "フィルターを表示";
|
||||||
"all_chats_edit_layout_show_recents" = "最近使用したものを表示";
|
"all_chats_edit_layout_show_recents" = "最近の履歴を表示";
|
||||||
"all_chats_edit_layout_alphabetical_order" = "アルファベット順で並び替え";
|
"all_chats_edit_layout_alphabetical_order" = "アルファベット順で並び替え";
|
||||||
"all_chats_edit_layout_activity_order" = "アクティビティで並び替え";
|
"all_chats_edit_layout_activity_order" = "アクティビティで並び替え";
|
||||||
"space_selector_create_space" = "スペースを作成";
|
"space_selector_create_space" = "スペースを作成";
|
||||||
"space_selector_empty_view_information" = "スペースは、ルームや連絡先をグループ化する方法です。以下からスペースを作成できます。";
|
"space_selector_empty_view_information" = "スペースは、ルームと連絡先をまとめる方法です。はじめに、スペースを作成しましょう。";
|
||||||
"all_chats_all_filter" = "全て";
|
"all_chats_all_filter" = "全て";
|
||||||
"all_chats_edit_layout_recents" = "最近";
|
"all_chats_edit_layout_recents" = "履歴";
|
||||||
"all_chats_edit_layout_unreads" = "未読";
|
"all_chats_edit_layout_unreads" = "未読";
|
||||||
"all_chats_section_title" = "チャット";
|
"all_chats_section_title" = "チャット";
|
||||||
|
|
||||||
|
@ -1799,3 +1799,5 @@
|
||||||
"service_terms_modal_information_title_identity_server" = "IDサーバー";
|
"service_terms_modal_information_title_identity_server" = "IDサーバー";
|
||||||
"location_sharing_invalid_power_level_message" = "位置情報(ライブ)の共有には適切な権限が必要です。";
|
"location_sharing_invalid_power_level_message" = "位置情報(ライブ)の共有には適切な権限が必要です。";
|
||||||
"location_sharing_live_error" = "位置情報(ライブ)のエラー";
|
"location_sharing_live_error" = "位置情報(ライブ)のエラー";
|
||||||
|
"all_chats_onboarding_page_title3" = "フィードバックを送信";
|
||||||
|
"all_chats_edit_layout" = "レイアウトの設定";
|
||||||
|
|
|
@ -168,3 +168,6 @@
|
||||||
|
|
||||||
/* New file message from a specific person, not referencing a room. */
|
/* New file message from a specific person, not referencing a room. */
|
||||||
"LOCATION_FROM_USER" = "%@ zdieľal/a svoju polohu";
|
"LOCATION_FROM_USER" = "%@ zdieľal/a svoju polohu";
|
||||||
|
|
||||||
|
/* New voice broadcast from a specific person, not referencing a room. */
|
||||||
|
"VOICE_BROADCAST_FROM_USER" = "%@ začal/a hlasové vysielanie";
|
||||||
|
|
|
@ -2891,3 +2891,32 @@
|
||||||
"poll_timeline_decryption_error" = "Z dôvodu chýb v dešifrovaní sa niektoré hlasy nemusia započítať";
|
"poll_timeline_decryption_error" = "Z dôvodu chýb v dešifrovaní sa niektoré hlasy nemusia započítať";
|
||||||
"voice_message_broadcast_in_progress_message" = "Nemôžete spustiť hlasovú správu, pretože práve nahrávate živé vysielanie. Ukončite prosím živé vysielanie, aby ste mohli začať nahrávať hlasovú správu";
|
"voice_message_broadcast_in_progress_message" = "Nemôžete spustiť hlasovú správu, pretože práve nahrávate živé vysielanie. Ukončite prosím živé vysielanie, aby ste mohli začať nahrávať hlasovú správu";
|
||||||
"voice_message_broadcast_in_progress_title" = "Nemožno spustiť hlasovú správu";
|
"voice_message_broadcast_in_progress_title" = "Nemožno spustiť hlasovú správu";
|
||||||
|
"poll_timeline_ended_text" = "Ukončil anketu";
|
||||||
|
"voice_broadcast_voip_cannot_start_description" = "Nemôžete spustiť hovor, pretože práve nahrávate živé vysielanie. Ukončite živé vysielanie, aby ste mohli začať hovor.";
|
||||||
|
"voice_broadcast_voip_cannot_start_title" = "Nie je možné začať hovor";
|
||||||
|
"poll_history_no_past_poll_text" = "V tejto miestnosti nie sú žiadne predchádzajúce ankety";
|
||||||
|
"poll_history_no_active_poll_text" = "V tejto miestnosti nie sú žiadne aktívne ankety";
|
||||||
|
"poll_history_past_segment_title" = "Predchádzajúce ankety";
|
||||||
|
"poll_history_active_segment_title" = "Aktívne ankety";
|
||||||
|
|
||||||
|
// MARK: - Polls history
|
||||||
|
|
||||||
|
"poll_history_title" = "História ankety";
|
||||||
|
"room_details_polls" = "História ankety";
|
||||||
|
"accessibility_selected" = "vybrané";
|
||||||
|
"voice_broadcast_connection_error_message" = "Bohužiaľ teraz nemôžeme spustiť nahrávanie. Skúste to prosím neskôr.";
|
||||||
|
"voice_broadcast_connection_error_title" = "Chyba pripojenia";
|
||||||
|
"voice_broadcast_playback_lock_screen_placeholder" = "Hlasové vysielanie";
|
||||||
|
"wysiwyg_composer_format_action_quote" = "Prepínanie citácie";
|
||||||
|
"wysiwyg_composer_format_action_code_block" = "Prepnutie bloku kódu";
|
||||||
|
"wysiwyg_composer_format_action_ordered_list" = "Prepínanie číslovaného zoznamu";
|
||||||
|
"wysiwyg_composer_format_action_unordered_list" = "Prepnúť zoznam s odrážkami";
|
||||||
|
"voice_broadcast_recorder_connection_error" = "Chyba pripojenia - nahrávanie pozastavené";
|
||||||
|
"poll_timeline_reply_ended_poll" = "Ukončená anketa";
|
||||||
|
|
||||||
|
// MARK: - Launch loading
|
||||||
|
|
||||||
|
"launch_loading_migrating_data" = "Migrácia údajov\n%@ %%";
|
||||||
|
"settings_labs_disable_crypto_sdk" = "Crypto SDK je povolené. Ak to chcete vypnúť, preinštalujte prosím aplikáciu";
|
||||||
|
"settings_labs_confirm_crypto_sdk" = "Túto akciu nemožno vrátiť späť";
|
||||||
|
"settings_labs_enable_crypto_sdk" = "Zapnúť nové Crypto SDK využívajúce Rust";
|
||||||
|
|
|
@ -2676,3 +2676,14 @@
|
||||||
"notice_voice_broadcast_ended" = "%@ përfundoi një transmetim zanor.";
|
"notice_voice_broadcast_ended" = "%@ përfundoi një transmetim zanor.";
|
||||||
"notice_voice_broadcast_live" = "Transmetim i drejtëpërdrejtë";
|
"notice_voice_broadcast_live" = "Transmetim i drejtëpërdrejtë";
|
||||||
"user_other_session_security_recommendation_title" = "Sesione të tjerë";
|
"user_other_session_security_recommendation_title" = "Sesione të tjerë";
|
||||||
|
"poll_timeline_ended_text" = "Përfundoi pyetësori";
|
||||||
|
"poll_timeline_decryption_error" = "Për shkak gabimesh shfshehtëzimi, mund të mos jenë numëruar disa vota";
|
||||||
|
"poll_history_no_past_poll_text" = "Në këtë dhomë s’ka pyetësorë të dikurshëm";
|
||||||
|
"poll_history_no_active_poll_text" = "Në këtë dhomë s’ka pyetësorë aktivë";
|
||||||
|
"poll_history_past_segment_title" = "Pyetësorë të dikurshëm";
|
||||||
|
"poll_history_active_segment_title" = "Pyetësorë aktivë";
|
||||||
|
"voice_broadcast_playback_lock_screen_placeholder" = "Transmetim zanor";
|
||||||
|
"voice_broadcast_voip_cannot_start_description" = "S’mund të niset thirrje, ngaqë aktualisht po regjistroni një transmetim të drejtpërdrejtë. Ju lutemi, përfundoni transmetimin e drejtpërdrejtë, që të mund të nisni një thirrje.";
|
||||||
|
"voice_broadcast_voip_cannot_start_title" = "S’niset dot një thirrje";
|
||||||
|
"voice_message_broadcast_in_progress_message" = "S’mund të niset mesazh zanor, ngaqë aktualisht po regjistroni një transmetim të drejtpërdrejtë. Ju lutemi, përfundoni transmetimin e drejtpërdrejtë, që të mund të nisni regjistrimin e një mesazhi zanor";
|
||||||
|
"voice_message_broadcast_in_progress_title" = "S’niset dot mesazh zanor";
|
||||||
|
|
|
@ -118,3 +118,6 @@
|
||||||
|
|
||||||
/* New file message from a specific person, not referencing a room. */
|
/* New file message from a specific person, not referencing a room. */
|
||||||
"LOCATION_FROM_USER" = "%@ delade sin plats";
|
"LOCATION_FROM_USER" = "%@ delade sin plats";
|
||||||
|
|
||||||
|
/* New voice broadcast from a specific person, not referencing a room. */
|
||||||
|
"VOICE_BROADCAST_FROM_USER" = "%@ påbörjade en röstsändning";
|
||||||
|
|
|
@ -2310,7 +2310,7 @@
|
||||||
"authentication_terms_policy_url_error" = "Kan inte hitta den valda policyn. Vänligen pröva igen senare.";
|
"authentication_terms_policy_url_error" = "Kan inte hitta den valda policyn. Vänligen pröva igen senare.";
|
||||||
/* The placeholder will show the homeserver's domain */
|
/* The placeholder will show the homeserver's domain */
|
||||||
"authentication_terms_message" = "Vänligen läs villkor och policyer för %@";
|
"authentication_terms_message" = "Vänligen läs villkor och policyer för %@";
|
||||||
"authentication_terms_title" = "Serverpolicyer";
|
"authentication_terms_title" = "Sekretesspolicyer";
|
||||||
"authentication_verify_msisdn_invalid_phone_number" = "Ogiltigt telefonnummer";
|
"authentication_verify_msisdn_invalid_phone_number" = "Ogiltigt telefonnummer";
|
||||||
"authentication_verify_msisdn_waiting_button" = "Skicka kod igen";
|
"authentication_verify_msisdn_waiting_button" = "Skicka kod igen";
|
||||||
/* The placeholder will show the phone number that was entered. */
|
/* The placeholder will show the phone number that was entered. */
|
||||||
|
@ -2363,3 +2363,112 @@
|
||||||
|
|
||||||
// MARK: Authentication
|
// MARK: Authentication
|
||||||
"authentication_registration_title" = "Skapa ditt konto";
|
"authentication_registration_title" = "Skapa ditt konto";
|
||||||
|
"voice_broadcast_time_left" = "%@ kvar";
|
||||||
|
"all_chats_empty_list_placeholder_title" = "Du är ikapp.";
|
||||||
|
"all_chats_empty_view_information" = "Den säkra allt-i-ett-chattappen för lag, vänner och organisationer. Skapa en chatt, eller gå med i ett existerande rum, för att komma igång.";
|
||||||
|
"all_chats_empty_space_information" = "Utrymmen är ett nytt sätt att gruppera rum och personer. Lägg till ett existerande rum, eller skapa ett nytt, med knappen nere till höger.";
|
||||||
|
"all_chats_empty_view_title" = "%@\nser lite tom ut.";
|
||||||
|
"all_chats_all_filter" = "Alla";
|
||||||
|
"all_chats_edit_layout_alphabetical_order" = "Sortera A-Ö";
|
||||||
|
"all_chats_edit_layout_activity_order" = "Sortera efter aktivitet";
|
||||||
|
"all_chats_edit_layout_show_filters" = "Visa filter";
|
||||||
|
"all_chats_edit_layout_show_recents" = "Visa nyliga";
|
||||||
|
"all_chats_edit_layout_sorting_options_title" = "Sortera meddelanden efter";
|
||||||
|
"all_chats_edit_layout_pin_spaces_title" = "Fäst dina utrymmen";
|
||||||
|
"all_chats_edit_layout_add_filters_message" = "Filtrera automatiskt dina meddelanden i valfria kategorier";
|
||||||
|
"all_chats_edit_layout_add_filters_title" = "Filtrera dina meddelanden";
|
||||||
|
"all_chats_edit_layout_add_section_message" = "Fäst sektioner till hem för enkel åtkomst";
|
||||||
|
"all_chats_edit_layout_add_section_title" = "Lägg till sektion i hem";
|
||||||
|
"all_chats_edit_layout_unreads" = "Olästa";
|
||||||
|
"all_chats_edit_layout_recents" = "Nyliga";
|
||||||
|
"all_chats_edit_layout" = "Layoutalternativ";
|
||||||
|
"all_chats_section_title" = "Chattar";
|
||||||
|
|
||||||
|
// MARK: - All Chats
|
||||||
|
|
||||||
|
"all_chats_title" = "Alla chattar";
|
||||||
|
"voice_broadcast_voip_cannot_start_description" = "Du kan inte starta ett samtal eftersom att du för närvarande spelar in en direktsändning. Vänligen avsluta din direktsändning för att starta ett samtal.";
|
||||||
|
"voice_broadcast_voip_cannot_start_title" = "Kan inte starta ett samtal";
|
||||||
|
"voice_broadcast_stop_alert_agree_button" = "Ja, avsluta";
|
||||||
|
"voice_broadcast_stop_alert_description" = "Är du säker på att du vill avsluta din direktsändning? Det här kommer att avsluta sändningen, och den fulla inspelningen kommer att bli tillgänglig i rummet.";
|
||||||
|
"voice_broadcast_stop_alert_title" = "Avsluta direktsändning?";
|
||||||
|
"voice_broadcast_buffering" = "Buffrar…";
|
||||||
|
"voice_broadcast_tile" = "Röstsändning";
|
||||||
|
"voice_broadcast_live" = "Live";
|
||||||
|
"voice_broadcast_playback_loading_error" = "Kunde inte spela den här röstsändningen.";
|
||||||
|
"voice_broadcast_already_in_progress_message" = "Du spelar redan in en röstsändning. Vänligen avsluta din nuvarande röstsändning för att starta en ny.";
|
||||||
|
"voice_broadcast_blocked_by_someone_else_message" = "Någon annan spelar redan in en röstsändning. Vänta på att deras röstsändning avslutas för att starta en ny.";
|
||||||
|
"voice_broadcast_permission_denied_message" = "Du har inte behörigheten som krävs för att starta en röstsändning i det här rummet. Kontakta en rumsadministratör för att uppgradera din behörighet.";
|
||||||
|
|
||||||
|
// MARK: - Voice Broadcast
|
||||||
|
"voice_broadcast_unauthorized_title" = "Du kan inte starta en ny röstsändning";
|
||||||
|
"voice_message_broadcast_in_progress_message" = "Du kan inte starta ett röstmeddelande eftersom att du för närvarande spelar in en direktsändning. Vänligen avsluta din direktsändning för att börja spela in ett röstmeddelande";
|
||||||
|
"voice_message_broadcast_in_progress_title" = "Kan inte starta röstmeddelande";
|
||||||
|
"spaces_subspace_creation_visibility_message" = "Det skapade utrymmet kommer att läggas till i %@.";
|
||||||
|
"spaces_subspace_creation_visibility_title" = "Vad för sorts utrymme vill du skapa?";
|
||||||
|
"spaces_explore_rooms_format" = "Utforska %@";
|
||||||
|
"spaces_create_subspace_title" = "Skapa ett underutrymme";
|
||||||
|
"spaces_add_subspace_title" = "Skapa utrymme inuti %@";
|
||||||
|
"launch_loading_processing_response" = "Hanterar data\n%@ %%";
|
||||||
|
"launch_loading_server_syncing_nth_attempt" = "Synkar med servern\n(%@ försök)";
|
||||||
|
|
||||||
|
// MARK: - Launch loading
|
||||||
|
|
||||||
|
"launch_loading_server_syncing" = "Synkar med servern";
|
||||||
|
"key_verification_alert_body" = "Granska för att försäkra att ditt konto är säkert.";
|
||||||
|
|
||||||
|
// Unverified sessions
|
||||||
|
"key_verification_alert_title" = "Du har overifierade sessioner";
|
||||||
|
"sign_out_confirmation_message" = "Är du säker på att du vill logga ut?";
|
||||||
|
|
||||||
|
// MARK: Sign out warning
|
||||||
|
|
||||||
|
"sign_out" = "Logga ut";
|
||||||
|
// User sessions management
|
||||||
|
"user_sessions_settings" = "Hantera sessioner";
|
||||||
|
"manage_session_sign_out_other_sessions" = "Logga ut ur alla andra sessioner";
|
||||||
|
"manage_session_rename" = "Döp om session";
|
||||||
|
"manage_session_name_info_link" = "Läs mer";
|
||||||
|
/* The placeholder will be replaces with manage_session_name_info_link */
|
||||||
|
"manage_session_name_info" = "Observera att sessionsnamn också är synliga för personer du pratar med. %@";
|
||||||
|
"manage_session_name_hint" = "Anpassade sessionsnamn kan hjälpa dig att känna igen dina enheter lättare.";
|
||||||
|
"settings_labs_enable_voice_broadcast" = "Röstsändning";
|
||||||
|
"settings_labs_enable_wysiwyg_composer" = "Pröva den nya riktextredigeraren";
|
||||||
|
"settings_labs_enable_new_app_layout" = "Ny applikationslayout";
|
||||||
|
"settings_labs_enable_new_client_info_feature" = "Spara klientens namn, version och URL för att lättare känna igen sessioner i sessionshanteraren";
|
||||||
|
"settings_labs_enable_new_session_manager" = "My sessionshanterare";
|
||||||
|
"room_first_message_placeholder" = "Skicka ditt första meddelande…";
|
||||||
|
"password_policy_pwd_in_dict_error" = "Det här lösenordet har hittats i en ordlista, och tillåts inte.";
|
||||||
|
"password_policy_weak_pwd_error" = "Det här lösenordet är för svagt. Det måste innehålla minst 8 tecken, och minst ett tecken av varje typ: stor bokstav, liten bokstav, siffra och specialtecken.";
|
||||||
|
|
||||||
|
// MARK: Password policy errors
|
||||||
|
"password_policy_too_short_pwd_error" = "För kort lösenord";
|
||||||
|
"authentication_qr_login_failure_retry" = "Pröva igen";
|
||||||
|
"authentication_qr_login_failure_request_timed_out" = "Länkningen slutfördes inte inom den krävda tiden.";
|
||||||
|
"authentication_qr_login_failure_request_denied" = "Förfrågan nekades på en andra enheten.";
|
||||||
|
"authentication_qr_login_failure_invalid_qr" = "QR-kod är ogiltig.";
|
||||||
|
"authentication_qr_login_failure_title" = "Länkning misslyckades";
|
||||||
|
"authentication_qr_login_loading_signed_in" = "Du är nu inloggad på din andra enhet.";
|
||||||
|
"authentication_qr_login_loading_waiting_signin" = "Väntar på att enheten loggar in.";
|
||||||
|
"authentication_qr_login_loading_connecting_device" = "Ansluter till enhet";
|
||||||
|
"authentication_qr_login_confirm_alert" = "Vänligen försäkra att du känner till källan till den här koden. Genom att länka enheter så ger du någon full åtkomst till ditt konto.";
|
||||||
|
"authentication_qr_login_confirm_subtitle" = "Bekräfta att koden nedan matchar den andra enheten:";
|
||||||
|
"authentication_qr_login_confirm_title" = "Säker kommunikation etablerad";
|
||||||
|
"authentication_qr_login_scan_subtitle" = "Placera QR-koden i rutan nedan";
|
||||||
|
"authentication_qr_login_scan_title" = "Skanna QR-kod";
|
||||||
|
"authentication_qr_login_display_step2" = "Välj 'Logga in med QR-kod'";
|
||||||
|
"authentication_qr_login_display_step1" = "Öppna Element på din andra enhet";
|
||||||
|
"authentication_qr_login_display_subtitle" = "Skanna QR-koden nedan med din enhet som är utloggad.";
|
||||||
|
"authentication_qr_login_display_title" = "Länka en enhet";
|
||||||
|
"authentication_qr_login_start_display_qr" = "Visa QR-kod på den här enheten";
|
||||||
|
"authentication_qr_login_start_need_alternative" = "Behöver du en alternativ metod?";
|
||||||
|
"authentication_qr_login_start_step4" = "Välj 'Visa QR-kod på den här enheten'";
|
||||||
|
"authentication_qr_login_start_step3" = "Välj 'Länka en enhet'";
|
||||||
|
"authentication_qr_login_start_step2" = "Gå till Inställningar -> Säkerhet & sekretess";
|
||||||
|
"authentication_qr_login_start_step1" = "Öppna Element på den andra enheten";
|
||||||
|
"authentication_qr_login_start_subtitle" = "Använd kameran på den här enheten för att skanna QR-koden som visas på den andra enheten:";
|
||||||
|
"authentication_qr_login_start_title" = "Skanna QR-kod";
|
||||||
|
"authentication_choose_password_not_verified_message" = "Kolla din inkorg";
|
||||||
|
"authentication_choose_password_not_verified_title" = "E-post inte verifierad";
|
||||||
|
"authentication_login_with_qr" = "Logga in med QR-kod";
|
||||||
|
"invite_to" = "Bjud in till %@";
|
||||||
|
|
|
@ -118,3 +118,6 @@
|
||||||
|
|
||||||
/* New file message from a specific person, not referencing a room. */
|
/* New file message from a specific person, not referencing a room. */
|
||||||
"LOCATION_FROM_USER" = "%@ надсилає дані про своє місцеперебування";
|
"LOCATION_FROM_USER" = "%@ надсилає дані про своє місцеперебування";
|
||||||
|
|
||||||
|
/* New voice broadcast from a specific person, not referencing a room. */
|
||||||
|
"VOICE_BROADCAST_FROM_USER" = "%@ розпочинає голосову трансляцію";
|
||||||
|
|
|
@ -2893,3 +2893,32 @@
|
||||||
"poll_timeline_decryption_error" = "Через помилки під час розшифрування деякі голоси можуть бути не враховані";
|
"poll_timeline_decryption_error" = "Через помилки під час розшифрування деякі голоси можуть бути не враховані";
|
||||||
"voice_message_broadcast_in_progress_title" = "Неможливо розпочати запис голосового повідомлення";
|
"voice_message_broadcast_in_progress_title" = "Неможливо розпочати запис голосового повідомлення";
|
||||||
"voice_message_broadcast_in_progress_message" = "Ви не можете розпочати запис голосового повідомлення, оскільки зараз триває запис трансляції наживо. Будь ласка, завершіть трансляцію, щоб розпочати запис голосового повідомлення";
|
"voice_message_broadcast_in_progress_message" = "Ви не можете розпочати запис голосового повідомлення, оскільки зараз триває запис трансляції наживо. Будь ласка, завершіть трансляцію, щоб розпочати запис голосового повідомлення";
|
||||||
|
"poll_timeline_ended_text" = "Опитування завершено";
|
||||||
|
"voice_broadcast_voip_cannot_start_description" = "Ви не можете розпочати виклик, оскільки зараз відбувається запис трансляції наживо. Завершіть трансляцію, щоб розпочати виклик.";
|
||||||
|
"voice_broadcast_voip_cannot_start_title" = "Неможливо розпочати виклик";
|
||||||
|
"poll_history_no_past_poll_text" = "У цій кімнаті немає минулих опитувань";
|
||||||
|
"poll_history_no_active_poll_text" = "У цій кімнаті немає активних опитувань";
|
||||||
|
"poll_history_past_segment_title" = "Минулі опитування";
|
||||||
|
"poll_history_active_segment_title" = "Активні опитування";
|
||||||
|
|
||||||
|
// MARK: - Polls history
|
||||||
|
|
||||||
|
"poll_history_title" = "Історія опитувань";
|
||||||
|
"room_details_polls" = "Історія опитувань";
|
||||||
|
"accessibility_selected" = "вибрано";
|
||||||
|
"voice_broadcast_playback_lock_screen_placeholder" = "Голосові трансляції";
|
||||||
|
"voice_broadcast_connection_error_message" = "На жаль, ми не можемо розпочати запис прямо зараз. Повторіть спробу пізніше.";
|
||||||
|
"voice_broadcast_connection_error_title" = "Помилка з'єднання";
|
||||||
|
"wysiwyg_composer_format_action_quote" = "Перемкнути цитування";
|
||||||
|
"wysiwyg_composer_format_action_code_block" = "Перемкнути блок коду";
|
||||||
|
"wysiwyg_composer_format_action_ordered_list" = "Перемкнути на нумерований список";
|
||||||
|
"wysiwyg_composer_format_action_unordered_list" = "Перемкнути на маркований список";
|
||||||
|
"voice_broadcast_recorder_connection_error" = "Помилка з'єднання - Запис призупинено";
|
||||||
|
"poll_timeline_reply_ended_poll" = "Завершене опитування";
|
||||||
|
|
||||||
|
// MARK: - Launch loading
|
||||||
|
|
||||||
|
"launch_loading_migrating_data" = "Перенесення даних\n%@ %%";
|
||||||
|
"settings_labs_disable_crypto_sdk" = "Crypto SDK увімкнено. Щоб вимкнути, перевстановіть застосунок";
|
||||||
|
"settings_labs_confirm_crypto_sdk" = "Дію не можна скасувати";
|
||||||
|
"settings_labs_enable_crypto_sdk" = "Увімкнути новий заснований на rust Crypto SDK";
|
||||||
|
|
|
@ -123,3 +123,6 @@
|
||||||
|
|
||||||
/* New file message from a specific person, not referencing a room. */
|
/* New file message from a specific person, not referencing a room. */
|
||||||
"LOCATION_FROM_USER" = "%@ 分享了他们的位置";
|
"LOCATION_FROM_USER" = "%@ 分享了他们的位置";
|
||||||
|
|
||||||
|
/* New voice broadcast from a specific person, not referencing a room. */
|
||||||
|
"VOICE_BROADCAST_FROM_USER" = "%@开始语音广播";
|
||||||
|
|
|
@ -196,7 +196,7 @@
|
||||||
"room_event_action_copy" = "复制";
|
"room_event_action_copy" = "复制";
|
||||||
"room_event_action_quote" = "引用";
|
"room_event_action_quote" = "引用";
|
||||||
"room_event_action_redact" = "移除";
|
"room_event_action_redact" = "移除";
|
||||||
"room_event_action_more" = "移动";
|
"room_event_action_more" = "更多";
|
||||||
"room_event_action_share" = "分享";
|
"room_event_action_share" = "分享";
|
||||||
"room_event_action_permalink" = "复制消息的链接";
|
"room_event_action_permalink" = "复制消息的链接";
|
||||||
"room_event_action_view_source" = "查看源数据";
|
"room_event_action_view_source" = "查看源数据";
|
||||||
|
@ -2231,3 +2231,47 @@
|
||||||
"onboarding_congratulations_home_button" = "带我到主页";
|
"onboarding_congratulations_home_button" = "带我到主页";
|
||||||
"onboarding_use_case_message" = "我们将帮助你连接";
|
"onboarding_use_case_message" = "我们将帮助你连接";
|
||||||
"invite_to" = "邀请到%@";
|
"invite_to" = "邀请到%@";
|
||||||
|
"threads_empty_title" = "保持讨论的有条理性";
|
||||||
|
"threads_action_my_threads" = "我的消息列";
|
||||||
|
"threads_action_all_threads" = "所有消息列";
|
||||||
|
"threads_title" = "消息列";
|
||||||
|
"thread_copy_link_to_thread" = "将链接复制到消息列";
|
||||||
|
|
||||||
|
// MARK: Threads
|
||||||
|
"room_thread_title" = "消息列";
|
||||||
|
"room_accessibility_record_voice_message_hint" = "双击并保持录音。";
|
||||||
|
"room_accessibility_record_voice_message" = "录制语音消息";
|
||||||
|
"room_accessibility_thread_more" = "更多";
|
||||||
|
"room_accessibility_threads" = "消息列";
|
||||||
|
"room_event_copy_link_info" = "链接已复制到剪贴板。";
|
||||||
|
"room_event_action_reply_in_thread" = "消息列";
|
||||||
|
"room_event_action_view_in_room" = "在房间浏览";
|
||||||
|
"room_first_message_placeholder" = "发送您的第一条消息……";
|
||||||
|
"room_participants_invite_prompt_to_msg" = "您确定要邀请%@ 到 %@吗?";
|
||||||
|
"room_participants_leave_success" = "离开房间";
|
||||||
|
"room_participants_leave_processing" = "离开";
|
||||||
|
"search_filter_placeholder" = "过滤";
|
||||||
|
"password_policy_pwd_in_dict_error" = "此密码已在字典中找到,不允许使用。";
|
||||||
|
"password_policy_weak_pwd_error" = "此密码太弱了。它必须包含至少8个字符,每种类型至少有一个字符: 大写、小写、数字和特殊字符。";
|
||||||
|
|
||||||
|
// MARK: Password policy errors
|
||||||
|
"password_policy_too_short_pwd_error" = "密码过短";
|
||||||
|
"authentication_qr_login_failure_retry" = "再试一次";
|
||||||
|
"authentication_qr_login_failure_request_timed_out" = "连接没有在规定的时间内完成。";
|
||||||
|
"authentication_qr_login_failure_request_denied" = "请求在另一个设备上被拒绝。";
|
||||||
|
"authentication_qr_login_failure_invalid_qr" = "二维码无效。";
|
||||||
|
"authentication_qr_login_failure_title" = "连接失败";
|
||||||
|
"authentication_qr_login_loading_signed_in" = "您现在已经登录到另一个设备上。";
|
||||||
|
"authentication_qr_login_loading_waiting_signin" = "等待设备登录。";
|
||||||
|
"authentication_qr_login_loading_connecting_device" = "连接到设备";
|
||||||
|
"authentication_qr_login_confirm_alert" = "请确保您知道此代码的来源。通过连接设备,您将为某人提供对您帐户的完全访问权限。";
|
||||||
|
"authentication_qr_login_confirm_subtitle" = "确认下面的代码与您的其他设备匹配:";
|
||||||
|
"authentication_qr_login_confirm_title" = "建立安全连接";
|
||||||
|
"authentication_qr_login_scan_subtitle" = "将二维码放置在下面的方框中";
|
||||||
|
"authentication_qr_login_scan_title" = "扫描二维码";
|
||||||
|
"authentication_qr_login_display_step2" = "选择“以二维码登入”";
|
||||||
|
"authentication_qr_login_display_step1" = "在您的其它设备中打开Element";
|
||||||
|
"onboarding_splash_page_4_title_no_pun" = "为您的团队发送消息。";
|
||||||
|
"user_session_learn_more" = "了解更多";
|
||||||
|
"manage_session_name_info_link" = "了解更多";
|
||||||
|
"threads_beta_information_link" = "了解更多";
|
||||||
|
|
|
@ -24,7 +24,6 @@ extension MXKTableViewCellWithTextView: Themable {
|
||||||
func update(theme: Theme) {
|
func update(theme: Theme) {
|
||||||
mxkTextView.backgroundColor = .clear
|
mxkTextView.backgroundColor = .clear
|
||||||
mxkTextView.textColor = theme.textPrimaryColor
|
mxkTextView.textColor = theme.textPrimaryColor
|
||||||
mxkTextView.tintColor = theme.tintColor
|
|
||||||
backgroundColor = theme.backgroundColor
|
backgroundColor = theme.backgroundColor
|
||||||
contentView.backgroundColor = .clear
|
contentView.backgroundColor = .clear
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,6 +110,7 @@ internal class Asset: NSObject {
|
||||||
internal static let strikethrough = ImageAsset(name: "Strikethrough")
|
internal static let strikethrough = ImageAsset(name: "Strikethrough")
|
||||||
internal static let underlined = ImageAsset(name: "Underlined")
|
internal static let underlined = ImageAsset(name: "Underlined")
|
||||||
internal static let bulletList = ImageAsset(name: "bullet_list")
|
internal static let bulletList = ImageAsset(name: "bullet_list")
|
||||||
|
internal static let codeBlock = ImageAsset(name: "code_block")
|
||||||
internal static let indentDecrease = ImageAsset(name: "indent_decrease")
|
internal static let indentDecrease = ImageAsset(name: "indent_decrease")
|
||||||
internal static let maximiseComposer = ImageAsset(name: "maximise_composer")
|
internal static let maximiseComposer = ImageAsset(name: "maximise_composer")
|
||||||
internal static let minimiseComposer = ImageAsset(name: "minimise_composer")
|
internal static let minimiseComposer = ImageAsset(name: "minimise_composer")
|
||||||
|
@ -285,6 +286,7 @@ internal class Asset: NSObject {
|
||||||
internal static let modIcon = ImageAsset(name: "mod_icon")
|
internal static let modIcon = ImageAsset(name: "mod_icon")
|
||||||
internal static let moreReactions = ImageAsset(name: "more_reactions")
|
internal static let moreReactions = ImageAsset(name: "more_reactions")
|
||||||
internal static let notifications = ImageAsset(name: "notifications")
|
internal static let notifications = ImageAsset(name: "notifications")
|
||||||
|
internal static let pollHistory = ImageAsset(name: "pollHistory")
|
||||||
internal static let reactionsMoreAction = ImageAsset(name: "reactions_more_action")
|
internal static let reactionsMoreAction = ImageAsset(name: "reactions_more_action")
|
||||||
internal static let roomAccessInfoHeaderIcon = ImageAsset(name: "room_access_info_header_icon")
|
internal static let roomAccessInfoHeaderIcon = ImageAsset(name: "room_access_info_header_icon")
|
||||||
internal static let scrollup = ImageAsset(name: "scrollup")
|
internal static let scrollup = ImageAsset(name: "scrollup")
|
||||||
|
|
|
@ -27,6 +27,10 @@ public class VectorL10n: NSObject {
|
||||||
public static var accessibilityCheckboxLabel: String {
|
public static var accessibilityCheckboxLabel: String {
|
||||||
return VectorL10n.tr("Vector", "accessibility_checkbox_label")
|
return VectorL10n.tr("Vector", "accessibility_checkbox_label")
|
||||||
}
|
}
|
||||||
|
/// selected
|
||||||
|
public static var accessibilitySelected: String {
|
||||||
|
return VectorL10n.tr("Vector", "accessibility_selected")
|
||||||
|
}
|
||||||
/// Unable to verify email address. Please check your email and click on the link it contains. Once this is done, click continue
|
/// Unable to verify email address. Please check your email and click on the link it contains. Once this is done, click continue
|
||||||
public static var accountEmailValidationError: String {
|
public static var accountEmailValidationError: String {
|
||||||
return VectorL10n.tr("Vector", "account_email_validation_error")
|
return VectorL10n.tr("Vector", "account_email_validation_error")
|
||||||
|
@ -3179,6 +3183,10 @@ public class VectorL10n: NSObject {
|
||||||
public static var later: String {
|
public static var later: String {
|
||||||
return VectorL10n.tr("Vector", "later")
|
return VectorL10n.tr("Vector", "later")
|
||||||
}
|
}
|
||||||
|
/// Migrating data\n%@ %%
|
||||||
|
public static func launchLoadingMigratingData(_ p1: String) -> String {
|
||||||
|
return VectorL10n.tr("Vector", "launch_loading_migrating_data", p1)
|
||||||
|
}
|
||||||
/// Processing data\n%@ %%
|
/// Processing data\n%@ %%
|
||||||
public static func launchLoadingProcessingResponse(_ p1: String) -> String {
|
public static func launchLoadingProcessingResponse(_ p1: String) -> String {
|
||||||
return VectorL10n.tr("Vector", "launch_loading_processing_response", p1)
|
return VectorL10n.tr("Vector", "launch_loading_processing_response", p1)
|
||||||
|
@ -4839,6 +4847,26 @@ public class VectorL10n: NSObject {
|
||||||
public static var pollEditFormUpdateFailureTitle: String {
|
public static var pollEditFormUpdateFailureTitle: String {
|
||||||
return VectorL10n.tr("Vector", "poll_edit_form_update_failure_title")
|
return VectorL10n.tr("Vector", "poll_edit_form_update_failure_title")
|
||||||
}
|
}
|
||||||
|
/// Active polls
|
||||||
|
public static var pollHistoryActiveSegmentTitle: String {
|
||||||
|
return VectorL10n.tr("Vector", "poll_history_active_segment_title")
|
||||||
|
}
|
||||||
|
/// There are no active polls in this room
|
||||||
|
public static var pollHistoryNoActivePollText: String {
|
||||||
|
return VectorL10n.tr("Vector", "poll_history_no_active_poll_text")
|
||||||
|
}
|
||||||
|
/// There are no past polls in this room
|
||||||
|
public static var pollHistoryNoPastPollText: String {
|
||||||
|
return VectorL10n.tr("Vector", "poll_history_no_past_poll_text")
|
||||||
|
}
|
||||||
|
/// Past polls
|
||||||
|
public static var pollHistoryPastSegmentTitle: String {
|
||||||
|
return VectorL10n.tr("Vector", "poll_history_past_segment_title")
|
||||||
|
}
|
||||||
|
/// Poll history
|
||||||
|
public static var pollHistoryTitle: String {
|
||||||
|
return VectorL10n.tr("Vector", "poll_history_title")
|
||||||
|
}
|
||||||
/// Due to decryption errors, some votes may not be counted
|
/// Due to decryption errors, some votes may not be counted
|
||||||
public static var pollTimelineDecryptionError: String {
|
public static var pollTimelineDecryptionError: String {
|
||||||
return VectorL10n.tr("Vector", "poll_timeline_decryption_error")
|
return VectorL10n.tr("Vector", "poll_timeline_decryption_error")
|
||||||
|
@ -4859,6 +4887,10 @@ public class VectorL10n: NSObject {
|
||||||
public static var pollTimelineOneVote: String {
|
public static var pollTimelineOneVote: String {
|
||||||
return VectorL10n.tr("Vector", "poll_timeline_one_vote")
|
return VectorL10n.tr("Vector", "poll_timeline_one_vote")
|
||||||
}
|
}
|
||||||
|
/// Ended poll
|
||||||
|
public static var pollTimelineReplyEndedPoll: String {
|
||||||
|
return VectorL10n.tr("Vector", "poll_timeline_reply_ended_poll")
|
||||||
|
}
|
||||||
/// Final results based on %lu votes
|
/// Final results based on %lu votes
|
||||||
public static func pollTimelineTotalFinalResults(_ p1: Int) -> String {
|
public static func pollTimelineTotalFinalResults(_ p1: Int) -> String {
|
||||||
return VectorL10n.tr("Vector", "poll_timeline_total_final_results", p1)
|
return VectorL10n.tr("Vector", "poll_timeline_total_final_results", p1)
|
||||||
|
@ -5503,6 +5535,10 @@ public class VectorL10n: NSObject {
|
||||||
public static var roomDetailsPhotoForDm: String {
|
public static var roomDetailsPhotoForDm: String {
|
||||||
return VectorL10n.tr("Vector", "room_details_photo_for_dm")
|
return VectorL10n.tr("Vector", "room_details_photo_for_dm")
|
||||||
}
|
}
|
||||||
|
/// Poll history
|
||||||
|
public static var roomDetailsPolls: String {
|
||||||
|
return VectorL10n.tr("Vector", "room_details_polls")
|
||||||
|
}
|
||||||
/// Suggest to space members
|
/// Suggest to space members
|
||||||
public static var roomDetailsPromoteRoomSuggestTitle: String {
|
public static var roomDetailsPromoteRoomSuggestTitle: String {
|
||||||
return VectorL10n.tr("Vector", "room_details_promote_room_suggest_title")
|
return VectorL10n.tr("Vector", "room_details_promote_room_suggest_title")
|
||||||
|
@ -7547,10 +7583,18 @@ public class VectorL10n: NSObject {
|
||||||
public static var settingsLabs: String {
|
public static var settingsLabs: String {
|
||||||
return VectorL10n.tr("Vector", "settings_labs")
|
return VectorL10n.tr("Vector", "settings_labs")
|
||||||
}
|
}
|
||||||
|
/// This action cannot be undone
|
||||||
|
public static var settingsLabsConfirmCryptoSdk: String {
|
||||||
|
return VectorL10n.tr("Vector", "settings_labs_confirm_crypto_sdk")
|
||||||
|
}
|
||||||
/// Create conference calls with jitsi
|
/// Create conference calls with jitsi
|
||||||
public static var settingsLabsCreateConferenceWithJitsi: String {
|
public static var settingsLabsCreateConferenceWithJitsi: String {
|
||||||
return VectorL10n.tr("Vector", "settings_labs_create_conference_with_jitsi")
|
return VectorL10n.tr("Vector", "settings_labs_create_conference_with_jitsi")
|
||||||
}
|
}
|
||||||
|
/// Crypto SDK is enabled. To disable please reinstall the app
|
||||||
|
public static var settingsLabsDisableCryptoSdk: String {
|
||||||
|
return VectorL10n.tr("Vector", "settings_labs_disable_crypto_sdk")
|
||||||
|
}
|
||||||
/// End-to-End Encryption
|
/// End-to-End Encryption
|
||||||
public static var settingsLabsE2eEncryption: String {
|
public static var settingsLabsE2eEncryption: String {
|
||||||
return VectorL10n.tr("Vector", "settings_labs_e2e_encryption")
|
return VectorL10n.tr("Vector", "settings_labs_e2e_encryption")
|
||||||
|
@ -7563,6 +7607,10 @@ public class VectorL10n: NSObject {
|
||||||
public static var settingsLabsEnableAutoReportDecryptionErrors: String {
|
public static var settingsLabsEnableAutoReportDecryptionErrors: String {
|
||||||
return VectorL10n.tr("Vector", "settings_labs_enable_auto_report_decryption_errors")
|
return VectorL10n.tr("Vector", "settings_labs_enable_auto_report_decryption_errors")
|
||||||
}
|
}
|
||||||
|
/// Enable new rust-based Crypto SDK
|
||||||
|
public static var settingsLabsEnableCryptoSdk: String {
|
||||||
|
return VectorL10n.tr("Vector", "settings_labs_enable_crypto_sdk")
|
||||||
|
}
|
||||||
/// Live location sharing - share current location (active development, and temporarily, locations persist in room history)
|
/// Live location sharing - share current location (active development, and temporarily, locations persist in room history)
|
||||||
public static var settingsLabsEnableLiveLocationSharing: String {
|
public static var settingsLabsEnableLiveLocationSharing: String {
|
||||||
return VectorL10n.tr("Vector", "settings_labs_enable_live_location_sharing")
|
return VectorL10n.tr("Vector", "settings_labs_enable_live_location_sharing")
|
||||||
|
@ -9179,6 +9227,14 @@ public class VectorL10n: NSObject {
|
||||||
public static var voiceBroadcastBuffering: String {
|
public static var voiceBroadcastBuffering: String {
|
||||||
return VectorL10n.tr("Vector", "voice_broadcast_buffering")
|
return VectorL10n.tr("Vector", "voice_broadcast_buffering")
|
||||||
}
|
}
|
||||||
|
/// Unfortunately we’re unable to start a recording right now. Please try again later.
|
||||||
|
public static var voiceBroadcastConnectionErrorMessage: String {
|
||||||
|
return VectorL10n.tr("Vector", "voice_broadcast_connection_error_message")
|
||||||
|
}
|
||||||
|
/// Connection error
|
||||||
|
public static var voiceBroadcastConnectionErrorTitle: String {
|
||||||
|
return VectorL10n.tr("Vector", "voice_broadcast_connection_error_title")
|
||||||
|
}
|
||||||
/// Live
|
/// Live
|
||||||
public static var voiceBroadcastLive: String {
|
public static var voiceBroadcastLive: String {
|
||||||
return VectorL10n.tr("Vector", "voice_broadcast_live")
|
return VectorL10n.tr("Vector", "voice_broadcast_live")
|
||||||
|
@ -9191,6 +9247,14 @@ public class VectorL10n: NSObject {
|
||||||
public static var voiceBroadcastPlaybackLoadingError: String {
|
public static var voiceBroadcastPlaybackLoadingError: String {
|
||||||
return VectorL10n.tr("Vector", "voice_broadcast_playback_loading_error")
|
return VectorL10n.tr("Vector", "voice_broadcast_playback_loading_error")
|
||||||
}
|
}
|
||||||
|
/// Voice broadcast
|
||||||
|
public static var voiceBroadcastPlaybackLockScreenPlaceholder: String {
|
||||||
|
return VectorL10n.tr("Vector", "voice_broadcast_playback_lock_screen_placeholder")
|
||||||
|
}
|
||||||
|
/// Connection error - Recording paused
|
||||||
|
public static var voiceBroadcastRecorderConnectionError: String {
|
||||||
|
return VectorL10n.tr("Vector", "voice_broadcast_recorder_connection_error")
|
||||||
|
}
|
||||||
/// Yes, stop
|
/// Yes, stop
|
||||||
public static var voiceBroadcastStopAlertAgreeButton: String {
|
public static var voiceBroadcastStopAlertAgreeButton: String {
|
||||||
return VectorL10n.tr("Vector", "voice_broadcast_stop_alert_agree_button")
|
return VectorL10n.tr("Vector", "voice_broadcast_stop_alert_agree_button")
|
||||||
|
@ -9215,6 +9279,14 @@ public class VectorL10n: NSObject {
|
||||||
public static var voiceBroadcastUnauthorizedTitle: String {
|
public static var voiceBroadcastUnauthorizedTitle: String {
|
||||||
return VectorL10n.tr("Vector", "voice_broadcast_unauthorized_title")
|
return VectorL10n.tr("Vector", "voice_broadcast_unauthorized_title")
|
||||||
}
|
}
|
||||||
|
/// You can’t start a call as you are currently recording a live broadcast. Please end your live broadcast in order to start a call.
|
||||||
|
public static var voiceBroadcastVoipCannotStartDescription: String {
|
||||||
|
return VectorL10n.tr("Vector", "voice_broadcast_voip_cannot_start_description")
|
||||||
|
}
|
||||||
|
/// Can’t start a call
|
||||||
|
public static var voiceBroadcastVoipCannotStartTitle: String {
|
||||||
|
return VectorL10n.tr("Vector", "voice_broadcast_voip_cannot_start_title")
|
||||||
|
}
|
||||||
/// You can't start a voice message as you are currently recording a live broadcast. Please end your live broadcast in order to start recording a voice message
|
/// You can't start a voice message as you are currently recording a live broadcast. Please end your live broadcast in order to start recording a voice message
|
||||||
public static var voiceMessageBroadcastInProgressMessage: String {
|
public static var voiceMessageBroadcastInProgressMessage: String {
|
||||||
return VectorL10n.tr("Vector", "voice_message_broadcast_in_progress_message")
|
return VectorL10n.tr("Vector", "voice_message_broadcast_in_progress_message")
|
||||||
|
@ -9339,6 +9411,10 @@ public class VectorL10n: NSObject {
|
||||||
public static var wysiwygComposerFormatActionBold: String {
|
public static var wysiwygComposerFormatActionBold: String {
|
||||||
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_bold")
|
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_bold")
|
||||||
}
|
}
|
||||||
|
/// Toggle code block
|
||||||
|
public static var wysiwygComposerFormatActionCodeBlock: String {
|
||||||
|
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_code_block")
|
||||||
|
}
|
||||||
/// Apply inline code format
|
/// Apply inline code format
|
||||||
public static var wysiwygComposerFormatActionInlineCode: String {
|
public static var wysiwygComposerFormatActionInlineCode: String {
|
||||||
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_inline_code")
|
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_inline_code")
|
||||||
|
@ -9351,6 +9427,14 @@ public class VectorL10n: NSObject {
|
||||||
public static var wysiwygComposerFormatActionLink: String {
|
public static var wysiwygComposerFormatActionLink: String {
|
||||||
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_link")
|
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_link")
|
||||||
}
|
}
|
||||||
|
/// Toggle numbered list
|
||||||
|
public static var wysiwygComposerFormatActionOrderedList: String {
|
||||||
|
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_ordered_list")
|
||||||
|
}
|
||||||
|
/// Toggle quote
|
||||||
|
public static var wysiwygComposerFormatActionQuote: String {
|
||||||
|
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_quote")
|
||||||
|
}
|
||||||
/// Apply underline format
|
/// Apply underline format
|
||||||
public static var wysiwygComposerFormatActionStrikethrough: String {
|
public static var wysiwygComposerFormatActionStrikethrough: String {
|
||||||
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_strikethrough")
|
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_strikethrough")
|
||||||
|
@ -9359,6 +9443,10 @@ public class VectorL10n: NSObject {
|
||||||
public static var wysiwygComposerFormatActionUnderline: String {
|
public static var wysiwygComposerFormatActionUnderline: String {
|
||||||
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_underline")
|
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_underline")
|
||||||
}
|
}
|
||||||
|
/// Toggle bulleted list
|
||||||
|
public static var wysiwygComposerFormatActionUnorderedList: String {
|
||||||
|
return VectorL10n.tr("Vector", "wysiwyg_composer_format_action_unordered_list")
|
||||||
|
}
|
||||||
/// Create a link
|
/// Create a link
|
||||||
public static var wysiwygComposerLinkActionCreateTitle: String {
|
public static var wysiwygComposerLinkActionCreateTitle: String {
|
||||||
return VectorL10n.tr("Vector", "wysiwyg_composer_link_action_create_title")
|
return VectorL10n.tr("Vector", "wysiwyg_composer_link_action_create_title")
|
||||||
|
|
|
@ -191,6 +191,12 @@ final class RiotSettings: NSObject {
|
||||||
/// Flag indicating if the voice broadcast feature is enabled
|
/// Flag indicating if the voice broadcast feature is enabled
|
||||||
@UserDefault(key: "enableVoiceBroadcast", defaultValue: false, storage: defaults)
|
@UserDefault(key: "enableVoiceBroadcast", defaultValue: false, storage: defaults)
|
||||||
var enableVoiceBroadcast
|
var enableVoiceBroadcast
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
/// Flag indicating if we are using rust-based `MatrixCryptoSDK` instead of `MatrixSDK`'s internal crypto module
|
||||||
|
@UserDefault(key: "enableCryptoSDK", defaultValue: false, storage: defaults)
|
||||||
|
var enableCryptoSDK
|
||||||
|
#endif
|
||||||
|
|
||||||
// MARK: Calls
|
// MARK: Calls
|
||||||
|
|
||||||
|
|
|
@ -168,14 +168,8 @@ class DarkTheme: NSObject, Theme {
|
||||||
searchBar.backgroundImage = UIImage() // Remove top and bottom shadow
|
searchBar.backgroundImage = UIImage() // Remove top and bottom shadow
|
||||||
searchBar.tintColor = self.tintColor
|
searchBar.tintColor = self.tintColor
|
||||||
|
|
||||||
if #available(iOS 13.0, *) {
|
searchBar.searchTextField.backgroundColor = self.searchBackgroundColor
|
||||||
searchBar.searchTextField.backgroundColor = self.searchBackgroundColor
|
searchBar.searchTextField.textColor = self.searchPlaceholderColor
|
||||||
searchBar.searchTextField.textColor = self.searchPlaceholderColor
|
|
||||||
} else {
|
|
||||||
if let searchBarTextField = searchBar.vc_searchTextField {
|
|
||||||
searchBarTextField.textColor = self.searchPlaceholderColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyStyle(onTextField texField: UITextField) {
|
func applyStyle(onTextField texField: UITextField) {
|
||||||
|
|
|
@ -177,14 +177,8 @@ class DefaultTheme: NSObject, Theme {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if #available(iOS 13.0, *) {
|
searchBar.searchTextField.backgroundColor = self.searchBackgroundColor
|
||||||
searchBar.searchTextField.backgroundColor = self.searchBackgroundColor
|
searchBar.searchTextField.textColor = self.searchPlaceholderColor
|
||||||
searchBar.searchTextField.textColor = self.searchPlaceholderColor
|
|
||||||
} else {
|
|
||||||
if let searchBarTextField = searchBar.vc_searchTextField {
|
|
||||||
searchBarTextField.textColor = self.searchPlaceholderColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyStyle(onTextField texField: UITextField) {
|
func applyStyle(onTextField texField: UITextField) {
|
||||||
|
|
|
@ -101,7 +101,7 @@ final class AppCoordinator: NSObject, AppCoordinatorType {
|
||||||
if AppDelegate.theDelegate().isOffline {
|
if AppDelegate.theDelegate().isOffline {
|
||||||
self.splitViewCoordinator?.showAppStateIndicator(with: VectorL10n.networkOfflineTitle, icon: UIImage(systemName: "wifi.slash"))
|
self.splitViewCoordinator?.showAppStateIndicator(with: VectorL10n.networkOfflineTitle, icon: UIImage(systemName: "wifi.slash"))
|
||||||
} else {
|
} else {
|
||||||
self.splitViewCoordinator?.hideAppStateIndicator()
|
self.splitViewCoordinator?.hideAppStateIndicator()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -618,6 +618,9 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||||
|
|
||||||
// Pause Voice Broadcast recording if needed
|
// Pause Voice Broadcast recording if needed
|
||||||
[VoiceBroadcastRecorderProvider.shared pauseRecording];
|
[VoiceBroadcastRecorderProvider.shared pauseRecording];
|
||||||
|
|
||||||
|
// Pause Voice Broadcast playing if needed
|
||||||
|
[VoiceBroadcastPlaybackProvider.shared pausePlayingInProgressVoiceBroadcast];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applicationWillEnterForeground:(UIApplication *)application
|
- (void)applicationWillEnterForeground:(UIApplication *)application
|
||||||
|
@ -2395,14 +2398,14 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||||
MXLogDebug(@"[AppDelegate] showLaunchAnimation");
|
MXLogDebug(@"[AppDelegate] showLaunchAnimation");
|
||||||
|
|
||||||
LaunchLoadingView *launchLoadingView;
|
LaunchLoadingView *launchLoadingView;
|
||||||
if (MXSDKOptions.sharedInstance.enableSyncProgress)
|
if (MXSDKOptions.sharedInstance.enableStartupProgress)
|
||||||
{
|
{
|
||||||
MXSession *mainSession = self.mxSessions.firstObject;
|
MXSession *mainSession = self.mxSessions.firstObject;
|
||||||
launchLoadingView = [LaunchLoadingView instantiateWithSyncProgress:mainSession.syncProgress];
|
launchLoadingView = [LaunchLoadingView instantiateWithStartupProgress:mainSession.startupProgress];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
launchLoadingView = [LaunchLoadingView instantiateWithSyncProgress:nil];
|
launchLoadingView = [LaunchLoadingView instantiateWithStartupProgress:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
launchLoadingView.frame = window.bounds;
|
launchLoadingView.frame = window.bounds;
|
||||||
|
|
|
@ -613,8 +613,8 @@ final class AuthenticationCoordinator: NSObject, AuthenticationCoordinatorProtoc
|
||||||
|
|
||||||
/// Replace the contents of the navigation router with a loading animation.
|
/// Replace the contents of the navigation router with a loading animation.
|
||||||
private func showLoadingAnimation() {
|
private func showLoadingAnimation() {
|
||||||
let syncProgress: MXSessionSyncProgress? = MXSDKOptions.sharedInstance().enableSyncProgress ? session?.syncProgress : nil
|
let startupProgress: MXSessionStartupProgress? = MXSDKOptions.sharedInstance().enableStartupProgress ? session?.startupProgress : nil
|
||||||
let loadingViewController = LaunchLoadingViewController(syncProgress: syncProgress)
|
let loadingViewController = LaunchLoadingViewController(startupProgress: startupProgress)
|
||||||
loadingViewController.modalPresentationStyle = .fullScreen
|
loadingViewController.modalPresentationStyle = .fullScreen
|
||||||
|
|
||||||
// Replace the navigation stack with the loading animation
|
// Replace the navigation stack with the loading animation
|
||||||
|
|
|
@ -106,8 +106,8 @@ final class LegacyAuthenticationCoordinator: NSObject, AuthenticationCoordinator
|
||||||
// MARK: - Private
|
// MARK: - Private
|
||||||
|
|
||||||
private func showLoadingAnimation() {
|
private func showLoadingAnimation() {
|
||||||
let syncProgress: MXSessionSyncProgress? = MXSDKOptions.sharedInstance().enableSyncProgress ? session?.syncProgress : nil
|
let startupProgress: MXSessionStartupProgress? = MXSDKOptions.sharedInstance().enableStartupProgress ? session?.startupProgress : nil
|
||||||
let loadingViewController = LaunchLoadingViewController(syncProgress: syncProgress)
|
let loadingViewController = LaunchLoadingViewController(startupProgress: startupProgress)
|
||||||
loadingViewController.modalPresentationStyle = .fullScreen
|
loadingViewController.modalPresentationStyle = .fullScreen
|
||||||
|
|
||||||
// Replace the navigation stack with the loading animation
|
// Replace the navigation stack with the loading animation
|
||||||
|
|
|
@ -28,9 +28,7 @@
|
||||||
[super customizeTableViewCellRendering];
|
[super customizeTableViewCellRendering];
|
||||||
|
|
||||||
self.roomNameLabel.textColor = ThemeService.shared.theme.textSecondaryColor;
|
self.roomNameLabel.textColor = ThemeService.shared.theme.textSecondaryColor;
|
||||||
|
|
||||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
|
||||||
|
|
||||||
[self updateUserNameColor];
|
[self updateUserNameColor];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,6 @@
|
||||||
[self updateUserNameColor];
|
[self updateUserNameColor];
|
||||||
|
|
||||||
self.roomNameLabel.textColor = ThemeService.shared.theme.textSecondaryColor;
|
self.roomNameLabel.textColor = ThemeService.shared.theme.textSecondaryColor;
|
||||||
|
|
||||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)render:(MXKCellData *)cellData
|
- (void)render:(MXKCellData *)cellData
|
||||||
|
|
|
@ -41,9 +41,9 @@ final class LaunchLoadingView: UIView, NibLoadable, Themable {
|
||||||
|
|
||||||
// MARK: - Setup
|
// MARK: - Setup
|
||||||
|
|
||||||
static func instantiate(syncProgress: MXSessionSyncProgress?) -> LaunchLoadingView {
|
static func instantiate(startupProgress: MXSessionStartupProgress?) -> LaunchLoadingView {
|
||||||
let view = LaunchLoadingView.loadFromNib()
|
let view = LaunchLoadingView.loadFromNib()
|
||||||
syncProgress?.delegate = view
|
startupProgress?.delegate = view
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ final class LaunchLoadingView: UIView, NibLoadable, Themable {
|
||||||
animationTimeline.play()
|
animationTimeline.play()
|
||||||
self.animationTimeline = animationTimeline
|
self.animationTimeline = animationTimeline
|
||||||
|
|
||||||
self.statusLabel.isHidden = !MXSDKOptions.sharedInstance().enableSyncProgress
|
self.statusLabel.isHidden = !MXSDKOptions.sharedInstance().enableStartupProgress
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Public
|
// MARK: - Public
|
||||||
|
@ -65,21 +65,35 @@ final class LaunchLoadingView: UIView, NibLoadable, Themable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension LaunchLoadingView: MXSessionSyncProgressDelegate {
|
extension LaunchLoadingView: MXSessionStartupProgressDelegate {
|
||||||
func sessionDidUpdateSyncState(_ state: MXSessionSyncState) {
|
func sessionDidUpdateStartupStage(_ stage: MXSessionStartupStage) {
|
||||||
guard MXSDKOptions.sharedInstance().enableSyncProgress else {
|
guard MXSDKOptions.sharedInstance().enableStartupProgress else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
updateStatusText(for: stage)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateStatusText(for stage: MXSessionStartupStage) {
|
||||||
|
guard Thread.isMainThread else {
|
||||||
|
DispatchQueue.main.async { [weak self] in
|
||||||
|
self?.updateStatusText(for: stage)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync may be doing a lot of heavy work on the main thread and the status text
|
// Sync may be doing a lot of heavy work on the main thread and the status text
|
||||||
// does not update reliably enough without explicitly refreshing
|
// does not update reliably enough without explicitly refreshing
|
||||||
CATransaction.begin()
|
CATransaction.begin()
|
||||||
statusLabel.text = statusText(for: state)
|
statusLabel.text = statusText(for: stage)
|
||||||
CATransaction.commit()
|
CATransaction.commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func statusText(for state: MXSessionSyncState) -> String {
|
private func statusText(for stage: MXSessionStartupStage) -> String {
|
||||||
switch state {
|
switch stage {
|
||||||
|
case .migratingData(let progress):
|
||||||
|
let percent = Int(floor(progress * 100))
|
||||||
|
return VectorL10n.launchLoadingMigratingData("\(percent)")
|
||||||
case .serverSyncing(let attempts):
|
case .serverSyncing(let attempts):
|
||||||
if attempts > 1, let nth = numberFormatter.string(from: NSNumber(value: attempts)) {
|
if attempts > 1, let nth = numberFormatter.string(from: NSNumber(value: attempts)) {
|
||||||
return VectorL10n.launchLoadingServerSyncingNthAttempt(nth)
|
return VectorL10n.launchLoadingServerSyncingNthAttempt(nth)
|
||||||
|
|
|
@ -21,10 +21,10 @@ class LaunchLoadingViewController: UIViewController, Reusable {
|
||||||
|
|
||||||
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
||||||
|
|
||||||
init(syncProgress: MXSessionSyncProgress?) {
|
init(startupProgress: MXSessionStartupProgress?) {
|
||||||
super.init(nibName: "LaunchLoadingViewController", bundle: nil)
|
super.init(nibName: "LaunchLoadingViewController", bundle: nil)
|
||||||
|
|
||||||
let launchLoadingView = LaunchLoadingView.instantiate(syncProgress: syncProgress)
|
let launchLoadingView = LaunchLoadingView.instantiate(startupProgress: startupProgress)
|
||||||
launchLoadingView.update(theme: ThemeService.shared().theme)
|
launchLoadingView.update(theme: ThemeService.shared().theme)
|
||||||
view.vc_addSubViewMatchingParent(launchLoadingView)
|
view.vc_addSubViewMatchingParent(launchLoadingView)
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ class LocationManager: NSObject {
|
||||||
|
|
||||||
private let locationManager: CLLocationManager
|
private let locationManager: CLLocationManager
|
||||||
private var authorizationHandler: LocationAuthorizationHandler?
|
private var authorizationHandler: LocationAuthorizationHandler?
|
||||||
|
private var authorizationReturnedSinceRequestingAlways = false
|
||||||
|
|
||||||
// MARK: Public
|
// MARK: Public
|
||||||
|
|
||||||
|
@ -144,14 +145,16 @@ class LocationManager: NSObject {
|
||||||
// See https://developer.apple.com/documentation/corelocation/cllocationmanager/1620551-requestalwaysauthorization?changes=_6_6
|
// See https://developer.apple.com/documentation/corelocation/cllocationmanager/1620551-requestalwaysauthorization?changes=_6_6
|
||||||
private func tryToRequestAlwaysAuthorization(handler: @escaping LocationAuthorizationHandler) {
|
private func tryToRequestAlwaysAuthorization(handler: @escaping LocationAuthorizationHandler) {
|
||||||
self.authorizationHandler = handler
|
self.authorizationHandler = handler
|
||||||
|
self.authorizationReturnedSinceRequestingAlways = false
|
||||||
|
self.locationManager.delegate = self
|
||||||
self.locationManager.requestAlwaysAuthorization()
|
self.locationManager.requestAlwaysAuthorization()
|
||||||
|
|
||||||
Timer.scheduledTimer(withTimeInterval: Constants.waitForAuthorizationStatusDelay, repeats: false) { [weak self] _ in
|
Timer.scheduledTimer(withTimeInterval: Constants.waitForAuthorizationStatusDelay, repeats: false) { [weak self] _ in
|
||||||
guard let self = self else {
|
guard let self = self, !self.authorizationReturnedSinceRequestingAlways else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
self.authorizationRequestDidComplete(with: self.locationManager.authorizationStatus)
|
self.authorizationAlwaysRequestDidComplete(with: self.locationManager.authorizationStatus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,8 +177,7 @@ class LocationManager: NSObject {
|
||||||
|
|
||||||
return status
|
return status
|
||||||
}
|
}
|
||||||
|
private func authorizationAlwaysRequestDidComplete(with status: CLAuthorizationStatus) {
|
||||||
private func authorizationRequestDidComplete(with status: CLAuthorizationStatus) {
|
|
||||||
guard let authorizationHandler = self.authorizationHandler else {
|
guard let authorizationHandler = self.authorizationHandler else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -191,7 +193,14 @@ extension LocationManager: CLLocationManagerDelegate {
|
||||||
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
|
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
|
||||||
|
|
||||||
let status = self.locationManager.authorizationStatus
|
let status = self.locationManager.authorizationStatus
|
||||||
self.authorizationRequestDidComplete(with: status)
|
authorizationReturnedSinceRequestingAlways = true
|
||||||
|
if status == .authorizedAlways {
|
||||||
|
// LocationManager can call locationManagerDidChangeAuthorization multiple times.
|
||||||
|
// For example it calls it at initialisation of LocationManager manager and we are also seeing it called
|
||||||
|
// after requestAlwaysAuthorization but before the user has actually selected on option on the prompt.
|
||||||
|
// Therefore we should only call `authorizationAlwaysRequestDidComplete` once on the success of authorizedAlways being granted.
|
||||||
|
self.authorizationAlwaysRequestDidComplete(with: status)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
|
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
|
||||||
|
|
|
@ -572,6 +572,7 @@ extern NSString *const kMXKRoomDataSourceTimelineErrorErrorKey;
|
||||||
Once complete, this local echo will be replaced by the event saved by the homeserver.
|
Once complete, this local echo will be replaced by the event saved by the homeserver.
|
||||||
|
|
||||||
@param audioFileLocalURL the local filesystem path of the audio file to send.
|
@param audioFileLocalURL the local filesystem path of the audio file to send.
|
||||||
|
@param additionalContentParams (optional) the additional parameters to the content.
|
||||||
@param mimeType (optional) the mime type of the file. Defaults to `audio/ogg`
|
@param mimeType (optional) the mime type of the file. Defaults to `audio/ogg`
|
||||||
@param duration the length of the voice message in milliseconds
|
@param duration the length of the voice message in milliseconds
|
||||||
@param samples an array of floating point values normalized to [0, 1], boxed within NSNumbers
|
@param samples an array of floating point values normalized to [0, 1], boxed within NSNumbers
|
||||||
|
@ -580,6 +581,7 @@ extern NSString *const kMXKRoomDataSourceTimelineErrorErrorKey;
|
||||||
@param failure A block object called when the operation fails.
|
@param failure A block object called when the operation fails.
|
||||||
*/
|
*/
|
||||||
- (void)sendVoiceMessage:(NSURL *)audioFileLocalURL
|
- (void)sendVoiceMessage:(NSURL *)audioFileLocalURL
|
||||||
|
additionalContentParams:(NSDictionary*)additionalContentParams
|
||||||
mimeType:mimeType
|
mimeType:mimeType
|
||||||
duration:(NSUInteger)duration
|
duration:(NSUInteger)duration
|
||||||
samples:(NSArray<NSNumber *> *)samples
|
samples:(NSArray<NSNumber *> *)samples
|
||||||
|
|
|
@ -1998,6 +1998,7 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)sendVoiceMessage:(NSURL *)audioFileLocalURL
|
- (void)sendVoiceMessage:(NSURL *)audioFileLocalURL
|
||||||
|
additionalContentParams:(NSDictionary *)additionalContentParams
|
||||||
mimeType:mimeType
|
mimeType:mimeType
|
||||||
duration:(NSUInteger)duration
|
duration:(NSUInteger)duration
|
||||||
samples:(NSArray<NSNumber *> *)samples
|
samples:(NSArray<NSNumber *> *)samples
|
||||||
|
@ -2006,7 +2007,7 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
|
||||||
{
|
{
|
||||||
__block MXEvent *localEchoEvent = nil;
|
__block MXEvent *localEchoEvent = nil;
|
||||||
|
|
||||||
[_room sendVoiceMessage:audioFileLocalURL mimeType:mimeType duration:duration samples:samples threadId:self.threadId localEcho:&localEchoEvent success:success failure:failure keepActualFilename:YES];
|
[_room sendVoiceMessage:audioFileLocalURL additionalContentParams:additionalContentParams mimeType:mimeType duration:duration samples:samples threadId:self.threadId localEcho:&localEchoEvent success:success failure:failure keepActualFilename:YES];
|
||||||
|
|
||||||
if (localEchoEvent)
|
if (localEchoEvent)
|
||||||
{
|
{
|
||||||
|
@ -2185,10 +2186,20 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) {
|
||||||
[self removeEventWithEventId:eventId];
|
[self removeEventWithEventId:eventId];
|
||||||
|
|
||||||
if (event.isVoiceMessage) {
|
if (event.isVoiceMessage) {
|
||||||
|
// Voice message
|
||||||
NSNumber *duration = event.content[kMXMessageContentKeyExtensibleAudioMSC1767][kMXMessageContentKeyExtensibleAudioDuration];
|
NSNumber *duration = event.content[kMXMessageContentKeyExtensibleAudioMSC1767][kMXMessageContentKeyExtensibleAudioDuration];
|
||||||
NSArray<NSNumber *> *samples = event.content[kMXMessageContentKeyExtensibleAudioMSC1767][kMXMessageContentKeyExtensibleAudioWaveform];
|
NSArray<NSNumber *> *samples = event.content[kMXMessageContentKeyExtensibleAudioMSC1767][kMXMessageContentKeyExtensibleAudioWaveform];
|
||||||
|
|
||||||
[self sendVoiceMessage:localFileURL mimeType:mimetype duration:duration.doubleValue samples:samples success:success failure:failure];
|
// Additional content params in case it is a voicebroacast chunk
|
||||||
|
NSDictionary* additionalContentParams = nil;
|
||||||
|
if (event.content[kMXEventRelationRelatesToKey] != nil && event.content[VoiceBroadcastSettings.voiceBroadcastContentKeyChunkType] != nil) {
|
||||||
|
additionalContentParams = @{
|
||||||
|
kMXEventRelationRelatesToKey: event.content[kMXEventRelationRelatesToKey],
|
||||||
|
VoiceBroadcastSettings.voiceBroadcastContentKeyChunkType: event.content[VoiceBroadcastSettings.voiceBroadcastContentKeyChunkType]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[self sendVoiceMessage:localFileURL additionalContentParams:additionalContentParams mimeType:mimetype duration:duration.doubleValue samples:samples success:success failure:failure];
|
||||||
} else {
|
} else {
|
||||||
[self sendAudioFile:localFileURL mimeType:mimetype success:success failure:failure];
|
[self sendAudioFile:localFileURL mimeType:mimetype success:success failure:failure];
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,34 +18,38 @@ import Foundation
|
||||||
|
|
||||||
class MXKSendReplyEventStringLocalizer: NSObject, MXSendReplyEventStringLocalizerProtocol {
|
class MXKSendReplyEventStringLocalizer: NSObject, MXSendReplyEventStringLocalizerProtocol {
|
||||||
func senderSentAnImage() -> String {
|
func senderSentAnImage() -> String {
|
||||||
return VectorL10n.messageReplyToSenderSentAnImage
|
VectorL10n.messageReplyToSenderSentAnImage
|
||||||
}
|
}
|
||||||
|
|
||||||
func senderSentAVideo() -> String {
|
func senderSentAVideo() -> String {
|
||||||
return VectorL10n.messageReplyToSenderSentAVideo
|
VectorL10n.messageReplyToSenderSentAVideo
|
||||||
}
|
}
|
||||||
|
|
||||||
func senderSentAnAudioFile() -> String {
|
func senderSentAnAudioFile() -> String {
|
||||||
return VectorL10n.messageReplyToSenderSentAnAudioFile
|
VectorL10n.messageReplyToSenderSentAnAudioFile
|
||||||
}
|
}
|
||||||
|
|
||||||
func senderSentAVoiceMessage() -> String {
|
func senderSentAVoiceMessage() -> String {
|
||||||
return VectorL10n.messageReplyToSenderSentAVoiceMessage
|
VectorL10n.messageReplyToSenderSentAVoiceMessage
|
||||||
}
|
}
|
||||||
|
|
||||||
func senderSentAFile() -> String {
|
func senderSentAFile() -> String {
|
||||||
return VectorL10n.messageReplyToSenderSentAFile
|
VectorL10n.messageReplyToSenderSentAFile
|
||||||
}
|
}
|
||||||
|
|
||||||
func senderSentTheirLocation() -> String {
|
func senderSentTheirLocation() -> String {
|
||||||
return VectorL10n.messageReplyToSenderSentTheirLocation
|
VectorL10n.messageReplyToSenderSentTheirLocation
|
||||||
}
|
}
|
||||||
|
|
||||||
func senderSentTheirLiveLocation() -> String {
|
func senderSentTheirLiveLocation() -> String {
|
||||||
return VectorL10n.messageReplyToSenderSentTheirLiveLocation
|
VectorL10n.messageReplyToSenderSentTheirLiveLocation
|
||||||
}
|
}
|
||||||
|
|
||||||
func messageToReplyToPrefix() -> String {
|
func messageToReplyToPrefix() -> String {
|
||||||
return VectorL10n.messageReplyToMessageToReplyToPrefix
|
VectorL10n.messageReplyToMessageToReplyToPrefix
|
||||||
|
}
|
||||||
|
|
||||||
|
func replyToEndedPoll() -> String {
|
||||||
|
VectorL10n.pollTimelineReplyEndedPoll
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,7 @@ class HTMLFormatter: NSObject {
|
||||||
DTDefaultFontName: font.fontName,
|
DTDefaultFontName: font.fontName,
|
||||||
DTDefaultFontSize: font.pointSize,
|
DTDefaultFontSize: font.pointSize,
|
||||||
DTDefaultLinkDecoration: false,
|
DTDefaultLinkDecoration: false,
|
||||||
|
DTDefaultLinkColor: ThemeService.shared().theme.colors.links,
|
||||||
DTWillFlushBlockCallBack: sanitizeCallback
|
DTWillFlushBlockCallBack: sanitizeCallback
|
||||||
]
|
]
|
||||||
options.merge(extraOptions) { (_, new) in new }
|
options.merge(extraOptions) { (_, new) in new }
|
||||||
|
|
|
@ -366,6 +366,12 @@ typedef enum : NSUInteger {
|
||||||
*/
|
*/
|
||||||
@property (nonatomic) UIColor *sendingTextColor;
|
@property (nonatomic) UIColor *sendingTextColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Color used to display links and hyperlinks contentt.
|
||||||
|
Default is [UIColor linkColor].
|
||||||
|
*/
|
||||||
|
@property (nonatomic) UIColor *linksColor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Color used to display error text.
|
Color used to display error text.
|
||||||
Default is red.
|
Default is red.
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#import "GeneratedInterface-Swift.h"
|
#import "GeneratedInterface-Swift.h"
|
||||||
|
|
||||||
static NSString *const kHTMLATagRegexPattern = @"<a href=(?:'|\")(.*?)(?:'|\")>([^<]*)</a>";
|
static NSString *const kHTMLATagRegexPattern = @"<a href=(?:'|\")(.*?)(?:'|\")>([^<]*)</a>";
|
||||||
|
static NSString *const kRepliedTextPattern = @"<mx-reply>.*<blockquote>.*<br>(.*)</blockquote></mx-reply>";
|
||||||
|
|
||||||
@interface MXKEventFormatter ()
|
@interface MXKEventFormatter ()
|
||||||
{
|
{
|
||||||
|
@ -89,6 +90,7 @@ static NSString *const kHTMLATagRegexPattern = @"<a href=(?:'|\")(.*?)(?:'|\")>(
|
||||||
_encryptingTextColor = [UIColor lightGrayColor];
|
_encryptingTextColor = [UIColor lightGrayColor];
|
||||||
_sendingTextColor = [UIColor lightGrayColor];
|
_sendingTextColor = [UIColor lightGrayColor];
|
||||||
_errorTextColor = [UIColor redColor];
|
_errorTextColor = [UIColor redColor];
|
||||||
|
_linksColor = [UIColor linkColor];
|
||||||
_htmlBlockquoteBorderColor = [MXKTools colorWithRGBValue:0xDDDDDD];
|
_htmlBlockquoteBorderColor = [MXKTools colorWithRGBValue:0xDDDDDD];
|
||||||
|
|
||||||
_defaultTextFont = [UIFont systemFontOfSize:14];
|
_defaultTextFont = [UIFont systemFontOfSize:14];
|
||||||
|
@ -1749,6 +1751,7 @@ static NSString *const kHTMLATagRegexPattern = @"<a href=(?:'|\")(.*?)(?:'|\")>(
|
||||||
if (url.URL)
|
if (url.URL)
|
||||||
{
|
{
|
||||||
[str addAttribute:NSLinkAttributeName value:url.URL range:matchRange];
|
[str addAttribute:NSLinkAttributeName value:url.URL range:matchRange];
|
||||||
|
[str addAttribute:NSForegroundColorAttributeName value:self.linksColor range:matchRange];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1806,6 +1809,7 @@ static NSString *const kHTMLATagRegexPattern = @"<a href=(?:'|\")(.*?)(?:'|\")>(
|
||||||
}
|
}
|
||||||
|
|
||||||
html = [self renderReplyTo:html withRoomState:roomState];
|
html = [self renderReplyTo:html withRoomState:roomState];
|
||||||
|
html = [self renderPollEndedReplyTo:html repliedEvent:repliedEvent];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply the css style that corresponds to the event state
|
// Apply the css style that corresponds to the event state
|
||||||
|
@ -1878,6 +1882,12 @@ static NSString *const kHTMLATagRegexPattern = @"<a href=(?:'|\")(.*?)(?:'|\")>(
|
||||||
{
|
{
|
||||||
MXJSONModelSetString(repliedEventContent, repliedEvent.content[kMXMessageBodyKey]);
|
MXJSONModelSetString(repliedEventContent, repliedEvent.content[kMXMessageBodyKey]);
|
||||||
}
|
}
|
||||||
|
if (!repliedEventContent && repliedEvent.eventType == MXEventTypePollStart) {
|
||||||
|
repliedEventContent = [MXEventContentPollStart modelFromJSON:repliedEvent.content].question;
|
||||||
|
}
|
||||||
|
if (!repliedEventContent && repliedEvent.eventType == MXEventTypePollEnd) {
|
||||||
|
repliedEventContent = MXSendReplyEventDefaultStringLocalizer.new.replyToEndedPoll;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// No message content in a non-redacted event. Formatter should use fallback.
|
// No message content in a non-redacted event. Formatter should use fallback.
|
||||||
|
@ -2012,6 +2022,44 @@ static NSString *const kHTMLATagRegexPattern = @"<a href=(?:'|\")(.*?)(?:'|\")>(
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString*)renderPollEndedReplyTo:(NSString*)htmlString repliedEvent:(MXEvent*)repliedEvent {
|
||||||
|
static NSRegularExpression *endedPollRegex;
|
||||||
|
static dispatch_once_t onceToken;
|
||||||
|
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
endedPollRegex = [NSRegularExpression regularExpressionWithPattern:kRepliedTextPattern options:NSRegularExpressionCaseInsensitive error:nil];
|
||||||
|
});
|
||||||
|
|
||||||
|
NSString* finalString = htmlString;
|
||||||
|
|
||||||
|
if (repliedEvent.eventType != MXEventTypePollEnd) {
|
||||||
|
return finalString;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSTextCheckingResult* match = [endedPollRegex firstMatchInString:htmlString options:0 range:NSMakeRange(0, htmlString.length)];
|
||||||
|
|
||||||
|
if (!(match && match.numberOfRanges > 1)) {
|
||||||
|
// no useful match found
|
||||||
|
return finalString;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSRange groupRange = [match rangeAtIndex:1];
|
||||||
|
NSString* replacementText;
|
||||||
|
|
||||||
|
if (repliedEvent) {
|
||||||
|
MXEvent* pollStartedEvent = [mxSession.store eventWithEventId:repliedEvent.relatesTo.eventId inRoom:repliedEvent.roomId];
|
||||||
|
replacementText = [MXEventContentPollStart modelFromJSON:pollStartedEvent.content].question;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (replacementText == nil) {
|
||||||
|
replacementText = VectorL10n.pollTimelineReplyEndedPoll;
|
||||||
|
}
|
||||||
|
|
||||||
|
finalString = [htmlString stringByReplacingCharactersInRange:groupRange withString:replacementText];
|
||||||
|
|
||||||
|
return finalString;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)postFormatMutableAttributedString:(NSMutableAttributedString*)mutableAttributedString
|
- (void)postFormatMutableAttributedString:(NSMutableAttributedString*)mutableAttributedString
|
||||||
forEvent:(MXEvent*)event
|
forEvent:(MXEvent*)event
|
||||||
andRepliedEvent:(MXEvent*)repliedEvent
|
andRepliedEvent:(MXEvent*)repliedEvent
|
||||||
|
|
|
@ -46,6 +46,7 @@ static NSRegularExpression *eventIdRegex;
|
||||||
static NSRegularExpression *httpLinksRegex;
|
static NSRegularExpression *httpLinksRegex;
|
||||||
// A regex to find all HTML tags
|
// A regex to find all HTML tags
|
||||||
static NSRegularExpression *htmlTagsRegex;
|
static NSRegularExpression *htmlTagsRegex;
|
||||||
|
static NSDataDetector *linkDetector;
|
||||||
|
|
||||||
@implementation MXKTools
|
@implementation MXKTools
|
||||||
|
|
||||||
|
@ -60,7 +61,8 @@ static NSRegularExpression *htmlTagsRegex;
|
||||||
eventIdRegex = [NSRegularExpression regularExpressionWithPattern:kMXToolsRegexStringForMatrixEventIdentifier options:NSRegularExpressionCaseInsensitive error:nil];
|
eventIdRegex = [NSRegularExpression regularExpressionWithPattern:kMXToolsRegexStringForMatrixEventIdentifier options:NSRegularExpressionCaseInsensitive error:nil];
|
||||||
|
|
||||||
httpLinksRegex = [NSRegularExpression regularExpressionWithPattern:@"(?i)\\b(https?://\\S*)\\b" options:NSRegularExpressionCaseInsensitive error:nil];
|
httpLinksRegex = [NSRegularExpression regularExpressionWithPattern:@"(?i)\\b(https?://\\S*)\\b" options:NSRegularExpressionCaseInsensitive error:nil];
|
||||||
htmlTagsRegex = [NSRegularExpression regularExpressionWithPattern:@"<(\\w+)[^>]*>" options:NSRegularExpressionCaseInsensitive error:nil];
|
htmlTagsRegex = [NSRegularExpression regularExpressionWithPattern:@"<(\\w+)[^>]*>" options:NSRegularExpressionCaseInsensitive error:nil];
|
||||||
|
linkDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1037,6 +1039,23 @@ manualChangeMessageForVideo:(NSString*)manualChangeMessageForVideo
|
||||||
{
|
{
|
||||||
[MXKTools createLinksInMutableAttributedString:mutableAttributedString matchingRegex:eventIdRegex];
|
[MXKTools createLinksInMutableAttributedString:mutableAttributedString matchingRegex:eventIdRegex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This allows to check for normal url based links (like https://element.io)
|
||||||
|
// And set back the default link color
|
||||||
|
NSArray *matches = [linkDetector matchesInString: [mutableAttributedString string] options:0 range: NSMakeRange(0,mutableAttributedString.length)];
|
||||||
|
if (matches)
|
||||||
|
{
|
||||||
|
for (NSTextCheckingResult *match in matches)
|
||||||
|
{
|
||||||
|
NSRange matchRange = [match range];
|
||||||
|
NSURL *matchUrl = [match URL];
|
||||||
|
NSURLComponents *url = [[NSURLComponents new] initWithURL:matchUrl resolvingAgainstBaseURL:NO];
|
||||||
|
if (url.URL)
|
||||||
|
{
|
||||||
|
[mutableAttributedString addAttribute:NSForegroundColorAttributeName value:ThemeService.shared.theme.colors.links range:matchRange];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)createLinksInMutableAttributedString:(NSMutableAttributedString*)mutableAttributedString matchingRegex:(NSRegularExpression*)regex
|
+ (void)createLinksInMutableAttributedString:(NSMutableAttributedString*)mutableAttributedString matchingRegex:(NSRegularExpression*)regex
|
||||||
|
@ -1083,6 +1102,8 @@ manualChangeMessageForVideo:(NSString*)manualChangeMessageForVideo
|
||||||
// If the match is fully in the link, skip it
|
// If the match is fully in the link, skip it
|
||||||
if (NSIntersectionRange(match.range, linkMatch.range).length == match.range.length)
|
if (NSIntersectionRange(match.range, linkMatch.range).length == match.range.length)
|
||||||
{
|
{
|
||||||
|
// but before we set the right color
|
||||||
|
[mutableAttributedString addAttribute:NSForegroundColorAttributeName value:ThemeService.shared.theme.colors.links range:linkMatch.range];
|
||||||
hasAlreadyLink = YES;
|
hasAlreadyLink = YES;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1097,6 +1118,7 @@ manualChangeMessageForVideo:(NSString*)manualChangeMessageForVideo
|
||||||
NSString *link = [mutableAttributedString.string substringWithRange:match.range];
|
NSString *link = [mutableAttributedString.string substringWithRange:match.range];
|
||||||
link = [link stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
|
link = [link stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
|
||||||
[mutableAttributedString addAttribute:NSLinkAttributeName value:link range:match.range];
|
[mutableAttributedString addAttribute:NSLinkAttributeName value:link range:match.range];
|
||||||
|
[mutableAttributedString addAttribute:NSForegroundColorAttributeName value:ThemeService.shared.theme.colors.links range:match.range];
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
|
|
||||||
- (void)setAttributedText:(NSAttributedString *)attributedText
|
- (void)setAttributedText:(NSAttributedString *)attributedText
|
||||||
{
|
{
|
||||||
|
self.linkTextAttributes = @{};
|
||||||
if (@available(iOS 15.0, *)) {
|
if (@available(iOS 15.0, *)) {
|
||||||
[self flushPills];
|
[self flushPills];
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,8 +174,11 @@ final class RoomInfoCoordinator: NSObject, RoomInfoCoordinatorType {
|
||||||
case .notifications:
|
case .notifications:
|
||||||
let coordinator = createRoomNotificationSettingsCoordinator()
|
let coordinator = createRoomNotificationSettingsCoordinator()
|
||||||
coordinator.start()
|
coordinator.start()
|
||||||
self.add(childCoordinator: coordinator)
|
push(coordinator: coordinator)
|
||||||
self.navigationRouter.push(coordinator, animated: true, popCompletion: nil)
|
case .pollHistory:
|
||||||
|
let coordinator: PollHistoryCoordinator = .init(parameters: .init(mode: .active))
|
||||||
|
coordinator.start()
|
||||||
|
push(coordinator: coordinator)
|
||||||
default:
|
default:
|
||||||
guard let tabIndex = target.tabIndex else {
|
guard let tabIndex = target.tabIndex else {
|
||||||
fatalError("No settings tab index for this target.")
|
fatalError("No settings tab index for this target.")
|
||||||
|
@ -189,6 +192,13 @@ final class RoomInfoCoordinator: NSObject, RoomInfoCoordinatorType {
|
||||||
navigationRouter.push(segmentedViewController, animated: animated, popCompletion: nil)
|
navigationRouter.push(segmentedViewController, animated: animated, popCompletion: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func push(coordinator: Coordinator & Presentable, animated: Bool = true) {
|
||||||
|
self.add(childCoordinator: coordinator)
|
||||||
|
navigationRouter.push(coordinator, animated: animated) {
|
||||||
|
self.remove(childCoordinator: coordinator)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - RoomInfoListCoordinatorDelegate
|
// MARK: - RoomInfoListCoordinatorDelegate
|
||||||
|
|
|
@ -25,6 +25,7 @@ enum RoomInfoListTarget: Equatable {
|
||||||
case integrations
|
case integrations
|
||||||
case search
|
case search
|
||||||
case notifications
|
case notifications
|
||||||
|
case pollHistory
|
||||||
|
|
||||||
var tabIndex: UInt? {
|
var tabIndex: UInt? {
|
||||||
switch self {
|
switch self {
|
||||||
|
|
|
@ -174,6 +174,11 @@ final class RoomInfoListViewController: UIViewController {
|
||||||
let rowMembers = Row(type: .default, icon: Asset.Images.userIcon.image, text: text, accessoryType: .disclosureIndicator) {
|
let rowMembers = Row(type: .default, icon: Asset.Images.userIcon.image, text: text, accessoryType: .disclosureIndicator) {
|
||||||
self.viewModel.process(viewAction: .navigate(target: .members))
|
self.viewModel.process(viewAction: .navigate(target: .members))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let rowPollHistory = Row(type: .default, icon: Asset.Images.pollHistory.image, text: VectorL10n.roomDetailsPolls, accessoryType: .disclosureIndicator) {
|
||||||
|
self.viewModel.process(viewAction: .navigate(target: .pollHistory))
|
||||||
|
}
|
||||||
|
|
||||||
let rowUploads = Row(type: .default, icon: Asset.Images.scrollup.image, text: VectorL10n.roomDetailsFiles, accessoryType: .disclosureIndicator) {
|
let rowUploads = Row(type: .default, icon: Asset.Images.scrollup.image, text: VectorL10n.roomDetailsFiles, accessoryType: .disclosureIndicator) {
|
||||||
self.viewModel.process(viewAction: .navigate(target: .uploads))
|
self.viewModel.process(viewAction: .navigate(target: .uploads))
|
||||||
}
|
}
|
||||||
|
@ -193,6 +198,11 @@ final class RoomInfoListViewController: UIViewController {
|
||||||
rows.append(rowIntegrations)
|
rows.append(rowIntegrations)
|
||||||
}
|
}
|
||||||
rows.append(rowMembers)
|
rows.append(rowMembers)
|
||||||
|
|
||||||
|
if BuildSettings.pollsHistoryEnabled {
|
||||||
|
rows.append(rowPollHistory)
|
||||||
|
}
|
||||||
|
|
||||||
rows.append(rowUploads)
|
rows.append(rowUploads)
|
||||||
if !viewData.isEncrypted {
|
if !viewData.isEncrypted {
|
||||||
rows.append(rowSearch)
|
rows.append(rowSearch)
|
||||||
|
|
|
@ -2454,13 +2454,19 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||||
// Prevents listening a VB when recording a new one
|
// Prevents listening a VB when recording a new one
|
||||||
[VoiceBroadcastPlaybackProvider.shared pausePlaying];
|
[VoiceBroadcastPlaybackProvider.shared pausePlaying];
|
||||||
|
|
||||||
|
// Check connectivity
|
||||||
|
if ([AppDelegate theDelegate].isOffline)
|
||||||
|
{
|
||||||
|
[self showAlertWithTitle:[VectorL10n voiceBroadcastConnectionErrorTitle] message:[VectorL10n voiceBroadcastConnectionErrorMessage]];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Request the voice broadcast service to start recording - No service is returned if someone else is already broadcasting in the room
|
// Request the voice broadcast service to start recording - No service is returned if someone else is already broadcasting in the room
|
||||||
[session getOrCreateVoiceBroadcastServiceFor:self.roomDataSource.room completion:^(VoiceBroadcastService *voiceBroadcastService) {
|
[session getOrCreateVoiceBroadcastServiceFor:self.roomDataSource.room completion:^(VoiceBroadcastService *voiceBroadcastService) {
|
||||||
if (voiceBroadcastService) {
|
if (voiceBroadcastService) {
|
||||||
[voiceBroadcastService startVoiceBroadcastWithSuccess:^(NSString * _Nullable success) {
|
[voiceBroadcastService startVoiceBroadcastWithSuccess:^(NSString * _Nullable success) { } failure:^(NSError * _Nonnull error) {
|
||||||
|
[self showAlertWithTitle:[VectorL10n voiceBroadcastConnectionErrorTitle] message:[VectorL10n voiceBroadcastConnectionErrorMessage]];
|
||||||
} failure:^(NSError * _Nonnull error) {
|
[session tearDownVoiceBroadcastService];
|
||||||
|
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -4296,8 +4302,14 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||||
|
|
||||||
[self startActivityIndicator];
|
[self startActivityIndicator];
|
||||||
|
|
||||||
|
NSArray<NSString *>* relationTypes = nil;
|
||||||
|
// If it's a voice broadcast, delete the selected event and all related events.
|
||||||
|
if (selectedEvent.eventType == MXEventTypeCustom && [selectedEvent.type isEqualToString:VoiceBroadcastSettings.voiceBroadcastInfoContentKeyType]) {
|
||||||
|
relationTypes = @[MXEventRelationTypeReference];
|
||||||
|
}
|
||||||
|
|
||||||
MXWeakify(self);
|
MXWeakify(self);
|
||||||
[self.roomDataSource.room redactEvent:selectedEvent.eventId reason:nil success:^{
|
[self.roomDataSource.room redactEvent:selectedEvent.eventId withRelations:relationTypes reason:nil success:^{
|
||||||
MXStrongifyAndReturnIfNil(self);
|
MXStrongifyAndReturnIfNil(self);
|
||||||
[self stopActivityIndicator];
|
[self stopActivityIndicator];
|
||||||
} failure:^(NSError *error) {
|
} failure:^(NSError *error) {
|
||||||
|
@ -5187,7 +5199,14 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||||
|
|
||||||
- (IBAction)onVoiceCallPressed:(id)sender
|
- (IBAction)onVoiceCallPressed:(id)sender
|
||||||
{
|
{
|
||||||
if (self.isCallActive)
|
// Manage case of a Voice broadcast listening -> Pause Voice broadcast playback
|
||||||
|
[VoiceBroadcastPlaybackProvider.shared pausePlaying];
|
||||||
|
|
||||||
|
if (VoiceBroadcastRecorderProvider.shared.isVoiceBroadcastRecording) {
|
||||||
|
[[AppDelegate theDelegate] showAlertWithTitle:VectorL10n.voiceBroadcastVoipCannotStartTitle
|
||||||
|
message:VectorL10n.voiceBroadcastVoipCannotStartDescription];
|
||||||
|
}
|
||||||
|
else if (self.isCallActive)
|
||||||
{
|
{
|
||||||
[self hangupCall];
|
[self hangupCall];
|
||||||
}
|
}
|
||||||
|
@ -5199,7 +5218,15 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||||
|
|
||||||
- (IBAction)onVideoCallPressed:(id)sender
|
- (IBAction)onVideoCallPressed:(id)sender
|
||||||
{
|
{
|
||||||
[self placeCallWithVideo:YES];
|
// Manage case of a Voice broadcast listening -> Pause Voice broadcast playback
|
||||||
|
[VoiceBroadcastPlaybackProvider.shared pausePlaying];
|
||||||
|
|
||||||
|
if (VoiceBroadcastRecorderProvider.shared.isVoiceBroadcastRecording) {
|
||||||
|
[[AppDelegate theDelegate] showAlertWithTitle:VectorL10n.voiceBroadcastVoipCannotStartTitle
|
||||||
|
message:VectorL10n.voiceBroadcastVoipCannotStartDescription];
|
||||||
|
} else {
|
||||||
|
[self placeCallWithVideo:YES];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)onThreadListTapped:(id)sender
|
- (IBAction)onThreadListTapped:(id)sender
|
||||||
|
@ -7911,7 +7938,7 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||||
samples:(NSArray<NSNumber *> *)samples
|
samples:(NSArray<NSNumber *> *)samples
|
||||||
completion:(void (^)(BOOL))completion
|
completion:(void (^)(BOOL))completion
|
||||||
{
|
{
|
||||||
[self.roomDataSource sendVoiceMessage:url mimeType:nil duration:duration samples:samples success:^(NSString *eventId) {
|
[self.roomDataSource sendVoiceMessage:url additionalContentParams:nil mimeType:nil duration:duration samples:samples success:^(NSString *eventId) {
|
||||||
MXLogDebug(@"Success with event id %@", eventId);
|
MXLogDebug(@"Success with event id %@", eventId);
|
||||||
completion(YES);
|
completion(YES);
|
||||||
} failure:^(NSError *error) {
|
} failure:^(NSError *error) {
|
||||||
|
|
|
@ -52,8 +52,7 @@ enum
|
||||||
ROOM_SETTINGS_MAIN_SECTION_ROW_TOPIC,
|
ROOM_SETTINGS_MAIN_SECTION_ROW_TOPIC,
|
||||||
ROOM_SETTINGS_MAIN_SECTION_ROW_TAG,
|
ROOM_SETTINGS_MAIN_SECTION_ROW_TAG,
|
||||||
ROOM_SETTINGS_MAIN_SECTION_ROW_DIRECT_CHAT,
|
ROOM_SETTINGS_MAIN_SECTION_ROW_DIRECT_CHAT,
|
||||||
ROOM_SETTINGS_MAIN_SECTION_ROW_MUTE_NOTIFICATIONS,
|
ROOM_SETTINGS_MAIN_SECTION_ROW_MUTE_NOTIFICATIONS
|
||||||
ROOM_SETTINGS_MAIN_SECTION_ROW_LEAVE
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -515,7 +514,6 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti
|
||||||
{
|
{
|
||||||
[sectionMain addRowWithTag:ROOM_SETTINGS_MAIN_SECTION_ROW_MUTE_NOTIFICATIONS];
|
[sectionMain addRowWithTag:ROOM_SETTINGS_MAIN_SECTION_ROW_MUTE_NOTIFICATIONS];
|
||||||
}
|
}
|
||||||
[sectionMain addRowWithTag:ROOM_SETTINGS_MAIN_SECTION_ROW_LEAVE];
|
|
||||||
[tmpSections addObject:sectionMain];
|
[tmpSections addObject:sectionMain];
|
||||||
|
|
||||||
if (RiotSettings.shared.roomSettingsScreenAllowChangingAccessSettings)
|
if (RiotSettings.shared.roomSettingsScreenAllowChangingAccessSettings)
|
||||||
|
@ -2325,22 +2323,6 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti
|
||||||
cell = favoriteCell;
|
cell = favoriteCell;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (row == ROOM_SETTINGS_MAIN_SECTION_ROW_LEAVE)
|
|
||||||
{
|
|
||||||
MXKTableViewCellWithButton *leaveCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithButton defaultReuseIdentifier] forIndexPath:indexPath];
|
|
||||||
|
|
||||||
NSString* title = [VectorL10n leave];
|
|
||||||
|
|
||||||
[leaveCell.mxkButton setTitle:title forState:UIControlStateNormal];
|
|
||||||
[leaveCell.mxkButton setTitle:title forState:UIControlStateHighlighted];
|
|
||||||
[leaveCell.mxkButton setTintColor:ThemeService.shared.theme.tintColor];
|
|
||||||
leaveCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17];
|
|
||||||
|
|
||||||
[leaveCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside];
|
|
||||||
[leaveCell.mxkButton addTarget:self action:@selector(onLeave:) forControlEvents:UIControlEventTouchUpInside];
|
|
||||||
|
|
||||||
cell = leaveCell;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (section == SECTION_TAG_ACCESS)
|
else if (section == SECTION_TAG_ACCESS)
|
||||||
{
|
{
|
||||||
|
@ -3196,76 +3178,6 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti
|
||||||
|
|
||||||
#pragma mark - actions
|
#pragma mark - actions
|
||||||
|
|
||||||
- (void)onLeave:(id)sender
|
|
||||||
{
|
|
||||||
// Prompt user before leaving the room
|
|
||||||
__weak typeof(self) weakSelf = self;
|
|
||||||
|
|
||||||
[currentAlert dismissViewControllerAnimated:NO completion:nil];
|
|
||||||
|
|
||||||
NSString *title, *message;
|
|
||||||
if ([self.mainSession roomWithRoomId:self.roomId].isDirect)
|
|
||||||
{
|
|
||||||
title = [VectorL10n roomParticipantsLeavePromptTitleForDm];
|
|
||||||
message = [VectorL10n roomParticipantsLeavePromptMsgForDm];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
title = [VectorL10n roomParticipantsLeavePromptTitle];
|
|
||||||
message = [VectorL10n roomParticipantsLeavePromptMsg];
|
|
||||||
}
|
|
||||||
|
|
||||||
currentAlert = [UIAlertController alertControllerWithTitle:title
|
|
||||||
message:message
|
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
|
||||||
|
|
||||||
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n cancel]
|
|
||||||
style:UIAlertActionStyleCancel
|
|
||||||
handler:^(UIAlertAction * action) {
|
|
||||||
|
|
||||||
if (weakSelf)
|
|
||||||
{
|
|
||||||
typeof(self) self = weakSelf;
|
|
||||||
self->currentAlert = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
}]];
|
|
||||||
|
|
||||||
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n leave]
|
|
||||||
style:UIAlertActionStyleDefault
|
|
||||||
handler:^(UIAlertAction * action) {
|
|
||||||
|
|
||||||
if (weakSelf)
|
|
||||||
{
|
|
||||||
typeof(self) self = weakSelf;
|
|
||||||
self->currentAlert = nil;
|
|
||||||
|
|
||||||
[self startActivityIndicator];
|
|
||||||
[self->mxRoom leave:^{
|
|
||||||
|
|
||||||
if (self.delegate) {
|
|
||||||
[self.delegate roomSettingsViewControllerDidLeaveRoom:self];
|
|
||||||
} else {
|
|
||||||
[[LegacyAppDelegate theDelegate] restoreInitialDisplay:nil];
|
|
||||||
}
|
|
||||||
|
|
||||||
} failure:^(NSError *error) {
|
|
||||||
|
|
||||||
[self stopActivityIndicator];
|
|
||||||
|
|
||||||
MXLogDebug(@"[RoomSettingsViewController] Leave room failed");
|
|
||||||
// Alert user
|
|
||||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
|
||||||
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
}]];
|
|
||||||
|
|
||||||
[currentAlert mxk_setAccessibilityIdentifier:@"RoomSettingsVCLeaveAlert"];
|
|
||||||
[self presentViewController:currentAlert animated:YES completion:nil];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)onRoomAvatarTap:(UITapGestureRecognizer *)recognizer
|
- (void)onRoomAvatarTap:(UITapGestureRecognizer *)recognizer
|
||||||
{
|
{
|
||||||
SingleImagePickerPresenter *singleImagePickerPresenter = [[SingleImagePickerPresenter alloc] initWithSession:self.mainSession];
|
SingleImagePickerPresenter *singleImagePickerPresenter = [[SingleImagePickerPresenter alloc] initWithSession:self.mainSession];
|
||||||
|
|
|
@ -26,8 +26,6 @@
|
||||||
- (void)customizeTableViewCellRendering
|
- (void)customizeTableViewCellRendering
|
||||||
{
|
{
|
||||||
[super customizeTableViewCellRendering];
|
[super customizeTableViewCellRendering];
|
||||||
|
|
||||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -37,13 +37,6 @@
|
||||||
xibPictureViewTopConstraintConstant = self.pictureViewTopConstraint.constant;
|
xibPictureViewTopConstraintConstant = self.pictureViewTopConstraint.constant;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)customizeTableViewCellRendering
|
|
||||||
{
|
|
||||||
[super customizeTableViewCellRendering];
|
|
||||||
|
|
||||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)prepareForReuse
|
- (void)prepareForReuse
|
||||||
{
|
{
|
||||||
[super prepareForReuse];
|
[super prepareForReuse];
|
||||||
|
|
|
@ -26,13 +26,6 @@
|
||||||
|
|
||||||
@implementation RoomMembershipCollapsedBubbleCell
|
@implementation RoomMembershipCollapsedBubbleCell
|
||||||
|
|
||||||
- (void)customizeTableViewCellRendering
|
|
||||||
{
|
|
||||||
[super customizeTableViewCellRendering];
|
|
||||||
|
|
||||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)layoutSubviews
|
- (void)layoutSubviews
|
||||||
{
|
{
|
||||||
[super layoutSubviews];
|
[super layoutSubviews];
|
||||||
|
|
|
@ -51,14 +51,6 @@ class TextMessageBaseBubbleCell: SizableBaseRoomCell, RoomCellURLPreviewDisplaya
|
||||||
override func setupMessageTextViewLongPressGesture() {
|
override func setupMessageTextViewLongPressGesture() {
|
||||||
// Do nothing, otherwise default setup prevent link tap
|
// Do nothing, otherwise default setup prevent link tap
|
||||||
}
|
}
|
||||||
|
|
||||||
override func update(theme: Theme) {
|
|
||||||
super.update(theme: theme)
|
|
||||||
|
|
||||||
if let messageTextView = self.messageTextView {
|
|
||||||
messageTextView.tintColor = theme.tintColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - RoomCellTimestampDisplayable
|
// MARK: - RoomCellTimestampDisplayable
|
||||||
|
|
|
@ -28,8 +28,6 @@
|
||||||
[super customizeTableViewCellRendering];
|
[super customizeTableViewCellRendering];
|
||||||
|
|
||||||
[self updateUserNameColor];
|
[self updateUserNameColor];
|
||||||
|
|
||||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)render:(MXKCellData *)cellData
|
- (void)render:(MXKCellData *)cellData
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
[self updateUserNameColor];
|
[self updateUserNameColor];
|
||||||
self.paginationLabel.textColor = ThemeService.shared.theme.tintColor;
|
self.paginationLabel.textColor = ThemeService.shared.theme.tintColor;
|
||||||
self.paginationSeparatorView.backgroundColor = ThemeService.shared.theme.tintColor;
|
self.paginationSeparatorView.backgroundColor = ThemeService.shared.theme.tintColor;
|
||||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)render:(MXKCellData *)cellData
|
- (void)render:(MXKCellData *)cellData
|
||||||
|
|
|
@ -23,13 +23,6 @@
|
||||||
|
|
||||||
@implementation RoomIncomingAttachmentWithoutSenderInfoBubbleCell
|
@implementation RoomIncomingAttachmentWithoutSenderInfoBubbleCell
|
||||||
|
|
||||||
- (void)customizeTableViewCellRendering
|
|
||||||
{
|
|
||||||
[super customizeTableViewCellRendering];
|
|
||||||
|
|
||||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (CGFloat)heightForCellData:(MXKCellData*)cellData withMaximumWidth:(CGFloat)maxWidth
|
+ (CGFloat)heightForCellData:(MXKCellData*)cellData withMaximumWidth:(CGFloat)maxWidth
|
||||||
{
|
{
|
||||||
CGFloat rowHeight = [self attachmentBubbleCellHeightForCellData:cellData withMaximumWidth:maxWidth];
|
CGFloat rowHeight = [self attachmentBubbleCellHeightForCellData:cellData withMaximumWidth:maxWidth];
|
||||||
|
|
|
@ -28,8 +28,6 @@
|
||||||
[super customizeTableViewCellRendering];
|
[super customizeTableViewCellRendering];
|
||||||
|
|
||||||
[self updateUserNameColor];
|
[self updateUserNameColor];
|
||||||
|
|
||||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)render:(MXKCellData *)cellData
|
- (void)render:(MXKCellData *)cellData
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
[self updateUserNameColor];
|
[self updateUserNameColor];
|
||||||
self.paginationLabel.textColor = ThemeService.shared.theme.tintColor;
|
self.paginationLabel.textColor = ThemeService.shared.theme.tintColor;
|
||||||
self.paginationSeparatorView.backgroundColor = ThemeService.shared.theme.tintColor;
|
self.paginationSeparatorView.backgroundColor = ThemeService.shared.theme.tintColor;
|
||||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)render:(MXKCellData *)cellData
|
- (void)render:(MXKCellData *)cellData
|
||||||
|
|
|
@ -22,11 +22,5 @@
|
||||||
|
|
||||||
@implementation RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell
|
@implementation RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell
|
||||||
|
|
||||||
- (void)customizeTableViewCellRendering
|
|
||||||
{
|
|
||||||
[super customizeTableViewCellRendering];
|
|
||||||
|
|
||||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -24,13 +24,6 @@
|
||||||
|
|
||||||
@implementation RoomOutgoingAttachmentWithoutSenderInfoBubbleCell
|
@implementation RoomOutgoingAttachmentWithoutSenderInfoBubbleCell
|
||||||
|
|
||||||
- (void)customizeTableViewCellRendering
|
|
||||||
{
|
|
||||||
[super customizeTableViewCellRendering];
|
|
||||||
|
|
||||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)render:(MXKCellData *)cellData
|
- (void)render:(MXKCellData *)cellData
|
||||||
{
|
{
|
||||||
[super render:cellData];
|
[super render:cellData];
|
||||||
|
|
|
@ -28,8 +28,6 @@
|
||||||
[super customizeTableViewCellRendering];
|
[super customizeTableViewCellRendering];
|
||||||
|
|
||||||
[self updateUserNameColor];
|
[self updateUserNameColor];
|
||||||
|
|
||||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)render:(MXKCellData *)cellData
|
- (void)render:(MXKCellData *)cellData
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
[self updateUserNameColor];
|
[self updateUserNameColor];
|
||||||
self.paginationLabel.textColor = ThemeService.shared.theme.tintColor;
|
self.paginationLabel.textColor = ThemeService.shared.theme.tintColor;
|
||||||
self.paginationSeparatorView.backgroundColor = ThemeService.shared.theme.tintColor;
|
self.paginationSeparatorView.backgroundColor = ThemeService.shared.theme.tintColor;
|
||||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)render:(MXKCellData *)cellData
|
- (void)render:(MXKCellData *)cellData
|
||||||
|
|
|
@ -22,11 +22,4 @@
|
||||||
|
|
||||||
@implementation RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell
|
@implementation RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell
|
||||||
|
|
||||||
- (void)customizeTableViewCellRendering
|
|
||||||
{
|
|
||||||
[super customizeTableViewCellRendering];
|
|
||||||
|
|
||||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -25,8 +25,6 @@
|
||||||
- (void)customizeTableViewCellRendering
|
- (void)customizeTableViewCellRendering
|
||||||
{
|
{
|
||||||
[super customizeTableViewCellRendering];
|
[super customizeTableViewCellRendering];
|
||||||
|
|
||||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -25,8 +25,6 @@
|
||||||
- (void)customizeTableViewCellRendering
|
- (void)customizeTableViewCellRendering
|
||||||
{
|
{
|
||||||
[super customizeTableViewCellRendering];
|
[super customizeTableViewCellRendering];
|
||||||
|
|
||||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -28,8 +28,6 @@
|
||||||
[super customizeTableViewCellRendering];
|
[super customizeTableViewCellRendering];
|
||||||
|
|
||||||
[self updateUserNameColor];
|
[self updateUserNameColor];
|
||||||
|
|
||||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,6 @@
|
||||||
- (void)customizeTableViewCellRendering
|
- (void)customizeTableViewCellRendering
|
||||||
{
|
{
|
||||||
[super customizeTableViewCellRendering];
|
[super customizeTableViewCellRendering];
|
||||||
|
|
||||||
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -44,7 +44,7 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
|
||||||
private var hostingViewController: VectorHostingController!
|
private var hostingViewController: VectorHostingController!
|
||||||
private var wysiwygViewModel = WysiwygComposerViewModel(
|
private var wysiwygViewModel = WysiwygComposerViewModel(
|
||||||
textColor: ThemeService.shared().theme.colors.primaryContent,
|
textColor: ThemeService.shared().theme.colors.primaryContent,
|
||||||
linkColor: ThemeService.shared().theme.colors.accent,
|
linkColor: ThemeService.shared().theme.colors.links,
|
||||||
codeBackgroundColor: ThemeService.shared().theme.selectedBackgroundColor
|
codeBackgroundColor: ThemeService.shared().theme.selectedBackgroundColor
|
||||||
)
|
)
|
||||||
private var viewModel: ComposerViewModelProtocol!
|
private var viewModel: ComposerViewModelProtocol!
|
||||||
|
@ -299,7 +299,7 @@ class WysiwygInputToolbarView: MXKRoomInputToolbarView, NibLoadable, HtmlRoomInp
|
||||||
private func update(theme: Theme) {
|
private func update(theme: Theme) {
|
||||||
hostingViewController.view.backgroundColor = theme.colors.background
|
hostingViewController.view.backgroundColor = theme.colors.background
|
||||||
wysiwygViewModel.textColor = theme.colors.primaryContent
|
wysiwygViewModel.textColor = theme.colors.primaryContent
|
||||||
wysiwygViewModel.linkColor = theme.colors.accent
|
wysiwygViewModel.linkColor = theme.colors.links
|
||||||
wysiwygViewModel.codeBackgroundColor = theme.selectedBackgroundColor
|
wysiwygViewModel.codeBackgroundColor = theme.selectedBackgroundColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ import MediaPlayer
|
||||||
private var roomAvatarLoader: MXMediaLoader?
|
private var roomAvatarLoader: MXMediaLoader?
|
||||||
private let audioPlayers: NSMapTable<NSString, VoiceMessageAudioPlayer>
|
private let audioPlayers: NSMapTable<NSString, VoiceMessageAudioPlayer>
|
||||||
private let audioRecorders: NSHashTable<VoiceMessageAudioRecorder>
|
private let audioRecorders: NSHashTable<VoiceMessageAudioRecorder>
|
||||||
|
private let nowPlayingInfoDelegates: NSMapTable<VoiceMessageAudioPlayer, VoiceMessageNowPlayingInfoDelegate>
|
||||||
|
|
||||||
private var displayLink: CADisplayLink!
|
private var displayLink: CADisplayLink!
|
||||||
|
|
||||||
|
@ -93,6 +94,7 @@ import MediaPlayer
|
||||||
private override init() {
|
private override init() {
|
||||||
audioPlayers = NSMapTable<NSString, VoiceMessageAudioPlayer>(valueOptions: .weakMemory)
|
audioPlayers = NSMapTable<NSString, VoiceMessageAudioPlayer>(valueOptions: .weakMemory)
|
||||||
audioRecorders = NSHashTable<VoiceMessageAudioRecorder>(options: .weakMemory)
|
audioRecorders = NSHashTable<VoiceMessageAudioRecorder>(options: .weakMemory)
|
||||||
|
nowPlayingInfoDelegates = NSMapTable<VoiceMessageAudioPlayer, VoiceMessageNowPlayingInfoDelegate>(keyOptions: .weakMemory, valueOptions: .weakMemory)
|
||||||
activeAudioPlayers = Set<VoiceMessageAudioPlayer>()
|
activeAudioPlayers = Set<VoiceMessageAudioPlayer>()
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
|
@ -123,27 +125,54 @@ import MediaPlayer
|
||||||
pauseAllServicesExcept(nil)
|
pauseAllServicesExcept(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func registerNowPlayingInfoDelegate(_ delegate: VoiceMessageNowPlayingInfoDelegate, forPlayer player: VoiceMessageAudioPlayer) {
|
||||||
|
nowPlayingInfoDelegates.setObject(delegate, forKey: player)
|
||||||
|
}
|
||||||
|
|
||||||
|
func deregisterNowPlayingInfoDelegate(forPlayer player: VoiceMessageAudioPlayer) {
|
||||||
|
nowPlayingInfoDelegates.removeObject(forKey: player)
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - VoiceMessageAudioPlayerDelegate
|
// MARK: - VoiceMessageAudioPlayerDelegate
|
||||||
|
|
||||||
func audioPlayerDidStartPlaying(_ audioPlayer: VoiceMessageAudioPlayer) {
|
func audioPlayerDidStartPlaying(_ audioPlayer: VoiceMessageAudioPlayer) {
|
||||||
currentlyPlayingAudioPlayer = audioPlayer
|
currentlyPlayingAudioPlayer = audioPlayer
|
||||||
activeAudioPlayers.insert(audioPlayer)
|
activeAudioPlayers.insert(audioPlayer)
|
||||||
setUpRemoteCommandCenter()
|
|
||||||
|
let shouldSetupRemoteCommandCenter = nowPlayingInfoDelegates.object(forKey: audioPlayer)?.shouldSetupRemoteCommandCenter(audioPlayer: audioPlayer) ?? true
|
||||||
|
if shouldSetupRemoteCommandCenter {
|
||||||
|
setUpRemoteCommandCenter()
|
||||||
|
} else {
|
||||||
|
// clean up the remote command center
|
||||||
|
tearDownRemoteCommandCenter()
|
||||||
|
}
|
||||||
pauseAllServicesExcept(audioPlayer)
|
pauseAllServicesExcept(audioPlayer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func audioPlayerDidStopPlaying(_ audioPlayer: VoiceMessageAudioPlayer) {
|
func audioPlayerDidStopPlaying(_ audioPlayer: VoiceMessageAudioPlayer) {
|
||||||
if currentlyPlayingAudioPlayer == audioPlayer {
|
if currentlyPlayingAudioPlayer == audioPlayer {
|
||||||
currentlyPlayingAudioPlayer = nil
|
// If we have a NowPlayingInfoDelegate for this player
|
||||||
tearDownRemoteCommandCenter()
|
let nowPlayingInfoDelegate = nowPlayingInfoDelegates.object(forKey: audioPlayer)
|
||||||
|
|
||||||
|
// ask the delegate if we should disconnect from NowPlayingInfoCenter (if there's no delegate, we consider it safe to disconnect it)
|
||||||
|
if nowPlayingInfoDelegate?.shouldDisconnectFromNowPlayingInfoCenter(audioPlayer: audioPlayer) ?? true {
|
||||||
|
currentlyPlayingAudioPlayer = nil
|
||||||
|
tearDownRemoteCommandCenter()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
activeAudioPlayers.remove(audioPlayer)
|
activeAudioPlayers.remove(audioPlayer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func audioPlayerDidFinishPlaying(_ audioPlayer: VoiceMessageAudioPlayer) {
|
func audioPlayerDidFinishPlaying(_ audioPlayer: VoiceMessageAudioPlayer) {
|
||||||
if currentlyPlayingAudioPlayer == audioPlayer {
|
if currentlyPlayingAudioPlayer == audioPlayer {
|
||||||
currentlyPlayingAudioPlayer = nil
|
// If we have a NowPlayingInfoDelegate for this player
|
||||||
tearDownRemoteCommandCenter()
|
let nowPlayingInfoDelegate = nowPlayingInfoDelegates.object(forKey: audioPlayer)
|
||||||
|
|
||||||
|
// ask the delegate if we should disconnect from NowPlayingInfoCenter (if there's no delegate, we consider it safe to disconnect it)
|
||||||
|
if nowPlayingInfoDelegate?.shouldDisconnectFromNowPlayingInfoCenter(audioPlayer: audioPlayer) ?? true {
|
||||||
|
currentlyPlayingAudioPlayer = nil
|
||||||
|
tearDownRemoteCommandCenter()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
activeAudioPlayers.remove(audioPlayer)
|
activeAudioPlayers.remove(audioPlayer)
|
||||||
}
|
}
|
||||||
|
@ -249,6 +278,17 @@ import MediaPlayer
|
||||||
|
|
||||||
let nowPlayingInfoCenter = MPNowPlayingInfoCenter.default()
|
let nowPlayingInfoCenter = MPNowPlayingInfoCenter.default()
|
||||||
nowPlayingInfoCenter.nowPlayingInfo = nil
|
nowPlayingInfoCenter.nowPlayingInfo = nil
|
||||||
|
nowPlayingInfoCenter.playbackState = .stopped
|
||||||
|
|
||||||
|
let commandCenter = MPRemoteCommandCenter.shared()
|
||||||
|
commandCenter.playCommand.isEnabled = false
|
||||||
|
commandCenter.playCommand.removeTarget(nil)
|
||||||
|
commandCenter.pauseCommand.isEnabled = false
|
||||||
|
commandCenter.pauseCommand.removeTarget(nil)
|
||||||
|
commandCenter.skipForwardCommand.isEnabled = false
|
||||||
|
commandCenter.skipForwardCommand.removeTarget(nil)
|
||||||
|
commandCenter.skipBackwardCommand.isEnabled = false
|
||||||
|
commandCenter.skipBackwardCommand.removeTarget(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateNowPlayingInfoCenter() {
|
private func updateNowPlayingInfoCenter() {
|
||||||
|
@ -256,9 +296,14 @@ import MediaPlayer
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let nowPlayingInfoCenter = MPNowPlayingInfoCenter.default()
|
// Checks if we have a delegate for this player, or if we should update the NowPlayingInfoCenter ourselves
|
||||||
nowPlayingInfoCenter.nowPlayingInfo = [MPMediaItemPropertyTitle: VectorL10n.voiceMessageLockScreenPlaceholder,
|
if let nowPlayingInfoDelegate = nowPlayingInfoDelegates.object(forKey: audioPlayer) {
|
||||||
MPMediaItemPropertyPlaybackDuration: audioPlayer.duration as Any,
|
nowPlayingInfoDelegate.updateNowPlayingInfoCenter(forPlayer: audioPlayer)
|
||||||
MPNowPlayingInfoPropertyElapsedPlaybackTime: audioPlayer.currentTime as Any]
|
} else {
|
||||||
|
let nowPlayingInfoCenter = MPNowPlayingInfoCenter.default()
|
||||||
|
nowPlayingInfoCenter.nowPlayingInfo = [MPMediaItemPropertyTitle: VectorL10n.voiceMessageLockScreenPlaceholder,
|
||||||
|
MPMediaItemPropertyPlaybackDuration: audioPlayer.duration as Any,
|
||||||
|
MPNowPlayingInfoPropertyElapsedPlaybackTime: audioPlayer.currentTime as Any]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
//
|
||||||
|
// Copyright 2023 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
@objc protocol VoiceMessageNowPlayingInfoDelegate {
|
||||||
|
|
||||||
|
func updateNowPlayingInfoCenter(forPlayer player: VoiceMessageAudioPlayer)
|
||||||
|
|
||||||
|
func shouldSetupRemoteCommandCenter(audioPlayer player: VoiceMessageAudioPlayer) -> Bool
|
||||||
|
|
||||||
|
func shouldDisconnectFromNowPlayingInfoCenter(audioPlayer: VoiceMessageAudioPlayer) -> Bool
|
||||||
|
}
|
|
@ -176,7 +176,8 @@ typedef NS_ENUM(NSUInteger, LABS_ENABLE)
|
||||||
LABS_ENABLE_NEW_SESSION_MANAGER,
|
LABS_ENABLE_NEW_SESSION_MANAGER,
|
||||||
LABS_ENABLE_NEW_CLIENT_INFO_FEATURE,
|
LABS_ENABLE_NEW_CLIENT_INFO_FEATURE,
|
||||||
LABS_ENABLE_WYSIWYG_COMPOSER,
|
LABS_ENABLE_WYSIWYG_COMPOSER,
|
||||||
LABS_ENABLE_VOICE_BROADCAST
|
LABS_ENABLE_VOICE_BROADCAST,
|
||||||
|
LABS_ENABLE_CRYPTO_SDK
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef NS_ENUM(NSUInteger, SECURITY)
|
typedef NS_ENUM(NSUInteger, SECURITY)
|
||||||
|
@ -587,6 +588,13 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
|
||||||
if (BuildSettings.settingsScreenShowLabSettings)
|
if (BuildSettings.settingsScreenShowLabSettings)
|
||||||
{
|
{
|
||||||
Section *sectionLabs = [Section sectionWithTag:SECTION_TAG_LABS];
|
Section *sectionLabs = [Section sectionWithTag:SECTION_TAG_LABS];
|
||||||
|
#if DEBUG
|
||||||
|
if (MXSDKOptions.sharedInstance.isCryptoSDKAvailable)
|
||||||
|
{
|
||||||
|
[sectionLabs addRowWithTag:LABS_ENABLE_CRYPTO_SDK];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
[sectionLabs addRowWithTag:LABS_ENABLE_RINGING_FOR_GROUP_CALLS_INDEX];
|
[sectionLabs addRowWithTag:LABS_ENABLE_RINGING_FOR_GROUP_CALLS_INDEX];
|
||||||
[sectionLabs addRowWithTag:LABS_ENABLE_THREADS_INDEX];
|
[sectionLabs addRowWithTag:LABS_ENABLE_THREADS_INDEX];
|
||||||
[sectionLabs addRowWithTag:LABS_ENABLE_AUTO_REPORT_DECRYPTION_ERRORS];
|
[sectionLabs addRowWithTag:LABS_ENABLE_AUTO_REPORT_DECRYPTION_ERRORS];
|
||||||
|
@ -2583,6 +2591,23 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
|
||||||
|
|
||||||
cell = labelAndSwitchCell;
|
cell = labelAndSwitchCell;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
if (row == LABS_ENABLE_CRYPTO_SDK)
|
||||||
|
{
|
||||||
|
MXKTableViewCellWithLabelAndSwitch *labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath];
|
||||||
|
BOOL isEnabled = MXSDKOptions.sharedInstance.enableCryptoSDK;
|
||||||
|
labelAndSwitchCell.mxkLabel.text = isEnabled ? VectorL10n.settingsLabsDisableCryptoSdk : VectorL10n.settingsLabsEnableCryptoSdk;
|
||||||
|
labelAndSwitchCell.mxkSwitch.on = isEnabled;
|
||||||
|
[labelAndSwitchCell.mxkSwitch setEnabled:!isEnabled];
|
||||||
|
labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor;
|
||||||
|
[labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleEnableCryptoSDKFeature:) forControlEvents:UIControlEventTouchUpInside];
|
||||||
|
|
||||||
|
cell = labelAndSwitchCell;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (section == SECTION_TAG_SECURITY)
|
else if (section == SECTION_TAG_SECURITY)
|
||||||
{
|
{
|
||||||
|
@ -3354,6 +3379,37 @@ ChangePasswordCoordinatorBridgePresenterDelegate>
|
||||||
RiotSettings.shared.enableVoiceBroadcast = sender.isOn;
|
RiotSettings.shared.enableVoiceBroadcast = sender.isOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
- (void)toggleEnableCryptoSDKFeature:(UISwitch *)sender
|
||||||
|
{
|
||||||
|
BOOL isEnabled = sender.isOn;
|
||||||
|
MXWeakify(self);
|
||||||
|
|
||||||
|
[currentAlert dismissViewControllerAnimated:NO completion:nil];
|
||||||
|
UIAlertController *confirmationAlert = [UIAlertController alertControllerWithTitle:nil
|
||||||
|
message:VectorL10n.settingsLabsConfirmCryptoSdk
|
||||||
|
preferredStyle:UIAlertControllerStyleAlert];
|
||||||
|
|
||||||
|
[confirmationAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n cancel] style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) {
|
||||||
|
MXStrongifyAndReturnIfNil(self);
|
||||||
|
self->currentAlert = nil;
|
||||||
|
|
||||||
|
[sender setOn:NO animated:YES];
|
||||||
|
}]];
|
||||||
|
|
||||||
|
[confirmationAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n continue] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
|
||||||
|
MXStrongifyAndReturnIfNil(self);
|
||||||
|
|
||||||
|
RiotSettings.shared.enableCryptoSDK = isEnabled;
|
||||||
|
MXSDKOptions.sharedInstance.enableCryptoSDK = isEnabled;
|
||||||
|
[[AppDelegate theDelegate] reloadMatrixSessions:YES];
|
||||||
|
}]];
|
||||||
|
|
||||||
|
[self presentViewController:confirmationAlert animated:YES completion:nil];
|
||||||
|
currentAlert = confirmationAlert;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
- (void)togglePinRoomsWithMissedNotif:(UISwitch *)sender
|
- (void)togglePinRoomsWithMissedNotif:(UISwitch *)sender
|
||||||
{
|
{
|
||||||
RiotSettings.shared.pinRoomsWithMissedNotificationsOnHome = sender.isOn;
|
RiotSettings.shared.pinRoomsWithMissedNotificationsOnHome = sender.isOn;
|
||||||
|
|
|
@ -53,6 +53,8 @@ public class VoiceBroadcastAggregator {
|
||||||
private var voiceBroadcastInfoStartEventContent: VoiceBroadcastInfo!
|
private var voiceBroadcastInfoStartEventContent: VoiceBroadcastInfo!
|
||||||
private var voiceBroadcastSenderId: String!
|
private var voiceBroadcastSenderId: String!
|
||||||
|
|
||||||
|
public private(set) var voiceBroadcastLastChunkSequence: Int = 0
|
||||||
|
|
||||||
private var referenceEventsListener: Any?
|
private var referenceEventsListener: Any?
|
||||||
|
|
||||||
private var events: [MXEvent] = []
|
private var events: [MXEvent] = []
|
||||||
|
@ -168,7 +170,10 @@ public class VoiceBroadcastAggregator {
|
||||||
let state = VoiceBroadcastInfoState(rawValue: voiceBroadcastInfo.state) else {
|
let state = VoiceBroadcastInfoState(rawValue: voiceBroadcastInfo.state) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// For .pause and .stopped, update the last chunk sequence
|
||||||
|
if [.stopped, .paused].contains(state) {
|
||||||
|
self.voiceBroadcastLastChunkSequence = voiceBroadcastInfo.lastChunkSequence
|
||||||
|
}
|
||||||
self.delegate?.voiceBroadcastAggregator(self, didReceiveState: state)
|
self.delegate?.voiceBroadcastAggregator(self, didReceiveState: state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,6 +192,7 @@ public class VoiceBroadcastAggregator {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.events.removeAll()
|
self.events.removeAll()
|
||||||
|
self.voiceBroadcastLastChunkSequence = 0
|
||||||
|
|
||||||
let filteredChunk = response.chunk.filter { event in
|
let filteredChunk = response.chunk.filter { event in
|
||||||
event.sender == self.voiceBroadcastSenderId &&
|
event.sender == self.voiceBroadcastSenderId &&
|
||||||
|
|
|
@ -186,7 +186,7 @@ public class VoiceBroadcastService: NSObject {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
self.room.sendStateEvent(.custom(VoiceBroadcastSettings.voiceBroadcastInfoContentKeyType),
|
let httpOperation = self.room.sendStateEvent(.custom(VoiceBroadcastSettings.voiceBroadcastInfoContentKeyType),
|
||||||
content: stateEventContent, stateKey: stateKey) { [weak self] response in
|
content: stateEventContent, stateKey: stateKey) { [weak self] response in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
|
|
||||||
|
@ -199,6 +199,9 @@ public class VoiceBroadcastService: NSObject {
|
||||||
}
|
}
|
||||||
taskCompleted()
|
taskCompleted()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// No retry to send the request
|
||||||
|
httpOperation.maxNumberOfTries = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -295,7 +298,7 @@ extension MXRoom {
|
||||||
threadId: String? = nil,
|
threadId: String? = nil,
|
||||||
sequence: UInt,
|
sequence: UInt,
|
||||||
success: @escaping ((String?) -> Void),
|
success: @escaping ((String?) -> Void),
|
||||||
failure: @escaping ((Error?) -> Void)) -> MXHTTPOperation? {
|
failure: @escaping ((Swift.Error?) -> Void)) -> MXHTTPOperation? {
|
||||||
guard let relatesTo = MXEventContentRelatesTo(relationType: MXEventRelationTypeReference,
|
guard let relatesTo = MXEventContentRelatesTo(relationType: MXEventRelationTypeReference,
|
||||||
eventId: voiceBroadcastId).jsonDictionary() as? [String: Any] else {
|
eventId: voiceBroadcastId).jsonDictionary() as? [String: Any] else {
|
||||||
failure(VoiceBroadcastServiceError.unknown)
|
failure(VoiceBroadcastServiceError.unknown)
|
||||||
|
|
|
@ -359,7 +359,8 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
|
||||||
attributes:@{
|
attributes:@{
|
||||||
NSLinkAttributeName: linkActionString,
|
NSLinkAttributeName: linkActionString,
|
||||||
NSForegroundColorAttributeName: self.sendingTextColor,
|
NSForegroundColorAttributeName: self.sendingTextColor,
|
||||||
NSFontAttributeName: self.encryptedMessagesTextFont
|
NSFontAttributeName: self.encryptedMessagesTextFont,
|
||||||
|
NSUnderlineStyleAttributeName: [NSNumber numberWithInt:NSUnderlineStyleSingle]
|
||||||
}]];
|
}]];
|
||||||
|
|
||||||
[attributedStringWithRerequestMessage appendAttributedString:
|
[attributedStringWithRerequestMessage appendAttributedString:
|
||||||
|
@ -384,8 +385,6 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
|
||||||
[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@" %@", [VectorL10n eventFormatterMessageEditedMention]]
|
[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@" %@", [VectorL10n eventFormatterMessageEditedMention]]
|
||||||
attributes:@{
|
attributes:@{
|
||||||
NSLinkAttributeName: linkActionString,
|
NSLinkAttributeName: linkActionString,
|
||||||
// NOTE: Color is curretly overidden by UIText.tintColor as we use `NSLinkAttributeName`.
|
|
||||||
// If we use UITextView.linkTextAttributes to set link color we will also have the issue that color will be the same for all kind of links.
|
|
||||||
NSForegroundColorAttributeName: self.editionMentionTextColor,
|
NSForegroundColorAttributeName: self.editionMentionTextColor,
|
||||||
NSFontAttributeName: self.editionMentionTextFont
|
NSFontAttributeName: self.editionMentionTextFont
|
||||||
}]];
|
}]];
|
||||||
|
@ -487,6 +486,7 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
|
||||||
self.bingTextColor = ThemeService.shared.theme.noticeColor;
|
self.bingTextColor = ThemeService.shared.theme.noticeColor;
|
||||||
self.encryptingTextColor = ThemeService.shared.theme.textPrimaryColor;
|
self.encryptingTextColor = ThemeService.shared.theme.textPrimaryColor;
|
||||||
self.sendingTextColor = ThemeService.shared.theme.textPrimaryColor;
|
self.sendingTextColor = ThemeService.shared.theme.textPrimaryColor;
|
||||||
|
self.linksColor = ThemeService.shared.theme.colors.links;
|
||||||
self.errorTextColor = ThemeService.shared.theme.textPrimaryColor;
|
self.errorTextColor = ThemeService.shared.theme.textPrimaryColor;
|
||||||
self.showEditionMention = YES;
|
self.showEditionMention = YES;
|
||||||
self.editionMentionTextColor = ThemeService.shared.theme.textSecondaryColor;
|
self.editionMentionTextColor = ThemeService.shared.theme.textSecondaryColor;
|
||||||
|
@ -546,8 +546,8 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - MXRoomSummaryUpdating
|
#pragma mark - MXRoomSummaryUpdating
|
||||||
- (BOOL)session:(MXSession *)session updateRoomSummary:(MXRoomSummary *)summary withLastEvent:(MXEvent *)event eventState:(MXRoomState *)eventState roomState:(MXRoomState *)roomState {
|
- (BOOL)session:(MXSession *)session updateRoomSummary:(MXRoomSummary *)summary withLastEvent:(MXEvent *)event eventState:(MXRoomState *)eventState roomState:(MXRoomState *)roomState
|
||||||
|
{
|
||||||
// Do not display voice broadcast chunk in last message.
|
// Do not display voice broadcast chunk in last message.
|
||||||
if (event.eventType == MXEventTypeRoomMessage && event.content[VoiceBroadcastSettings.voiceBroadcastContentKeyChunkType])
|
if (event.eventType == MXEventTypeRoomMessage && event.content[VoiceBroadcastSettings.voiceBroadcastContentKeyChunkType])
|
||||||
{
|
{
|
||||||
|
@ -555,31 +555,94 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update last message if we have a voice broadcast in the room.
|
// Update last message if we have a voice broadcast in the room.
|
||||||
if ([event.type isEqualToString:VoiceBroadcastSettings.voiceBroadcastInfoContentKeyType])
|
MXEvent *lastVoiceBroadcastInfoEvent = [self lastVoiceBroadcastInfoEventWithEvent:event roomState:roomState];
|
||||||
|
if (lastVoiceBroadcastInfoEvent != nil)
|
||||||
{
|
{
|
||||||
return [self session:session updateRoomSummary:summary withVoiceBroadcastInfoStateEvent:event roomState:roomState];
|
MXEvent *voiceBroadcastInfoStartedEvent = [self voiceBroadcastInfoStartedEventWithEvent:lastVoiceBroadcastInfoEvent
|
||||||
}
|
roomId:summary.roomId
|
||||||
else
|
session:session];
|
||||||
{
|
if (voiceBroadcastInfoStartedEvent != nil
|
||||||
MXEvent *stateEvent = [roomState stateEventsWithType:VoiceBroadcastSettings.voiceBroadcastInfoContentKeyType].lastObject;
|
&& !(voiceBroadcastInfoStartedEvent.isRedactedEvent || [voiceBroadcastInfoStartedEvent.eventId isEqualToString:event.redacts]))
|
||||||
if (stateEvent && ![VoiceBroadcastInfo isStoppedFor:[VoiceBroadcastInfo modelFromJSON: stateEvent.content].state])
|
|
||||||
{
|
{
|
||||||
return [self session:session updateRoomSummary:summary withVoiceBroadcastInfoStateEvent:stateEvent roomState:roomState];
|
return [self session:session
|
||||||
|
updateRoomSummary:summary
|
||||||
|
withVoiceBroadcastInfoStateEvent:lastVoiceBroadcastInfoEvent
|
||||||
|
voiceBroadcastInfoStartedEvent:voiceBroadcastInfoStartedEvent roomState:roomState];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL updated = [super session:session updateRoomSummary:summary withLastEvent:event eventState:eventState roomState:roomState];
|
BOOL updated = [super session:session updateRoomSummary:summary withLastEvent:event eventState:eventState roomState:roomState];
|
||||||
|
|
||||||
if (updated) {
|
if (updated)
|
||||||
|
{
|
||||||
// Force the default text color for the last message (cancel highlighted message color)
|
// Force the default text color for the last message (cancel highlighted message color)
|
||||||
NSMutableAttributedString *lastEventDescription = [[NSMutableAttributedString alloc] initWithAttributedString:summary.lastMessage.attributedText];
|
NSMutableAttributedString *lastEventDescription = [[NSMutableAttributedString alloc] initWithAttributedString:summary.lastMessage.attributedText];
|
||||||
[lastEventDescription addAttribute:NSForegroundColorAttributeName value:ThemeService.shared.theme.textSecondaryColor range:NSMakeRange(0, lastEventDescription.length)];
|
[lastEventDescription addAttribute:NSForegroundColorAttributeName value:ThemeService.shared.theme.textSecondaryColor
|
||||||
|
range:NSMakeRange(0, lastEventDescription.length)];
|
||||||
summary.lastMessage.attributedText = lastEventDescription;
|
summary.lastMessage.attributedText = lastEventDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
return updated;
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (MXEvent *)lastVoiceBroadcastInfoEventWithEvent:(MXEvent *)event roomState:(MXRoomState *)roomState
|
||||||
|
{
|
||||||
|
MXEvent *voiceBroadcastInfoEvent = nil;
|
||||||
|
VoiceBroadcastInfo *info = nil;
|
||||||
|
if ([event.type isEqualToString:VoiceBroadcastSettings.voiceBroadcastInfoContentKeyType])
|
||||||
|
{
|
||||||
|
info = [VoiceBroadcastInfo modelFromJSON: event.content];
|
||||||
|
|
||||||
|
if (info != nil)
|
||||||
|
{
|
||||||
|
voiceBroadcastInfoEvent = event;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
MXEvent *stateEvent = [roomState stateEventsWithType:VoiceBroadcastSettings.voiceBroadcastInfoContentKeyType].lastObject;
|
||||||
|
if (stateEvent != nil)
|
||||||
|
{
|
||||||
|
info = [VoiceBroadcastInfo modelFromJSON: stateEvent.content];
|
||||||
|
if (info != nil && ![VoiceBroadcastInfo isStoppedFor:info.state])
|
||||||
|
{
|
||||||
|
voiceBroadcastInfoEvent = stateEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return voiceBroadcastInfoEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (MXEvent *)voiceBroadcastInfoStartedEventWithEvent:(MXEvent *)voiceBroadcastInfoEvent roomId:(NSString *)roomId session:(MXSession *)session
|
||||||
|
{
|
||||||
|
VoiceBroadcastInfo *voiceBroadcastInfo = [VoiceBroadcastInfo modelFromJSON: voiceBroadcastInfoEvent.content];
|
||||||
|
if ([VoiceBroadcastInfo isStartedFor:voiceBroadcastInfo.state])
|
||||||
|
{
|
||||||
|
return voiceBroadcastInfoEvent;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dispatch_group_t group = dispatch_group_create();
|
||||||
|
dispatch_group_enter(group);
|
||||||
|
|
||||||
|
__block MXEvent *voiceBroadcastInfoStartedEvent;
|
||||||
|
|
||||||
|
[session eventWithEventId:voiceBroadcastInfo.voiceBroadcastId inRoom:roomId success:^(MXEvent *resultEvent) {
|
||||||
|
voiceBroadcastInfoStartedEvent = resultEvent;
|
||||||
|
dispatch_group_leave(group);
|
||||||
|
} failure:^(NSError *error) {
|
||||||
|
MXLogErrorDetails(@"[EventFormatter] Fetch eventWithEventId with error = %@", error.description);
|
||||||
|
dispatch_group_leave(group);
|
||||||
|
}];
|
||||||
|
|
||||||
|
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
|
||||||
|
|
||||||
|
return voiceBroadcastInfoStartedEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)session:(MXSession *)session updateRoomSummary:(MXRoomSummary *)summary withStateEvents:(NSArray<MXEvent *> *)stateEvents roomState:(MXRoomState *)roomState
|
- (BOOL)session:(MXSession *)session updateRoomSummary:(MXRoomSummary *)summary withStateEvents:(NSArray<MXEvent *> *)stateEvents roomState:(MXRoomState *)roomState
|
||||||
{
|
{
|
||||||
BOOL updated = [super session:session updateRoomSummary:summary withStateEvents:stateEvents roomState:roomState];
|
BOOL updated = [super session:session updateRoomSummary:summary withStateEvents:stateEvents roomState:roomState];
|
||||||
|
@ -603,18 +666,29 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
|
||||||
return updated;
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)session:(MXSession *)session updateRoomSummary:(MXRoomSummary *)summary withVoiceBroadcastInfoStateEvent:(MXEvent *)stateEvent roomState:(MXRoomState *)roomState
|
- (BOOL)session:(MXSession *)session updateRoomSummary:(MXRoomSummary *)summary withVoiceBroadcastInfoStateEvent:(MXEvent *)stateEvent voiceBroadcastInfoStartedEvent:(MXEvent *)voiceBroadcastInfoStartedEvent roomState:(MXRoomState *)roomState
|
||||||
{
|
{
|
||||||
[summary updateLastMessage:[[MXRoomLastMessage alloc] initWithEvent:stateEvent]];
|
BOOL isStoppedVoiceBroadcast = [VoiceBroadcastInfo isStoppedFor:[VoiceBroadcastInfo modelFromJSON: stateEvent.content].state];
|
||||||
if (summary.lastMessage.others == nil)
|
|
||||||
|
if ([summary.lastMessage.eventId isEqualToString:voiceBroadcastInfoStartedEvent.eventId])
|
||||||
{
|
{
|
||||||
summary.lastMessage.others = [NSMutableDictionary dictionary];
|
if (!isStoppedVoiceBroadcast)
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[summary updateLastMessage:[[MXRoomLastMessage alloc] initWithEvent:voiceBroadcastInfoStartedEvent]];
|
||||||
|
if (summary.lastMessage.others == nil)
|
||||||
|
{
|
||||||
|
summary.lastMessage.others = [NSMutableDictionary dictionary];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
summary.lastMessage.others[@"lastEventDate"] = [self dateStringFromEvent:stateEvent withTime:YES];
|
|
||||||
|
|
||||||
NSAttributedString *attachmentString = nil;
|
NSAttributedString *attachmentString = nil;
|
||||||
UIColor *textColor;
|
UIColor *textColor;
|
||||||
if ([VoiceBroadcastInfo isStoppedFor:[VoiceBroadcastInfo modelFromJSON: stateEvent.content].state])
|
if (isStoppedVoiceBroadcast)
|
||||||
{
|
{
|
||||||
textColor = ThemeService.shared.theme.textSecondaryColor;
|
textColor = ThemeService.shared.theme.textSecondaryColor;
|
||||||
NSString *senderDisplayName;
|
NSString *senderDisplayName;
|
||||||
|
@ -627,6 +701,7 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
|
||||||
senderDisplayName = [self senderDisplayNameForEvent:stateEvent withRoomState:roomState];
|
senderDisplayName = [self senderDisplayNameForEvent:stateEvent withRoomState:roomState];
|
||||||
summary.lastMessage.text = [VectorL10n noticeVoiceBroadcastEnded:senderDisplayName];
|
summary.lastMessage.text = [VectorL10n noticeVoiceBroadcastEnded:senderDisplayName];
|
||||||
}
|
}
|
||||||
|
summary.lastMessage.others[@"lastEventDate"] = [self dateStringFromEvent:stateEvent withTime:YES];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -638,6 +713,7 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
|
||||||
attachmentString = [NSAttributedString attributedStringWithAttachment:attachment];
|
attachmentString = [NSAttributedString attributedStringWithAttachment:attachment];
|
||||||
|
|
||||||
summary.lastMessage.text = VectorL10n.noticeVoiceBroadcastLive;
|
summary.lastMessage.text = VectorL10n.noticeVoiceBroadcastLive;
|
||||||
|
summary.lastMessage.others[@"lastEventDate"] = [self dateStringFromEvent:voiceBroadcastInfoStartedEvent withTime:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the attribute text message
|
// Compute the attribute text message
|
||||||
|
|
|
@ -23,4 +23,6 @@
|
||||||
|
|
||||||
#import "BuildInfo.h"
|
#import "BuildInfo.h"
|
||||||
|
|
||||||
|
#import "ThemeService.h"
|
||||||
|
|
||||||
#endif /* RiotNSE_Bridging_Header_h */
|
#endif /* RiotNSE_Bridging_Header_h */
|
||||||
|
|
|
@ -78,3 +78,5 @@ targets:
|
||||||
- "**/*.md" # excludes all files with the .md extension
|
- "**/*.md" # excludes all files with the .md extension
|
||||||
- path: ../Riot/Modules/Room/TimelineCells/Styles/RoomTimelineStyleIdentifier.swift
|
- path: ../Riot/Modules/Room/TimelineCells/Styles/RoomTimelineStyleIdentifier.swift
|
||||||
- path: ../Riot/Modules/VoiceBroadcast/VoiceBroadcastSDK/MatrixSDK
|
- path: ../Riot/Modules/VoiceBroadcast/VoiceBroadcastSDK/MatrixSDK
|
||||||
|
- path: ../Riot/Managers/Theme
|
||||||
|
- path: ../Riot/Categories/UIColor.swift
|
||||||
|
|
|
@ -47,7 +47,7 @@ enum MockAnalyticsPromptScreenState: MockScreenState, CaseIterable {
|
||||||
return (
|
return (
|
||||||
[promptType, viewModel],
|
[promptType, viewModel],
|
||||||
AnyView(AnalyticsPrompt(viewModel: viewModel.context)
|
AnyView(AnalyticsPrompt(viewModel: viewModel.context)
|
||||||
.addDependency(MockAvatarService.example))
|
.environmentObject(AvatarViewModel.withMockedServices()))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,10 +32,6 @@ class AvatarService: AvatarServiceProtocol {
|
||||||
|
|
||||||
private let mediaManager: MXMediaManager
|
private let mediaManager: MXMediaManager
|
||||||
|
|
||||||
static func instantiate(mediaManager: MXMediaManager) -> AvatarServiceProtocol {
|
|
||||||
AvatarService(mediaManager: mediaManager)
|
|
||||||
}
|
|
||||||
|
|
||||||
init(mediaManager: MXMediaManager) {
|
init(mediaManager: MXMediaManager) {
|
||||||
self.mediaManager = mediaManager
|
self.mediaManager = mediaManager
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,7 @@ import SwiftUI
|
||||||
|
|
||||||
struct AvatarImage: View {
|
struct AvatarImage: View {
|
||||||
@Environment(\.theme) var theme: ThemeSwiftUI
|
@Environment(\.theme) var theme: ThemeSwiftUI
|
||||||
@Environment(\.dependencies) var dependencies: DependencyContainer
|
@EnvironmentObject var viewModel: AvatarViewModel
|
||||||
@StateObject var viewModel = AvatarViewModel()
|
|
||||||
|
|
||||||
var mxContentUri: String?
|
var mxContentUri: String?
|
||||||
var matrixItemId: String
|
var matrixItemId: String
|
||||||
|
@ -43,7 +42,6 @@ struct AvatarImage: View {
|
||||||
.frame(maxWidth: CGFloat(size.rawValue), maxHeight: CGFloat(size.rawValue))
|
.frame(maxWidth: CGFloat(size.rawValue), maxHeight: CGFloat(size.rawValue))
|
||||||
.clipShape(Circle())
|
.clipShape(Circle())
|
||||||
.onAppear {
|
.onAppear {
|
||||||
viewModel.inject(dependencies: dependencies)
|
|
||||||
viewModel.loadAvatar(
|
viewModel.loadAvatar(
|
||||||
mxContentUri: mxContentUri,
|
mxContentUri: mxContentUri,
|
||||||
matrixItemId: matrixItemId,
|
matrixItemId: matrixItemId,
|
||||||
|
@ -95,7 +93,7 @@ struct AvatarImage_Previews: PreviewProvider {
|
||||||
AvatarImage(mxContentUri: nil, matrixItemId: name, displayName: name, size: .xLarge)
|
AvatarImage(mxContentUri: nil, matrixItemId: name, displayName: name, size: .xLarge)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.addDependency(MockAvatarService.example)
|
.environmentObject(AvatarViewModel.withMockedServices())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue