Merge pull request #5033 from vector-im/release/1.6.6/release
Release 1.6.6
@@ -16,7 +16,7 @@ env:
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-11
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
@@ -16,7 +16,7 @@ env:
|
||||
jobs:
|
||||
tests:
|
||||
name: Tests
|
||||
runs-on: macos-latest
|
||||
runs-on: macos-11
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
name: Move new issues onto Issue triage board
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
automate-project-columns:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: alex-page/github-project-automation-plus@v0.8.1
|
||||
with:
|
||||
project: Issue triage
|
||||
column: Incoming
|
||||
repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
@@ -0,0 +1,16 @@
|
||||
name: Move X-Needs-Info into Need info column in the Issue triage board
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
|
||||
jobs:
|
||||
Move_Labeled_Issue_On_Project_Board:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: konradpabjan/move-labeled-or-milestoned-issue@v2.0
|
||||
with:
|
||||
action-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
project-url: "https://github.com/vector-im/element-ios/projects/12"
|
||||
column-name: "Need info"
|
||||
label-name: "X-Needs-Info"
|
||||
@@ -11,7 +11,8 @@ disabled_rules:
|
||||
- large_tuple
|
||||
- shorthand_operator
|
||||
- vertical_parameter_alignment
|
||||
- identifier_name
|
||||
- identifier_name
|
||||
- inclusive_language # Disabled until MasterTabBarController refactoring complete
|
||||
|
||||
# some rules are only opt-in
|
||||
opt_in_rules:
|
||||
|
||||
@@ -1,3 +1,40 @@
|
||||
## Changes in 1.6.6 (2021-10-21)
|
||||
|
||||
✨ Features
|
||||
|
||||
- M10.4.1 Home space data filtering ([#4570](https://github.com/vector-im/element-ios/issues/4570))
|
||||
- Implemented message forwarding from within the main application. Updated the share extension designs. ([#5009](https://github.com/vector-im/element-ios/issues/5009))
|
||||
|
||||
🙌 Improvements
|
||||
|
||||
- Settings: Refresh the appearance of headers and footers, with a few minor tweaks to the organisation. ([#5011](https://github.com/vector-im/element-ios/pull/5011))
|
||||
- Upgrade MatrixKit version ([v0.16.9](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.16.9)).
|
||||
- RecentsDataSource: Refactorings for lazy loading room summaries. ([#4384](https://github.com/vector-im/element-ios/issues/4384))
|
||||
- Contacts Access: Request access via a button tap in the new Find Your Contacts footer instead of doing it automatically. ([#4484](https://github.com/vector-im/element-ios/issues/4484))
|
||||
- Navigation: Create RoomCoordinator. ([#4734](https://github.com/vector-im/element-ios/issues/4734))
|
||||
- Navigation: Enable room stacking. ([#4834](https://github.com/vector-im/element-ios/issues/4834))
|
||||
- SwiftUI: Add FramePreferenceKey for use in ViewFrameReader. ([#4974](https://github.com/vector-im/element-ios/issues/4974))
|
||||
- URL Previews: Stop requesting URL previews if the feature has been disabled on the homeserver. ([#5002](https://github.com/vector-im/element-ios/issues/5002))
|
||||
- VectorWellKnown: Make all properties optional. ([#5008](https://github.com/vector-im/element-ios/issues/5008))
|
||||
|
||||
🐛 Bugfixes
|
||||
|
||||
- Message Composer: Pasting images from Safari now pastes the image and not its URL. ([#2076](https://github.com/vector-im/element-ios/issues/2076))
|
||||
- Fixed private space invite should use lock icon instead of planet ([#4886](https://github.com/vector-im/element-ios/issues/4886))
|
||||
- Room Lists: Fix generated avatar colours not matching Element Web. ([#4978](https://github.com/vector-im/element-ios/issues/4978))
|
||||
- Contacts Sync: Move call to validateSyncLocalContactsState into MatrixKit. ([#4989](https://github.com/vector-im/element-ios/issues/4989))
|
||||
- Timeline: Selecting a message now correctly selects any reactions and URL previews too. ([#4992](https://github.com/vector-im/element-ios/issues/4992))
|
||||
|
||||
🧱 Build
|
||||
|
||||
- Build: Update to Xcode 12.5 in the Fastfile and macOS 11 in the GitHub actions. ([#4998](https://github.com/vector-im/element-ios/pull/4998))
|
||||
|
||||
Others
|
||||
|
||||
- Replaced deprecated HPGrowingTextView with GrowingTextView. ([#4976](https://github.com/vector-im/element-ios/issues/4976))
|
||||
- Move new issues into incoming column and move X-Needs-Info into Need info column on the issue triage board ([#5012](https://github.com/vector-im/element-ios/issues/5012))
|
||||
|
||||
|
||||
## Changes in 1.6.5 (2021-10-14)
|
||||
|
||||
🙌 Improvements
|
||||
|
||||
@@ -15,5 +15,5 @@
|
||||
//
|
||||
|
||||
// Version
|
||||
MARKETING_VERSION = 1.6.5
|
||||
CURRENT_PROJECT_VERSION = 1.6.5
|
||||
MARKETING_VERSION = 1.6.6
|
||||
CURRENT_PROJECT_VERSION = 1.6.6
|
||||
|
||||
@@ -281,6 +281,9 @@ final class BuildSettings: NSObject {
|
||||
static let roomScreenAllowStickerAction: Bool = true
|
||||
static let roomScreenAllowFilesAction: Bool = true
|
||||
|
||||
/// Allow split view detail view stacking
|
||||
static let allowSplitViewDetailsScreenStacking: Bool = true
|
||||
|
||||
// MARK: - Room Contextual Menu
|
||||
|
||||
static let roomContextualMenuShowMoreOptionForMessages: Bool = true
|
||||
|
||||
@@ -20,7 +20,7 @@ import UIKit
|
||||
/**
|
||||
ObjC class for holding fonts for use in UIKit.
|
||||
*/
|
||||
@objc public class FontsUIKit: NSObject, Fonts {
|
||||
@objcMembers public class FontsUIKit: NSObject, Fonts {
|
||||
|
||||
public var largeTitle: UIFont
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ use_frameworks!
|
||||
# - `{ {kit spec hash} => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for each 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
|
||||
$matrixKitVersion = '= 0.16.7'
|
||||
$matrixKitVersion = '= 0.16.9'
|
||||
# $matrixKitVersion = :local
|
||||
# $matrixKitVersion = {'develop' => 'develop'}
|
||||
|
||||
@@ -48,6 +48,7 @@ abstract_target 'RiotPods' do
|
||||
pod 'GBDeviceInfo', '~> 6.6.0'
|
||||
pod 'Reusable', '~> 4.1'
|
||||
pod 'KeychainAccess', '~> 4.2.2'
|
||||
pod 'WeakDictionary', '~> 2.0'
|
||||
|
||||
# Piwik for analytics
|
||||
pod 'MatomoTracker', '~> 7.4.1'
|
||||
@@ -55,7 +56,6 @@ abstract_target 'RiotPods' do
|
||||
# Remove warnings from "bad" pods
|
||||
pod 'OLMKit', :inhibit_warnings => true
|
||||
pod 'zxcvbn-ios', :inhibit_warnings => true
|
||||
pod 'HPGrowingTextView', :inhibit_warnings => true
|
||||
|
||||
# Tools
|
||||
pod 'SwiftGen', '~> 6.3'
|
||||
@@ -73,6 +73,7 @@ abstract_target 'RiotPods' do
|
||||
pod 'SideMenu', '~> 6.5'
|
||||
pod 'DSWaveformImage', '~> 6.1.1'
|
||||
pod 'ffmpeg-kit-ios-audio', '~> 4.5'
|
||||
pod 'GrowingTextView', '~> 0.7.2'
|
||||
|
||||
pod 'FLEX', '~> 4.5.0', :configurations => ['Debug']
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "information_button.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"preserves-vector-representation" : true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< >>
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
<< /Length 3 0 R >>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
-1.000000 0.000000 -0.000000 -1.000000 19.184572 19.000000 cm
|
||||
0.552000 0.592000 0.648000 scn
|
||||
9.087891 0.000000 m
|
||||
14.071289 0.000000 18.184570 4.113281 18.184570 9.087891 c
|
||||
18.184570 14.062500 14.062500 18.175781 9.079102 18.175781 c
|
||||
4.104492 18.175781 0.000000 14.062500 0.000000 9.087891 c
|
||||
0.000000 4.113281 4.113281 0.000000 9.087891 0.000000 c
|
||||
h
|
||||
9.087891 1.810547 m
|
||||
5.053711 1.810547 1.828125 5.053711 1.828125 9.087891 c
|
||||
1.828125 13.122070 5.053711 16.356445 9.079102 16.356445 c
|
||||
13.113281 16.356445 16.356445 13.122070 16.365234 9.087891 c
|
||||
16.374023 5.053711 13.122070 1.810547 9.087891 1.810547 c
|
||||
h
|
||||
9.079102 7.628906 m
|
||||
9.562500 7.628906 9.843750 7.901367 9.852539 8.411133 c
|
||||
9.984375 12.638672 l
|
||||
10.001953 13.157227 9.615234 13.535156 9.070312 13.535156 c
|
||||
8.525391 13.535156 8.147461 13.166016 8.165039 12.647461 c
|
||||
8.288086 8.411133 l
|
||||
8.305664 7.910156 8.586914 7.628906 9.079102 7.628906 c
|
||||
h
|
||||
9.079102 4.710938 m
|
||||
9.650391 4.710938 10.116211 5.124023 10.116211 5.686523 c
|
||||
10.116211 6.240234 9.659180 6.653320 9.079102 6.653320 c
|
||||
8.507812 6.653320 8.041992 6.240234 8.041992 5.686523 c
|
||||
8.041992 5.132812 8.516602 4.710938 9.079102 4.710938 c
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
1184
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 20.000000 20.000000 ]
|
||||
/Resources 1 0 R
|
||||
/Contents 2 0 R
|
||||
/Parent 5 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<< /Kids [ 4 0 R ]
|
||||
/Count 1
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<< /Type /Catalog
|
||||
/Pages 5 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 7
|
||||
0000000000 65535 f
|
||||
0000000010 00000 n
|
||||
0000000034 00000 n
|
||||
0000001274 00000 n
|
||||
0000001297 00000 n
|
||||
0000001470 00000 n
|
||||
0000001544 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 6 0 R
|
||||
/Size 7
|
||||
>>
|
||||
startxref
|
||||
1603
|
||||
%%EOF
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "facepile.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "facepile@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "facepile@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 87 KiB |
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "integration_manager_iconpile.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"preserves-vector-representation" : true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,522 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< /BBox [ 0.000000 0.000000 110.000000 46.000000 ]
|
||||
/Resources << >>
|
||||
/Subtype /Form
|
||||
/Length 2 0 R
|
||||
/Group << /Type /Group
|
||||
/S /Transparency
|
||||
>>
|
||||
/Type /XObject
|
||||
>>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 46.000000 13.067383 cm
|
||||
0.450980 0.490196 0.549020 scn
|
||||
8.832680 0.000023 m
|
||||
3.859828 0.578173 0.000000 4.804639 0.000000 9.932617 c
|
||||
0.000000 15.455465 4.477152 19.932617 10.000000 19.932617 c
|
||||
15.152602 19.932617 19.395014 16.035631 19.940670 11.028222 c
|
||||
19.906002 11.044100 19.870073 11.058149 19.832964 11.070212 c
|
||||
16.719622 12.082235 13.238947 11.455502 10.848575 9.043321 c
|
||||
8.464049 6.637041 7.840186 3.135887 8.832680 0.000023 c
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 46.000000 13.067383 cm
|
||||
0.450980 0.490196 0.549020 scn
|
||||
10.722207 0.654825 m
|
||||
19.219536 9.152152 l
|
||||
16.732798 9.960095 14.059622 9.433351 12.260846 7.618164 c
|
||||
10.476121 5.817157 9.948320 3.147501 10.722207 0.654825 c
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
54.832680 13.067406 m
|
||||
49.859829 13.645554 46.000000 17.872021 46.000000 23.000000 c
|
||||
46.000000 28.522848 50.477154 33.000000 56.000000 33.000000 c
|
||||
61.152603 33.000000 65.395012 29.103014 65.940674 24.095604 c
|
||||
65.906006 24.111483 65.870071 24.125532 65.832962 24.137596 c
|
||||
62.719620 25.149618 59.238945 24.522884 56.848576 22.110703 c
|
||||
54.464050 19.704424 53.840187 16.203270 54.832680 13.067406 c
|
||||
h
|
||||
W*
|
||||
n
|
||||
56.722206 13.722206 m
|
||||
65.219536 22.219536 l
|
||||
62.732796 23.027477 60.059624 22.500732 58.260845 20.685547 c
|
||||
56.476120 18.884541 55.948318 16.214884 56.722206 13.722206 c
|
||||
h
|
||||
W*
|
||||
n
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 46.000000 13.067383 cm
|
||||
0.450980 0.490196 0.549020 scn
|
||||
8.832680 0.000023 m
|
||||
8.717499 -0.990683 l
|
||||
9.053570 -1.029755 9.386534 -0.895788 9.601898 -0.634851 c
|
||||
9.817264 -0.373913 9.885659 -0.021587 9.783568 0.300978 c
|
||||
8.832680 0.000023 l
|
||||
h
|
||||
19.940670 11.028222 m
|
||||
19.525362 10.121425 l
|
||||
19.851667 9.971979 20.233105 10.009373 20.524176 10.219343 c
|
||||
20.815245 10.429314 20.971058 10.779479 20.932178 11.136267 c
|
||||
19.940670 11.028222 l
|
||||
h
|
||||
19.832964 11.070212 m
|
||||
20.141296 12.018734 l
|
||||
20.141291 12.018736 l
|
||||
19.832964 11.070212 l
|
||||
h
|
||||
10.848575 9.043321 m
|
||||
11.557022 8.341278 l
|
||||
11.557022 8.341278 l
|
||||
10.848575 9.043321 l
|
||||
h
|
||||
10.722207 0.654825 m
|
||||
9.769680 0.359100 l
|
||||
9.873262 0.025461 10.143859 -0.229664 10.483012 -0.313446 c
|
||||
10.822165 -0.397228 11.180433 -0.297455 11.427460 -0.050428 c
|
||||
10.722207 0.654825 l
|
||||
h
|
||||
19.219536 9.152152 m
|
||||
19.924788 8.446899 l
|
||||
20.170168 8.692279 20.270367 9.047563 20.189354 9.384994 c
|
||||
20.108341 9.722424 19.857763 9.993490 19.527727 10.100719 c
|
||||
19.219536 9.152152 l
|
||||
h
|
||||
12.260846 7.618164 m
|
||||
12.969294 6.916121 l
|
||||
12.969294 6.916121 l
|
||||
12.260846 7.618164 l
|
||||
h
|
||||
8.947861 0.990728 m
|
||||
4.472036 1.511093 0.997378 5.316795 0.997378 9.932617 c
|
||||
-0.997378 9.932617 l
|
||||
-0.997378 4.292482 3.247620 -0.354748 8.717499 -0.990683 c
|
||||
8.947861 0.990728 l
|
||||
h
|
||||
0.997378 9.932617 m
|
||||
0.997378 14.904629 5.027989 18.935240 10.000000 18.935240 c
|
||||
10.000000 20.929995 l
|
||||
3.926316 20.929995 -0.997378 16.006302 -0.997378 9.932617 c
|
||||
0.997378 9.932617 l
|
||||
h
|
||||
10.000000 18.935240 m
|
||||
14.638034 18.935240 18.458044 15.427099 18.949162 10.920177 c
|
||||
20.932178 11.136267 l
|
||||
20.331984 16.644163 15.667171 20.929995 10.000000 20.929995 c
|
||||
10.000000 18.935240 l
|
||||
h
|
||||
20.355978 11.935019 m
|
||||
20.286608 11.966791 20.214968 11.994786 20.141296 12.018734 c
|
||||
19.524632 10.121691 l
|
||||
19.525362 10.121425 l
|
||||
20.355978 11.935019 l
|
||||
h
|
||||
20.141291 12.018736 m
|
||||
16.712317 13.133358 12.825830 12.455570 10.140127 9.745363 c
|
||||
11.557022 8.341278 l
|
||||
13.652063 10.455433 16.726927 11.031113 19.524637 10.121689 c
|
||||
20.141291 12.018736 l
|
||||
h
|
||||
10.140127 9.745363 m
|
||||
7.462934 7.043747 6.791740 3.143171 7.881791 -0.300932 c
|
||||
9.783568 0.300978 l
|
||||
8.888631 3.128603 9.465164 6.230335 11.557022 8.341278 c
|
||||
10.140127 9.745363 l
|
||||
h
|
||||
11.427460 -0.050428 m
|
||||
19.924788 8.446899 l
|
||||
18.514284 9.857405 l
|
||||
10.016954 1.360079 l
|
||||
11.427460 -0.050428 l
|
||||
h
|
||||
19.527727 10.100719 m
|
||||
16.723921 11.011679 13.645474 10.432379 11.552399 8.320207 c
|
||||
12.969294 6.916121 l
|
||||
14.473769 8.434322 16.741674 8.908512 18.911345 8.203585 c
|
||||
19.527727 10.100719 l
|
||||
h
|
||||
11.552399 8.320207 m
|
||||
9.477654 6.226535 8.899933 3.160538 9.769680 0.359100 c
|
||||
11.674734 0.950550 l
|
||||
10.996708 3.134464 11.474587 5.407779 12.969294 6.916121 c
|
||||
11.552399 8.320207 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
3998
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
<< /BBox [ 0.000000 0.000000 110.000000 46.000000 ]
|
||||
/Resources << >>
|
||||
/Subtype /Form
|
||||
/Length 4 0 R
|
||||
/Group << /Type /Group
|
||||
/S /Transparency
|
||||
>>
|
||||
/Type /XObject
|
||||
>>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 39.257812 0.000000 cm
|
||||
0.890196 0.909804 0.941176 scn
|
||||
37.742256 23.000000 m
|
||||
37.742256 10.297451 27.444805 0.000000 14.742256 0.000000 c
|
||||
9.132510 0.000000 3.991834 2.008327 0.000000 5.345207 c
|
||||
4.760142 9.730907 7.742256 16.017200 7.742256 23.000000 c
|
||||
7.742256 29.982801 4.760141 36.269093 0.000000 40.654793 c
|
||||
3.991834 43.991673 9.132510 46.000000 14.742256 46.000000 c
|
||||
27.444805 46.000000 37.742256 35.702549 37.742256 23.000000 c
|
||||
h
|
||||
f*
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
506
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<< /XObject << /X1 1 0 R >>
|
||||
/ExtGState << /E1 << /SMask << /Type /Mask
|
||||
/G 3 0 R
|
||||
/S /Alpha
|
||||
>>
|
||||
/Type /ExtGState
|
||||
>> >>
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<< /Length 7 0 R >>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 71.212158 0.000000 cm
|
||||
0.890196 0.909804 0.941176 scn
|
||||
-0.000005 6.274433 m
|
||||
4.200984 10.596851 6.787903 16.496323 6.787903 23.000000 c
|
||||
6.787903 29.503679 4.200984 35.403149 -0.000005 39.725567 c
|
||||
4.119314 43.615345 9.675125 46.000000 15.787903 46.000000 c
|
||||
28.490452 46.000000 38.787903 35.702549 38.787903 23.000000 c
|
||||
38.787903 10.297451 28.490452 0.000000 15.787903 0.000000 c
|
||||
9.675125 0.000000 4.119314 2.384655 -0.000005 6.274433 c
|
||||
h
|
||||
f*
|
||||
n
|
||||
Q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 39.257812 0.000000 cm
|
||||
0.890196 0.909804 0.941176 scn
|
||||
37.742264 23.000000 m
|
||||
37.742264 10.297451 27.444813 0.000000 14.742264 0.000000 c
|
||||
9.132518 0.000000 3.991842 2.008327 0.000008 5.345207 c
|
||||
4.760150 9.730907 7.742264 16.017200 7.742264 23.000000 c
|
||||
7.742264 29.982801 4.760149 36.269093 0.000008 40.654793 c
|
||||
3.991842 43.991673 9.132518 46.000000 14.742264 46.000000 c
|
||||
27.444813 46.000000 37.742264 35.702549 37.742264 23.000000 c
|
||||
h
|
||||
f*
|
||||
n
|
||||
Q
|
||||
q
|
||||
/E1 gs
|
||||
/X1 Do
|
||||
Q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
|
||||
0.890196 0.909804 0.941176 scn
|
||||
46.000000 23.000000 m
|
||||
46.000000 10.297451 35.702549 0.000000 23.000000 0.000000 c
|
||||
10.297451 0.000000 0.000000 10.297451 0.000000 23.000000 c
|
||||
0.000000 35.702549 10.297451 46.000000 23.000000 46.000000 c
|
||||
35.702549 46.000000 46.000000 35.702549 46.000000 23.000000 c
|
||||
h
|
||||
f*
|
||||
n
|
||||
Q
|
||||
q
|
||||
q
|
||||
1.000000 -0.000000 -0.000000 1.000000 79.000000 12.999998 cm
|
||||
0.450980 0.490196 0.549020 scn
|
||||
0.000000 16.000000 m
|
||||
0.000000 18.209139 1.790861 20.000000 4.000000 20.000000 c
|
||||
15.999997 20.000000 l
|
||||
18.209137 20.000000 19.999998 18.209139 19.999998 16.000000 c
|
||||
19.999998 4.000003 l
|
||||
19.999998 1.790863 18.209137 0.000002 15.999998 0.000002 c
|
||||
4.000000 0.000002 l
|
||||
1.790862 0.000002 0.000000 1.790863 0.000000 4.000002 c
|
||||
0.000000 16.000000 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
79.000000 29.000000 m
|
||||
79.000000 31.209137 80.790863 33.000000 83.000000 33.000000 c
|
||||
95.000000 33.000000 l
|
||||
97.209137 33.000000 99.000000 31.209139 99.000000 29.000000 c
|
||||
99.000000 17.000000 l
|
||||
99.000000 14.790861 97.209137 13.000000 95.000000 13.000000 c
|
||||
83.000000 13.000000 l
|
||||
80.790863 13.000000 79.000000 14.790861 79.000000 17.000000 c
|
||||
79.000000 29.000000 l
|
||||
h
|
||||
W*
|
||||
n
|
||||
q
|
||||
1.000000 -0.000000 -0.000000 1.000000 79.000000 12.999998 cm
|
||||
0.450980 0.490196 0.549020 scn
|
||||
4.000000 18.000000 m
|
||||
15.999997 18.000000 l
|
||||
15.999997 22.000000 l
|
||||
4.000000 22.000000 l
|
||||
4.000000 18.000000 l
|
||||
h
|
||||
17.999998 16.000000 m
|
||||
17.999998 4.000003 l
|
||||
21.999998 4.000003 l
|
||||
21.999998 16.000000 l
|
||||
17.999998 16.000000 l
|
||||
h
|
||||
15.999998 2.000002 m
|
||||
4.000000 2.000002 l
|
||||
4.000000 -1.999998 l
|
||||
15.999998 -1.999998 l
|
||||
15.999998 2.000002 l
|
||||
h
|
||||
2.000000 4.000002 m
|
||||
2.000000 16.000000 l
|
||||
-2.000000 16.000000 l
|
||||
-2.000000 4.000002 l
|
||||
2.000000 4.000002 l
|
||||
h
|
||||
4.000000 2.000002 m
|
||||
2.895431 2.000002 2.000000 2.895433 2.000000 4.000002 c
|
||||
-2.000000 4.000002 l
|
||||
-2.000000 0.686293 0.686293 -1.999998 4.000000 -1.999998 c
|
||||
4.000000 2.000002 l
|
||||
h
|
||||
17.999998 4.000003 m
|
||||
17.999998 2.895433 17.104567 2.000002 15.999998 2.000002 c
|
||||
15.999998 -1.999998 l
|
||||
19.313707 -1.999998 21.999998 0.686295 21.999998 4.000003 c
|
||||
17.999998 4.000003 l
|
||||
h
|
||||
15.999997 18.000000 m
|
||||
17.104567 18.000000 17.999998 17.104568 17.999998 16.000000 c
|
||||
21.999998 16.000000 l
|
||||
21.999998 19.313709 19.313705 22.000000 15.999997 22.000000 c
|
||||
15.999997 18.000000 l
|
||||
h
|
||||
4.000000 22.000000 m
|
||||
0.686291 22.000000 -2.000000 19.313707 -2.000000 16.000000 c
|
||||
2.000000 16.000000 l
|
||||
2.000000 17.104568 2.895431 18.000000 4.000000 18.000000 c
|
||||
4.000000 22.000000 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
Q
|
||||
q
|
||||
1.000000 -0.000000 -0.000000 1.000000 81.000000 14.999998 cm
|
||||
1.000000 1.000000 1.000000 scn
|
||||
16.000000 8.000000 m
|
||||
16.000000 3.581722 12.418278 0.000000 8.000000 0.000000 c
|
||||
3.581722 0.000000 0.000000 3.581722 0.000000 8.000000 c
|
||||
0.000000 12.418278 3.581722 16.000000 8.000000 16.000000 c
|
||||
12.418278 16.000000 16.000000 12.418278 16.000000 8.000000 c
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
q
|
||||
1.000000 -0.000000 -0.000000 1.000000 89.000000 19.896606 cm
|
||||
0.450980 0.490196 0.549020 scn
|
||||
0.750000 7.103394 m
|
||||
0.750000 7.517607 0.414214 7.853394 0.000000 7.853394 c
|
||||
-0.414214 7.853394 -0.750000 7.517607 -0.750000 7.103394 c
|
||||
0.750000 7.103394 l
|
||||
h
|
||||
0.000000 3.290894 m
|
||||
-0.750000 3.290894 l
|
||||
-0.750000 3.041655 -0.626185 2.808699 -0.419605 2.669257 c
|
||||
0.000000 3.290894 l
|
||||
h
|
||||
2.080395 0.981757 m
|
||||
2.423716 0.750016 2.889895 0.840468 3.121636 1.183789 c
|
||||
3.353378 1.527109 3.262925 1.993289 2.919605 2.225030 c
|
||||
2.080395 0.981757 l
|
||||
h
|
||||
-0.750000 7.103394 m
|
||||
-0.750000 3.290894 l
|
||||
0.750000 3.290894 l
|
||||
0.750000 7.103394 l
|
||||
-0.750000 7.103394 l
|
||||
h
|
||||
-0.419605 2.669257 m
|
||||
2.080395 0.981757 l
|
||||
2.919605 2.225030 l
|
||||
0.419605 3.912530 l
|
||||
-0.419605 2.669257 l
|
||||
h
|
||||
f
|
||||
n
|
||||
Q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 14.000000 15.000000 cm
|
||||
0.450980 0.490196 0.549020 scn
|
||||
0.000000 14.727272 m
|
||||
0.000000 16.534750 1.465250 18.000000 3.272727 18.000000 c
|
||||
14.727273 18.000000 l
|
||||
16.534750 18.000000 18.000000 16.534750 18.000000 14.727272 c
|
||||
18.000000 3.272727 l
|
||||
18.000000 1.465250 16.534750 0.000000 14.727273 0.000000 c
|
||||
3.272727 0.000000 l
|
||||
1.465250 0.000000 0.000000 1.465250 0.000000 3.272727 c
|
||||
0.000000 14.727272 l
|
||||
h
|
||||
8.181818 12.681818 m
|
||||
8.181818 11.100275 6.899724 9.818182 5.318182 9.818182 c
|
||||
3.736639 9.818182 2.454545 11.100275 2.454545 12.681818 c
|
||||
2.454545 14.263361 3.736639 15.545454 5.318182 15.545454 c
|
||||
6.899724 15.545454 8.181818 14.263361 8.181818 12.681818 c
|
||||
h
|
||||
5.318182 2.454546 m
|
||||
6.899724 2.454546 8.181818 3.736639 8.181818 5.318182 c
|
||||
8.181818 6.899724 6.899724 8.181818 5.318182 8.181818 c
|
||||
3.736639 8.181818 2.454545 6.899724 2.454545 5.318182 c
|
||||
2.454545 3.736639 3.736639 2.454546 5.318182 2.454546 c
|
||||
h
|
||||
15.545454 5.318182 m
|
||||
15.545454 3.736639 14.263361 2.454546 12.681818 2.454546 c
|
||||
11.100276 2.454546 9.818182 3.736639 9.818182 5.318182 c
|
||||
9.818182 6.899724 11.100276 8.181818 12.681818 8.181818 c
|
||||
14.263361 8.181818 15.545454 6.899724 15.545454 5.318182 c
|
||||
h
|
||||
12.681818 9.818182 m
|
||||
14.263361 9.818182 15.545454 11.100275 15.545454 12.681818 c
|
||||
15.545454 14.263361 14.263361 15.545454 12.681818 15.545454 c
|
||||
11.100276 15.545454 9.818182 14.263361 9.818182 12.681818 c
|
||||
9.818182 11.100275 11.100276 9.818182 12.681818 9.818182 c
|
||||
h
|
||||
f*
|
||||
n
|
||||
Q
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 14.000000 15.000000 cm
|
||||
0.450980 0.490196 0.549020 scn
|
||||
0.000000 14.727272 m
|
||||
0.000000 16.534750 1.465250 18.000000 3.272727 18.000000 c
|
||||
14.727273 18.000000 l
|
||||
16.534750 18.000000 18.000000 16.534750 18.000000 14.727272 c
|
||||
18.000000 3.272727 l
|
||||
18.000000 1.465250 16.534750 0.000000 14.727273 0.000000 c
|
||||
3.272727 0.000000 l
|
||||
1.465250 0.000000 0.000000 1.465250 0.000000 3.272727 c
|
||||
0.000000 14.727272 l
|
||||
h
|
||||
8.181818 12.681818 m
|
||||
8.181818 11.100275 6.899724 9.818182 5.318182 9.818182 c
|
||||
3.736639 9.818182 2.454545 11.100275 2.454545 12.681818 c
|
||||
2.454545 14.263361 3.736639 15.545454 5.318182 15.545454 c
|
||||
6.899724 15.545454 8.181818 14.263361 8.181818 12.681818 c
|
||||
h
|
||||
5.318182 2.454546 m
|
||||
6.899724 2.454546 8.181818 3.736639 8.181818 5.318182 c
|
||||
8.181818 6.899724 6.899724 8.181818 5.318182 8.181818 c
|
||||
3.736639 8.181818 2.454545 6.899724 2.454545 5.318182 c
|
||||
2.454545 3.736639 3.736639 2.454546 5.318182 2.454546 c
|
||||
h
|
||||
15.545454 5.318182 m
|
||||
15.545454 3.736639 14.263361 2.454546 12.681818 2.454546 c
|
||||
11.100276 2.454546 9.818182 3.736639 9.818182 5.318182 c
|
||||
9.818182 6.899724 11.100276 8.181818 12.681818 8.181818 c
|
||||
14.263361 8.181818 15.545454 6.899724 15.545454 5.318182 c
|
||||
h
|
||||
12.681818 9.818182 m
|
||||
14.263361 9.818182 15.545454 11.100275 15.545454 12.681818 c
|
||||
15.545454 14.263361 14.263361 15.545454 12.681818 15.545454 c
|
||||
11.100276 15.545454 9.818182 14.263361 9.818182 12.681818 c
|
||||
9.818182 11.100275 11.100276 9.818182 12.681818 9.818182 c
|
||||
h
|
||||
f*
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
7 0 obj
|
||||
7483
|
||||
endobj
|
||||
|
||||
8 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 110.000000 46.000000 ]
|
||||
/Resources 5 0 R
|
||||
/Contents 6 0 R
|
||||
/Parent 9 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
9 0 obj
|
||||
<< /Kids [ 8 0 R ]
|
||||
/Count 1
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
10 0 obj
|
||||
<< /Type /Catalog
|
||||
/Pages 9 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 11
|
||||
0000000000 65535 f
|
||||
0000000010 00000 n
|
||||
0000004257 00000 n
|
||||
0000004280 00000 n
|
||||
0000005035 00000 n
|
||||
0000005057 00000 n
|
||||
0000005355 00000 n
|
||||
0000012894 00000 n
|
||||
0000012917 00000 n
|
||||
0000013091 00000 n
|
||||
0000013165 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 10 0 R
|
||||
/Size 11
|
||||
>>
|
||||
startxref
|
||||
13225
|
||||
%%EOF
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "space_private_icon.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "space_private_icon@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "space_private_icon@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"template-rendering-intent" : "template"
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 1003 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "radio-button-default.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "radio-button-default@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "radio-button-default@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 615 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "radio-button-selected.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "radio-button-selected@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "radio-button-selected@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 729 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
@@ -1483,3 +1483,4 @@
|
||||
"space_tag" = "Space";
|
||||
"open" = "Öffnen";
|
||||
"settings_links" = "LINKS";
|
||||
"find_your_contacts_footer" = "Dies kann jederzeit in den Einstellungen deaktiviert werden.";
|
||||
|
||||
@@ -18,6 +18,6 @@
|
||||
"NSCameraUsageDescription" = "The camera is used to take photos and videos, make video calls.";
|
||||
"NSPhotoLibraryUsageDescription" = "The photo library is used to send photos and videos.";
|
||||
"NSMicrophoneUsageDescription" = "Element needs to access your microphone to make and receive calls, take videos, and record voice messages.";
|
||||
"NSContactsUsageDescription" = "To discover contacts already using Matrix, Element can send email addresses and phone numbers in your address book to your chosen Matrix identity server. Where supported, personal data is hashed before sending - please check your identity server's privacy policy for more details.";
|
||||
"NSContactsUsageDescription" = "Element will show your contacts so you can invite them to chat.";
|
||||
"NSCalendarsUsageDescription" = "See your scheduled meetings in the app.";
|
||||
"NSFaceIDUsageDescription" = "Face ID is used to access your app.";
|
||||
|
||||
@@ -178,7 +178,7 @@
|
||||
"room_creation_keep_private" = "Keep private";
|
||||
"room_creation_make_private" = "Make private";
|
||||
"room_creation_wait_for_creation" = "A room is already being created. Please wait.";
|
||||
"room_creation_invite_another_user" = "Search / invite by User ID, Name or email";
|
||||
"room_creation_invite_another_user" = "User ID, name or email";
|
||||
"room_creation_error_invite_user_by_email_without_identity_server" = "No identity server is configured so you cannot add a participant with an email.";
|
||||
"room_creation_dm_error" = "We couldn't create your DM. Please check the users you want to invite and try again.";
|
||||
|
||||
@@ -244,8 +244,15 @@ Tap the + to start adding people.";
|
||||
"contacts_address_book_no_contact" = "No local contacts";
|
||||
"contacts_address_book_permission_required" = "Permission required to access local contacts";
|
||||
"contacts_address_book_permission_denied" = "You didn't allow %@ to access your local contacts";
|
||||
"contacts_address_book_permission_denied_alert_title" = "Contacts disabled";
|
||||
"contacts_address_book_permission_denied_alert_message" = "To enable contacts, go to your device settings.";
|
||||
"contacts_user_directory_section" = "USER DIRECTORY";
|
||||
"contacts_user_directory_offline_section" = "USER DIRECTORY (offline)";
|
||||
"find_your_contacts_title" = "Start by listing your contacts";
|
||||
"find_your_contacts_message" = "Let %@ show your contacts so you can quickly start chatting with those you know best.";
|
||||
"find_your_contacts_button_title" = "Find your contacts";
|
||||
"find_your_contacts_footer" = "This can be disabled anytime from settings.";
|
||||
"find_your_contacts_identity_service_error" = "Unable to connect to the identity server.";
|
||||
|
||||
// Chat participants
|
||||
"room_participants_title" = "Participants";
|
||||
@@ -353,6 +360,7 @@ Tap the + to start adding people.";
|
||||
"room_event_action_redact" = "Remove";
|
||||
"room_event_action_more" = "More";
|
||||
"room_event_action_share" = "Share";
|
||||
"room_event_action_forward" = "Forward";
|
||||
"room_event_action_permalink" = "Permalink";
|
||||
"room_event_action_view_source" = "View Source";
|
||||
"room_event_action_view_decrypted_source" = "View Decrypted Source";
|
||||
@@ -449,7 +457,6 @@ Tap the + to start adding people.";
|
||||
"settings_report_bug" = "Report bug";
|
||||
"settings_clear_cache" = "Clear cache";
|
||||
"settings_config_home_server" = "Homeserver is %@";
|
||||
"settings_config_identity_server" = "Identity server is %@";
|
||||
"settings_config_user_id" = "Logged in as %@";
|
||||
|
||||
"settings_user_settings" = "USER SETTINGS";
|
||||
@@ -462,9 +469,10 @@ Tap the + to start adding people.";
|
||||
"settings_integrations" = "INTEGRATIONS";
|
||||
"settings_user_interface" = "USER INTERFACE";
|
||||
"settings_ignored_users" = "IGNORED USERS";
|
||||
"settings_contacts" = "LOCAL CONTACTS";
|
||||
"settings_contacts" = "DEVICE CONTACTS";
|
||||
"settings_phone_contacts" = "PHONE CONTACTS";
|
||||
"settings_advanced" = "ADVANCED";
|
||||
"settings_other" = "OTHER";
|
||||
"settings_about" = "ABOUT";
|
||||
"settings_labs" = "LABS";
|
||||
"settings_flair" = "Show flair where allowed";
|
||||
"settings_devices" = "SESSIONS";
|
||||
@@ -550,8 +558,9 @@ Tap the + to start adding people.";
|
||||
|
||||
"settings_unignore_user" = "Show all messages from %@?";
|
||||
|
||||
"settings_contacts_discover_matrix_users" = "Use emails and phone numbers to discover users";
|
||||
"settings_contacts_enable_sync" = "Find your contacts";
|
||||
"settings_contacts_phonebook_country" = "Phonebook country";
|
||||
"settings_contacts_enable_sync_description" = "This will use your identity server to connect you with your contacts, and help them find you.";
|
||||
|
||||
"settings_labs_e2e_encryption" = "End-to-End Encryption";
|
||||
"settings_labs_e2e_encryption_prompt_message" = "To finish setting up encryption you must log in again.";
|
||||
@@ -619,6 +628,7 @@ Tap the + to start adding people.";
|
||||
|
||||
"settings_discovery_no_identity_server" = "You are not currently using an identity server. To be discoverable by existing contacts you known, add one.";
|
||||
"settings_discovery_terms_not_signed" = "Agree to the identity server (%@) Terms of Service to allow yourself to be discoverable by email address or phone number.";
|
||||
"settings_discovery_accept_terms" = "Accept Identity Server Terms";
|
||||
"settings_discovery_three_pids_management_information_part1" = "Manage which email addresses or phone numbers other users can use to discover you and use to invite you to rooms. Add or remove email addresses or phone numbers from this list in ";
|
||||
"settings_discovery_three_pids_management_information_part2" = "User Settings";
|
||||
"settings_discovery_three_pids_management_information_part3" = ".";
|
||||
@@ -1020,18 +1030,21 @@ Tap the + to start adding people.";
|
||||
"gdpr_consent_not_given_alert_review_now_action" = "Review now";
|
||||
|
||||
// Service terms
|
||||
"service_terms_modal_title" = "Terms Of Service";
|
||||
"service_terms_modal_message" = "To continue you need to accept the terms of this service (%@).";
|
||||
"service_terms_modal_title_message" = "To continue, accept the below terms and conditions";
|
||||
"service_terms_modal_accept_button" = "Accept";
|
||||
"service_terms_modal_decline_button" = "Decline";
|
||||
"service_terms_modal_footer" = "This can be disabled anytime in settings.";
|
||||
|
||||
"service_terms_modal_description_for_identity_server_1" = "Find others by phone or email";
|
||||
"service_terms_modal_description_for_identity_server_2" = "Be found by phone or email";
|
||||
"service_terms_modal_description_for_integration_manager" = "Use Bots, bridges, widgets and sticker packs";
|
||||
"service_terms_modal_table_header_identity_server" = "IDENTITY SERVER TERMS";
|
||||
"service_terms_modal_table_header_integration_manager" = "INTEGRATION MANAGER TERMS";
|
||||
"service_terms_modal_description_identity_server" = "This will allow someone to find you if they have your phone number or email saved in their phone contacts.";
|
||||
"service_terms_modal_description_integration_manager" = "This will allow you to use bots, bridges, widgets and sticker packs.";
|
||||
|
||||
// Service terms - Variant for identity server when displayed out of a context
|
||||
"service_terms_modal_title_identity_server" = "Contact discovery";
|
||||
"service_terms_modal_message_identity_server" = "Accept the terms of the identity server (%@) to discover contacts.";
|
||||
// Alert explaining what an identity server / integration manager is.
|
||||
"service_terms_modal_information_title_identity_server" = "Identity Server";
|
||||
"service_terms_modal_information_title_integration_manager" = "Integration Manager";
|
||||
"service_terms_modal_information_description_identity_server" = "An identity server helps you find your contacts, by looking up their phone number or email address, to see if they already have an account.";
|
||||
"service_terms_modal_information_description_integration_manager" = "An integration manager lets you add features from third parties.";
|
||||
|
||||
"service_terms_modal_policy_checkbox_accessibility_hint" = "Check to accept %@";
|
||||
|
||||
@@ -1718,6 +1731,7 @@ Tap the + to start adding people.";
|
||||
"spaces_coming_soon_detail" = "This feature hasn’t been implemented here, but it’s on the way. For now, you can do that with Element on your computer.";
|
||||
"space_participants_action_remove" = "Remove from this space";
|
||||
"space_participants_action_ban" = "Ban from this space";
|
||||
"space_home_show_all_rooms" = "Show all rooms";
|
||||
|
||||
"space_private_join_rule" = "Private space";
|
||||
"space_public_join_rule" = "Public space";
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
"NSPhotoLibraryUsageDescription" = "Fotogaleriid kasutatakse fotode ja videote saatmiseks teistele kasutajatele.";
|
||||
"NSMicrophoneUsageDescription" = "Kõnede tegemiseks, videote ja häälsõnumite salvestamiseks vajab Element ligipääsu sinu seadme mikrofonile.";
|
||||
"NSCalendarsUsageDescription" = "Vaata päevakavasse lisatud koosolekuid vastvast rakendusest.";
|
||||
"NSContactsUsageDescription" = "Selleks, et leida Matrixi võrgu kasutajaid, võib Element saata sinu aadressiraamatus leiduvad e-posti aadressid ja telefoninumbrid sinu valitud Matrixi isikutuvastusserverile. Kui server seda toetab, siis andmed muudetakse enne saatmist räsideks - täpsema teabe leiad oma isikutuvastusserveri privaatsuspoliitikast.";
|
||||
"NSContactsUsageDescription" = "Element näitab sulle tuttavaid, kellega saad alustada vestlust.";
|
||||
"NSFaceIDUsageDescription" = "Ligipääsuks sinu rakendusele on kasutusel Face ID.";
|
||||
|
||||
@@ -691,10 +691,10 @@
|
||||
"user_verification_sessions_list_user_trust_level_unknown_title" = "Teadmata olek";
|
||||
"user_verification_sessions_list_information" = "Sõnumid selle kasutajaga selles jututoas on läbivalt krüptitud ning kolmandad osapooled ei saa neid lugeda.";
|
||||
"user_verification_sessions_list_table_title" = "Sessioonid";
|
||||
"user_verification_sessions_list_session_trusted" = "Usaldusväärsed";
|
||||
"user_verification_sessions_list_session_untrusted" = "Ei ole usaldusväärsed";
|
||||
"user_verification_session_details_trusted_title" = "Usaldusväärsed";
|
||||
"user_verification_session_details_untrusted_title" = "Ei ole usaldusväärsed";
|
||||
"user_verification_sessions_list_session_trusted" = "Usaldusväärne";
|
||||
"user_verification_sessions_list_session_untrusted" = "Ei ole usaldusväärne";
|
||||
"user_verification_session_details_trusted_title" = "Usaldusväärne";
|
||||
"user_verification_session_details_untrusted_title" = "Ei ole usaldusväärne";
|
||||
// Chat creation
|
||||
"room_creation_title" = "Uus vestlus";
|
||||
"room_creation_account" = "Kasutajakonto";
|
||||
@@ -710,7 +710,7 @@
|
||||
"room_creation_keep_private" = "Jäta privaatseks";
|
||||
"room_creation_make_private" = "Muuda privaatseks";
|
||||
"room_creation_wait_for_creation" = "Jututuba on just loomisel. Palun oota üks hetk.";
|
||||
"room_creation_invite_another_user" = "Otsi või kutsu uut kasutajat tema kasutajatunnuse, nime või e-posti aadressi alusel";
|
||||
"room_creation_invite_another_user" = "Kasutajatunnus, nimi või e-posti aadress";
|
||||
"room_creation_error_invite_user_by_email_without_identity_server" = "Ühtegi isikutuvastusserverit pole seadistatud ning sul ei ole võimalik lisada kasutajaid e-posti aadressi alusel.";
|
||||
"room_recents_low_priority_section" = "VÄHETÄHTIS";
|
||||
"room_recents_server_notice_section" = "SÜSTEEMSED TEATED";
|
||||
@@ -757,7 +757,7 @@
|
||||
"settings_integrations" = "LÕIMINGUD";
|
||||
"settings_user_interface" = "KASUTAJALIIDES";
|
||||
"settings_ignored_users" = "EIRATUD KASUTAJAD";
|
||||
"settings_contacts" = "KONTAKTID SIIN SEADMES";
|
||||
"settings_contacts" = "KONTAKTID SEADMES";
|
||||
"settings_advanced" = "KEERUKAMAD SEADISTUSED";
|
||||
"settings_other" = "MUUD SEADISTUSED";
|
||||
"settings_labs" = "KATSED";
|
||||
@@ -916,7 +916,7 @@
|
||||
"user_verification_start_information_part2" = " võrreldes selleks üheks korraks loodud koodi mõlemas seadmes.";
|
||||
"user_verification_start_waiting_partner" = "Ootan vastust kasutajalt %@…";
|
||||
"user_verification_start_additional_information" = "Turvalisuse mõttes on oluline, et teed seda nii, et kas olete üheskoos või kasutate suhtluskanalit, mida mõlemad usaldate.";
|
||||
"user_verification_sessions_list_user_trust_level_trusted_title" = "Usaldusväärsed";
|
||||
"user_verification_sessions_list_user_trust_level_trusted_title" = "Usaldusväärne";
|
||||
"user_verification_session_details_information_trusted_current_user" = "Kuna sina oled selle sessiooni verifitseerinud, siis see sessioon on krüptitud sõnumite saatmiseks usaldusväärne:";
|
||||
"user_verification_session_details_information_trusted_other_user_part1" = "See sessioon on krüptitud sõnumite saatmiseks usaldusväärne, sest ";
|
||||
"user_verification_session_details_information_trusted_other_user_part2" = " verifitseeris selle:";
|
||||
@@ -1443,3 +1443,27 @@
|
||||
"room_recents_suggested_rooms_section" = "SOOVITATUD JUTUTOAD";
|
||||
"done" = "Valmis";
|
||||
"open" = "Ava";
|
||||
"settings_contacts_enable_sync_description" = "Sellega võimaldad oma isikutuvastusserveril lubada sind leida.";
|
||||
|
||||
// Service terms
|
||||
"service_terms_modal_title_message" = "Jätkamiseks palun nõustu kasutustingimustega";
|
||||
"settings_phone_contacts" = "KONTAKTID NUTISEADMES";
|
||||
"settings_contacts_enable_sync" = "Otsi kontakte";
|
||||
"service_terms_modal_information_description_integration_manager" = "Lõiminguhalduri alusel saad lisada ja kasutada kolmandate osapoolte loodud lisavõimalusi.";
|
||||
"service_terms_modal_information_description_identity_server" = "Isikutuvastusserver võimaldab sul telefoninumbri või e-posti aadressi alusel leida Matrix'i kasutajaid.";
|
||||
"service_terms_modal_information_title_integration_manager" = "Lõiminguhaldur";
|
||||
|
||||
// Alert explaining what an identity server / integration manager is.
|
||||
"service_terms_modal_information_title_identity_server" = "Isikutuvastusserver";
|
||||
"service_terms_modal_description_integration_manager" = "Sellega tekib sul võimalus kasutada roboteid, sõnumisildu, vidinaid ja kleepsupakke.";
|
||||
"service_terms_modal_description_identity_server" = "Sellega annad teistele inimestele võimaluse sind leida, kui nende aadressiraamatus on sinu telefoninumber või e-posti aadress.";
|
||||
"service_terms_modal_table_header_integration_manager" = "LÕIMINGUHALDURI TINGIMUSED";
|
||||
"service_terms_modal_table_header_identity_server" = "ISIKUTUVASTUSSERVERI TINGIMUSED";
|
||||
"service_terms_modal_footer" = "Selle võimaluse saad alati seadistustest välja lülitada.";
|
||||
"find_your_contacts_identity_service_error" = "Ei õnnestu leida isikutuvastusserverit.";
|
||||
"find_your_contacts_footer" = "Selle võimaluse saad alati seadistustest välja lülitada.";
|
||||
"find_your_contacts_message" = "Las %@ näitab sulle kontakte ja nii saad tuttavatega kiiresti vestlema asuda.";
|
||||
"find_your_contacts_button_title" = "Otsi kontakte";
|
||||
"find_your_contacts_title" = "Alusta kontaktide looendist";
|
||||
"contacts_address_book_permission_denied_alert_message" = "Palun luba seadistustest aadressiraamatu lugemine.";
|
||||
"contacts_address_book_permission_denied_alert_title" = "Kontaktid pole kasutusel";
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"back" = "بازگشت";
|
||||
"store_full_description" = "المنت یک پیامرسان جدید و ابزاری برای همکاری افراد است که:\n\n۱. امکانات کنترلی لازم برای حفاظت از حریم خصوصی را در اختیار شما قرار میدهد.\n۲. امکان برقراری ارتباط با هر کسی را بر بستر شبکهی ماتریکس و حتی فراتر از آن، امکان برقراری ارتباط با برنامههای دیگر نظیر Slack را در اختیار شما قرار میدهد.\n۳. شما را در برابر تبلیغات، کندوکاو دادههایتان، در پشتی و همچنین یک زیستبوم بسته و محصور محافظت میکند.\n۴. شما را از طریق رمزنگاری سرتاسری و همچنین امضاء متقابل برای تائيد هویت دیگران، امن میکند.\n\nالمنت یک پیامرسان و ابزار ارتباطی کاملا متفاوت است، چرا که از معماری غیرمتمرکز بهره برده و متنباز است.\n\nالمنت امکان استقرار محلی - یا انتخاب هر میزبان دلخواهی - را به شما داده و از این طریق حریم خصوصی، مالکیت و کنترل دادهها و گفتگوهایتان برای شما به ارمغان میآورد. همچنین دسترسی به یک شبکهی باز را برای شما فراهم کرده، به طوری که مجبور نیستید فقط با کاربران المنت به گفتگو و صحبت بپردازید. در کنار همهی اینها، بسیار امن است.\n\nپشتوانهی قابلیتهای بالا، استفاده از ماتریکس است - یک استاندارد برای ارتباطات غیرمحدود و متمرکز.\n\nالمنت به شما اختیار میدهد سرور گفتگوهای خود را انتخاب کنید. در برنامه المنت، به طرق مختلف میتوانید سرور مورد نظر خود را انتخاب کنید:\n\n۱. ساختن یک حسابکاربری رایگان بر روی سرور عمومی matrix.org\n۲. استقرار محلی و راهاندازی سرور بر روی سختافزار خودتان و ایجاد حساب کاربری بر روی آن\n۳. ایجاد حساب کاربری بر روی یک سرور دلخواه از طریق عضویت در پلتفورم استقرار Element Matrix Services\n\nچرا المنت گزینهی جذابی است؟\n\nمالک حقیقی دادههای خود باشید: شما تصمیم بگیرید دادهها و پیامهایتان کجا ذخیره شوند. المنت مانند برخی اَبَرشرکت ها، در دادههای شما کاوش نکرده و آنها را در اختیار شخص ثالثی قرار نمیدهد.\n\nپیامرسانی و ارتباطات باز: شما میتوانید با هر کسی بر بستر ماتریکس ارتباط بگیرید، فارغ از اینکه از کدام کلاینت ماتریکسی استفاده میکنند؛ حتی فراتر، شما میتوانید افراد بر بستر سازوکارهای پیامرسانی دیگر نظیر Slack ،XMPP و یا IRC نیز ارتباط برقرار نمائید.\n\nفوقالعاده امن: رمزنگاری سرتاسری واقعی (فقط افرادی که در حال گفتگو هستند امکان رمزگشایی پیامها را دارند)، به همراه قابلیت امضاء متقابل برای تائید هویت دستگاه و هویت طرفهای گفتگو.\n\nپکیج ارتباطی کامل: پیامرسانی، تماسهای صوتی و تصویری، ارسال فایل، به اشتراکگذاری صفحه نمایش و یک طیف گستردهای از یکپارچهسازیها، باتها و ابزارکها. اتاقها و فضاهای کاری مختلف بسازید و برای به سرانجام رسیدن امور، در ارتباط باشید.\n\nحاضر در همه جا: هرجا و هر زمان در دسترس بوده و پیامهای خود را به صورت همگامسازیشده بر روی دستگاههای مختلف در اختیار داشته باشید.";
|
||||
// String for App Store
|
||||
"store_short_description" = "چت/تماس صوتی مبتنی بر اینترنت امن غیرمتمرکز";
|
||||
"store_short_description" = "پیامرسان/تماس صوتی تصویری اینترنتی امن مبتنی بر بستر غیرمتمرکز";
|
||||
"auth_missing_password" = "لطفا رمز عبور را وارد نمایید";
|
||||
"auth_invalid_phone" = "شماره تماس وارد شده بنظر اشتباه است";
|
||||
"auth_invalid_email" = "آدرس پست الکترونیکی وارد شده بنظر اشتباه است";
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
"auth_missing_phone" = "Numéro de téléphone manquant";
|
||||
"auth_missing_email_or_phone" = "Adresse e-mail ou numéro de téléphone manquant";
|
||||
"auth_password_dont_match" = "Les mots de passe ne correspondent pas";
|
||||
"auth_username_in_use" = "L’identifiant est déjà utilisé";
|
||||
"auth_username_in_use" = "";
|
||||
"auth_forgot_password" = "Mot de passe oublié ?";
|
||||
"auth_use_server_options" = "Utiliser un serveur personnalisé (avancé)";
|
||||
"auth_email_validation_message" = "Merci de vérifier vos e-mails pour continuer l’inscription";
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
"NSCameraUsageDescription" = "A kamera fényképek, videók készítéséhez és videóhívásokhoz lesz használva.";
|
||||
"NSPhotoLibraryUsageDescription" = "A fénykép galéria fényképek és videók küldéséhez lesz használva.";
|
||||
"NSMicrophoneUsageDescription" = "A hívás indításához és fogadásához, videó és hangüzenet felvételéhez az Elementnek hozzáférési engedélyre van szüksége a mikrofonhoz.";
|
||||
"NSContactsUsageDescription" = "Az olyan ismerősök felderítéséhez akik már használják a Matrixot, Elementet el tudja küldeni a címjegyzékben található e-mail címeket és telefonszámokat az általad választott Matrix azonosítási szervernek. Ahol lehetséges a személyes adatok hash-elve lesznek - kérlek ellenőrizd az azonosítási szervered adatvédelmi szabályait.";
|
||||
"NSContactsUsageDescription" = "Element megmutatja a névjegyzéket, hogy beszélgetésbe meghívhasd őket.";
|
||||
"NSCalendarsUsageDescription" = "Nézd meg a találkozóidat az alkalmazásban.";
|
||||
"NSFaceIDUsageDescription" = "Arc felismerés használata az alkalmazás eléréséhez.";
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
"auth_phone_in_use" = "Ez a telefonszám már használatban van";
|
||||
"auth_untrusted_id_server" = "Az azonosító szerver megbízhatatlan";
|
||||
"auth_password_dont_match" = "A jelszavak nem egyeznek meg";
|
||||
"auth_username_in_use" = "A felhasználói név használatban";
|
||||
"auth_username_in_use" = "A felhasználónév foglalt";
|
||||
"auth_forgot_password" = "Elfelejtetted a jelszót?";
|
||||
"auth_email_not_found" = "E-mail küldési hiba: Az e-mail cím nem található";
|
||||
"auth_use_server_options" = "Egyedi szerver beállítások használata (haladó)";
|
||||
@@ -105,7 +105,7 @@
|
||||
"room_creation_keep_private" = "Maradjon zárt";
|
||||
"room_creation_make_private" = "Legyen nyilvános";
|
||||
"room_creation_wait_for_creation" = "A szoba elkészítése folyamatban van. Kérlek várj.";
|
||||
"room_creation_invite_another_user" = "Keresés / meghívás felhasználói azonosítás, név vagy e-mail cím alapján";
|
||||
"room_creation_invite_another_user" = "Felhasználói azonosító, név vagy e-mail";
|
||||
// Room recents
|
||||
"room_recents_directory_section" = "SZOBA KÖNYVTÁR";
|
||||
"room_recents_favourites_section" = "KEDVENCEK";
|
||||
@@ -281,7 +281,7 @@
|
||||
"settings_calls_settings" = "HÍVÁSOK";
|
||||
"settings_user_interface" = "FELHASZNÁLÓI FELÜLET";
|
||||
"settings_ignored_users" = "FIGYELMEN KÍVÜL HAGYOTT FELHASZNÁLÓK";
|
||||
"settings_contacts" = "HELYI KAPCSOLATOK";
|
||||
"settings_contacts" = "ESZKÖZ NÉVJEGYZÉK";
|
||||
"settings_advanced" = "HALADÓ";
|
||||
"settings_other" = "MÁS";
|
||||
"settings_labs" = "LABOR";
|
||||
@@ -863,7 +863,7 @@
|
||||
"settings_calls_stun_server_fallback_description" = "Másodlagos hívást segítő szerver (%@) engedélyezése ha a matrix szervered nem ajánl fel másikat (az IP címed a hívás ideje alatt meg lesz osztva).";
|
||||
"settings_devices_description" = "Az munkamenet nyilvános neve látható azoknál az embereknél akikkel beszélgetsz";
|
||||
"settings_discovery_no_identity_server" = "Jelenleg nem használsz azonosítási szervert. Ahhoz, hogy az ismerősök megtalálhassanak adj hozzá egyet.";
|
||||
"settings_discovery_terms_not_signed" = "Egyetértés az Azonosítási Szerver (%@) Felhasználási Feltételeivel, hogy e-mail címmel vagy telefonszámmal megtalálható lehess.";
|
||||
"settings_discovery_terms_not_signed" = "Egyetértés az azonosítási szerver (%@) Felhasználási Feltételeivel, hogy e-mail címmel vagy telefonszámmal megtalálható lehess.";
|
||||
"settings_discovery_three_pids_management_information_part1" = "E-mail címek és telefonszámok beállítása amivel más felhasználók megtalálhatnak és meghívhatna szobákba. E-mail cím és telefonszám hozzáadása és törlése a listából itt: ";
|
||||
"settings_discovery_three_pids_management_information_part2" = "Felhasználói Beállítások";
|
||||
"settings_discovery_three_pids_management_information_part3" = ".";
|
||||
@@ -880,7 +880,7 @@
|
||||
"settings_identity_server_no_is" = "Azonosítási szerver nincs beállítva";
|
||||
"settings_identity_server_no_is_description" = "Jelenleg nem használsz azonosítási szervert. Ahhoz, hogy megtalálhass másokat és az ismerősök megtalálhassanak adj hozzá egyet alább.";
|
||||
// Identity server settings
|
||||
"identity_server_settings_title" = "Azonosítási Szerver";
|
||||
"identity_server_settings_title" = "Azonosítási szerver";
|
||||
"identity_server_settings_description" = "Jelenleg ezt használod: %@, hogy megtalálj másokat és megtalálhassanak ismerősök.";
|
||||
"identity_server_settings_no_is_description" = "Jelenleg nem használsz azonosítási szervert. Ahhoz, hogy megtalálj másokat és megtalálhassanak ismerősök adj meg egyet alább.";
|
||||
"identity_server_settings_place_holder" = "Adj meg egy azonosítási szervet";
|
||||
@@ -1506,3 +1506,27 @@
|
||||
"room_recents_suggested_rooms_section" = "JAVASOLT SZOBÁK";
|
||||
"done" = "Kész";
|
||||
"open" = "Megnyitás";
|
||||
"find_your_contacts_title" = "Kezdjük a kapcsolataid felsorolásával";
|
||||
"service_terms_modal_information_description_integration_manager" = "Az integrációs menedzser lehetővé teszi harmadik féltől származó lehetőségek használatát.";
|
||||
"service_terms_modal_information_description_identity_server" = "Az azonosítási szerver lehetővé teszi, hogy megtaláld a kapcsolataidat azzal, hogy megnézi regisztráltak-e már az ő telefonszámaival vagy e-mail címeivel.";
|
||||
"service_terms_modal_information_title_integration_manager" = "Integrációs Menedzser";
|
||||
|
||||
// Alert explaining what an identity server / integration manager is.
|
||||
"service_terms_modal_information_title_identity_server" = "Azonosító szerver";
|
||||
"service_terms_modal_description_integration_manager" = "Ez lehetővé teszi, hogy botokat, hidakat, kisalkalmazásokat vagy matricákat használj.";
|
||||
"service_terms_modal_description_identity_server" = "Ez lehetővé teszi másnak, akinek a telefonjába el van mentve a telefonszámod vagy e-mail címed, hogy megtaláljon.";
|
||||
"service_terms_modal_table_header_integration_manager" = "INTEGRÁCIÓS MENEDZSER FELTÉTELEK";
|
||||
"service_terms_modal_table_header_identity_server" = "AZONOSÍTÁSI SZERVER FELTÉTELEK";
|
||||
"settings_contacts_enable_sync" = "Kapcsolatok megkeresése";
|
||||
"find_your_contacts_button_title" = "Kapcsolatok megkeresése";
|
||||
"find_your_contacts_message" = "Engedd meg, hogy %@ megjelenítse a névjegyzéket, hogy gyorsan elkezdhess beszélgetni azokkal akiket a legjobban ismersz.";
|
||||
"service_terms_modal_footer" = "Bármikor letiltható a beállításokban.";
|
||||
|
||||
// Service terms
|
||||
"service_terms_modal_title_message" = "A folytatáshoz fogadd el a felhasználási feltételeket alább";
|
||||
"settings_contacts_enable_sync_description" = "Az azonosítási szerveredet fogja használni, hogy összekössön az ismerőseiddel és megtalálhassanak.";
|
||||
"settings_phone_contacts" = "TELEFON NÉVJEGYZÉK";
|
||||
"find_your_contacts_identity_service_error" = "Az azonosítási szerverhez nem sikerült csatlakozni.";
|
||||
"find_your_contacts_footer" = "Bármikor letiltható a beállításokban.";
|
||||
"contacts_address_book_permission_denied_alert_message" = "A névjegyzék engedélyezéséhez lépj be az eszköz beállításokba.";
|
||||
"contacts_address_book_permission_denied_alert_title" = "Névjegyzék letiltva";
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
|
||||
"NSContactsUsageDescription" = "Element akan menampilkan kontak Anda supaya Anda bisa mengundang mereka ke obrolan.";
|
||||
// Permissions usage explanations
|
||||
"NSCameraUsageDescription" = "Kamera digunakan untuk mengambil foto dan video, dan melakukan panggilan video.";
|
||||
"NSFaceIDUsageDescription" = "Face ID digunakan untuk mengakses aplikasi Anda.";
|
||||
"NSCalendarsUsageDescription" = "Lihat pertemuan yang sudah dijadwalkan di aplikasi.";
|
||||
"NSMicrophoneUsageDescription" = "Element membutuhkan akses ke mikrofon Anda untuk melakukan dan menerima panggilan, mengambil video, dan merekam pesan suara.";
|
||||
"NSPhotoLibraryUsageDescription" = "Galeri digunakan untuk mengirim foto dan video.";
|
||||
@@ -0,0 +1,167 @@
|
||||
|
||||
|
||||
|
||||
/** Key verification **/
|
||||
|
||||
"KEY_VERIFICATION_REQUEST_FROM_USER" = "%@ ingin memverifikasi";
|
||||
|
||||
/* Group call from user, CallKit caller name */
|
||||
"GROUP_CALL_FROM_USER" = "%@ (Panggilan grup)";
|
||||
|
||||
/* A user added a Jitsi call to a room */
|
||||
"GROUP_CALL_STARTED" = "Panggilan grup dimulai";
|
||||
|
||||
/* Incoming named video conference invite from a specific person */
|
||||
"VIDEO_CONF_NAMED_FROM_USER" = "Panggilan video grup dari %@: '%@'";
|
||||
|
||||
/* Incoming named voice conference invite from a specific person */
|
||||
"VOICE_CONF_NAMED_FROM_USER" = "Panggilan grup dari %@: '%@'";
|
||||
|
||||
/* Incoming unnamed video conference invite from a specific person */
|
||||
"VIDEO_CONF_FROM_USER" = "Panggilan video grup dari %@";
|
||||
|
||||
/* Incoming unnamed voice conference invite from a specific person */
|
||||
"VOICE_CONF_FROM_USER" = "Panggilan grup dari %@";
|
||||
|
||||
/* Incoming one-to-one video call */
|
||||
"VIDEO_CALL_FROM_USER" = "Panggilan video dari %@";
|
||||
|
||||
/** Calls **/
|
||||
|
||||
/* Incoming one-to-one voice call */
|
||||
"VOICE_CALL_FROM_USER" = "Panggilan dari %@";
|
||||
|
||||
/* A user's membership has updated in an unknown way */
|
||||
"USER_MEMBERSHIP_UPDATED" = "%@ memperbarui profilnya";
|
||||
|
||||
/* A user has change their avatar */
|
||||
"USER_UPDATED_AVATAR" = "%@ mengubah avatarnya";
|
||||
|
||||
/* A user has change their name to a new name which we don't know */
|
||||
"GENERIC_USER_UPDATED_DISPLAYNAME" = "%@ mengubah namanya";
|
||||
|
||||
/** Membership Updates **/
|
||||
|
||||
/* A user has change their name to a new name */
|
||||
"USER_UPDATED_DISPLAYNAME" = "%@ mengubah namanya ke %@";
|
||||
|
||||
/* A user has invited you to a named room */
|
||||
"USER_INVITE_TO_NAMED_ROOM" = "%@ mengundang Anda ke %@";
|
||||
|
||||
/* A user has invited you to an (unamed) group chat */
|
||||
"USER_INVITE_TO_CHAT_GROUP_CHAT" = "%@ mengundang Anda ke obrolan grup";
|
||||
|
||||
/** Invites **/
|
||||
|
||||
/* A user has invited you to a chat */
|
||||
"USER_INVITE_TO_CHAT" = "%@ mengundang Anda untuk mengobrol";
|
||||
|
||||
/* A user has reacted to a message, but the reaction content is unknown */
|
||||
"GENERIC_REACTION_FROM_USER" = "%@ mengirim sebuah reaksi";
|
||||
|
||||
/** Reactions **/
|
||||
|
||||
/* A user has reacted to a message, including the reaction e.g. "Alice reacted 👍". */
|
||||
"REACTION_FROM_USER" = "%@ mereaksi %@";
|
||||
|
||||
/* Look, stuff's happened, alright? Just open the app. */
|
||||
"MSGS_IN_TWO_PLUS_ROOMS" = "%@ pesan baru di %@, %@ dan %@ lainnya";
|
||||
|
||||
/* Multiple messages in two rooms */
|
||||
"MSGS_IN_TWO_ROOMS" = "%@ pesan baru di %@ dan %@";
|
||||
|
||||
/* Multiple unread messages from two plus people (ie. for 4+ people: 'others' replaces the third person) */
|
||||
"MSGS_FROM_TWO_PLUS_USERS" = "%@ pesan baru dari %@, %@ dan %@ lainnya";
|
||||
|
||||
/* Multiple unread messages from three people */
|
||||
"MSGS_FROM_THREE_USERS" = "%@ pesan baru dari %@, %@ dan %@";
|
||||
|
||||
/* Multiple unread messages from two people */
|
||||
"MSGS_FROM_TWO_USERS" = "%@ pesan baru dari %@ dan %@";
|
||||
|
||||
/* Multiple unread messages from a specific person, not referencing a room */
|
||||
"MSGS_FROM_USER" = "%@ pesan baru di %@";
|
||||
|
||||
/** Coalesced messages **/
|
||||
|
||||
/* Multiple unread messages in a room */
|
||||
"UNREAD_IN_ROOM" = "%@ pesan baru di %@";
|
||||
|
||||
/* New message with hidden content due to PIN enabled */
|
||||
"MESSAGE_PROTECTED" = "Pesan Baru";
|
||||
|
||||
/* New message indicator on a room */
|
||||
"MESSAGE_IN_X" = "Pesan di %@";
|
||||
|
||||
/* New message indicator from a DM */
|
||||
"MESSAGE_FROM_X" = "Pesan dari %@";
|
||||
|
||||
/** Notification messages **/
|
||||
|
||||
/* New message indicator on unknown room */
|
||||
"MESSAGE" = "Pesan";
|
||||
|
||||
/* Sticker from a specific person, not referencing a room. */
|
||||
"STICKER_FROM_USER" = "%@ mengirim sebuah stiker";
|
||||
|
||||
/** Single, end-to-end encrypted messages (ie. we don't know what they say) */
|
||||
|
||||
/* New message from a specific person, not referencing a room */
|
||||
"MSG_FROM_USER" = "%@ mengirim sebuah pesan";
|
||||
|
||||
/* New image message from a specific person in a named room. */
|
||||
"IMAGE_FROM_USER_IN_ROOM" = "%@ mengirim gambar %@ di %@";
|
||||
|
||||
/** Media Messages **/
|
||||
|
||||
/* New image message from a specific person, not referencing a room. */
|
||||
"PICTURE_FROM_USER" = "%@ mengirim sebuah gambar";
|
||||
|
||||
/* New video message from a specific person, not referencing a room. */
|
||||
"VIDEO_FROM_USER" = "%@ mengirim sebuah video";
|
||||
|
||||
/* New audio message from a specific person, not referencing a room. */
|
||||
"AUDIO_FROM_USER" = "%@ mengirim sebuah file audio %@";
|
||||
|
||||
/* New voice message from a specific person, not referencing a room. */
|
||||
"VOICE_MESSAGE_FROM_USER" = "%@ mengirim sebuah pesan suara";
|
||||
|
||||
/* New file message from a specific person, not referencing a room. */
|
||||
"FILE_FROM_USER" = "%@ mengirim sebuah file %@";
|
||||
|
||||
/* A single unread message in a room */
|
||||
"SINGLE_UNREAD_IN_ROOM" = "Anda menerima sebuah pesan di %@";
|
||||
|
||||
/* A single unread message */
|
||||
"SINGLE_UNREAD" = "Anda menerima sebuah pesan";
|
||||
|
||||
/* New action message from a specific person in a named room. */
|
||||
"ACTION_FROM_USER_IN_ROOM" = "%@: * %@ %@";
|
||||
|
||||
/* New message from a specific person in a named room. Content included. */
|
||||
"MSG_FROM_USER_IN_ROOM_WITH_CONTENT" = "%@ di %@: %@";
|
||||
|
||||
/* New action message from a specific person, not referencing a room. */
|
||||
"ACTION_FROM_USER" = "* %@ %@";
|
||||
|
||||
/** Single, unencrypted messages (where we can include the content */
|
||||
|
||||
/* New message from a specific person, not referencing a room. Content included. */
|
||||
"MSG_FROM_USER_WITH_CONTENT" = "%@: %@";
|
||||
|
||||
/* New message from a specific person in a named room */
|
||||
"MSG_FROM_USER_IN_ROOM" = "%@ mengirim di %@";
|
||||
|
||||
/* New message reply from a specific person in a named room. */
|
||||
"REPLY_FROM_USER_IN_ROOM_TITLE" = "%@ membalas di %@";
|
||||
|
||||
/* New message reply from a specific person, not referencing a room. */
|
||||
"REPLY_FROM_USER_TITLE" = "%@ membalas";
|
||||
|
||||
/** Titles **/
|
||||
|
||||
/* Message title for a specific person in a named room */
|
||||
"MSG_FROM_USER_IN_ROOM_TITLE" = "%@ di %@";
|
||||
/** General **/
|
||||
|
||||
"NOTIFICATION" = "Notifikasi";
|
||||
@@ -35,7 +35,7 @@
|
||||
"close" = "Tutup";
|
||||
"sending" = "Mengirim";
|
||||
"send_to" = "Kirim ke %@";
|
||||
"rename" = "Ubah nama";
|
||||
"rename" = "Ubah Nama";
|
||||
"later" = "Nanti";
|
||||
"active_call_details" = "Panggilan Aktif (%@)";
|
||||
"active_call" = "Panggilan Aktif";
|
||||
@@ -47,21 +47,21 @@
|
||||
"decline" = "Tolak";
|
||||
"join" = "Bergabung";
|
||||
"save" = "Simpan";
|
||||
"cancel" = "Batal";
|
||||
"cancel" = "Batalkan";
|
||||
"off" = "Nonaktif";
|
||||
"on" = "Aktif";
|
||||
"retry" = "Coba lagi";
|
||||
"retry" = "Coba Lagi";
|
||||
"invite" = "Undang";
|
||||
"remove" = "Hapus";
|
||||
"leave" = "Tinggalkan";
|
||||
"start" = "Mulai";
|
||||
"create" = "Buat";
|
||||
"continue" = "Lanjut";
|
||||
"continue" = "Lanjutkan";
|
||||
"back" = "Kembali";
|
||||
"next" = "Selanjutnya";
|
||||
|
||||
// Actions
|
||||
"view" = "Lihat";
|
||||
"view" = "Tampilkan";
|
||||
"warning" = "Peringatan";
|
||||
"title_groups" = "Komunitas-komunitas";
|
||||
"title_rooms" = "Ruangan-ruangan";
|
||||
@@ -75,7 +75,7 @@
|
||||
"auth_email_not_found" = "Gagal mengirim surel: Alamat email ini tidak ditemukan";
|
||||
"auth_forgot_password_error_no_configured_identity_server" = "Tidak ada server identitas yang dikonfigurasikan: tambahkan satu untuk mengatur ulang kata sandi Anda.";
|
||||
"auth_forgot_password" = "Lupa kata sandi?";
|
||||
"auth_username_in_use" = "Nama pengguna sudah dipakai";
|
||||
"auth_username_in_use" = "Nama pengguna telah dipakai";
|
||||
"auth_password_dont_match" = "Kata sandi tidak cocok";
|
||||
"auth_untrusted_id_server" = "Server identitas tidak dipercaya";
|
||||
"auth_phone_is_required" = "Tidak ada server identitas yang dikonfigurasi sehingga Anda tidak dapat menambahkan nomor telepon untuk mengatur ulang kata sandi Anda di masa depan.";
|
||||
@@ -102,6 +102,510 @@
|
||||
"joined" = "Bergabung";
|
||||
"collapse" = "tutup";
|
||||
"store_promotional_text" = "Aplikasi perpesanan dan kolaborasi yang menjaga privasi, pada jaringan terbuka. Terdesentralisasi untuk Anda kendali. Tidak ada penambangan data, tidak ada backdoor dan tidak ada akses pihak ketiga.";
|
||||
"store_full_description" = "Element adalah aplikasi messenger dan kolaborasi tipe baru yang:\n\n1. Menempatkan Anda dalam kendali untuk mempertahankan privasi Anda\n2. Memungkinkan Anda berkomunikasi dengan siapa pun di jaringan Matrix, dan bahkan di luar dengan mengintegrasikan dengan aplikasi seperti Slack\n3. Melindungi Anda dari iklan, menambangan data, backdoor, dan taman berdinding\n4. Mengamankan Anda melalui enkripsi ujung-ke-ujung, dengan penandatanganan-silang untuk memverifikasi orang lain\n\nElement benar-benar berbeda dari aplikasi perpesanan dan kolaborasi lain karena terdesentralisasi dan sumber terbuka.\n\nElement memungkinkan Anda host sendiri - atau memilih host - sehingga Anda memiliki privasi, kepemilikan, dan kontrol data dan percakapan Anda. Ini memberi Anda akses ke jaringan terbuka; jadi Anda tidak hanya terjebak berbicara dengan pengguna Element. Itu sangat aman.\n\nElement dapat melakukan semua ini karena beroperasi pada Matrix - standar untuk komunikasi terdesentralisasi terbuka.\n\nElement menempatkan Anda dalam kendali dengan membiarkan Anda memilih siapa yang meng-host percakapan Anda. Dari aplikasi Element, Anda dapat memilih untuk meng-host dengan cara yang berbeda:\n\n1. Dapatkan akun gratis pada server publik matrix.org\n2. Host sendiri akun Anda dengan menjalankan server pada perangkat keras Anda sendiri\n3. Mendaftar untuk akun di server khusus dengan hanya berlangganan platform hosting Element Matrix Services\n\nMengapa memilih Element?\n\nMILIKI DATA ANDA: Anda memutuskan di mana harus menyimpan data dan pesan Anda. Anda memilikinya dan mengendalikannya, bukan perusahaan besar yang menambang data Anda atau memberikan akses ke pihak ketiga.\n\nPESAN DAN KOLABORASI TERBUKA: Anda dapat mengobrol dengan orang lain di jaringan Matrix, jika mereka menggunakan Element atau aplikasi Matrix lain, dan bahkan jika mereka menggunakan sistem perpesanan seperti Slack, IRC atau XMPP.\n\nSUPER-AMAN: Enkripsi ujung-ke-ujung (hanya mereka yang dalam percakapan dapat mendekripsi pesan), dan penandatanganan-silang untuk memverifikasi perangkat peserta percakapan.\n\nKOMUNIKASI LENGKAP: Pesan, panggilan suara dan video, berbagi file, berbagi layar dan banyak integrasi, bot dan widget. Buat ruangan, komunitas, tetap terhubung dan selesaikan hal-hal.\n\nDI MANA PUN ANDA BERADA: Tetap berkomunikasi di mana pun Anda berada dengan riwayat pesan yang sepenuhnya disinkronkan di semua perangkat Anda dan di web di https://element.io/app.";
|
||||
"store_full_description" = "Element adalah aplikasi messenger dan kolaborasi tipe baru yang:\n\n1. Menempatkan Anda dalam kendali untuk mempertahankan privasi Anda\n2. Memungkinkan Anda berkomunikasi dengan siapa pun di jaringan Matrix, dan bahkan di luar dengan mengintegrasikan dengan aplikasi seperti Slack\n3. Melindungi Anda dari iklan, menambangan data, backdoor, dan taman berdinding\n4. Mengamankan Anda melalui enkripsi ujung-ke-ujung, dengan penandatanganan-silang untuk memverifikasi orang lain\n\nElement benar-benar berbeda dari aplikasi perpesanan dan kolaborasi lain karena terdesentralisasi dan sumber terbuka.\n\nElement memungkinkan Anda host sendiri - atau memilih host - sehingga Anda memiliki privasi, kepemilikan, dan kontrol data dan percakapan Anda. Ini memberi Anda akses ke jaringan terbuka; jadi Anda tidak hanya terjebak berbicara dengan pengguna Element. Itu sangat aman.\n\nElement dapat melakukan semua ini karena beroperasi pada Matrix - standar untuk komunikasi terdesentralisasi terbuka.\n\nElement menempatkan Anda dalam kendali dengan membiarkan Anda memilih siapa yang meng-host percakapan Anda. Dari aplikasi Element, Anda dapat memilih untuk meng-host dengan cara yang berbeda:\n\n1. Dapatkan akun gratis pada server publik matrix.org\n2. Host sendiri akun Anda dengan menjalankan server pada perangkat keras Anda sendiri\n3. Mendaftar untuk akun di server khusus dengan hanya berlangganan platform hosting Element Matrix Services\n\nMengapa memilih Element?\n\nMILIKI DATA ANDA: Anda memutuskan di mana harus menyimpan data dan pesan Anda. Anda memilikinya dan mengendalikannya, bukan perusahaan besar yang menambang data Anda atau memberikan akses ke pihak ketiga.\n\nPESAN DAN KOLABORASI TERBUKA: Anda dapat mengobrol dengan orang lain di jaringan Matrix, jika mereka menggunakan Element atau aplikasi Matrix lain, dan bahkan jika mereka menggunakan sistem perpesanan seperti Slack, IRC atau XMPP.\n\nSUPER-AMAN: Enkripsi ujung-ke-ujung (hanya mereka yang dalam percakapan dapat mendekripsi pesan), dan penandatanganan-silang untuk memverifikasi perangkat peserta percakapan.\n\nKOMUNIKASI LENGKAP: Pesan, panggilan suara dan video, berbagi file, berbagi layar dan banyak integrasi, bot dan widget. Buat ruangan, komunitas, tetap terhubung dan selesaikan hal-hal.\n\nDI MANA PUN ANDA BERADA: Tetap berkomunikasi di mana pun Anda berada dengan riwayat pesan yang sepenuhnya disinkronkan di semua perangkat Anda dan di web di https://app.element.io/.";
|
||||
// String for App Store
|
||||
"store_short_description" = "Obrolan/VoIP terdesentralisasi aman";
|
||||
|
||||
|
||||
// Room Details
|
||||
"room_details_title" = "Detail Ruangan";
|
||||
"security_settings_secure_backup_setup" = "Siapkan";
|
||||
"security_settings_secure_backup" = "CADANGAN AMAN";
|
||||
"security_settings_crypto_sessions" = "SESI SAYA";
|
||||
"settings_discovery_three_pid_details_title_email" = "Kelola email";
|
||||
"settings_discovery_three_pids_management_information_part2" = "Pengaturan Pengguna";
|
||||
"settings_key_backup_delete_confirmation_prompt_title" = "Hapus Cadangan";
|
||||
"settings_key_backup_button_delete" = "Hapus Cadangan";
|
||||
"settings_key_backup_info_algorithm" = "Algoritma: %@";
|
||||
"settings_crypto_export" = "Ekspor kunci";
|
||||
"settings_crypto_device_key" = "\nKunci sesi:\n";
|
||||
"settings_crypto_device_id" = "\nID Sesi: ";
|
||||
"settings_crypto_device_name" = "Nama sesi: ";
|
||||
"settings_add_3pid_invalid_password_message" = "Kredential tidak valid";
|
||||
"settings_confirm_password" = "konfirmasi kata sandi";
|
||||
"settings_new_password" = "kata sandi baru";
|
||||
"settings_old_password" = "kata sandi lama";
|
||||
"settings_third_party_notices" = "Pemberitahuan Pihak Ketiga";
|
||||
"settings_privacy_policy" = "Kebijakan Privasi";
|
||||
"settings_version" = "Versi %@";
|
||||
"settings_labs_e2e_encryption" = "Enkripsi Ujung-ke-Ujung";
|
||||
"settings_contacts_phonebook_country" = "Negara buku telepon";
|
||||
"settings_integrations_allow_button" = "Kelola integrasi";
|
||||
"settings_enable_callkit" = "Panggilan yang diintegrasi";
|
||||
"settings_night_mode" = "Mode Malam";
|
||||
"settings_change_password" = "Ubah kata sandi";
|
||||
"settings_first_name" = "Nama Depan";
|
||||
"settings_display_name" = "Nama Tampilan";
|
||||
"settings_profile_picture" = "Gambar Profil";
|
||||
"settings_sign_out" = "Keluar";
|
||||
"settings_deactivate_account" = "NONAKTIFKAN AKUN";
|
||||
"settings_key_backup" = "CADANGAN KUNCI";
|
||||
"settings_contacts" = "KONTAK PERANGKAT";
|
||||
"settings_ignored_users" = "PENGGUNA YANG DIABAIKAN";
|
||||
"settings_user_interface" = "ANTARMUKA PENGGUNA";
|
||||
"settings_identity_server_settings" = "SERVER IDENTITAS";
|
||||
"settings_user_settings" = "PENGATURAN PENGGUNA";
|
||||
"settings_clear_cache" = "Bersihkan cache";
|
||||
"room_event_action_report" = "Laporkan konten";
|
||||
"settings_report_bug" = "Laporkan bug";
|
||||
"room_preview_try_join_an_unknown_room_default" = "sebuah ruangan";
|
||||
"room_title_one_member" = "1 anggota";
|
||||
"room_title_members" = "%@ anggota";
|
||||
"room_title_invite_members" = "Undang anggota";
|
||||
|
||||
// Room Title
|
||||
"room_title_new_room" = "Ruangan baru";
|
||||
"unknown_devices_title" = "Sesi tidak diketahui";
|
||||
"unknown_devices_answer_anyway" = "Jawab Saja";
|
||||
"unknown_devices_call_anyway" = "Panggil Saja";
|
||||
"unknown_devices_send_anyway" = "Kirim Saja";
|
||||
"room_open_dialpad" = "Papan nomor";
|
||||
"room_place_voice_call" = "Panggilan suara";
|
||||
"room_accessibility_hangup" = "Jeda";
|
||||
"room_accessibility_video_call" = "Panggilan Video";
|
||||
"room_message_edits_history_title" = "Editan pesan";
|
||||
"room_action_send_file" = "Kirim file";
|
||||
"room_action_send_sticker" = "Kirim stiker";
|
||||
"room_event_action_reaction_history" = "Sejarah reaksi";
|
||||
"room_event_action_reaction_show_less" = "Tampilkan lebih sedikit";
|
||||
"room_event_action_reaction_show_all" = "Tampilkan semua";
|
||||
"room_event_action_view_encryption" = "Informasi enkripsi";
|
||||
"room_event_action_cancel_download" = "Batalkan Pengunduhan";
|
||||
"room_event_action_cancel_send" = "Batalkan Pengiriman";
|
||||
"room_event_action_view_source" = "Tampilkan Sumber";
|
||||
"room_prompt_cancel" = "batalkan semuanya";
|
||||
"room_prompt_resend" = "Kirim ulang semuanya";
|
||||
"room_participants_action_security_status_complete_security" = "Selesaikan keamanan";
|
||||
"room_participants_action_set_admin" = "Buat sebagai admin";
|
||||
"room_participants_action_set_moderator" = "Buat sebagai moderator";
|
||||
"room_participants_action_section_direct_chats" = "Pesan langsung";
|
||||
"room_participants_action_section_admin_tools" = "Alat admin";
|
||||
"room_participants_invite_malformed_id_title" = "Kesalahan dalam Mengundang";
|
||||
"room_participants_filter_room_members_for_dm" = "Filter anggota";
|
||||
"room_participants_leave_prompt_title" = "Tinggalkan ruangan";
|
||||
"room_participants_multi_participants" = "%d anggota";
|
||||
"room_participants_one_participant" = "1 anggota";
|
||||
"room_participants_add_participant" = "Tambahkan anggota";
|
||||
"contacts_user_directory_section" = "DIREKTORI PENGGUNA";
|
||||
|
||||
// Contacts
|
||||
"contacts_address_book_section" = "KONTAK LOKAL";
|
||||
"directory_cell_description" = "%tu ruangan";
|
||||
|
||||
// Directory
|
||||
"directory_cell_title" = "Jelajahi direktori";
|
||||
"search_no_result" = "Tidak ada hasil";
|
||||
"people_no_conversation" = "Tidak ada obrolan";
|
||||
"room_recents_join_room" = "Bergabung ke ruangan";
|
||||
"room_recents_create_empty_room" = "Buat ruangan";
|
||||
"room_recents_start_chat_with" = "Mulai obrolan";
|
||||
"room_recents_server_notice_section" = "PEMBERITAHUAN SISTEM";
|
||||
"room_recents_low_priority_section" = "PRIORITAS RENDAH";
|
||||
"room_recents_no_conversation" = "Tidak ada ruangan";
|
||||
|
||||
// Room recents
|
||||
"room_recents_directory_section" = "DIREKTORI RUANGAN";
|
||||
"room_creation_make_private" = "Buat privat";
|
||||
"room_creation_keep_private" = "Tetap buat privat";
|
||||
"room_creation_make_public" = "Buat publik";
|
||||
|
||||
// Chat creation
|
||||
"room_creation_title" = "Obrolan Baru";
|
||||
|
||||
// Social login
|
||||
|
||||
"social_login_list_title_continue" = "Lanjut dengan";
|
||||
"auth_softlogout_clear_data_sign_out" = "Keluar";
|
||||
"side_menu_action_feedback" = "Masukan";
|
||||
"side_menu_action_help" = "Bantuan";
|
||||
"side_menu_action_settings" = "Pengaturan";
|
||||
|
||||
// Mark: - User avatar view
|
||||
|
||||
"user_avatar_view_accessibility_label" = "avatar";
|
||||
|
||||
// Mark: Avatar
|
||||
|
||||
"space_avatar_view_accessibility_label" = "avatar";
|
||||
"space_tag" = "space";
|
||||
"spaces_suggested_room" = "Disarankan";
|
||||
"spaces_left_panel_title" = "Space";
|
||||
"spaces_home_space_title" = "Beranda";
|
||||
"pin_protection_settings_section_header" = "PIN";
|
||||
"room_notifs_settings_cancel_action" = "Batalkan";
|
||||
"room_notifs_settings_done_action" = "Selesai";
|
||||
"room_notifs_settings_none" = "Tidak Ada";
|
||||
"room_details_notifs" = "Notifikasi";
|
||||
"security_settings_secure_backup_reset" = "Atur Ulang";
|
||||
"settings_messages_containing_keywords" = "Keyword";
|
||||
"settings_messages_containing_at_room" = "@room";
|
||||
"settings_notifications" = "NOTIFIKASI";
|
||||
"settings_links" = "TAUTAN";
|
||||
"auth_softlogout_sign_in" = "Masuk";
|
||||
"space_beta_announce_badge" = "BETA";
|
||||
"room_intro_cell_information_dm_sentence1_part3" = ". ";
|
||||
"room_intro_cell_information_room_sentence1_part3" = ". ";
|
||||
|
||||
// Mark: - Room avatar view
|
||||
|
||||
"room_avatar_view_accessibility_label" = "avatar";
|
||||
"call_transfer_error_title" = "Kesalahan";
|
||||
"call_transfer_contacts_all" = "Semua";
|
||||
"call_transfer_contacts_recent" = "Baru Ini";
|
||||
"call_transfer_users" = "Pengguna";
|
||||
|
||||
// MARK: - Call Transfer
|
||||
"call_transfer_title" = "Pindahkan";
|
||||
"room_info_list_section_other" = "Lainnya";
|
||||
"create_room_placeholder_address" = "#ruangantest:matrix.org";
|
||||
"create_room_placeholder_topic" = "Topik";
|
||||
"create_room_placeholder_name" = "Nama";
|
||||
"biometrics_cant_unlocked_alert_message_retry" = "Coba lagi";
|
||||
"pin_protection_reset_alert_action_reset" = "Atur Ulang";
|
||||
"pin_protection_choose_pin_welcome_after_register" = "Selamat datang.";
|
||||
"secrets_reset_reset_action" = "Atur Ulang";
|
||||
"secrets_setup_recovery_passphrase_confirm_passphrase_title" = "Konfirmasi";
|
||||
"secrets_setup_recovery_passphrase_validate_action" = "Selesai";
|
||||
"security_settings_secure_backup_info_checking" = "Memeriksa…";
|
||||
"secrets_setup_recovery_key_done_action" = "Selesai";
|
||||
"secrets_setup_recovery_key_export_action" = "Simpan";
|
||||
"secrets_recovery_with_key_recovery_key_title" = "Masukkan";
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part3" = ".";
|
||||
"secrets_recovery_with_passphrase_passphrase_title" = "Masukkan";
|
||||
|
||||
// Session details
|
||||
|
||||
"user_verification_session_details_trusted_title" = "Dipercayai";
|
||||
"user_verification_sessions_list_session_trusted" = "Dipercayai";
|
||||
"user_verification_sessions_list_table_title" = "Sesi";
|
||||
"user_verification_sessions_list_user_trust_level_unknown_title" = "Tidak Diketahui";
|
||||
"user_verification_sessions_list_user_trust_level_warning_title" = "Peringatan";
|
||||
|
||||
// Sessions list
|
||||
|
||||
"user_verification_sessions_list_user_trust_level_trusted_title" = "Dipercayai";
|
||||
"key_verification_tile_conclusion_done_title" = "Terverifikasi";
|
||||
"key_verification_tile_request_incoming_approval_decline" = "Tolak";
|
||||
"key_verification_tile_request_incoming_approval_accept" = "Terima";
|
||||
"key_verification_tile_request_status_expired" = "Kedaluwarsa";
|
||||
|
||||
// MARK: - Key Verification
|
||||
|
||||
"key_verification_bootstrap_not_setup_title" = "Kesalahan";
|
||||
|
||||
// MARK: Reaction history
|
||||
"reaction_history_title" = "Reaksi";
|
||||
"emoji_picker_flags_category" = "Bendera";
|
||||
"emoji_picker_symbols_category" = "Simbol";
|
||||
"emoji_picker_objects_category" = "Benda";
|
||||
"emoji_picker_activity_category" = "Aktifitas";
|
||||
|
||||
// MARK: Emoji picker
|
||||
"emoji_picker_title" = "Reaksi";
|
||||
"device_verification_emoji_pin" = "Pin";
|
||||
"device_verification_emoji_folder" = "Map";
|
||||
"device_verification_emoji_headphones" = "Headphone";
|
||||
"device_verification_emoji_anchor" = "Jangkar";
|
||||
"device_verification_emoji_bell" = "Lonceng";
|
||||
"device_verification_emoji_trumpet" = "Terompet";
|
||||
"device_verification_emoji_guitar" = "Gitar";
|
||||
"device_verification_emoji_ball" = "Bola";
|
||||
"device_verification_emoji_trophy" = "Piala";
|
||||
"device_verification_emoji_rocket" = "Roket";
|
||||
"device_verification_emoji_aeroplane" = "Pesawat";
|
||||
"device_verification_emoji_bicycle" = "Sepeda";
|
||||
"device_verification_emoji_train" = "Kereta Api";
|
||||
"device_verification_emoji_flag" = "Bendera";
|
||||
"device_verification_emoji_telephone" = "Telepon";
|
||||
"device_verification_emoji_hammer" = "Palu";
|
||||
"device_verification_emoji_lock" = "Gembok";
|
||||
"device_verification_emoji_key" = "Kunci";
|
||||
"device_verification_emoji_scissors" = "Gunting";
|
||||
"device_verification_emoji_paperclip" = "Klip Kertas";
|
||||
"device_verification_emoji_pencil" = "Pensil";
|
||||
"device_verification_emoji_book" = "Buku";
|
||||
"device_verification_emoji_gift" = "Hadiah";
|
||||
"device_verification_emoji_clock" = "Jam";
|
||||
"device_verification_emoji_hourglass" = "Jam Pasir";
|
||||
"device_verification_emoji_umbrella" = "Payung";
|
||||
"device_verification_emoji_santa" = "Santa";
|
||||
"device_verification_emoji_spanner" = "Kunci (Bengkel)";
|
||||
"device_verification_emoji_glasses" = "Kacamata";
|
||||
"device_verification_emoji_hat" = "Topi";
|
||||
"device_verification_emoji_robot" = "Robot";
|
||||
"device_verification_emoji_smiley" = "Senyuman";
|
||||
"device_verification_emoji_heart" = "Hati";
|
||||
"device_verification_emoji_cake" = "Kue";
|
||||
"device_verification_emoji_pizza" = "Pizza";
|
||||
"device_verification_emoji_corn" = "Jagung";
|
||||
"device_verification_emoji_strawberry" = "Stroberi";
|
||||
"device_verification_emoji_apple" = "Apel";
|
||||
"device_verification_emoji_banana" = "Pisang";
|
||||
"device_verification_emoji_fire" = "Api";
|
||||
"device_verification_emoji_cloud" = "Awan";
|
||||
"device_verification_emoji_moon" = "Bulan";
|
||||
"device_verification_emoji_globe" = "Bola Dunia";
|
||||
"device_verification_emoji_mushroom" = "Jamur";
|
||||
"device_verification_emoji_cactus" = "Kaktus";
|
||||
"device_verification_emoji_tree" = "Pohon";
|
||||
"device_verification_emoji_flower" = "Bunga";
|
||||
"device_verification_emoji_butterfly" = "Kupu-Kupu";
|
||||
"device_verification_emoji_octopus" = "Gurita";
|
||||
"device_verification_emoji_fish" = "Ikan";
|
||||
"device_verification_emoji_turtle" = "Kura-Kura";
|
||||
"device_verification_emoji_penguin" = "Penguin";
|
||||
"device_verification_emoji_rooster" = "Ayam";
|
||||
"device_verification_emoji_panda" = "Panda";
|
||||
"device_verification_emoji_rabbit" = "Kelinci";
|
||||
"device_verification_emoji_elephant" = "Gajah";
|
||||
"device_verification_emoji_pig" = "Babi";
|
||||
"device_verification_emoji_unicorn" = "Unicorn";
|
||||
"device_verification_emoji_horse" = "Kuda";
|
||||
"device_verification_emoji_lion" = "Singa";
|
||||
"device_verification_emoji_cat" = "Kucing";
|
||||
|
||||
// MARK: Emoji
|
||||
"device_verification_emoji_dog" = "Anjing";
|
||||
|
||||
// MARK: Verified
|
||||
|
||||
// Device
|
||||
|
||||
"device_verification_verified_title" = "Terverifikasi!";
|
||||
"key_verification_manually_verify_device_validate_action" = "Verifikasi";
|
||||
"key_verification_self_verify_unverified_sessions_alert_validate_action" = "Tampilkan";
|
||||
"key_verification_self_verify_current_session_alert_validate_action" = "Verifikasi";
|
||||
"device_verification_self_verify_alert_validate_action" = "Verifikasi";
|
||||
"sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "Cadangan";
|
||||
"key_backup_recover_done_action" = "Selesai";
|
||||
"key_backup_recover_from_recovery_key_recovery_key_title" = "Masukkan";
|
||||
"key_backup_recover_from_passphrase_lost_passphrase_action_part3" = ".";
|
||||
"key_backup_recover_from_passphrase_passphrase_title" = "Masukkan";
|
||||
"key_backup_setup_success_from_passphrase_done_action" = "Selesai";
|
||||
|
||||
// Success
|
||||
|
||||
"key_backup_setup_success_title" = "Berhasil!";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_valid" = "Hebat!";
|
||||
"key_backup_setup_passphrase_passphrase_valid" = "Hebat!";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_title" = "Konfirmasi";
|
||||
"key_backup_setup_passphrase_passphrase_title" = "Masukkan";
|
||||
"key_backup_setup_intro_manual_export_info" = "(Lanjutan)";
|
||||
"key_backup_setup_skip_alert_skip_action" = "Lewat";
|
||||
"deactivate_account_forget_messages_information_part2_emphasize" = "Peringatan";
|
||||
"service_terms_modal_decline_button" = "Tolak";
|
||||
"service_terms_modal_accept_button" = "Terima";
|
||||
|
||||
// Widget Picker
|
||||
"widget_picker_title" = "Integrasi";
|
||||
"widget_menu_refresh" = "Muat Ulang";
|
||||
"bug_report_send" = "Kirim";
|
||||
"e2e_key_backup_wrong_version_button_settings" = "Pengaturan";
|
||||
"call_actions_unhold" = "Lanjutkan";
|
||||
"large_badge_value_k_format" = "%.1fK";
|
||||
"yesterday" = "Kemarin";
|
||||
"today" = "Sekarang";
|
||||
"you" = "Anda";
|
||||
|
||||
// Others
|
||||
"or" = "atau";
|
||||
"event_formatter_group_call_leave" = "Tinggalkan";
|
||||
"event_formatter_group_call_join" = "Bergabung";
|
||||
"event_formatter_call_retry" = "Coba Lagi";
|
||||
"event_formatter_call_answer" = "Jawab";
|
||||
"event_formatter_call_decline" = "Tolak";
|
||||
"event_formatter_message_edited_mention" = "(diedit)";
|
||||
"directory_server_placeholder" = "matrix.org";
|
||||
|
||||
// Directory
|
||||
"directory_title" = "Direktori";
|
||||
"media_picker_select" = "PIlih";
|
||||
"media_picker_library" = "Perpustakaan";
|
||||
"receipt_status_read" = "Baca: ";
|
||||
"group_participants_invited_section" = "DIUNDANG";
|
||||
"group_participants_invite_prompt_title" = "Konfirmasi";
|
||||
"group_participants_remove_prompt_title" = "Konfirmasi";
|
||||
"group_details_rooms" = "Ruangan";
|
||||
"group_details_people" = "Orang";
|
||||
"group_details_home" = "Beranda";
|
||||
"room_details_advanced_room_id_for_dm" = "ID:";
|
||||
"room_details_advanced_section" = "Lanjutan";
|
||||
"room_details_addresses_section" = "Alamat";
|
||||
"room_details_history_section_anyone" = "Siapa Saja";
|
||||
"room_details_favourite_tag" = "Favorit";
|
||||
"room_details_topic" = "Topik";
|
||||
"room_details_room_name_for_dm" = "Nama";
|
||||
"room_details_photo_for_dm" = "Foto";
|
||||
"room_details_settings" = "Pengaturan";
|
||||
"room_details_integrations" = "Integrasi";
|
||||
"room_details_files" = "Unggahan";
|
||||
"room_details_people" = "Anggota";
|
||||
"room_details_title_for_dm" = "Detail";
|
||||
"identity_server_settings_alert_disconnect_button" = "Putuskan";
|
||||
"identity_server_settings_disconnect" = "Putuskan";
|
||||
"identity_server_settings_change" = "Ubah";
|
||||
"identity_server_settings_add" = "Tambahkan";
|
||||
"security_settings_advanced" = "LANJUTAN";
|
||||
"security_settings_cryptography" = "KRIPTOGRAFI";
|
||||
"security_settings_crosssigning_reset" = "Atur Ulang";
|
||||
"security_settings_crosssigning" = "TANDA TANGAN SILANG";
|
||||
|
||||
// Security settings
|
||||
"security_settings_title" = "Keamanan";
|
||||
"settings_discovery_three_pid_details_revoke_action" = "Hapus";
|
||||
"settings_discovery_three_pid_details_share_action" = "Bagikan";
|
||||
"settings_discovery_three_pids_management_information_part3" = ".";
|
||||
"settings_copyright" = "Hak Cipta";
|
||||
"settings_ui_theme_black" = "Hitam";
|
||||
"settings_ui_theme_dark" = "Gelap";
|
||||
"settings_ui_theme_light" = "Terang";
|
||||
"settings_ui_theme_auto" = "Otomatis";
|
||||
"settings_ui_theme" = "Tema";
|
||||
"settings_ui_language" = "Bahasa";
|
||||
"settings_security" = "KEAMANAN";
|
||||
"settings_three_pids_management_information_part3" = ".";
|
||||
"settings_three_pids_management_information_part2" = "Penemuan";
|
||||
"settings_phone_number" = "Nomor telepon";
|
||||
"settings_email_address" = "Email";
|
||||
"settings_remove_prompt_title" = "Konfirmasi";
|
||||
"settings_surname" = "Nama belakang";
|
||||
"settings_cryptography" = "KRIPTOGRAFI";
|
||||
"settings_devices" = "SESI";
|
||||
"settings_labs" = "UJI COBA";
|
||||
"settings_other" = "LAINNYA";
|
||||
"settings_advanced" = "LANJUTAN";
|
||||
"settings_integrations" = "INTEGRASI";
|
||||
"settings_discovery_settings" = "PENEMUAN";
|
||||
"settings_calls_settings" = "PANGGILAN";
|
||||
|
||||
// Settings
|
||||
"settings_title" = "Pengaturan";
|
||||
"media_type_accessibility_sticker" = "Stiker";
|
||||
"media_type_accessibility_file" = "File";
|
||||
"media_type_accessibility_location" = "Lokasi";
|
||||
"media_type_accessibility_video" = "Video";
|
||||
"media_type_accessibility_audio" = "Audio";
|
||||
"media_type_accessibility_image" = "Gambar";
|
||||
"room_join_group_call" = "Gabung";
|
||||
"room_accessibility_call" = "Panggilan";
|
||||
"room_accessibility_upload" = "Unggah";
|
||||
"room_accessibility_integrations" = "Integrasi";
|
||||
"room_accessibility_search" = "Cari";
|
||||
"room_resource_limit_exceeded_message_contact_1" = " Mohon ";
|
||||
"room_action_reply" = "Balas";
|
||||
"room_event_action_edit" = "Edit";
|
||||
"room_event_action_reply" = "Balas";
|
||||
"room_event_action_delete" = "Hapus";
|
||||
"room_event_action_resend" = "Kirim Ulang";
|
||||
"room_event_action_save" = "Simpan";
|
||||
"room_event_action_permalink" = "Tautan";
|
||||
"room_event_action_share" = "Bagikan";
|
||||
"room_event_action_more" = "Lainnya";
|
||||
"room_event_action_redact" = "Hapus";
|
||||
"room_event_action_quote" = "Kutip";
|
||||
"room_event_action_copy" = "Salin";
|
||||
"room_ongoing_conference_call_close" = "Tutup";
|
||||
"room_message_editing" = "Mengedit";
|
||||
"room_member_power_level_short_custom" = "Kustom";
|
||||
"room_member_power_level_short_moderator" = "Moderator";
|
||||
"room_member_power_level_short_admin" = "Admin";
|
||||
"room_participants_action_security_status_warning" = "Peringatan";
|
||||
"room_participants_action_security_status_verify" = "Verifikasi";
|
||||
"room_participants_action_security_status_verified" = "Terverifikasi";
|
||||
"room_participants_action_mention" = "Sebutan";
|
||||
"room_participants_action_unban" = "Hilangkan cekalan";
|
||||
"room_participants_action_invite" = "Undangan";
|
||||
"room_participants_action_section_security" = "Keamanan";
|
||||
"room_participants_action_section_other" = "Opsi";
|
||||
"room_participants_action_section_devices" = "Sesi";
|
||||
"room_participants_ago" = "lalu";
|
||||
"room_participants_now" = "sekarang";
|
||||
"room_participants_idle" = "Idle";
|
||||
"room_participants_unknown" = "Tidak diketahui";
|
||||
"room_participants_offline" = "Offline";
|
||||
"room_participants_online" = "Online";
|
||||
"room_participants_invited_section" = "DIUNDANG";
|
||||
"room_participants_invite_prompt_title" = "Konfirmasi";
|
||||
"room_participants_remove_prompt_title" = "Konfirmasi";
|
||||
"room_participants_leave_prompt_title_for_dm" = "Tinggalkan";
|
||||
|
||||
// Chat participants
|
||||
"room_participants_title" = "Anggota";
|
||||
"search_in_progress" = "Mencari…";
|
||||
"search_default_placeholder" = "Cari";
|
||||
"search_files" = "File";
|
||||
"search_people" = "Orang";
|
||||
"search_messages" = "Pesan";
|
||||
|
||||
// Search
|
||||
"search_rooms" = "Ruangan";
|
||||
"group_section" = "KOMUNITAS";
|
||||
|
||||
// Groups tab
|
||||
"group_invite_section" = "UNDANGAN";
|
||||
"rooms_empty_view_title" = "Ruangan";
|
||||
"people_empty_view_title" = "Orang";
|
||||
"secrets_setup_recovery_key_loading" = "Memuat…";
|
||||
"key_verification_tile_request_status_waiting" = "Menunggu…";
|
||||
"device_verification_self_verify_start_waiting" = "Menunggu…";
|
||||
"event_formatter_call_ringing" = "Berdering…";
|
||||
"event_formatter_call_connecting" = "Menghubungkan…";
|
||||
"security_settings_crypto_sessions_loading" = "Memuat sesi…";
|
||||
"settings_key_backup_info_checking" = "Memeriksa…";
|
||||
"unknown_devices_verify" = "Verifikasi…";
|
||||
"room_participants_security_loading" = "Memuat…";
|
||||
"room_participants_action_security_status_loading" = "Memuat…";
|
||||
"directory_searching_title" = "Mencari direktori…";
|
||||
"room_details_advanced_room_id" = "ID Ruangan:";
|
||||
"room_details_banned_users_section" = "Pengguna yang dicekal";
|
||||
"room_details_flair_invalid_id_prompt_title" = "Format tidak valid";
|
||||
"room_details_history_section_prompt_title" = "Peringatan privasi";
|
||||
"room_details_direct_chat" = "Pesan Langsung";
|
||||
"room_details_mute_notifs" = "Bisukan notifikasi";
|
||||
"room_details_low_priority_tag" = "Prioritas rendah";
|
||||
"room_details_room_name" = "Nama Ruangan";
|
||||
"room_details_photo" = "Foto Ruangan";
|
||||
"room_details_search" = "Cari ruangan";
|
||||
"identity_server_settings_alert_disconnect_still_sharing_3pid_button" = "Putuskan saja";
|
||||
|
||||
// Identity server settings
|
||||
"identity_server_settings_title" = "Server identitas";
|
||||
"manage_session_not_trusted" = "Tidak dipercayai";
|
||||
"manage_session_name" = "Nama sesi";
|
||||
"manage_session_info" = "INFORMASI SESI";
|
||||
|
||||
// Manage session
|
||||
"manage_session_title" = "Kelola sesi";
|
||||
"security_settings_complete_security_alert_title" = "Keamanan lengkap";
|
||||
"security_settings_crosssigning_complete_security" = "Keamanan lengkap";
|
||||
"security_settings_crosssigning_bootstrap" = "Siapkan";
|
||||
"security_settings_backup" = "CADANGAN PESAN";
|
||||
"security_settings_secure_backup_delete" = "Hapus Cadangan";
|
||||
"people_conversation_section" = "OBROLAN";
|
||||
|
||||
// People tab
|
||||
"people_invites_section" = "UNDANGAN";
|
||||
"room_recents_invites_section" = "UNDANGAN";
|
||||
"room_recents_conversations_section" = "RUANGAN";
|
||||
"room_recents_people_section" = "ORANG";
|
||||
"room_recents_favourites_section" = "FAVORIT";
|
||||
"room_creation_privacy" = "Privasi";
|
||||
"room_creation_appearance_name" = "Nama";
|
||||
"room_creation_appearance" = "Tampilan";
|
||||
"room_creation_account" = "Akun";
|
||||
"social_login_list_title_sign_up" = "Atau";
|
||||
"social_login_list_title_sign_in" = "Atau";
|
||||
"auth_reset_password_error_is_required" = "Tidak ada server identitas yang diatur: tambahkan di pengaturan server untuk mengatur ulang kata sandi Anda.";
|
||||
"auth_reset_password_error_not_found" = "Alamat email Anda terlihat tidak diasosiasikan dengan sebuah ID Matrix di homeserver ini.";
|
||||
"auth_reset_password_error_unauthorized" = "Gagal untuk memverifikasi alamat email: pastikan Anda membuka tautan yang ada di email";
|
||||
"auth_reset_password_next_step_button" = "Saya telah memverifikasi alamat email saya";
|
||||
"auth_reset_password_email_validation_message" = "Sebuah email telah dikirim ke %@. Setelah Anda membuka tautan yang ada, klik di bawah.";
|
||||
"auth_reset_password_missing_password" = "Sebuah kata sandi baru harus dimasukkan.";
|
||||
"auth_reset_password_missing_email" = "Alamat email yang tertaut dengan akun Anda harus dimasukkan.";
|
||||
"auth_reset_password_message" = "Untuk mengatur ulang kata sandi Anda, masukkan alamat email yang tertaut ke akun Anda:";
|
||||
"auth_recaptcha_message" = "Homeserver ini ingin memastikan bahwa Anda bukan sebuah robot";
|
||||
"auth_msisdn_validation_error" = "Tidak dapat memverifikasi nomor telepon.";
|
||||
"auth_msisdn_validation_message" = "Kami telah mengirim sebuah SMS dengan kode aktivasi. Silakan masukkan kodenya di bawah.";
|
||||
"auth_msisdn_validation_title" = "Menunggu Verifikasi";
|
||||
"done" = "Selesai";
|
||||
"open" = "Buka";
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
"NSCameraUsageDescription" = "La fotocamera viene utilizzata per scattare fotografie, registrare video ed eseguire videochiamate.";
|
||||
"NSPhotoLibraryUsageDescription" = "La libreria fotografica viene utilizzata per inviare foto e video.";
|
||||
"NSMicrophoneUsageDescription" = "Element ha bisogno di accedere al microfono per effettuare e ricevere chiamate, registrare video e messaggi vocali.";
|
||||
"NSContactsUsageDescription" = "Per scoprire i contatti che già usano Matrix, Element può inviare gli indirizzi email e i numeri di telefono della tua rubrica al server identità che hai scelto. Se supportato, viene fatto un hash dei dati personali prima dell'invio - controlla la politica sulla privacy del tuo server di identità per maggiori informazioni.";
|
||||
"NSContactsUsageDescription" = "Element mostrerà i tuoi contatti così da poterli invitare in chat.";
|
||||
"NSCalendarsUsageDescription" = "Vedi le tue riunioni programmate nell'app.";
|
||||
"NSFaceIDUsageDescription" = "Face ID viene usato per accedere all'app.";
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
"room_creation_keep_private" = "Mantieni privata";
|
||||
"room_creation_make_private" = "Rendi privata";
|
||||
"room_creation_wait_for_creation" = "Una stanza è già in fase di creazione. Per favore attendi.";
|
||||
"room_creation_invite_another_user" = "Cerca / invita per ID utente, nome o email";
|
||||
"room_creation_invite_another_user" = "ID utente, nome o email";
|
||||
// Room recents
|
||||
"room_recents_directory_section" = "ELENCO STANZE";
|
||||
"room_recents_favourites_section" = "PREFERITI";
|
||||
@@ -295,7 +295,7 @@
|
||||
"settings_calls_settings" = "CHIAMATE";
|
||||
"settings_user_interface" = "INTERFACCIA UTENTE";
|
||||
"settings_ignored_users" = "UTENTI IGNORATI";
|
||||
"settings_contacts" = "CONTATTI LOCALI";
|
||||
"settings_contacts" = "CONTATTI DEL DISPOSITIVO";
|
||||
"settings_advanced" = "AVANZATE";
|
||||
"settings_other" = "ALTRO";
|
||||
"settings_labs" = "LABORATORIO";
|
||||
@@ -892,7 +892,7 @@
|
||||
"widget_menu_remove" = "Rimuovi per tutti";
|
||||
"settings_integrations" = "INTEGRAZIONI";
|
||||
"settings_integrations_allow_button" = "Gestisci le integrazioni";
|
||||
"settings_integrations_allow_description" = "Usa un Integration Manager (%@) per gestire bot, bridge, widget e pacchetti di sticker.\n\nGli Integration Manager possono ricevere dati di configurazione, modificare widget, mandare inviti alle stanze e modificare permessi a tuo nome.";
|
||||
"settings_integrations_allow_description" = "Usa un gestore di integrazioni (%@) per gestire bot, bridge, widget e pacchetti di sticker.\n\nI gestori di integrazioni possono ricevere dati di configurazione, modificare widget, mandare inviti alle stanze e modificare permessi a tuo nome.";
|
||||
"widget_integration_manager_disabled" = "Devi attivare il gestore di integrazioni nelle impostazioni";
|
||||
// Room widget permissions
|
||||
"room_widget_permission_title" = "Carica widget";
|
||||
@@ -1477,3 +1477,27 @@
|
||||
"room_recents_suggested_rooms_section" = "STANZE CONSIGLIATE";
|
||||
"done" = "Fatto";
|
||||
"open" = "Apri";
|
||||
"service_terms_modal_information_description_integration_manager" = "Un gestore di integrazioni ti permette di aggiungere funzioni da terze parti.";
|
||||
"service_terms_modal_information_description_identity_server" = "Un server d'identità ti aiuta a trovare i tuoi contatti, cercando il loro numero di telefono o l'indirizzo email, per vedere se hanno già un account.";
|
||||
"service_terms_modal_information_title_integration_manager" = "Gestore di integrazioni";
|
||||
|
||||
// Alert explaining what an identity server / integration manager is.
|
||||
"service_terms_modal_information_title_identity_server" = "Server d'identità";
|
||||
"service_terms_modal_description_integration_manager" = "Ciò ti permetterà di usare bot, bridge, widget e pacchetti di sticker.";
|
||||
"service_terms_modal_description_identity_server" = "Ciò aiuterà qualcuno a trovarti se ha il tuo numero di telefono o l'email salvati nei suoi contatti.";
|
||||
"service_terms_modal_table_header_integration_manager" = "TERMINI DEL GESTORE DI INTEGRAZIONI";
|
||||
"service_terms_modal_table_header_identity_server" = "TERMINI DEL SERVER D'IDENTITÀ";
|
||||
"service_terms_modal_footer" = "Può essere disattivato in qualsiasi momento nelle impostazioni.";
|
||||
|
||||
// Service terms
|
||||
"service_terms_modal_title_message" = "Per continuare, accetta i termini e condizioni sottostanti";
|
||||
"settings_contacts_enable_sync_description" = "Verrà usato il tuo server d'identità per connetterti ai tuoi contatti e per aiutarli a trovarti.";
|
||||
"settings_contacts_enable_sync" = "Trova i tuoi contatti";
|
||||
"settings_phone_contacts" = "CONTATTI DEL TELEFONO";
|
||||
"find_your_contacts_identity_service_error" = "Impossibile connettersi al server d'identità.";
|
||||
"find_your_contacts_footer" = "Può essere disattivato in qualsiasi momento dalle impostazioni.";
|
||||
"find_your_contacts_button_title" = "Trova i tuoi contatti";
|
||||
"find_your_contacts_message" = "Lascia che %@ mostri i tuoi contatti per poter iniziare subito a chattare con chi conosci già.";
|
||||
"find_your_contacts_title" = "Inizia elencando i tuoi contatti";
|
||||
"contacts_address_book_permission_denied_alert_message" = "Per attivare i contatti, vai nelle impostazioni del tuo dispositivo.";
|
||||
"contacts_address_book_permission_denied_alert_title" = "Contatti disattivati";
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
"NSCameraUsageDescription" = "A câmera é usada para tirar fotos e vídeos, fazer chamadas de vídeo.";
|
||||
"NSPhotoLibraryUsageDescription" = "A biblioteca de fotos é usada para enviar fotos e vídeos.";
|
||||
"NSMicrophoneUsageDescription" = "Element precisa acessar seu microfone para fazer e receber chamadas, tirar vídeos, e gravar mensagens de voz.";
|
||||
"NSContactsUsageDescription" = "Para descobrir contatos já usando Matrix, Element pode enviar endereços de email e números de telefone em seu livro de endereços para seu servidor de identidade Matrix escolhido. Onde suportado, dados pessoais são hashados antes do envio - por favor cheque a política de privacidade de seu servidor de identidade para mais detalhes.";
|
||||
"NSContactsUsageDescription" = "Element vai mostrar seus contatos para que você possa convidá-los a conversar.";
|
||||
"NSCalendarsUsageDescription" = "Ver suas reuniões agendadas no app.";
|
||||
"NSFaceIDUsageDescription" = "Face ID é usada para acessar seu app.";
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
/* Look, stuff's happened, alright? Just open the app. */
|
||||
"MSGS_IN_TWO_PLUS_ROOMS" = "%@ novas mensagens em %@, %@ e outras";
|
||||
/* A user has invited you to a chat */
|
||||
"USER_INVITE_TO_CHAT" = "%@ tem conviado você para fazer chat";
|
||||
"USER_INVITE_TO_CHAT" = "%@ tem conviado você para conversar";
|
||||
/* A user has invited you to an (unamed) group chat */
|
||||
"USER_INVITE_TO_CHAT_GROUP_CHAT" = "%@ tem convidado você para um chat de grupo";
|
||||
/* A user has invited you to a named room */
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
"room_creation_keep_private" = "Manter privado";
|
||||
"room_creation_make_private" = "Fazer privado";
|
||||
"room_creation_wait_for_creation" = "Uma sala já está sendo criada. Por favor espere.";
|
||||
"room_creation_invite_another_user" = "Buscar / convidar por ID de usuária(o), Nome ou email";
|
||||
"room_creation_invite_another_user" = "ID de usuária(o), nome ou email";
|
||||
"room_recents_favourites_section" = "FAVORITOS";
|
||||
"room_recents_people_section" = "PESSOAS";
|
||||
"room_recents_conversations_section" = "SALAS";
|
||||
@@ -288,7 +288,7 @@
|
||||
"settings_calls_settings" = "CHAMADAS";
|
||||
"settings_user_interface" = "INTERFACE DE USUÁRIA(O)";
|
||||
"settings_ignored_users" = "USUÁRIAS(OS) IGNORADAS(OS)";
|
||||
"settings_contacts" = "CONTATOS LOCAIS";
|
||||
"settings_contacts" = "CONTATOS DE DISPOSITIVO";
|
||||
"settings_advanced" = "AVANÇADAS";
|
||||
"settings_other" = "OUTRAS";
|
||||
"settings_labs" = "LABS";
|
||||
@@ -556,7 +556,7 @@
|
||||
"rerequest_keys_alert_message" = "Por favor lance %@ num outro dispositivo que possa decriptar a mensagem para que ele possa enviar as chaves para esta sessão.";
|
||||
// String for App Store
|
||||
"store_short_description" = "Chat/VoIP descentralizado e seguro";
|
||||
"store_full_description" = "Element is um novo tipo de mensageiro e app de colaboração que:\n\n1. Põe você em controle para preservar sua privacidade\n2. Permite você se comunicar com qualquer pessoa na rede Matrix, e até além ao integrar-se com apps como Slack\n3. Protege você de publicidade, datamining, backdoors e jardins murados\n4. Assegura você através de encriptação ponta-a-pontam com assinatura cruzada para verificar ouras(os)\n\nElement é completamente diferente de outros apps de mensageria e colaboração porque ele é descentralizado e open source.\n\nElement permite você auto-hospedar - ou escolher um host - para que você tenha privacidade, propriedade e controle de seus dados e conversas. Ele dá a você acesso a uma rede aberta; então você não está simplesmente preso falando com outras(os) usuárias(os) Element somente. E ele é muito seguro.\n\nElement é capaz de fazer tudo isso porque ele opera em Matrix - o padrão para comunicação aberta e descentralizada.\n\nElement põe você em controle ao permitir você escolher quem hospeda suas conversas. De seu app Element, você pode escolher hospedar de diferentes maneiras:\n\n1. Pegar uma conta grátis no servidor público matrix.org\n2. Auto-hospedar sua conta ao rodar um servidor em seu próprio hardware\n3. Registrar-se para uma conta num servidor personalizado ao simplesmente assinar a plataforma de hospedagem Element Matrix Services\n\nPorquê escolher Element?\n\nTENHA POSSE DE SEUS DADOS: Você decide onde manter seus dados e mensagens. Você os possui e controla, não alguma MEGACORP que mina seus dados ou dá acesso a terceiros.\n\nMENSAGERIA E COLABORAÇÃO ABERTOS: Você pode fazer chat com qualquer outra pessoa na rede Matrix, caso ela esteja usando Element ou um outro app Matrix, e mesmo se ela estiver usando um sistema de mensageria diferente, do tipo de Slack, IRC ou XMPP.\n\nSUPER-SEGURO: Encriptação ponta-a-ponta real (somente aquelas/es na conversa podem decriptar mensagens), e assinatura cruzada para verificar os dispositivos de participantes de conversa.\n\nCOMUNICAÇÃO COMPLETA: Mensageria, chamadas de voz e vídeo, compartilhamento de arquivo, compartilhamento de tela e um monte de integrações, bots e widgets. Construa salas, comunidades, fique em contato e tenha as coisas feitas.\n\nEM TODO LUGAR ONDE VOCÊ ESTEJA: Fique em contato onde quer que você esteja com histórico de mensagem sincronizado por todos os dispositivos e na web em https://element.io/app.";
|
||||
"store_full_description" = "Element is um novo tipo de mensageiro e app de colaboração que:\n\n1. Põe você em controle para preservar sua privacidade\n2. Permite você se comunicar com qualquer pessoa na rede Matrix, e até além ao integrar-se com apps como Slack\n3. Protege você de publicidade, datamining, backdoors e jardins murados\n4. Assegura você através de encriptação ponta-a-pontam com assinatura cruzada para verificar ouras(os)\n\nElement é completamente diferente de outros apps de mensageria e colaboração porque ele é descentralizado e open source.\n\nElement permite você auto-hospedar - ou escolher um host - para que você tenha privacidade, propriedade e controle de seus dados e conversas. Ele dá a você acesso a uma rede aberta; então você não está simplesmente preso falando com outras(os) usuárias(os) Element somente. E ele é muito seguro.\n\nElement é capaz de fazer tudo isso porque ele opera em Matrix - o padrão para comunicação aberta e descentralizada.\n\nElement põe você em controle ao permitir você escolher quem hospeda suas conversas. De seu app Element, você pode escolher hospedar de diferentes maneiras:\n\n1. Pegar uma conta grátis no servidor público matrix.org\n2. Auto-hospedar sua conta ao rodar um servidor em seu próprio hardware\n3. Registrar-se para uma conta num servidor personalizado ao simplesmente assinar a plataforma de hospedagem Element Matrix Services\n\nPorquê escolher Element?\n\nTENHA POSSE DE SEUS DADOS: Você decide onde manter seus dados e mensagens. Você os possui e controla, não alguma MEGACORP que mina seus dados ou dá acesso a terceiros.\n\nMENSAGERIA E COLABORAÇÃO ABERTOS: Você pode conversar com qualquer outra pessoa na rede Matrix, caso ela esteja usando Element ou um outro app Matrix, e mesmo se ela estiver usando um sistema de mensageria diferente, do tipo de Slack, IRC ou XMPP.\n\nSUPER-SEGURO: Encriptação ponta-a-ponta real (somente aquelas/es na conversa podem decriptar mensagens), e assinatura cruzada para verificar os dispositivos de participantes de conversa.\n\nCOMUNICAÇÃO COMPLETA: Mensageria, chamadas de voz e vídeo, compartilhamento de arquivo, compartilhamento de tela e um monte de integrações, bots e widgets. Construa salas, comunidades, fique em contato e tenha as coisas feitas.\n\nEM TODO LUGAR ONDE VOCÊ ESTEJA: Fique em contato onde quer que você esteja com histórico de mensagem sincronizado por todos os dispositivos e na web em https://element.io/app.";
|
||||
"auth_login_single_sign_on" = "Fazer Sign In";
|
||||
"auth_autodiscover_invalid_response" = "Resposta de descoberta de servidorcasa inválida";
|
||||
"room_message_unable_open_link_error_message" = "Incapaz de abrir o link.";
|
||||
@@ -720,7 +720,7 @@
|
||||
"settings_three_pids_management_information_part3" = ".";
|
||||
"settings_security" = "SEGURANÇA";
|
||||
"settings_integrations_allow_button" = "Gerenciar integrações";
|
||||
"settings_integrations_allow_description" = "Use um Gerenciador de Integrações (%@) para gerenciar bots, bridges, widgets e pacotes de stickers.\n\nGerenciadores de Integrações recebem dados de configuração, e podem modificar widgets, enviar convites de sala e definir níveis de poder em seu nome.";
|
||||
"settings_integrations_allow_description" = "Use um gerenciador de integrações (%@) para gerenciar bots, bridges, widgets e pacotes de stickers.\n\nGerenciadores de integrações recebem dados de configuração, e podem modificar widgets, enviar convites de sala e definir níveis de poder em seu nome.";
|
||||
"settings_add_3pid_password_title_email" = "Adicionar endereço de email";
|
||||
"settings_discovery_three_pids_management_information_part2" = "Configurações de Usuária(o)";
|
||||
"settings_discovery_three_pids_management_information_part3" = ".";
|
||||
@@ -779,7 +779,7 @@
|
||||
"room_participants_action_security_status_warning" = "Aviso";
|
||||
"settings_three_pids_management_information_part1" = "Gerencie quais endereços de email ou números de telefone você pode usar para fazer login ou recuperar sua conta aqui. Controle quem pode encontrar você em ";
|
||||
"settings_calls_stun_server_fallback_button" = "Permitir servidor fallback de assistência de chamadas";
|
||||
"settings_discovery_terms_not_signed" = "Concorde com os Termos de Serviço do Servidor de Identidade (%@) para permitir que você mesma(o) seja descobertável por endereço de email ou número de telefone.";
|
||||
"settings_discovery_terms_not_signed" = "Concorde com os Termos de Serviço do servidor de identidade (%@) para permitir que você mesma(o) seja descobertável por endereço de email ou número de telefone.";
|
||||
"settings_discovery_three_pids_management_information_part1" = "Gerencie quais endereços de email ou números de telefone outras(os) usuárias(os) podem usar para descobrir você e usar para convidar você para salas. Adicione ou remova endereços de email ou números de telefone desta lista em ";
|
||||
"settings_discovery_three_pid_details_title_email" = "Gerenciar email";
|
||||
"settings_discovery_three_pid_details_information_email" = "Gerencie preferências para este endereço de email, que outras(os) usuárias(os) podem usar para descobrir você e usar para convidar você para salas. Adicione ou remova endereços de email em Contas.";
|
||||
@@ -794,7 +794,7 @@
|
||||
"identity_server_settings_disconnect_info" = "Desconectar-se de seu servidor de identidade vai significar que você não vai ser descobertável por outras(os) usuárias(os) e ser capaz de convidar outras(os) por email ou telefone.";
|
||||
"identity_server_settings_alert_disconnect_still_sharing_3pid" = "Você ainda está compartilhando seus dados pessoais no servidor de identidade %@.\n\nNós recomendamos que você remova seus endereços de email e números de telefone do servidor de identidade antes de se desconectar.";
|
||||
"call_no_stun_server_error_title" = "Chamada falhou devido a servidor malconfigurado";
|
||||
"widget_integration_manager_disabled" = "Você precisa habilitar Gerenciador de Integrações em configurações";
|
||||
"widget_integration_manager_disabled" = "Você precisa habilitar gerenciador de integrações em configurações";
|
||||
"service_terms_modal_description_for_identity_server_1" = "Encontrar outras(os) por telefone ou email";
|
||||
"service_terms_modal_description_for_identity_server_2" = "Ser encontrada(o) por telefone ou email";
|
||||
"device_verification_self_verify_wait_additional_information" = "Isto funciona com %@ e outros clientes Matrix capazes de assinatura cruzada.";
|
||||
@@ -885,7 +885,7 @@
|
||||
"manage_session_not_trusted" = "Não confiada";
|
||||
"manage_session_sign_out" = "Fazer signout desta sessão";
|
||||
// Identity server settings
|
||||
"identity_server_settings_title" = "Servidor de Identidade";
|
||||
"identity_server_settings_title" = "Servidor de identidade";
|
||||
"identity_server_settings_description" = "Vvocê está atualmente usando %@ para descobrir e ser descobertável por contatos existentes que você conhece.";
|
||||
"identity_server_settings_no_is_description" = "Você não está atualmente usando um servidor de identidade. Para descobrir e ser descobertável por contatos existentes, adicione um acima.";
|
||||
"identity_server_settings_place_holder" = "Entrar um servidor de identidade";
|
||||
@@ -1474,3 +1474,27 @@
|
||||
"room_recents_suggested_rooms_section" = "SALAS SUGERIDAS";
|
||||
"done" = "Feito";
|
||||
"open" = "Abrir";
|
||||
"service_terms_modal_information_description_integration_manager" = "Um gerenciador de integrações deixa você adicionar funcionalidades de terceiros.";
|
||||
"service_terms_modal_information_description_identity_server" = "Um servidor de identidade ajuda você a encontrar seus contatos, ao buscar o número de telefone ou endereço de email deles, para ver se eles já têm uma conta.";
|
||||
"service_terms_modal_information_title_integration_manager" = "Gerenciador de Integrações";
|
||||
|
||||
// Alert explaining what an identity server / integration manager is.
|
||||
"service_terms_modal_information_title_identity_server" = "Servidor de Identidade";
|
||||
"service_terms_modal_description_integration_manager" = "Isto vai permitir você usar bots, bridges, widgets e pacotes de stickers.";
|
||||
"service_terms_modal_description_identity_server" = "Isto vai permitir alguém encontrar você se ela/ele tem seu número de telefone ou email salvo nos contatos de telefone dela/dele.";
|
||||
"service_terms_modal_table_header_integration_manager" = "TERMOS DE GERENCIADOR DE INTEGRAÇÕES";
|
||||
"service_terms_modal_table_header_identity_server" = "TERMOS DE SERVIDOR DE IDENTIDADE";
|
||||
"service_terms_modal_footer" = "Isto pode ser desabilitado a qualquer hora em configurações.";
|
||||
|
||||
// Service terms
|
||||
"service_terms_modal_title_message" = "Para continuar, aceite os termos e condições abaixo";
|
||||
"settings_contacts_enable_sync_description" = "Isto vai usar seu servidor de identidade para conectar você com seus contatos, e ajudá-los a encontrar você.";
|
||||
"settings_contacts_enable_sync" = "Encontre seus contatos";
|
||||
"settings_phone_contacts" = "CONTATOS DE TELEFONE";
|
||||
"find_your_contacts_identity_service_error" = "Incapaz de se conectar ao servidor de identidade.";
|
||||
"find_your_contacts_footer" = "Isto pode ser desabilitado a qualquer hora a partir de configurações.";
|
||||
"find_your_contacts_button_title" = "Encontre seus contatos";
|
||||
"find_your_contacts_message" = "Deixe %@ mostrar seus contatos para que você possa rapidamente começar a conversar com aqueles que você conhece melhor.";
|
||||
"find_your_contacts_title" = "Comece por listar seus contatos";
|
||||
"contacts_address_book_permission_denied_alert_message" = "Para habilitar contatos, vá para as configurações de seu dispositivo.";
|
||||
"contacts_address_book_permission_denied_alert_title" = "Contatos desabilitados";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Permissions usage explanations
|
||||
"NSCameraUsageDescription" = "Камера используется для съемки фотографий и видеороликов, а также для видеозвонков.";
|
||||
"NSPhotoLibraryUsageDescription" = "Галерея используется для отправки фотографий и видео.";
|
||||
"NSCameraUsageDescription" = "Камера используется для съемки фото и видео, совершения видеозвонков.";
|
||||
"NSPhotoLibraryUsageDescription" = "Галерея используется для отправки фото и видео.";
|
||||
"NSMicrophoneUsageDescription" = "Element необходим доступ к вашему микрофону, чтобы совершать и принимать звонки, снимать видео и записывать голосовые сообщения.";
|
||||
"NSContactsUsageDescription" = "Чтобы обнаружить контакты, уже использующие Matrix, Element может отправлять адреса электронной почты и номера телефонов из адресной книги на выбранный вами сервер идентификации Matrix. Если поддерживается, то личные данные перед отправкой хэшируются - пожалуйста, ознакомьтесь с политикой конфиденциальности вашего сервера идентификации для получения более подробной информации.";
|
||||
"NSCalendarsUsageDescription" = "Ознакомьтесь со своими запланированными встречами в приложении.";
|
||||
"NSContactsUsageDescription" = "Element покажет ваши контакты, чтобы вы могли пригласить их в чат.";
|
||||
"NSCalendarsUsageDescription" = "Просматривайте запланированные встречи в приложении.";
|
||||
"NSFaceIDUsageDescription" = "Face ID используется для доступа к вашему приложению.";
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
"room_creation_keep_private" = "Оставить приватным";
|
||||
"room_creation_make_private" = "Сделать приватным";
|
||||
"room_creation_wait_for_creation" = "Комната уже создана. Подождите.";
|
||||
"room_creation_invite_another_user" = "Поиск / приглашение по идентификатору пользователя, имени или адресу электронной почты";
|
||||
"room_creation_invite_another_user" = "Идентификатор пользователя, имя или электронная почта";
|
||||
// Room recents
|
||||
"room_recents_directory_section" = "КАТАЛОГ КОМНАТ";
|
||||
"room_recents_favourites_section" = "ИЗБРАННЫЕ";
|
||||
@@ -237,7 +237,7 @@
|
||||
"settings_notifications_settings" = "НАСТРОЙКИ УВЕДОМЛЕНИЙ";
|
||||
"settings_user_interface" = "ПОЛЬЗОВАТЕЛЬСКИЙ ИНТЕРФЕЙС";
|
||||
"settings_ignored_users" = "ИГНОРИРУЕМЫЕ ПОЛЬЗОВАТЕЛИ";
|
||||
"settings_contacts" = "ЛОКАЛЬНЫЕ КОНТАКТЫ";
|
||||
"settings_contacts" = "КОНТАКТЫ УСТРОЙСТВА";
|
||||
"settings_advanced" = "ДОПОЛНИТЕЛЬНО";
|
||||
"settings_other" = "ДРУГИЕ";
|
||||
"settings_labs" = "ЛАБОРАТОРИЯ";
|
||||
@@ -1420,20 +1420,20 @@
|
||||
"event_formatter_call_has_ended_with_time" = "Вызов закончен • %@";
|
||||
"settings_notifications" = "УВЕДОМЛЕНИЯ";
|
||||
"version_check_modal_action_title_deprecated" = "Узнайте, как";
|
||||
"version_check_modal_subtitle_deprecated" = "Мы работали над улучшением Element для более быстрой и совершенной работы. К сожалению, ваша текущая версия iOS не совместима с некоторыми из этих исправлений и больше не будет поддерживаться.\nМы советуем вам обновить свою операционную систему, чтобы использовать Element в полной мере.";
|
||||
"version_check_modal_subtitle_deprecated" = "Мы работали над улучшением %@ для более быстрой и совершенной работы. К сожалению, ваша текущая версия iOS не совместима с некоторыми из этих исправлений и больше не будет поддерживаться.\nМы советуем вам обновить свою операционную систему, чтобы использовать %@ в полной мере.";
|
||||
"version_check_modal_title_deprecated" = "Мы больше не поддерживаем iOS %@";
|
||||
"version_check_modal_action_title_supported" = "Понятно";
|
||||
"version_check_modal_subtitle_supported" = "Мы работали над улучшением Element для более быстрой и совершенной работы. К сожалению, ваша текущая версия iOS не совместима с некоторыми из этих исправлений и больше не будет поддерживаться.\nМы советуем вам обновить свою операционную систему, чтобы использовать Element в полной мере.";
|
||||
"version_check_modal_subtitle_supported" = "Мы работали над улучшением %@ для более быстрой и совершенной работы. К сожалению, ваша текущая версия iOS не совместима с некоторыми из этих исправлений и больше не будет поддерживаться.\nМы советуем вам обновить свою операционную систему, чтобы использовать %@ в полной мере.";
|
||||
"version_check_modal_title_supported" = "Мы прекращаем поддержку iOS %@";
|
||||
"version_check_banner_subtitle_deprecated" = "Мы больше не поддерживаем Element на iOS %@. Чтобы продолжать использовать Element в полной мере, мы советуем вам обновить версию iOS.";
|
||||
"version_check_banner_subtitle_deprecated" = "Мы больше не поддерживаем %@ на iOS %@. Чтобы продолжать использовать %@ в полной мере, мы советуем вам обновить версию iOS.";
|
||||
"version_check_banner_title_deprecated" = "Мы больше не поддерживаем iOS %@";
|
||||
"version_check_banner_subtitle_supported" = "В ближайшее время мы прекращаем поддержку Element на iOS %@. Чтобы продолжать использовать Element в полной мере, мы советуем вам обновить вашу версию iOS.";
|
||||
"version_check_banner_subtitle_supported" = "В ближайшее время мы прекращаем поддержку %@ на iOS %@. Чтобы продолжать использовать %@ в полной мере, мы советуем вам обновить версию iOS.";
|
||||
|
||||
// Mark: - Version check
|
||||
|
||||
"version_check_banner_title_supported" = "Мы прекращаем поддержку iOS %@";
|
||||
"settings_show_url_previews_description" = "Предварительный просмотр будет осуществляться только в незашифрованных комнатах.";
|
||||
"settings_show_url_previews" = "Показывать встроенные предварительные просмотры URL-адресов";
|
||||
"settings_show_url_previews" = "Предварительный просмотр веб-сайта";
|
||||
"settings_mentions_and_keywords_encryption_notice" = "Вы не будете получать уведомления об упоминаниях и ключевых словах в зашифрованных комнатах на мобильных устройствах.";
|
||||
"settings_new_keyword" = "Добавить новое ключевое слово";
|
||||
"settings_your_keywords" = "Ваши ключевые слова";
|
||||
@@ -1487,3 +1487,27 @@
|
||||
"settings_links" = "ССЫЛКИ";
|
||||
"done" = "Готово";
|
||||
"open" = "Открыть";
|
||||
"service_terms_modal_information_description_integration_manager" = "Менеджер интеграции позволяет добавлять функции от сторонних производителей.";
|
||||
"service_terms_modal_information_description_identity_server" = "Сервер идентификации помогает найти контакты, просматривая номер телефона или адрес электронной почты, чтобы узнать, есть ли у них учетная запись.";
|
||||
"service_terms_modal_information_title_integration_manager" = "Менеджер интеграции";
|
||||
|
||||
// Alert explaining what an identity server / integration manager is.
|
||||
"service_terms_modal_information_title_identity_server" = "Сервер идентификации";
|
||||
"service_terms_modal_description_integration_manager" = "Это позволит вам использовать ботов, мосты, виджеты и пакеты стикеров.";
|
||||
"service_terms_modal_description_identity_server" = "Это позволит найти вас, если у них есть ваш номер телефона или электронная почта, сохраненные в контактах на его телефоне.";
|
||||
"service_terms_modal_table_header_integration_manager" = "УСЛОВИЯ МЕНЕДЖЕРА ИНТЕГРАЦИИ";
|
||||
"service_terms_modal_table_header_identity_server" = "УСЛОВИЯ СЕРВЕРА ИДЕНТИФИКАЦИИ";
|
||||
"service_terms_modal_footer" = "Это можно отключить в любое время в настройках.";
|
||||
|
||||
// Service terms
|
||||
"service_terms_modal_title_message" = "Чтобы продолжить, примите приведенные ниже положения и условия";
|
||||
"settings_contacts_enable_sync_description" = "Это позволит использовать ваш сервер идентификации для связи с вашими контактами и поможет им найти вас.";
|
||||
"settings_contacts_enable_sync" = "Поиск контактов";
|
||||
"settings_phone_contacts" = "КОНТАКТЫ ТЕЛЕФОНА";
|
||||
"find_your_contacts_identity_service_error" = "Невозможно подключиться к серверу идентификации.";
|
||||
"find_your_contacts_footer" = "Это можно отключить в настройках в любое время.";
|
||||
"find_your_contacts_button_title" = "Поиск контактов";
|
||||
"find_your_contacts_message" = "Пусть %@ покажет ваши контакты, так вы сразу начнёте общаться с теми, кого вы хорошо знаете.";
|
||||
"find_your_contacts_title" = "Начните с составления списка контактов";
|
||||
"contacts_address_book_permission_denied_alert_message" = "Для включения контактов, перейдите в настройки устройства.";
|
||||
"contacts_address_book_permission_denied_alert_title" = "Контакты отключены";
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
"NSCameraUsageDescription" = "Kamera përdoret për të bërë foto dhe regjistruar video, dhe për të bërë thirrje video.";
|
||||
"NSPhotoLibraryUsageDescription" = "Fototeka përdoret për të dërguar foto dhe video.";
|
||||
"NSMicrophoneUsageDescription" = "Element-it i duhet të përdorë mikrofonin tuaj për të bërë dhe marrë thirrje, për të regjistruar video, dhe për të regjistruar mesazhe zanorë.";
|
||||
"NSContactsUsageDescription" = "Për zbulim kontaktesh që përdorin tashmë Matrix-in, Element-i mund të dërgojë adresa email dhe numra telefonash nga libri juaj i adresave te shërbyesi juaj i zgjedhur Matrix i identiteteve. Kur kjo mbulohet, të dhënat personale fshehtëzohen, para se të dërgohen - ju lutemi, për më tepër hollësi, shihni rregulla privatësie të shërbyesit tuaj të identiteteve.";
|
||||
"NSContactsUsageDescription" = "Element-i do të shfaqë kontaktet tuaja, që kështu të mund t’i ftoni për të biseduar.";
|
||||
"NSCalendarsUsageDescription" = "Shihini te aplikacioni takimet tuaja të planifikuara.";
|
||||
"NSFaceIDUsageDescription" = "Face ID përdoret që të hyni në aplikacionin tuaj.";
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"auth_phone_in_use" = "Ky numër telefoni është tashmë në përdorim";
|
||||
"auth_untrusted_id_server" = "Shërbyesi i identiteteve s’është i besuar";
|
||||
"auth_password_dont_match" = "Fjalëkalimet s’përputhen";
|
||||
"auth_username_in_use" = "Emër përdoruesi në përdorim";
|
||||
"auth_username_in_use" = "Emër përdoruesi i përdorur";
|
||||
"auth_forgot_password" = "Harruat fjalëkalimin?";
|
||||
"auth_email_not_found" = "S’u arrit të dërgohej email: Kjo adresë email s’u gjet";
|
||||
"auth_email_validation_message" = "Ju lutemi, që të vazhdojë regjistrimi, kontrolloni email-in tuaj";
|
||||
@@ -220,7 +220,7 @@
|
||||
"settings_calls_settings" = "THIRRJE";
|
||||
"settings_user_interface" = "NDËRFAQE PËRDORUESI";
|
||||
"settings_ignored_users" = "PËRDORUES TË SHPËRFILLUR";
|
||||
"settings_contacts" = "KONTAKTE VENDORE";
|
||||
"settings_contacts" = "KONTAKTE PAJISJEJE";
|
||||
"settings_advanced" = "TË MËTEJSHME";
|
||||
"settings_other" = "TË TJERA";
|
||||
"settings_devices" = "SESIONE";
|
||||
@@ -397,7 +397,7 @@
|
||||
"auth_use_server_options" = "Përdor mundësi vetjake shërbyesi (e përparuar)";
|
||||
"auth_add_email_and_phone_warning" = "Regjistrimi me email dhe me numër telefoni njëherazi nuk mbulohet ende, deri sa të ketë API. Do të merret parasysh vetëm numri i telefonit. Email-in tuaj mund ta shtoni te profili juaj, te rregullimet.";
|
||||
"room_creation_appearance_picture" = "Foto fjalosjeje (në daçi)";
|
||||
"room_creation_invite_another_user" = "Kërkoni / ftoni sipas ID-je Përdoruesi, Emri ose email-i";
|
||||
"room_creation_invite_another_user" = "ID Përdoruesi, emër ose email";
|
||||
"room_recents_favourites_section" = "TË PARAPALQYERA";
|
||||
"room_recents_server_notice_section" = "SINJALIZIME SISTEMI";
|
||||
"room_recents_join_room_title" = "Hyni në një dhomë";
|
||||
@@ -854,7 +854,7 @@
|
||||
"settings_add_3pid_invalid_password_message" = "Kredenciale të pavlefshme";
|
||||
"settings_devices_description" = "Emri publik i një sesioni është i dukshëm për persona me të cilët komunikoni";
|
||||
"settings_discovery_no_identity_server" = "S’po përdorni ndonjë shërbyes identitetesh. Që të jeni i zbulueshëm nga kontakte ekzistuese që njihni, shtoni një të tillë.";
|
||||
"settings_discovery_terms_not_signed" = "Pajtohuni me Kushtet e Shërbimit të Shërbyesit të Identiteteve që t’i lejoni vetes të jeni i zbulueshëm përmes adrese email ose numri telefoni.";
|
||||
"settings_discovery_terms_not_signed" = "Pajtohuni me Kushtet e Shërbimit të shërbyesit të identiteteve (%@), që t’i lejoni vetes të jeni i zbulueshëm përmes adrese email ose numri telefoni.";
|
||||
"settings_discovery_three_pids_management_information_part1" = "Administroni cilat adresa email ose numra telefonash mund të përdorin përdoruesit e tjerë për t’ju zbuluar dhe ftuar në dhoma. Shtoni ose hiqni prej kësaj liste adresa email ose numra telefonash ";
|
||||
"settings_discovery_three_pids_management_information_part2" = "Rregullime Përdoruesi";
|
||||
"settings_discovery_three_pids_management_information_part3" = ".";
|
||||
@@ -871,7 +871,7 @@
|
||||
"settings_identity_server_no_is" = "S’ka të formësuar shërbyes identitetesh";
|
||||
"settings_identity_server_no_is_description" = "S’po përdorni ndonjë shërbyes identitetesh. Që të zbuloni dhe të jeni i zbulueshëm nga kontakte ekzistuese që njihni, shtoni një më sipër.";
|
||||
// Identity server settings
|
||||
"identity_server_settings_title" = "Shërbyes Identitetesh";
|
||||
"identity_server_settings_title" = "Shërbyes identitetesh";
|
||||
"identity_server_settings_description" = "Po përdorni %@ që të zbuloni dhe të jeni i zbulueshëm nga kontakte ekzistuese që dini.";
|
||||
"identity_server_settings_no_is_description" = "S’po përdorni ndonjë shërbyes identitetesh. Që të zbuloni dhe të jeni i zbulueshëm nga kontakte ekzistuese, shtoni një më sipër.";
|
||||
"identity_server_settings_place_holder" = "Jepni një shërbyes identitetesh";
|
||||
@@ -909,12 +909,12 @@
|
||||
"accessibility_checkbox_label" = "kutizë";
|
||||
"settings_integrations" = "INTEGRIME";
|
||||
"settings_integrations_allow_button" = "Administroni integrime";
|
||||
"settings_integrations_allow_description" = "Përdorni një Përgjegjës Integrimesh (%@) që të administroni robotë, ura, widget-e dhe paketa ngjitësish.\n\nPërgjegjësit e Integrimeve marrin të dhëna formësimi dhe mund të ndryshojnë widget-e, të dërgojnë ftesa për në dhoma dhe të caktojnë shkallë pushteti në emrin tuaj.";
|
||||
"settings_integrations_allow_description" = "Përdorni një përgjegjës integrimesh (%@) që të administroni robotë, ura, widget-e dhe paketa ngjitësish.\n\nPërgjegjësit e integrimeve marrin të dhëna formësimi dhe mund të ndryshojnë widget-e, të dërgojnë ftesa për në dhoma dhe të caktojnë shkallë pushteti në emrin tuaj.";
|
||||
"widget_menu_refresh" = "Rifreskoje";
|
||||
"widget_menu_open_outside" = "Hape në shfletues";
|
||||
"widget_menu_revoke_permission" = "Shfuqizo hyrje për mua";
|
||||
"widget_menu_remove" = "Hiqe për këdo";
|
||||
"widget_integration_manager_disabled" = "Lypset të aktivizoni Përgjegjës Integrimesh te rregullimet";
|
||||
"widget_integration_manager_disabled" = "Lypset të aktivizoni përgjegjës integrimesh te rregullimet";
|
||||
"widget_picker_manage_integrations" = "Administroni integrime…";
|
||||
// Room widget permissions
|
||||
"room_widget_permission_title" = "Ngarko Widget";
|
||||
@@ -1492,3 +1492,29 @@
|
||||
"settings_links" = "LIDHJE";
|
||||
"room_recents_suggested_rooms_section" = "DHOMA TË SUGJERUARA";
|
||||
"done" = "U bë";
|
||||
"spaces_home_space_title" = "Kreu";
|
||||
"service_terms_modal_information_description_integration_manager" = "Një përgjegjës integrimesh ju lejon të shtoni veçori prej palësh të treta.";
|
||||
"service_terms_modal_information_description_identity_server" = "Një shërbyes identitetesh ju ndihmon të gjeni kontaktet tuaja, duke kërkuar numrat e telefonave ose adresat email të tyre, për të parë nëse kanë tashmë një llogari.";
|
||||
"service_terms_modal_information_title_integration_manager" = "Përgjegjës Integrimesh";
|
||||
|
||||
// Alert explaining what an identity server / integration manager is.
|
||||
"service_terms_modal_information_title_identity_server" = "Shërbyes Identitetesh";
|
||||
"service_terms_modal_description_integration_manager" = "Kjo do t’ju lejojë të përdorni robotë, ura, widget-e dhe paketa ngjitësish.";
|
||||
"service_terms_modal_description_identity_server" = "Kjo do t’i lejojë dikujt t’ju gjejë, nëse ka ruajtur në kontaktet e telefonit të vet numrin tuaj të telefonit ose email-in tuaj.";
|
||||
"service_terms_modal_table_header_integration_manager" = "KUSHTE PËRGJEGJËSI INTEGRIMESH";
|
||||
"service_terms_modal_table_header_identity_server" = "KUSHTE SHËRBYESI IDENTITETESH";
|
||||
"service_terms_modal_footer" = "Kjo mund të çaktivizohet kurdo që nga rregullimet.";
|
||||
|
||||
// Service terms
|
||||
"service_terms_modal_title_message" = "Që të vazhdohet, pranoni termat dhe kushtet më poshtë";
|
||||
"security_settings_secure_backup_reset" = "Riktheji te parazgjedhjet";
|
||||
"settings_contacts_enable_sync_description" = "Kjo do të përdorë shërbyesin tuaj të identiteteve për t’ju lidhur me kontaktet tuaja dhe për t’i ndihmuar ata t’ju gjejnë.";
|
||||
"settings_contacts_enable_sync" = "Gjeni kontaktet tuaja";
|
||||
"settings_phone_contacts" = "KONTAKTE TELEFONI";
|
||||
"find_your_contacts_identity_service_error" = "S’arrihet të lidhet me shërbyesin e identiteteve.";
|
||||
"find_your_contacts_footer" = "Kjo mund të çaktivizohet kurdo që nga rregullimet.";
|
||||
"find_your_contacts_button_title" = "Gjeni kontakte tuajt";
|
||||
"find_your_contacts_message" = "Lejojeni %@ të shfaqë kontaktet tuaja, që kështu të mund të filloni shpejt e shpejt të bisedoni me ata që ju njohin më mirë.";
|
||||
"find_your_contacts_title" = "Fillojani duke shfaqur kontaktet tuaja";
|
||||
"contacts_address_book_permission_denied_alert_message" = "Që të aktivizoni kontakte, kaloni te rregullimet e pajisjes tua.";
|
||||
"contacts_address_book_permission_denied_alert_title" = "Kontaktet u çaktivizuan";
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
// Permissions usage explanations
|
||||
"NSCameraUsageDescription" = "Kameran används för att ta bilder och videor, och ringa videosamtal.";
|
||||
"NSMicrophoneUsageDescription" = "Element behöver åtkomst till din mikrofon för att kunna ringa och ta emot samtal samt spela in video och röstmeddelanden.";
|
||||
"NSContactsUsageDescription" = "För att upptäcka kontakter som redan använder Matrix kan Element skicka e-postadresser och telefonnummer i din adressbok till din valda Matrix-identitetsserver. Där det stöds hashas personuppgifter innan de skickas - kontrollera din identitetsservers integritetspolicy för mer information.";
|
||||
"NSContactsUsageDescription" = "Element kommer att visa dina kontakter så du kan bjuda in dem att chatta.";
|
||||
"NSFaceIDUsageDescription" = "Face ID används för att komma åt appen.";
|
||||
|
||||
@@ -1885,6 +1885,32 @@ permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
</pre>
|
||||
</li>
|
||||
<li>
|
||||
<b>WeakDictionary</b> (<a href="https://github.com/nicholascross/WeakDictionary">https://github.com/nicholascross/WeakDictionary/</a>)
|
||||
<br/><br/>
|
||||
MIT License
|
||||
<br/><br/>
|
||||
Copyright (c) 2016 Nicholas Cross
|
||||
<br/><br/>
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
<br/><br/>
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
<br/><br/>
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
<br/><br/>
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
"NSCameraUsageDescription" = "Камера використовується для знімків фото і відео, а також для відео-викликів.";
|
||||
"NSPhotoLibraryUsageDescription" = "Фотографії використовуються для надсилання фото і відео.";
|
||||
"NSMicrophoneUsageDescription" = "Element потребує доступу до вашого мікрофона, щоб здійснювати та отримувати виклики, знімати відео та записувати голосові повідомлення.";
|
||||
"NSContactsUsageDescription" = "Щоб показати, які з ваших контактів вже використовують Matrix, Element може надіслати адреси електронної пошти і номери телефонів з вашої адресної книги до вашого ідентифікаційного сервера Matrix. При наявності підтримки, перед надсиланням створюється хеш особистих даних. Для докладних відомостей ознайомтеся з політикою приватності свого ідентифікаційного сервера.";
|
||||
"NSContactsUsageDescription" = "Element покаже ваші контакти, щоб ви могли запросити їх до бесіди.";
|
||||
"NSCalendarsUsageDescription" = "Переглядайте свої заплановані зустрічі в додатку.";
|
||||
"NSFaceIDUsageDescription" = "Face ID використовується для доступу до вашого додатку.";
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
"client_web_name" = "Element Web";
|
||||
"client_ios_name" = "Element iOS";
|
||||
"auth_login_single_sign_on" = "Увійти";
|
||||
"room_creation_invite_another_user" = "Пошук / запрошення за ID користувача, іменем або е-поштою";
|
||||
"room_creation_invite_another_user" = "ID користувача, ім'я або е-пошта";
|
||||
"room_creation_error_invite_user_by_email_without_identity_server" = "Сервер ідентифікації не налаштовано, тому ви не можете додати учасника з е-поштою.";
|
||||
// Room recents
|
||||
"room_recents_directory_section" = "КАТАЛОГ КІМНАТ";
|
||||
@@ -381,7 +381,7 @@
|
||||
"secrets_recovery_with_passphrase_lost_passphrase_action_part3" = ".";
|
||||
"key_backup_recover_from_passphrase_lost_passphrase_action_part3" = ".";
|
||||
"settings_discovery_three_pids_management_information_part3" = ".";
|
||||
"settings_contacts" = "ЛОКАЛЬНІ КОНТАКТИ";
|
||||
"settings_contacts" = "КОНТАКТИ ПРИСТРОЮ";
|
||||
"settings_ignored_users" = "НЕХТУВАНІ КОРИСТУВАЧІ";
|
||||
"settings_user_interface" = "КОРИСТУВАЦЬКИЙ ІНТЕРФЕЙС";
|
||||
"settings_integrations" = "ІНТЕГРАЦІЇ";
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
"NSCameraUsageDescription" = "摄像头权限用于拍摄照片、录制视频或进行视频聊天。";
|
||||
"NSPhotoLibraryUsageDescription" = "照片库访问权限用于发送图片与视频。";
|
||||
"NSMicrophoneUsageDescription" = "Element 需要访问您的麦克风才能拨打和接听电话、拍摄视频和录制语音消息。";
|
||||
"NSContactsUsageDescription" = "为了发现已在使用 Matrix 的联系人,Element 可以把你地址簿里的邮箱地址和电话号码发送到你所选择的 Matrix 身份认证服务器。如果支持的话,个人数据在发送前会被哈希处理——请检查你的身份认证服务器的隐私政策以获取详细信息。";
|
||||
"NSContactsUsageDescription" = "Element 将显示您的联系人,以便您可以邀请他们聊天。";
|
||||
"NSCalendarsUsageDescription" = "在此应用中查看你计划的会议。";
|
||||
"NSFaceIDUsageDescription" = "Face ID 权限用于访问您的应用。";
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"auth_missing_phone" = "缺少电话号码";
|
||||
"auth_missing_email_or_phone" = "缺少电子邮箱地址或电话号码";
|
||||
"auth_password_dont_match" = "密码不匹配";
|
||||
"auth_username_in_use" = "用户名已被占用";
|
||||
"auth_username_in_use" = "用户名被占用";
|
||||
"auth_forgot_password" = "忘记密码?";
|
||||
"auth_use_server_options" = "使用自定义服务器选项(高级)";
|
||||
"auth_email_validation_message" = "请检查我们发给您的电子邮件以继续注册";
|
||||
@@ -93,7 +93,7 @@
|
||||
"room_creation_keep_private" = "保持私密";
|
||||
"room_creation_make_private" = "使其变成私密";
|
||||
"room_creation_wait_for_creation" = "聊天室已创建。请稍候。";
|
||||
"room_creation_invite_another_user" = "通过用户 ID、名称或电子邮件进行搜索/邀请";
|
||||
"room_creation_invite_another_user" = "用户 ID、名称或电子邮件";
|
||||
// Room recents
|
||||
"room_recents_directory_section" = "聊天室目录";
|
||||
"room_recents_favourites_section" = "收藏夹";
|
||||
@@ -245,7 +245,7 @@
|
||||
"settings_user_settings" = "用户设置";
|
||||
"settings_notifications_settings" = "通知设置";
|
||||
"settings_ignored_users" = "已忽略用户";
|
||||
"settings_contacts" = "本地联系人";
|
||||
"settings_contacts" = "设备联系人";
|
||||
"settings_advanced" = "高级";
|
||||
"settings_other" = "其他";
|
||||
"settings_labs" = "实验室";
|
||||
@@ -1521,3 +1521,27 @@
|
||||
"room_recents_suggested_rooms_section" = "建议的聊天室";
|
||||
"done" = "完成";
|
||||
"open" = "打开";
|
||||
"service_terms_modal_information_description_integration_manager" = "集成管理器允许您添加来自第三方的功能。";
|
||||
"service_terms_modal_information_description_identity_server" = "身份服务器通过查找电话号码或电子邮件地址帮助您找到联系人,看看他们是否已经有一个帐户。";
|
||||
"service_terms_modal_information_title_integration_manager" = "集成管理器";
|
||||
|
||||
// Alert explaining what an identity server / integration manager is.
|
||||
"service_terms_modal_information_title_identity_server" = "身份服务器";
|
||||
"service_terms_modal_description_integration_manager" = "这将允许您使用机器人、桥、小部件和贴纸包。";
|
||||
"service_terms_modal_description_identity_server" = "如果有人在电话联系人中保存了你的电话号码或电子邮件,就可以找到你。";
|
||||
"service_terms_modal_table_header_integration_manager" = "集成管理器条款";
|
||||
"service_terms_modal_table_header_identity_server" = "身份服务器条款";
|
||||
"service_terms_modal_footer" = "你可以随时在设置中禁用它。";
|
||||
|
||||
// Service terms
|
||||
"service_terms_modal_title_message" = "如需继续,请接受以下条款和条件";
|
||||
"settings_contacts_enable_sync_description" = "这将使用您的身份服务器连接您和您的联系人,并帮助他们找到您。";
|
||||
"settings_contacts_enable_sync" = "寻找联系人";
|
||||
"settings_phone_contacts" = "电话联系人";
|
||||
"find_your_contacts_identity_service_error" = "无法连接到身份服务器。";
|
||||
"find_your_contacts_footer" = "你可以随时从设置中禁用它。";
|
||||
"find_your_contacts_button_title" = "寻找联系人";
|
||||
"find_your_contacts_message" = "让 %@ 显示你的联系人,以便你可以快速开始和你最了解的人聊天。";
|
||||
"find_your_contacts_title" = "从列出你的联系人开始";
|
||||
"contacts_address_book_permission_denied_alert_message" = "要启用联系人,请转到设备设置。";
|
||||
"contacts_address_book_permission_denied_alert_title" = "联系人被禁用";
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// Copyright 2021 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
|
||||
|
||||
extension Array where Element: Equatable {
|
||||
|
||||
/// Remove first collection element that is equal to the given `object`
|
||||
/// Credits: https://stackoverflow.com/a/45008042
|
||||
mutating func vc_removeFirstOccurrence(of object: Element) {
|
||||
guard let index = firstIndex(of: object) else {
|
||||
return
|
||||
}
|
||||
remove(at: index)
|
||||
}
|
||||
}
|
||||
@@ -17,9 +17,9 @@
|
||||
import Foundation
|
||||
|
||||
extension MXKImageView {
|
||||
@objc func vc_setRoomAvatarImage(with url: String?, displayName: String, mediaManager: MXMediaManager) {
|
||||
@objc func vc_setRoomAvatarImage(with url: String?, roomId: String, displayName: String, mediaManager: MXMediaManager) {
|
||||
// Use the display name to prepare the default avatar image.
|
||||
let avatarImage = AvatarGenerator.generateAvatar(forText: displayName)
|
||||
let avatarImage = AvatarGenerator.generateAvatar(forMatrixItem: roomId, withDisplayName: displayName)
|
||||
|
||||
if let avatarUrl = url {
|
||||
self.enableInMemoryCache = true
|
||||
|
||||
@@ -19,13 +19,6 @@
|
||||
|
||||
#import "UserEncryptionTrustLevel.h"
|
||||
|
||||
typedef NS_ENUM(NSUInteger, RoomSentStatus)
|
||||
{
|
||||
RoomSentStatusOk,
|
||||
RoomSentStatusSentFailed,
|
||||
RoomSentStatusSentFailedDueToUnknownDevices
|
||||
};
|
||||
|
||||
/**
|
||||
Define a `MXRoom` category at Riot level.
|
||||
*/
|
||||
@@ -51,9 +44,6 @@ typedef NS_ENUM(NSUInteger, RoomSentStatus)
|
||||
*/
|
||||
@property (nonatomic) id notificationCenterDidUpdateObserver;
|
||||
|
||||
/// Check if all messages have been sent.
|
||||
@property (nonatomic, readonly) RoomSentStatus sentStatus;
|
||||
|
||||
/**
|
||||
Update the room tag.
|
||||
|
||||
|
||||
@@ -656,30 +656,4 @@
|
||||
return objc_getAssociatedObject(self, @selector(notificationCenterDidUpdateObserver));
|
||||
}
|
||||
|
||||
#pragma mark - Unread messages
|
||||
|
||||
- (RoomSentStatus)sentStatus
|
||||
{
|
||||
RoomSentStatus status = RoomSentStatusOk;
|
||||
NSArray<MXEvent*> *outgoingMsgs = self.outgoingMessages;
|
||||
|
||||
for (MXEvent *event in outgoingMsgs)
|
||||
{
|
||||
if (event.sentState == MXEventSentStateFailed)
|
||||
{
|
||||
status = RoomSentStatusSentFailed;
|
||||
|
||||
// Check if the error is due to unknown devices
|
||||
if ([event.sentError.domain isEqualToString:MXEncryptingErrorDomain]
|
||||
&& event.sentError.code == MXEncryptingErrorUnknownDeviceCode)
|
||||
{
|
||||
status = RoomSentStatusSentFailedDueToUnknownDevices;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -19,32 +19,20 @@
|
||||
|
||||
#import "AvatarGenerator.h"
|
||||
|
||||
#ifdef IS_SHARE_EXTENSION
|
||||
#import "RiotShareExtension-Swift.h"
|
||||
#else
|
||||
#import "Riot-Swift.h"
|
||||
#endif
|
||||
|
||||
@implementation MXRoomSummary (Riot)
|
||||
|
||||
- (void)setRoomAvatarImageIn:(MXKImageView*)mxkImageView
|
||||
{
|
||||
// Use the room display name to prepare the default avatar image.
|
||||
NSString *avatarDisplayName = self.displayname;
|
||||
UIImage* avatarImage = [AvatarGenerator generateAvatarForMatrixItem:self.roomId withDisplayName:avatarDisplayName];
|
||||
|
||||
if (self.avatar)
|
||||
{
|
||||
mxkImageView.enableInMemoryCache = YES;
|
||||
|
||||
[mxkImageView setImageURI:self.avatar
|
||||
withType:nil
|
||||
andImageOrientation:UIImageOrientationUp
|
||||
toFitViewSize:mxkImageView.frame.size
|
||||
withMethod:MXThumbnailingMethodCrop
|
||||
previewImage:avatarImage
|
||||
mediaManager:self.mxSession.mediaManager];
|
||||
}
|
||||
else
|
||||
{
|
||||
mxkImageView.image = avatarImage;
|
||||
}
|
||||
|
||||
mxkImageView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
[mxkImageView vc_setRoomAvatarImageWith:self.avatar
|
||||
roomId:self.roomId
|
||||
displayName:self.displayname
|
||||
mediaManager:self.mxSession.mediaManager];
|
||||
}
|
||||
|
||||
- (RoomEncryptionTrustLevel)roomEncryptionTrustLevel
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// Copyright 2021 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/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface NSArray (Element)
|
||||
|
||||
/// Returns an array containing the results of mapping the given closure over the array's elements.
|
||||
/// @param transform A mapping closure. `transform` accepts an element of this array as its parameter
|
||||
/// and returns a transformed value of the same or of a different type.
|
||||
/// @return An array containing the transformed elements of this array.
|
||||
- (NSArray *)vc_map:(id (^)(id obj))transform;
|
||||
|
||||
/// Returns an array containing the non-nil results of mapping the given closure over the array's elements.
|
||||
/// @param transform A mapping closure. `transform` accepts an element of this array as its parameter
|
||||
/// and returns a nullable transformed value of the same or of a different type.
|
||||
/// @return An array of the non-nil results of calling `transform` with each element of the array.
|
||||
- (NSArray *)vc_compactMap:(id _Nullable (^)(id obj))transform;
|
||||
|
||||
/// Returns an array containing the concatenated results of mapping the given closure over the array's elements.
|
||||
/// @param transform A mapping closure. `transform` accepts an element of this array as its parameter
|
||||
/// and returns an array..
|
||||
/// @return The resulting flattened array.
|
||||
- (NSArray *)vc_flatMap:(NSArray* (^)(id obj))transform;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// Copyright 2021 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 "NSArray+Element.h"
|
||||
|
||||
@implementation NSArray (Element)
|
||||
|
||||
- (NSArray *)vc_map:(id (^)(id obj))transform
|
||||
{
|
||||
NSMutableArray *result = [NSMutableArray arrayWithCapacity:self.count];
|
||||
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
|
||||
{
|
||||
[result addObject:transform(obj)];
|
||||
}];
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSArray *)vc_compactMap:(id _Nullable (^)(id obj))transform
|
||||
{
|
||||
NSMutableArray *result = [NSMutableArray arrayWithCapacity:self.count];
|
||||
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
|
||||
{
|
||||
id mappedObject = transform(obj);
|
||||
if (mappedObject)
|
||||
{
|
||||
[result addObject:mappedObject];
|
||||
}
|
||||
}];
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSArray *)vc_flatMap:(NSArray* (^)(id obj))transform
|
||||
{
|
||||
NSMutableArray *result = [NSMutableArray arrayWithCapacity:self.count];
|
||||
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
|
||||
{
|
||||
[result addObjectsFromArray:transform(obj)];
|
||||
}];
|
||||
return result;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -103,4 +103,16 @@ extension UIViewController {
|
||||
|
||||
return fabImageView
|
||||
}
|
||||
|
||||
/// Set leftBarButtonItem with split view display mode button if there is no leftBarButtonItem defined and splitViewController exists.
|
||||
/// To be Used when view controller is displayed as detail controller in split view.
|
||||
func vc_setupDisplayModeLeftBarButtonItemIfNeeded() {
|
||||
guard let splitViewController = self.splitViewController, self.navigationItem.leftBarButtonItem == nil else {
|
||||
return
|
||||
}
|
||||
|
||||
// If there is no leftBarButtonItem defined,
|
||||
// set split view display mode button as left bar button item
|
||||
self.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ internal enum Asset {
|
||||
internal static let errorIcon = ImageAsset(name: "error_icon")
|
||||
internal static let faceidIcon = ImageAsset(name: "faceid_icon")
|
||||
internal static let group = ImageAsset(name: "group")
|
||||
internal static let informationButton = ImageAsset(name: "information_button")
|
||||
internal static let monitor = ImageAsset(name: "monitor")
|
||||
internal static let placeholder = ImageAsset(name: "placeholder")
|
||||
internal static let plusIcon = ImageAsset(name: "plus_icon")
|
||||
@@ -74,6 +75,7 @@ internal enum Asset {
|
||||
internal static let touchidIcon = ImageAsset(name: "touchid_icon")
|
||||
internal static let addGroupParticipant = ImageAsset(name: "add_group_participant")
|
||||
internal static let removeIconBlue = ImageAsset(name: "remove_icon_blue")
|
||||
internal static let findYourContactsFacepile = ImageAsset(name: "find_your_contacts_facepile")
|
||||
internal static let captureAvatar = ImageAsset(name: "capture_avatar")
|
||||
internal static let e2eBlocked = ImageAsset(name: "e2e_blocked")
|
||||
internal static let e2eUnencrypted = ImageAsset(name: "e2e_unencrypted")
|
||||
@@ -95,6 +97,7 @@ internal enum Asset {
|
||||
internal static let plusFloatingAction = ImageAsset(name: "plus_floating_action")
|
||||
internal static let versionCheckCloseIcon = ImageAsset(name: "version_check_close_icon")
|
||||
internal static let versionCheckInfoIcon = ImageAsset(name: "version_check_info_icon")
|
||||
internal static let integrationManagerIconpile = ImageAsset(name: "integration_manager_iconpile")
|
||||
internal static let closeBanner = ImageAsset(name: "close_banner")
|
||||
internal static let importFilesButton = ImageAsset(name: "import_files_button")
|
||||
internal static let keyBackupLogo = ImageAsset(name: "key_backup_logo")
|
||||
@@ -192,6 +195,7 @@ internal enum Asset {
|
||||
internal static let spaceMenuLeave = ImageAsset(name: "space_menu_leave")
|
||||
internal static let spaceMenuMembers = ImageAsset(name: "space_menu_members")
|
||||
internal static let spaceMenuRooms = ImageAsset(name: "space_menu_rooms")
|
||||
internal static let spacePrivateIcon = ImageAsset(name: "space_private_icon")
|
||||
internal static let spaceRoomIcon = ImageAsset(name: "space_room_icon")
|
||||
internal static let spaceTypeIcon = ImageAsset(name: "space_type_icon")
|
||||
internal static let spaceUserIcon = ImageAsset(name: "space_user_icon")
|
||||
@@ -207,6 +211,8 @@ internal enum Asset {
|
||||
internal static let cancel = ImageAsset(name: "cancel")
|
||||
internal static let e2eVerified = ImageAsset(name: "e2e_verified")
|
||||
internal static let horizontalLogo = ImageAsset(name: "horizontal_logo")
|
||||
internal static let radioButtonDefault = ImageAsset(name: "radio-button-default")
|
||||
internal static let radioButtonSelected = ImageAsset(name: "radio-button-selected")
|
||||
}
|
||||
}
|
||||
// swiftlint:enable identifier_name line_length nesting type_body_length type_name
|
||||
@@ -222,6 +228,7 @@ internal struct ImageAsset {
|
||||
internal typealias Image = UIImage
|
||||
#endif
|
||||
|
||||
@available(iOS 8.0, tvOS 9.0, watchOS 2.0, macOS 10.7, *)
|
||||
internal var image: Image {
|
||||
let bundle = BundleToken.bundle
|
||||
#if os(iOS) || os(tvOS)
|
||||
@@ -233,13 +240,25 @@ internal struct ImageAsset {
|
||||
let image = Image(named: name)
|
||||
#endif
|
||||
guard let result = image else {
|
||||
fatalError("Unable to load image named \(name).")
|
||||
fatalError("Unable to load image asset named \(name).")
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
#if os(iOS) || os(tvOS)
|
||||
@available(iOS 8.0, tvOS 9.0, *)
|
||||
internal func image(compatibleWith traitCollection: UITraitCollection) -> Image {
|
||||
let bundle = BundleToken.bundle
|
||||
guard let result = Image(named: name, in: bundle, compatibleWith: traitCollection) else {
|
||||
fatalError("Unable to load image asset named \(name).")
|
||||
}
|
||||
return result
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
internal extension ImageAsset.Image {
|
||||
@available(iOS 8.0, tvOS 9.0, watchOS 2.0, *)
|
||||
@available(macOS, deprecated,
|
||||
message: "This initializer is unsafe on macOS, please use the ImageAsset.image property")
|
||||
convenience init!(asset: ImageAsset) {
|
||||
|
||||
@@ -559,6 +559,14 @@ public class VectorL10n: NSObject {
|
||||
public static func contactsAddressBookPermissionDenied(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "contacts_address_book_permission_denied", p1)
|
||||
}
|
||||
/// To enable contacts, go to your device settings.
|
||||
public static var contactsAddressBookPermissionDeniedAlertMessage: String {
|
||||
return VectorL10n.tr("Vector", "contacts_address_book_permission_denied_alert_message")
|
||||
}
|
||||
/// Contacts disabled
|
||||
public static var contactsAddressBookPermissionDeniedAlertTitle: String {
|
||||
return VectorL10n.tr("Vector", "contacts_address_book_permission_denied_alert_title")
|
||||
}
|
||||
/// Permission required to access local contacts
|
||||
public static var contactsAddressBookPermissionRequired: String {
|
||||
return VectorL10n.tr("Vector", "contacts_address_book_permission_required")
|
||||
@@ -1403,6 +1411,26 @@ public class VectorL10n: NSObject {
|
||||
public static var fileUploadErrorUnsupportedFileTypeMessage: String {
|
||||
return VectorL10n.tr("Vector", "file_upload_error_unsupported_file_type_message")
|
||||
}
|
||||
/// Find your contacts
|
||||
public static var findYourContactsButtonTitle: String {
|
||||
return VectorL10n.tr("Vector", "find_your_contacts_button_title")
|
||||
}
|
||||
/// This can be disabled anytime from settings.
|
||||
public static var findYourContactsFooter: String {
|
||||
return VectorL10n.tr("Vector", "find_your_contacts_footer")
|
||||
}
|
||||
/// Unable to connect to the identity server.
|
||||
public static var findYourContactsIdentityServiceError: String {
|
||||
return VectorL10n.tr("Vector", "find_your_contacts_identity_service_error")
|
||||
}
|
||||
/// Let %@ show your contacts so you can quickly start chatting with those you know best.
|
||||
public static func findYourContactsMessage(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "find_your_contacts_message", p1)
|
||||
}
|
||||
/// Start by listing your contacts
|
||||
public static var findYourContactsTitle: String {
|
||||
return VectorL10n.tr("Vector", "find_your_contacts_title")
|
||||
}
|
||||
/// To continue using the %@ homeserver you must review and agree to the terms and conditions.
|
||||
public static func gdprConsentNotGivenAlertMessage(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "gdpr_consent_not_given_alert_message", p1)
|
||||
@@ -2463,7 +2491,7 @@ public class VectorL10n: NSObject {
|
||||
public static var roomCreationErrorInviteUserByEmailWithoutIdentityServer: String {
|
||||
return VectorL10n.tr("Vector", "room_creation_error_invite_user_by_email_without_identity_server")
|
||||
}
|
||||
/// Search / invite by User ID, Name or email
|
||||
/// User ID, name or email
|
||||
public static var roomCreationInviteAnotherUser: String {
|
||||
return VectorL10n.tr("Vector", "room_creation_invite_another_user")
|
||||
}
|
||||
@@ -2859,6 +2887,10 @@ public class VectorL10n: NSObject {
|
||||
public static var roomEventActionEdit: String {
|
||||
return VectorL10n.tr("Vector", "room_event_action_edit")
|
||||
}
|
||||
/// Forward
|
||||
public static var roomEventActionForward: String {
|
||||
return VectorL10n.tr("Vector", "room_event_action_forward")
|
||||
}
|
||||
/// Reason for kicking this user
|
||||
public static var roomEventActionKickPromptReason: String {
|
||||
return VectorL10n.tr("Vector", "room_event_action_kick_prompt_reason")
|
||||
@@ -4011,37 +4043,53 @@ public class VectorL10n: NSObject {
|
||||
public static var serviceTermsModalDeclineButton: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_decline_button")
|
||||
}
|
||||
/// Find others by phone or email
|
||||
public static var serviceTermsModalDescriptionForIdentityServer1: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_description_for_identity_server_1")
|
||||
/// This will allow someone to find you if they have your phone number or email saved in their phone contacts.
|
||||
public static var serviceTermsModalDescriptionIdentityServer: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_description_identity_server")
|
||||
}
|
||||
/// Be found by phone or email
|
||||
public static var serviceTermsModalDescriptionForIdentityServer2: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_description_for_identity_server_2")
|
||||
/// This will allow you to use bots, bridges, widgets and sticker packs.
|
||||
public static var serviceTermsModalDescriptionIntegrationManager: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_description_integration_manager")
|
||||
}
|
||||
/// Use Bots, bridges, widgets and sticker packs
|
||||
public static var serviceTermsModalDescriptionForIntegrationManager: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_description_for_integration_manager")
|
||||
/// This can be disabled anytime in settings.
|
||||
public static var serviceTermsModalFooter: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_footer")
|
||||
}
|
||||
/// To continue you need to accept the terms of this service (%@).
|
||||
public static func serviceTermsModalMessage(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_message", p1)
|
||||
/// An identity server helps you find your contacts, by looking up their phone number or email address, to see if they already have an account.
|
||||
public static var serviceTermsModalInformationDescriptionIdentityServer: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_information_description_identity_server")
|
||||
}
|
||||
/// Accept the terms of the identity server (%@) to discover contacts.
|
||||
public static func serviceTermsModalMessageIdentityServer(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_message_identity_server", p1)
|
||||
/// An integration manager lets you add features from third parties.
|
||||
public static var serviceTermsModalInformationDescriptionIntegrationManager: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_information_description_integration_manager")
|
||||
}
|
||||
/// Identity Server
|
||||
public static var serviceTermsModalInformationTitleIdentityServer: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_information_title_identity_server")
|
||||
}
|
||||
/// Integration Manager
|
||||
public static var serviceTermsModalInformationTitleIntegrationManager: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_information_title_integration_manager")
|
||||
}
|
||||
/// Check to accept %@
|
||||
public static func serviceTermsModalPolicyCheckboxAccessibilityHint(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_policy_checkbox_accessibility_hint", p1)
|
||||
}
|
||||
/// Terms Of Service
|
||||
public static var serviceTermsModalTitle: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_title")
|
||||
/// IDENTITY SERVER TERMS
|
||||
public static var serviceTermsModalTableHeaderIdentityServer: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_table_header_identity_server")
|
||||
}
|
||||
/// Contact discovery
|
||||
public static var serviceTermsModalTitleIdentityServer: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_title_identity_server")
|
||||
/// INTEGRATION MANAGER TERMS
|
||||
public static var serviceTermsModalTableHeaderIntegrationManager: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_table_header_integration_manager")
|
||||
}
|
||||
/// To continue, accept the below terms and conditions
|
||||
public static var serviceTermsModalTitleMessage: String {
|
||||
return VectorL10n.tr("Vector", "service_terms_modal_title_message")
|
||||
}
|
||||
/// ABOUT
|
||||
public static var settingsAbout: String {
|
||||
return VectorL10n.tr("Vector", "settings_about")
|
||||
}
|
||||
/// Invalid credentials
|
||||
public static var settingsAdd3pidInvalidPasswordMessage: String {
|
||||
@@ -4103,10 +4151,6 @@ public class VectorL10n: NSObject {
|
||||
public static func settingsConfigHomeServer(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "settings_config_home_server", p1)
|
||||
}
|
||||
/// Identity server is %@
|
||||
public static func settingsConfigIdentityServer(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "settings_config_identity_server", p1)
|
||||
}
|
||||
/// No build info
|
||||
public static var settingsConfigNoBuildInfo: String {
|
||||
return VectorL10n.tr("Vector", "settings_config_no_build_info")
|
||||
@@ -4127,13 +4171,17 @@ public class VectorL10n: NSObject {
|
||||
public static var settingsConfirmPassword: String {
|
||||
return VectorL10n.tr("Vector", "settings_confirm_password")
|
||||
}
|
||||
/// LOCAL CONTACTS
|
||||
/// DEVICE CONTACTS
|
||||
public static var settingsContacts: String {
|
||||
return VectorL10n.tr("Vector", "settings_contacts")
|
||||
}
|
||||
/// Use emails and phone numbers to discover users
|
||||
public static var settingsContactsDiscoverMatrixUsers: String {
|
||||
return VectorL10n.tr("Vector", "settings_contacts_discover_matrix_users")
|
||||
/// Find your contacts
|
||||
public static var settingsContactsEnableSync: String {
|
||||
return VectorL10n.tr("Vector", "settings_contacts_enable_sync")
|
||||
}
|
||||
/// This will use your identity server to connect you with your contacts, and help them find you.
|
||||
public static var settingsContactsEnableSyncDescription: String {
|
||||
return VectorL10n.tr("Vector", "settings_contacts_enable_sync_description")
|
||||
}
|
||||
/// Phonebook country
|
||||
public static var settingsContactsPhonebookCountry: String {
|
||||
@@ -4195,6 +4243,10 @@ public class VectorL10n: NSObject {
|
||||
public static var settingsDirectMessages: String {
|
||||
return VectorL10n.tr("Vector", "settings_direct_messages")
|
||||
}
|
||||
/// Accept Identity Server Terms
|
||||
public static var settingsDiscoveryAcceptTerms: String {
|
||||
return VectorL10n.tr("Vector", "settings_discovery_accept_terms")
|
||||
}
|
||||
/// An error occured. Please retry.
|
||||
public static var settingsDiscoveryErrorMessage: String {
|
||||
return VectorL10n.tr("Vector", "settings_discovery_error_message")
|
||||
@@ -4543,6 +4595,10 @@ public class VectorL10n: NSObject {
|
||||
public static var settingsPasswordUpdated: String {
|
||||
return VectorL10n.tr("Vector", "settings_password_updated")
|
||||
}
|
||||
/// PHONE CONTACTS
|
||||
public static var settingsPhoneContacts: String {
|
||||
return VectorL10n.tr("Vector", "settings_phone_contacts")
|
||||
}
|
||||
/// Phone
|
||||
public static var settingsPhoneNumber: String {
|
||||
return VectorL10n.tr("Vector", "settings_phone_number")
|
||||
@@ -4855,6 +4911,10 @@ public class VectorL10n: NSObject {
|
||||
public static var spaceFeatureUnavailableTitle: String {
|
||||
return VectorL10n.tr("Vector", "space_feature_unavailable_title")
|
||||
}
|
||||
/// Show all rooms
|
||||
public static var spaceHomeShowAllRooms: String {
|
||||
return VectorL10n.tr("Vector", "space_home_show_all_rooms")
|
||||
}
|
||||
/// Ban from this space
|
||||
public static var spaceParticipantsActionBan: String {
|
||||
return VectorL10n.tr("Vector", "space_participants_action_ban")
|
||||
|
||||
@@ -16,7 +16,11 @@
|
||||
|
||||
#import "BuildInfo.h"
|
||||
|
||||
#ifdef IS_SHARE_EXTENSION
|
||||
#import "RiotShareExtension-Swift.h"
|
||||
#else
|
||||
#import "Riot-Swift.h"
|
||||
#endif
|
||||
|
||||
#define MAKE_STRING(x) #x
|
||||
#define MAKE_NS_STRING(x) @MAKE_STRING(x)
|
||||
|
||||
@@ -22,10 +22,13 @@ final class RiotSettings: NSObject {
|
||||
|
||||
// MARK: - Constants
|
||||
|
||||
private enum UserDefaultsKeys {
|
||||
public enum UserDefaultsKeys {
|
||||
static let enableCrashReport = "enableCrashReport"
|
||||
static let notificationsShowDecryptedContent = "showDecryptedContent"
|
||||
static let allowStunServerFallback = "allowStunServerFallback"
|
||||
static let pinRoomsWithMissedNotificationsOnHome = "pinRoomsWithMissedNotif"
|
||||
static let pinRoomsWithUnreadMessagesOnHome = "pinRoomsWithUnread"
|
||||
static let showAllRoomsInHomeSpace = "showAllRoomsInHomeSpace"
|
||||
}
|
||||
|
||||
static let shared = RiotSettings()
|
||||
@@ -79,11 +82,11 @@ final class RiotSettings: NSObject {
|
||||
var showDecryptedContentInNotifications
|
||||
|
||||
/// Indicate if rooms with missed notifications should be displayed first on home screen.
|
||||
@UserDefault(key: "pinRoomsWithMissedNotif", defaultValue: false, storage: defaults)
|
||||
@UserDefault(key: UserDefaultsKeys.pinRoomsWithMissedNotificationsOnHome, defaultValue: false, storage: defaults)
|
||||
var pinRoomsWithMissedNotificationsOnHome
|
||||
|
||||
/// Indicate if rooms with unread messages should be displayed first on home screen.
|
||||
@UserDefault(key: "pinRoomsWithUnread", defaultValue: false, storage: defaults)
|
||||
@UserDefault(key: UserDefaultsKeys.pinRoomsWithUnreadMessagesOnHome, defaultValue: false, storage: defaults)
|
||||
var pinRoomsWithUnreadMessagesOnHome
|
||||
|
||||
/// Indicate to show Not Safe For Work public rooms.
|
||||
@@ -140,6 +143,9 @@ final class RiotSettings: NSObject {
|
||||
@UserDefault(key: "roomsAllowToJoinPublicRooms", defaultValue: BuildSettings.roomsAllowToJoinPublicRooms, storage: defaults)
|
||||
var roomsAllowToJoinPublicRooms
|
||||
|
||||
@UserDefault(key: UserDefaultsKeys.showAllRoomsInHomeSpace, defaultValue: false, storage: defaults)
|
||||
var showAllRoomsInHomeSpace
|
||||
|
||||
// MARK: - Room Screen
|
||||
|
||||
@UserDefault(key: "roomScreenAllowVoIPForDirectRoom", defaultValue: BuildSettings.roomScreenAllowVoIPForDirectRoom, storage: defaults)
|
||||
@@ -227,9 +233,6 @@ final class RiotSettings: NSObject {
|
||||
@UserDefault(key: "settingsScreenShowChangePassword", defaultValue: BuildSettings.settingsScreenShowChangePassword, storage: defaults)
|
||||
var settingsScreenShowChangePassword
|
||||
|
||||
@UserDefault(key: "settingsScreenShowInviteFriends", defaultValue: BuildSettings.settingsScreenShowInviteFriends, storage: defaults)
|
||||
var settingsScreenShowInviteFriends
|
||||
|
||||
@UserDefault(key: "settingsScreenShowEnableStunServerFallback", defaultValue: BuildSettings.settingsScreenShowEnableStunServerFallback, storage: defaults)
|
||||
var settingsScreenShowEnableStunServerFallback
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ import DesignKit
|
||||
var textPrimaryColor: UIColor { get }
|
||||
var textSecondaryColor: UIColor { get }
|
||||
var textTertiaryColor: UIColor { get }
|
||||
var textQuinaryColor: UIColor { get }
|
||||
|
||||
var tintColor: UIColor { get }
|
||||
var tintBackgroundColor: UIColor { get }
|
||||
|
||||
@@ -42,6 +42,7 @@ class DarkTheme: NSObject, Theme {
|
||||
var textPrimaryColor: UIColor = UIColor(rgb: 0xFFFFFF)
|
||||
var textSecondaryColor: UIColor = UIColor(rgb: 0xA9B2BC)
|
||||
var textTertiaryColor: UIColor = UIColor(rgb: 0x8E99A4)
|
||||
var textQuinaryColor: UIColor = UIColor(rgb: 0x394049)
|
||||
|
||||
var tintColor: UIColor = UIColor(displayP3Red: 0.05098039216, green: 0.7450980392, blue: 0.5450980392, alpha: 1.0)
|
||||
var tintBackgroundColor: UIColor = UIColor(rgb: 0x1F6954)
|
||||
|
||||
@@ -42,6 +42,7 @@ class DefaultTheme: NSObject, Theme {
|
||||
var textPrimaryColor: UIColor = UIColor(rgb: 0x17191C)
|
||||
var textSecondaryColor: UIColor = UIColor(rgb: 0x737D8C)
|
||||
var textTertiaryColor: UIColor = UIColor(rgb: 0x8D99A5)
|
||||
var textQuinaryColor: UIColor = UIColor(rgb: 0xE3E8F0)
|
||||
|
||||
var tintColor: UIColor = UIColor(displayP3Red: 0.05098039216, green: 0.7450980392, blue: 0.5450980392, alpha: 1.0)
|
||||
var tintBackgroundColor: UIColor = UIColor(rgb: 0xe9fff9)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import AFNetworking
|
||||
|
||||
enum URLPreviewServiceError: Error {
|
||||
case missingResponse
|
||||
@@ -74,7 +75,10 @@ class URLPreviewService: NSObject {
|
||||
success(previewData)
|
||||
}
|
||||
|
||||
}, failure: failure)
|
||||
}, failure: { error in
|
||||
self.checkForDisabledAPI(in: error)
|
||||
failure(error)
|
||||
})
|
||||
}
|
||||
|
||||
/// Removes any cached preview data that has expired.
|
||||
@@ -82,9 +86,11 @@ class URLPreviewService: NSObject {
|
||||
store.removeExpiredItems()
|
||||
}
|
||||
|
||||
/// Deletes all cached preview data and closed previews from the store.
|
||||
/// Deletes all cached preview data and closed previews from the store,
|
||||
/// re-enabling URL previews if they have been disabled by `checkForDisabledAPI`.
|
||||
func clearStore() {
|
||||
store.deleteAll()
|
||||
MXKAppSettings.standard().enableBubbleComponentLinkDetection = true
|
||||
}
|
||||
|
||||
/// Store the `eventId` and `roomId` of a closed preview.
|
||||
@@ -156,4 +162,20 @@ class URLPreviewService: NSObject {
|
||||
|
||||
return components?.url ?? url
|
||||
}
|
||||
|
||||
/// Checks an error returned from `MXRestClient` to see whether the previews API
|
||||
/// has been disabled on the homeserver. If this is true, link detection will be disabled
|
||||
/// to prevent further requests being made and stop any previews loaders being presented.
|
||||
private func checkForDisabledAPI(in error: Error?) {
|
||||
// The error we're looking for is a generic 404 and not a matrix error.
|
||||
guard
|
||||
!MXError.isMXError(error),
|
||||
let response = MXHTTPOperation.urlResponse(fromError: error)
|
||||
else { return }
|
||||
|
||||
if response.statusCode == 404 {
|
||||
MXLog.debug("[URLPreviewService] Disabling link detection as homeserver does not support URL previews.")
|
||||
MXKAppSettings.standard().enableBubbleComponentLinkDetection = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,20 +41,16 @@ final class HomeserverConfigurationBuilder: NSObject {
|
||||
}
|
||||
|
||||
// Encryption configuration
|
||||
if let vectorWellKnownEncryptionConfig = vectorWellKnownEncryptionConfiguration {
|
||||
isE2EEByDefaultEnabled = vectorWellKnownEncryptionConfig.isE2EEByDefaultEnabled
|
||||
} else {
|
||||
// Enable E2EE by default when there is no value
|
||||
isE2EEByDefaultEnabled = true
|
||||
}
|
||||
// Enable E2EE by default when there is no value
|
||||
isE2EEByDefaultEnabled = vectorWellKnownEncryptionConfiguration?.isE2EEByDefaultEnabled ?? true
|
||||
|
||||
// Jitsi configuration
|
||||
let jitsiServerURL: URL
|
||||
let hardcodedJitsiServerURL: URL = BuildSettings.jitsiServerUrl
|
||||
|
||||
if let vectorWellKnownJitsiConfig = vectorWellKnownJitsiConfiguration {
|
||||
jitsiPreferredDomain = vectorWellKnownJitsiConfig.preferredDomain
|
||||
jitsiServerURL = self.jitsiServerURL(from: jitsiPreferredDomain) ?? hardcodedJitsiServerURL
|
||||
if let preferredDomain = vectorWellKnownJitsiConfiguration?.preferredDomain {
|
||||
jitsiPreferredDomain = preferredDomain
|
||||
jitsiServerURL = self.jitsiServerURL(from: preferredDomain) ?? hardcodedJitsiServerURL
|
||||
} else {
|
||||
guard let hardcodedJitsiDomain = hardcodedJitsiServerURL.host else {
|
||||
fatalError("[HomeserverConfigurationBuilder] Fail to get Jitsi domain from hardcoded Jitsi URL")
|
||||
|
||||
@@ -45,7 +45,7 @@ extension VectorWellKnown: Decodable {
|
||||
struct VectorWellKnownEncryptionConfiguration: Decodable {
|
||||
|
||||
/// Indicate if E2EE is enabled by default
|
||||
let isE2EEByDefaultEnabled: Bool
|
||||
let isE2EEByDefaultEnabled: Bool?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case isE2EEByDefaultEnabled = "default"
|
||||
@@ -56,5 +56,5 @@ struct VectorWellKnownEncryptionConfiguration: Decodable {
|
||||
struct VectorWellKnownJitsiConfiguration: Decodable {
|
||||
|
||||
/// Default Jitsi server
|
||||
let preferredDomain: String
|
||||
let preferredDomain: String?
|
||||
}
|
||||
|
||||
@@ -80,6 +80,9 @@ final class AppCoordinator: NSObject, AppCoordinatorType {
|
||||
self.setupLogger()
|
||||
self.setupTheme()
|
||||
|
||||
// Setup navigation router store
|
||||
_ = NavigationRouterStore.shared
|
||||
|
||||
if BuildSettings.enableSideMenu {
|
||||
self.addSideMenu()
|
||||
}
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
@protocol LegacyAppDelegateDelegate;
|
||||
@class CallBar;
|
||||
@class CallPresenter;
|
||||
@class RoomNavigationParameters;
|
||||
@class RoomPreviewNavigationParameters;
|
||||
@class UniversalLinkParameters;
|
||||
|
||||
#pragma mark - Notifications
|
||||
/**
|
||||
@@ -204,15 +207,24 @@ UINavigationControllerDelegate
|
||||
#pragma mark - Matrix Room handling
|
||||
|
||||
// Show a room and jump to the given event if event id is not nil otherwise go to last messages.
|
||||
- (void)showRoom:(NSString*)roomId andEventId:(NSString*)eventId withMatrixSession:(MXSession*)mxSession restoreInitialDisplay:(BOOL)restoreInitialDisplay completion:(void (^)(void))completion;
|
||||
- (void)showRoomWithParameters:(RoomNavigationParameters*)parameters completion:(void (^)(void))completion;
|
||||
|
||||
- (void)showRoom:(NSString*)roomId andEventId:(NSString*)eventId withMatrixSession:(MXSession*)mxSession restoreInitialDisplay:(BOOL)restoreInitialDisplay;
|
||||
- (void)showRoomWithParameters:(RoomNavigationParameters*)parameters;
|
||||
|
||||
// Restore display and show the room
|
||||
- (void)showRoom:(NSString*)roomId andEventId:(NSString*)eventId withMatrixSession:(MXSession*)mxSession;
|
||||
|
||||
// Creates a new direct chat with the provided user id
|
||||
- (void)createDirectChatWithUserId:(NSString*)userId completion:(void (^)(void))completion;
|
||||
|
||||
// Show room preview
|
||||
- (void)showRoomPreviewWithParameters:(RoomPreviewNavigationParameters*)parameters completion:(void (^)(void))completion;
|
||||
|
||||
- (void)showRoomPreviewWithParameters:(RoomPreviewNavigationParameters*)parameters;
|
||||
|
||||
// Restore display and show the room preview
|
||||
- (void)showRoomPreview:(RoomPreviewData*)roomPreviewData;
|
||||
|
||||
// Reopen an existing direct room with this userId or creates a new one (if it doesn't exist)
|
||||
- (void)startDirectChatWithUserId:(NSString*)userId completion:(void (^)(void))completion;
|
||||
|
||||
@@ -241,6 +253,14 @@ UINavigationControllerDelegate
|
||||
*/
|
||||
- (BOOL)handleUniversalLinkURL:(NSURL*)universalLinkURL;
|
||||
|
||||
/**
|
||||
Process universal link.
|
||||
|
||||
@param parameters the universal link parameters.
|
||||
@return YES in case of processing success.
|
||||
*/
|
||||
- (BOOL)handleUniversalLinkWithParameters:(UniversalLinkParameters*)parameters;
|
||||
|
||||
/**
|
||||
Extract params from the URL fragment part (after '#') of a vector.im Universal link:
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ NSString *const AppDelegateDidValidateEmailNotificationClientSecretKey = @"AppDe
|
||||
|
||||
NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUniversalLinkDidChangeNotification";
|
||||
|
||||
@interface LegacyAppDelegate () <GDPRConsentViewControllerDelegate, KeyVerificationCoordinatorBridgePresenterDelegate, ServiceTermsModalCoordinatorBridgePresenterDelegate, PushNotificationServiceDelegate, SetPinCoordinatorBridgePresenterDelegate, CallPresenterDelegate, SpaceDetailPresenterDelegate>
|
||||
@interface LegacyAppDelegate () <GDPRConsentViewControllerDelegate, KeyVerificationCoordinatorBridgePresenterDelegate, PushNotificationServiceDelegate, SetPinCoordinatorBridgePresenterDelegate, CallPresenterDelegate, SpaceDetailPresenterDelegate>
|
||||
{
|
||||
/**
|
||||
Reachability observer
|
||||
@@ -201,7 +201,6 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||
|
||||
@property (weak, nonatomic) UIAlertController *incomingKeyVerificationRequestAlertController;
|
||||
|
||||
@property (nonatomic, strong) ServiceTermsModalCoordinatorBridgePresenter *serviceTermsModalCoordinatorBridgePresenter;
|
||||
@property (nonatomic, strong) SlidingModalPresenter *slidingModalPresenter;
|
||||
@property (nonatomic, strong) SetPinCoordinatorBridgePresenter *setPinCoordinatorBridgePresenter;
|
||||
@property (nonatomic, strong) SpaceDetailPresenter *spaceDetailPresenter;
|
||||
@@ -674,9 +673,6 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||
// Register to GDPR consent not given notification
|
||||
[self registerUserConsentNotGivenNotification];
|
||||
|
||||
// Register to identity server terms not signed notification
|
||||
[self registerIdentityServiceTermsNotSignedNotification];
|
||||
|
||||
// Start monitoring reachability
|
||||
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
|
||||
|
||||
@@ -1240,8 +1236,24 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||
return [self handleUniversalLinkFragment:fragment fromURL:nil];
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)handleUniversalLinkFragment:(NSString*)fragment fromURL:(NSURL*)universalLinkURL
|
||||
|
||||
{
|
||||
ScreenPresentationParameters *presentationParameters = [[ScreenPresentationParameters alloc] initWithRestoreInitialDisplay:YES stackAboveVisibleViews:NO];
|
||||
|
||||
UniversalLinkParameters *parameters = [[UniversalLinkParameters alloc] initWithFragment:fragment universalLinkURL:universalLinkURL presentationParameters:presentationParameters];
|
||||
|
||||
return [self handleUniversalLinkWithParameters:parameters];
|
||||
}
|
||||
|
||||
- (BOOL)handleUniversalLinkWithParameters:(UniversalLinkParameters*)universalLinkParameters
|
||||
{
|
||||
NSString *fragment = universalLinkParameters.fragment;
|
||||
NSURL *universalLinkURL = universalLinkParameters.universalLinkURL;
|
||||
ScreenPresentationParameters *screenPresentationParameters = universalLinkParameters.presentationParameters;
|
||||
BOOL restoreInitialDisplay = screenPresentationParameters.restoreInitialDisplay;
|
||||
|
||||
BOOL continueUserActivity = NO;
|
||||
MXKAccountManager *accountManager = [MXKAccountManager sharedManager];
|
||||
|
||||
@@ -1342,26 +1354,23 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||
|
||||
if (room.summary.roomType == MXRoomTypeSpace)
|
||||
{
|
||||
[self restoreInitialDisplay:^{
|
||||
self.spaceDetailPresenter = [SpaceDetailPresenter new];
|
||||
self.spaceDetailPresenter.delegate = self;
|
||||
[self.spaceDetailPresenter presentForSpaceWithId:room.roomId from:self.masterNavigationController sourceView:nil session:account.mxSession animated:YES];
|
||||
}];
|
||||
SpaceNavigationParameters *spaceNavigationParameters = [[SpaceNavigationParameters alloc] initWithRoomId:room.roomId mxSession:account.mxSession presentationParameters:screenPresentationParameters];
|
||||
|
||||
[self showSpaceWithParameters:spaceNavigationParameters];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Open the room page
|
||||
[self showRoom:roomId andEventId:eventId withMatrixSession:account.mxSession];
|
||||
RoomNavigationParameters *roomNavigationParameters = [[RoomNavigationParameters alloc] initWithRoomId:roomId eventId:eventId mxSession:account.mxSession presentationParameters: screenPresentationParameters];
|
||||
|
||||
[self showRoomWithParameters:roomNavigationParameters];
|
||||
}
|
||||
|
||||
continueUserActivity = YES;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We will display something but we need to do some requests before.
|
||||
// So, come back to the home VC and show its loading wheel while processing
|
||||
[self restoreInitialDisplay:^{
|
||||
|
||||
void(^findRoom)(void) = ^{
|
||||
if ([_masterTabBarController.selectedViewController isKindOfClass:MXKActivityHandlingViewController.class])
|
||||
{
|
||||
MXKActivityHandlingViewController *homeViewController = (MXKActivityHandlingViewController*)_masterTabBarController.selectedViewController;
|
||||
@@ -1402,7 +1411,9 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||
{
|
||||
universalLinkFragmentPendingRoomAlias = @{roomId: roomIdOrAlias};
|
||||
|
||||
[self handleUniversalLinkFragment:newUniversalLinkFragment fromURL:universalLinkURL];
|
||||
UniversalLinkParameters *newParameters = [[UniversalLinkParameters alloc] initWithFragment:newUniversalLinkFragment universalLinkURL:universalLinkURL presentationParameters:screenPresentationParameters];
|
||||
|
||||
[self handleUniversalLinkWithParameters:newParameters];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1440,7 +1451,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||
if (notif.object == account.mxSession && account.mxSession.state == MXSessionStateRunning)
|
||||
{
|
||||
MXLogDebug(@"[AppDelegate] Universal link: The session is running. Retry the link");
|
||||
[self handleUniversalLinkFragment:fragment fromURL:universalLinkURL];
|
||||
[self handleUniversalLinkWithParameters:universalLinkParameters];
|
||||
}
|
||||
}
|
||||
}];
|
||||
@@ -1459,26 +1470,44 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||
roomPreviewData.viaServers = queryParams[@"via"];
|
||||
}
|
||||
|
||||
RoomPreviewNavigationParameters *roomPreviewNavigationParameters = [[RoomPreviewNavigationParameters alloc] initWithPreviewData:roomPreviewData presentationParameters:screenPresentationParameters];
|
||||
|
||||
[account.mxSession.matrixRestClient roomSummaryWith:roomIdOrAlias via:roomPreviewData.viaServers success:^(MXPublicRoom *room) {
|
||||
if ([room.roomTypeString isEqualToString:MXRoomTypeStringSpace])
|
||||
{
|
||||
[homeViewController stopActivityIndicator];
|
||||
|
||||
self.spaceDetailPresenter = [SpaceDetailPresenter new];
|
||||
self.spaceDetailPresenter.delegate = self;
|
||||
[self.spaceDetailPresenter presentForSpaceWithPublicRoom:room from:self.masterNavigationController sourceView:nil session:account.mxSession animated:YES];
|
||||
SpacePreviewNavigationParameters *spacePreviewNavigationParameters = [[SpacePreviewNavigationParameters alloc] initWithPublicRoom:room mxSession:account.mxSession presentationParameters:screenPresentationParameters];
|
||||
|
||||
[self showSpacePreviewWithParameters:spacePreviewNavigationParameters];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self peekInRoomWithId:roomIdOrAlias forPreviewData:roomPreviewData params:pathParams];
|
||||
[self peekInRoomWithNavigationParameters:roomPreviewNavigationParameters pathParams:pathParams];
|
||||
}
|
||||
} failure:^(NSError *error) {
|
||||
[self peekInRoomWithId:roomIdOrAlias forPreviewData:roomPreviewData params:pathParams];
|
||||
[self peekInRoomWithNavigationParameters:roomPreviewNavigationParameters pathParams:pathParams];
|
||||
}];
|
||||
}
|
||||
|
||||
}
|
||||
}];
|
||||
};
|
||||
|
||||
|
||||
// We will display something but we need to do some requests before.
|
||||
// So, come back to the home VC and show its loading wheel while processing
|
||||
|
||||
if (restoreInitialDisplay)
|
||||
{
|
||||
[self restoreInitialDisplay:^{
|
||||
findRoom();
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
findRoom();
|
||||
}
|
||||
|
||||
|
||||
// Let's say we are handling the case
|
||||
continueUserActivity = YES;
|
||||
@@ -1498,7 +1527,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||
if ([universalLinkFragmentPending isEqualToString:fragment])
|
||||
{
|
||||
MXLogDebug(@"[AppDelegate] Universal link: The user is now logged in. Retry the link");
|
||||
[self handleUniversalLinkFragment:fragment fromURL:universalLinkURL];
|
||||
[self handleUniversalLinkWithParameters:universalLinkParameters];
|
||||
}
|
||||
}];
|
||||
}
|
||||
@@ -1526,7 +1555,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||
|
||||
// Create the contact related to this member
|
||||
MXKContact *contact = [[MXKContact alloc] initMatrixContactWithDisplayName:displayName andMatrixID:userId];
|
||||
[self showContact:contact];
|
||||
[self showContact:contact presentationParameters:screenPresentationParameters];
|
||||
|
||||
continueUserActivity = YES;
|
||||
}
|
||||
@@ -1545,7 +1574,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||
}
|
||||
|
||||
// Display the group details
|
||||
[self showGroup:group withMatrixSession:account.mxSession];
|
||||
[self showGroup:group withMatrixSession:account.mxSession presentationParamters:screenPresentationParameters];
|
||||
|
||||
continueUserActivity = YES;
|
||||
}
|
||||
@@ -1563,7 +1592,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||
if ([universalLinkFragmentPending isEqualToString:fragment])
|
||||
{
|
||||
MXLogDebug(@"[AppDelegate] Universal link: The user is now logged in. Retry the link");
|
||||
[self handleUniversalLinkFragment:fragment fromURL:universalLinkURL];
|
||||
[self handleUniversalLinkWithParameters:universalLinkParameters];
|
||||
}
|
||||
}];
|
||||
}
|
||||
@@ -1581,7 +1610,10 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||
// Unknown command: Do nothing except coming back to the main screen
|
||||
MXLogDebug(@"[AppDelegate] Universal link: TODO: Do not know what to do with the link arguments: %@", pathParams);
|
||||
|
||||
[self popToHomeViewControllerAnimated:NO completion:nil];
|
||||
if (restoreInitialDisplay)
|
||||
{
|
||||
[self popToHomeViewControllerAnimated:NO completion:nil];
|
||||
}
|
||||
}
|
||||
|
||||
return continueUserActivity;
|
||||
@@ -1605,8 +1637,11 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||
}
|
||||
}
|
||||
|
||||
- (void)peekInRoomWithId:(NSString*)roomIdOrAlias forPreviewData:(RoomPreviewData *)roomPreviewData params:(NSArray<NSString*> *)pathParams
|
||||
- (void)peekInRoomWithNavigationParameters:(RoomPreviewNavigationParameters*)presentationParameters pathParams:(NSArray<NSString*> *)pathParams
|
||||
{
|
||||
RoomPreviewData *roomPreviewData = presentationParameters.previewData;
|
||||
NSString *roomIdOrAlias = presentationParameters.roomId;
|
||||
|
||||
// Is it a link to an event of a room?
|
||||
// If yes, the event will be displayed once the room is joined
|
||||
roomPreviewData.eventId = (pathParams.count >= 3) ? pathParams[2] : nil;
|
||||
@@ -1628,7 +1663,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||
}
|
||||
self->universalLinkFragmentPendingRoomAlias = nil;
|
||||
|
||||
[self showRoomPreview:roomPreviewData];
|
||||
[self showRoomPreviewWithParameters:presentationParameters];
|
||||
}];
|
||||
}
|
||||
|
||||
@@ -2786,8 +2821,17 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||
}
|
||||
}
|
||||
|
||||
- (void)showRoom:(NSString*)roomId andEventId:(NSString*)eventId withMatrixSession:(MXSession*)mxSession restoreInitialDisplay:(BOOL)restoreInitialDisplay completion:(void (^)(void))completion
|
||||
- (void)showRoomWithParameters:(RoomNavigationParameters*)parameters
|
||||
{
|
||||
[self showRoomWithParameters:parameters completion:nil];
|
||||
}
|
||||
|
||||
- (void)showRoomWithParameters:(RoomNavigationParameters*)parameters completion:(void (^)(void))completion
|
||||
{
|
||||
NSString *roomId = parameters.roomId;
|
||||
MXSession *mxSession = parameters.mxSession;
|
||||
BOOL restoreInitialDisplay = parameters.presentationParameters.restoreInitialDisplay;
|
||||
|
||||
if (roomId && mxSession)
|
||||
{
|
||||
MXRoom *room = [mxSession roomWithRoomId:roomId];
|
||||
@@ -2809,8 +2853,8 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||
|
||||
void (^selectRoom)(void) = ^() {
|
||||
// Select room to display its details (dispatch this action in order to let TabBarController end its refresh)
|
||||
[self.masterTabBarController selectRoomWithId:roomId andEventId:eventId inMatrixSession:mxSession completion:^{
|
||||
|
||||
|
||||
[self.masterTabBarController selectRoomWithParameters:parameters completion:^{
|
||||
// Remove delivered notifications for this room
|
||||
[self.pushNotificationService removeDeliveredNotificationsWithRoomId:roomId completion:nil];
|
||||
|
||||
@@ -2833,23 +2877,124 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||
}
|
||||
}
|
||||
|
||||
- (void)showRoom:(NSString*)roomId andEventId:(NSString*)eventId withMatrixSession:(MXSession*)mxSession restoreInitialDisplay:(BOOL)restoreInitialDisplay
|
||||
{
|
||||
[self showRoom:roomId andEventId:eventId withMatrixSession:mxSession restoreInitialDisplay:restoreInitialDisplay completion:nil];
|
||||
}
|
||||
|
||||
- (void)showRoom:(NSString*)roomId andEventId:(NSString*)eventId withMatrixSession:(MXSession*)mxSession
|
||||
{
|
||||
[self showRoom:roomId andEventId:eventId withMatrixSession:mxSession restoreInitialDisplay:YES completion:nil];
|
||||
// Ask to restore initial display
|
||||
ScreenPresentationParameters *presentationParameters = [[ScreenPresentationParameters alloc] initWithRestoreInitialDisplay:YES];
|
||||
|
||||
RoomNavigationParameters *parameters = [[RoomNavigationParameters alloc] initWithRoomId:roomId
|
||||
eventId:eventId mxSession:mxSession presentationParameters:presentationParameters];
|
||||
|
||||
[self showRoomWithParameters:parameters];
|
||||
}
|
||||
|
||||
- (void)showRoomPreviewWithParameters:(RoomPreviewNavigationParameters*)parameters completion:(void (^)(void))completion
|
||||
{
|
||||
void (^showRoomPreview)(void) = ^() {
|
||||
[self.masterTabBarController selectRoomPreviewWithParameters:parameters completion:completion];
|
||||
};
|
||||
|
||||
if (parameters.presentationParameters.restoreInitialDisplay)
|
||||
{
|
||||
[self restoreInitialDisplay:^{
|
||||
showRoomPreview();
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
showRoomPreview();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)showRoomPreviewWithParameters:(RoomPreviewNavigationParameters*)parameters
|
||||
{
|
||||
[self showRoomPreviewWithParameters:parameters completion:nil];
|
||||
}
|
||||
|
||||
- (void)showRoomPreview:(RoomPreviewData*)roomPreviewData
|
||||
{
|
||||
[self restoreInitialDisplay:^{
|
||||
|
||||
[_masterTabBarController showRoomPreview:roomPreviewData];
|
||||
|
||||
}];
|
||||
// Ask to restore initial display
|
||||
ScreenPresentationParameters *presentationParameters = [[ScreenPresentationParameters alloc] initWithRestoreInitialDisplay:YES];
|
||||
|
||||
RoomPreviewNavigationParameters *parameters = [[RoomPreviewNavigationParameters alloc] initWithPreviewData:roomPreviewData presentationParameters:presentationParameters];
|
||||
|
||||
[self showRoomPreviewWithParameters:parameters];
|
||||
}
|
||||
|
||||
- (void)showSpacePreviewWithParameters:(SpacePreviewNavigationParameters*)parameters
|
||||
{
|
||||
UIViewController *presentingViewController;
|
||||
UIView *sourceView;
|
||||
|
||||
if (parameters.presentationParameters.presentingViewController)
|
||||
{
|
||||
presentingViewController = parameters.presentationParameters.presentingViewController;
|
||||
sourceView = parameters.presentationParameters.sourceView;
|
||||
}
|
||||
else
|
||||
{
|
||||
presentingViewController = self.masterNavigationController;
|
||||
}
|
||||
|
||||
self.spaceDetailPresenter = [SpaceDetailPresenter new];
|
||||
self.spaceDetailPresenter.delegate = self;
|
||||
|
||||
void(^showSpace)(void) = ^{
|
||||
[self.spaceDetailPresenter presentForSpaceWithPublicRoom:parameters.publicRoom
|
||||
from:presentingViewController
|
||||
sourceView:sourceView
|
||||
session:parameters.mxSession
|
||||
animated:YES];
|
||||
};
|
||||
|
||||
if (parameters.presentationParameters.restoreInitialDisplay)
|
||||
{
|
||||
[self restoreInitialDisplay:^{
|
||||
showSpace();
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
showSpace();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)showSpaceWithParameters:(SpaceNavigationParameters*)parameters
|
||||
{
|
||||
UIViewController *presentingViewController;
|
||||
UIView *sourceView;
|
||||
|
||||
if (parameters.presentationParameters.presentingViewController)
|
||||
{
|
||||
presentingViewController = parameters.presentationParameters.presentingViewController;
|
||||
sourceView = parameters.presentationParameters.sourceView;
|
||||
}
|
||||
else
|
||||
{
|
||||
presentingViewController = self.masterNavigationController;
|
||||
}
|
||||
|
||||
self.spaceDetailPresenter = [SpaceDetailPresenter new];
|
||||
self.spaceDetailPresenter.delegate = self;
|
||||
|
||||
void(^showSpace)(void) = ^{
|
||||
[self.spaceDetailPresenter presentForSpaceWithId:parameters.roomId
|
||||
from:presentingViewController
|
||||
sourceView:sourceView
|
||||
session:parameters.mxSession
|
||||
animated:YES];
|
||||
};
|
||||
|
||||
if (parameters.presentationParameters.restoreInitialDisplay)
|
||||
{
|
||||
[self restoreInitialDisplay:^{
|
||||
showSpace();
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
showSpace();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setVisibleRoomId:(NSString *)roomId
|
||||
@@ -2964,25 +3109,43 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||
|
||||
#pragma mark - Contacts handling
|
||||
|
||||
- (void)showContact:(MXKContact*)contact
|
||||
- (void)showContact:(MXKContact*)contact presentationParameters:(ScreenPresentationParameters*)presentationParameters
|
||||
{
|
||||
[self restoreInitialDisplay:^{
|
||||
|
||||
[self.masterTabBarController selectContact:contact];
|
||||
|
||||
}];
|
||||
void(^showContact)(void) = ^{
|
||||
[self.masterTabBarController selectContact:contact withPresentationParameters:presentationParameters];
|
||||
};
|
||||
|
||||
if (presentationParameters.restoreInitialDisplay)
|
||||
{
|
||||
[self restoreInitialDisplay:^{
|
||||
showContact();
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
showContact();
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Matrix Groups handling
|
||||
|
||||
- (void)showGroup:(MXGroup*)group withMatrixSession:(MXSession*)mxSession
|
||||
- (void)showGroup:(MXGroup*)group withMatrixSession:(MXSession*)mxSession presentationParamters:(ScreenPresentationParameters*)presentationParameters
|
||||
{
|
||||
[self restoreInitialDisplay:^{
|
||||
|
||||
void(^showGroup)(void) = ^{
|
||||
// Select group to display its details (dispatch this action in order to let TabBarController end its refresh)
|
||||
[_masterTabBarController selectGroup:group inMatrixSession:mxSession];
|
||||
|
||||
}];
|
||||
[self.masterTabBarController selectGroup:group inMatrixSession:mxSession presentationParameters:presentationParameters];
|
||||
};
|
||||
|
||||
if (presentationParameters.restoreInitialDisplay)
|
||||
{
|
||||
[self restoreInitialDisplay:^{
|
||||
showGroup();
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
showGroup();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)promptForStunServerFallback
|
||||
@@ -4131,82 +4294,6 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Identity server service terms
|
||||
|
||||
// Observe identity server terms not signed notification
|
||||
- (void)registerIdentityServiceTermsNotSignedNotification
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleIdentityServiceTermsNotSignedNotification:) name:MXIdentityServiceTermsNotSignedNotification object:nil];
|
||||
}
|
||||
|
||||
- (void)handleIdentityServiceTermsNotSignedNotification:(NSNotification*)notification
|
||||
{
|
||||
MXLogDebug(@"[AppDelegate] IS Terms: handleIdentityServiceTermsNotSignedNotification.");
|
||||
|
||||
NSString *baseURL;
|
||||
NSString *accessToken;
|
||||
|
||||
MXJSONModelSetString(baseURL, notification.userInfo[MXIdentityServiceNotificationIdentityServerKey]);
|
||||
MXJSONModelSetString(accessToken, notification.userInfo[MXIdentityServiceNotificationAccessTokenKey]);
|
||||
|
||||
[self presentIdentityServerTermsWithBaseURL:baseURL andAccessToken:accessToken];
|
||||
}
|
||||
|
||||
- (void)presentIdentityServerTermsWithBaseURL:(NSString*)baseURL andAccessToken:(NSString*)accessToken
|
||||
{
|
||||
MXSession *mxSession = self.mxSessions.firstObject;
|
||||
|
||||
if (!mxSession || !baseURL || !accessToken || self.serviceTermsModalCoordinatorBridgePresenter.isPresenting)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ServiceTermsModalCoordinatorBridgePresenter *serviceTermsModalCoordinatorBridgePresenter = [[ServiceTermsModalCoordinatorBridgePresenter alloc] initWithSession:mxSession
|
||||
baseUrl:baseURL
|
||||
serviceType:MXServiceTypeIdentityService
|
||||
outOfContext:YES
|
||||
accessToken:accessToken];
|
||||
|
||||
serviceTermsModalCoordinatorBridgePresenter.delegate = self;
|
||||
|
||||
[serviceTermsModalCoordinatorBridgePresenter presentFrom:self.presentedViewController animated:YES];
|
||||
self.serviceTermsModalCoordinatorBridgePresenter = serviceTermsModalCoordinatorBridgePresenter;
|
||||
}
|
||||
|
||||
- (void)serviceTermsModalCoordinatorBridgePresenterDelegateDidAccept:(ServiceTermsModalCoordinatorBridgePresenter * _Nonnull)coordinatorBridgePresenter
|
||||
{
|
||||
[coordinatorBridgePresenter dismissWithAnimated:YES completion:^{
|
||||
|
||||
}];
|
||||
self.serviceTermsModalCoordinatorBridgePresenter = nil;
|
||||
}
|
||||
|
||||
- (void)serviceTermsModalCoordinatorBridgePresenterDelegateDidDecline:(ServiceTermsModalCoordinatorBridgePresenter *)coordinatorBridgePresenter session:(MXSession *)session
|
||||
{
|
||||
MXLogDebug(@"[AppDelegate] IS Terms: User has declined the use of the default IS.");
|
||||
|
||||
// The user does not want to use the proposed IS.
|
||||
// Disable IS feature on user's account
|
||||
[session setIdentityServer:nil andAccessToken:nil];
|
||||
[session setAccountDataIdentityServer:nil success:^{
|
||||
} failure:^(NSError *error) {
|
||||
MXLogDebug(@"[AppDelegate] IS Terms: Error: %@", error);
|
||||
}];
|
||||
|
||||
[coordinatorBridgePresenter dismissWithAnimated:YES completion:^{
|
||||
|
||||
}];
|
||||
self.serviceTermsModalCoordinatorBridgePresenter = nil;
|
||||
}
|
||||
|
||||
- (void)serviceTermsModalCoordinatorBridgePresenterDelegateDidCancel:(ServiceTermsModalCoordinatorBridgePresenter * _Nonnull)coordinatorBridgePresenter
|
||||
{
|
||||
[coordinatorBridgePresenter dismissWithAnimated:YES completion:^{
|
||||
|
||||
}];
|
||||
self.serviceTermsModalCoordinatorBridgePresenter = nil;
|
||||
}
|
||||
|
||||
#pragma mark - Settings
|
||||
|
||||
- (void)setupUserDefaults
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// Copyright 2021 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
|
||||
|
||||
/// Navigation parameters to display a room with a provided identifier in a specific matrix session.
|
||||
@objcMembers
|
||||
class RoomNavigationParameters: NSObject {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
/// The room identifier
|
||||
let roomId: String
|
||||
|
||||
/// If not nil, the room will be opened on this event.
|
||||
let eventId: String?
|
||||
|
||||
/// The Matrix session in which the room should be available.
|
||||
let mxSession: MXSession
|
||||
|
||||
/// Screen presentation parameters.
|
||||
let presentationParameters: ScreenPresentationParameters
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(roomId: String,
|
||||
eventId: String?,
|
||||
mxSession: MXSession,
|
||||
presentationParameters: ScreenPresentationParameters) {
|
||||
self.roomId = roomId
|
||||
self.eventId = eventId
|
||||
self.mxSession = mxSession
|
||||
self.presentationParameters = presentationParameters
|
||||
|
||||
super.init()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// Copyright 2021 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
|
||||
|
||||
/// Navigation parameters to display a preview of a room that is unknown for the user.
|
||||
/// This room can come from an email invitation link or a simple link to a room.
|
||||
@objcMembers
|
||||
class RoomPreviewNavigationParameters: RoomNavigationParameters {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
/// The data for the room preview
|
||||
let previewData: RoomPreviewData
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(previewData: RoomPreviewData, presentationParameters: ScreenPresentationParameters) {
|
||||
self.previewData = previewData
|
||||
|
||||
super.init(roomId: previewData.roomId,
|
||||
eventId: previewData.eventId,
|
||||
mxSession: previewData.mxSession,
|
||||
presentationParameters: presentationParameters)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// Copyright 2021 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
|
||||
|
||||
/// Screen presentation parameters used when a universal link is triggered
|
||||
@objcMembers
|
||||
class ScreenPresentationParameters: NSObject {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
/// Indicate to pop to home and restore initial view hierarchy
|
||||
let restoreInitialDisplay: Bool
|
||||
|
||||
/// Indicate to stack above visible views
|
||||
/// If this variable is set to true `restoreInitialDisplay` should be set to false to have effect
|
||||
let stackAboveVisibleViews: Bool
|
||||
|
||||
/// The object that triggers the universal link action.
|
||||
let sender: AnyObject?
|
||||
|
||||
/// The view containing the anchor rectangle for the popover. Useful for iPad if a universlink trigger a pop over.
|
||||
let sourceView: UIView?
|
||||
|
||||
/// The view controller from which the universal link is triggered. `nil` if triggered from some other kind of object.
|
||||
var presentingViewController: UIViewController? {
|
||||
return self.sender as? UIViewController
|
||||
}
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
init(restoreInitialDisplay: Bool,
|
||||
stackAboveVisibleViews: Bool,
|
||||
sender: AnyObject?,
|
||||
sourceView: UIView?) {
|
||||
self.restoreInitialDisplay = restoreInitialDisplay
|
||||
self.stackAboveVisibleViews = stackAboveVisibleViews
|
||||
self.sender = sender
|
||||
self.sourceView = sourceView
|
||||
|
||||
super.init()
|
||||
}
|
||||
|
||||
convenience init(restoreInitialDisplay: Bool, stackAboveVisibleViews: Bool) {
|
||||
self.init(restoreInitialDisplay: restoreInitialDisplay, stackAboveVisibleViews: stackAboveVisibleViews, sender: nil, sourceView: nil)
|
||||
}
|
||||
|
||||
/// In this initializer `stackAboveVisibleViews` is set to false`
|
||||
convenience init(restoreInitialDisplay: Bool) {
|
||||
self.init(restoreInitialDisplay: restoreInitialDisplay, stackAboveVisibleViews: false, sender: nil, sourceView: nil)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// Copyright 2021 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
|
||||
|
||||
/// Navigation parameters to display a space with a provided identifier in a specific matrix session.
|
||||
@objcMembers
|
||||
class SpaceNavigationParameters: NSObject {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
/// The room identifier
|
||||
let roomId: String
|
||||
|
||||
/// The Matrix session in which the room should be available.
|
||||
let mxSession: MXSession
|
||||
|
||||
/// Screen presentation parameters.
|
||||
let presentationParameters: ScreenPresentationParameters
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(roomId: String,
|
||||
mxSession: MXSession,
|
||||
presentationParameters: ScreenPresentationParameters) {
|
||||
self.roomId = roomId
|
||||
self.mxSession = mxSession
|
||||
self.presentationParameters = presentationParameters
|
||||
|
||||
super.init()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// Copyright 2021 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
|
||||
|
||||
/// Navigation parameters to display a preview of a space that is unknown for the user.
|
||||
@objcMembers
|
||||
class SpacePreviewNavigationParameters: SpaceNavigationParameters {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
/// The data for the room preview
|
||||
let publicRoom: MXPublicRoom
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
init(publicRoom: MXPublicRoom,
|
||||
mxSession: MXSession,
|
||||
presentationParameters: ScreenPresentationParameters) {
|
||||
self.publicRoom = publicRoom
|
||||
|
||||
super.init(roomId: publicRoom.roomId,
|
||||
mxSession: mxSession,
|
||||
presentationParameters: presentationParameters)
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,35 @@ final class Section: NSObject {
|
||||
|
||||
let tag: Int
|
||||
var rows: [Row]
|
||||
var headerTitle: String?
|
||||
var attributedHeaderTitle: NSAttributedString?
|
||||
var attributedFooterTitle: NSAttributedString?
|
||||
|
||||
var headerTitle: String? {
|
||||
get {
|
||||
attributedHeaderTitle?.string
|
||||
}
|
||||
set {
|
||||
guard let newValue = newValue else {
|
||||
attributedHeaderTitle = nil
|
||||
return
|
||||
}
|
||||
|
||||
attributedHeaderTitle = NSAttributedString(string: newValue)
|
||||
}
|
||||
}
|
||||
var footerTitle: String? {
|
||||
get {
|
||||
attributedFooterTitle?.string
|
||||
}
|
||||
set {
|
||||
guard let newValue = newValue else {
|
||||
attributedFooterTitle = nil
|
||||
return
|
||||
}
|
||||
|
||||
attributedFooterTitle = NSAttributedString(string: newValue)
|
||||
}
|
||||
}
|
||||
|
||||
init(withTag tag: Int) {
|
||||
self.tag = tag
|
||||
|
||||
@@ -19,20 +19,22 @@
|
||||
|
||||
#import "PublicRoomsDirectoryDataSource.h"
|
||||
|
||||
@protocol RecentsListServiceProtocol;
|
||||
@class DiscussionsCount;
|
||||
@class MXSpace;
|
||||
|
||||
/**
|
||||
List the different modes used to prepare the recents data source.
|
||||
Each mode corresponds to an application tab: Home, Favourites, People and Rooms.
|
||||
Used as the tag of UITableView, starting from 1 in order to avoid collision with default tag of UIView.
|
||||
*/
|
||||
typedef enum : NSUInteger
|
||||
typedef NS_ENUM(NSInteger, RecentsDataSourceMode)
|
||||
{
|
||||
RecentsDataSourceModeHome,
|
||||
RecentsDataSourceModeHome = 1,
|
||||
RecentsDataSourceModeFavourites,
|
||||
RecentsDataSourceModePeople,
|
||||
RecentsDataSourceModeRooms
|
||||
|
||||
} RecentsDataSourceMode;
|
||||
};
|
||||
|
||||
/**
|
||||
List the different secure backup banners that could be displayed.
|
||||
@@ -76,17 +78,40 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange;
|
||||
@property (nonatomic) NSInteger serverNoticeSection;
|
||||
@property (nonatomic) NSInteger suggestedRoomsSection;
|
||||
|
||||
@property (nonatomic, readonly) NSArray* invitesCellDataArray;
|
||||
@property (nonatomic, readonly) NSArray* favoriteCellDataArray;
|
||||
@property (nonatomic, readonly) NSArray* peopleCellDataArray;
|
||||
@property (nonatomic, readonly) NSArray* conversationCellDataArray;
|
||||
@property (nonatomic, readonly) NSArray* lowPriorityCellDataArray;
|
||||
@property (nonatomic, readonly) NSArray* serverNoticeCellDataArray;
|
||||
@property (nonatomic, readonly) NSArray* suggestedRoomCellDataArray;
|
||||
@property (nonatomic, readonly) NSInteger totalVisibleItemCount;
|
||||
|
||||
/**
|
||||
Counts for favorited rooms.
|
||||
*/
|
||||
@property (nonatomic, readonly) DiscussionsCount *favoriteMissedDiscussionsCount;
|
||||
|
||||
/**
|
||||
Counts for direct rooms.
|
||||
*/
|
||||
@property (nonatomic, readonly) DiscussionsCount *directMissedDiscussionsCount;
|
||||
|
||||
/**
|
||||
Counts for group rooms.
|
||||
*/
|
||||
@property (nonatomic, readonly) DiscussionsCount *groupMissedDiscussionsCount;
|
||||
|
||||
@property (nonatomic, readonly) SecureBackupBannerDisplay secureBackupBannerDisplay;
|
||||
@property (nonatomic, readonly) CrossSigningBannerDisplay crossSigningBannerDisplay;
|
||||
|
||||
@property (nonatomic, readonly) id<RecentsListServiceProtocol> recentsListService;
|
||||
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
- (instancetype)initWithMatrixSession:(MXSession*)mxSession NS_UNAVAILABLE;
|
||||
|
||||
/**
|
||||
Initializer
|
||||
@param mxSession session instance
|
||||
@param recentsListService service instance
|
||||
*/
|
||||
- (instancetype)initWithMatrixSession:(MXSession*)mxSession
|
||||
recentsListService:(id<RecentsListServiceProtocol>)recentsListService;
|
||||
|
||||
/**
|
||||
Set the delegate by specifying the selected display mode.
|
||||
*/
|
||||
@@ -163,44 +188,4 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange;
|
||||
*/
|
||||
- (void)moveRoomCell:(MXRoom*)room from:(NSIndexPath*)oldPath to:(NSIndexPath*)newPath success:(void (^)(void))moveSuccess failure:(void (^)(NSError *error))moveFailure;
|
||||
|
||||
/**
|
||||
The current number of the favourite rooms with missed notifications.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger missedFavouriteDiscussionsCount;
|
||||
|
||||
/**
|
||||
The current number of the favourite rooms with unread highlighted messages.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger missedHighlightFavouriteDiscussionsCount;
|
||||
|
||||
/**
|
||||
The current number of the direct chats with missed notifications, including the invites.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger missedDirectDiscussionsCount;
|
||||
|
||||
/**
|
||||
The current number of the direct chats with unread highlighted messages.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger missedHighlightDirectDiscussionsCount;
|
||||
|
||||
/**
|
||||
The current number of the direct chats with unsent messages.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger unsentMessagesDirectDiscussionsCount;
|
||||
|
||||
/**
|
||||
The current number of the group chats with missed notifications, including the invites.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger missedGroupDiscussionsCount;
|
||||
|
||||
/**
|
||||
The current number of the group chats with unread highlighted messages.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger missedHighlightGroupDiscussionsCount;
|
||||
|
||||
/**
|
||||
The current number of the group chats with unsent messages.
|
||||
*/
|
||||
@property (nonatomic, readonly) NSUInteger unsentMessagesGroupDiscussionsCount;
|
||||
|
||||
@end
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#import "MXRoom+Riot.h"
|
||||
#import "MXSession+Riot.h"
|
||||
#import "NSArray+Element.h"
|
||||
|
||||
#import "Riot-Swift.h"
|
||||
|
||||
@@ -40,9 +41,8 @@
|
||||
|
||||
NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSourceTapOnDirectoryServerChange";
|
||||
|
||||
@interface RecentsDataSource() <SecureBackupBannerCellDelegate, CrossSigningSetupBannerCellDelegate>
|
||||
@interface RecentsDataSource() <SecureBackupBannerCellDelegate, CrossSigningSetupBannerCellDelegate, RecentsListServiceDelegate>
|
||||
{
|
||||
RecentsDataSourceState *state;
|
||||
dispatch_queue_t processingQueue;
|
||||
|
||||
NSInteger shrinkedSectionsBitMask;
|
||||
@@ -56,6 +56,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
@property (nonatomic, assign, readwrite) SecureBackupBannerDisplay secureBackupBannerDisplay;
|
||||
@property (nonatomic, assign, readwrite) CrossSigningBannerDisplay crossSigningBannerDisplay;
|
||||
|
||||
@property (nonatomic, readwrite) id<RecentsListServiceProtocol> recentsListService;
|
||||
|
||||
@property (nonatomic, strong) CrossSigningService *crossSigningService;
|
||||
|
||||
@end
|
||||
@@ -64,10 +66,10 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
@synthesize directorySection, invitesSection, favoritesSection, peopleSection, conversationSection, lowPrioritySection, serverNoticeSection, suggestedRoomsSection, secureBackupBannerSection, crossSigningBannerSection;
|
||||
@synthesize hiddenCellIndexPath, droppingCellIndexPath, droppingCellBackGroundView;
|
||||
|
||||
- (instancetype)init
|
||||
- (instancetype)initWithMatrixSession:(MXSession *)mxSession
|
||||
recentsListService:(id<RecentsListServiceProtocol>)theRecentsListService
|
||||
{
|
||||
self = [super init];
|
||||
if (self)
|
||||
if (self = [super initWithMatrixSession:mxSession])
|
||||
{
|
||||
processingQueue = dispatch_queue_create("RecentsDataSource", DISPATCH_QUEUE_SERIAL);
|
||||
|
||||
@@ -87,6 +89,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
[self registerCellDataClass:RecentCellData.class forCellIdentifier:kMXKRecentCellIdentifier];
|
||||
|
||||
[self registerSpaceServiceDidBuildGraphNotification];
|
||||
self.recentsListService = theRecentsListService;
|
||||
[self.recentsListService addDelegate:self];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -112,69 +116,53 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
|
||||
#pragma mark - Properties
|
||||
|
||||
- (NSArray *)invitesCellDataArray
|
||||
- (NSArray<id<MXRoomSummaryProtocol>> *)invitesCellDataArray
|
||||
{
|
||||
return state.invitesCellDataArray;
|
||||
return self.recentsListService.invitedRoomListData.rooms;
|
||||
}
|
||||
- (NSArray *)favoriteCellDataArray
|
||||
- (NSArray<id<MXRoomSummaryProtocol>> *)favoriteCellDataArray
|
||||
{
|
||||
return state.favoriteCellDataArray;
|
||||
return self.recentsListService.favoritedRoomListData.rooms;
|
||||
}
|
||||
- (NSArray *)peopleCellDataArray
|
||||
- (NSArray<id<MXRoomSummaryProtocol>> *)peopleCellDataArray
|
||||
{
|
||||
return state.peopleCellDataArray;
|
||||
return self.recentsListService.peopleRoomListData.rooms;
|
||||
}
|
||||
- (NSArray *)conversationCellDataArray
|
||||
- (NSArray<id<MXRoomSummaryProtocol>> *)conversationCellDataArray
|
||||
{
|
||||
return state.conversationCellDataArray;
|
||||
return self.recentsListService.conversationRoomListData.rooms;
|
||||
}
|
||||
- (NSArray *)lowPriorityCellDataArray
|
||||
- (NSArray<id<MXRoomSummaryProtocol>> *)lowPriorityCellDataArray
|
||||
{
|
||||
return state.lowPriorityCellDataArray;
|
||||
return self.recentsListService.lowPriorityRoomListData.rooms;
|
||||
}
|
||||
- (NSArray *)serverNoticeCellDataArray
|
||||
- (NSArray<id<MXRoomSummaryProtocol>> *)serverNoticeCellDataArray
|
||||
{
|
||||
return state.serverNoticeCellDataArray;
|
||||
return self.recentsListService.serverNoticeRoomListData.rooms;
|
||||
}
|
||||
- (NSArray *)suggestedRoomCellDataArray
|
||||
- (NSArray<id<MXRoomSummaryProtocol>> *)suggestedRoomCellDataArray
|
||||
{
|
||||
return state.suggestedRoomCellDataArray;
|
||||
return self.recentsListService.suggestedRoomListData.rooms;
|
||||
}
|
||||
|
||||
- (NSUInteger)missedFavouriteDiscussionsCount
|
||||
- (NSInteger)totalVisibleItemCount
|
||||
{
|
||||
return state.favouriteMissedDiscussionsCount.count;
|
||||
}
|
||||
- (NSUInteger)missedHighlightFavouriteDiscussionsCount
|
||||
{
|
||||
return state.favouriteMissedDiscussionsCount.highlightCount;
|
||||
return self.recentsListService.totalVisibleItemCount;
|
||||
}
|
||||
|
||||
- (NSUInteger)missedDirectDiscussionsCount
|
||||
- (DiscussionsCount *)favoriteMissedDiscussionsCount
|
||||
{
|
||||
return state.directMissedDiscussionsCount.count;
|
||||
}
|
||||
- (NSUInteger)missedHighlightDirectDiscussionsCount
|
||||
{
|
||||
return state.directMissedDiscussionsCount.highlightCount;
|
||||
return self.recentsListService.favoritedMissedDiscussionsCount;
|
||||
}
|
||||
|
||||
- (NSUInteger)missedGroupDiscussionsCount
|
||||
- (DiscussionsCount *)directMissedDiscussionsCount
|
||||
{
|
||||
return state.groupMissedDiscussionsCount.count;
|
||||
}
|
||||
- (NSUInteger)groupMissedDiscussionsCount
|
||||
{
|
||||
return state.favouriteMissedDiscussionsCount.highlightCount;
|
||||
return self.recentsListService.peopleMissedDiscussionsCount;
|
||||
}
|
||||
|
||||
- (NSUInteger)unsentMessagesDirectDiscussionsCount
|
||||
- (DiscussionsCount *)groupMissedDiscussionsCount
|
||||
{
|
||||
return state.unsentMessagesDirectDiscussionsCount;
|
||||
}
|
||||
- (NSUInteger)unsentMessagesGroupDiscussionsCount
|
||||
{
|
||||
return state.unsentMessagesGroupDiscussionsCount;
|
||||
return self.recentsListService.conversationMissedDiscussionsCount;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
@@ -201,8 +189,13 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
}
|
||||
|
||||
[self updateSecureBackupBanner];
|
||||
[self forceRefresh];
|
||||
[self refreshCrossSigningBannerDisplay];
|
||||
[self.recentsListService updateMode:_recentsDataSourceMode];
|
||||
}
|
||||
|
||||
- (void)setCurrentSpace:(MXSpace *)currentSpace
|
||||
{
|
||||
[self.recentsListService updateSpace:currentSpace];
|
||||
}
|
||||
|
||||
- (UIView *)viewForStickyHeaderInSection:(NSInteger)section withFrame:(CGRect)frame
|
||||
@@ -449,10 +442,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
// Refresh is disabled during drag&drop animation"
|
||||
if (!self.droppingCellIndexPath)
|
||||
{
|
||||
[self refreshRoomsSection:^{
|
||||
// And inform the delegate about the update
|
||||
[self.delegate dataSource:self didCellChange:nil];
|
||||
}];
|
||||
[self.recentsListService refresh];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,13 +492,13 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
favoritesSection = sectionsCount++;
|
||||
}
|
||||
|
||||
if (_recentsDataSourceMode == RecentsDataSourceModeHome)
|
||||
if (self.peopleCellDataArray.count > 0 || _recentsDataSourceMode == RecentsDataSourceModeHome)
|
||||
{
|
||||
peopleSection = sectionsCount++;
|
||||
}
|
||||
|
||||
// Keep visible the main rooms section even if it is empty, except on favourites screen.
|
||||
if (_recentsDataSourceMode != RecentsDataSourceModeFavourites)
|
||||
if (self.conversationCellDataArray.count > 0 || _recentsDataSourceMode == RecentsDataSourceModeHome)
|
||||
{
|
||||
conversationSection = sectionsCount++;
|
||||
}
|
||||
@@ -696,61 +686,54 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
- (UIView *)badgeViewForHeaderTitleInHomeSection:(NSInteger)section
|
||||
{
|
||||
// Prepare a badge to display the total of missed notifications in this section.
|
||||
NSUInteger count = 0;
|
||||
NSArray *sectionArray;
|
||||
id<MXRoomListDataCounts> counts = nil;
|
||||
UIView *missedNotifAndUnreadBadgeBgView = nil;
|
||||
|
||||
if (section == favoritesSection)
|
||||
{
|
||||
sectionArray = self.favoriteCellDataArray;
|
||||
counts = self.recentsListService.favoritedRoomListData.counts;
|
||||
}
|
||||
else if (section == peopleSection)
|
||||
{
|
||||
sectionArray = self.peopleCellDataArray;
|
||||
counts = self.recentsListService.peopleRoomListData.counts;
|
||||
}
|
||||
else if (section == conversationSection)
|
||||
{
|
||||
sectionArray = self.conversationCellDataArray;
|
||||
counts = self.recentsListService.conversationRoomListData.counts;
|
||||
}
|
||||
else if (section == lowPrioritySection)
|
||||
{
|
||||
sectionArray = self.lowPriorityCellDataArray;
|
||||
counts = self.recentsListService.lowPriorityRoomListData.counts;
|
||||
}
|
||||
else if (section == serverNoticeSection)
|
||||
{
|
||||
sectionArray = self.serverNoticeCellDataArray;
|
||||
counts = self.recentsListService.serverNoticeRoomListData.counts;
|
||||
}
|
||||
else if (section == suggestedRoomsSection)
|
||||
{
|
||||
sectionArray = self.suggestedRoomCellDataArray;
|
||||
counts = self.recentsListService.suggestedRoomListData.counts;
|
||||
}
|
||||
|
||||
BOOL highlight = NO;
|
||||
for (id<MXKRecentCellDataStoring> cellData in sectionArray)
|
||||
{
|
||||
count += cellData.notificationCount;
|
||||
highlight |= (cellData.highlightCount > 0);
|
||||
}
|
||||
|
||||
if (count)
|
||||
if (counts.numberOfNotifications)
|
||||
{
|
||||
UILabel *missedNotifAndUnreadBadgeLabel = [[UILabel alloc] init];
|
||||
missedNotifAndUnreadBadgeLabel.textColor = ThemeService.shared.theme.baseTextPrimaryColor;
|
||||
missedNotifAndUnreadBadgeLabel.font = [UIFont boldSystemFontOfSize:14];
|
||||
if (count > 1000)
|
||||
if (counts.numberOfNotifications > 1000)
|
||||
{
|
||||
CGFloat value = count / 1000.0;
|
||||
CGFloat value = counts.numberOfNotifications / 1000.0;
|
||||
missedNotifAndUnreadBadgeLabel.text = [VectorL10n largeBadgeValueKFormat:value];
|
||||
}
|
||||
else
|
||||
{
|
||||
missedNotifAndUnreadBadgeLabel.text = [NSString stringWithFormat:@"%tu", count];
|
||||
missedNotifAndUnreadBadgeLabel.text = [NSString stringWithFormat:@"%tu", counts.numberOfNotifications];
|
||||
}
|
||||
|
||||
[missedNotifAndUnreadBadgeLabel sizeToFit];
|
||||
|
||||
CGFloat bgViewWidth = missedNotifAndUnreadBadgeLabel.frame.size.width + 18;
|
||||
|
||||
BOOL highlight = counts.numberOfHighlights > 0;
|
||||
missedNotifAndUnreadBadgeBgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, bgViewWidth, 20)];
|
||||
[missedNotifAndUnreadBadgeBgView.layer setCornerRadius:10];
|
||||
missedNotifAndUnreadBadgeBgView.backgroundColor = highlight ? ThemeService.shared.theme.noticeColor : ThemeService.shared.theme.noticeSecondaryColor;
|
||||
@@ -954,7 +937,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
|
||||
- (id<MXKRecentCellDataStoring>)cellDataAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
id<MXKRecentCellDataStoring> cellData = nil;
|
||||
id<MXRoomSummaryProtocol> summary = nil;
|
||||
NSUInteger cellDataIndex = indexPath.row;
|
||||
NSInteger tableSection = indexPath.section;
|
||||
|
||||
@@ -972,53 +955,57 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
{
|
||||
if (cellDataIndex < self.favoriteCellDataArray.count)
|
||||
{
|
||||
cellData = self.favoriteCellDataArray[cellDataIndex];
|
||||
summary = self.favoriteCellDataArray[cellDataIndex];
|
||||
}
|
||||
}
|
||||
else if (tableSection == peopleSection)
|
||||
{
|
||||
if (cellDataIndex < self.peopleCellDataArray.count)
|
||||
{
|
||||
cellData = self.peopleCellDataArray[cellDataIndex];
|
||||
summary = self.peopleCellDataArray[cellDataIndex];
|
||||
}
|
||||
}
|
||||
else if (tableSection== conversationSection)
|
||||
{
|
||||
if (cellDataIndex < self.conversationCellDataArray.count)
|
||||
{
|
||||
cellData = self.conversationCellDataArray[cellDataIndex];
|
||||
summary = self.conversationCellDataArray[cellDataIndex];
|
||||
}
|
||||
}
|
||||
else if (tableSection == lowPrioritySection)
|
||||
{
|
||||
if (cellDataIndex < self.lowPriorityCellDataArray.count)
|
||||
{
|
||||
cellData = self.lowPriorityCellDataArray[cellDataIndex];
|
||||
summary = self.lowPriorityCellDataArray[cellDataIndex];
|
||||
}
|
||||
}
|
||||
else if (tableSection == serverNoticeSection)
|
||||
{
|
||||
if (cellDataIndex < self.serverNoticeCellDataArray.count)
|
||||
{
|
||||
cellData = self.serverNoticeCellDataArray[cellDataIndex];
|
||||
summary = self.serverNoticeCellDataArray[cellDataIndex];
|
||||
}
|
||||
}
|
||||
else if (tableSection == invitesSection)
|
||||
{
|
||||
if (cellDataIndex < self.invitesCellDataArray.count)
|
||||
{
|
||||
cellData = self.invitesCellDataArray[cellDataIndex];
|
||||
summary = self.invitesCellDataArray[cellDataIndex];
|
||||
}
|
||||
}
|
||||
else if (tableSection == suggestedRoomsSection)
|
||||
{
|
||||
if (cellDataIndex < self.suggestedRoomCellDataArray.count)
|
||||
{
|
||||
cellData = self.suggestedRoomCellDataArray[cellDataIndex];
|
||||
summary = self.suggestedRoomCellDataArray[cellDataIndex];
|
||||
}
|
||||
}
|
||||
|
||||
return cellData;
|
||||
if (summary)
|
||||
{
|
||||
return [[MXKRecentCellData alloc] initWithRoomSummary:summary dataSource:self];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (CGFloat)cellHeightAtIndexPath:(NSIndexPath *)indexPath
|
||||
@@ -1065,32 +1052,15 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (NSInteger)cellIndexPosWithRoomId:(NSString*)roomId andMatrixSession:(MXSession*)matrixSession within:(NSArray*)cellDataArray
|
||||
- (NSInteger)cellIndexPosWithRoomId:(NSString*)roomId andMatrixSession:(MXSession*)matrixSession within:(NSArray<id<MXRoomSummaryProtocol>> *)summaries
|
||||
{
|
||||
if (roomId && matrixSession && cellDataArray.count)
|
||||
if (!roomId || !matrixSession || !summaries.count || self.mxSession != matrixSession)
|
||||
{
|
||||
for (int index = 0; index < cellDataArray.count; index++)
|
||||
{
|
||||
id<MXKRecentCellDataStoring> cellDataStoring = cellDataArray[index];
|
||||
|
||||
if (cellDataStoring.roomSummary)
|
||||
{
|
||||
if ([roomId isEqualToString:cellDataStoring.roomSummary.roomId] && (matrixSession == cellDataStoring.roomSummary.room.mxSession))
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
else if (cellDataStoring.spaceChildInfo)
|
||||
{
|
||||
if ([roomId isEqualToString:cellDataStoring.spaceChildInfo.name])
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NSNotFound;
|
||||
}
|
||||
|
||||
return NSNotFound;
|
||||
return [summaries indexOfObjectPassingTest:^BOOL(id<MXRoomSummaryProtocol> _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
return [obj.roomId isEqualToString:roomId];
|
||||
}];
|
||||
}
|
||||
|
||||
- (NSIndexPath*)cellIndexPathWithRoomId:(NSString*)roomId andMatrixSession:(MXSession*)matrixSession
|
||||
@@ -1206,427 +1176,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
return indexPath;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - MXKDataSourceDelegate
|
||||
|
||||
- (void)refreshRoomsSection:(void (^)(void))onComplete
|
||||
{
|
||||
if (displayedRecentsDataSourceArray.count > 0)
|
||||
{
|
||||
// FIXME manage multi accounts
|
||||
MXKSessionRecentsDataSource *recentsDataSource = displayedRecentsDataSourceArray[0];
|
||||
|
||||
NSMutableArray<id<MXKRecentCellDataStoring>> *cells = [NSMutableArray new];
|
||||
NSInteger count = recentsDataSource.numberOfCells;
|
||||
|
||||
for (NSUInteger index = 0; index < count; index++)
|
||||
{
|
||||
id<MXKRecentCellDataStoring> cell = [recentsDataSource cellDataAtIndex:index];
|
||||
[cells addObject:cell];
|
||||
}
|
||||
|
||||
MXWeakify(self);
|
||||
[self computeStateAsyncWithCells:cells recentsDataSourceMode:self.recentsDataSourceMode matrixSession:recentsDataSource.mxSession onComplete:^(RecentsDataSourceState *newState) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
self->state = newState;
|
||||
onComplete();
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
onComplete();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)computeStateAsyncWithCells:(NSArray<id<MXKRecentCellDataStoring>> *)cells
|
||||
recentsDataSourceMode:(RecentsDataSourceMode)recentsDataSourceMode
|
||||
matrixSession:(MXSession*)mxSession
|
||||
onComplete:(void (^)(RecentsDataSourceState *newState))onComplete
|
||||
{
|
||||
dispatch_async(processingQueue, ^{
|
||||
RecentsDataSourceState *newState = [RecentsDataSource computeStateWithCells:cells recentsDataSourceMode:recentsDataSourceMode matrixSession:mxSession];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
onComplete(newState);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
+ (RecentsDataSourceState *)computeStateWithCells:(NSArray<id<MXKRecentCellDataStoring>> *)cells
|
||||
recentsDataSourceMode:(RecentsDataSourceMode)recentsDataSourceMode
|
||||
matrixSession:(MXSession*)mxSession
|
||||
{
|
||||
NSDate *startDate = [NSDate date];
|
||||
|
||||
NSMutableArray<id<MXKRecentCellDataStoring>> *invitesCellDataArray = [NSMutableArray new];
|
||||
NSMutableArray<id<MXKRecentCellDataStoring>> *favoriteCellDataArray = [NSMutableArray new];
|
||||
NSMutableArray<id<MXKRecentCellDataStoring>> *peopleCellDataArray = [NSMutableArray new];
|
||||
NSMutableArray<id<MXKRecentCellDataStoring>> *conversationCellDataArray = [NSMutableArray new];
|
||||
NSMutableArray<id<MXKRecentCellDataStoring>> *lowPriorityCellDataArray = [NSMutableArray new];
|
||||
NSMutableArray<id<MXKRecentCellDataStoring>> *serverNoticeCellDataArray = [NSMutableArray new];
|
||||
NSMutableArray<id<MXKRecentCellDataStoring>> *suggestedRoomCellDataArray = [NSMutableArray new];
|
||||
|
||||
MissedDiscussionsCount *favouriteMissedDiscussionsCount = [MissedDiscussionsCount new];
|
||||
MissedDiscussionsCount *directMissedDiscussionsCount = [MissedDiscussionsCount new];
|
||||
MissedDiscussionsCount *groupMissedDiscussionsCount = [MissedDiscussionsCount new];
|
||||
NSUInteger unsentMessagesDirectDiscussionsCount = 0;
|
||||
NSUInteger unsentMessagesGroupDiscussionsCount = 0;
|
||||
|
||||
for (id<MXKRecentCellDataStoring> recentCellDataStoring in cells)
|
||||
{
|
||||
MXRoom* room = recentCellDataStoring.roomSummary.room;
|
||||
|
||||
if (recentsDataSourceMode == RecentsDataSourceModeHome)
|
||||
{
|
||||
if (room.accountData.tags[kMXRoomTagServerNotice])
|
||||
{
|
||||
[serverNoticeCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
else if (room.accountData.tags[kMXRoomTagFavourite])
|
||||
{
|
||||
[favoriteCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
else if (room.accountData.tags[kMXRoomTagLowPriority])
|
||||
{
|
||||
[lowPriorityCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
else if (room.summary.membership == MXMembershipInvite)
|
||||
{
|
||||
if (room.summary.roomType != MXRoomTypeSpace && !MXSDKOptions.sharedInstance.autoAcceptRoomInvites)
|
||||
{
|
||||
[invitesCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
}
|
||||
else if (room.isDirect)
|
||||
{
|
||||
[peopleCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
else if (recentCellDataStoring.isSuggestedRoom && recentCellDataStoring.spaceChildInfo.roomType != MXRoomTypeSpace)
|
||||
{
|
||||
MXRoomSummary *roomSummary = [mxSession roomSummaryWithRoomId:recentCellDataStoring.spaceChildInfo.childRoomId];
|
||||
if (!roomSummary.isJoined)
|
||||
{
|
||||
[suggestedRoomCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hide spaces from home (keep space invites)
|
||||
if (room.summary.roomType != MXRoomTypeSpace)
|
||||
{
|
||||
[conversationCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (recentsDataSourceMode == RecentsDataSourceModeFavourites)
|
||||
{
|
||||
// Keep only the favourites rooms.
|
||||
if (room.accountData.tags[kMXRoomTagFavourite])
|
||||
{
|
||||
[favoriteCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
}
|
||||
else if (recentsDataSourceMode == RecentsDataSourceModePeople)
|
||||
{
|
||||
// Keep only the direct rooms which are not low priority
|
||||
if (room.isDirect && !room.accountData.tags[kMXRoomTagLowPriority])
|
||||
{
|
||||
if (room.summary.membership == MXMembershipInvite)
|
||||
{
|
||||
if (!MXSDKOptions.sharedInstance.autoAcceptRoomInvites)
|
||||
{
|
||||
[invitesCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
[conversationCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (recentsDataSourceMode == RecentsDataSourceModeRooms)
|
||||
{
|
||||
if (recentCellDataStoring.isSuggestedRoom && recentCellDataStoring.spaceChildInfo.roomType != MXRoomTypeSpace)
|
||||
{
|
||||
MXRoomSummary *roomSummary = [mxSession roomSummaryWithRoomId:recentCellDataStoring.spaceChildInfo.childRoomId];
|
||||
BOOL isJoined = roomSummary.membership == MXMembershipJoin || roomSummary.membershipTransitionState == MXMembershipTransitionStateJoined;
|
||||
if (!isJoined)
|
||||
{
|
||||
[suggestedRoomCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
}
|
||||
// Consider only non direct rooms.
|
||||
else if (!room.isDirect)
|
||||
{
|
||||
// Keep only the invites, the favourites and the rooms without tag and room type different from space
|
||||
if (room.summary.membership == MXMembershipInvite)
|
||||
{
|
||||
if (room.summary.roomType != MXRoomTypeSpace && !MXSDKOptions.sharedInstance.autoAcceptRoomInvites)
|
||||
{
|
||||
[invitesCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
}
|
||||
else if ((!room.accountData.tags.count || room.accountData.tags[kMXRoomTagFavourite]) && room.summary.roomType != MXRoomTypeSpace)
|
||||
{
|
||||
[conversationCellDataArray addObject:recentCellDataStoring];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update missed conversations counts
|
||||
NSUInteger notificationCount = recentCellDataStoring.roomSummary.notificationCount;
|
||||
|
||||
// Ignore the regular notification count if the room is in 'mentions only" mode at the Riot level.
|
||||
if (room.isMentionsOnly)
|
||||
{
|
||||
// Only the highlighted missed messages must be considered here.
|
||||
notificationCount = recentCellDataStoring.roomSummary.highlightCount;
|
||||
}
|
||||
|
||||
if (notificationCount)
|
||||
{
|
||||
if (room.accountData.tags[kMXRoomTagFavourite])
|
||||
{
|
||||
favouriteMissedDiscussionsCount.count ++;
|
||||
|
||||
if (recentCellDataStoring.roomSummary.highlightCount)
|
||||
{
|
||||
favouriteMissedDiscussionsCount.highlightCount ++;
|
||||
}
|
||||
}
|
||||
|
||||
if (room.isDirect)
|
||||
{
|
||||
directMissedDiscussionsCount.count ++;
|
||||
|
||||
if (recentCellDataStoring.roomSummary.highlightCount)
|
||||
{
|
||||
directMissedDiscussionsCount.highlightCount ++;
|
||||
}
|
||||
}
|
||||
else if (!room.accountData.tags.count || room.accountData.tags[kMXRoomTagFavourite])
|
||||
{
|
||||
groupMissedDiscussionsCount.count ++;
|
||||
|
||||
if (recentCellDataStoring.roomSummary.highlightCount)
|
||||
{
|
||||
groupMissedDiscussionsCount.highlightCount ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (room.summary.membership == MXMembershipInvite)
|
||||
{
|
||||
if (room.isDirect)
|
||||
{
|
||||
directMissedDiscussionsCount.count ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
groupMissedDiscussionsCount.highlightCount ++;
|
||||
}
|
||||
}
|
||||
|
||||
if (room.sentStatus != RoomSentStatusOk)
|
||||
{
|
||||
if (room.isDirect)
|
||||
{
|
||||
unsentMessagesDirectDiscussionsCount ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsentMessagesGroupDiscussionsCount ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (recentsDataSourceMode == RecentsDataSourceModeHome)
|
||||
{
|
||||
BOOL pinMissedNotif = RiotSettings.shared.pinRoomsWithMissedNotificationsOnHome;
|
||||
BOOL pinUnread = RiotSettings.shared.pinRoomsWithUnreadMessagesOnHome;
|
||||
NSComparator comparator = nil;
|
||||
|
||||
if (pinMissedNotif)
|
||||
{
|
||||
// Sort each rooms collection by considering first the rooms with some missed notifs, the rooms with unread, then the others.
|
||||
comparator = ^NSComparisonResult(id<MXKRecentCellDataStoring> recentCellData1, id<MXKRecentCellDataStoring> recentCellData2) {
|
||||
|
||||
if (recentCellData1.spaceChildInfo && !recentCellData2.spaceChildInfo)
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
if (recentCellData2.spaceChildInfo && !recentCellData1.spaceChildInfo)
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
|
||||
if (recentCellData1.roomSummary.room.sentStatus != RoomSentStatusOk
|
||||
&& recentCellData2.roomSummary.room.sentStatus == RoomSentStatusOk)
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
|
||||
if (recentCellData2.roomSummary.room.sentStatus != RoomSentStatusOk
|
||||
&& recentCellData1.roomSummary.room.sentStatus == RoomSentStatusOk)
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
|
||||
if (recentCellData1.highlightCount)
|
||||
{
|
||||
if (recentCellData2.highlightCount)
|
||||
{
|
||||
return NSOrderedSame;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
}
|
||||
else if (recentCellData2.highlightCount)
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
else if (recentCellData1.notificationCount)
|
||||
{
|
||||
if (recentCellData2.notificationCount)
|
||||
{
|
||||
return NSOrderedSame;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
}
|
||||
else if (recentCellData2.notificationCount)
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
else if (pinUnread)
|
||||
{
|
||||
if (recentCellData1.hasUnread)
|
||||
{
|
||||
if (recentCellData2.hasUnread)
|
||||
{
|
||||
return NSOrderedSame;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
}
|
||||
else if (recentCellData2.hasUnread)
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
}
|
||||
|
||||
return NSOrderedSame;
|
||||
};
|
||||
}
|
||||
else if (pinUnread)
|
||||
{
|
||||
// Sort each rooms collection by considering first the rooms with some unread messages then the others.
|
||||
comparator = ^NSComparisonResult(id<MXKRecentCellDataStoring> recentCellData1, id<MXKRecentCellDataStoring> recentCellData2) {
|
||||
|
||||
if (recentCellData1.spaceChildInfo && !recentCellData2.spaceChildInfo)
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
if (recentCellData2.spaceChildInfo && !recentCellData1.spaceChildInfo)
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
|
||||
if (recentCellData1.roomSummary.room.sentStatus != RoomSentStatusOk
|
||||
&& recentCellData2.roomSummary.room.sentStatus == RoomSentStatusOk)
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
|
||||
if (recentCellData2.roomSummary.room.sentStatus != RoomSentStatusOk
|
||||
&& recentCellData1.roomSummary.room.sentStatus == RoomSentStatusOk)
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
|
||||
if (recentCellData1.hasUnread)
|
||||
{
|
||||
if (recentCellData2.hasUnread)
|
||||
{
|
||||
return NSOrderedSame;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
}
|
||||
else if (recentCellData2.hasUnread)
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
|
||||
return NSOrderedSame;
|
||||
};
|
||||
}
|
||||
|
||||
if (comparator)
|
||||
{
|
||||
// Sort the rooms collections
|
||||
[favoriteCellDataArray sortUsingComparator:comparator];
|
||||
[peopleCellDataArray sortUsingComparator:comparator];
|
||||
[conversationCellDataArray sortUsingComparator:comparator];
|
||||
[lowPriorityCellDataArray sortUsingComparator:comparator];
|
||||
[serverNoticeCellDataArray sortUsingComparator:comparator];
|
||||
}
|
||||
}
|
||||
else if (favoriteCellDataArray.count > 0 && recentsDataSourceMode == RecentsDataSourceModeFavourites)
|
||||
{
|
||||
// Sort them according to their tag order
|
||||
[favoriteCellDataArray sortUsingComparator:^NSComparisonResult(id<MXKRecentCellDataStoring> recentCellData1, id<MXKRecentCellDataStoring> recentCellData2) {
|
||||
|
||||
return [mxSession compareRoomsByTag:kMXRoomTagFavourite room1:recentCellData1.roomSummary.room room2:recentCellData2.roomSummary.room];
|
||||
|
||||
}];
|
||||
}
|
||||
else if (conversationCellDataArray.count > 0 && (recentsDataSourceMode == RecentsDataSourceModeRooms || recentsDataSourceMode == RecentsDataSourceModePeople))
|
||||
{
|
||||
[conversationCellDataArray sortUsingComparator:^NSComparisonResult(id<MXKRecentCellDataStoring> recentCellData1, id<MXKRecentCellDataStoring> recentCellData2) {
|
||||
|
||||
if (recentCellData1.roomSummary.room.sentStatus != RoomSentStatusOk
|
||||
&& recentCellData2.roomSummary.room.sentStatus == RoomSentStatusOk)
|
||||
{
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
|
||||
if (recentCellData2.roomSummary.room.sentStatus != RoomSentStatusOk
|
||||
&& recentCellData1.roomSummary.room.sentStatus == RoomSentStatusOk)
|
||||
{
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
|
||||
return NSOrderedAscending;
|
||||
}];
|
||||
}
|
||||
|
||||
MXLogDebug(@"[RecentsDataSource] refreshRoomsSections: Done in %.0fms", [[NSDate date] timeIntervalSinceDate:startDate] * 1000);
|
||||
MXLogDebug(@"[Spaces] refreshRoomsSections with %ld suggested room", suggestedRoomCellDataArray.count);
|
||||
|
||||
return [[RecentsDataSourceState alloc]
|
||||
initWithInvitesCellDataArray:invitesCellDataArray
|
||||
favoriteCellDataArray:favoriteCellDataArray
|
||||
peopleCellDataArray:peopleCellDataArray
|
||||
conversationCellDataArray:conversationCellDataArray
|
||||
lowPriorityCellDataArray:lowPriorityCellDataArray
|
||||
serverNoticeCellDataArray:serverNoticeCellDataArray
|
||||
suggestedRoomCellDataArray:suggestedRoomCellDataArray
|
||||
favouriteMissedDiscussionsCount:favouriteMissedDiscussionsCount
|
||||
directMissedDiscussionsCount:directMissedDiscussionsCount
|
||||
groupMissedDiscussionsCount:groupMissedDiscussionsCount
|
||||
unsentMessagesDirectDiscussionsCount:unsentMessagesDirectDiscussionsCount
|
||||
unsentMessagesGroupDiscussionsCount:unsentMessagesGroupDiscussionsCount];
|
||||
}
|
||||
|
||||
- (void)dataSource:(MXKDataSource*)dataSource didCellChange:(id)changes
|
||||
{
|
||||
// Refresh is disabled during drag&drop animation
|
||||
@@ -1646,12 +1197,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
// 1 - call [super thisNewMethod]
|
||||
// 2 - call [self refreshRoomsSections]
|
||||
|
||||
// refresh the sections
|
||||
[self refreshRoomsSection:^{
|
||||
// Call super to keep update readyRecentsDataSourceArray.
|
||||
[super dataSource:dataSource didCellChange:changes];
|
||||
}];
|
||||
|
||||
// Call super to keep update readyRecentsDataSourceArray.
|
||||
[super dataSource:dataSource didCellChange:changes];
|
||||
}
|
||||
|
||||
#pragma mark - Drag & Drop handling
|
||||
@@ -1720,6 +1267,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
|
||||
[publicRoomsTriggerTimer invalidate];
|
||||
publicRoomsTriggerTimer = nil;
|
||||
|
||||
[self.recentsListService stop];
|
||||
}
|
||||
|
||||
#pragma mark - Override MXKRecentsDataSource
|
||||
@@ -1727,11 +1276,13 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
- (void)searchWithPatterns:(NSArray *)patternsList
|
||||
{
|
||||
[super searchWithPatterns:patternsList];
|
||||
|
||||
NSString *searchPattern = [patternsList componentsJoinedByString:@" "];
|
||||
|
||||
[self.recentsListService updateQuery:searchPattern];
|
||||
|
||||
if (_publicRoomsDirectoryDataSource)
|
||||
{
|
||||
NSString *searchPattern = [patternsList componentsJoinedByString:@" "];
|
||||
|
||||
// Do not send a /publicRooms request for every keystroke
|
||||
// Let user finish typing
|
||||
[publicRoomsTriggerTimer invalidate];
|
||||
@@ -1878,4 +1429,12 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
|
||||
[self hideCrossSigningBannerWithDisplay:self.crossSigningBannerDisplay];
|
||||
}
|
||||
|
||||
#pragma mark - RecentsListServiceDelegate
|
||||
|
||||
- (void)serviceDidChangeData:(id<RecentsListServiceProtocol>)service
|
||||
{
|
||||
// TODO: Update only updated sections
|
||||
[self.delegate dataSource:self didCellChange:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
//
|
||||
// Copyright 2021 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
|
||||
|
||||
/// The state for a room list screens.
|
||||
@objcMembers
|
||||
class RecentsDataSourceState: NSObject {
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
// MARK: Cells
|
||||
let invitesCellDataArray: [MXKRecentCellDataStoring]
|
||||
let favoriteCellDataArray: [MXKRecentCellDataStoring]
|
||||
let peopleCellDataArray: [MXKRecentCellDataStoring]
|
||||
let conversationCellDataArray: [MXKRecentCellDataStoring]
|
||||
let lowPriorityCellDataArray: [MXKRecentCellDataStoring]
|
||||
let serverNoticeCellDataArray: [MXKRecentCellDataStoring]
|
||||
let suggestedRoomCellDataArray: [MXKRecentCellDataStoring]
|
||||
|
||||
// MARK: Notifications counts
|
||||
let favouriteMissedDiscussionsCount: MissedDiscussionsCount
|
||||
let directMissedDiscussionsCount: MissedDiscussionsCount
|
||||
let groupMissedDiscussionsCount: MissedDiscussionsCount
|
||||
|
||||
// MARK: Unsent counts
|
||||
let unsentMessagesDirectDiscussionsCount: UInt
|
||||
let unsentMessagesGroupDiscussionsCount: UInt
|
||||
|
||||
|
||||
// MARK: - Setup
|
||||
init(invitesCellDataArray: [MXKRecentCellDataStoring],
|
||||
favoriteCellDataArray: [MXKRecentCellDataStoring],
|
||||
peopleCellDataArray: [MXKRecentCellDataStoring],
|
||||
conversationCellDataArray: [MXKRecentCellDataStoring],
|
||||
lowPriorityCellDataArray: [MXKRecentCellDataStoring],
|
||||
serverNoticeCellDataArray: [MXKRecentCellDataStoring],
|
||||
suggestedRoomCellDataArray: [MXKRecentCellDataStoring],
|
||||
favouriteMissedDiscussionsCount: MissedDiscussionsCount,
|
||||
directMissedDiscussionsCount: MissedDiscussionsCount,
|
||||
groupMissedDiscussionsCount: MissedDiscussionsCount,
|
||||
unsentMessagesDirectDiscussionsCount: UInt,
|
||||
unsentMessagesGroupDiscussionsCount: UInt) {
|
||||
self.invitesCellDataArray = invitesCellDataArray
|
||||
self.favoriteCellDataArray = favoriteCellDataArray
|
||||
self.peopleCellDataArray = peopleCellDataArray
|
||||
self.conversationCellDataArray = conversationCellDataArray
|
||||
self.lowPriorityCellDataArray = lowPriorityCellDataArray
|
||||
self.serverNoticeCellDataArray = serverNoticeCellDataArray
|
||||
self.suggestedRoomCellDataArray = suggestedRoomCellDataArray
|
||||
self.favouriteMissedDiscussionsCount = favouriteMissedDiscussionsCount
|
||||
self.directMissedDiscussionsCount = directMissedDiscussionsCount
|
||||
self.groupMissedDiscussionsCount = groupMissedDiscussionsCount
|
||||
self.unsentMessagesDirectDiscussionsCount = unsentMessagesDirectDiscussionsCount
|
||||
self.unsentMessagesGroupDiscussionsCount = unsentMessagesGroupDiscussionsCount
|
||||
super.init()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Noticiations counts per section
|
||||
@objcMembers
|
||||
class MissedDiscussionsCount: NSObject {
|
||||
/// Regular notifications
|
||||
var count: UInt = 0
|
||||
|
||||
/// Mentions like notications
|
||||
var highlightCount: UInt = 0
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// Copyright 2021 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
|
||||
|
||||
/// Noticiations counts per section
|
||||
@objcMembers
|
||||
public class DiscussionsCount: NSObject {
|
||||
/// Number of notified rooms with regular notifications
|
||||
public let numberOfNotified: Int
|
||||
|
||||
/// Number of highlighted rooms with mentions like notications
|
||||
public let numberOfHighlighted: Int
|
||||
|
||||
/// Number of rooms that have unsent messages in it
|
||||
public let numberOfUnsent: Int
|
||||
|
||||
/// Flag indicating is there any unsent
|
||||
public var hasUnsent: Bool {
|
||||
return numberOfUnsent > 0
|
||||
}
|
||||
|
||||
/// Flag indicating is there any highlight
|
||||
public var hasHighlight: Bool {
|
||||
return numberOfHighlighted > 0
|
||||
}
|
||||
|
||||
public static let zero: DiscussionsCount = DiscussionsCount(numberOfNotified: 0,
|
||||
numberOfHighlighted: 0,
|
||||
numberOfUnsent: 0)
|
||||
|
||||
public init(numberOfNotified: Int,
|
||||
numberOfHighlighted: Int,
|
||||
numberOfUnsent: Int) {
|
||||
self.numberOfNotified = numberOfNotified
|
||||
self.numberOfHighlighted = numberOfHighlighted
|
||||
self.numberOfUnsent = numberOfUnsent
|
||||
super.init()
|
||||
}
|
||||
|
||||
public init(withRoomListDataCounts counts: MXRoomListDataCounts) {
|
||||
self.numberOfNotified = counts.numberOfNotifiedRooms
|
||||
self.numberOfHighlighted = counts.numberOfHighlightedRooms + counts.numberOfInvitedRooms
|
||||
self.numberOfUnsent = counts.numberOfUnsentRooms
|
||||
super.init()
|
||||
}
|
||||
}
|
||||
@@ -27,10 +27,8 @@
|
||||
#endif
|
||||
|
||||
@implementation RecentCellData
|
||||
// trick to hide the mother class property as it is readonly one.
|
||||
// self.roomDisplayname returns this value instead of the mother class.
|
||||
@synthesize roomDisplayname;
|
||||
|
||||
// Adds K handling to super implementation
|
||||
- (NSString*)notificationCountStringValue
|
||||
{
|
||||
NSString *stringValue;
|
||||
@@ -49,26 +47,29 @@
|
||||
return stringValue;
|
||||
}
|
||||
|
||||
// Adds mentions-only handling to super implementation
|
||||
- (NSUInteger)notificationCount
|
||||
{
|
||||
MXRoom *room = [self.mxSession roomWithRoomId:self.roomSummary.roomId];
|
||||
// Ignore the regular notification count if the room is in 'mentions only" mode at the Riot level.
|
||||
if (self.roomSummary.room.isMentionsOnly)
|
||||
if (room.isMentionsOnly)
|
||||
{
|
||||
// Only the highlighted missed messages must be considered here.
|
||||
return self.roomSummary.highlightCount;
|
||||
return super.highlightCount;
|
||||
}
|
||||
|
||||
return self.roomSummary.notificationCount;
|
||||
return super.notificationCount;
|
||||
}
|
||||
|
||||
- (void)update
|
||||
// Adds "Empty Room" case to super implementation
|
||||
- (NSString *)roomDisplayname
|
||||
{
|
||||
[super update];
|
||||
roomDisplayname = self.spaceChildInfo ? self.spaceChildInfo.name: self.roomSummary.displayname;
|
||||
if (!roomDisplayname.length)
|
||||
NSString *result = [super roomDisplayname];
|
||||
if (!result.length)
|
||||
{
|
||||
roomDisplayname = [MatrixKitL10n roomDisplaynameEmptyRoom];
|
||||
result = [MatrixKitL10n roomDisplaynameEmptyRoom];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -18,8 +18,9 @@ import Foundation
|
||||
|
||||
extension RecentsViewController {
|
||||
|
||||
@objc func canShowRoomPreview(for room: MXRoom) -> Bool {
|
||||
let membershipTransitionState = room.summary.membershipTransitionState
|
||||
@objc
|
||||
func canShowRoomPreview(for summary: MXRoomSummaryProtocol) -> Bool {
|
||||
let membershipTransitionState = summary.membershipTransitionState
|
||||
|
||||
// NOTE: For the moment do not offer the possibility to show room preview when invitation action is in progress
|
||||
|
||||
|
||||
@@ -417,7 +417,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
// Update here the index of the current selected cell (if any) - Useful in landscape mode with split view controller.
|
||||
NSIndexPath *currentSelectedCellIndexPath = nil;
|
||||
MasterTabBarController *masterTabBarController = [AppDelegate theDelegate].masterTabBarController;
|
||||
if (masterTabBarController.currentRoomViewController)
|
||||
if (masterTabBarController.selectedRoomId)
|
||||
{
|
||||
// Look for the rank of this selected room in displayed recents
|
||||
currentSelectedCellIndexPath = [self.dataSource cellIndexPathWithRoomId:masterTabBarController.selectedRoomId andMatrixSession:masterTabBarController.selectedRoomSession];
|
||||
@@ -856,16 +856,34 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dispayRoomWithRoomId:(NSString*)roomId inMatrixSession:(MXSession*)matrixSession
|
||||
- (void)showRoomWithRoomId:(NSString*)roomId inMatrixSession:(MXSession*)matrixSession
|
||||
{
|
||||
// Avoid multiple openings of rooms
|
||||
self.userInteractionEnabled = NO;
|
||||
|
||||
// Do not stack views when showing room
|
||||
ScreenPresentationParameters *presentationParameters = [[ScreenPresentationParameters alloc] initWithRestoreInitialDisplay:NO stackAboveVisibleViews:NO];
|
||||
|
||||
[[AppDelegate theDelegate] showRoom:roomId andEventId:nil withMatrixSession:matrixSession restoreInitialDisplay:NO completion:^{
|
||||
RoomNavigationParameters *parameters = [[RoomNavigationParameters alloc] initWithRoomId:roomId
|
||||
eventId:nil
|
||||
mxSession:matrixSession
|
||||
presentationParameters:presentationParameters];
|
||||
|
||||
[[AppDelegate theDelegate] showRoomWithParameters:parameters completion:^{
|
||||
self.userInteractionEnabled = YES;
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)showRoomPreviewWithData:(RoomPreviewData*)roomPreviewData
|
||||
{
|
||||
// Do not stack views when showing room
|
||||
ScreenPresentationParameters *presentationParameters = [[ScreenPresentationParameters alloc] initWithRestoreInitialDisplay:NO stackAboveVisibleViews:NO sender:nil sourceView:nil];
|
||||
|
||||
RoomPreviewNavigationParameters *parameters = [[RoomPreviewNavigationParameters alloc] initWithPreviewData:roomPreviewData presentationParameters:presentationParameters];
|
||||
|
||||
[[AppDelegate theDelegate] showRoomPreviewWithParameters:parameters];
|
||||
}
|
||||
|
||||
// Disable UI interactions in this screen while we are going to open another screen.
|
||||
// Interactions on reset on viewWillAppear.
|
||||
- (void)setUserInteractionEnabled:(BOOL)userInteractionEnabled
|
||||
@@ -901,7 +919,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
{
|
||||
id<MXKRecentCellDataStoring> cellDataStoring = (id<MXKRecentCellDataStoring> )cellData;
|
||||
|
||||
if (cellDataStoring.roomSummary.room.summary.membership != MXMembershipInvite)
|
||||
if (cellDataStoring.roomSummary.membership != MXMembershipInvite)
|
||||
{
|
||||
return RecentTableViewCell.class;
|
||||
}
|
||||
@@ -939,7 +957,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
}
|
||||
|
||||
// Display the room preview
|
||||
[self dispayRoomWithRoomId:invitedRoom.roomId inMatrixSession:invitedRoom.mxSession];
|
||||
[self showRoomWithRoomId:invitedRoom.roomId inMatrixSession:invitedRoom.mxSession];
|
||||
}
|
||||
else if ([actionIdentifier isEqualToString:kInviteRecentTableViewCellAcceptButtonPressed])
|
||||
{
|
||||
@@ -1451,18 +1469,17 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
id<MXKRecentCellDataStoring> cellData = [self.dataSource cellDataAtIndexPath:indexPath];
|
||||
|
||||
// Retrieve the invited room
|
||||
MXRoom* invitedRoom = cellData.roomSummary.room;
|
||||
|
||||
if (invitedRoom.summary.roomType == MXRoomTypeSpace)
|
||||
if (cellData.roomSummary.roomType == MXRoomTypeSpace)
|
||||
{
|
||||
// Indicates that spaces are not supported
|
||||
[self showSpaceInviteNotAvailable];
|
||||
}
|
||||
// Check if can show preview for the invited room
|
||||
else if ([self canShowRoomPreviewFor:invitedRoom])
|
||||
else if ([self canShowRoomPreviewFor:cellData.roomSummary])
|
||||
{
|
||||
// Display the room preview
|
||||
[self dispayRoomWithRoomId:invitedRoom.roomId inMatrixSession:invitedRoom.mxSession];
|
||||
[self showRoomWithRoomId:cellData.roomIdentifier inMatrixSession:cellData.mxSession];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1982,7 +1999,8 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
if ([self.recentsDataSource.publicRoomsDirectoryDataSource.mxSession roomWithRoomId:publicRoom.roomId])
|
||||
{
|
||||
// Open the public room
|
||||
[[AppDelegate theDelegate] showRoom:publicRoom.roomId andEventId:nil withMatrixSession:self.recentsDataSource.publicRoomsDirectoryDataSource.mxSession restoreInitialDisplay:NO];
|
||||
[self showRoomWithRoomId:publicRoom.roomId
|
||||
inMatrixSession:self.recentsDataSource.publicRoomsDirectoryDataSource.mxSession];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1996,14 +2014,15 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
// Try to get more information about the room before opening its preview
|
||||
[roomPreviewData peekInRoom:^(BOOL succeeded) {
|
||||
[self stopActivityIndicator];
|
||||
|
||||
[[AppDelegate theDelegate].masterTabBarController showRoomPreview:roomPreviewData];
|
||||
|
||||
[self showRoomPreviewWithData:roomPreviewData];
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
RoomPreviewData *roomPreviewData = [[RoomPreviewData alloc] initWithPublicRoom:publicRoom andSession:self.recentsDataSource.publicRoomsDirectoryDataSource.mxSession];
|
||||
[[AppDelegate theDelegate].masterTabBarController showRoomPreview:roomPreviewData];
|
||||
|
||||
[self showRoomPreviewWithData:roomPreviewData];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2069,7 +2088,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
|
||||
- (void)recentListViewController:(MXKRecentListViewController *)recentListViewController didSelectRoom:(NSString *)roomId inMatrixSession:(MXSession *)matrixSession
|
||||
{
|
||||
[self dispayRoomWithRoomId:roomId inMatrixSession:matrixSession];
|
||||
[self showRoomWithRoomId:roomId inMatrixSession:matrixSession];
|
||||
}
|
||||
|
||||
- (void)recentListViewController:(MXKRecentListViewController *)recentListViewController didSelectSuggestedRoom:(MXSpaceChildInfo *)childInfo
|
||||
@@ -2080,7 +2099,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
[previewData peekInRoom:^(BOOL succeeded) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self stopActivityIndicator];
|
||||
[[AppDelegate theDelegate].masterTabBarController showRoomPreview:previewData];
|
||||
[self showRoomPreviewWithData:previewData];
|
||||
}];
|
||||
}
|
||||
|
||||
@@ -2123,7 +2142,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
- (void)createRoomCoordinatorBridgePresenterDelegate:(CreateRoomCoordinatorBridgePresenter *)coordinatorBridgePresenter didCreateNewRoom:(MXRoom *)room
|
||||
{
|
||||
[coordinatorBridgePresenter dismissWithAnimated:YES completion:^{
|
||||
[[AppDelegate theDelegate] showRoom:room.roomId andEventId:nil withMatrixSession:self.mainSession restoreInitialDisplay:NO];
|
||||
[self showRoomWithRoomId:room.roomId inMatrixSession:self.mainSession];
|
||||
}];
|
||||
coordinatorBridgePresenter = nil;
|
||||
}
|
||||
@@ -2217,7 +2236,13 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
|
||||
- (BOOL)shouldShowEmptyView
|
||||
{
|
||||
return NO;
|
||||
// Do not present empty screen while searching
|
||||
if (self.recentsDataSource.searchPatternsList.count)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
return self.recentsDataSource.totalVisibleItemCount == 0;
|
||||
}
|
||||
|
||||
#pragma mark - RoomsDirectoryCoordinatorBridgePresenterDelegate
|
||||
@@ -2252,7 +2277,8 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
{
|
||||
// Room is known show it directly
|
||||
[coordinatorBridgePresenter dismissWithAnimated:YES completion:^{
|
||||
[[AppDelegate theDelegate] showRoom:room.roomId andEventId:nil withMatrixSession:self.mainSession restoreInitialDisplay:NO];
|
||||
[self showRoomWithRoomId:room.roomId
|
||||
inMatrixSession:self.mainSession];
|
||||
}];
|
||||
coordinatorBridgePresenter = nil;
|
||||
}
|
||||
@@ -2280,7 +2306,8 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
|
||||
if (succeeded) {
|
||||
[coordinatorBridgePresenter dismissWithAnimated:YES completion:^{
|
||||
[[AppDelegate theDelegate].masterTabBarController showRoomPreview:roomPreviewData];
|
||||
|
||||
[self showRoomPreviewWithData:roomPreviewData];
|
||||
}];
|
||||
self.roomsDirectoryCoordinatorBridgePresenter = nil;
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,510 @@
|
||||
//
|
||||
// Copyright 2021 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
|
||||
|
||||
@objcMembers
|
||||
public class RecentsListService: NSObject, RecentsListServiceProtocol {
|
||||
|
||||
private weak var session: MXSession?
|
||||
public private(set) var mode: RecentsDataSourceMode
|
||||
public private(set) var query: String?
|
||||
public private(set) var space: MXSpace?
|
||||
|
||||
// MARK: - Fetchers
|
||||
|
||||
private var invitedRoomListDataFetcher: MXRoomListDataFetcher?
|
||||
private var favoritedRoomListDataFetcher: MXRoomListDataFetcher?
|
||||
private var directRoomListDataFetcher: MXRoomListDataFetcher? {
|
||||
switch mode {
|
||||
case .home:
|
||||
return directRoomListDataFetcherForHome
|
||||
case .people:
|
||||
return directRoomListDataFetcherForPeople
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
private var conversationRoomListDataFetcher: MXRoomListDataFetcher? {
|
||||
switch mode {
|
||||
case .home:
|
||||
return conversationRoomListDataFetcherForHome
|
||||
case .rooms:
|
||||
return conversationRoomListDataFetcherForRooms
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
private var lowPriorityRoomListDataFetcher: MXRoomListDataFetcher?
|
||||
private var serverNoticeRoomListDataFetcher: MXRoomListDataFetcher?
|
||||
private var suggestedRoomListDataFetcher: MXRoomListDataFetcher?
|
||||
|
||||
private var conversationRoomListDataFetcherForHome: MXRoomListDataFetcher?
|
||||
private var conversationRoomListDataFetcherForRooms: MXRoomListDataFetcher?
|
||||
private var directRoomListDataFetcherForHome: MXRoomListDataFetcher?
|
||||
private var directRoomListDataFetcherForPeople: MXRoomListDataFetcher?
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private var fetcherTypesForMode: [RecentsDataSourceMode: FetcherTypes] = [
|
||||
.home: [.invited, .favorited, .directHome, .conversationHome, .lowPriority, .serverNotice, .suggested],
|
||||
.favourites: [.favorited],
|
||||
.people: [.directPeople],
|
||||
.rooms: [.conversationRooms, .suggested]
|
||||
]
|
||||
|
||||
private var allFetchers: [MXRoomListDataFetcher] {
|
||||
var result: [MXRoomListDataFetcher] = []
|
||||
if let fetcher = invitedRoomListDataFetcher {
|
||||
result.append(fetcher)
|
||||
}
|
||||
if let fetcher = favoritedRoomListDataFetcher {
|
||||
result.append(fetcher)
|
||||
}
|
||||
if let fetcher = directRoomListDataFetcherForHome {
|
||||
result.append(fetcher)
|
||||
}
|
||||
if let fetcher = directRoomListDataFetcherForPeople {
|
||||
result.append(fetcher)
|
||||
}
|
||||
if let fetcher = conversationRoomListDataFetcherForHome {
|
||||
result.append(fetcher)
|
||||
}
|
||||
if let fetcher = conversationRoomListDataFetcherForRooms {
|
||||
result.append(fetcher)
|
||||
}
|
||||
if let fetcher = lowPriorityRoomListDataFetcher {
|
||||
result.append(fetcher)
|
||||
}
|
||||
if let fetcher = serverNoticeRoomListDataFetcher {
|
||||
result.append(fetcher)
|
||||
}
|
||||
if let fetcher = suggestedRoomListDataFetcher {
|
||||
result.append(fetcher)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private var visibleFetchers: [MXRoomListDataFetcher] {
|
||||
guard let fetcherTypes = fetcherTypesForMode[mode] else {
|
||||
return []
|
||||
}
|
||||
var result: [MXRoomListDataFetcher] = []
|
||||
if let fetcher = invitedRoomListDataFetcher, fetcherTypes.contains(.invited) {
|
||||
result.append(fetcher)
|
||||
}
|
||||
if let fetcher = favoritedRoomListDataFetcher, fetcherTypes.contains(.favorited) {
|
||||
result.append(fetcher)
|
||||
}
|
||||
if let fetcher = directRoomListDataFetcherForHome, fetcherTypes.contains(.directHome) {
|
||||
result.append(fetcher)
|
||||
}
|
||||
if let fetcher = directRoomListDataFetcherForPeople, fetcherTypes.contains(.directPeople) {
|
||||
result.append(fetcher)
|
||||
}
|
||||
if let fetcher = conversationRoomListDataFetcherForHome, fetcherTypes.contains(.conversationHome) {
|
||||
result.append(fetcher)
|
||||
}
|
||||
if let fetcher = conversationRoomListDataFetcherForRooms, fetcherTypes.contains(.conversationRooms) {
|
||||
result.append(fetcher)
|
||||
}
|
||||
if let fetcher = lowPriorityRoomListDataFetcher, fetcherTypes.contains(.lowPriority) {
|
||||
result.append(fetcher)
|
||||
}
|
||||
if let fetcher = serverNoticeRoomListDataFetcher, fetcherTypes.contains(.serverNotice) {
|
||||
result.append(fetcher)
|
||||
}
|
||||
if let fetcher = suggestedRoomListDataFetcher,
|
||||
fetcherTypes.contains(.suggested) {
|
||||
result.append(fetcher)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private var hideInvitedSection: Bool {
|
||||
return MXSDKOptions.sharedInstance().autoAcceptRoomInvites
|
||||
}
|
||||
|
||||
private var showAllRoomsInHomeSpace: Bool {
|
||||
return RiotSettings.shared.showAllRoomsInHomeSpace
|
||||
}
|
||||
|
||||
// swiftlint:disable weak_delegate
|
||||
private let multicastDelegate: MXMulticastDelegate<RecentsListServiceDelegate> = MXMulticastDelegate()
|
||||
// swiftlint:enable weak_delegate
|
||||
|
||||
private var sortOptions: MXRoomListDataSortOptions {
|
||||
switch mode {
|
||||
case .home:
|
||||
let pinMissed = RiotSettings.shared.pinRoomsWithMissedNotificationsOnHome
|
||||
let pinUnread = RiotSettings.shared.pinRoomsWithUnreadMessagesOnHome
|
||||
return MXRoomListDataSortOptions(missedNotificationsFirst: pinMissed,
|
||||
unreadMessagesFirst: pinUnread)
|
||||
default:
|
||||
return MXRoomListDataSortOptions(missedNotificationsFirst: false,
|
||||
unreadMessagesFirst: false)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Public API
|
||||
|
||||
public convenience init(withSession session: MXSession) {
|
||||
self.init(withSession: session,
|
||||
mode: .home,
|
||||
query: nil,
|
||||
space: nil)
|
||||
}
|
||||
|
||||
private init(withSession session: MXSession,
|
||||
mode: RecentsDataSourceMode,
|
||||
query: String?,
|
||||
space: MXSpace?) {
|
||||
self.session = session
|
||||
self.mode = mode
|
||||
self.query = query
|
||||
self.space = space
|
||||
super.init()
|
||||
createFetchers()
|
||||
addRiotSettingsObserver()
|
||||
}
|
||||
|
||||
// MARK: - View Data
|
||||
|
||||
public var invitedRoomListData: MXRoomListData? {
|
||||
guard shouldShowInvited else { return nil }
|
||||
return invitedRoomListDataFetcher?.data
|
||||
}
|
||||
public var favoritedRoomListData: MXRoomListData? {
|
||||
guard shouldShowFavorited else { return nil }
|
||||
return favoritedRoomListDataFetcher?.data
|
||||
}
|
||||
public var peopleRoomListData: MXRoomListData? {
|
||||
guard shouldShowDirect else { return nil }
|
||||
return directRoomListDataFetcher?.data
|
||||
}
|
||||
public var conversationRoomListData: MXRoomListData? {
|
||||
guard shouldShowConversation else { return nil }
|
||||
return conversationRoomListDataFetcher?.data
|
||||
}
|
||||
public var lowPriorityRoomListData: MXRoomListData? {
|
||||
guard shouldShowLowPriority else { return nil }
|
||||
return lowPriorityRoomListDataFetcher?.data
|
||||
}
|
||||
public var serverNoticeRoomListData: MXRoomListData? {
|
||||
guard shouldShowServerNotice else { return nil }
|
||||
return serverNoticeRoomListDataFetcher?.data
|
||||
}
|
||||
public var suggestedRoomListData: MXRoomListData? {
|
||||
guard shouldShowSuggested else { return nil }
|
||||
return suggestedRoomListDataFetcher?.data
|
||||
}
|
||||
|
||||
public var favoritedMissedDiscussionsCount: DiscussionsCount {
|
||||
guard let data = favoritedRoomListDataFetcher?.data else {
|
||||
return .zero
|
||||
}
|
||||
return DiscussionsCount(withRoomListDataCounts: data.counts)
|
||||
}
|
||||
|
||||
public var peopleMissedDiscussionsCount: DiscussionsCount {
|
||||
guard let data = directRoomListDataFetcherForPeople?.data else {
|
||||
return .zero
|
||||
}
|
||||
return DiscussionsCount(withRoomListDataCounts: data.counts)
|
||||
}
|
||||
|
||||
public var conversationMissedDiscussionsCount: DiscussionsCount {
|
||||
guard let data = conversationRoomListDataFetcherForRooms?.data else {
|
||||
return .zero
|
||||
}
|
||||
return DiscussionsCount(withRoomListDataCounts: data.counts)
|
||||
}
|
||||
|
||||
public var totalVisibleItemCount: Int {
|
||||
return visibleFetchers.reduce(0, { $0 + ($1.data?.counts.numberOfRooms ?? 0) })
|
||||
}
|
||||
|
||||
public func updateMode(_ mode: RecentsDataSourceMode) {
|
||||
self.mode = mode
|
||||
if let fetcher = favoritedRoomListDataFetcher {
|
||||
updateFavoritedFetcher(fetcher, for: mode)
|
||||
}
|
||||
allFetchers.forEach({ notifyDataChange(on: $0) })
|
||||
}
|
||||
|
||||
public func updateQuery(_ query: String?) {
|
||||
self.query = query
|
||||
visibleFetchers.forEach({ $0.fetchOptions.filterOptions.query = query })
|
||||
}
|
||||
|
||||
public func updateSpace(_ space: MXSpace?) {
|
||||
self.space = space
|
||||
allFetchers.forEach({ $0.fetchOptions.filterOptions.space = space })
|
||||
}
|
||||
|
||||
public func refresh() {
|
||||
allFetchers.forEach({ $0.fetchOptions.sortOptions = sortOptions })
|
||||
allFetchers.forEach({ $0.fetchOptions.filterOptions.showAllRoomsInHomeSpace = showAllRoomsInHomeSpace })
|
||||
}
|
||||
|
||||
public func stop() {
|
||||
removeRiotSettingsObserver()
|
||||
removeAllDelegates()
|
||||
allFetchers.forEach({ $0.stop() })
|
||||
}
|
||||
|
||||
// MARK: - Delegate
|
||||
|
||||
public func addDelegate(_ delegate: RecentsListServiceDelegate) {
|
||||
multicastDelegate.addDelegate(delegate)
|
||||
}
|
||||
|
||||
public func removeDelegate(_ delegate: RecentsListServiceDelegate) {
|
||||
multicastDelegate.removeDelegate(delegate)
|
||||
}
|
||||
|
||||
public func removeAllDelegates() {
|
||||
multicastDelegate.removeAllDelegates()
|
||||
}
|
||||
|
||||
// MARK: - Riot Settings Observer
|
||||
|
||||
private func addRiotSettingsObserver() {
|
||||
NotificationCenter.default.addObserver(self,
|
||||
selector: #selector(userDefaultsUpdated(_:)),
|
||||
name: .userDefaultValueUpdated,
|
||||
object: nil)
|
||||
}
|
||||
|
||||
private func removeRiotSettingsObserver() {
|
||||
NotificationCenter.default.removeObserver(self,
|
||||
name: .userDefaultValueUpdated,
|
||||
object: nil)
|
||||
}
|
||||
|
||||
@objc
|
||||
private func userDefaultsUpdated(_ notification: Notification) {
|
||||
guard let key = notification.object as? String else {
|
||||
return
|
||||
}
|
||||
switch key {
|
||||
case RiotSettings.UserDefaultsKeys.pinRoomsWithMissedNotificationsOnHome,
|
||||
RiotSettings.UserDefaultsKeys.pinRoomsWithUnreadMessagesOnHome:
|
||||
refresh()
|
||||
case RiotSettings.UserDefaultsKeys.showAllRoomsInHomeSpace:
|
||||
refresh()
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
private var shouldShowInvited: Bool {
|
||||
return fetcherTypesForMode[mode]?.contains(.invited) ?? false
|
||||
}
|
||||
|
||||
private var shouldShowFavorited: Bool {
|
||||
return fetcherTypesForMode[mode]?.contains(.favorited) ?? false
|
||||
}
|
||||
|
||||
private var shouldShowDirect: Bool {
|
||||
switch mode {
|
||||
case .home:
|
||||
return fetcherTypesForMode[mode]?.contains(.directHome) ?? false
|
||||
case .people:
|
||||
return fetcherTypesForMode[mode]?.contains(.directPeople) ?? false
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private var shouldShowConversation: Bool {
|
||||
switch mode {
|
||||
case .home:
|
||||
return fetcherTypesForMode[mode]?.contains(.conversationHome) ?? false
|
||||
case .rooms:
|
||||
return fetcherTypesForMode[mode]?.contains(.conversationRooms) ?? false
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private var shouldShowLowPriority: Bool {
|
||||
return fetcherTypesForMode[mode]?.contains(.lowPriority) ?? false
|
||||
}
|
||||
|
||||
private var shouldShowServerNotice: Bool {
|
||||
return fetcherTypesForMode[mode]?.contains(.serverNotice) ?? false
|
||||
}
|
||||
|
||||
private var shouldShowSuggested: Bool {
|
||||
return fetcherTypesForMode[mode]?.contains(.suggested) ?? false
|
||||
}
|
||||
|
||||
private func createCommonRoomListDataFetcher(withDataTypes dataTypes: MXRoomSummaryDataTypes = [],
|
||||
onlySuggested: Bool = false,
|
||||
paginate: Bool = true) -> MXRoomListDataFetcher {
|
||||
guard let session = session else {
|
||||
fatalError("Session deallocated")
|
||||
}
|
||||
let filterOptions = MXRoomListDataFilterOptions(dataTypes: dataTypes,
|
||||
onlySuggested: onlySuggested,
|
||||
query: query,
|
||||
space: space,
|
||||
showAllRoomsInHomeSpace: showAllRoomsInHomeSpace)
|
||||
|
||||
let fetchOptions = MXRoomListDataFetchOptions(filterOptions: filterOptions,
|
||||
sortOptions: sortOptions,
|
||||
async: false)
|
||||
let fetcher = session.roomListDataManager.fetcher(withOptions: fetchOptions)
|
||||
if paginate {
|
||||
fetcher.addDelegate(self)
|
||||
fetcher.paginate()
|
||||
}
|
||||
return fetcher
|
||||
}
|
||||
|
||||
private func createDirectRoomListDataFetcherForHome() -> MXRoomListDataFetcher {
|
||||
let fetcher = createCommonRoomListDataFetcher(withDataTypes: [.direct], paginate: false)
|
||||
updateDirectFetcher(fetcher, for: .home)
|
||||
fetcher.addDelegate(self)
|
||||
fetcher.paginate()
|
||||
return fetcher
|
||||
}
|
||||
|
||||
private func createDirectRoomListDataFetcherForPeople() -> MXRoomListDataFetcher {
|
||||
let fetcher = createCommonRoomListDataFetcher(withDataTypes: [.direct], paginate: false)
|
||||
updateDirectFetcher(fetcher, for: .people)
|
||||
fetcher.addDelegate(self)
|
||||
fetcher.paginate()
|
||||
return fetcher
|
||||
}
|
||||
|
||||
private func createConversationRoomListDataFetcherForHome() -> MXRoomListDataFetcher {
|
||||
let fetcher = createCommonRoomListDataFetcher(withDataTypes: [], paginate: false)
|
||||
updateConversationFetcher(fetcher, for: .home)
|
||||
fetcher.addDelegate(self)
|
||||
fetcher.paginate()
|
||||
return fetcher
|
||||
}
|
||||
|
||||
private func createConversationRoomListDataFetcherForRooms() -> MXRoomListDataFetcher {
|
||||
let fetcher = createCommonRoomListDataFetcher(withDataTypes: [], paginate: false)
|
||||
updateConversationFetcher(fetcher, for: .rooms)
|
||||
fetcher.addDelegate(self)
|
||||
fetcher.paginate()
|
||||
return fetcher
|
||||
}
|
||||
|
||||
private func createFetchers() {
|
||||
if !hideInvitedSection {
|
||||
invitedRoomListDataFetcher = createCommonRoomListDataFetcher(withDataTypes: [.invited])
|
||||
}
|
||||
favoritedRoomListDataFetcher = createCommonRoomListDataFetcher(withDataTypes: [.favorited])
|
||||
directRoomListDataFetcherForHome = createDirectRoomListDataFetcherForHome()
|
||||
directRoomListDataFetcherForPeople = createDirectRoomListDataFetcherForPeople()
|
||||
conversationRoomListDataFetcherForHome = createConversationRoomListDataFetcherForHome()
|
||||
conversationRoomListDataFetcherForRooms = createConversationRoomListDataFetcherForRooms()
|
||||
lowPriorityRoomListDataFetcher = createCommonRoomListDataFetcher(withDataTypes: [.lowPriority])
|
||||
serverNoticeRoomListDataFetcher = createCommonRoomListDataFetcher(withDataTypes: [.serverNotice])
|
||||
suggestedRoomListDataFetcher = createCommonRoomListDataFetcher(onlySuggested: true)
|
||||
}
|
||||
|
||||
private func updateDirectFetcher(_ fetcher: MXRoomListDataFetcher, for mode: RecentsDataSourceMode) {
|
||||
switch mode {
|
||||
case .home:
|
||||
fetcher.fetchOptions.filterOptions.notDataTypes = [.invited, .lowPriority]
|
||||
case .people:
|
||||
fetcher.fetchOptions.filterOptions.notDataTypes = [.lowPriority]
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
private func updateFavoritedFetcher(_ fetcher: MXRoomListDataFetcher, for mode: RecentsDataSourceMode) {
|
||||
switch mode {
|
||||
case .home:
|
||||
fetcher.fetchOptions.sortOptions = sortOptions
|
||||
case .favourites:
|
||||
let newSortOptions = sortOptions
|
||||
newSortOptions.favoriteTag = true
|
||||
fetcher.fetchOptions.sortOptions = newSortOptions
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
private func updateConversationFetcher(_ fetcher: MXRoomListDataFetcher, for mode: RecentsDataSourceMode) {
|
||||
var notDataTypes: MXRoomSummaryDataTypes = [.hidden, .conferenceUser, .direct, .lowPriority, .serverNotice, .space]
|
||||
switch mode {
|
||||
case .home:
|
||||
notDataTypes.insert([.invited, .favorited])
|
||||
fetcher.fetchOptions.filterOptions.notDataTypes = notDataTypes
|
||||
case .rooms:
|
||||
if hideInvitedSection {
|
||||
notDataTypes.insert(.invited)
|
||||
}
|
||||
fetcher.fetchOptions.filterOptions.notDataTypes = notDataTypes
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
private func notifyDataChange(on fetcher: MXRoomListDataFetcher) {
|
||||
multicastDelegate.invoke({ $0.serviceDidChangeData(self) })
|
||||
}
|
||||
|
||||
deinit {
|
||||
stop()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - MXRoomListDataFetcherDelegate
|
||||
|
||||
extension RecentsListService: MXRoomListDataFetcherDelegate {
|
||||
|
||||
public func fetcherDidChangeData(_ fetcher: MXRoomListDataFetcher) {
|
||||
notifyDataChange(on: fetcher)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - FetcherTypes
|
||||
|
||||
private struct FetcherTypes: OptionSet {
|
||||
typealias RawValue = Int
|
||||
let rawValue: RawValue
|
||||
|
||||
init(rawValue: RawValue) {
|
||||
self.rawValue = rawValue
|
||||
}
|
||||
|
||||
static let invited = FetcherTypes(rawValue: 1 << 0)
|
||||
static let favorited = FetcherTypes(rawValue: 1 << 1)
|
||||
static let directHome = FetcherTypes(rawValue: 1 << 2)
|
||||
static let directPeople = FetcherTypes(rawValue: 1 << 3)
|
||||
static let conversationHome = FetcherTypes(rawValue: 1 << 4)
|
||||
static let conversationRooms = FetcherTypes(rawValue: 1 << 5)
|
||||
static let lowPriority = FetcherTypes(rawValue: 1 << 6)
|
||||
static let serverNotice = FetcherTypes(rawValue: 1 << 7)
|
||||
static let suggested = FetcherTypes(rawValue: 1 << 8)
|
||||
|
||||
static let none: FetcherTypes = []
|
||||
static let all: FetcherTypes = [
|
||||
.invited, .favorited, .directHome, .directPeople, .conversationHome, .conversationRooms, .lowPriority, .serverNotice, .suggested]
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
//
|
||||
// Copyright 2021 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
|
||||
|
||||
@objcMembers
|
||||
public class MockRecentsListService: NSObject, RecentsListServiceProtocol {
|
||||
|
||||
private var rooms: [MockRoomSummary]
|
||||
|
||||
private var _invitedRoomListData: MXRoomListData?
|
||||
private var _favoritedRoomListData: MXRoomListData?
|
||||
private var _peopleRoomListData: MXRoomListData?
|
||||
private var _conversationRoomListData: MXRoomListData?
|
||||
private var _lowPriorityRoomListData: MXRoomListData?
|
||||
private var _serverNoticeRoomListData: MXRoomListData?
|
||||
|
||||
// swiftlint:disable weak_delegate
|
||||
private let multicastDelegate: MXMulticastDelegate<RecentsListServiceDelegate> = MXMulticastDelegate()
|
||||
// swiftlint:enable weak_delegate
|
||||
|
||||
public init(withRooms rooms: [MockRoomSummary]) {
|
||||
self.rooms = rooms
|
||||
|
||||
var invited: [MockRoomSummary] = []
|
||||
var favorited: [MockRoomSummary] = []
|
||||
var people: [MockRoomSummary] = []
|
||||
var conversation: [MockRoomSummary] = []
|
||||
var lowPriority: [MockRoomSummary] = []
|
||||
var serverNotice: [MockRoomSummary] = []
|
||||
|
||||
rooms.forEach { summary in
|
||||
if summary.isTyped(.invited) {
|
||||
invited.append(summary)
|
||||
}
|
||||
if summary.isTyped(.favorited) {
|
||||
favorited.append(summary)
|
||||
}
|
||||
if summary.isTyped(.direct) {
|
||||
people.append( summary)
|
||||
}
|
||||
if !summary.isTyped([.direct,
|
||||
.invited,
|
||||
.favorited,
|
||||
.lowPriority,
|
||||
.serverNotice]) {
|
||||
conversation.append(summary)
|
||||
}
|
||||
if summary.isTyped(.lowPriority) {
|
||||
lowPriority.append(summary)
|
||||
}
|
||||
if summary.isTyped(.serverNotice) {
|
||||
serverNotice.append(summary)
|
||||
}
|
||||
}
|
||||
_invitedRoomListData = MockRoomListData(withRooms: invited)
|
||||
_favoritedRoomListData = MockRoomListData(withRooms: favorited)
|
||||
_peopleRoomListData = MockRoomListData(withRooms: people)
|
||||
_conversationRoomListData = MockRoomListData(withRooms: conversation)
|
||||
_lowPriorityRoomListData = MockRoomListData(withRooms: lowPriority)
|
||||
_serverNoticeRoomListData = MockRoomListData(withRooms: serverNotice)
|
||||
|
||||
super.init()
|
||||
}
|
||||
|
||||
public static func generate(withNumberOfRooms numberOfRooms: Int) -> MockRecentsListService {
|
||||
var rooms: [MockRoomSummary] = []
|
||||
for i in 0..<numberOfRooms {
|
||||
let room = MockRoomSummary(withRoomId: "!room_\(i+1):matrix.org")
|
||||
if i % 2 == 0 {
|
||||
room.dataTypes = .direct
|
||||
} else if i % 3 == 0 {
|
||||
room.dataTypes = .favorited
|
||||
} else if i % 5 == 0 {
|
||||
room.dataTypes = .lowPriority
|
||||
} else if i % 7 == 0 {
|
||||
room.dataTypes = .invited
|
||||
} else if i % 11 == 0 {
|
||||
room.dataTypes = .serverNotice
|
||||
}
|
||||
room.displayname = "Room \(i+1)"
|
||||
if let event = MXEvent(fromJSON: [
|
||||
"event_id": MXTools.generateTransactionId() as Any,
|
||||
"room_id": room.roomId,
|
||||
"type": kMXEventTypeStringRoomMessage,
|
||||
"origin_server_ts": Date().timeIntervalSince1970,
|
||||
"content": [
|
||||
"type": kMXMessageTypeText,
|
||||
"content": "Message \(i+1)"
|
||||
]
|
||||
]) {
|
||||
room.lastMessage = MXRoomLastMessage(event: event)
|
||||
}
|
||||
rooms.append(room)
|
||||
}
|
||||
return MockRecentsListService(withRooms: rooms)
|
||||
}
|
||||
|
||||
public weak var session: MXSession?
|
||||
|
||||
public var mode: RecentsDataSourceMode = .home
|
||||
|
||||
public var query: String?
|
||||
|
||||
public var space: MXSpace?
|
||||
|
||||
public var invitedRoomListData: MXRoomListData? {
|
||||
guard mode == .home else { return nil }
|
||||
return _invitedRoomListData
|
||||
}
|
||||
|
||||
public var favoritedRoomListData: MXRoomListData? {
|
||||
guard mode == .home || mode == .favourites else { return nil }
|
||||
return _favoritedRoomListData
|
||||
}
|
||||
|
||||
public var peopleRoomListData: MXRoomListData? {
|
||||
guard mode == .home || mode == .people else { return nil }
|
||||
return _peopleRoomListData
|
||||
}
|
||||
|
||||
public var conversationRoomListData: MXRoomListData? {
|
||||
guard mode == .home || mode == .rooms else { return nil }
|
||||
return _conversationRoomListData
|
||||
}
|
||||
|
||||
public var lowPriorityRoomListData: MXRoomListData? {
|
||||
guard mode == .home else { return nil }
|
||||
return _lowPriorityRoomListData
|
||||
}
|
||||
|
||||
public var serverNoticeRoomListData: MXRoomListData? {
|
||||
guard mode == .home else { return nil }
|
||||
return _serverNoticeRoomListData
|
||||
}
|
||||
|
||||
public var suggestedRoomListData: MXRoomListData?
|
||||
|
||||
public var favoritedMissedDiscussionsCount: DiscussionsCount = .zero
|
||||
|
||||
public var peopleMissedDiscussionsCount: DiscussionsCount = .zero
|
||||
|
||||
public var conversationMissedDiscussionsCount: DiscussionsCount = .zero
|
||||
|
||||
public var totalVisibleItemCount: Int {
|
||||
switch mode {
|
||||
case .home:
|
||||
return rooms.count
|
||||
case .favourites:
|
||||
return favoritedRoomListData?.counts.numberOfRooms ?? 0
|
||||
case .people:
|
||||
return peopleRoomListData?.counts.numberOfRooms ?? 0
|
||||
case .rooms:
|
||||
return conversationRoomListData?.counts.numberOfRooms ?? 0
|
||||
@unknown default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
public func updateMode(_ mode: RecentsDataSourceMode) {
|
||||
self.mode = mode
|
||||
notifyDataChange()
|
||||
}
|
||||
|
||||
public func updateQuery(_ query: String?) {
|
||||
notifyDataChange()
|
||||
}
|
||||
|
||||
public func updateSpace(_ space: MXSpace?) {
|
||||
notifyDataChange()
|
||||
}
|
||||
|
||||
public func refresh() {
|
||||
notifyDataChange()
|
||||
}
|
||||
|
||||
public func stop() {
|
||||
_invitedRoomListData = nil
|
||||
_favoritedRoomListData = nil
|
||||
_peopleRoomListData = nil
|
||||
_conversationRoomListData = nil
|
||||
_lowPriorityRoomListData = nil
|
||||
_serverNoticeRoomListData = nil
|
||||
removeAllDelegates()
|
||||
}
|
||||
|
||||
public func addDelegate(_ delegate: RecentsListServiceDelegate) {
|
||||
multicastDelegate.addDelegate(delegate)
|
||||
}
|
||||
|
||||
public func removeDelegate(_ delegate: RecentsListServiceDelegate) {
|
||||
multicastDelegate.removeDelegate(delegate)
|
||||
}
|
||||
|
||||
public func removeAllDelegates() {
|
||||
multicastDelegate.removeAllDelegates()
|
||||
}
|
||||
|
||||
private func notifyDataChange() {
|
||||
multicastDelegate.invoke({ $0.serviceDidChangeData(self) })
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// Copyright 2021 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 MatrixSDK
|
||||
|
||||
@objcMembers
|
||||
public class MockRoomListData: MXRoomListData {
|
||||
|
||||
public init(withRooms rooms: [MXRoomSummaryProtocol]) {
|
||||
super.init(rooms: rooms,
|
||||
counts: MXStoreRoomListDataCounts(withRooms: rooms,
|
||||
totalRoomsCount: rooms.count),
|
||||
paginationOptions: .none)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
//
|
||||
// Copyright 2021 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
|
||||
|
||||
@objcMembers
|
||||
public class MockRoomSummary: NSObject, MXRoomSummaryProtocol {
|
||||
public var roomId: String
|
||||
|
||||
public var roomTypeString: String?
|
||||
|
||||
public var roomType: MXRoomType = .room
|
||||
|
||||
public var avatar: String?
|
||||
|
||||
public var displayname: String?
|
||||
|
||||
public var topic: String?
|
||||
|
||||
public var creatorUserId: String = "@room_creator:matrix.org"
|
||||
|
||||
public var aliases: [String] = []
|
||||
|
||||
public var joinRule: String? = kMXRoomJoinRuleInvite
|
||||
|
||||
public var membership: MXMembership = .join
|
||||
|
||||
public var membershipTransitionState: MXMembershipTransitionState = .joined
|
||||
|
||||
public var membersCount: MXRoomMembersCount = MXRoomMembersCount(members: 2, joined: 2, invited: 0)
|
||||
|
||||
public var isConferenceUserRoom: Bool = false
|
||||
|
||||
public var hiddenFromUser: Bool = false
|
||||
|
||||
public var storedHash: UInt = 0
|
||||
|
||||
public var lastMessage: MXRoomLastMessage?
|
||||
|
||||
public var isEncrypted: Bool = false
|
||||
|
||||
public var trust: MXUsersTrustLevelSummary?
|
||||
|
||||
public var localUnreadEventCount: UInt = 0
|
||||
|
||||
public var notificationCount: UInt = 0
|
||||
|
||||
public var highlightCount: UInt = 0
|
||||
|
||||
public var isDirect: Bool {
|
||||
return isTyped(.direct)
|
||||
}
|
||||
|
||||
public var directUserId: String?
|
||||
|
||||
public var others: [String: NSCoding]?
|
||||
|
||||
public var favoriteTagOrder: String?
|
||||
|
||||
public var dataTypes: MXRoomSummaryDataTypes = []
|
||||
|
||||
public func isTyped(_ types: MXRoomSummaryDataTypes) -> Bool {
|
||||
return (dataTypes.rawValue & types.rawValue) != 0
|
||||
}
|
||||
|
||||
public var sentStatus: MXRoomSummarySentStatus = .ok
|
||||
|
||||
public var spaceChildInfo: MXSpaceChildInfo?
|
||||
|
||||
public var parentSpaceIds: Set<String> = []
|
||||
|
||||
public init(withRoomId roomId: String) {
|
||||
self.roomId = roomId
|
||||
super.init()
|
||||
}
|
||||
|
||||
public static func generate() -> MockRoomSummary {
|
||||
return generate(withTypes: [])
|
||||
}
|
||||
|
||||
public static func generateDirect() -> MockRoomSummary {
|
||||
return generate(withTypes: .direct)
|
||||
}
|
||||
|
||||
public static func generate(withTypes types: MXRoomSummaryDataTypes) -> MockRoomSummary {
|
||||
guard let random = MXTools.generateSecret() else {
|
||||
fatalError("Room id cannot be created")
|
||||
}
|
||||
let result = MockRoomSummary(withRoomId: "!\(random):matrix.org")
|
||||
result.dataTypes = types
|
||||
if types.contains(.invited) {
|
||||
result.membership = .invite
|
||||
result.membershipTransitionState = .invited
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// Copyright 2021 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
|
||||
public protocol RecentsListServiceDelegate: AnyObject {
|
||||
|
||||
/// Delegate method to be called when service data updated
|
||||
/// - Parameter service: service object
|
||||
func serviceDidChangeData(_ service: RecentsListServiceProtocol)
|
||||
}
|
||||