Merge branch 'release/1.0.6/master'

This commit is contained in:
ismailgulek 2020-08-26 14:17:04 +03:00
commit ae2a5e9967
178 changed files with 1425 additions and 1616 deletions

View file

@ -1,8 +1,7 @@
### Pull Request Checklist
<!-- Please read CONTRIBUTING.rst before submitting your pull request -->
* [ ] UI change has been tested on both light and dark themes
* [ ] I read the [contributing guide](https://github.com/vector-im/element-ios/blob/develop/CONTRIBUTING.md)
* [ ] UI change has been tested on both light and dark themes, in portrait and landscape orientations and on iPhone and iPad simulators
* [ ] Pull request is based on the develop branch
* [ ] Pull request updates [CHANGES.rst](https://github.com/vector-im/riot-ios/blob/develop/CHANGES.rst)
* [ ] Pull request includes screenshots or videos of UI changes

2
.gitignore vendored
View file

@ -33,5 +33,7 @@ Pods/
fastlane/report.xml
fastlane/Reports
fastlane/README.md
fastlane/Preview.html
fastlane/metadata/
provisioning_profiles/

View file

@ -1,3 +1,39 @@
Changes in 1.0.6 (2020-08-26)
=================================================
Features:
*
Improvements:
* Upgrade MatrixKit version ([v0.12.15](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.12.15)).
* Config fixes.
* Introduce TableViewSections. Refactor RoomSettingsViewController & SettingsViewController.
* AuthenticationVC: Make forgot password button and phone number text field configurable.
* Introduce httpAdditionalHeaders in BuildSettings.
Bugfix:
* Fix biometry name null case (#3551).
* Avoid email validation link to redirect to web app (#3513).
* Wait for first sync complete before stopping loading screen (#3336).
* Disable key backup on extensions (#3371).
* Gracefully cancel verification on iOS 13 drag gesture (#3556).
API Change:
*
Translations:
*
Others:
* Ignore fastlane/Preview.html
* SonarCloud: Fix some code smells.
Build:
*
Test:
*
Changes in 1.0.5 (2020-08-13)
=================================================

33
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,33 @@
# Contributing code to Matrix
Please read Synapse [contributing guide](https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.md).
# Contributing code to Element iOS
## I want to help translating
If you want to fix an issue for an English string, please submit a pull request to the Element iOS GitHub repository.
If you want to fix an issue for another language, add a missing translation, or add a new language, please read [Element Web translating guide](https://github.com/vector-im/element-web/blob/develop/docs/translating.md) first and then use the Element iOS [Weblate](https://translate.riot.im/projects/riot-ios/).
If you have any question regarding translations please ask in [Element Translation room](https://matrix.to/#/#element-translations:matrix.org).
## Setting up a development environment
Please refer to the [installation guide](INSTALL.md) to setup the project.
## Implement a new screen or new screen flow
New screen flows are currently using MVVM-Coordinator pattern. Please refer to the screen template [Readme](Tools/Templates/README.md) to create a new screen or a new screen flow.
## Coding style
For Swift coding style we use [SwiftLint](https://github.com/realm/SwiftLint) to check some conventions at compile time (rules are located in the `.swiftlint.yml` file).
Otherwise please have a look to [Apple Swift conventions](https://swift.org/documentation/api-design-guidelines.html#conventions). We are also using some of the conventions of [raywenderlich.com Swift style guide](https://github.com/raywenderlich/swift-style-guide).
## Pull request
When you are making a pull request please read carefully the [Pull Request Checklist](https://github.com/vector-im/element-ios/blob/develop/.github/PULL_REQUEST_TEMPLATE.md).
## Thanks
Thanks for contributing to Matrix projects!

View file

@ -1,4 +0,0 @@
Contributing code to Riot iOS
==================================
riot-ios follows the same pattern as https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.md

View file

@ -36,6 +36,9 @@ class AppConfiguration: CommonConfiguration {
// Each room member will be considered as a potential contact.
MXKContactManager.shared().contactManagerMXRoomSource = MXKContactManagerMXRoomSource.all
// Enable key backup on app
MXSDKOptions.sharedInstance().enableKeyBackupWhenStartingMXCrypto = true
}

View file

@ -166,7 +166,7 @@ final class BuildSettings: NSObject {
static let allowLocalContactsAccess: Bool = true
// MARK: - Screen settings -
// MARK: - General Settings Screen
static let settingsScreenShowUserFirstName: Bool = false
static let settingsScreenShowUserSurname: Bool = false
@ -182,13 +182,31 @@ final class BuildSettings: NSObject {
static let settingsScreenAllowBugReportingManually: Bool = true
static let settingsScreenAllowDeactivatingAccount: Bool = true
// MARK: - Room Settings Screen
static let roomSettingsScreenShowLowPriorityOption: Bool = true
static let roomSettingsScreenShowDirectChatOption: Bool = true
static let roomSettingsScreenAllowChangingAccessSettings: Bool = true
static let roomSettingsScreenAllowChangingHistorySettings: Bool = true
static let roomSettingsScreenShowAddressSettings: Bool = true
static let roomSettingsScreenShowFlairSettings: Bool = true
static let roomSettingsScreenShowAdvancedSettings: Bool = true
// MARK: - Message
static let messageDetailsAllowShare: Bool = true
static let messageDetailsAllowPermalink: Bool = true
static let messageDetailsAllowViewSource: Bool = true
static let messageDetailsAllowSave: Bool = true
// MARK: - HTTP
/// Additional HTTP headers will be sent by all requests. Not recommended to use request-specific headers, like `Authorization`.
/// Empty dictionary by default.
static let httpAdditionalHeaders: [String: String] = [:]
// MARK: - Authentication Screen
static let authScreenShowRegister = true
static let authScreenShowPhoneNumber = true
static let authScreenShowForgotPassword = true
static let authScreenShowCustomServerOptions = true
}

View file

@ -40,6 +40,11 @@ class CommonConfiguration: NSObject, Configurable {
// Enable lazy loading
settings.syncWithLazyLoadOfRoomMembers = true
settings.messageDetailsAllowSharing = BuildSettings.messageDetailsAllowShare
settings.messageDetailsAllowSaving = BuildSettings.messageDetailsAllowSave
MXKContactManager.shared().allowLocalContactsAccess = BuildSettings.allowLocalContactsAccess
}
private func setupMatrixSDKSettings() {
@ -59,6 +64,12 @@ class CommonConfiguration: NSObject, Configurable {
// Use UIKit BackgroundTask for handling background tasks in the SDK
sdkOptions.backgroundModeHandler = MXUIKitBackgroundModeHandler()
// Pass httpAdditionalHeaders to the SDK
sdkOptions.httpAdditionalHeaders = BuildSettings.httpAdditionalHeaders
// Disable key backup on common
sdkOptions.enableKeyBackupWhenStartingMXCrypto = false
}

157
INSTALL.md Normal file
View file

@ -0,0 +1,157 @@
# Installation
## Install build tools
To build Element iOS project you need:
- Xcode 11.4+.
- [Ruby](https://www.ruby-lang.org/), a dynamic programming language used by several build tools.
- [cmake](https://gitlab.kitware.com/cmake/cmake), used to build [cmark](https://github.com/commonmark/cmark) dependency of [MatrixKit](https://github.com/matrix-org/matrix-ios-kit) pod.
- [CocoaPods](https://cocoapods.org) 1.9.3. Manages library dependencies for Xcode projects.
- [Homebrew](http://brew.sh/) (recommended), is a package manager for macOS that can be used to install cmake.
- [bundler](https://bundler.io/) (optional), is also a dependency manager used to manage build tools dependency (CocoaPods, Fastlane).
### Install Ruby
Ruby is required for several build tools like CocoaPods, bundler and fastlane. Ruby is preinstalled on macOS, the system version is sufficient to build the porject tools, it's not required to install the latest version. If you want to install the lastest version of Ruby please check [official instructions](https://www.ruby-lang.org/en/documentation/installation/#homebrew).
If you do not want to grant the ruby package manager, [RubyGems](https://rubygems.org/), admin privileges and you prefer install gems into your user directory, you can read instructions from the CocoaPods [guide about sudo-less installation](https://guides.cocoapods.org/using/getting-started.html#sudo-less-installation).
### Install cmake
There are several ways to install cmake, downloading binary from [official website](https://cmake.org/download/) or using a package manager like [MacPorts](https://ports.macports.org/port/cmake/summary) or [Homebrew](http://brew.sh/).
To keep it up to date, we recommend you to install cmake using [Homebrew](http://brew.sh/):
```
brew install cmake
```
### Install CocoaPods
To install CocoaPods you can grab the right version by using `bundler` (recommended) or you can directly install it with RubyGems:
```
gem install cocoapods
```
In the last case please ensure that you are using the same version as indicated at the end of the `Podfile.lock` file.
### Install bundler (optional)
By using `bundler` you will ensure to use the right versions of build tools used to build and deliver the project. You can find dependency definitions in the `Gemfile`. To install `bundler`:
```
gem install bundler
```
## Choose Matrix SDKs version to build
To choose the [MatrixKit](https://github.com/matrix-org/matrix-ios-kit) version (and depending MatrixSDK and OLMKit) you want to develop and build against you will have to modify the right definitions of `$matrixKitVersion` variable in the `Podfile`.
### Determine your needs
To select which `$matrixKitVersion` value to use you have to determine your needs:
- **Build an App Store release version**
To build the last published App Store code you just need to checkout master branch. If you want to build an older App Store version just checkout the tag of the corresponding version. You have nothing to modify in the `Podfile`. In this case `$matrixKitVersion` will be set to a specific version of the MatrixKit already published on CocoaPods repository.
- **Build last development code and modify Element project only**
If you want to build last development code you have to checkout the develop branch and use `$matrixKitVersion = {'develop' => 'develop'}` in the `Podfile`. This will also use MatrixKit and MatrixSDK develop branches.
- **Build specific branch of Kit and SDK and modify Element project only**
If you want to build a specific branch for the MatrixKit and the MatrixSDK you have to indicate them using a dictionary like this: `$matrixKitVersion = {'kit branch name' => 'sdk branch name'}`.
- **Build any branch and be able to modify MatrixKit and MatrixSDK locally**
If you want to modify MatrixKit and/or MatrixSDK locally and see the result in Element project you have to uncommment `$matrixKitVersion = :local` in the `Podfile`.
But before you have to checkout [MatrixKit](https://github.com/matrix-org/matrix-ios-kit) repository in `../matrix-ios-kit` and [MatrixSDK](https://github.com/matrix-org/matrix-ios-sdk) in `../matrix-ios-sdk` locally relatively to your Element iOS project folder.
Be sure to use compatible branches for Element iOS, MatrixKit and MatrixSDK. For example if you want to modify Element iOS from develop branch use MatrixKit and MatrixSDK develop branches and then make your modifications.
**Important**: By working with local pods (development pods) you will need to use legacy build system in Xcode, to have your local changes taken into account. To enable it go to Xcode menu and select `File > Workspace Settings… > Build System` and then choose `Legacy Build System`.
### Modify `$matrixKitVersion` after installation of dependencies
Assuming you have already completed the **Install dependencies** instructions from **Build** section below.
Each time you edit `$matrixKitVersion` variable in the `Podfile` you will have to run the `pod install` command.
## Build
### Install dependencies
Before opening the Element Xcode workspace, you need to install dependencies via CocoaPods.
To be sure to use the right CocoaPods version you can use `bundler`:
```
$ cd Riot
$ bundle install
$ bundle exec pod install
```
Or if you prefer to use directly CocoaPods:
```
$ cd Riot
$ pod install
```
This will load all dependencies for the Element source code, including [MatrixKit](https://github.com/matrix-org/matrix-ios-kit)
and [MatrixSDK](https://github.com/matrix-org/matrix-ios-sdk).
### Open workspace
Then, open `Riot.xcworkspace` with Xcode.
```
$ open Riot.xcworkspace
```
**Note**: If you have multiple Xcode versions installed don't forget to use the right version of Command Line Tools when you are building the app. To check the Command Line Tools version go to `Xcode > Preferences > Locations > Command Line Tools` and check that the displayed version match your Xcode version.
### Configure project
You may need to change the bundle identifier and app group identifier to be unique to get Xcode to build the app. Make sure to change the bundle identifier, application group identifier and app name in the `Config/Common.xcconfig` file to your new identifiers.
## Generate IPA
To build the IPA we are currently using [fastlane](https://fastlane.tools/).
**Set your project informations**
Before making the release you need to modify the `fastlane/.env.default` file and set all your project informations like your App ID, Team ID, certificate names and so on.
**Install or update build tools**
The preferred way to use the fastlane script is to use `bundler`, to be sure to use the right dependency versions.
After opening the terminal in the project root folder. The first time you perform a release you need to run:
`bundle install`
For other times:
`bundle update`
**Run fastlane script**
Before executing the release command you need to export your Apple ID in environment variables:
`export APPLE_ID="foo.bar@apple.com"`
To make an App Store release you can directly execute this command:
`bundle exec fastlane app_store build_number:<your_build_number>`
Or you can use the wrapper script located at `/Tools/Release/buildRelease.sh`. For that go to the `Release` folder:
`$ cd ./Tools/Release/`
And then indicate a branch or a tag like this:
`$ ./buildRelease.sh <tag or branch>`

View file

@ -11,7 +11,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.12.12'
$matrixKitVersion = '= 0.12.15'
# $matrixKitVersion = :local
# $matrixKitVersion = {'develop' => 'develop'}

View file

@ -16,27 +16,27 @@ PODS:
- AFNetworking/NSURLSession
- cmark (0.24.1)
- DGCollectionViewLeftAlignFlowLayout (1.0.4)
- DTCoreText (1.6.24):
- DTCoreText/Core (= 1.6.24)
- DTCoreText (1.6.25):
- DTCoreText/Core (= 1.6.25)
- DTFoundation/Core (~> 1.7.5)
- DTFoundation/DTAnimatedGIF (~> 1.7.5)
- DTFoundation/DTHTMLParser (~> 1.7.5)
- DTFoundation/UIKit (~> 1.7.5)
- DTCoreText/Core (1.6.24):
- DTCoreText/Core (1.6.25):
- DTFoundation/Core (~> 1.7.5)
- DTFoundation/DTAnimatedGIF (~> 1.7.5)
- DTFoundation/DTHTMLParser (~> 1.7.5)
- DTFoundation/UIKit (~> 1.7.5)
- DTCoreText/Extension (1.6.24):
- DTCoreText/Extension (1.6.25):
- DTFoundation/Core (~> 1.7.5)
- DTFoundation/DTAnimatedGIF (~> 1.7.5)
- DTFoundation/DTHTMLParser (~> 1.7.5)
- DTFoundation/UIKit (~> 1.7.5)
- DTFoundation/Core (1.7.14)
- DTFoundation/DTAnimatedGIF (1.7.14)
- DTFoundation/DTHTMLParser (1.7.14):
- DTFoundation/Core (1.7.15)
- DTFoundation/DTAnimatedGIF (1.7.15)
- DTFoundation/DTHTMLParser (1.7.15):
- DTFoundation/Core
- DTFoundation/UIKit (1.7.14):
- DTFoundation/UIKit (1.7.15):
- DTFoundation/Core
- FlowCommoniOS (1.8.7)
- GBDeviceInfo (6.3.0):
@ -52,38 +52,38 @@ PODS:
- MatomoTracker (7.2.1):
- MatomoTracker/Core (= 7.2.1)
- MatomoTracker/Core (7.2.1)
- MatrixKit (0.12.12):
- MatrixKit (0.12.15):
- cmark (~> 0.24.1)
- DTCoreText (~> 1.6.23)
- HPGrowingTextView (~> 1.1)
- libPhoneNumber-iOS (~> 0.9.13)
- MatrixKit/Core (= 0.12.12)
- MatrixSDK (= 0.16.11)
- MatrixKit/AppExtension (0.12.12):
- MatrixKit/Core (= 0.12.15)
- MatrixSDK (= 0.16.13)
- MatrixKit/AppExtension (0.12.15):
- cmark (~> 0.24.1)
- DTCoreText (~> 1.6.23)
- DTCoreText/Extension
- HPGrowingTextView (~> 1.1)
- libPhoneNumber-iOS (~> 0.9.13)
- MatrixSDK (= 0.16.11)
- MatrixKit/Core (0.12.12):
- MatrixSDK (= 0.16.13)
- MatrixKit/Core (0.12.15):
- cmark (~> 0.24.1)
- DTCoreText (~> 1.6.23)
- HPGrowingTextView (~> 1.1)
- libPhoneNumber-iOS (~> 0.9.13)
- MatrixSDK (= 0.16.11)
- MatrixSDK (0.16.11):
- MatrixSDK/Core (= 0.16.11)
- MatrixSDK/Core (0.16.11):
- MatrixSDK (= 0.16.13)
- MatrixSDK (0.16.13):
- MatrixSDK/Core (= 0.16.13)
- MatrixSDK/Core (0.16.13):
- AFNetworking (~> 4.0.0)
- GZIP (~> 1.2.2)
- libbase58 (~> 0.1.4)
- OLMKit (~> 3.1.0)
- Realm (~> 4.4.0)
- MatrixSDK/JingleCallStack (0.16.11):
- MatrixSDK/JingleCallStack (0.16.13):
- JitsiMeetSDK (~> 2.8.1)
- MatrixSDK/Core
- MatrixSDK/SwiftSupport (0.16.11):
- MatrixSDK/SwiftSupport (0.16.13):
- MatrixSDK/Core
- OLMKit (3.1.0):
- OLMKit/olmc (= 3.1.0)
@ -113,8 +113,8 @@ DEPENDENCIES:
- KeychainAccess (~> 4.2)
- KTCenterFlowLayout (~> 1.3.1)
- MatomoTracker (~> 7.2.0)
- MatrixKit (= 0.12.12)
- MatrixKit/AppExtension (= 0.12.12)
- MatrixKit (= 0.12.15)
- MatrixKit/AppExtension (= 0.12.15)
- MatrixSDK
- MatrixSDK/JingleCallStack
- MatrixSDK/SwiftSupport
@ -156,8 +156,8 @@ SPEC CHECKSUMS:
AFNetworking: 7864c38297c79aaca1500c33288e429c3451fdce
cmark: 1d9ad0375e3b9fa281732e992467903606015520
DGCollectionViewLeftAlignFlowLayout: a0fa58797373ded039cafba8133e79373d048399
DTCoreText: 0298d372ccc137e51f27b3ec1af65fd4af5d173a
DTFoundation: 25aa19bb7c6e225b1dfae195604fb8cf1da0ab4c
DTCoreText: e92f4cf6b36d9d71ce4436d12cf089d74ab0596b
DTFoundation: 767ca882209ef4d5132ec7e702526d5ed5bb71a2
FlowCommoniOS: 1647a1775b988f5d97202f635bcbcbce4f4c46a1
GBDeviceInfo: a3f39dba1a04dcb630abff65d6f7e8fbf319eadd
GZIP: af5c90ef903776a7e9afe6ebebd794a84a2929d4
@ -168,8 +168,8 @@ SPEC CHECKSUMS:
libbase58: 7c040313537b8c44b6e2d15586af8e21f7354efd
libPhoneNumber-iOS: 0a32a9525cf8744fe02c5206eb30d571e38f7d75
MatomoTracker: 246b6b0693cf39b356134dec7561f719d3538b96
MatrixKit: cb92677c837ca56448a2f938717c9be6c7d03973
MatrixSDK: 021fe99187eb3eb6999997039bcdcfcacb8b50aa
MatrixKit: 0fcc9a131a120637d7da37db2e02ab22241f171d
MatrixSDK: f96afe337d5a408c33a4a67a198afaf5cade56e7
OLMKit: 4ee0159d63feeb86d836fdcfefe418e163511639
Realm: 4eb04d7487bd43c0581256f40b424eafb711deff
Reusable: 53a9acf5c536f229b31b5865782414b508252ddb
@ -178,6 +178,6 @@ SPEC CHECKSUMS:
zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb
PODFILE CHECKSUM: c9fbf64577fd39d125dfea51f638685bde771786
PODFILE CHECKSUM: 4b6b00d796458412d40d8a1e776fd1ce8de97631
COCOAPODS: 1.9.3

51
README.md Normal file
View file

@ -0,0 +1,51 @@
# Element iOS
![GitHub release (latest by date)](https://img.shields.io/github/v/release/vector-im/element-ios)
![badge-languages](https://img.shields.io/badge/languages-Swift%20%7C%20ObjC-orange.svg)
[![Swift 5.x](https://img.shields.io/badge/Swift-5.x-orange)](https://developer.apple.com/swift)
[![Build status](https://badge.buildkite.com/cc8f93e32da93fa7c1172398bd8af66254490567c7195a5f3f.svg?branch=develop)](https://buildkite.com/matrix-dot-org/element-ios/builds?branch=develop)
[![Weblate](https://translate.riot.im/widgets/riot-ios/-/svg-badge.svg)](https://translate.riot.im/engage/riot-ios/?utm_source=widget)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=im.vector.app.ios&metric=alert_status)](https://sonarcloud.io/dashboard?id=im.vector.app.ios)
[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=im.vector.app.ios&metric=bugs)](https://sonarcloud.io/dashboard?id=im.vector.app.ios)
[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=im.vector.app.ios&metric=vulnerabilities)](https://sonarcloud.io/dashboard?id=im.vector.app.ios)
[![Element iOS Matrix room #element-ios:matrix.org](https://img.shields.io/matrix/element-ios:matrix.org.svg?label=%23element-ios:matrix.org&logo=matrix&server_fqdn=matrix.org)](https://matrix.to/#/#element-ios:matrix.org)
![GitHub](https://img.shields.io/github/license/vector-im/element-ios)
[![Twitter URL](https://img.shields.io/twitter/url?label=Element&url=https%3A%2F%2Ftwitter.com%2Felement_hq)](https://twitter.com/element_hq)
Element iOS is an iOS [Matrix](https://matrix.org/) client provided by [Element](https://element.io/). It is based on [MatrixKit](https://github.com/matrix-org/matrix-ios-kit) and [MatrixSDK](https://github.com/matrix-org/matrix-ios-sdk).
<p align="center">
<a href=https://itunes.apple.com/us/app/element/id1083446067?mt=8>
<img alt="Download on the app store" src="https://linkmaker.itunes.apple.com/images/badges/en-us/badge_appstore-lrg.svg" width=160>
</a>
</p>
## Beta testing
You can try last beta build by accessing our [TestFlight Public Link](https://testflight.apple.com/join/lCeTuDKM). For questions and feedback about latest TestFlight build, please access the Element iOS Matrix room: [#element-ios:matrix.org](https://matrix.to/#/#element-ios:matrix.org).
## Build instructions
To build the application please refer to the [installation guide](./INSTALL.md).
## Contributing
If you want to contribute to Element iOS code or translations please refer to the [contribution guide](CONTRIBUTING.md).
## Support
When you are experiencing an issue on Element iOS, please first search in [GitHub issues](https://github.com/vector-im/element-ios/issues)
and then in [#element-ios:matrix.org](https://matrix.to/#/#element-ios:matrix.org).
If after your research you still have a question, ask at [#element-ios:matrix.org](https://matrix.to/#/#element-ios:matrix.org). Otherwise feel free to create a GitHub issue if you encounter a bug or a crash, by explaining clearly in detail what happened. You can also perform bug reporting (Rageshake) from the Element application by shaking your phone or going to the application settings. This is especially recommended when you encounter a crash.
## Copyright & License
Copyright (c) 2014-2017 OpenMarket Ltd
Copyright (c) 2017 Vector Creations Ltd
Copyright (c) 2017-2020 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with the License. You may obtain a copy of the License in the [LICENSE](LICENSE) file, or at:
[http://www.apache.org/licenses/LICENSE-2.0](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.

View file

@ -1,53 +0,0 @@
Element iOS
==========
.. image:: https://img.shields.io/matrix/element-ios:matrix.org.svg?label=%23element-ios:matrix.org
:alt: #element-ios:matrix.org
:target: https://matrix.to/#/#element-ios:matrix.org
Element iOS is an iOS Matrix client.
.. image:: https://linkmaker.itunes.apple.com/images/badges/en-us/badge_appstore-lrg.svg
:target: https://itunes.apple.com/us/app/element/id1083446067?mt=8
It is based on MatrixKit (https://github.com/matrix-org/matrix-ios-kit) and MatrixSDK (https://github.com/matrix-org/matrix-ios-sdk).
You can build the app from source as per below:
Build instructions
==================
Before opening the Element Xcode workspace, you need to build it with the
CocoaPods command::
$ cd Element
$ bundle install
$ bundle exec pod install
This will load all dependencies for the Element source code, including MatrixKit
and MatrixSDK. You will need an recent and updated (``pod setup``) install of
CocoaPods.
Then, open ``Riot.xcworkspace`` with Xcode
$ open Riot.xcworkspace
Developing
==========
Uncomment the right definitions of ``$matrixKitVersion`` for the version you want to develop and build against. For example, if you are trying to build the develop branch, uncomment ``$matrixKitVersion = 'develop'`` and make sure the more specific MatrixKit version is commented out. Once you are done editing the ``Podfile``, run ``pod install``.
You may need to change the bundle identifier and app group identifier to be unique to get Xcode to build the app. Make sure to change the application group identifier everywhere by running a search for ``group.im.vector`` and changing every spot that identifier is used to your new identifier.
Copyright & License
==================
Copyright (c) 2014-2017 OpenMarket Ltd
Copyright (c) 2017 Vector Creations Ltd
Copyright (c) 2017-2019 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in compliance with the License. You may obtain a copy of the License in the LICENSE file, or 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.

View file

@ -750,8 +750,6 @@
EC1CA89A24C9C9A200DE9EBF /* SetupBiometricsCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1CA89224C9C9A200DE9EBF /* SetupBiometricsCoordinatorType.swift */; };
EC1CA89B24C9C9A200DE9EBF /* SetupBiometricsViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1CA89324C9C9A200DE9EBF /* SetupBiometricsViewState.swift */; };
EC1CA89C24C9C9A200DE9EBF /* SetupBiometricsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1CA89424C9C9A200DE9EBF /* SetupBiometricsViewModel.swift */; };
EC1CA8C824D3160100DE9EBF /* Row.m in Sources */ = {isa = PBXBuildFile; fileRef = EC1CA8C724D3160100DE9EBF /* Row.m */; };
EC1CA8CB24D3168F00DE9EBF /* Section.m in Sources */ = {isa = PBXBuildFile; fileRef = EC1CA8CA24D3168F00DE9EBF /* Section.m */; };
EC1CA8D424D8103400DE9EBF /* App-Common.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = EC1CA8D324D8103400DE9EBF /* App-Common.xcconfig */; };
EC1CA8D624D8108700DE9EBF /* ShareExtension-Common.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = EC1CA8D524D8108700DE9EBF /* ShareExtension-Common.xcconfig */; };
EC1CA8D824D8118400DE9EBF /* SiriIntents-Common.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = EC1CA8D724D8118400DE9EBF /* SiriIntents-Common.xcconfig */; };
@ -843,10 +841,14 @@
EC85D754247C0F5B002C44C9 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D753247C0F5B002C44C9 /* Constants.swift */; };
EC85D755247C0F84002C44C9 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D753247C0F5B002C44C9 /* Constants.swift */; };
EC85D757247E700F002C44C9 /* NSEMemoryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC85D756247E700F002C44C9 /* NSEMemoryStore.swift */; };
EC9A3EC524E1616900A8CFAE /* PushNotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC9A3EC424E1616900A8CFAE /* PushNotificationManager.swift */; };
EC9A3EC624E1632C00A8CFAE /* PushNotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC9A3EC424E1616900A8CFAE /* PushNotificationManager.swift */; };
EC9A3EC524E1616900A8CFAE /* PushNotificationStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC9A3EC424E1616900A8CFAE /* PushNotificationStore.swift */; };
EC9A3EC624E1632C00A8CFAE /* PushNotificationStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC9A3EC424E1616900A8CFAE /* PushNotificationStore.swift */; };
EC9A3EC724E1634100A8CFAE /* KeyValueStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1CA87124C823E700DE9EBF /* KeyValueStore.swift */; };
EC9A3EC824E1634800A8CFAE /* KeychainStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1CA87424C8259700DE9EBF /* KeychainStore.swift */; };
ECAE7AE524EC0E01002FA813 /* TableViewSections.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECAE7AE424EC0E01002FA813 /* TableViewSections.swift */; };
ECAE7AE724EC15F7002FA813 /* Section.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECAE7AE624EC15F7002FA813 /* Section.swift */; };
ECAE7AE924EC1888002FA813 /* Row.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECAE7AE824EC1888002FA813 /* Row.swift */; };
ECAE7AEE24EFDD1F002FA813 /* MXSessionState.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECAE7AED24EFDD1F002FA813 /* MXSessionState.swift */; };
ECB101302477CFDB00CF8C11 /* UITableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECB1012C2477CFDB00CF8C11 /* UITableView.swift */; };
ECB101312477CFDB00CF8C11 /* UILabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECB1012D2477CFDB00CF8C11 /* UILabel.swift */; };
ECB101322477CFDB00CF8C11 /* UIDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECB1012E2477CFDB00CF8C11 /* UIDevice.swift */; };
@ -986,7 +988,6 @@
3267EFB320E379FD00FF1CAA /* CHANGES.rst */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGES.rst; sourceTree = "<group>"; };
3267EFB420E379FD00FF1CAA /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; fileEncoding = 4; path = Podfile; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
3267EFB520E379FD00FF1CAA /* AUTHORS.rst */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = AUTHORS.rst; sourceTree = "<group>"; };
3267EFB620E379FD00FF1CAA /* README.rst */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.rst; sourceTree = "<group>"; };
3275FD8B21A5A2C500B9C13D /* TermsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsView.swift; sourceTree = "<group>"; };
3281BCF62201FA4200F4A383 /* UIControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIControl.swift; sourceTree = "<group>"; };
3284A35020A07C210044F922 /* postMessageAPI.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = postMessageAPI.js; sourceTree = "<group>"; };
@ -1697,6 +1698,7 @@
B1B5598F20EFC5E400210D55 /* DecryptionFailure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DecryptionFailure.h; sourceTree = "<group>"; };
B1B5599020EFC5E400210D55 /* Analytics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Analytics.h; sourceTree = "<group>"; };
B1B5599120EFC5E400210D55 /* DecryptionFailureTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DecryptionFailureTracker.m; sourceTree = "<group>"; };
B1B7F22824F3F8E900FD567B /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
B1B9194A2118984300FE25B5 /* RoomPredecessorBubbleCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RoomPredecessorBubbleCell.xib; sourceTree = "<group>"; };
B1B9DED922E9B7350065E677 /* SerializationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SerializationService.swift; sourceTree = "<group>"; };
B1B9DEDB22E9B7440065E677 /* SerializationServiceType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SerializationServiceType.swift; sourceTree = "<group>"; };
@ -1877,10 +1879,6 @@
EC1CA8BB24D1B4BF00DE9EBF /* SiriIntents-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "SiriIntents-Debug.xcconfig"; sourceTree = "<group>"; };
EC1CA8BC24D1B4CF00DE9EBF /* NSE-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "NSE-Debug.xcconfig"; sourceTree = "<group>"; };
EC1CA8BD24D1B4CF00DE9EBF /* NSE-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "NSE-Release.xcconfig"; sourceTree = "<group>"; };
EC1CA8C624D3160100DE9EBF /* Row.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Row.h; sourceTree = "<group>"; };
EC1CA8C724D3160100DE9EBF /* Row.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Row.m; sourceTree = "<group>"; };
EC1CA8C924D3168F00DE9EBF /* Section.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Section.h; sourceTree = "<group>"; };
EC1CA8CA24D3168F00DE9EBF /* Section.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Section.m; sourceTree = "<group>"; };
EC1CA8D324D8103400DE9EBF /* App-Common.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "App-Common.xcconfig"; sourceTree = "<group>"; };
EC1CA8D524D8108700DE9EBF /* ShareExtension-Common.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "ShareExtension-Common.xcconfig"; sourceTree = "<group>"; };
EC1CA8D724D8118400DE9EBF /* SiriIntents-Common.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = "SiriIntents-Common.xcconfig"; sourceTree = "<group>"; };
@ -1975,7 +1973,11 @@
EC85D750247C0E8F002C44C9 /* UNUserNotificationCenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UNUserNotificationCenter.swift; sourceTree = "<group>"; };
EC85D753247C0F5B002C44C9 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
EC85D756247E700F002C44C9 /* NSEMemoryStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSEMemoryStore.swift; sourceTree = "<group>"; };
EC9A3EC424E1616900A8CFAE /* PushNotificationManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushNotificationManager.swift; sourceTree = "<group>"; };
EC9A3EC424E1616900A8CFAE /* PushNotificationStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushNotificationStore.swift; sourceTree = "<group>"; };
ECAE7AE424EC0E01002FA813 /* TableViewSections.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewSections.swift; sourceTree = "<group>"; };
ECAE7AE624EC15F7002FA813 /* Section.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Section.swift; sourceTree = "<group>"; };
ECAE7AE824EC1888002FA813 /* Row.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Row.swift; sourceTree = "<group>"; };
ECAE7AED24EFDD1F002FA813 /* MXSessionState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MXSessionState.swift; sourceTree = "<group>"; };
ECB1012C2477CFDB00CF8C11 /* UITableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UITableView.swift; sourceTree = "<group>"; };
ECB1012D2477CFDB00CF8C11 /* UILabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UILabel.swift; sourceTree = "<group>"; };
ECB1012E2477CFDB00CF8C11 /* UIDevice.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIDevice.swift; sourceTree = "<group>"; };
@ -3197,7 +3199,6 @@
B1B5567720EE6C4C00210D55 /* Settings */ = {
isa = PBXGroup;
children = (
EC1CA8C524D315EA00DE9EBF /* Models */,
B1B5567F20EE6C4C00210D55 /* SettingsViewController.h */,
B1B5567E20EE6C4C00210D55 /* SettingsViewController.m */,
B1B5578120EF564900210D55 /* Views */,
@ -3467,6 +3468,7 @@
B1B556CD20EE6C4C00210D55 /* Common */ = {
isa = PBXGroup;
children = (
ECAE7AEA24EC223D002FA813 /* Models */,
EC85D7312477DD54002C44C9 /* SectionHeaders */,
B183226923F59F3E0035B2E8 /* Buttons */,
B1963B3622933B9500CBA17F /* CollectionView */,
@ -4613,17 +4615,6 @@
path = SetupBiometrics;
sourceTree = "<group>";
};
EC1CA8C524D315EA00DE9EBF /* Models */ = {
isa = PBXGroup;
children = (
EC1CA8C624D3160100DE9EBF /* Row.h */,
EC1CA8C724D3160100DE9EBF /* Row.m */,
EC1CA8C924D3168F00DE9EBF /* Section.h */,
EC1CA8CA24D3168F00DE9EBF /* Section.m */,
);
path = Models;
sourceTree = "<group>";
};
EC3B066324AC6ADD000DF9BF /* CrossSigning */ = {
isa = PBXGroup;
children = (
@ -4838,7 +4829,7 @@
children = (
EC85D73C2477DDD0002C44C9 /* PushNotificationService.h */,
EC85D73D2477DDD0002C44C9 /* PushNotificationService.m */,
EC9A3EC424E1616900A8CFAE /* PushNotificationManager.swift */,
EC9A3EC424E1616900A8CFAE /* PushNotificationStore.swift */,
);
path = PushNotification;
sourceTree = "<group>";
@ -4857,6 +4848,16 @@
path = RiotNSE;
sourceTree = "<group>";
};
ECAE7AEA24EC223D002FA813 /* Models */ = {
isa = PBXGroup;
children = (
ECAE7AE424EC0E01002FA813 /* TableViewSections.swift */,
ECAE7AE624EC15F7002FA813 /* Section.swift */,
ECAE7AE824EC1888002FA813 /* Row.swift */,
);
path = Models;
sourceTree = "<group>";
};
F083BB021E7005FD00A9B29C /* RiotTests */ = {
isa = PBXGroup;
children = (
@ -4965,6 +4966,7 @@
B1DCC63322E72C1B00625807 /* UISearchBar.swift */,
B11291EB238D704C0077B478 /* FloatingPoint.swift */,
32FD757524D2C9BA00BA7B37 /* Bundle.swift */,
ECAE7AED24EFDD1F002FA813 /* MXSessionState.swift */,
);
path = Categories;
sourceTree = "<group>";
@ -5015,7 +5017,7 @@
F094A9991B78D8F000B1FBBF = {
isa = PBXGroup;
children = (
3267EFB620E379FD00FF1CAA /* README.rst */,
B1B7F22824F3F8E900FD567B /* README.md */,
3267EFB320E379FD00FF1CAA /* CHANGES.rst */,
3267EFB520E379FD00FF1CAA /* AUTHORS.rst */,
3267EFB420E379FD00FF1CAA /* Podfile */,
@ -5706,7 +5708,7 @@
EC2B4EF224A1EF34005EB739 /* DataProtectionHelper.swift in Sources */,
EC85D7462477E5F7002C44C9 /* NotificationService.swift in Sources */,
32FD755424D074C700BA7B37 /* CommonConfiguration.swift in Sources */,
EC9A3EC624E1632C00A8CFAE /* PushNotificationManager.swift in Sources */,
EC9A3EC624E1632C00A8CFAE /* PushNotificationStore.swift in Sources */,
32FD757424D2BEF700BA7B37 /* InfoPlist.swift in Sources */,
EC85D752247C0F52002C44C9 /* UNUserNotificationCenter.swift in Sources */,
EC9A3EC724E1634100A8CFAE /* KeyValueStore.swift in Sources */,
@ -5898,6 +5900,7 @@
F05927C91FDED836009F2A68 /* MXGroup+Riot.m in Sources */,
B1B5594520EF7BD000210D55 /* TableViewCellWithCollectionView.m in Sources */,
B1A6C109238828A6002882FD /* SlidingModalPresentationDelegate.swift in Sources */,
ECAE7AEE24EFDD1F002FA813 /* MXSessionState.swift in Sources */,
32DB557722FDADE50016329E /* ServiceTermsModalCoordinator.swift in Sources */,
B185145B24B8C98200EE19EA /* MajorUpdateViewController.swift in Sources */,
32DB557922FDADE50016329E /* ServiceTermsModalScreenViewModel.swift in Sources */,
@ -6058,7 +6061,6 @@
B1A6C10D23882D1D002882FD /* SlidingModalPresentationController.swift in Sources */,
32A6001D22C661100042C1D9 /* EditHistoryCoordinatorType.swift in Sources */,
F083BDFA1E7009ED00A9B29C /* RoomPreviewData.m in Sources */,
EC1CA8CB24D3168F00DE9EBF /* Section.m in Sources */,
B1B557B420EF5AEF00210D55 /* EventDetailsView.m in Sources */,
EC85D751247C0E8F002C44C9 /* UNUserNotificationCenter.swift in Sources */,
B1BEE73823DF44A60003A4CB /* UserVerificationSessionsStatusViewAction.swift in Sources */,
@ -6083,7 +6085,6 @@
EC711B7624A63B37008F830C /* SecretsSetupRecoveryKeyViewState.swift in Sources */,
32FDC1CD2386CD390084717A /* RiotSettingIntegrationProvisioning.swift in Sources */,
B1BEE73523DF44A60003A4CB /* UserVerificationSessionsStatusViewModel.swift in Sources */,
EC1CA8C824D3160100DE9EBF /* Row.m in Sources */,
B1B5572020EE6C4D00210D55 /* ContactsTableViewController.m in Sources */,
EC85D7142477DCD7002C44C9 /* KeyVerificationScanConfirmationViewState.swift in Sources */,
EC711B9124A63B37008F830C /* SecretsRecoveryWithKeyCoordinatorType.swift in Sources */,
@ -6171,7 +6172,7 @@
EC711BA924A63B58008F830C /* SecureBackupSetupCoordinatorBridgePresenter.swift in Sources */,
B1B558C720EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.m in Sources */,
B1B336C5242B933700F95EC4 /* KeyVerificationSelfVerifyStartViewModel.swift in Sources */,
EC9A3EC524E1616900A8CFAE /* PushNotificationManager.swift in Sources */,
EC9A3EC524E1616900A8CFAE /* PushNotificationStore.swift in Sources */,
B1B558F020EF768F00210D55 /* RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m in Sources */,
926FA53F1F4C132000F826C2 /* MXSession+Riot.m in Sources */,
EC711B8324A63B37008F830C /* SecretsSetupRecoveryPassphraseCoordinator.swift in Sources */,
@ -6224,6 +6225,7 @@
B14084CE23BFA0990010F692 /* KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.swift in Sources */,
B14F143222144F6500FA0595 /* KeyBackupRecoverFromRecoveryKeyCoordinator.swift in Sources */,
B110872621F098F0003554A5 /* ActivityIndicatorView.swift in Sources */,
ECAE7AE924EC1888002FA813 /* Row.swift in Sources */,
B1CE83E02422817200D07506 /* KeyVerificationVerifyBySASViewController.swift in Sources */,
B19EFA3921F8BB2C00FC070E /* KeyBackupRecoverCoordinatorType.swift in Sources */,
B1C3360322F1ED600021BA8D /* MediaPickerCoordinator.swift in Sources */,
@ -6294,6 +6296,7 @@
B125FE1B231D5BF200B72806 /* SettingsDiscoveryTableViewSection.swift in Sources */,
B18DEDD5243377C10075FEF7 /* KeyVerificationSelfVerifyWaitViewModel.swift in Sources */,
EC711B8B24A63B37008F830C /* SecretsRecoveryWithPassphraseViewState.swift in Sources */,
ECAE7AE524EC0E01002FA813 /* TableViewSections.swift in Sources */,
B1CE83DA2422817200D07506 /* KeyVerificationVerifyByScanningViewModel.swift in Sources */,
32242F0921E8B05F00725742 /* UIColor.swift in Sources */,
B16932E720F3C37100746532 /* HomeMessagesSearchDataSource.m in Sources */,
@ -6311,6 +6314,7 @@
B1B558FF20EF768F00210D55 /* RoomIncomingTextMsgBubbleCell.m in Sources */,
EC85D7342477DD54002C44C9 /* SectionHeaderView.m in Sources */,
B1098C0021ECFE65000DDA48 /* KeyBackupSetupPassphraseViewController.swift in Sources */,
ECAE7AE724EC15F7002FA813 /* Section.swift in Sources */,
B1B5591020EF782800210D55 /* TableViewCellWithPhoneNumberTextField.m in Sources */,
B1CE83E52422817200D07506 /* KeyVerificationVerifyBySASViewModel.swift in Sources */,
B1DB4F06223015080065DBFA /* Character.swift in Sources */,
@ -6715,7 +6719,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1.0.5;
CURRENT_PROJECT_VERSION = 1.0.6;
DEFINES_MODULE = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@ -6735,7 +6739,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 1.0.5;
MARKETING_VERSION = 1.0.6;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@ -6773,7 +6777,7 @@
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = YES;
CURRENT_PROJECT_VERSION = 1.0.5;
CURRENT_PROJECT_VERSION = 1.0.6;
DEFINES_MODULE = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@ -6786,7 +6790,7 @@
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 1.0.5;
MARKETING_VERSION = 1.0.6;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;

View file

@ -74,7 +74,7 @@ extern NSString *const AppDelegateUniversalLinkDidChangeNotification;
/**
Let the AppDelegate handle and display self verification requests.
Default is YES;
Default is YES.
*/
@property (nonatomic) BOOL handleSelfVerificationRequest;

View file

@ -237,6 +237,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
Related push notification service instance. Will be created when launch finished.
*/
@property (nonatomic, strong) PushNotificationService *pushNotificationService;
@property (nonatomic, strong) PushNotificationStore *pushNotificationStore;
@property (nonatomic, strong) LocalAuthenticationService *localAuthenticationService;
@property (nonatomic, strong) MajorUpdateManager *majorUpdateManager;
@ -412,23 +413,6 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
NSLog(@"[AppDelegate] didFinishLaunchingWithOptions");
#endif
// User credentials (in MXKAccount) are no more stored in NSUserDefaults but in a file
// as advised at https://forums.developer.apple.com/thread/15685#45849.
// So, there is no more need to loop (sometimes forever) until
// [application isProtectedDataAvailable] becomes YES.
// But, as we are not so sure, loop but no more than 10s.
// // TODO: Remove this loop.
// NSUInteger loopCount = 0;
//
// // Check whether the content protection is active before going further.
// // Should fix the spontaneous logout.
// while (![application isProtectedDataAvailable] && loopCount++ < 50)
// {
// // Wait for protected data.
// [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.2f]];
// }
//
// NSLog(@"[AppDelegate] didFinishLaunchingWithOptions: isProtectedDataAvailable: %@ (%tu)", @([application isProtectedDataAvailable]), loopCount);
NSLog(@"[AppDelegate] didFinishLaunchingWithOptions: isProtectedDataAvailable: %@", @([application isProtectedDataAvailable]));
_configuration = [AppConfiguration new];
@ -510,7 +494,8 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
self.localAuthenticationService = [[LocalAuthenticationService alloc] initWithPinCodePreferences:[PinCodePreferences shared]];
self.pushNotificationService = [[PushNotificationService alloc] initWithPushNotificationManager:PushNotificationManager.shared];
self.pushNotificationStore = [PushNotificationStore new];
self.pushNotificationService = [[PushNotificationService alloc] initWithPushNotificationStore:self.pushNotificationStore];
self.pushNotificationService.delegate = self;
// Add matrix observers, and initialize matrix sessions if the app is not launched in background.
@ -1993,14 +1978,6 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
// Use MXFileStore as MXStore to permanently store events.
accountManager.storeClass = [MXFileStore class];
// Disable APNS use.
// if (accountManager.apnsDeviceToken)
// {
// // We use now Pushkit, unregister for all remote notifications received via Apple Push Notification service.
// [[UIApplication sharedApplication] unregisterForRemoteNotifications];
// [accountManager setApnsDeviceToken:nil];
// }
// Observers have been defined, we can start a matrix session for each enabled accounts.
NSLog(@"[AppDelegate] initMatrixSessions: prepareSessionForActiveAccounts (app state: %tu)", [[UIApplication sharedApplication] applicationState]);
@ -2250,8 +2227,8 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
// Reset user pin code
[PinCodePreferences.shared reset];
// Reset push notification manager
[PushNotificationManager.shared reset];
// Reset push notification store
[self.pushNotificationStore reset];
#ifdef MX_CALL_STACK_ENDPOINT
// Erase all created certificates and private keys by MXEndpointCallStack
@ -2430,6 +2407,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
// Stay in launching during the first server sync if the store is empty.
isLaunching = (mainSession.rooms.count == 0 && launchAnimationContainerView);
default:
isLaunching = NO;
break;
}

View file

@ -1121,6 +1121,7 @@
"device_verification_self_verify_wait_recover_secrets_without_passphrase" = "Use Recovery Key";
"device_verification_self_verify_wait_recover_secrets_with_passphrase" = "Use Recovery Passphrase or Key";
"device_verification_self_verify_wait_recover_secrets_additional_information" = "If you can't accessing an existing session";
"device_verification_self_verify_wait_recover_secrets_checking_availability" = "Checking for other verification capabilities ...";
// MARK: Verify

View file

@ -14,22 +14,12 @@
// limitations under the License.
//
#import "Row.h"
import Foundation
@implementation Row
+ (instancetype)rowWithTag:(NSInteger)tag
{
return [[self alloc] initWithTag:tag];
}
- (instancetype)initWithTag:(NSInteger)tag
{
self = [super init];
if (self) {
self.tag = tag;
extension MXSessionState: Comparable {
public static func < (lhs: MXSessionState, rhs: MXSessionState) -> Bool {
return lhs.rawValue < rhs.rawValue
}
return self;
}
@end

View file

@ -135,7 +135,8 @@ internal struct ImageAsset {
#if os(iOS) || os(tvOS)
let image = Image(named: name, in: bundle, compatibleWith: nil)
#elseif os(macOS)
let image = bundle.image(forResource: NSImage.Name(name))
let name = NSImage.Name(self.name)
let image = (bundle == .main) ? NSImage(named: name) : bundle.image(forResource: name)
#elseif os(watchOS)
let image = Image(named: name)
#endif

View file

@ -52,8 +52,7 @@ internal enum InfoPlist {
// MARK: - Implementation Details
private func arrayFromPlist<T>(at path: String) -> [T] {
let bundle = BundleToken.bundle
guard let url = bundle.url(forResource: path, withExtension: nil),
guard let url = BundleToken.bundle.url(forResource: path, withExtension: nil),
let data = NSArray(contentsOf: url) as? [T] else {
fatalError("Unable to load PLIST at path: \(path)")
}
@ -64,8 +63,7 @@ private struct PlistDocument {
let data: [String: Any]
init(path: String) {
let bundle = BundleToken.bundle
guard let url = bundle.url(forResource: path, withExtension: nil),
guard let url = BundleToken.bundle.url(forResource: path, withExtension: nil),
let data = NSDictionary(contentsOf: url) as? [String: Any] else {
fatalError("Unable to load PLIST at path: \(path)")
}

View file

@ -926,6 +926,10 @@ internal enum VectorL10n {
internal static var deviceVerificationSelfVerifyWaitRecoverSecretsAdditionalInformation: String {
return VectorL10n.tr("Vector", "device_verification_self_verify_wait_recover_secrets_additional_information")
}
/// Checking for other verification capabilities ...
internal static var deviceVerificationSelfVerifyWaitRecoverSecretsCheckingAvailability: String {
return VectorL10n.tr("Vector", "device_verification_self_verify_wait_recover_secrets_checking_availability")
}
/// Use Recovery Passphrase or Key
internal static var deviceVerificationSelfVerifyWaitRecoverSecretsWithPassphrase: String {
return VectorL10n.tr("Vector", "device_verification_self_verify_wait_recover_secrets_with_passphrase")

View file

@ -34,8 +34,8 @@ NS_ASSUME_NONNULL_BEGIN
+ (instancetype)new NS_UNAVAILABLE;
/// Designated initializer
/// @param pushNotificationManager Push Notification Manager instance
- (instancetype)initWithPushNotificationManager:(PushNotificationManager *)pushNotificationManager;
/// @param pushNotificationStore Push Notification Store instance
- (instancetype)initWithPushNotificationStore:(PushNotificationStore *)pushNotificationStore;
/**
Is push really registered.

View file

@ -22,16 +22,14 @@
#import <PushKit/PushKit.h>
@interface PushNotificationService()<PKPushRegistryDelegate>
{
/**
Matrix session observer used to detect new opened sessions.
*/
id matrixSessionStateObserver;
}
/**
Matrix session observer used to detect new opened sessions.
*/
@property (nonatomic, weak) id matrixSessionStateObserver;
@property (nonatomic, nullable, copy) void (^registrationForRemoteNotificationsCompletion)(NSError *);
@property (nonatomic, strong) PKPushRegistry *pushRegistry;
@property (nonatomic, strong) PushNotificationManager *pushNotificationManager;
@property (nonatomic, strong) PushNotificationStore *pushNotificationStore;
/// Should PushNotificationService receive VoIP pushes
@property (nonatomic, assign) BOOL shouldReceiveVoIPPushes;
@ -40,11 +38,11 @@
@implementation PushNotificationService
- (instancetype)initWithPushNotificationManager:(PushNotificationManager *)pushNotificationManager
- (instancetype)initWithPushNotificationStore:(PushNotificationStore *)pushNotificationStore
{
if (self = [super init])
{
self.pushNotificationManager = pushNotificationManager;
self.pushNotificationStore = pushNotificationStore;
_pushRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
self.shouldReceiveVoIPPushes = YES;
}
@ -117,7 +115,7 @@
_isPushRegistered = YES;
if (!_pushNotificationManager.pushKitToken)
if (!_pushNotificationStore.pushKitToken)
{
[self configurePushKit];
}
@ -162,7 +160,7 @@
- (void)applicationDidEnterBackground
{
if (_pushNotificationManager.pushKitToken)
if (_pushNotificationStore.pushKitToken)
{
self.shouldReceiveVoIPPushes = YES;
}
@ -172,7 +170,7 @@
{
[[UNUserNotificationCenter currentNotificationCenter] removeUnwantedNotifications];
[[UNUserNotificationCenter currentNotificationCenter] removeCallNotificationsFor:nil];
if (_pushNotificationManager.pushKitToken)
if (_pushNotificationStore.pushKitToken)
{
self.shouldReceiveVoIPPushes = NO;
}
@ -184,7 +182,7 @@
{
_shouldReceiveVoIPPushes = shouldReceiveVoIPPushes;
if (_shouldReceiveVoIPPushes && _pushNotificationManager.pushKitToken)
if (_shouldReceiveVoIPPushes && _pushNotificationStore.pushKitToken)
{
MXSession *session = [AppDelegate theDelegate].mxSessions.firstObject;
if (session.state >= MXSessionStateStoreDataReady)
@ -194,7 +192,11 @@
else
{
// add an observer for session state
matrixSessionStateObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXSessionStateDidChangeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXWeakify(self);
NSNotificationCenter * __weak notificationCenter = [NSNotificationCenter defaultCenter];
self.matrixSessionStateObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXSessionStateDidChangeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
MXStrongifyAndReturnIfNil(self);
MXSession *mxSession = (MXSession*)notif.object;
if ([[AppDelegate theDelegate].mxSessions containsObject:mxSession]
@ -202,8 +204,7 @@
&& self->_shouldReceiveVoIPPushes)
{
[self configurePushKit];
[[NSNotificationCenter defaultCenter] removeObserver:self->matrixSessionStateObserver];
self->matrixSessionStateObserver = nil;
[notificationCenter removeObserver:self.matrixSessionStateObserver];
}
}];
}
@ -230,15 +231,12 @@
if (account.mxSession.state == MXSessionStatePaused)
{
NSLog(@"[PushNotificationService] launchBackgroundSync");
__weak typeof(self) weakSelf = self;
MXWeakify(self);
[account backgroundSync:20000 success:^{
// Sanity check
if (!weakSelf)
{
return;
}
MXStrongifyAndReturnIfNil(self);
[[UNUserNotificationCenter currentNotificationCenter] removeUnwantedNotifications];
[[UNUserNotificationCenter currentNotificationCenter] removeCallNotificationsFor:nil];
@ -450,7 +448,7 @@
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)pushCredentials forType:(PKPushType)type
{
NSLog(@"[PushNotificationService] did update PushKit credentials");
_pushNotificationManager.pushKitToken = pushCredentials.token;
_pushNotificationStore.pushKitToken = pushCredentials.token;
if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive)
{
self.shouldReceiveVoIPPushes = NO;
@ -459,7 +457,7 @@
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(PKPushType)type withCompletionHandler:(void (^)(void))completion
{
NSLog(@"[PushNotificationService] did receive PushKit push with payload: %@", payload.dictionaryPayload);
NSLog(@"[PushNotificationService] didReceiveIncomingPushWithPayload: %@", payload.dictionaryPayload);
NSString *roomId = payload.dictionaryPayload[@"room_id"];
NSString *eventId = payload.dictionaryPayload[@"event_id"];
@ -469,14 +467,14 @@
if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground)
{
NSLog(@"[PushNotificationService] application is in bg");
NSLog(@"[PushNotificationService] didReceiveIncomingPushWithPayload: application is in bg");
if (@available(iOS 13.0, *))
{
// for iOS 13, we'll just report the incoming call in the same runloop. It means we cannot call an async API here.
MXEvent *lastCallInvite = _pushNotificationManager.lastCallInvite;
MXEvent *lastCallInvite = _pushNotificationStore.lastCallInvite;
// remove event
_pushNotificationManager.lastCallInvite = nil;
_pushNotificationStore.lastCallInvite = nil;
MXSession *session = [AppDelegate theDelegate].mxSessions.firstObject;
// when we have a VoIP push while the application is killed, session.callManager will not be ready yet. Configure it.
[[AppDelegate theDelegate] configureCallManagerIfRequiredForSession:session];
@ -486,30 +484,26 @@
[session decryptEvent:lastCallInvite inTimeline:nil];
}
NSLog(@"[PushNotificationService] lastCallInvite: %@", lastCallInvite);
NSLog(@"[PushNotificationService] didReceiveIncomingPushWithPayload: lastCallInvite: %@", lastCallInvite);
if ([lastCallInvite.eventId isEqualToString:eventId])
{
SEL handleCallInvite = NSSelectorFromString(@"handleCallInvite:");
if ([session.callManager respondsToSelector:handleCallInvite])
{
[session.callManager performSelector:handleCallInvite withObject:lastCallInvite];
}
[session.callManager handleCallEvent:lastCallInvite];
MXCall *call = [session.callManager callWithCallId:lastCallInvite.content[@"call_id"]];
if (call)
{
[session.callManager.callKitAdapter reportIncomingCall:call];
NSLog(@"[PushNotificationService] Reporting new call in room %@ for the event: %@", roomId, eventId);
NSLog(@"[PushNotificationService] didReceiveIncomingPushWithPayload: Reporting new call in room %@ for the event: %@", roomId, eventId);
}
else
{
NSLog(@"[PushNotificationService] Error on call object on room %@ for the event: %@", roomId, eventId);
NSLog(@"[PushNotificationService] didReceiveIncomingPushWithPayload: Error on call object on room %@ for the event: %@", roomId, eventId);
}
}
else
{
// It's a serious error. There is nothing to avoid iOS to kill us here.
NSLog(@"[PushNotificationService] iOS 13 and in bg, but we don't have the last callInvite event for the event %@. There is something wrong.", eventId);
NSLog(@"[PushNotificationService] didReceiveIncomingPushWithPayload: iOS 13 and in bg, but we don't have the last callInvite event for the event %@. There is something wrong.", eventId);
}
}
else
@ -520,7 +514,7 @@
}
else
{
NSLog(@"[PushNotificationService] application is not in bg. There is something wrong.");
NSLog(@"[PushNotificationService] didReceiveIncomingPushWithPayload: application is not in bg. There is something wrong.");
}
completion();

View file

@ -19,7 +19,7 @@ import KeychainAccess
import MatrixSDK
@objcMembers
final class PushNotificationManager: NSObject {
final class PushNotificationStore: NSObject {
// MARK: - Constants
@ -32,8 +32,6 @@ final class PushNotificationManager: NSObject {
static let lastCallInvite: String = "lastCallInvite"
}
static let shared = PushNotificationManager()
/// Store. Defaults to `KeychainStore`
private let store: KeyValueStore

View file

@ -929,8 +929,15 @@
{
authInputsview = (AuthInputsView*)self.authInputsView;
}
BOOL showForgotPasswordButton = NO;
self.forgotPasswordButton.hidden = (self.authType != MXKAuthenticationTypeLogin) || authInputsview.isSingleSignOnRequired;
if (BuildSettings.authScreenShowForgotPassword)
{
showForgotPasswordButton = (self.authType == MXKAuthenticationTypeLogin) && !authInputsview.isSingleSignOnRequired;
}
self.forgotPasswordButton.hidden = !showForgotPasswordButton;
// Adjust minimum leading constraint of the submit button
if (self.forgotPasswordButton.isHidden)

View file

@ -204,6 +204,8 @@
if ([self isFlowSupported:kMXLoginFlowTypePassword])
{
BOOL showPhoneTextField = BuildSettings.authScreenShowPhoneNumber;
self.passWordTextField.returnKeyType = UIReturnKeyDone;
self.phoneTextField.returnKeyType = UIReturnKeyNext;
@ -219,13 +221,27 @@
attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.placeholderTextColor}];
self.userLoginContainer.hidden = NO;
self.messageLabel.hidden = NO;
self.phoneContainer.hidden = NO;
self.messageLabel.hidden = !showPhoneTextField;
self.phoneContainer.hidden = !showPhoneTextField;
self.passwordContainer.hidden = NO;
self.messageLabelTopConstraint.constant = 59;
self.phoneContainerTopConstraint.constant = 70;
self.passwordContainerTopConstraint.constant = 150;
CGFloat phoneContainerTopConstraintConstant = 0.0;
CGFloat passwordContainerTopConstraintConstant = 0.0;
if (showPhoneTextField)
{
phoneContainerTopConstraintConstant = 70;
passwordContainerTopConstraintConstant = 150;
}
else
{
passwordContainerTopConstraintConstant = 50;
}
self.phoneContainerTopConstraint.constant = phoneContainerTopConstraintConstant;
self.passwordContainerTopConstraint.constant = passwordContainerTopConstraintConstant;
self.currentLastContainer = self.passwordContainer;
}
@ -649,22 +665,9 @@
NSString *identityServer = restClient.identityServer;
// Create the next link that is common to all Vector.im clients
NSString *nextLink = [NSString stringWithFormat:@"%@/#/register?client_secret=%@&hs_url=%@&session_id=%@",
BuildSettings.applicationWebAppUrlString,
[self->submittedEmail.clientSecret stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]],
[restClient.homeserver stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]],
[self->currentSession.session stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]];
if (identityServer)
{
nextLink = [NSString stringWithFormat:@"%@&is_url=%@", nextLink,
[identityServer stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]]];
}
[self->submittedEmail requestValidationTokenWithMatrixRestClient:restClient
isDuringRegistration:YES
nextLink:nextLink
nextLink:nil
success:^
{
NSMutableDictionary *threepidCreds = [NSMutableDictionary dictionaryWithDictionary:@{

View file

@ -221,10 +221,6 @@
[super viewWillDisappear:animated];
}
- (void)dealloc
{
}
#pragma mark - override MXKViewController
- (void)destroy
@ -366,7 +362,7 @@
{
// Detect if we should display the prompt to fallback to the STUN server defined
// in the app plist if the homeserver does not provide STUN or TURN servers.
// We should if the call ends while we were in connecting state
// We should display it if the call ends while we were in connecting state
if (!self.mainSession.callManager.turnServers
&& !self.mainSession.callManager.fallbackSTUNServer
&& !RiotSettings.shared.isAllowStunServerFallbackHasBeenSetOnce)
@ -388,6 +384,7 @@
}
default:
// There is nothing to do for other states
break;
}
}

View file

@ -30,8 +30,7 @@ final class CameraAccessAlertPresenter {
let alert = UIAlertController(title: VectorL10n.camera, message: VectorL10n.cameraAccessNotGranted(appDisplayName), preferredStyle: .alert)
let cancelActionTitle = Bundle.mxk_localizedString(forKey: "ok")
let cancelAction = UIAlertAction(title: cancelActionTitle, style: .cancel, handler: { _ in
})
let cancelAction = UIAlertAction(title: cancelActionTitle, style: .cancel)
let settingsActionTitle = Bundle.mxk_localizedString(forKey: "settings")
let settingsAction = UIAlertAction(title: settingsActionTitle, style: .default, handler: { _ in

View file

@ -14,19 +14,20 @@
// limitations under the License.
//
#import <Foundation/Foundation.h>
import Foundation
NS_ASSUME_NONNULL_BEGIN
/// Row object for tableviews
@interface Row: NSObject
@property (nonatomic, assign) NSInteger tag;
+ (instancetype)rowWithTag:(NSInteger)tag;
- (instancetype)initWithTag:(NSInteger)tag;
@end
NS_ASSUME_NONNULL_END
@objcMembers
final class Row: NSObject {
let tag: Int
init(withTag tag: Int) {
self.tag = tag
super.init()
}
static func row(withTag tag: Int) -> Row {
return Row(withTag: tag)
}
}

View file

@ -0,0 +1,52 @@
//
// Copyright 2020 Vector Creations 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
final class Section: NSObject {
let tag: Int
var rows: [Row]
var headerTitle: String?
init(withTag tag: Int) {
self.tag = tag
self.rows = []
super.init()
}
static func section(withTag tag: Int) -> Section {
return Section(withTag: tag)
}
func addRow(_ row: Row) {
rows.append(row)
}
func addRow(withTag tag: Int) {
addRow(Row.row(withTag: tag))
}
func indexOfRow(withTag tag: Int) -> Int? {
return rows.firstIndex(where: { $0.tag == tag })
}
var hasAnyRows: Bool {
return rows.count > 0
}
}

View file

@ -0,0 +1,97 @@
//
// Copyright 2020 Vector Creations Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
@objc
protocol TableViewSectionsDelegate {
func tableViewSectionsDidUpdateSections(_ sections: TableViewSections)
}
@objcMembers
final class TableViewSections: NSObject {
/// Delegate object
weak var delegate: TableViewSectionsDelegate?
/// Sections. Updating this will trigger `tableViewSectionsDidUpdateSections` of the delegate object.
var sections: [Section] = [] {
didSet {
delegate?.tableViewSectionsDidUpdateSections(self)
}
}
/// Finds the exact indexpath for the given row and section tag. If cannot find, returns nil
/// - Parameters:
/// - rowTag: Tag for row
/// - sectionTag: Tag for section
/// - Returns: IndexPath object if found, otherwise nil.
func exactIndexPath(forRowTag rowTag: Int, sectionTag: Int) -> IndexPath? {
guard let sectionIndex = sections.firstIndex(where: { $0.tag == sectionTag }) else {
return nil
}
guard let indexOfRow = sections[sectionIndex].indexOfRow(withTag: rowTag) else {
return nil
}
return IndexPath(row: indexOfRow, section: sectionIndex)
}
/// Finds the nearest next indexPath for given row tag and section tag. If the section finishes, also checks for the next section. If cannot find any row available, returns nil.
/// - Parameters:
/// - rowTag: Tag for row
/// - sectionTag: Tag for section
/// - Returns: IndexPath object if found, otherwise nil.
func nearestIndexPath(forRowTag rowTag: Int, sectionTag: Int) -> IndexPath? {
let sectionIndex = sections.firstIndex(where: { $0.tag == sectionTag })
if let sectionIndex = sectionIndex {
if let indexOfRow = sections[sectionIndex].indexOfRow(withTag: rowTag) {
return IndexPath(row: indexOfRow, section: sectionIndex)
} else if rowTag + 1 < sections[sectionIndex].rows.count {
return nearestIndexPath(forRowTag: rowTag + 1, sectionTag: sectionTag)
} else if sectionTag + 1 < sections.count {
return nearestIndexPath(forRowTag: 0, sectionTag: sectionTag + 1)
}
} else if sectionTag + 1 < sections.count {
// try to return the first row of the next section
return nearestIndexPath(forRowTag: 0, sectionTag: sectionTag + 1)
}
return nil
}
/// Section at index.
/// - Parameter index: Index of desired section
/// - Returns: Section object if index is in bounds of the sections array. Otherwise nil.
func section(atIndex index: Int) -> Section? {
if index < sections.count {
return sections[index]
}
return nil
}
func tagsIndexPath(fromTableViewIndexPath indexPath: IndexPath) -> IndexPath? {
guard let section = section(atIndex: indexPath.section) else {
// section not found
return nil
}
guard indexPath.row < section.rows.count else {
return nil
}
return IndexPath(row: section.rows[indexPath.row].tag, section: section.tag)
}
}

View file

@ -615,48 +615,6 @@
currentAlert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
// [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_recents_start_chat_with", @"Vector", nil)
// style:UIAlertActionStyleDefault
// handler:^(UIAlertAction * action) {
//
// if (weakSelf)
// {
// typeof(self) self = weakSelf;
// self->currentAlert = nil;
//
// [self performSegueWithIdentifier:@"presentStartChat" sender:self];
// }
//
// }]];
//
// [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_recents_create_empty_room", @"Vector", nil)
// style:UIAlertActionStyleDefault
// handler:^(UIAlertAction * action) {
//
// if (weakSelf)
// {
// typeof(self) self = weakSelf;
// self->currentAlert = nil;
//
// [self createAnEmptyRoom];
// }
//
// }]];
//
// [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_recents_join_room", @"Vector", nil)
// style:UIAlertActionStyleDefault
// handler:^(UIAlertAction * action) {
//
// if (weakSelf)
// {
// typeof(self) self = weakSelf;
// self->currentAlert = nil;
//
// [self joinARoom];
// }
//
// }]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
@ -676,76 +634,6 @@
[self presentViewController:currentAlert animated:YES completion:nil];
}
//- (void)joinARoom
//{
// [currentAlert dismissViewControllerAnimated:NO completion:nil];
//
// __weak typeof(self) weakSelf = self;
//
// // Prompt the user to type a room id or room alias
// currentAlert = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"room_recents_join_room_title", @"Vector", nil)
// message:NSLocalizedStringFromTable(@"room_recents_join_room_prompt", @"Vector", nil)
// preferredStyle:UIAlertControllerStyleAlert];
//
// [currentAlert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
//
// textField.secureTextEntry = NO;
// textField.placeholder = nil;
// textField.keyboardType = UIKeyboardTypeDefault;
// }];
//
// [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"]
// style:UIAlertActionStyleDefault
// handler:^(UIAlertAction * action) {
//
// if (weakSelf)
// {
// typeof(self) self = weakSelf;
// self->currentAlert = nil;
// }
//
// }]];
//
// [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"join", @"Vector", nil)
// style:UIAlertActionStyleDefault
// handler:^(UIAlertAction * action) {
//
// if (weakSelf)
// {
// typeof(self) self = weakSelf;
//
// NSString *roomAliasOrId = [self->currentAlert textFields].firstObject.text;
//
// self->currentAlert = nil;
//
// [self.activityIndicator startAnimating];
//
// self->currentRequest = [self.mainSession joinRoom:roomAliasOrId success:^(MXRoom *room) {
//
// self->currentRequest = nil;
// [self.activityIndicator stopAnimating];
//
// // Show the room
// [[AppDelegate theDelegate] showRoom:room.roomId andEventId:nil withMatrixSession:self.mainSession];
//
// } failure:^(NSError *error) {
//
// NSLog(@"[RecentsViewController] Join joinARoom (%@) failed", roomAliasOrId);
//
// self->currentRequest = nil;
// [self.activityIndicator stopAnimating];
//
// // Alert user
// [[AppDelegate theDelegate] showErrorAsAlert:error];
// }];
// }
//
// }]];
//
// [currentAlert mxk_setAccessibilityIdentifier:@"RecentsVCJoinARoomAlert"];
// [self presentViewController:currentAlert animated:YES completion:nil];
//}
#pragma mark - Table view scrolling
- (void)scrollToTop:(BOOL)animated

View file

@ -577,25 +577,6 @@
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
//- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
//{
// NSMutableArray* actions;
//
// // @TODO Add the swipe to remove this room from the community if the current user is admin
// actions = [[NSMutableArray alloc] init];
//
// // Patch: Force the width of the button by adding whitespace characters into the title string.
// UITableViewRowAction *leaveAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:@" " handler:^(UITableViewRowAction *action, NSIndexPath *indexPath){
//
// // @TODO Remove the room
//
// }];
//
// leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:ThemeService.shared.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)];
// [actions insertObject:leaveAction atIndex:0];
//
// return actions;
//}
#pragma mark - UISearchBar delegate

View file

@ -66,11 +66,6 @@
}
}
- (void)dealloc
{
}
- (void)destroy
{
[super destroy];

View file

@ -114,11 +114,6 @@
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
}
- (void)dealloc
{
}
- (void)destroy
{
[super destroy];

View file

@ -349,7 +349,7 @@ NSString *const kIntegrationManagerAddIntegrationScreen = @"add_integ";
if (!widget_id)
{
[self sendLocalisedError:@"widget_integration_unable_to_create" toRequest:requestId]; // new Error("Missing required widget fields."));
[self sendLocalisedError:@"widget_integration_unable_to_create" toRequest:requestId];
return;
}

View file

@ -213,10 +213,12 @@ static const NSString *kJitsiDataErrorKey = @"error";
- (void)conferenceWillJoin:(NSDictionary *)data
{
// Nothing to do
}
- (void)conferenceJoined:(NSDictionary *)data
{
// Nothing to do
}
- (void)conferenceTerminated:(NSDictionary *)data

View file

@ -40,8 +40,6 @@ final class KeyBackupRecoverFromPrivateKeyViewModel: KeyBackupRecoverFromPrivate
self.keyBackupVersion = keyBackupVersion
}
deinit {
}
// MARK: - Public

View file

@ -128,7 +128,9 @@ final class KeyVerificationCoordinatorBridgePresenter: NSObject {
private func present(coordinator keyVerificationCoordinator: KeyVerificationCoordinator, from viewController: UIViewController, animated: Bool) {
keyVerificationCoordinator.delegate = self
viewController.present(keyVerificationCoordinator.toPresentable(), animated: animated, completion: nil)
let presentable = keyVerificationCoordinator.toPresentable()
presentable.presentationController?.delegate = self
viewController.present(presentable, animated: animated, completion: nil)
keyVerificationCoordinator.start()
self.coordinator = keyVerificationCoordinator
@ -146,3 +148,13 @@ extension KeyVerificationCoordinatorBridgePresenter: KeyVerificationCoordinatorD
self.delegate?.keyVerificationCoordinatorBridgePresenterDelegateDidCancel(self)
}
}
extension KeyVerificationCoordinatorBridgePresenter: UIAdaptivePresentationControllerDelegate {
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
if let coordinator = self.coordinator {
keyVerificationCoordinatorDidCancel(coordinator)
}
}
}

View file

@ -53,9 +53,6 @@ final class KeyVerificationScanConfirmationViewModel: KeyVerificationScanConfirm
self.verificationKind = verificationKind
}
deinit {
}
// MARK: - Public
func process(viewAction: KeyVerificationScanConfirmationViewAction) {

View file

@ -46,9 +46,6 @@ final class KeyVerificationVerifyBySASViewModel: KeyVerificationVerifyBySASViewM
self.verificationKind = verificationKind
}
deinit {
}
// MARK: - Public
func process(viewAction: KeyVerificationVerifyBySASViewAction) {

View file

@ -51,10 +51,7 @@ final class DeviceVerificationIncomingViewModel: DeviceVerificationIncomingViewM
self.mediaManager = session.mediaManager
}
deinit {
}
// MARK: - Public
func process(viewAction: DeviceVerificationIncomingViewAction) {

View file

@ -45,9 +45,6 @@ final class KeyVerificationSelfVerifyStartViewModel: KeyVerificationSelfVerifySt
self.keyVerificationService = KeyVerificationService()
}
deinit {
}
// MARK: - Public
func process(viewAction: KeyVerificationSelfVerifyStartViewAction) {

View file

@ -1,11 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="79A-qb-tmk">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16096" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="79A-qb-tmk">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@ -19,16 +17,16 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="asO-rj-82y">
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="tIM-sl-gwE">
<rect key="frame" x="0.0" y="0.0" width="375" height="412.5"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="527"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IlB-Ch-LEo">
<rect key="frame" x="0.0" y="0.0" width="375" height="412.5"/>
<rect key="frame" x="27.5" y="0.0" width="320" height="527"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="d5Y-pj-XsI">
<rect key="frame" x="20" y="20" width="335" height="84"/>
<rect key="frame" x="20" y="20" width="280" height="84"/>
<string key="text">Verify this session from one of your others sessions, granting it access to encrypted messages.
Use the latest Riot on your other devices:</string>
@ -37,7 +35,7 @@ Use the latest Riot on your other devices:</string>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillEqually" translatesAutoresizingMaskIntoConstraints="NO" id="ANK-XS-dY7">
<rect key="frame" x="27.5" y="144" width="320" height="95.5"/>
<rect key="frame" x="0.0" y="144" width="320" height="95.5"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" spacing="14" translatesAutoresizingMaskIntoConstraints="NO" id="3at-ql-vhb">
<rect key="frame" x="0.0" y="0.0" width="160" height="95.5"/>
@ -85,19 +83,43 @@ Riot X for Android</string>
</constraints>
</stackView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="or another cross-signing capable Matrix client" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rFM-AQ-wAB">
<rect key="frame" x="20" y="259.5" width="335" height="14.5"/>
<rect key="frame" x="20" y="259.5" width="280" height="14.5"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="12"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="8oJ-o6-DLK">
<rect key="frame" x="20" y="294" width="335" height="118.5"/>
<rect key="frame" x="20" y="294" width="280" height="233"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dXT-cL-ukJ">
<rect key="frame" x="0.0" y="0.0" width="280" height="114.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Checking for other verification capabilities ..." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="A4x-sK-d5C">
<rect key="frame" x="20" y="10" width="240" height="38.5"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<activityIndicatorView opaque="NO" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" style="medium" translatesAutoresizingMaskIntoConstraints="NO" id="esP-Lt-anU">
<rect key="frame" x="0.0" y="64.5" width="280" height="20"/>
</activityIndicatorView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="esP-Lt-anU" firstAttribute="leading" secondItem="dXT-cL-ukJ" secondAttribute="leading" id="1Rg-vU-DJm"/>
<constraint firstItem="A4x-sK-d5C" firstAttribute="top" secondItem="dXT-cL-ukJ" secondAttribute="top" constant="10" id="7We-Ox-BZt"/>
<constraint firstItem="A4x-sK-d5C" firstAttribute="leading" secondItem="dXT-cL-ukJ" secondAttribute="leading" constant="20" id="FuM-Cv-7mT"/>
<constraint firstAttribute="trailing" secondItem="A4x-sK-d5C" secondAttribute="trailing" constant="20" id="Lk0-BP-Fdw"/>
<constraint firstAttribute="trailing" secondItem="esP-Lt-anU" secondAttribute="trailing" id="SJY-m2-DP4"/>
<constraint firstItem="esP-Lt-anU" firstAttribute="top" secondItem="A4x-sK-d5C" secondAttribute="bottom" constant="16" id="Tif-UR-9I2"/>
<constraint firstAttribute="bottom" secondItem="esP-Lt-anU" secondAttribute="bottom" constant="30" id="gcZ-sx-3Ff"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="nf8-Ye-b9r">
<rect key="frame" x="0.0" y="0.0" width="335" height="118.5"/>
<rect key="frame" x="0.0" y="114.5" width="280" height="118.5"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="OEt-k0-vgM" customClass="RoundedButton" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="0.0" y="10" width="335" height="44"/>
<rect key="frame" x="0.0" y="10" width="280" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="7ws-Nc-I7y"/>
</constraints>
@ -110,7 +132,7 @@ Riot X for Android</string>
</connections>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="If you can't accessing an existing session" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4Ou-cM-K9C">
<rect key="frame" x="20" y="64" width="295" height="24.5"/>
<rect key="frame" x="20" y="64" width="240" height="24.5"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="12"/>
<color key="textColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
@ -189,6 +211,9 @@ Riot X for Android</string>
<outlet property="mobileClientImageView" destination="P0P-X4-uSQ" id="WtT-ix-yq8"/>
<outlet property="mobileClientLabel" destination="gLH-sE-KCq" id="jQ0-7U-mr8"/>
<outlet property="recoverSecretsAdditionalInformationLabel" destination="4Ou-cM-K9C" id="80N-lF-x2L"/>
<outlet property="recoverSecretsAvailabilityActivityIndicatorView" destination="esP-Lt-anU" id="4jv-GA-Hm9"/>
<outlet property="recoverSecretsAvailabilityLoadingContainerView" destination="dXT-cL-ukJ" id="rBM-Hj-c3o"/>
<outlet property="recoverSecretsAvailabilityLoadingLabel" destination="A4x-sK-d5C" id="n5k-IO-RkV"/>
<outlet property="recoverSecretsButton" destination="OEt-k0-vgM" id="RHU-ps-4m7"/>
<outlet property="recoverSecretsContainerView" destination="nf8-Ye-b9r" id="4az-pe-0Uc"/>
</connections>

View file

@ -40,7 +40,9 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController {
@IBOutlet private weak var additionalInformationLabel: UILabel!
@IBOutlet private weak var recoverSecretsAvailabilityLoadingContainerView: UIView!
@IBOutlet private weak var recoverSecretsAvailabilityLoadingLabel: UILabel!
@IBOutlet private weak var recoverSecretsAvailabilityActivityIndicatorView: UIActivityIndicatorView!
@IBOutlet private weak var recoverSecretsContainerView: UIView!
@IBOutlet private weak var recoverSecretsButton: RoundedButton!
@IBOutlet private weak var recoverSecretsAdditionalInformationLabel: UILabel!
@ -102,6 +104,8 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController {
self.mobileClientLabel.textColor = theme.textPrimaryColor
self.mobileClientImageView.tintColor = theme.tintColor
self.additionalInformationLabel.textColor = theme.textSecondaryColor
self.recoverSecretsAvailabilityLoadingLabel.textColor = theme.textSecondaryColor
self.recoverSecretsAvailabilityActivityIndicatorView.color = theme.tintColor
}
private func registerThemeServiceDidChangeThemeNotification() {
@ -141,6 +145,8 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController {
switch viewState {
case .loading:
self.renderLoading()
case .secretsRecoveryCheckingAvailability(let text):
self.renderSecretsRecoveryCheckingAvailability(withText: text)
case .loaded(let viewData):
self.renderLoaded(viewData: viewData)
case .cancelled(let reason):
@ -156,6 +162,13 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController {
self.activityPresenter.presentActivityIndicator(on: self.view, animated: true)
}
private func renderSecretsRecoveryCheckingAvailability(withText text: String?) {
self.recoverSecretsAvailabilityLoadingLabel.text = text
self.recoverSecretsAvailabilityActivityIndicatorView.startAnimating()
self.recoverSecretsAvailabilityLoadingContainerView.isHidden = false
self.recoverSecretsContainerView.isHidden = true
}
private func renderLoaded(viewData: KeyVerificationSelfVerifyWaitViewData) {
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
@ -180,6 +193,8 @@ final class KeyVerificationSelfVerifyWaitViewController: UIViewController {
}
}
self.recoverSecretsAvailabilityLoadingContainerView.isHidden = true
self.recoverSecretsAvailabilityActivityIndicatorView.stopAnimating()
self.recoverSecretsContainerView.isHidden = hideRecoverSecrets
self.recoverSecretsButton.setTitle(recoverSecretsButtonTitle, for: .normal)
}

View file

@ -28,7 +28,7 @@ final class KeyVerificationSelfVerifyWaitViewModel: KeyVerificationSelfVerifyWai
private let keyVerificationService: KeyVerificationService
private let verificationManager: MXKeyVerificationManager
private let isNewSignIn: Bool
private let secretsRecoveryAvailability: SecretsRecoveryAvailability
private var secretsRecoveryAvailability: SecretsRecoveryAvailability
private var keyVerificationRequest: MXKeyVerificationRequest?
// MARK: Public
@ -62,7 +62,8 @@ final class KeyVerificationSelfVerifyWaitViewModel: KeyVerificationSelfVerifyWai
switch self.secretsRecoveryAvailability {
case .notAvailable:
fatalError("Should not happen: When recovery is not available button is hidden")
case .available(let secretsRecoveryMode): self.coordinatorDelegate?.keyVerificationSelfVerifyWaitViewModel(self, wantsToRecoverSecretsWith: secretsRecoveryMode)
case .available(let secretsRecoveryMode):
self.coordinatorDelegate?.keyVerificationSelfVerifyWaitViewModel(self, wantsToRecoverSecretsWith: secretsRecoveryMode)
}
}
}
@ -85,7 +86,31 @@ final class KeyVerificationSelfVerifyWaitViewModel: KeyVerificationSelfVerifyWai
}, failure: { [weak self] error in
self?.update(viewState: .error(error))
})
continueLoadData()
} else {
// be sure that session has completed its first sync
if session.state >= MXSessionStateRunning {
continueLoadData()
} else {
// show loader
self.update(viewState: .secretsRecoveryCheckingAvailability(VectorL10n.deviceVerificationSelfVerifyWaitRecoverSecretsCheckingAvailability))
NotificationCenter.default.addObserver(self, selector: #selector(sessionStateChanged), name: .mxSessionStateDidChange, object: session)
}
}
}
@objc
private func sessionStateChanged() {
if session.state >= MXSessionStateRunning {
NotificationCenter.default.removeObserver(self, name: .mxSessionStateDidChange, object: session)
continueLoadData()
}
}
private func continueLoadData() {
// update availability again
self.secretsRecoveryAvailability = session.crypto.recoveryService.vc_availability
let viewData = KeyVerificationSelfVerifyWaitViewData(isNewSignIn: self.isNewSignIn, secretsRecoveryAvailability: self.secretsRecoveryAvailability)

View file

@ -31,6 +31,7 @@ struct KeyVerificationSelfVerifyWaitViewData {
/// KeyVerificationSelfVerifyWaitViewController view state
enum KeyVerificationSelfVerifyWaitViewState {
case loading
case secretsRecoveryCheckingAvailability(_ text: String?)
case loaded(_ viewData: KeyVerificationSelfVerifyWaitViewData)
case cancelled(MXTransactionCancelCode)
case cancelledByMe(MXTransactionCancelCode)

View file

@ -45,9 +45,6 @@ final class DeviceVerificationStartViewModel: DeviceVerificationStartViewModelTy
self.otherDevice = otherDevice
}
deinit {
}
// MARK: - Public
func process(viewAction: DeviceVerificationStartViewAction) {

View file

@ -59,9 +59,6 @@ final class UserVerificationStartViewModel: UserVerificationStartViewModelType {
self.keyVerificationService = KeyVerificationService()
}
deinit {
}
// MARK: - Public
func process(viewAction: UserVerificationStartViewAction) {

View file

@ -134,8 +134,7 @@ final class UserVerificationCoordinator: NSObject, UserVerificationCoordinatorTy
message: VectorL10n.keyVerificationBootstrapNotSetupMessage,
preferredStyle: .alert)
let cancelAction = UIAlertAction(title: Bundle.mxk_localizedString(forKey: "ok"), style: .cancel, handler: { _ in
})
let cancelAction = UIAlertAction(title: Bundle.mxk_localizedString(forKey: "ok"), style: .cancel)
alert.addAction(cancelAction)
self.presenter.toPresentable().present(alert, animated: true, completion: nil)

View file

@ -64,8 +64,7 @@ final class SingleImagePickerPresenter: NSObject {
self.presentPhotoLibray(sourceView: sourceView, sourceRect: sourceRect, animated: animated)
})
let cancelAction = UIAlertAction(title: VectorL10n.cancel, style: .cancel, handler: { _ in
})
let cancelAction = UIAlertAction(title: VectorL10n.cancel, style: .cancel)
alert.addAction(cameraAction)
alert.addAction(photoLibraryAction)

View file

@ -792,8 +792,8 @@
// Refresh here the preview header according to the coming screen orientation.
// Retrieve the affine transform indicating the amount of rotation being applied to the interface.
// This transform is the identity transform when no rotation is applied;
// otherwise, it is a transform that applies a 90 degree, -90 degree, or 180 degree rotation.
// This transform is the identity transform when no rotation is applied.
// Otherwise, it is a transform that applies a 90 degree, -90 degree, or 180 degree rotation.
CGAffineTransform transform = coordinator.targetTransform;
// Consider here only the transform that applies a +/- 90 degree.
@ -2609,40 +2609,43 @@
}
else // Add action for attachment
{
if (attachment.type == MXKAttachmentTypeImage || attachment.type == MXKAttachmentTypeVideo)
if (BuildSettings.messageDetailsAllowSave)
{
[currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_event_action_save", @"Vector", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
[self cancelEventSelection];
[self startActivityIndicator];
[attachment save:^{
__strong __typeof(weakSelf)self = weakSelf;
[self stopActivityIndicator];
} failure:^(NSError *error) {
__strong __typeof(weakSelf)self = weakSelf;
[self stopActivityIndicator];
//Alert user
[[AppDelegate theDelegate] showErrorAsAlert:error];
}];
// Start animation in case of download during attachment preparing
[roomBubbleTableViewCell startProgressUI];
}
}]];
if (attachment.type == MXKAttachmentTypeImage || attachment.type == MXKAttachmentTypeVideo)
{
[currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_event_action_save", @"Vector", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
[self cancelEventSelection];
[self startActivityIndicator];
[attachment save:^{
__strong __typeof(weakSelf)self = weakSelf;
[self stopActivityIndicator];
} failure:^(NSError *error) {
__strong __typeof(weakSelf)self = weakSelf;
[self stopActivityIndicator];
//Alert user
[[AppDelegate theDelegate] showErrorAsAlert:error];
}];
// Start animation in case of download during attachment preparing
[roomBubbleTableViewCell startProgressUI];
}
}]];
}
}
// Check status of the selected event

File diff suppressed because it is too large Load diff

View file

@ -248,14 +248,6 @@
#pragma mark - HPGrowingTextView delegate
//- (BOOL)growingTextViewShouldReturn:(HPGrowingTextView *)hpGrowingTextView
//{
// // The return sends the message rather than giving a carriage return.
// [self onTouchUpInside:self.rightInputToolbarButton];
//
// return NO;
//}
- (void)growingTextViewDidChange:(HPGrowingTextView *)hpGrowingTextView
{
// Clean the carriage return added on return press

View file

@ -84,11 +84,6 @@
}
}
- (void)dealloc
{
}
- (void)destroy
{
[super destroy];

View file

@ -48,9 +48,6 @@ final class ServiceTermsModalScreenViewModel: ServiceTermsModalScreenViewModelTy
self.outOfContext = outOfContext
}
deinit {
}
// MARK: - Public
func process(viewAction: ServiceTermsModalScreenViewAction) {

View file

@ -111,6 +111,8 @@ final class PinCodePreferences: NSObject {
func localizedBiometricsName() -> String? {
if isBiometricsAvailable {
let context = LAContext()
// canEvaluatePolicy should be called for biometryType to be set
_ = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)
switch context.biometryType {
case .touchID:
return VectorL10n.biometricsModeTouchId
@ -126,6 +128,8 @@ final class PinCodePreferences: NSObject {
func biometricsIcon() -> UIImage? {
if isBiometricsAvailable {
let context = LAContext()
// canEvaluatePolicy should be called for biometryType to be set
_ = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)
switch context.biometryType {
case .touchID:
return Asset.Images.touchidIcon.image

View file

@ -1,39 +0,0 @@
//
// Copyright 2020 Vector Creations 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
@class Row;
/// Section object for tableviews
@interface Section: NSObject
@property (nonatomic, assign) NSInteger tag;
@property (nonatomic, strong) NSMutableArray<Row*> *rows;
@property (nonatomic, copy) NSString *headerTitle;
+ (instancetype)sectionWithTag:(NSInteger)tag;
- (instancetype)initWithTag:(NSInteger)tag;
- (void)addRow:(Row *)row;
- (void)addRowWithTag:(NSInteger)tag;
- (NSInteger)indexOfRowForTag:(NSInteger)tag;
@end
NS_ASSUME_NONNULL_END

View file

@ -1,54 +0,0 @@
//
// Copyright 2020 Vector Creations 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 "Section.h"
#import "Row.h"
@implementation Section
+ (instancetype)sectionWithTag:(NSInteger)tag
{
return [[self alloc] initWithTag:tag];
}
- (instancetype)initWithTag:(NSInteger)tag
{
self = [super init];
if (self) {
self.tag = tag;
_rows = [NSMutableArray arrayWithCapacity:10];
}
return self;
}
- (void)addRow:(Row *)row
{
[_rows addObject:row];
}
- (void)addRowWithTag:(NSInteger)tag
{
[_rows addObject:[Row rowWithTag:tag]];
}
- (NSInteger)indexOfRowForTag:(NSInteger)tag
{
return [_rows indexOfObjectPassingTest:^BOOL(Row * _Nonnull row, NSUInteger idx, BOOL * _Nonnull stop) {
return row.tag == tag;
}];
}
@end

View file

@ -732,7 +732,6 @@ enum {
{
NSLog(@"[ManageSessionVC] Delete device (%@) failed, auth session flow type is not supported", self->device.deviceId);
[self.activityIndicator stopAnimating];
//[[AppDelegate theDelegate] showErrorAsAlert:error];
}
} failure:^(NSError *error) {

View file

@ -42,9 +42,6 @@
#import "GroupsDataSource.h"
#import "GroupTableViewCellWithSwitch.h"
#import "Row.h"
#import "Section.h"
#import "GBDeviceInfo_iOS.h"
#import "Riot-Swift.h"
@ -96,12 +93,6 @@ enum
NOTIFICATION_SETTINGS_GLOBAL_SETTINGS_INDEX,
NOTIFICATION_SETTINGS_PIN_MISSED_NOTIFICATIONS_INDEX,
NOTIFICATION_SETTINGS_PIN_UNREAD_INDEX,
//NOTIFICATION_SETTINGS_CONTAINING_MY_USER_NAME_INDEX,
//NOTIFICATION_SETTINGS_CONTAINING_MY_DISPLAY_NAME_INDEX,
//NOTIFICATION_SETTINGS_SENT_TO_ME_INDEX,
//NOTIFICATION_SETTINGS_INVITED_TO_ROOM_INDEX,
//NOTIFICATION_SETTINGS_PEOPLE_LEAVE_JOIN_INDEX,
//NOTIFICATION_SETTINGS_CALL_INVITATION_INDEX,
};
enum
@ -167,11 +158,12 @@ SecureBackupSetupCoordinatorBridgePresenterDelegate,
SignOutAlertPresenterDelegate,
SingleImagePickerPresenterDelegate,
SettingsDiscoveryTableViewSectionDelegate, SettingsDiscoveryViewModelCoordinatorDelegate,
SettingsIdentityServerCoordinatorBridgePresenterDelegate>
SettingsIdentityServerCoordinatorBridgePresenterDelegate,
TableViewSectionsDelegate>
{
// Current alert (if any).
UIAlertController *currentAlert;
// listener
id removedAccountObserver;
id accountUserInfoObserver;
@ -253,7 +245,7 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
@property (nonatomic, strong) SecureBackupSetupCoordinatorBridgePresenter *secureBackupSetupCoordinatorBridgePresenter;
@property (nonatomic, strong) AuthenticatedSessionViewControllerFactory *authenticatedSessionViewControllerFactory;
@property (nonatomic, strong) NSArray<Section*> *sections;
@property (nonatomic, strong) TableViewSections *tableViewSections;
@end
@ -470,78 +462,7 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
}
// update sections
self.sections = tmpSections;
}
- (void)setSections:(NSArray<Section *> *)sections
{
_sections = sections;
// reload table
[self.tableView reloadData];
}
/// Returns index of section for the given tag. If cannot find, return `NSNotFound`
/// @param tag Tag for section
- (NSInteger)indexOfSectionForTag:(NSInteger)tag
{
return [_sections indexOfObjectPassingTest:^BOOL(Section * _Nonnull section, NSUInteger idx, BOOL * _Nonnull stop) {
return section.tag == tag;
}];
}
/// Finds the exact indexpath for the given row and section tag. If cannot find, returns nil
/// @param rowTag Tag for row
/// @param sectionTag Tag for section
- (NSIndexPath *)exactIndexPathForRowTag:(NSInteger)rowTag sectionTag:(NSInteger)sectionTag
{
NSInteger sectionIndex = [self indexOfSectionForTag:sectionTag];
if (sectionIndex != NSNotFound)
{
Section *section = _sections[sectionIndex];
NSInteger rowIndex = [section indexOfRowForTag:rowTag];
if (rowIndex != NSNotFound)
{
return [NSIndexPath indexPathForRow:rowIndex inSection:sectionIndex];
}
}
return nil;
}
/// Finds the nearest next indexPath for given row tag and section tag. If the section finishes, also checks for the next section. If cannot find any row available, returns nil.
/// @param rowTag Tag for row
/// @param sectionTag Tag for section
- (NSIndexPath *)nearestIndexPathForRowTag:(NSInteger)rowTag sectionTag:(NSInteger)sectionTag
{
NSInteger sectionIndex = [self indexOfSectionForTag:sectionTag];
if (sectionIndex != NSNotFound)
{
Section *section = _sections[sectionIndex];
NSInteger rowIndex = [section indexOfRowForTag:rowTag];
if (rowIndex != NSNotFound)
{
// exact row found, return it
return [NSIndexPath indexPathForRow:rowIndex inSection:sectionIndex];
}
else if (rowTag + 1 < section.rows.count)
{
// try to return next row in the same section
return [self nearestIndexPathForRowTag:rowTag + 1 sectionTag:sectionTag];
}
else if (sectionTag + 1 < _sections.count)
{
// try to return the first row of the next section
return [self nearestIndexPathForRowTag:0 sectionTag:sectionTag + 1];
}
return nil;
}
else if (sectionTag + 1 < _sections.count)
{
// try to return the first row of the next section
return [self nearestIndexPathForRowTag:0 sectionTag:sectionTag + 1];
}
return nil;
_tableViewSections.sections = tmpSections;
}
- (void)viewDidLoad
@ -624,6 +545,8 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
self.signOutAlertPresenter = [SignOutAlertPresenter new];
self.signOutAlertPresenter.delegate = self;
_tableViewSections = [TableViewSections new];
_tableViewSections.delegate = self;
[self updateSections];
}
@ -881,8 +804,8 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
[self.tableView beginUpdates];
// Refresh the corresponding table view cell with animation
NSIndexPath *addEmailIndexPath = [self exactIndexPathForRowTag:USER_SETTINGS_ADD_EMAIL_INDEX
sectionTag:SECTION_TAG_USER_SETTINGS];
NSIndexPath *addEmailIndexPath = [self.tableViewSections exactIndexPathForRowTag:USER_SETTINGS_ADD_EMAIL_INDEX
sectionTag:SECTION_TAG_USER_SETTINGS];
if (addEmailIndexPath)
{
[self.tableView reloadRowsAtIndexPaths:@[addEmailIndexPath] withRowAnimation:UITableViewRowAnimationFade];
@ -912,8 +835,8 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
[self.tableView beginUpdates];
// Refresh the corresponding table view cell with animation
NSIndexPath *addPhoneIndexPath = [self exactIndexPathForRowTag:USER_SETTINGS_ADD_PHONENUMBER_INDEX
sectionTag:SECTION_TAG_USER_SETTINGS];
NSIndexPath *addPhoneIndexPath = [self.tableViewSections exactIndexPathForRowTag:USER_SETTINGS_ADD_PHONENUMBER_INDEX
sectionTag:SECTION_TAG_USER_SETTINGS];
if (addPhoneIndexPath)
{
[self.tableView reloadRowsAtIndexPaths:@[addPhoneIndexPath] withRowAnimation:UITableViewRowAnimationFade];
@ -1400,16 +1323,12 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
// update the save button if there is an update
[self updateSaveButtonStatus];
return _sections.count;
return _tableViewSections.sections.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
Section *sectionObject = nil;
if (section < _sections.count)
{
sectionObject = _sections[section];
}
Section *sectionObject = [_tableViewSections sectionAtIndex:section];
return sectionObject.rows.count;
}
@ -1496,19 +1415,9 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
Section *sectionObj = nil;
NSInteger section = NSNotFound;
NSInteger row = NSNotFound;
if (indexPath.section < _sections.count)
{
sectionObj = _sections[indexPath.section];
section = sectionObj.tag;
if (indexPath.row < sectionObj.rows.count)
{
row = sectionObj.rows[indexPath.row].tag;
}
}
NSIndexPath *tagsIndexPath = [_tableViewSections tagsIndexPathFromTableViewIndexPath:indexPath];
NSInteger section = tagsIndexPath.section;
NSInteger row = tagsIndexPath.row;
// set the cell to a default value to avoid application crashes
UITableViewCell *cell = [[UITableViewCell alloc] init];
@ -2369,11 +2278,7 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
Section *sectionObj = nil;
if (section < _sections.count)
{
sectionObj = _sections[section];
}
Section *sectionObj = [_tableViewSections sectionAtIndex:section];
return sectionObj.headerTitle;
}
@ -2390,19 +2295,9 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
Section *sectionObj = nil;
NSInteger section = NSNotFound;
NSInteger row = NSNotFound;
if (indexPath.section < _sections.count)
{
sectionObj = _sections[indexPath.section];
section = sectionObj.tag;
if (indexPath.row < sectionObj.rows.count)
{
row = sectionObj.rows[indexPath.row].tag;
}
}
NSIndexPath *tagsIndexPath = [_tableViewSections tagsIndexPathFromTableViewIndexPath:indexPath];
NSInteger section = tagsIndexPath.section;
NSInteger row = tagsIndexPath.row;
if (section == SECTION_TAG_USER_SETTINGS)
{
@ -2456,19 +2351,9 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
Section *sectionObj = nil;
NSInteger section = NSNotFound;
NSInteger row = NSNotFound;
if (indexPath.section < _sections.count)
{
sectionObj = _sections[indexPath.section];
section = sectionObj.tag;
if (indexPath.row < sectionObj.rows.count)
{
row = sectionObj.rows[indexPath.row].tag;
}
}
NSIndexPath *tagsIndexPath = [_tableViewSections tagsIndexPathFromTableViewIndexPath:indexPath];
NSInteger section = tagsIndexPath.section;
NSInteger row = tagsIndexPath.row;
NSMutableArray* actions;
@ -2501,19 +2386,9 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
{
if (self.tableView == tableView)
{
Section *sectionObj = nil;
NSInteger section = NSNotFound;
NSInteger row = NSNotFound;
if (indexPath.section < _sections.count)
{
sectionObj = _sections[indexPath.section];
section = sectionObj.tag;
if (indexPath.row < sectionObj.rows.count)
{
row = sectionObj.rows[indexPath.row].tag;
}
}
NSIndexPath *tagsIndexPath = [_tableViewSections tagsIndexPathFromTableViewIndexPath:indexPath];
NSInteger section = tagsIndexPath.section;
NSInteger row = tagsIndexPath.row;
if (section == SECTION_TAG_USER_INTERFACE)
{
@ -2535,7 +2410,7 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
// settingsDiscoveryTableViewSection is a dynamic section, so check number of rows before scroll to avoid crashes
if (self.settingsDiscoveryTableViewSection.numberOfRows > 0)
{
NSIndexPath *discoveryIndexPath = [self exactIndexPathForRowTag:0 sectionTag:SECTION_TAG_DISCOVERY];
NSIndexPath *discoveryIndexPath = [_tableViewSections exactIndexPathForRowTag:0 sectionTag:SECTION_TAG_DISCOVERY];
if (discoveryIndexPath)
{
[tableView scrollToRowAtIndexPath:discoveryIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
@ -2544,7 +2419,7 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
else
{
// this won't be precise in scroll location, but seems the best option for now
NSIndexPath *discoveryIndexPath = [self nearestIndexPathForRowTag:0 sectionTag:SECTION_TAG_DISCOVERY];
NSIndexPath *discoveryIndexPath = [_tableViewSections nearestIndexPathForRowTag:0 sectionTag:SECTION_TAG_DISCOVERY];
if (discoveryIndexPath)
{
[tableView scrollToRowAtIndexPath:discoveryIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
@ -2744,19 +2619,9 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
- (void)onRemove3PID:(NSIndexPath*)indexPath
{
Section *sectionObj = nil;
NSInteger section = NSNotFound;
NSInteger row = NSNotFound;
if (indexPath.section < _sections.count)
{
sectionObj = _sections[indexPath.section];
section = sectionObj.tag;
if (indexPath.row < sectionObj.rows.count)
{
row = sectionObj.rows[indexPath.row].tag;
}
}
NSIndexPath *tagsIndexPath = [_tableViewSections tagsIndexPathFromTableViewIndexPath:indexPath];
NSInteger section = tagsIndexPath.section;
NSInteger row = tagsIndexPath.row;
if (section == SECTION_TAG_USER_SETTINGS)
{
@ -3143,46 +3008,6 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
[self pushViewController:newPhoneNumberCountryPicker];
}
//- (void)onRuleUpdate:(id)sender
//{
// MXPushRule* pushRule = nil;
// MXSession* session = [[AppDelegate theDelegate].mxSessions objectAtIndex:0];
//
// NSInteger row = ((UIView*)sender).tag;
//
// if (row == NOTIFICATION_SETTINGS_CONTAINING_MY_DISPLAY_NAME_INDEX)
// {
// pushRule = [session.notificationCenter ruleById:kMXNotificationCenterContainDisplayNameRuleID];
// }
// else if (row == NOTIFICATION_SETTINGS_CONTAINING_MY_USER_NAME_INDEX)
// {
// pushRule = [session.notificationCenter ruleById:kMXNotificationCenterContainUserNameRuleID];
// }
// else if (row == NOTIFICATION_SETTINGS_SENT_TO_ME_INDEX)
// {
// pushRule = [session.notificationCenter ruleById:kMXNotificationCenterOneToOneRoomRuleID];
// }
// else if (row == NOTIFICATION_SETTINGS_INVITED_TO_ROOM_INDEX)
// {
// pushRule = [session.notificationCenter ruleById:kMXNotificationCenterInviteMeRuleID];
// }
// else if (row == NOTIFICATION_SETTINGS_PEOPLE_LEAVE_JOIN_INDEX)
// {
// pushRule = [session.notificationCenter ruleById:kMXNotificationCenterMemberEventRuleID];
// }
// else if (row == NOTIFICATION_SETTINGS_CALL_INVITATION_INDEX)
// {
// pushRule = [session.notificationCenter ruleById:kMXNotificationCenterCallRuleID];
// }
//
// if (pushRule)
// {
// // toggle the rule
// [session.notificationCenter enableRule:pushRule isEnabled:!pushRule.enabled];
// }
//}
- (void)onSave:(id)sender
{
// sanity check
@ -3623,8 +3448,8 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
SingleImagePickerPresenter *singleImagePickerPresenter = [[SingleImagePickerPresenter alloc] initWithSession:self.mainSession];
singleImagePickerPresenter.delegate = self;
NSIndexPath *indexPath = [self exactIndexPathForRowTag:USER_SETTINGS_PROFILE_PICTURE_INDEX
sectionTag:SECTION_TAG_USER_SETTINGS];
NSIndexPath *indexPath = [_tableViewSections exactIndexPathForRowTag:USER_SETTINGS_PROFILE_PICTURE_INDEX
sectionTag:SECTION_TAG_USER_SETTINGS];
if (indexPath)
{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
@ -3723,7 +3548,7 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
style:UIAlertActionStyleCancel
handler:nil]];
NSIndexPath *indexPath = [self exactIndexPathForRowTag:USER_INTERFACE_THEME_INDEX
NSIndexPath *indexPath = [_tableViewSections exactIndexPathForRowTag:USER_INTERFACE_THEME_INDEX
sectionTag:SECTION_TAG_USER_INTERFACE];
if (indexPath)
{
@ -3845,7 +3670,7 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
MXKAccount* account = [MXKAccountManager sharedManager].activeAccounts.firstObject;
[account changePassword:currentPasswordTextField.text with:newPasswordTextField1.text success:^{
[account changePassword:self->currentPasswordTextField.text with:self->newPasswordTextField1.text success:^{
if (weakSelf)
{
@ -4280,7 +4105,7 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
}
else if ([tableViewCellClass isEqual:[MXKTableViewCellWithTextView class]])
{
NSIndexPath *indexPath = [self exactIndexPathForRowTag:forRow sectionTag:SECTION_TAG_DISCOVERY];
NSIndexPath *indexPath = [_tableViewSections exactIndexPathForRowTag:forRow sectionTag:SECTION_TAG_DISCOVERY];
if (indexPath)
{
tableViewCell = [self textViewCellForTableView:self.tableView atIndexPath:indexPath];
@ -4307,7 +4132,7 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
}
else if ([tableViewCellClass isEqual:[MXKTableViewCellWithLabelAndSwitch class]])
{
NSIndexPath *indexPath = [self exactIndexPathForRowTag:forRow sectionTag:SECTION_TAG_DISCOVERY];
NSIndexPath *indexPath = [_tableViewSections exactIndexPathForRowTag:forRow sectionTag:SECTION_TAG_DISCOVERY];
if (indexPath)
{
tableViewCell = [self getLabelAndSwitchCell:self.tableView forIndexPath:indexPath];
@ -4336,7 +4161,7 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
- (void)settingsDiscoveryViewModelDidTapUserSettingsLink:(SettingsDiscoveryViewModel *)viewModel
{
NSIndexPath *discoveryIndexPath = [self exactIndexPathForRowTag:USER_SETTINGS_ADD_EMAIL_INDEX
NSIndexPath *discoveryIndexPath = [_tableViewSections exactIndexPathForRowTag:USER_SETTINGS_ADD_EMAIL_INDEX
sectionTag:SECTION_TAG_USER_SETTINGS];
if (discoveryIndexPath)
{
@ -4363,4 +4188,11 @@ SettingsIdentityServerCoordinatorBridgePresenterDelegate>
[self refreshSettings];
}
#pragma mark - TableViewSectionsDelegate
- (void)tableViewSectionsDidUpdateSections:(TableViewSections *)sections
{
[self.tableView reloadData];
}
@end

View file

@ -72,7 +72,7 @@ final class SignOutAlertPresenter: NSObject {
self.delegate?.signOutAlertPresenterDidTapSignOutAction(self)
}
let cancelAction = UIAlertAction(title: VectorL10n.cancel, style: .cancel, handler: nil)
let cancelAction = UIAlertAction(title: VectorL10n.cancel, style: .cancel)
alertContoller.addAction(signoutAction)
alertContoller.addAction(cancelAction)
@ -93,7 +93,7 @@ final class SignOutAlertPresenter: NSObject {
self.delegate?.signOutAlertPresenterDidTapBackupAction(self)
}
let cancelAction = UIAlertAction(title: VectorL10n.cancel, style: .cancel, handler: nil)
let cancelAction = UIAlertAction(title: VectorL10n.cancel, style: .cancel)
alertContoller.addAction(doNotWantKeyBackupAction)
alertContoller.addAction(setUpKeyBackupAction)
@ -130,7 +130,7 @@ final class SignOutAlertPresenter: NSObject {
self.delegate?.signOutAlertPresenterDidTapSignOutAction(self)
}
let cancelAction = UIAlertAction(title: VectorL10n.signOutKeyBackupInProgressAlertCancelAction, style: .cancel, handler: nil)
let cancelAction = UIAlertAction(title: VectorL10n.signOutKeyBackupInProgressAlertCancelAction, style: .cancel)
alertContoller.addAction(discardKeyBackupAction)
alertContoller.addAction(cancelAction)

View file

@ -40,7 +40,7 @@ class NotificationService: UNNotificationServiceExtension {
let url = URL(string: BuildSettings.serverConfigSygnalAPIUrlString)!
return MXPushGatewayRestClient(pushGateway: url.scheme! + "://" + url.host!, andOnUnrecognizedCertificateBlock: nil)
}()
private var pushNotificationManager: PushNotificationManager = .shared
private var pushNotificationStore: PushNotificationStore = PushNotificationStore()
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
// Set static application settings
@ -549,11 +549,11 @@ class NotificationService: UNNotificationServiceExtension {
/// Attempts to send trigger a VoIP push for the given event
/// - Parameter event: The call invite event.
private func sendVoipPush(forEvent event: MXEvent) {
guard let token = pushNotificationManager.pushKitToken else {
guard let token = pushNotificationStore.pushKitToken else {
return
}
pushNotificationManager.lastCallInvite = event
pushNotificationStore.lastCallInvite = event
let appId = BuildSettings.pushKitAppId

View file

@ -3,7 +3,7 @@ The `buildable` folder contains templates with source files that build.
The goal is to turn these templates as Xcode templates. They are part of the Riot project in order to ensure they build
# ScreenTemplate
This is the boilerplate to create a screen that follows the MVVM-C pattern used within the Riot app.
This is the boilerplate to create a screen that follows the MVVM-C pattern used within the Element app.
To create a screen from this template (before it becomes an Xcode template):

View file

@ -1 +0,0 @@
We do not want to release for tvOS.

View file

@ -1,15 +0,0 @@
Una aplicació de xat, sota el vostre control i totalment flexible. El Element us permet comunicar-vos de la manera que preferiu. Fet per al [matrix] - lestàndard per a la comunicació oberta i descentralitzada.
Obteniu un compte gratuït de matrix.org, executeu el vostre servidor propi a https://ems.element.io, o empreu un altre servidor de Matrix.
Per què triar Element?
• COMUNICACIÓ COMPLETA: Creeu sales al voltant dels vostres equips, els vostre amics o la vostra comunitat - de la manera que preferiu! Converseu, compartiu fitxers, afegiu ginys i feu trucades de veu i vídeo - tot de manera gratuïta.
• INTEGRACIONS POTENTS: Empreu el Element amb les eines que ja coneixeu i us agraden. Amb el Element fins i tot podeu conversar amb usuaris i grups daltres aplicacions de xat.
• PRIVAT I SEGUR: Mantingueu les vostres converses en secret. Xifratge punt a punt us assegura que les comunicacions privades continuaran sent privades.
• OBERT, NO TANCAT: Programari lliure, i construït damunt de Matrix. Sigueu els propietaris de les vostres dades hostatjant el vostre servidor propi, o emprant un en què confieu.
• ALLÀ ON SIGUEU: Esteu en contacte allà on esteu amb una sincronització total de lhistorial dels missatges en tots els vostres dispositius, i en línia a https://element.io/app.

View file

@ -1 +0,0 @@
messaging,collaboration,messenger,chat,secure,open,private,E2EE,decentralised,encrypted,self-host

View file

@ -1 +0,0 @@
https://element.io

View file

@ -1 +0,0 @@
Element (previously Riot.im)

View file

@ -1 +0,0 @@
https://riot.im/privacy

View file

@ -1 +0,0 @@

View file

@ -1 +0,0 @@

View file

@ -1 +0,0 @@
Secure decentralised chat/VoIP

View file

@ -1 +0,0 @@
https://element.io

View file

@ -1 +0,0 @@
New Vector Ltd, 2017-2020

View file

@ -1 +0,0 @@
We do not want to release for tvOS.

View file

@ -1,15 +0,0 @@
Eine Chat-App unter deiner Kontrolle und total flexibel. Element lässt dich auf die Art kommunizieren wie du willst. Die App wurde gemacht für [matrix] - dem Standard für offene, dezentrale Komunikation.
Hole dir ein kostenloses Konto auf matrix.org, hol dir einen eigenen Server auf https://ems.element.io oder nutze einen anderen Matrix-Server.
Warum solltest du Element wählen?
• KOMPLETTE KOMMUNIKATION: Baue Räume um deine Teams, deine Freunde, deine Community - wie auch immer du willst! Chatte, teile Dateien, füge Widgets hinzu und führe Sprach- und Videotelefonate - alles kostenlos.
• MÄCHTIGE INTEGRATIONEN: Benutze Element mit den Werkzeugen die du kennst und liebst. Mit Element kannst du sogar mit Personen und Gruppen chatten, die andere Chat-Anwendungen benutzen.
• PRIVAT UND SICHER: Halte deine Konversationen geheim. Aktuellste Ende-zu-Ende-Verschlüsselung sorgt dafür, dass deine private Kommunikation auch privat bleibt.
• OFFEN - NICHT VERSCHLOSSEN: Quelloffen und basierend auf Matrix. Behalte deine Daten indem du deinen eigenen Server betreibst oder einen auswählst dem du vertraust.
• WO AUCH IMMER DU BIST: Bleibe im Kontakt wo auch immer du bist wobei deine Nachrichtenhistorie zwischen all deinen Geräten synchronisiert wird. Das andere \"Gerät\" kann auch ein Browser sein. Schau dir dazu auch Element an.

View file

@ -1 +0,0 @@
messaging,collaboration,messenger,chat,secure,open,private,E2EE,decentralised,encrypted,self-host

View file

@ -1 +0,0 @@
https://element.io/

View file

@ -1 +0,0 @@
Element (previously Riot.im)

View file

@ -1 +0,0 @@
https://riot.im/privacy

View file

@ -1 +0,0 @@

View file

@ -1 +0,0 @@
Secure decentralised chat/VoIP

View file

@ -1 +0,0 @@
https://element.io/

View file

@ -1 +0,0 @@
We do not want to release for tvOS.

View file

@ -1,30 +0,0 @@
Element is a new type of messenger and collaboration app that:
1. Puts you in control to preserve your privacy
2. Lets you communicate with anyone in the Matrix network, and even beyond by integrating with apps such as Slack
3. Protects you from advertising, datamining, backdoors and walled gardens
4. Secures you through end-to-end encryption, with cross-signing to verify others
Element is completely different from other messaging and collaboration apps because it is decentralised and open source.
Element lets you self-host - or choose a host - so that you have privacy, ownership and control of your data and conversations. It gives you access to an open network; so youre not just stuck speaking to other Element users only. And it is very secure.
Element is able to do all this because it operates on Matrix - the standard for open, decentralised communication.
Element puts you in control by letting you choose who hosts your conversations. From the Element app, you can choose to host in different ways:
1. Get a free account on the matrix.org public server
2. Self-host your account by running a server on your own hardware
3. Sign up for an account on a custom server by simply subscribing to the Element Matrix Services hosting platform
Why choose Element?
OWN YOUR DATA: You decide where to keep your data and messages. You own it and control it, not some MEGACORP that mines your data or gives access to third parties.
OPEN MESSAGING AND COLLABORATION: You can chat with anyone else in the Matrix network, whether theyre using Element or another Matrix app, and even if they are using a different messaging system of the likes of Slack, IRC or XMPP.
SUPER-SECURE: Real end-to-end encryption (only those in the conversation can decrypt messages), and cross-signing to verify the devices of conversation participants.
COMPLETE COMMUNICATION: Messaging, voice and video calls, file sharing, screen sharing and a whole bunch of integrations, bots and widgets. Build rooms, communities, stay in touch and get things done.
EVERYWHERE YOU ARE: Stay in touch wherever you are with fully synchronised message history across all your devices and on the web at https://element.io/app.

View file

@ -1 +0,0 @@
collaboration,chat,secure,matrix,private,E2EE,decentralised,encrypted,self-host

View file

@ -1 +0,0 @@
http://element.io

View file

@ -1 +0,0 @@
Element (previously Riot.im)

View file

@ -1 +0,0 @@
https://riot.im/privacy

View file

@ -1 +0,0 @@

View file

@ -1 +0,0 @@
Secure decentralised chat/VoIP

View file

@ -1 +0,0 @@
http://element.io

View file

@ -1 +0,0 @@
We do not want to release for tvOS.

View file

@ -1,15 +0,0 @@
Une application de discussion, que vous contrôlez et entièrement flexible. Element vous laisse communiquer comme vous le souhaitez. Conçu pour [matrix], le standard pour les communications libres et décentralisées.
Créez un compte matrix.org gratuit, gérez votre propre serveur sur https://ems.element.io ou utilisez un autre serveur Matrix.
Pourquoi choisir Element ?
• COMMUNICATION COMPLÈTE : Construisez des salons autours de vos équipes, de vos amis, de votre communauté comme vous le souhaitez ! Discutez, partagez des fichiers, ajoutez des widgets et passez des appels audio et vidéo gratuitement.
• INTÉGRATIONS PUISSANTES : Utilisez Element avec les outils que vous connaissez déjà. Avec Element vous pouvez même discuter avec les utilisateurs et les groupes qui utilisent dautres applications de discussion.
• PRIVÉ ET SÉCURISÉ : Gardez vos conversations secrètes. Un chiffrement de bout en bout de pointe vous garanti que vos communications privées restent privées.
• OUVERT, PAS FERMÉ : Open source, et construit autour de Matrix. Restez en possession de vos données en hébergeant votre propre serveur, ou choisissez celui auquel vous faites confiance.
• PARTOUT OÙ VOUS ÊTES : Restez en contact où que vous soyez avec la synchronisation complète de lhistorique de vos messages entre vos différents appareils et en ligne sur https://element.io/app.

View file

@ -1 +0,0 @@
messaging,collaboration,messenger,chat,secure,open,private,E2EE,decentralised,encrypted,self-host

View file

@ -1 +0,0 @@
https://element.io/

View file

@ -1 +0,0 @@
Element (previously Riot.im)

Some files were not shown because too many files have changed in this diff Show more