Rename directories of sample sources (matrixConsole)
29
.gitignore
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
# Xcode
|
||||
#
|
||||
build/
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
DerivedData
|
||||
*.hmap
|
||||
*.ipa
|
||||
*.xcuserstate
|
||||
|
||||
# CocoaPods
|
||||
#
|
||||
# We recommend against adding the Pods directory to your .gitignore. However
|
||||
# you should judge for yourself, the pros and cons are mentioned at:
|
||||
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
|
||||
#
|
||||
Pods/
|
||||
|
||||
# Do not track our workspace since it is created by CocoaPods
|
||||
*.xcworkspace
|
16
Podfile
Normal file
|
@ -0,0 +1,16 @@
|
|||
# Uncomment this line to define a global platform for your project
|
||||
# platform :ios, "6.0"
|
||||
|
||||
source 'https://github.com/CocoaPods/Specs.git'
|
||||
|
||||
target "matrixConsole" do
|
||||
|
||||
# Points to SDK local sources file
|
||||
pod 'MatrixSDK', :path => '../../MatrixSDK.podspec'
|
||||
|
||||
end
|
||||
|
||||
target "matrixConsole" do
|
||||
|
||||
end
|
||||
|
42
Podfile.lock
Normal file
|
@ -0,0 +1,42 @@
|
|||
PODS:
|
||||
- AFNetworking (2.4.1):
|
||||
- AFNetworking/NSURLConnection
|
||||
- AFNetworking/NSURLSession
|
||||
- AFNetworking/Reachability
|
||||
- AFNetworking/Security
|
||||
- AFNetworking/Serialization
|
||||
- AFNetworking/UIKit
|
||||
- AFNetworking/NSURLConnection (2.4.1):
|
||||
- AFNetworking/Reachability
|
||||
- AFNetworking/Security
|
||||
- AFNetworking/Serialization
|
||||
- AFNetworking/NSURLSession (2.4.1):
|
||||
- AFNetworking/Reachability
|
||||
- AFNetworking/Security
|
||||
- AFNetworking/Serialization
|
||||
- AFNetworking/Reachability (2.4.1)
|
||||
- AFNetworking/Security (2.4.1)
|
||||
- AFNetworking/Serialization (2.4.1)
|
||||
- AFNetworking/UIKit (2.4.1):
|
||||
- AFNetworking/NSURLConnection
|
||||
- AFNetworking/NSURLSession
|
||||
- Mantle (1.5.1):
|
||||
- Mantle/extobjc
|
||||
- Mantle/extobjc (1.5.1)
|
||||
- MatrixSDK (0.0.1):
|
||||
- AFNetworking (~> 2.4.1)
|
||||
- Mantle (~> 1.5)
|
||||
|
||||
DEPENDENCIES:
|
||||
- MatrixSDK (from `../../MatrixSDK.podspec`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
MatrixSDK:
|
||||
:path: ../../MatrixSDK.podspec
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
AFNetworking: 0aabc6fae66d6e5d039eeb21c315843c7aae51ab
|
||||
Mantle: d7c5ac734579ec751c58fecbf56189853056c58c
|
||||
MatrixSDK: 42aac6ed0123d5339f27e3f57d8972edf17f8224
|
||||
|
||||
COCOAPODS: 0.34.1
|
11
README.rst
Normal file
|
@ -0,0 +1,11 @@
|
|||
Build instructions
|
||||
==================
|
||||
|
||||
Before opening the sample workspace, you need to build it with the CocoaPods command::
|
||||
|
||||
$ pod install
|
||||
|
||||
This will load your local SDK source code into the sample workspace.
|
||||
|
||||
|
||||
Then, open ``syMessaging.xcworkspace``.
|
640
matrixConsole.xcodeproj/project.pbxproj
Normal file
|
@ -0,0 +1,640 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
D648B86A591308736E2D4078 /* libPods-matrixConsole.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8141B1E2401FFCC3C5B99234 /* libPods-matrixConsole.a */; };
|
||||
F00B5DB91A1B9BCE00EA1C8D /* CustomImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = F00B5DB81A1B9BCE00EA1C8D /* CustomImageView.m */; };
|
||||
F01628C119E29C660071C473 /* default-profile.png in Resources */ = {isa = PBXBuildFile; fileRef = F01628BC19E29C660071C473 /* default-profile.png */; };
|
||||
F01628C319E29C660071C473 /* logo.png in Resources */ = {isa = PBXBuildFile; fileRef = F01628BE19E29C660071C473 /* logo.png */; };
|
||||
F024098219E7D177006E741B /* tab_recents@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F024098119E7D177006E741B /* tab_recents@2x.png */; };
|
||||
F02BCE231A1A5A2B00543B47 /* play.png in Resources */ = {isa = PBXBuildFile; fileRef = F02BCE221A1A5A2B00543B47 /* play.png */; };
|
||||
F02D707619F1DC9E007B47D3 /* RoomMemberTableCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F02D707519F1DC9E007B47D3 /* RoomMemberTableCell.m */; };
|
||||
F03C47111A02952800E445AB /* CustomAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = F03C47101A02952800E445AB /* CustomAlert.m */; };
|
||||
F03EF5F619F171EB00A0EE52 /* HomeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F03EF5EB19F171EB00A0EE52 /* HomeViewController.m */; };
|
||||
F03EF5F719F171EB00A0EE52 /* LoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F03EF5ED19F171EB00A0EE52 /* LoginViewController.m */; };
|
||||
F03EF5F819F171EB00A0EE52 /* MasterTabBarController.m in Sources */ = {isa = PBXBuildFile; fileRef = F03EF5EF19F171EB00A0EE52 /* MasterTabBarController.m */; };
|
||||
F03EF5F919F171EB00A0EE52 /* RecentsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F03EF5F119F171EB00A0EE52 /* RecentsViewController.m */; };
|
||||
F03EF5FA19F171EB00A0EE52 /* RoomViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F03EF5F319F171EB00A0EE52 /* RoomViewController.m */; };
|
||||
F03EF5FB19F171EB00A0EE52 /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = F03EF5F519F171EB00A0EE52 /* SettingsViewController.m */; };
|
||||
F03EF5FF19F1762000A0EE52 /* RoomMessageTableCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F03EF5FE19F1762000A0EE52 /* RoomMessageTableCell.m */; };
|
||||
F03EF60219F19E7C00A0EE52 /* MediaManager.m in Sources */ = {isa = PBXBuildFile; fileRef = F03EF60119F19E7C00A0EE52 /* MediaManager.m */; };
|
||||
F05B955F19DEED8A008761B0 /* MatrixHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = F05B955E19DEED8A008761B0 /* MatrixHandler.m */; };
|
||||
F07A80D819DD9DE700B621A1 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F07A80D719DD9DE700B621A1 /* main.m */; };
|
||||
F07A80DB19DD9DE700B621A1 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F07A80DA19DD9DE700B621A1 /* AppDelegate.m */; };
|
||||
F07A80E419DD9DE700B621A1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F07A80E219DD9DE700B621A1 /* Main.storyboard */; };
|
||||
F07A80E619DD9DE700B621A1 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F07A80E519DD9DE700B621A1 /* Images.xcassets */; };
|
||||
F07A80E919DD9DE700B621A1 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = F07A80E719DD9DE700B621A1 /* LaunchScreen.xib */; };
|
||||
F07A80F519DD9DE700B621A1 /* syMessagingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F07A80F419DD9DE700B621A1 /* syMessagingTests.m */; };
|
||||
F08B6FCC1A1DE7F80094A35B /* matrixConsole.jpg in Resources */ = {isa = PBXBuildFile; fileRef = F08B6FCB1A1DE7F80094A35B /* matrixConsole.jpg */; };
|
||||
F08DCBDB1A093BFA008C65B6 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F08DCBDA1A093BFA008C65B6 /* MobileCoreServices.framework */; };
|
||||
F0CEA5AE19E6895E00E47915 /* logoHighRes.png in Resources */ = {isa = PBXBuildFile; fileRef = F0CEA5AC19E6895E00E47915 /* logoHighRes.png */; };
|
||||
F0CEA5AF19E6895E00E47915 /* tab_recents.png in Resources */ = {isa = PBXBuildFile; fileRef = F0CEA5AD19E6895E00E47915 /* tab_recents.png */; };
|
||||
F0CEA5B119E6898800E47915 /* tab_home.ico in Resources */ = {isa = PBXBuildFile; fileRef = F0CEA5B019E6898800E47915 /* tab_home.ico */; };
|
||||
F0D3C30C1A011EF10000D49E /* AppSettings.m in Sources */ = {isa = PBXBuildFile; fileRef = F0D3C30B1A011EF10000D49E /* AppSettings.m */; };
|
||||
F0D3C30F1A01330F0000D49E /* SettingsTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F0D3C30E1A01330F0000D49E /* SettingsTableViewCell.m */; };
|
||||
F0E84D401A1F9AEC005F2E42 /* RecentsTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F0E84D3F1A1F9AEC005F2E42 /* RecentsTableViewCell.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
F07A80EF19DD9DE700B621A1 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = F07A80CA19DD9DE700B621A1 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = F07A80D119DD9DE700B621A1;
|
||||
remoteInfo = syMessaging;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
13057A57E74FD5504196F47F /* Pods-matrixConsole.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-matrixConsole.release.xcconfig"; path = "Pods/Target Support Files/Pods-matrixConsole/Pods-matrixConsole.release.xcconfig"; sourceTree = "<group>"; };
|
||||
8141B1E2401FFCC3C5B99234 /* libPods-matrixConsole.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-matrixConsole.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B7EC7E45C718BF2BBCE0CF48 /* Pods-matrixConsole.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-matrixConsole.debug.xcconfig"; path = "Pods/Target Support Files/Pods-matrixConsole/Pods-matrixConsole.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
F00B5DB71A1B9BCE00EA1C8D /* CustomImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomImageView.h; sourceTree = "<group>"; };
|
||||
F00B5DB81A1B9BCE00EA1C8D /* CustomImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CustomImageView.m; sourceTree = "<group>"; };
|
||||
F01628BC19E29C660071C473 /* default-profile.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "default-profile.png"; sourceTree = "<group>"; };
|
||||
F01628BE19E29C660071C473 /* logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = logo.png; sourceTree = "<group>"; };
|
||||
F024098119E7D177006E741B /* tab_recents@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "tab_recents@2x.png"; sourceTree = "<group>"; };
|
||||
F02BCE221A1A5A2B00543B47 /* play.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = play.png; sourceTree = "<group>"; };
|
||||
F02D707419F1DC9E007B47D3 /* RoomMemberTableCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomMemberTableCell.h; sourceTree = "<group>"; };
|
||||
F02D707519F1DC9E007B47D3 /* RoomMemberTableCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomMemberTableCell.m; sourceTree = "<group>"; };
|
||||
F03C470F1A02952800E445AB /* CustomAlert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomAlert.h; sourceTree = "<group>"; };
|
||||
F03C47101A02952800E445AB /* CustomAlert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CustomAlert.m; sourceTree = "<group>"; };
|
||||
F03EF5EA19F171EB00A0EE52 /* HomeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HomeViewController.h; sourceTree = "<group>"; };
|
||||
F03EF5EB19F171EB00A0EE52 /* HomeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HomeViewController.m; sourceTree = "<group>"; };
|
||||
F03EF5EC19F171EB00A0EE52 /* LoginViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoginViewController.h; sourceTree = "<group>"; };
|
||||
F03EF5ED19F171EB00A0EE52 /* LoginViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LoginViewController.m; sourceTree = "<group>"; };
|
||||
F03EF5EE19F171EB00A0EE52 /* MasterTabBarController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MasterTabBarController.h; sourceTree = "<group>"; };
|
||||
F03EF5EF19F171EB00A0EE52 /* MasterTabBarController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MasterTabBarController.m; sourceTree = "<group>"; };
|
||||
F03EF5F019F171EB00A0EE52 /* RecentsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecentsViewController.h; sourceTree = "<group>"; };
|
||||
F03EF5F119F171EB00A0EE52 /* RecentsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RecentsViewController.m; sourceTree = "<group>"; };
|
||||
F03EF5F219F171EB00A0EE52 /* RoomViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomViewController.h; sourceTree = "<group>"; };
|
||||
F03EF5F319F171EB00A0EE52 /* RoomViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomViewController.m; sourceTree = "<group>"; };
|
||||
F03EF5F419F171EB00A0EE52 /* SettingsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsViewController.h; sourceTree = "<group>"; };
|
||||
F03EF5F519F171EB00A0EE52 /* SettingsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsViewController.m; sourceTree = "<group>"; };
|
||||
F03EF5FD19F1762000A0EE52 /* RoomMessageTableCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomMessageTableCell.h; sourceTree = "<group>"; };
|
||||
F03EF5FE19F1762000A0EE52 /* RoomMessageTableCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomMessageTableCell.m; sourceTree = "<group>"; };
|
||||
F03EF60019F19E7C00A0EE52 /* MediaManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaManager.h; sourceTree = "<group>"; };
|
||||
F03EF60119F19E7C00A0EE52 /* MediaManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MediaManager.m; sourceTree = "<group>"; };
|
||||
F05B955D19DEED8A008761B0 /* MatrixHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MatrixHandler.h; sourceTree = "<group>"; };
|
||||
F05B955E19DEED8A008761B0 /* MatrixHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MatrixHandler.m; sourceTree = "<group>"; };
|
||||
F07A80D219DD9DE700B621A1 /* matrixConsole.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = matrixConsole.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F07A80D619DD9DE700B621A1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
F07A80D719DD9DE700B621A1 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||
F07A80D919DD9DE700B621A1 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
F07A80DA19DD9DE700B621A1 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
F07A80E319DD9DE700B621A1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
F07A80E519DD9DE700B621A1 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
|
||||
F07A80E819DD9DE700B621A1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
|
||||
F07A80EE19DD9DE700B621A1 /* matrixConsoleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = matrixConsoleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F07A80F319DD9DE700B621A1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
F07A80F419DD9DE700B621A1 /* syMessagingTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = syMessagingTests.m; sourceTree = "<group>"; };
|
||||
F08B6FCB1A1DE7F80094A35B /* matrixConsole.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = matrixConsole.jpg; sourceTree = "<group>"; };
|
||||
F08DCBDA1A093BFA008C65B6 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
|
||||
F0CEA5AC19E6895E00E47915 /* logoHighRes.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = logoHighRes.png; sourceTree = "<group>"; };
|
||||
F0CEA5AD19E6895E00E47915 /* tab_recents.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = tab_recents.png; sourceTree = "<group>"; };
|
||||
F0CEA5B019E6898800E47915 /* tab_home.ico */ = {isa = PBXFileReference; lastKnownFileType = image.ico; path = tab_home.ico; sourceTree = "<group>"; };
|
||||
F0D3C30A1A011EF10000D49E /* AppSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppSettings.h; sourceTree = "<group>"; };
|
||||
F0D3C30B1A011EF10000D49E /* AppSettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppSettings.m; sourceTree = "<group>"; };
|
||||
F0D3C30D1A01330F0000D49E /* SettingsTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsTableViewCell.h; sourceTree = "<group>"; };
|
||||
F0D3C30E1A01330F0000D49E /* SettingsTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsTableViewCell.m; sourceTree = "<group>"; };
|
||||
F0E84D3E1A1F9AEC005F2E42 /* RecentsTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecentsTableViewCell.h; sourceTree = "<group>"; };
|
||||
F0E84D3F1A1F9AEC005F2E42 /* RecentsTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RecentsTableViewCell.m; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
F07A80CF19DD9DE700B621A1 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F08DCBDB1A093BFA008C65B6 /* MobileCoreServices.framework in Frameworks */,
|
||||
D648B86A591308736E2D4078 /* libPods-matrixConsole.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F07A80EB19DD9DE700B621A1 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
B18A10A9FB884DD357EBD414 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
B7EC7E45C718BF2BBCE0CF48 /* Pods-matrixConsole.debug.xcconfig */,
|
||||
13057A57E74FD5504196F47F /* Pods-matrixConsole.release.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
EAA71E3C2B16D1D86B3F5100 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F08DCBDA1A093BFA008C65B6 /* MobileCoreServices.framework */,
|
||||
8141B1E2401FFCC3C5B99234 /* libPods-matrixConsole.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F01628B519E298710071C473 /* Assets */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F08B6FCB1A1DE7F80094A35B /* matrixConsole.jpg */,
|
||||
F02BCE221A1A5A2B00543B47 /* play.png */,
|
||||
F024098119E7D177006E741B /* tab_recents@2x.png */,
|
||||
F0CEA5B019E6898800E47915 /* tab_home.ico */,
|
||||
F0CEA5AD19E6895E00E47915 /* tab_recents.png */,
|
||||
F01628BC19E29C660071C473 /* default-profile.png */,
|
||||
F01628BE19E29C660071C473 /* logo.png */,
|
||||
F0CEA5AC19E6895E00E47915 /* logoHighRes.png */,
|
||||
);
|
||||
path = Assets;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F03EF5E919F171EB00A0EE52 /* ViewController */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F03EF5EA19F171EB00A0EE52 /* HomeViewController.h */,
|
||||
F03EF5EB19F171EB00A0EE52 /* HomeViewController.m */,
|
||||
F03EF5EC19F171EB00A0EE52 /* LoginViewController.h */,
|
||||
F03EF5ED19F171EB00A0EE52 /* LoginViewController.m */,
|
||||
F03EF5EE19F171EB00A0EE52 /* MasterTabBarController.h */,
|
||||
F03EF5EF19F171EB00A0EE52 /* MasterTabBarController.m */,
|
||||
F03EF5F019F171EB00A0EE52 /* RecentsViewController.h */,
|
||||
F03EF5F119F171EB00A0EE52 /* RecentsViewController.m */,
|
||||
F03EF5F219F171EB00A0EE52 /* RoomViewController.h */,
|
||||
F03EF5F319F171EB00A0EE52 /* RoomViewController.m */,
|
||||
F03EF5F419F171EB00A0EE52 /* SettingsViewController.h */,
|
||||
F03EF5F519F171EB00A0EE52 /* SettingsViewController.m */,
|
||||
);
|
||||
path = ViewController;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F03EF5FC19F1762000A0EE52 /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F00B5DB71A1B9BCE00EA1C8D /* CustomImageView.h */,
|
||||
F00B5DB81A1B9BCE00EA1C8D /* CustomImageView.m */,
|
||||
F0E84D3E1A1F9AEC005F2E42 /* RecentsTableViewCell.h */,
|
||||
F0E84D3F1A1F9AEC005F2E42 /* RecentsTableViewCell.m */,
|
||||
F02D707419F1DC9E007B47D3 /* RoomMemberTableCell.h */,
|
||||
F02D707519F1DC9E007B47D3 /* RoomMemberTableCell.m */,
|
||||
F03EF5FD19F1762000A0EE52 /* RoomMessageTableCell.h */,
|
||||
F03EF5FE19F1762000A0EE52 /* RoomMessageTableCell.m */,
|
||||
F0D3C30D1A01330F0000D49E /* SettingsTableViewCell.h */,
|
||||
F0D3C30E1A01330F0000D49E /* SettingsTableViewCell.m */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F07A80C919DD9DE700B621A1 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F07A80D419DD9DE700B621A1 /* syMessaging */,
|
||||
F07A80F119DD9DE700B621A1 /* syMessagingTests */,
|
||||
F07A80D319DD9DE700B621A1 /* Products */,
|
||||
B18A10A9FB884DD357EBD414 /* Pods */,
|
||||
EAA71E3C2B16D1D86B3F5100 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F07A80D319DD9DE700B621A1 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F07A80D219DD9DE700B621A1 /* matrixConsole.app */,
|
||||
F07A80EE19DD9DE700B621A1 /* matrixConsoleTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F07A80D419DD9DE700B621A1 /* syMessaging */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F03EF5FC19F1762000A0EE52 /* View */,
|
||||
F03EF5E919F171EB00A0EE52 /* ViewController */,
|
||||
F07A80D919DD9DE700B621A1 /* AppDelegate.h */,
|
||||
F07A80DA19DD9DE700B621A1 /* AppDelegate.m */,
|
||||
F0D3C30A1A011EF10000D49E /* AppSettings.h */,
|
||||
F0D3C30B1A011EF10000D49E /* AppSettings.m */,
|
||||
F03C470F1A02952800E445AB /* CustomAlert.h */,
|
||||
F03C47101A02952800E445AB /* CustomAlert.m */,
|
||||
F05B955D19DEED8A008761B0 /* MatrixHandler.h */,
|
||||
F05B955E19DEED8A008761B0 /* MatrixHandler.m */,
|
||||
F03EF60019F19E7C00A0EE52 /* MediaManager.h */,
|
||||
F03EF60119F19E7C00A0EE52 /* MediaManager.m */,
|
||||
F07A80E219DD9DE700B621A1 /* Main.storyboard */,
|
||||
F07A80E519DD9DE700B621A1 /* Images.xcassets */,
|
||||
F07A80E719DD9DE700B621A1 /* LaunchScreen.xib */,
|
||||
F01628B519E298710071C473 /* Assets */,
|
||||
F07A80D519DD9DE700B621A1 /* Supporting Files */,
|
||||
);
|
||||
path = syMessaging;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F07A80D519DD9DE700B621A1 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F07A80D619DD9DE700B621A1 /* Info.plist */,
|
||||
F07A80D719DD9DE700B621A1 /* main.m */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F07A80F119DD9DE700B621A1 /* syMessagingTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F07A80F419DD9DE700B621A1 /* syMessagingTests.m */,
|
||||
F07A80F219DD9DE700B621A1 /* Supporting Files */,
|
||||
);
|
||||
path = syMessagingTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F07A80F219DD9DE700B621A1 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F07A80F319DD9DE700B621A1 /* Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
F07A80D119DD9DE700B621A1 /* matrixConsole */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = F07A80F819DD9DE700B621A1 /* Build configuration list for PBXNativeTarget "matrixConsole" */;
|
||||
buildPhases = (
|
||||
A063750719371855C7755702 /* Check Pods Manifest.lock */,
|
||||
F07A80CE19DD9DE700B621A1 /* Sources */,
|
||||
F07A80CF19DD9DE700B621A1 /* Frameworks */,
|
||||
F07A80D019DD9DE700B621A1 /* Resources */,
|
||||
3496B335A95D95AB2A8DCEF4 /* Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = matrixConsole;
|
||||
productName = syMessaging;
|
||||
productReference = F07A80D219DD9DE700B621A1 /* matrixConsole.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
F07A80ED19DD9DE700B621A1 /* matrixConsoleTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = F07A80FB19DD9DE700B621A1 /* Build configuration list for PBXNativeTarget "matrixConsoleTests" */;
|
||||
buildPhases = (
|
||||
F07A80EA19DD9DE700B621A1 /* Sources */,
|
||||
F07A80EB19DD9DE700B621A1 /* Frameworks */,
|
||||
F07A80EC19DD9DE700B621A1 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
F07A80F019DD9DE700B621A1 /* PBXTargetDependency */,
|
||||
);
|
||||
name = matrixConsoleTests;
|
||||
productName = syMessagingTests;
|
||||
productReference = F07A80EE19DD9DE700B621A1 /* matrixConsoleTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
F07A80CA19DD9DE700B621A1 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0600;
|
||||
ORGANIZATIONNAME = matrix.org;
|
||||
TargetAttributes = {
|
||||
F07A80D119DD9DE700B621A1 = {
|
||||
CreatedOnToolsVersion = 6.0;
|
||||
};
|
||||
F07A80ED19DD9DE700B621A1 = {
|
||||
CreatedOnToolsVersion = 6.0;
|
||||
TestTargetID = F07A80D119DD9DE700B621A1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = F07A80CD19DD9DE700B621A1 /* Build configuration list for PBXProject "matrixConsole" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = F07A80C919DD9DE700B621A1;
|
||||
productRefGroup = F07A80D319DD9DE700B621A1 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
F07A80D119DD9DE700B621A1 /* matrixConsole */,
|
||||
F07A80ED19DD9DE700B621A1 /* matrixConsoleTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
F07A80D019DD9DE700B621A1 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F024098219E7D177006E741B /* tab_recents@2x.png in Resources */,
|
||||
F02BCE231A1A5A2B00543B47 /* play.png in Resources */,
|
||||
F07A80E419DD9DE700B621A1 /* Main.storyboard in Resources */,
|
||||
F07A80E919DD9DE700B621A1 /* LaunchScreen.xib in Resources */,
|
||||
F0CEA5AF19E6895E00E47915 /* tab_recents.png in Resources */,
|
||||
F01628C319E29C660071C473 /* logo.png in Resources */,
|
||||
F01628C119E29C660071C473 /* default-profile.png in Resources */,
|
||||
F0CEA5AE19E6895E00E47915 /* logoHighRes.png in Resources */,
|
||||
F0CEA5B119E6898800E47915 /* tab_home.ico in Resources */,
|
||||
F07A80E619DD9DE700B621A1 /* Images.xcassets in Resources */,
|
||||
F08B6FCC1A1DE7F80094A35B /* matrixConsole.jpg in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F07A80EC19DD9DE700B621A1 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
3496B335A95D95AB2A8DCEF4 /* Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Copy Pods Resources";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-matrixConsole/Pods-matrixConsole-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
A063750719371855C7755702 /* Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
F07A80CE19DD9DE700B621A1 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F07A80DB19DD9DE700B621A1 /* AppDelegate.m in Sources */,
|
||||
F03EF5FF19F1762000A0EE52 /* RoomMessageTableCell.m in Sources */,
|
||||
F07A80D819DD9DE700B621A1 /* main.m in Sources */,
|
||||
F05B955F19DEED8A008761B0 /* MatrixHandler.m in Sources */,
|
||||
F03EF5FB19F171EB00A0EE52 /* SettingsViewController.m in Sources */,
|
||||
F03EF5FA19F171EB00A0EE52 /* RoomViewController.m in Sources */,
|
||||
F03EF5F819F171EB00A0EE52 /* MasterTabBarController.m in Sources */,
|
||||
F03EF5F619F171EB00A0EE52 /* HomeViewController.m in Sources */,
|
||||
F03EF60219F19E7C00A0EE52 /* MediaManager.m in Sources */,
|
||||
F03EF5F919F171EB00A0EE52 /* RecentsViewController.m in Sources */,
|
||||
F03C47111A02952800E445AB /* CustomAlert.m in Sources */,
|
||||
F0E84D401A1F9AEC005F2E42 /* RecentsTableViewCell.m in Sources */,
|
||||
F02D707619F1DC9E007B47D3 /* RoomMemberTableCell.m in Sources */,
|
||||
F00B5DB91A1B9BCE00EA1C8D /* CustomImageView.m in Sources */,
|
||||
F0D3C30C1A011EF10000D49E /* AppSettings.m in Sources */,
|
||||
F03EF5F719F171EB00A0EE52 /* LoginViewController.m in Sources */,
|
||||
F0D3C30F1A01330F0000D49E /* SettingsTableViewCell.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
F07A80EA19DD9DE700B621A1 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F07A80F519DD9DE700B621A1 /* syMessagingTests.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
F07A80F019DD9DE700B621A1 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = F07A80D119DD9DE700B621A1 /* matrixConsole */;
|
||||
targetProxy = F07A80EF19DD9DE700B621A1 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
F07A80E219DD9DE700B621A1 /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
F07A80E319DD9DE700B621A1 /* Base */,
|
||||
);
|
||||
name = Main.storyboard;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F07A80E719DD9DE700B621A1 /* LaunchScreen.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
F07A80E819DD9DE700B621A1 /* Base */,
|
||||
);
|
||||
name = LaunchScreen.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
F07A80F619DD9DE700B621A1 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
F07A80F719DD9DE700B621A1 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
F07A80F919DD9DE700B621A1 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B7EC7E45C718BF2BBCE0CF48 /* Pods-matrixConsole.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
|
||||
INFOPLIST_FILE = syMessaging/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_NAME = matrixConsole;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
F07A80FA19DD9DE700B621A1 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 13057A57E74FD5504196F47F /* Pods-matrixConsole.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
|
||||
INFOPLIST_FILE = syMessaging/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 6.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_NAME = matrixConsole;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
F07A80FC19DD9DE700B621A1 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = syMessagingTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = matrixConsoleTests;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/matrixConsole.app/matrixConsole";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
F07A80FD19DD9DE700B621A1 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(SDKROOT)/Developer/Library/Frameworks",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = syMessagingTests/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
PRODUCT_NAME = matrixConsoleTests;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/matrixConsole.app/matrixConsole";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
F07A80CD19DD9DE700B621A1 /* Build configuration list for PBXProject "matrixConsole" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
F07A80F619DD9DE700B621A1 /* Debug */,
|
||||
F07A80F719DD9DE700B621A1 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
F07A80F819DD9DE700B621A1 /* Build configuration list for PBXNativeTarget "matrixConsole" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
F07A80F919DD9DE700B621A1 /* Debug */,
|
||||
F07A80FA19DD9DE700B621A1 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
F07A80FB19DD9DE700B621A1 /* Build configuration list for PBXNativeTarget "matrixConsoleTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
F07A80FC19DD9DE700B621A1 /* Debug */,
|
||||
F07A80FD19DD9DE700B621A1 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = F07A80CA19DD9DE700B621A1 /* Project object */;
|
||||
}
|
36
matrixConsole/AppDelegate.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 <UIKit/UIKit.h>
|
||||
|
||||
#import "MasterTabBarController.h"
|
||||
#import "CustomAlert.h"
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate>
|
||||
|
||||
@property (strong, nonatomic) UIWindow *window;
|
||||
@property (strong, nonatomic) MasterTabBarController *masterTabBarController;
|
||||
|
||||
@property (strong, nonatomic) CustomAlert *errorNotification;
|
||||
|
||||
+ (AppDelegate*)theDelegate;
|
||||
|
||||
- (void)logout;
|
||||
|
||||
- (CustomAlert*)showErrorAsAlert:(NSError*)error;
|
||||
|
||||
@end
|
||||
|
133
matrixConsole/AppDelegate.m
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 "AppDelegate.h"
|
||||
#import "AppSettings.h"
|
||||
#import "RoomViewController.h"
|
||||
#import "MatrixHandler.h"
|
||||
#import "MediaManager.h"
|
||||
|
||||
@interface AppDelegate () <UISplitViewControllerDelegate>
|
||||
|
||||
@end
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
#pragma mark -
|
||||
|
||||
+ (AppDelegate*)theDelegate {
|
||||
return (AppDelegate*)[[UIApplication sharedApplication] delegate];
|
||||
}
|
||||
#pragma mark -
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
// Override point for customization after application launch.
|
||||
if ([self.window.rootViewController isKindOfClass:[MasterTabBarController class]])
|
||||
{
|
||||
self.masterTabBarController = (MasterTabBarController*)self.window.rootViewController;
|
||||
self.masterTabBarController.delegate = self;
|
||||
|
||||
// By default the "Home" tab is focussed
|
||||
[self.masterTabBarController setSelectedIndex:TABBAR_HOME_INDEX];
|
||||
|
||||
UIViewController* recents = [self.masterTabBarController.viewControllers objectAtIndex:TABBAR_RECENTS_INDEX];
|
||||
if ([recents isKindOfClass:[UISplitViewController class]]) {
|
||||
UISplitViewController *splitViewController = (UISplitViewController *)recents;
|
||||
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
|
||||
navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem;
|
||||
splitViewController.delegate = self;
|
||||
} else {
|
||||
// Patch missing image in tabBarItem for iOS < 8.0
|
||||
recents.tabBarItem.image = [[UIImage imageNamed:@"tab_recents"] imageWithRenderingMode:UIImageRenderingModeAutomatic];
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication *)application {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
|
||||
if (self.errorNotification) {
|
||||
[self.errorNotification dismiss:NO];
|
||||
self.errorNotification = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForeground:(UIApplication *)application {
|
||||
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
- (void)applicationDidBecomeActive:(UIApplication *)application {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(UIApplication *)application {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)logout {
|
||||
// Clear cache
|
||||
[MediaManager clearCache];
|
||||
// Reset App settings
|
||||
[[AppSettings sharedSettings] reset];
|
||||
// Logout Matrix
|
||||
[[MatrixHandler sharedHandler] logout];
|
||||
[self.masterTabBarController showLoginScreen];
|
||||
// By default the "Home" tab is focussed
|
||||
[self.masterTabBarController setSelectedIndex:TABBAR_HOME_INDEX];
|
||||
}
|
||||
|
||||
- (CustomAlert*)showErrorAsAlert:(NSError*)error {
|
||||
if (self.errorNotification) {
|
||||
[self.errorNotification dismiss:NO];
|
||||
}
|
||||
|
||||
NSString *title = [error.userInfo valueForKey:NSLocalizedFailureReasonErrorKey];
|
||||
if (!title)
|
||||
{
|
||||
title = @"Error";
|
||||
}
|
||||
NSString *msg = [error.userInfo valueForKey:NSLocalizedDescriptionKey];
|
||||
|
||||
self.errorNotification = [[CustomAlert alloc] initWithTitle:title message:msg style:CustomAlertStyleAlert];
|
||||
self.errorNotification.cancelButtonIndex = [self.errorNotification addActionWithTitle:@"OK" style:CustomAlertActionStyleDefault handler:^(CustomAlert *alert) {
|
||||
[AppDelegate theDelegate].errorNotification = nil;
|
||||
}];
|
||||
[self.errorNotification showInViewController:[self.masterTabBarController selectedViewController]];
|
||||
|
||||
return self.errorNotification;
|
||||
}
|
||||
|
||||
#pragma mark - Split view
|
||||
|
||||
- (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController {
|
||||
if ([secondaryViewController isKindOfClass:[UINavigationController class]] && [[(UINavigationController *)secondaryViewController topViewController] isKindOfClass:[RoomViewController class]] && ([(RoomViewController *)[(UINavigationController *)secondaryViewController topViewController] roomId] == nil)) {
|
||||
// Return YES to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
29
matrixConsole/AppSettings.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 <UIKit/UIKit.h>
|
||||
|
||||
@interface AppSettings : NSObject
|
||||
|
||||
@property (nonatomic) BOOL enableNotifications;
|
||||
@property (nonatomic) BOOL displayAllEvents;
|
||||
@property (nonatomic) BOOL hideUnsupportedMessages;
|
||||
@property (nonatomic) BOOL sortMembersUsingLastSeenTime;
|
||||
|
||||
+ (AppSettings *)sharedSettings;
|
||||
|
||||
- (void)reset;
|
||||
|
||||
@end
|
89
matrixConsole/AppSettings.m
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 "AppSettings.h"
|
||||
#import "MatrixHandler.h"
|
||||
|
||||
static AppSettings *sharedSettings = nil;
|
||||
|
||||
@implementation AppSettings
|
||||
|
||||
+ (AppSettings *)sharedSettings {
|
||||
@synchronized(self) {
|
||||
if(sharedSettings == nil)
|
||||
{
|
||||
sharedSettings = [[super allocWithZone:NULL] init];
|
||||
}
|
||||
}
|
||||
return sharedSettings;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
-(AppSettings *)init {
|
||||
if (self = [super init]) {
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
}
|
||||
|
||||
- (void)reset {
|
||||
self.enableNotifications = NO;
|
||||
self.displayAllEvents = NO;
|
||||
self.hideUnsupportedMessages = NO;
|
||||
self.sortMembersUsingLastSeenTime = NO;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (BOOL)enableNotifications {
|
||||
return [[NSUserDefaults standardUserDefaults] boolForKey:@"enableNotifications"];
|
||||
}
|
||||
|
||||
- (void)setEnableNotifications:(BOOL)notifications {
|
||||
[[MatrixHandler sharedHandler] enableEventsNotifications:notifications];
|
||||
[[NSUserDefaults standardUserDefaults] setBool:notifications forKey:@"enableNotifications"];
|
||||
}
|
||||
|
||||
- (BOOL)displayAllEvents {
|
||||
return [[NSUserDefaults standardUserDefaults] boolForKey:@"displayAllEvents"];
|
||||
}
|
||||
|
||||
- (void)setDisplayAllEvents:(BOOL)displayAllEvents {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:displayAllEvents forKey:@"displayAllEvents"];
|
||||
// Flush and restore Matrix data
|
||||
[[MatrixHandler sharedHandler] forceInitialSync];
|
||||
}
|
||||
|
||||
- (BOOL)hideUnsupportedMessages {
|
||||
return [[NSUserDefaults standardUserDefaults] boolForKey:@"hideUnsupportedMessages"];
|
||||
}
|
||||
|
||||
- (void)setHideUnsupportedMessages:(BOOL)hideUnsupportedMessages {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:hideUnsupportedMessages forKey:@"hideUnsupportedMessages"];
|
||||
}
|
||||
|
||||
- (BOOL)sortMembersUsingLastSeenTime {
|
||||
return [[NSUserDefaults standardUserDefaults] boolForKey:@"sortMembersUsingLastSeenTime"];
|
||||
}
|
||||
|
||||
- (void)setSortMembersUsingLastSeenTime:(BOOL)sortMembersUsingLastSeen {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:sortMembersUsingLastSeen forKey:@"sortMembersUsingLastSeenTime"];
|
||||
}
|
||||
|
||||
@end
|
BIN
matrixConsole/Assets/close.png
Normal file
After Width: | Height: | Size: 397 B |
BIN
matrixConsole/Assets/default-profile.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
matrixConsole/Assets/gradient.png
Normal file
After Width: | Height: | Size: 194 B |
BIN
matrixConsole/Assets/logo.png
Normal file
After Width: | Height: | Size: 910 B |
BIN
matrixConsole/Assets/logoHighRes.png
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
matrixConsole/Assets/matrixConsole.jpg
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
matrixConsole/Assets/play.png
Executable file
After Width: | Height: | Size: 1.6 KiB |
BIN
matrixConsole/Assets/tab_home.ico
Normal file
After Width: | Height: | Size: 198 B |
BIN
matrixConsole/Assets/tab_recents.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
matrixConsole/Assets/tab_recents@2x.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
35
matrixConsole/Base.lproj/LaunchScreen.xib
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6250" systemVersion="13F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6244"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="matrixConsole.jpg" translatesAutoresizingMaskIntoConstraints="NO" id="Aaa-NS-PsE">
|
||||
<rect key="frame" x="120" y="150" width="240" height="128"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="128" id="1ye-KY-Dhp"/>
|
||||
<constraint firstAttribute="width" constant="240" id="Ar8-en-VzW"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstItem="Aaa-NS-PsE" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="150" id="8Ty-H4-BZ5"/>
|
||||
<constraint firstAttribute="centerX" secondItem="Aaa-NS-PsE" secondAttribute="centerX" id="JqN-6c-hL6"/>
|
||||
</constraints>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<point key="canvasLocation" x="548" y="455"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="matrixConsole.jpg" width="500" height="230"/>
|
||||
</resources>
|
||||
</document>
|
1064
matrixConsole/Base.lproj/Main.storyboard
Normal file
53
matrixConsole/CustomAlert.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 <UIKit/UIKit.h>
|
||||
|
||||
// Note: UIAlertView is deprecated in iOS 8. To create and manage alerts in iOS 8 and later, instead use UIAlertController
|
||||
// with a preferredStyle of UIAlertControllerStyleAlert.
|
||||
|
||||
typedef enum : NSUInteger {
|
||||
CustomAlertActionStyleDefault = 0,
|
||||
CustomAlertActionStyleCancel,
|
||||
CustomAlertActionStyleDestructive
|
||||
} CustomAlertActionStyle;
|
||||
|
||||
typedef enum : NSUInteger {
|
||||
CustomAlertStyleActionSheet = 0,
|
||||
CustomAlertStyleAlert
|
||||
} CustomAlertStyle;
|
||||
|
||||
@interface CustomAlert : NSObject <UIActionSheetDelegate> {
|
||||
}
|
||||
|
||||
typedef void (^blockCustomAlert_onClick)(CustomAlert *alert);
|
||||
typedef void (^blockCustomAlert_textFieldHandler)(UITextField *textField);
|
||||
|
||||
@property(nonatomic) NSInteger cancelButtonIndex; // required to dismiss cusmtomAlert on iOS < 8 (default is -1).
|
||||
@property(nonatomic, weak) UIView *sourceView;
|
||||
|
||||
- (id)initWithTitle:(NSString *)title message:(NSString *)message style:(CustomAlertStyle)style;
|
||||
// adds a button with the title. returns the index (0 based) of where it was added.
|
||||
- (NSInteger)addActionWithTitle:(NSString *)title style:(CustomAlertActionStyle)style handler:(blockCustomAlert_onClick)handler;
|
||||
// Adds a text field to an alert (Note: You can add a text field only if the style property is set to CustomAlertStyleAlert).
|
||||
- (void)addTextFieldWithConfigurationHandler:(blockCustomAlert_textFieldHandler)configurationHandler;
|
||||
|
||||
- (void)showInViewController:(UIViewController*)viewController;
|
||||
|
||||
- (void)dismiss:(BOOL)animated;
|
||||
- (UITextField *)textFieldAtIndex:(NSInteger)textFieldIndex;
|
||||
|
||||
@end
|
210
matrixConsole/CustomAlert.m
Normal file
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 "CustomAlert.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
@interface CustomAlert()
|
||||
{
|
||||
UIViewController* parentViewController;
|
||||
NSMutableArray *actions; // use only for iOS < 8
|
||||
}
|
||||
|
||||
@property(nonatomic, strong) id alert; // alert is kind of UIAlertController for IOS 8 and later, in other cases it's kind of UIAlertView or UIActionSheet.
|
||||
@end
|
||||
|
||||
@implementation CustomAlert
|
||||
|
||||
- (void)dealloc {
|
||||
// iOS < 8
|
||||
if ([_alert isKindOfClass:[UIActionSheet class]] || [_alert isKindOfClass:[UIAlertView class]]) {
|
||||
// Dismiss here AlertView or ActionSheet (if any) because its delegate is released
|
||||
[self dismiss:NO];
|
||||
}
|
||||
|
||||
_alert = nil;
|
||||
parentViewController = nil;
|
||||
actions = nil;
|
||||
}
|
||||
|
||||
- (id)initWithTitle:(NSString *)title message:(NSString *)message style:(CustomAlertStyle)style {
|
||||
if (self = [super init]) {
|
||||
// Check iOS version
|
||||
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8) {
|
||||
_alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:(UIAlertControllerStyle)style];
|
||||
} else {
|
||||
// Use legacy objects
|
||||
if (style == CustomAlertStyleActionSheet) {
|
||||
_alert = [[UIActionSheet alloc] initWithTitle:title delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
|
||||
} else {
|
||||
_alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
|
||||
}
|
||||
|
||||
self.cancelButtonIndex = -1;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (NSInteger)addActionWithTitle:(NSString *)title style:(CustomAlertActionStyle)style handler:(blockCustomAlert_onClick)handler {
|
||||
NSInteger index = 0;
|
||||
if ([_alert isKindOfClass:[UIAlertController class]]) {
|
||||
index = [(UIAlertController *)_alert actions].count;
|
||||
UIAlertAction* action = [UIAlertAction actionWithTitle:title
|
||||
style:(UIAlertActionStyle)style
|
||||
handler:^(UIAlertAction * action) {
|
||||
if (handler) {
|
||||
handler(self);
|
||||
}
|
||||
}];
|
||||
|
||||
[(UIAlertController *)_alert addAction:action];
|
||||
} else if ([_alert isKindOfClass:[UIActionSheet class]]) {
|
||||
if (actions == nil) {
|
||||
actions = [NSMutableArray array];
|
||||
}
|
||||
index = [(UIActionSheet *)_alert addButtonWithTitle:title];
|
||||
if (handler) {
|
||||
[actions addObject:handler];
|
||||
} else {
|
||||
[actions addObject:[NSNull null]];
|
||||
}
|
||||
} else if ([_alert isKindOfClass:[UIAlertView class]]) {
|
||||
if (actions == nil) {
|
||||
actions = [NSMutableArray array];
|
||||
}
|
||||
index = [(UIAlertView *)_alert addButtonWithTitle:title];
|
||||
if (handler) {
|
||||
[actions addObject:handler];
|
||||
} else {
|
||||
[actions addObject:[NSNull null]];
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
- (void)addTextFieldWithConfigurationHandler:(blockCustomAlert_textFieldHandler)configurationHandler {
|
||||
if ([_alert isKindOfClass:[UIAlertController class]]) {
|
||||
[(UIAlertController *)_alert addTextFieldWithConfigurationHandler:configurationHandler];
|
||||
} else if ([_alert isKindOfClass:[UIAlertView class]]) {
|
||||
UIAlertView *alertView = (UIAlertView *)_alert;
|
||||
// Check the current style
|
||||
if (alertView.alertViewStyle == UIAlertViewStyleDefault) {
|
||||
// Add the first text fields
|
||||
alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
|
||||
|
||||
if (configurationHandler) {
|
||||
// Store the callback
|
||||
UITextField *textField = [alertView textFieldAtIndex:0];
|
||||
objc_setAssociatedObject(textField, "configurationHandler", [configurationHandler copy], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
} else if (alertView.alertViewStyle != UIAlertViewStyleLoginAndPasswordInput) {
|
||||
// Add a second text field
|
||||
alertView.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
|
||||
|
||||
if (configurationHandler) {
|
||||
// Store the callback
|
||||
UITextField *textField = [alertView textFieldAtIndex:1];
|
||||
objc_setAssociatedObject(textField, "configurationHandler", [configurationHandler copy], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
}
|
||||
// CAUTION 1: only 2 text fields are supported fro iOS < 8
|
||||
// CAUTION 2: alert style "UIAlertViewStyleSecureTextInput" is not supported, use the configurationHandler to handle secure text field
|
||||
}
|
||||
}
|
||||
|
||||
- (void)showInViewController:(UIViewController*)viewController {
|
||||
if ([_alert isKindOfClass:[UIAlertController class]]) {
|
||||
if (viewController) {
|
||||
parentViewController = viewController;
|
||||
if (self.sourceView) {
|
||||
[_alert popoverPresentationController].sourceView = self.sourceView;
|
||||
[_alert popoverPresentationController].sourceRect = self.sourceView.bounds;
|
||||
}
|
||||
[viewController presentViewController:(UIAlertController *)_alert animated:YES completion:nil];
|
||||
}
|
||||
} else if ([_alert isKindOfClass:[UIActionSheet class]]) {
|
||||
[(UIActionSheet *)_alert showInView:[[UIApplication sharedApplication] keyWindow]];
|
||||
} else if ([_alert isKindOfClass:[UIAlertView class]]) {
|
||||
UIAlertView *alertView = (UIAlertView *)_alert;
|
||||
if (alertView.alertViewStyle != UIAlertViewStyleDefault) {
|
||||
// Call here textField handlers
|
||||
UITextField *textField = [alertView textFieldAtIndex:0];
|
||||
blockCustomAlert_textFieldHandler configurationHandler = objc_getAssociatedObject(textField, "configurationHandler");
|
||||
if (configurationHandler) {
|
||||
configurationHandler (textField);
|
||||
}
|
||||
if (alertView.alertViewStyle == UIAlertViewStyleLoginAndPasswordInput) {
|
||||
textField = [alertView textFieldAtIndex:1];
|
||||
blockCustomAlert_textFieldHandler configurationHandler = objc_getAssociatedObject(textField, "configurationHandler");
|
||||
if (configurationHandler) {
|
||||
configurationHandler (textField);
|
||||
}
|
||||
}
|
||||
}
|
||||
[alertView show];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dismiss:(BOOL)animated {
|
||||
if ([_alert isKindOfClass:[UIAlertController class]]) {
|
||||
[parentViewController dismissViewControllerAnimated:animated completion:nil];
|
||||
} else if ([_alert isKindOfClass:[UIActionSheet class]]) {
|
||||
[((UIActionSheet *)_alert) dismissWithClickedButtonIndex:self.cancelButtonIndex animated:animated];
|
||||
} else if ([_alert isKindOfClass:[UIAlertView class]]) {
|
||||
[((UIAlertView *)_alert) dismissWithClickedButtonIndex:self.cancelButtonIndex animated:animated];
|
||||
}
|
||||
_alert = nil;
|
||||
}
|
||||
|
||||
- (UITextField *)textFieldAtIndex:(NSInteger)textFieldIndex{
|
||||
if ([_alert isKindOfClass:[UIAlertController class]]) {
|
||||
return [((UIAlertController*)_alert).textFields objectAtIndex:textFieldIndex];
|
||||
} else if ([_alert isKindOfClass:[UIAlertView class]]) {
|
||||
return [((UIAlertView*)_alert) textFieldAtIndex:textFieldIndex];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark - UIAlertViewDelegate (iOS < 8)
|
||||
|
||||
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
|
||||
// Retrieve the callback
|
||||
blockCustomAlert_onClick block = [actions objectAtIndex:buttonIndex];
|
||||
if ([block isEqual:[NSNull null]] == NO) {
|
||||
// And call it
|
||||
block(self);
|
||||
}
|
||||
// Release alert reference
|
||||
_alert = nil;
|
||||
}
|
||||
|
||||
#pragma mark - UIActionSheetDelegate (iOS < 8)
|
||||
|
||||
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
|
||||
// Retrieve the callback
|
||||
blockCustomAlert_onClick block = [actions objectAtIndex:buttonIndex];
|
||||
if ([block isEqual:[NSNull null]] == NO) {
|
||||
// And call it
|
||||
block(self);
|
||||
}
|
||||
// Release _alert reference
|
||||
_alert = nil;
|
||||
}
|
||||
|
||||
@end
|
122
matrixConsole/Images.xcassets/AppIcon.appiconset/Contents.json
Normal file
|
@ -0,0 +1,122 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-29.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-29@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-29@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-40@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-40@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "57x57",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-57.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "57x57",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-57@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-60@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "Icon-60@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-29-1.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-29@2x-1.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-40.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-40@2x-1.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "50x50",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-50.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "50x50",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-50@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "72x72",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-72.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "72x72",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-72@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-76.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "Icon-76@2x.png",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
BIN
matrixConsole/Images.xcassets/AppIcon.appiconset/Icon-29-1.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
matrixConsole/Images.xcassets/AppIcon.appiconset/Icon-29.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 5.1 KiB |
BIN
matrixConsole/Images.xcassets/AppIcon.appiconset/Icon-29@2x.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
matrixConsole/Images.xcassets/AppIcon.appiconset/Icon-29@3x.png
Normal file
After Width: | Height: | Size: 6.3 KiB |
BIN
matrixConsole/Images.xcassets/AppIcon.appiconset/Icon-40.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 6 KiB |
BIN
matrixConsole/Images.xcassets/AppIcon.appiconset/Icon-40@2x.png
Normal file
After Width: | Height: | Size: 6 KiB |
BIN
matrixConsole/Images.xcassets/AppIcon.appiconset/Icon-40@3x.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
matrixConsole/Images.xcassets/AppIcon.appiconset/Icon-50.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
matrixConsole/Images.xcassets/AppIcon.appiconset/Icon-50@2x.png
Normal file
After Width: | Height: | Size: 7 KiB |
BIN
matrixConsole/Images.xcassets/AppIcon.appiconset/Icon-57.png
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
matrixConsole/Images.xcassets/AppIcon.appiconset/Icon-57@2x.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
matrixConsole/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
matrixConsole/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
matrixConsole/Images.xcassets/AppIcon.appiconset/Icon-72.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
matrixConsole/Images.xcassets/AppIcon.appiconset/Icon-72@2x.png
Normal file
After Width: | Height: | Size: 9.2 KiB |
BIN
matrixConsole/Images.xcassets/AppIcon.appiconset/Icon-76.png
Normal file
After Width: | Height: | Size: 6 KiB |
BIN
matrixConsole/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
|
@ -0,0 +1,107 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "iphone",
|
||||
"extent" : "full-screen",
|
||||
"minimum-system-version" : "7.0",
|
||||
"filename" : "launch@2x-1.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"extent" : "full-screen",
|
||||
"idiom" : "iphone",
|
||||
"subtype" : "retina4",
|
||||
"filename" : "launch-568h@2x-1.png",
|
||||
"minimum-system-version" : "7.0",
|
||||
"orientation" : "portrait",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "ipad",
|
||||
"extent" : "full-screen",
|
||||
"minimum-system-version" : "7.0",
|
||||
"filename" : "Default-Portrait~ipad.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"orientation" : "landscape",
|
||||
"idiom" : "ipad",
|
||||
"extent" : "full-screen",
|
||||
"minimum-system-version" : "7.0",
|
||||
"filename" : "Default-Landscape~ipad.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "ipad",
|
||||
"extent" : "full-screen",
|
||||
"minimum-system-version" : "7.0",
|
||||
"filename" : "Default-Portrait@2x~ipad.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "landscape",
|
||||
"idiom" : "ipad",
|
||||
"extent" : "full-screen",
|
||||
"minimum-system-version" : "7.0",
|
||||
"filename" : "Default-Landscape@2x~ipad.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "iphone",
|
||||
"extent" : "full-screen",
|
||||
"filename" : "launch.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "iphone",
|
||||
"extent" : "full-screen",
|
||||
"filename" : "launch@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "iphone",
|
||||
"extent" : "full-screen",
|
||||
"filename" : "launch-568h@2x.png",
|
||||
"subtype" : "retina4",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "ipad",
|
||||
"extent" : "to-status-bar",
|
||||
"filename" : "Default-Portrait.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"orientation" : "landscape",
|
||||
"idiom" : "ipad",
|
||||
"extent" : "to-status-bar",
|
||||
"filename" : "Default-Landscape.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"orientation" : "portrait",
|
||||
"idiom" : "ipad",
|
||||
"extent" : "to-status-bar",
|
||||
"filename" : "Default-Portrait@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"orientation" : "landscape",
|
||||
"idiom" : "ipad",
|
||||
"extent" : "to-status-bar",
|
||||
"filename" : "Default-Landscape@2x.png",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 74 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 75 KiB |
After Width: | Height: | Size: 76 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 30 KiB |
BIN
matrixConsole/Images.xcassets/LaunchImage.launchimage/launch.png
Normal file
After Width: | Height: | Size: 19 KiB |
After Width: | Height: | Size: 27 KiB |
After Width: | Height: | Size: 27 KiB |
57
matrixConsole/Info.plist
Normal file
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.matrix.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UIStatusBarTintParameters</key>
|
||||
<dict>
|
||||
<key>UINavigationBar</key>
|
||||
<dict>
|
||||
<key>Style</key>
|
||||
<string>UIBarStyleDefault</string>
|
||||
<key>Translucent</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
52
matrixConsole/MatrixHandler.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import <MatrixSDK/MatrixSDK.h>
|
||||
|
||||
extern NSString *const kMatrixHandlerUnsupportedMessagePrefix;
|
||||
|
||||
@interface MatrixHandler : NSObject
|
||||
|
||||
@property (strong, nonatomic) MXRestClient *mxRestClient;
|
||||
@property (strong, nonatomic) MXSession *mxSession;
|
||||
|
||||
@property (strong, nonatomic) NSString *homeServerURL;
|
||||
@property (strong, nonatomic) NSString *homeServer;
|
||||
@property (strong, nonatomic) NSString *userLogin;
|
||||
@property (strong, nonatomic) NSString *userId;
|
||||
@property (strong, nonatomic) NSString *accessToken;
|
||||
|
||||
// Matrix user's settings
|
||||
@property (strong, nonatomic) NSString *userDisplayName;
|
||||
@property (strong, nonatomic) NSString *userPictureURL;
|
||||
|
||||
@property (nonatomic,readonly) BOOL isLogged;
|
||||
@property (nonatomic,readonly) BOOL isInitialSyncDone;
|
||||
|
||||
+ (MatrixHandler *)sharedHandler;
|
||||
|
||||
- (void)logout;
|
||||
|
||||
// Flush and restore Matrix data
|
||||
- (void)forceInitialSync;
|
||||
|
||||
- (void)enableEventsNotifications:(BOOL)isEnabled;
|
||||
|
||||
- (BOOL)isAttachment:(MXEvent*)message;
|
||||
- (BOOL)isNotification:(MXEvent*)message;
|
||||
- (NSString*)displayTextFor:(MXEvent*)message inSubtitleMode:(BOOL)isSubtitle;
|
||||
|
||||
@end
|
629
matrixConsole/MatrixHandler.m
Normal file
|
@ -0,0 +1,629 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 "MatrixHandler.h"
|
||||
#import "AppDelegate.h"
|
||||
#import "AppSettings.h"
|
||||
#import "CustomAlert.h"
|
||||
|
||||
NSString *const kMatrixHandlerUnsupportedMessagePrefix = @"UNSUPPORTED MSG: ";
|
||||
|
||||
static MatrixHandler *sharedHandler = nil;
|
||||
|
||||
@interface MatrixHandler () {
|
||||
// We will notify user only once on session failure
|
||||
BOOL notifyOpenSessionFailure;
|
||||
|
||||
// Handle user's settings change
|
||||
id roomMembersListener;
|
||||
// Handle events notification
|
||||
id eventsListener;
|
||||
}
|
||||
|
||||
@property (nonatomic,readwrite) BOOL isInitialSyncDone;
|
||||
@property (strong, nonatomic) CustomAlert *mxNotification;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MatrixHandler
|
||||
|
||||
@synthesize homeServerURL, homeServer, userLogin, userId, accessToken;
|
||||
@synthesize userDisplayName, userPictureURL;
|
||||
|
||||
+ (MatrixHandler *)sharedHandler {
|
||||
@synchronized(self) {
|
||||
if(sharedHandler == nil)
|
||||
{
|
||||
sharedHandler = [[super allocWithZone:NULL] init];
|
||||
}
|
||||
}
|
||||
return sharedHandler;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
-(MatrixHandler *)init {
|
||||
if (self = [super init]) {
|
||||
_isInitialSyncDone = NO;
|
||||
notifyOpenSessionFailure = YES;
|
||||
|
||||
// Read potential homeserver url in shared defaults object
|
||||
if (self.homeServerURL) {
|
||||
self.mxRestClient = [[MXRestClient alloc] initWithHomeServer:self.homeServerURL];
|
||||
|
||||
if (self.accessToken) {
|
||||
[self openSession];
|
||||
}
|
||||
}
|
||||
// The app will look for user's display name in incoming messages, it must not be nil.
|
||||
if (self.userDisplayName == nil) {
|
||||
self.userDisplayName = @"";
|
||||
}
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onAppDidEnterBackground) name:UIApplicationDidEnterBackgroundNotification object:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)openSession {
|
||||
|
||||
MXCredentials *credentials = [[MXCredentials alloc] init];
|
||||
credentials.homeServer = self.homeServerURL;
|
||||
credentials.userId = self.userId;
|
||||
credentials.accessToken = self.accessToken;
|
||||
|
||||
self.mxRestClient = [[MXRestClient alloc] initWithCredentials:credentials];
|
||||
if (self.mxRestClient) {
|
||||
// Request user's display name
|
||||
[self.mxRestClient displayNameForUser:self.userId success:^(NSString *displayname) {
|
||||
self.userDisplayName = displayname;
|
||||
} failure:^(NSError *error) {
|
||||
NSLog(@"Get displayName failed: %@", error);
|
||||
//Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
}];
|
||||
// Request user's avatar
|
||||
[self.mxRestClient avatarUrlForUser:self.userId success:^(NSString *avatar_url) {
|
||||
self.userPictureURL = avatar_url;
|
||||
} failure:^(NSError *error) {
|
||||
NSLog(@"Get picture url failed: %@", error);
|
||||
//Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
}];
|
||||
|
||||
self.mxSession = [[MXSession alloc] initWithMatrixRestClient:self.mxRestClient];
|
||||
// Check here whether the app user wants to display all the events
|
||||
if ([[AppSettings sharedSettings] displayAllEvents]) {
|
||||
// Override events filter to retrieve all the events
|
||||
self.mxSession.eventsFilterForMessages = @[
|
||||
kMXEventTypeStringRoomName,
|
||||
kMXEventTypeStringRoomTopic,
|
||||
kMXEventTypeStringRoomMember,
|
||||
kMXEventTypeStringRoomCreate,
|
||||
kMXEventTypeStringRoomJoinRules,
|
||||
kMXEventTypeStringRoomPowerLevels,
|
||||
kMXEventTypeStringRoomAddStateLevel,
|
||||
kMXEventTypeStringRoomSendEventLevel,
|
||||
kMXEventTypeStringRoomOpsLevel,
|
||||
kMXEventTypeStringRoomAliases,
|
||||
kMXEventTypeStringRoomMessage,
|
||||
kMXEventTypeStringRoomMessageFeedback,
|
||||
kMXEventTypeStringPresence
|
||||
];
|
||||
}
|
||||
// Launch mxSession
|
||||
[self.mxSession start:^{
|
||||
self.isInitialSyncDone = YES;
|
||||
|
||||
// Register listener to update user's information
|
||||
roomMembersListener = [self.mxSession listenToEventsOfTypes:@[kMXEventTypeStringPresence] onEvent:^(MXEvent *event, MXEventDirection direction, id customObject) {
|
||||
// Consider only live events
|
||||
if (direction == MXEventDirectionForwards) {
|
||||
// Consider only events from app user
|
||||
if ([event.userId isEqualToString:self.userId]) {
|
||||
// Update local storage
|
||||
if (![self.userDisplayName isEqualToString:event.content[@"displayname"]]) {
|
||||
self.userDisplayName = event.content[@"displayname"];
|
||||
}
|
||||
if (![self.userPictureURL isEqualToString:event.content[@"avatar_url"]]) {
|
||||
self.userPictureURL = event.content[@"avatar_url"];
|
||||
}
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
// Check whether the app user wants notifications on new events
|
||||
if ([[AppSettings sharedSettings] enableNotifications]) {
|
||||
[self enableEventsNotifications:YES];
|
||||
}
|
||||
} failure:^(NSError *error) {
|
||||
NSLog(@"Initial Sync failed: %@", error);
|
||||
if (notifyOpenSessionFailure) {
|
||||
//Alert user only once
|
||||
notifyOpenSessionFailure = NO;
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
}
|
||||
|
||||
// Postpone a new attempt in 10 sec
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[self openSession];
|
||||
});
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)closeSession {
|
||||
if (eventsListener) {
|
||||
[self.mxSession removeListener:eventsListener];
|
||||
eventsListener = nil;
|
||||
}
|
||||
if (roomMembersListener) {
|
||||
[self.mxSession removeListener:roomMembersListener];
|
||||
roomMembersListener = nil;
|
||||
}
|
||||
[self.mxSession close];
|
||||
self.mxSession = nil;
|
||||
|
||||
[self.mxRestClient close];
|
||||
if (self.homeServerURL) {
|
||||
self.mxRestClient = [[MXRestClient alloc] initWithHomeServer:self.homeServerURL];
|
||||
} else {
|
||||
self.mxRestClient = nil;
|
||||
}
|
||||
|
||||
self.isInitialSyncDone = NO;
|
||||
notifyOpenSessionFailure = YES;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
|
||||
[self closeSession];
|
||||
self.mxSession = nil;
|
||||
|
||||
if (self.mxNotification) {
|
||||
[self.mxNotification dismiss:NO];
|
||||
self.mxNotification = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)onAppDidEnterBackground {
|
||||
// Hide potential notification
|
||||
if (self.mxNotification) {
|
||||
[self.mxNotification dismiss:NO];
|
||||
self.mxNotification = nil;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (BOOL)isLogged {
|
||||
return (self.accessToken != nil);
|
||||
}
|
||||
|
||||
- (void)logout {
|
||||
// Reset access token (mxSession is closed by setter)
|
||||
self.accessToken = nil;
|
||||
|
||||
// Reset local storage of user's settings
|
||||
self.userDisplayName = @"";
|
||||
self.userPictureURL = nil;
|
||||
}
|
||||
|
||||
- (void)forceInitialSync {
|
||||
[self closeSession];
|
||||
notifyOpenSessionFailure = NO;
|
||||
if (self.accessToken) {
|
||||
[self openSession];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)enableEventsNotifications:(BOOL)isEnabled {
|
||||
if (isEnabled) {
|
||||
// Register events listener
|
||||
eventsListener = [self.mxSession listenToEventsOfTypes:self.mxSession.eventsFilterForMessages onEvent:^(MXEvent *event, MXEventDirection direction, id customObject) {
|
||||
// Consider only live event (Ignore presence event)
|
||||
if (direction == MXEventDirectionForwards && (event.eventType != MXEventTypePresence)) {
|
||||
// If we are running on background, show a local notif
|
||||
if (UIApplicationStateBackground == [UIApplication sharedApplication].applicationState)
|
||||
{
|
||||
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
|
||||
localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:0];
|
||||
localNotification.hasAction = YES;
|
||||
[localNotification setAlertBody:[self displayTextFor:event inSubtitleMode:YES]];
|
||||
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
|
||||
} else if ([[AppDelegate theDelegate].masterTabBarController.visibleRoomId isEqualToString:event.roomId] == NO) {
|
||||
// The concerned room is not presently visible, we display a notification by removing existing one (if any)
|
||||
if (self.mxNotification) {
|
||||
[self.mxNotification dismiss:NO];
|
||||
}
|
||||
|
||||
self.mxNotification = [[CustomAlert alloc] initWithTitle:[self.mxSession room:event.roomId].state.displayname
|
||||
message:[self displayTextFor:event inSubtitleMode:YES]
|
||||
style:CustomAlertStyleAlert];
|
||||
self.mxNotification.cancelButtonIndex = [self.mxNotification addActionWithTitle:@"OK"
|
||||
style:CustomAlertActionStyleDefault
|
||||
handler:^(CustomAlert *alert) {
|
||||
[MatrixHandler sharedHandler].mxNotification = nil;
|
||||
}];
|
||||
[self.mxNotification addActionWithTitle:@"View"
|
||||
style:CustomAlertActionStyleDefault
|
||||
handler:^(CustomAlert *alert) {
|
||||
[MatrixHandler sharedHandler].mxNotification = nil;
|
||||
// Show the room
|
||||
[[AppDelegate theDelegate].masterTabBarController showRoom:event.roomId];
|
||||
}];
|
||||
|
||||
[self.mxNotification showInViewController:[[AppDelegate theDelegate].masterTabBarController selectedViewController]];
|
||||
}
|
||||
}
|
||||
}];
|
||||
} else {
|
||||
if (eventsListener) {
|
||||
[self.mxSession removeListener:eventsListener];
|
||||
eventsListener = nil;
|
||||
}
|
||||
if (self.mxNotification) {
|
||||
[self.mxNotification dismiss:NO];
|
||||
self.mxNotification = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Properties
|
||||
|
||||
- (NSString *)homeServerURL {
|
||||
return [[NSUserDefaults standardUserDefaults] objectForKey:@"homeserverurl"];
|
||||
}
|
||||
|
||||
- (void)setHomeServerURL:(NSString *)inHomeserverURL {
|
||||
if (inHomeserverURL.length) {
|
||||
[[NSUserDefaults standardUserDefaults] setObject:inHomeserverURL forKey:@"homeserverurl"];
|
||||
self.mxRestClient = [[MXRestClient alloc] initWithHomeServer:inHomeserverURL];
|
||||
} else {
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"homeserverurl"];
|
||||
// Reinitialize matrix handler
|
||||
[self logout];
|
||||
}
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
}
|
||||
|
||||
- (NSString *)homeServer {
|
||||
return [[NSUserDefaults standardUserDefaults] objectForKey:@"homeserver"];
|
||||
}
|
||||
|
||||
- (void)setHomeServer:(NSString *)inHomeserver {
|
||||
if (inHomeserver.length) {
|
||||
[[NSUserDefaults standardUserDefaults] setObject:inHomeserver forKey:@"homeserver"];
|
||||
} else {
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"homeserver"];
|
||||
}
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
}
|
||||
|
||||
- (NSString *)userLogin {
|
||||
return [[NSUserDefaults standardUserDefaults] objectForKey:@"userlogin"];
|
||||
}
|
||||
|
||||
- (void)setUserLogin:(NSString *)inUserLogin {
|
||||
if (inUserLogin.length) {
|
||||
[[NSUserDefaults standardUserDefaults] setObject:inUserLogin forKey:@"userlogin"];
|
||||
} else {
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"userlogin"];
|
||||
}
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
}
|
||||
|
||||
- (NSString *)userId {
|
||||
return [[NSUserDefaults standardUserDefaults] objectForKey:@"userid"];
|
||||
}
|
||||
|
||||
- (void)setUserId:(NSString *)inUserId {
|
||||
if (inUserId.length) {
|
||||
[[NSUserDefaults standardUserDefaults] setObject:inUserId forKey:@"userid"];
|
||||
} else {
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"userid"];
|
||||
}
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
}
|
||||
|
||||
- (NSString *)accessToken {
|
||||
return [[NSUserDefaults standardUserDefaults] objectForKey:@"accesstoken"];
|
||||
}
|
||||
|
||||
- (void)setAccessToken:(NSString *)inAccessToken {
|
||||
if (inAccessToken.length) {
|
||||
[[NSUserDefaults standardUserDefaults] setObject:inAccessToken forKey:@"accesstoken"];
|
||||
[self openSession];
|
||||
} else {
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"accesstoken"];
|
||||
[self closeSession];
|
||||
}
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
}
|
||||
|
||||
#pragma mark - Matrix user's settings
|
||||
|
||||
- (NSString *)userDisplayName {
|
||||
return [[NSUserDefaults standardUserDefaults] objectForKey:@"userdisplayname"];
|
||||
}
|
||||
|
||||
- (void)setUserDisplayName:(NSString *)inUserDisplayName {
|
||||
if ([inUserDisplayName isEqual:[NSNull null]] == NO && inUserDisplayName.length) {
|
||||
[[NSUserDefaults standardUserDefaults] setObject:inUserDisplayName forKey:@"userdisplayname"];
|
||||
} else {
|
||||
// the app will look for this display name in incoming messages, it must not be nil.
|
||||
[[NSUserDefaults standardUserDefaults] setObject:@"" forKey:@"userdisplayname"];
|
||||
}
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
}
|
||||
|
||||
- (NSString *)userPictureURL {
|
||||
return [[NSUserDefaults standardUserDefaults] objectForKey:@"userpictureurl"];
|
||||
}
|
||||
|
||||
- (void)setUserPictureURL:(NSString *)inUserPictureURL {
|
||||
if ([inUserPictureURL isEqual:[NSNull null]] == NO && inUserPictureURL.length) {
|
||||
[[NSUserDefaults standardUserDefaults] setObject:inUserPictureURL forKey:@"userpictureurl"];
|
||||
} else {
|
||||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"userpictureurl"];
|
||||
}
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
}
|
||||
|
||||
#pragma mark - messages handler
|
||||
|
||||
- (BOOL)isAttachment:(MXEvent*)message {
|
||||
if (message.eventType == MXEventTypeRoomMessage) {
|
||||
NSString *msgtype = message.content[@"msgtype"];
|
||||
if ([msgtype isEqualToString:kMXMessageTypeImage]
|
||||
|| [msgtype isEqualToString:kMXMessageTypeAudio]
|
||||
|| [msgtype isEqualToString:kMXMessageTypeVideo]
|
||||
|| [msgtype isEqualToString:kMXMessageTypeLocation]) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)isNotification:(MXEvent*)message {
|
||||
// We consider as notification mxEvent which is not a text message or an attachment
|
||||
if (message.eventType == MXEventTypeRoomMessage) {
|
||||
NSString *msgtype = message.content[@"msgtype"];
|
||||
if ([msgtype isEqualToString:kMXMessageTypeEmote]) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSString*)displayTextFor:(MXEvent*)message inSubtitleMode:(BOOL)isSubtitle {
|
||||
NSString *displayText = nil;
|
||||
// Retrieve roomData related to the message
|
||||
MXRoom *room = [self.mxSession room:message.roomId];
|
||||
// Prepare display name for concerned users
|
||||
NSString *memberDisplayName = [room.state memberName:message.userId];
|
||||
NSString *targetDisplayName = nil;
|
||||
if (message.stateKey) {
|
||||
targetDisplayName = [room.state memberName:message.stateKey];
|
||||
}
|
||||
|
||||
switch (message.eventType) {
|
||||
case MXEventTypeRoomName: {
|
||||
displayText = [NSString stringWithFormat:@"%@ changed the room name to: %@", memberDisplayName, message.content[@"name"]];
|
||||
break;
|
||||
}
|
||||
case MXEventTypeRoomTopic: {
|
||||
displayText = [NSString stringWithFormat:@"%@ changed the topic to: %@", memberDisplayName, message.content[@"topic"]];
|
||||
break;
|
||||
}
|
||||
case MXEventTypeRoomMember: {
|
||||
// Presently only change on membership, display name and avatar are supported
|
||||
|
||||
// Retrieve membership
|
||||
NSString* membership = message.content[@"membership"];
|
||||
NSString *prevMembership = nil;
|
||||
if (message.prevContent) {
|
||||
prevMembership = message.prevContent[@"membership"];
|
||||
}
|
||||
|
||||
// Check whether the membership is unchanged
|
||||
if (prevMembership && membership && [membership isEqualToString:prevMembership]) {
|
||||
// Check whether the display name has been changed
|
||||
NSString *displayname = message.content[@"displayname"];
|
||||
NSString *prevDisplayname = message.prevContent[@"displayname"];
|
||||
if (!displayname.length) {
|
||||
displayname = nil;
|
||||
}
|
||||
if (!prevDisplayname.length) {
|
||||
prevDisplayname = nil;
|
||||
}
|
||||
if ((displayname || prevDisplayname) && ([displayname isEqualToString:prevDisplayname] == NO)) {
|
||||
displayText = [NSString stringWithFormat:@"%@ changed their display name from %@ to %@", message.userId, prevDisplayname, displayname];
|
||||
}
|
||||
|
||||
// Check whether the avatar has been changed
|
||||
NSString *avatar = message.content[@"avatar_url"];
|
||||
NSString *prevAvatar = message.prevContent[@"avatar_url"];
|
||||
if (!avatar.length) {
|
||||
avatar = nil;
|
||||
}
|
||||
if (!prevAvatar.length) {
|
||||
prevAvatar = nil;
|
||||
}
|
||||
if ((prevAvatar || avatar) && ([avatar isEqualToString:prevAvatar] == NO)) {
|
||||
if (displayText) {
|
||||
displayText = [NSString stringWithFormat:@"%@ (picture profile was changed too)", displayText];
|
||||
} else {
|
||||
displayText = [NSString stringWithFormat:@"%@ changed their picture profile", memberDisplayName];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Consider here a membership change
|
||||
if ([membership isEqualToString:@"invite"]) {
|
||||
displayText = [NSString stringWithFormat:@"%@ invited %@", memberDisplayName, targetDisplayName];
|
||||
} else if ([membership isEqualToString:@"join"]) {
|
||||
displayText = [NSString stringWithFormat:@"%@ joined", memberDisplayName];
|
||||
} else if ([membership isEqualToString:@"leave"]) {
|
||||
if ([message.userId isEqualToString:message.stateKey]) {
|
||||
displayText = [NSString stringWithFormat:@"%@ left", memberDisplayName];
|
||||
} else if (prevMembership) {
|
||||
if ([prevMembership isEqualToString:@"join"] || [prevMembership isEqualToString:@"invite"]) {
|
||||
displayText = [NSString stringWithFormat:@"%@ kicked %@", memberDisplayName, targetDisplayName];
|
||||
if (message.content[@"reason"]) {
|
||||
displayText = [NSString stringWithFormat:@"%@: %@", displayText, message.content[@"reason"]];
|
||||
}
|
||||
} else if ([prevMembership isEqualToString:@"ban"]) {
|
||||
displayText = [NSString stringWithFormat:@"%@ unbanned %@", memberDisplayName, targetDisplayName];
|
||||
}
|
||||
}
|
||||
} else if ([membership isEqualToString:@"ban"]) {
|
||||
displayText = [NSString stringWithFormat:@"%@ banned %@", memberDisplayName, targetDisplayName];
|
||||
if (message.content[@"reason"]) {
|
||||
displayText = [NSString stringWithFormat:@"%@: %@", displayText, message.content[@"reason"]];
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MXEventTypeRoomCreate: {
|
||||
NSString *creatorId = message.content[@"creator"];
|
||||
if (creatorId) {
|
||||
displayText = [NSString stringWithFormat:@"%@ created the room", [room.state memberName:creatorId]];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MXEventTypeRoomJoinRules: {
|
||||
NSString *joinRule = message.content[@"join_rule"];
|
||||
if (joinRule) {
|
||||
displayText = [NSString stringWithFormat:@"The join rule is: %@", joinRule];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MXEventTypeRoomPowerLevels: {
|
||||
displayText = @"The power level of room members are:";
|
||||
NSDictionary *users = message.content[@"users"];
|
||||
for (NSString *key in users.allKeys) {
|
||||
displayText = [NSString stringWithFormat:@"%@\r\n\u2022 %@: %@", displayText, key, [users objectForKey:key]];
|
||||
}
|
||||
if (message.content[@"users_default"]) {
|
||||
displayText = [NSString stringWithFormat:@"%@\r\n\u2022 %@: %@", displayText, @"default", message.content[@"users_default"]];
|
||||
}
|
||||
|
||||
displayText = [NSString stringWithFormat:@"%@\r\nThe minimum power levels that a user must have before acting are:", displayText];
|
||||
if (message.content[@"ban"]) {
|
||||
displayText = [NSString stringWithFormat:@"%@\r\n\u2022 ban: %@", displayText, message.content[@"ban"]];
|
||||
}
|
||||
if (message.content[@"kick"]) {
|
||||
displayText = [NSString stringWithFormat:@"%@\r\n\u2022 kick: %@", displayText, message.content[@"kick"]];
|
||||
}
|
||||
if (message.content[@"redact"]) {
|
||||
displayText = [NSString stringWithFormat:@"%@\r\n\u2022 redact: %@", displayText, message.content[@"redact"]];
|
||||
}
|
||||
|
||||
displayText = [NSString stringWithFormat:@"%@\r\nThe minimum power levels related to events are:", displayText];
|
||||
NSDictionary *events = message.content[@"events"];
|
||||
for (NSString *key in events.allKeys) {
|
||||
displayText = [NSString stringWithFormat:@"%@\r\n\u2022 %@: %@", displayText, key, [events objectForKey:key]];
|
||||
}
|
||||
if (message.content[@"events_default"]) {
|
||||
displayText = [NSString stringWithFormat:@"%@\r\n\u2022 %@: %@", displayText, @"events_default", message.content[@"events_default"]];
|
||||
}
|
||||
if (message.content[@"state_default"]) {
|
||||
displayText = [NSString stringWithFormat:@"%@\r\n\u2022 %@: %@", displayText, @"state_default", message.content[@"state_default"]];
|
||||
}
|
||||
break;
|
||||
}
|
||||
// case MXEventTypeRoomAddStateLevel: {
|
||||
// NSString *minLevel = message.content[@"level"];
|
||||
// if (minLevel) {
|
||||
// displayText = [NSString stringWithFormat:@"The minimum power level a user needs to add state is: %@", minLevel];
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// case MXEventTypeRoomSendEventLevel: {
|
||||
// NSString *minLevel = message.content[@"level"];
|
||||
// if (minLevel) {
|
||||
// displayText = [NSString stringWithFormat:@"The minimum power level a user needs to send an event is: %@", minLevel];
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// case MXEventTypeRoomOpsLevel: {
|
||||
// displayText = @"The minimum power levels that a user must have before acting are:";
|
||||
// for (NSString *key in message.content.allKeys) {
|
||||
// displayText = [NSString stringWithFormat:@"%@\r\n%@:%@", displayText, key, [message.content objectForKey:key]];
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
case MXEventTypeRoomAliases: {
|
||||
NSArray *aliases = message.content[@"aliases"];
|
||||
if (aliases) {
|
||||
displayText = [NSString stringWithFormat:@"The room aliases are: %@", aliases];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MXEventTypeRoomMessage: {
|
||||
NSString *msgtype = message.content[@"msgtype"];
|
||||
if ([msgtype isEqualToString:kMXMessageTypeText]) {
|
||||
displayText = message.content[@"body"];
|
||||
} else if ([msgtype isEqualToString:kMXMessageTypeEmote]) {
|
||||
displayText = [NSString stringWithFormat:@"* %@ %@", memberDisplayName, message.content[@"body"]];
|
||||
} else if ([msgtype isEqualToString:kMXMessageTypeImage]) {
|
||||
displayText = @"image attachment";
|
||||
} else if ([msgtype isEqualToString:kMXMessageTypeAudio]) {
|
||||
displayText = @"audio attachment";
|
||||
} else if ([msgtype isEqualToString:kMXMessageTypeVideo]) {
|
||||
displayText = @"video attachment";
|
||||
} else if ([msgtype isEqualToString:kMXMessageTypeLocation]) {
|
||||
displayText = @"location attachment";
|
||||
}
|
||||
|
||||
// Check whether the sender name has to be added
|
||||
if (isSubtitle && [msgtype isEqualToString:kMXMessageTypeEmote] == NO) {
|
||||
displayText = [NSString stringWithFormat:@"%@: %@", memberDisplayName, displayText];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MXEventTypeRoomMessageFeedback: {
|
||||
NSString *type = message.content[@"type"];
|
||||
NSString *eventId = message.content[@"target_event_id"];
|
||||
if (type && eventId) {
|
||||
displayText = [NSString stringWithFormat:@"Feedback event (id: %@): %@", eventId, type];
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MXEventTypeCustom:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (displayText == nil) {
|
||||
NSLog(@"ERROR: Unsupported message %@)", message.description);
|
||||
if (isSubtitle || [AppSettings sharedSettings].hideUnsupportedMessages) {
|
||||
displayText = @"";
|
||||
} else {
|
||||
// Return event content as unsupported message
|
||||
displayText = [NSString stringWithFormat:@"%@%@", kMatrixHandlerUnsupportedMessagePrefix, message.description];
|
||||
}
|
||||
}
|
||||
|
||||
return displayText;
|
||||
}
|
||||
|
||||
@end
|
50
matrixConsole/MediaManager.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 <AVFoundation/AVFoundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
extern NSString *const kMediaManagerPrefixForDummyURL;
|
||||
|
||||
// The callback blocks
|
||||
typedef void (^blockMediaManager_onImageReady)(UIImage *image);
|
||||
typedef void (^blockMediaManager_onMediaReady)(NSString *cacheFilePath);
|
||||
typedef void (^blockMediaManager_onError)(NSError *error);
|
||||
|
||||
@interface MediaManager : NSObject
|
||||
|
||||
+ (id)sharedInstance;
|
||||
|
||||
+ (UIImage *)resize:(UIImage *)image toFitInSize:(CGSize)size;
|
||||
|
||||
// Load a picture from the local cache or download it if it is not available yet.
|
||||
// In this second case a mediaLoader reference is returned in order to let the user cancel this action.
|
||||
+ (id)loadPicture:(NSString *)pictureURL
|
||||
success:(blockMediaManager_onImageReady)success
|
||||
failure:(blockMediaManager_onError)failure;
|
||||
// Prepare a media from the local cache or download it if it is not available yet.
|
||||
// In this second case a mediaLoader reference is returned in order to let the user cancel this action.
|
||||
+ (id)prepareMedia:(NSString *)mediaURL
|
||||
mimeType:(NSString *)mimeType
|
||||
success:(blockMediaManager_onMediaReady)success
|
||||
failure:(blockMediaManager_onError)failure;
|
||||
+ (void)cancel:(id)mediaLoader;
|
||||
|
||||
+ (NSString *)cacheMediaData:(NSData *)mediaData forURL:(NSString *)mediaURL mimeType:(NSString *)mimeType;
|
||||
|
||||
+ (void)clearCache;
|
||||
|
||||
@end
|
327
matrixConsole/MediaManager.m
Normal file
|
@ -0,0 +1,327 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 "MediaManager.h"
|
||||
|
||||
NSString *const kMediaManagerPrefixForDummyURL = @"dummyUrl-";
|
||||
|
||||
static NSString* mediaCachePath = nil;
|
||||
static NSString *mediaDir = @"mediacache";
|
||||
|
||||
static MediaManager *sharedMediaManager = nil;
|
||||
|
||||
@interface MediaLoader : NSObject <NSURLConnectionDataDelegate> {
|
||||
NSString *mediaURL;
|
||||
NSString *mimeType;
|
||||
|
||||
blockMediaManager_onMediaReady onMediaReady;
|
||||
blockMediaManager_onError onError;
|
||||
|
||||
NSMutableData *downloadData;
|
||||
NSURLConnection *downloadConnection;
|
||||
}
|
||||
@end
|
||||
|
||||
#pragma mark - MediaLoader
|
||||
|
||||
@implementation MediaLoader
|
||||
|
||||
- (void)downloadPicture:(NSString*)pictureURL
|
||||
success:(blockMediaManager_onImageReady)success
|
||||
failure:(blockMediaManager_onError)failure {
|
||||
// Download picture content
|
||||
[self downloadMedia:pictureURL mimeType:@"image/jpeg" success:^(NSString *cacheFilePath) {
|
||||
if (success) {
|
||||
NSData* imageContent = [NSData dataWithContentsOfFile:cacheFilePath options:(NSDataReadingMappedAlways | NSDataReadingUncached) error:nil];
|
||||
if (imageContent) {
|
||||
UIImage *image = [UIImage imageWithData:imageContent];
|
||||
if (image) {
|
||||
success(image);
|
||||
} else {
|
||||
NSLog(@"ERROR: picture download failed: %@", pictureURL);
|
||||
if (failure){
|
||||
failure(nil);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} failure:^(NSError *error) {
|
||||
failure(error);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)downloadMedia:(NSString*)aMediaURL
|
||||
mimeType:(NSString *)aMimeType
|
||||
success:(blockMediaManager_onMediaReady)success
|
||||
failure:(blockMediaManager_onError)failure {
|
||||
// Report provided params
|
||||
mediaURL = aMediaURL;
|
||||
mimeType = aMimeType;
|
||||
onMediaReady = success;
|
||||
onError = failure;
|
||||
|
||||
// Start downloading
|
||||
NSURL *url = [NSURL URLWithString:aMediaURL];
|
||||
downloadData = [[NSMutableData alloc] init];
|
||||
downloadConnection = [[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:url] delegate:self];
|
||||
}
|
||||
|
||||
- (void)cancel {
|
||||
// Reset blocks
|
||||
onMediaReady = nil;
|
||||
onError = nil;
|
||||
// Cancel potential connection
|
||||
if (downloadConnection) {
|
||||
[downloadConnection cancel];
|
||||
downloadConnection = nil;
|
||||
downloadData = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self cancel];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
|
||||
NSLog(@"ERROR: media download failed: %@, %@", error, mediaURL);
|
||||
if (onError) {
|
||||
onError (error);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
|
||||
// Append data
|
||||
[downloadData appendData:data];
|
||||
}
|
||||
|
||||
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
|
||||
if (downloadData.length) {
|
||||
// Cache the downloaded data
|
||||
NSString *cacheFilePath = [MediaManager cacheMediaData:downloadData forURL:mediaURL mimeType:mimeType];
|
||||
// Call registered block
|
||||
if (onMediaReady) {
|
||||
onMediaReady(cacheFilePath);
|
||||
}
|
||||
} else {
|
||||
NSLog(@"ERROR: media download failed: %@", mediaURL);
|
||||
if (onError){
|
||||
onError(nil);
|
||||
}
|
||||
}
|
||||
|
||||
downloadData = nil;
|
||||
downloadConnection = nil;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - MediaManager
|
||||
|
||||
@implementation MediaManager
|
||||
|
||||
+ (id)sharedInstance {
|
||||
@synchronized(self) {
|
||||
if(sharedMediaManager == nil)
|
||||
sharedMediaManager = [[self alloc] init];
|
||||
}
|
||||
return sharedMediaManager;
|
||||
}
|
||||
|
||||
+ (UIImage *)resize:(UIImage *)image toFitInSize:(CGSize)size {
|
||||
UIImage *resizedImage = image;
|
||||
|
||||
// Check whether resize is required
|
||||
if (size.width && size.height) {
|
||||
CGFloat width = image.size.width;
|
||||
CGFloat height = image.size.height;
|
||||
|
||||
if (width > size.width) {
|
||||
height = (height * size.width) / width;
|
||||
height = floorf(height / 2) * 2;
|
||||
width = size.width;
|
||||
}
|
||||
if (height > size.height) {
|
||||
width = (width * size.height) / height;
|
||||
width = floorf(width / 2) * 2;
|
||||
height = size.height;
|
||||
}
|
||||
|
||||
if (width != image.size.width || height != image.size.height) {
|
||||
// Create the thumbnail
|
||||
CGSize imageSize = CGSizeMake(width, height);
|
||||
UIGraphicsBeginImageContext(imageSize);
|
||||
|
||||
CGRect thumbnailRect = CGRectMake(0, 0, 0, 0);
|
||||
thumbnailRect.origin = CGPointMake(0.0,0.0);
|
||||
thumbnailRect.size.width = imageSize.width;
|
||||
thumbnailRect.size.height = imageSize.height;
|
||||
|
||||
[image drawInRect:thumbnailRect];
|
||||
resizedImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
}
|
||||
}
|
||||
|
||||
return resizedImage;
|
||||
}
|
||||
|
||||
// Load a picture from the local cache or download it if it is not available yet.
|
||||
// In this second case a mediaLoader reference is returned in order to let the user cancel this action.
|
||||
+ (id)loadPicture:(NSString*)pictureURL
|
||||
success:(blockMediaManager_onImageReady)success
|
||||
failure:(blockMediaManager_onError)failure {
|
||||
id ret = nil;
|
||||
// Check cached pictures
|
||||
UIImage *image = [MediaManager loadCachePicture:pictureURL];
|
||||
if (image) {
|
||||
if (success) {
|
||||
// Reply synchronously
|
||||
success (image);
|
||||
}
|
||||
}
|
||||
else if ([pictureURL hasPrefix:kMediaManagerPrefixForDummyURL] == NO) {
|
||||
// Create a media loader to download picture
|
||||
MediaLoader *mediaLoader = [[MediaLoader alloc] init];
|
||||
[mediaLoader downloadPicture:pictureURL success:success failure:failure];
|
||||
ret = mediaLoader;
|
||||
} else {
|
||||
NSLog(@"Load tmp picture from cache failed: %@", pictureURL);
|
||||
if (failure){
|
||||
failure(nil);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ (id)prepareMedia:(NSString *)mediaURL
|
||||
mimeType:(NSString *)mimeType
|
||||
success:(blockMediaManager_onMediaReady)success
|
||||
failure:(blockMediaManager_onError)failure {
|
||||
id ret = nil;
|
||||
// Check cache
|
||||
NSString* filename = [MediaManager getCacheFileNameFor:mediaURL mimeType:mimeType];
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:filename]) {
|
||||
if (success) {
|
||||
// Reply synchronously
|
||||
success (filename);
|
||||
}
|
||||
}
|
||||
else if ([mediaURL hasPrefix:kMediaManagerPrefixForDummyURL] == NO) {
|
||||
// Create a media loader to download media content
|
||||
MediaLoader *mediaLoader = [[MediaLoader alloc] init];
|
||||
[mediaLoader downloadMedia:mediaURL mimeType:mimeType success:success failure:failure];
|
||||
ret = mediaLoader;
|
||||
} else {
|
||||
NSLog(@"Load tmp media from cache failed: %@", mediaURL);
|
||||
if (failure){
|
||||
failure(nil);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ (void)cancel:(id)mediaLoader {
|
||||
[((MediaLoader*)mediaLoader) cancel];
|
||||
}
|
||||
|
||||
+ (NSString*)cacheMediaData:(NSData*)mediaData forURL:(NSString *)mediaURL mimeType:(NSString *)mimeType {
|
||||
NSString* filename = [MediaManager getCacheFileNameFor:mediaURL mimeType:mimeType];
|
||||
|
||||
if ([mediaData writeToFile:filename atomically:YES]) {
|
||||
return filename;
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)clearCache {
|
||||
NSError *error = nil;
|
||||
|
||||
if (!mediaCachePath) {
|
||||
// compute the path
|
||||
mediaCachePath = [MediaManager getCachePath];
|
||||
}
|
||||
|
||||
if (mediaCachePath) {
|
||||
if (![[NSFileManager defaultManager] removeItemAtPath:mediaCachePath error:&error]) {
|
||||
NSLog(@"Fails to delete media cache dir : %@", error);
|
||||
} else {
|
||||
NSLog(@"Media cache : deleted !");
|
||||
}
|
||||
} else {
|
||||
NSLog(@"Media cache does not exist");
|
||||
}
|
||||
|
||||
mediaCachePath = nil;
|
||||
}
|
||||
|
||||
#pragma mark - Cache handling
|
||||
|
||||
+ (UIImage*)loadCachePicture:(NSString*)pictureURL {
|
||||
UIImage* res = nil;
|
||||
NSString* filename = [MediaManager getCacheFileNameFor:pictureURL mimeType:@"image/jpeg"];
|
||||
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:filename]) {
|
||||
NSData* imageContent = [NSData dataWithContentsOfFile:filename options:(NSDataReadingMappedAlways | NSDataReadingUncached) error:nil];
|
||||
if (imageContent) {
|
||||
res = [[UIImage alloc] initWithData:imageContent];
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
+ (NSString*)getCachePath {
|
||||
NSString *cachePath = nil;
|
||||
|
||||
if (!mediaCachePath) {
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
NSString *cacheRoot = [paths objectAtIndex:0];
|
||||
|
||||
mediaCachePath = [cacheRoot stringByAppendingPathComponent:mediaDir];
|
||||
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:mediaCachePath]) {
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:mediaCachePath withIntermediateDirectories:NO attributes:nil error:nil];
|
||||
}
|
||||
}
|
||||
cachePath = mediaCachePath;
|
||||
|
||||
return cachePath;
|
||||
}
|
||||
|
||||
+ (NSString*)getCacheFileNameFor:(NSString*)mediaURL mimeType:(NSString *)mimeType {
|
||||
NSString *fileName;
|
||||
if ([mimeType isEqualToString:@"image/jpeg"]) {
|
||||
fileName = [NSString stringWithFormat:@"ima%lu.jpg", (unsigned long)mediaURL.hash];
|
||||
} else if ([mimeType isEqualToString:@"video/mp4"]) {
|
||||
fileName = [NSString stringWithFormat:@"video%lu.mp4", (unsigned long)mediaURL.hash];
|
||||
} else if ([mimeType isEqualToString:@"video/quicktime"]) {
|
||||
fileName = [NSString stringWithFormat:@"video%lu.mov", (unsigned long)mediaURL.hash];
|
||||
} else {
|
||||
NSString *extension = @"";
|
||||
NSArray *components = [mediaURL componentsSeparatedByString:@"."];
|
||||
if (components && components.count > 1) {
|
||||
extension = [components lastObject];
|
||||
}
|
||||
fileName = [NSString stringWithFormat:@"%lu.%@", (unsigned long)mediaURL.hash, extension];
|
||||
}
|
||||
|
||||
return [[MediaManager getCachePath] stringByAppendingPathComponent:fileName];
|
||||
}
|
||||
|
||||
@end
|
27
matrixConsole/View/CustomImageView.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 <UIKit/UIKit.h>
|
||||
|
||||
// Customize UIImageView in order to let UIImageView handle automatically remote url
|
||||
@interface CustomImageView : UIImageView
|
||||
|
||||
@property (strong, nonatomic) NSString *placeholder;
|
||||
@property (strong, nonatomic) NSString *imageURL;
|
||||
// Information about the media represented by this image (image, video...)
|
||||
@property (strong, nonatomic) NSDictionary *mediaInfo;
|
||||
@end
|
||||
|
82
matrixConsole/View/CustomImageView.m
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 "CustomImageView.h"
|
||||
#import "MediaManager.h"
|
||||
|
||||
@interface CustomImageView () {
|
||||
id imageLoader;
|
||||
UIActivityIndicatorView *loadingWheel;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation CustomImageView
|
||||
|
||||
- (void)setImageURL:(NSString *)imageURL {
|
||||
// Cancel media loader in progress (if any)
|
||||
if (imageLoader) {
|
||||
[MediaManager cancel:imageLoader];
|
||||
imageLoader = nil;
|
||||
}
|
||||
|
||||
_imageURL = imageURL;
|
||||
|
||||
// Reset image view
|
||||
self.image = nil;
|
||||
if (_placeholder) {
|
||||
// Set picture placeholder
|
||||
self.image = [UIImage imageNamed:_placeholder];
|
||||
}
|
||||
// Consider provided url to update image view
|
||||
if (imageURL) {
|
||||
// Start loading animation
|
||||
if (loadingWheel == nil) {
|
||||
loadingWheel = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
|
||||
CGPoint center = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
|
||||
loadingWheel.center = center;
|
||||
[self addSubview:loadingWheel];
|
||||
}
|
||||
if ([self.backgroundColor isEqual:[UIColor blackColor]]) {
|
||||
loadingWheel.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhite;
|
||||
} else {
|
||||
loadingWheel.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
|
||||
}
|
||||
[loadingWheel startAnimating];
|
||||
// Load picture
|
||||
imageLoader = [MediaManager loadPicture:imageURL
|
||||
success:^(UIImage *image) {
|
||||
[loadingWheel stopAnimating];
|
||||
self.image = image;
|
||||
}
|
||||
failure:^(NSError *error) {
|
||||
[loadingWheel stopAnimating];
|
||||
NSLog(@"Failed to download image (%@): %@", imageURL, error);
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
if (imageLoader) {
|
||||
[MediaManager cancel:imageLoader];
|
||||
imageLoader = nil;
|
||||
}
|
||||
if (loadingWheel) {
|
||||
[loadingWheel removeFromSuperview];
|
||||
loadingWheel = nil;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
25
matrixConsole/View/RecentsTableViewCell.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 <UIKit/UIKit.h>
|
||||
|
||||
@interface RecentsTableViewCell : UITableViewCell
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UILabel *roomTitle;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *lastEventDescription;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *recentDate;
|
||||
|
||||
@end
|
20
matrixConsole/View/RecentsTableViewCell.m
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 "RecentsTableViewCell.h"
|
||||
|
||||
@implementation RecentsTableViewCell
|
||||
@end
|
32
matrixConsole/View/RoomMemberTableCell.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 <UIKit/UIKit.h>
|
||||
#import "CustomImageView.h"
|
||||
|
||||
@class MXRoomMember;
|
||||
@class MXRoom;
|
||||
|
||||
// Room Member Table View Cell
|
||||
@interface RoomMemberTableCell : UITableViewCell
|
||||
@property (strong, nonatomic) IBOutlet CustomImageView *pictureView;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *userLabel;
|
||||
@property (weak, nonatomic) IBOutlet UIProgressView *userPowerLevel;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *lastActiveAgoLabel;
|
||||
|
||||
- (void)setRoomMember:(MXRoomMember *)roomMember withRoom:(MXRoom *)room;
|
||||
@end
|
||||
|
148
matrixConsole/View/RoomMemberTableCell.m
Normal file
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 "RoomMemberTableCell.h"
|
||||
#import "MatrixHandler.h"
|
||||
|
||||
@implementation RoomMemberTableCell
|
||||
|
||||
- (void)setRoomMember:(MXRoomMember *)roomMember withRoom:(MXRoom *)room {
|
||||
if (room && roomMember) {
|
||||
self.userLabel.text = [room.state memberName:roomMember.userId];
|
||||
self.pictureView.placeholder = @"default-profile";
|
||||
self.pictureView.imageURL = roomMember.avatarUrl;
|
||||
// Round image view
|
||||
[self.pictureView.layer setCornerRadius:self.pictureView.frame.size.width / 2];
|
||||
self.pictureView.clipsToBounds = YES;
|
||||
|
||||
// Shade invited users
|
||||
if (roomMember.membership == MXMembershipInvite) {
|
||||
for (UIView *view in self.subviews) {
|
||||
view.alpha = 0.3;
|
||||
}
|
||||
} else {
|
||||
for (UIView *view in self.subviews) {
|
||||
view.alpha = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Customize banned and left (kicked) members
|
||||
if (roomMember.membership == MXMembershipLeave || roomMember.membership == MXMembershipBan) {
|
||||
self.backgroundColor = [UIColor colorWithRed:0.8 green:0.8 blue:0.8 alpha:1.0];
|
||||
|
||||
self.userPowerLevel.hidden = YES;
|
||||
|
||||
self.lastActiveAgoLabel.backgroundColor = [UIColor lightGrayColor];
|
||||
self.lastActiveAgoLabel.text = (roomMember.membership == MXMembershipLeave) ? @"left" : @"banned";
|
||||
} else {
|
||||
self.backgroundColor = [UIColor whiteColor];
|
||||
|
||||
// Handle power level display
|
||||
self.userPowerLevel.hidden = NO;
|
||||
NSDictionary *powerLevels;
|
||||
if (room.state.powerLevels[@"users"]){
|
||||
// In Matrix 0.5, users power levels are listed under the `users` dictionnary
|
||||
powerLevels = room.state.powerLevels[@"users"];
|
||||
}
|
||||
else {
|
||||
// @TODO: Remove this backward compatibility
|
||||
powerLevels = room.state.powerLevels;
|
||||
}
|
||||
|
||||
if (powerLevels) {
|
||||
int maxLevel = 0;
|
||||
for (NSString *powerLevel in powerLevels.allValues) {
|
||||
int level = [powerLevel intValue];
|
||||
if (level > maxLevel) {
|
||||
maxLevel = level;
|
||||
}
|
||||
}
|
||||
NSString *userPowerLevel = [powerLevels objectForKey:roomMember.userId]; // CAUTION: we invoke objectForKey here because user_id starts with an '@' character
|
||||
if (userPowerLevel == nil) {
|
||||
userPowerLevel = [powerLevels valueForKey:@"default"];
|
||||
}
|
||||
float userPowerLevelFloat = 0.0;
|
||||
if (userPowerLevel) {
|
||||
userPowerLevelFloat = [userPowerLevel floatValue];
|
||||
}
|
||||
self.userPowerLevel.progress = maxLevel ? userPowerLevelFloat / maxLevel : 1;
|
||||
} else {
|
||||
self.userPowerLevel.progress = 0;
|
||||
}
|
||||
|
||||
if (roomMember.membership == MXMembershipInvite) {
|
||||
self.lastActiveAgoLabel.backgroundColor = [UIColor lightGrayColor];
|
||||
self.lastActiveAgoLabel.text = @"invited";
|
||||
} else {
|
||||
// Get the user that corresponds to this member
|
||||
MatrixHandler *mxHandler = [MatrixHandler sharedHandler];
|
||||
MXUser *user = [mxHandler.mxSession user:roomMember.userId];
|
||||
|
||||
// Prepare last active ago string
|
||||
NSUInteger lastActiveAgoInSec = user.lastActiveAgo / 1000;
|
||||
NSString *lastActive;
|
||||
if (lastActiveAgoInSec < 60) {
|
||||
lastActive = [NSString stringWithFormat:@"%ds ago", lastActiveAgoInSec];
|
||||
} else if (lastActiveAgoInSec < 3600) {
|
||||
lastActive = [NSString stringWithFormat:@"%dm ago", (lastActiveAgoInSec / 60)];
|
||||
} else if (lastActiveAgoInSec < 86400) {
|
||||
lastActive = [NSString stringWithFormat:@"%dh ago", (lastActiveAgoInSec / 3600)];
|
||||
} else {
|
||||
lastActive = [NSString stringWithFormat:@"%dd ago", (lastActiveAgoInSec / 86400)];
|
||||
}
|
||||
|
||||
// Check presence
|
||||
switch (user.presence) {
|
||||
case MXPresenceUnknown: {
|
||||
self.lastActiveAgoLabel.backgroundColor = [UIColor clearColor];
|
||||
self.lastActiveAgoLabel.text = nil;//@"unknown";
|
||||
break;
|
||||
}
|
||||
case MXPresenceOnline: {
|
||||
self.lastActiveAgoLabel.backgroundColor = [UIColor colorWithRed:0.2 green:0.9 blue:0.2 alpha:1.0];
|
||||
self.lastActiveAgoLabel.text = lastActive;
|
||||
self.lastActiveAgoLabel.numberOfLines = 0;
|
||||
break;
|
||||
}
|
||||
case MXPresenceUnavailable: {
|
||||
self.lastActiveAgoLabel.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.0 alpha:1.0];
|
||||
self.lastActiveAgoLabel.text = lastActive;
|
||||
self.lastActiveAgoLabel.numberOfLines = 0;
|
||||
break;
|
||||
}
|
||||
case MXPresenceOffline: {
|
||||
self.lastActiveAgoLabel.backgroundColor = [UIColor colorWithRed:0.9 green:0.2 blue:0.2 alpha:1.0];
|
||||
self.lastActiveAgoLabel.text = @"offline";
|
||||
break;
|
||||
}
|
||||
case MXPresenceFreeForChat: {
|
||||
self.lastActiveAgoLabel.backgroundColor = [UIColor clearColor];
|
||||
self.lastActiveAgoLabel.text = nil;//@"free for chat";
|
||||
break;
|
||||
}
|
||||
case MXPresenceHidden: {
|
||||
self.lastActiveAgoLabel.backgroundColor = [UIColor clearColor];
|
||||
self.lastActiveAgoLabel.text = nil;//@"hidden";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@end
|
44
matrixConsole/View/RoomMessageTableCell.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 <UIKit/UIKit.h>
|
||||
#import "CustomImageView.h"
|
||||
|
||||
// Room Message Table View Cell
|
||||
@interface RoomMessageTableCell : UITableViewCell
|
||||
@property (strong, nonatomic) IBOutlet CustomImageView *pictureView;
|
||||
@property (weak, nonatomic) IBOutlet UITextView *messageTextView;
|
||||
@property (strong, nonatomic) IBOutlet CustomImageView *attachmentView;
|
||||
@property (strong, nonatomic) IBOutlet UIImageView *playIconView;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *dateTimeLabel;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *msgTextViewWidthConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *msgTextViewTopConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *msgTextViewBottomConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *dateTimeLabelTopConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *attachmentViewTopAlignmentConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *attachmentViewBottomAlignmentConstraint;
|
||||
@end
|
||||
|
||||
@interface IncomingMessageTableCell : RoomMessageTableCell
|
||||
@property (weak, nonatomic) IBOutlet UILabel *userNameLabel;
|
||||
@end
|
||||
|
||||
@interface OutgoingMessageTableCell : RoomMessageTableCell
|
||||
@property (weak, nonatomic) IBOutlet UILabel *unsentLabel;
|
||||
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *unsentLabelTopConstraint;
|
||||
@end
|
||||
|
29
matrixConsole/View/RoomMessageTableCell.m
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 "RoomMessageTableCell.h"
|
||||
#import "MediaManager.h"
|
||||
|
||||
@implementation RoomMessageTableCell
|
||||
@end
|
||||
|
||||
|
||||
@implementation IncomingMessageTableCell
|
||||
@end
|
||||
|
||||
|
||||
@implementation OutgoingMessageTableCell
|
||||
@end
|
29
matrixConsole/View/SettingsTableViewCell.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 <UIKit/UIKit.h>
|
||||
|
||||
@interface SettingsTableViewCell : UITableViewCell
|
||||
@end
|
||||
|
||||
@interface SettingsTableCellWithSwitch : SettingsTableViewCell
|
||||
@property (strong, nonatomic) IBOutlet UILabel *settingLabel;
|
||||
@property (strong, nonatomic) IBOutlet UISwitch *settingSwitch;
|
||||
@end
|
||||
|
||||
@interface SettingsTableCellWithTextView : SettingsTableViewCell
|
||||
@property (strong, nonatomic) IBOutlet UITextView *settingTextView;
|
||||
@end
|
26
matrixConsole/View/SettingsTableViewCell.m
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 "SettingsTableViewCell.h"
|
||||
|
||||
@implementation SettingsTableViewCell
|
||||
@end
|
||||
|
||||
@implementation SettingsTableCellWithSwitch
|
||||
@end
|
||||
|
||||
@implementation SettingsTableCellWithTextView
|
||||
@end
|
22
matrixConsole/ViewController/HomeViewController.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 <UIKit/UIKit.h>
|
||||
|
||||
@interface HomeViewController : UITableViewController <UITextFieldDelegate>
|
||||
|
||||
@end
|
||||
|
386
matrixConsole/ViewController/HomeViewController.m
Normal file
|
@ -0,0 +1,386 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 "HomeViewController.h"
|
||||
|
||||
#import "MatrixHandler.h"
|
||||
#import "AppDelegate.h"
|
||||
|
||||
|
||||
|
||||
@interface HomeViewController () {
|
||||
NSArray *publicRooms;
|
||||
// List of public room names to highlight in displayed list
|
||||
NSArray* highlightedPublicRooms;
|
||||
}
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UITableView *publicRoomsTable;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *roomCreationLabel;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *roomNameLabel;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *roomAliasLabel;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *participantsLabel;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *roomNameTextField;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *roomAliasTextField;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *participantsTextField;
|
||||
@property (weak, nonatomic) IBOutlet UISegmentedControl *roomVisibilityControl;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *createRoomBtn;
|
||||
- (IBAction)onButtonPressed:(id)sender;
|
||||
|
||||
@end
|
||||
|
||||
@implementation HomeViewController
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
|
||||
// Do any additional setup after loading the view, typically from a nib.
|
||||
_roomCreationLabel.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1.0];
|
||||
_createRoomBtn.enabled = NO;
|
||||
_createRoomBtn.alpha = 0.5;
|
||||
|
||||
// Init
|
||||
publicRooms = nil;
|
||||
highlightedPublicRooms = @[@"#matrix:matrix.org"]; // Add here a room name to highlight its display in public room list
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
- (void)dealloc{
|
||||
publicRooms = nil;
|
||||
highlightedPublicRooms = nil;
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Ensure to display room creation section
|
||||
[self.tableView scrollRectToVisible:_roomCreationLabel.frame animated:NO];
|
||||
|
||||
if ([[MatrixHandler sharedHandler] isLogged]) {
|
||||
// Update alias placeholder
|
||||
_roomAliasTextField.placeholder = [NSString stringWithFormat:@"(e.g. #foo:%@)", [MatrixHandler sharedHandler].homeServer];
|
||||
// Refresh listed public rooms
|
||||
[self refreshPublicRooms];
|
||||
}
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onTextFieldChange:) name:UITextFieldTextDidChangeNotification object:nil];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
[super viewWillDisappear:animated];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidChangeNotification object:nil];
|
||||
}
|
||||
|
||||
#pragma mark - Internals
|
||||
|
||||
- (void)refreshPublicRooms {
|
||||
// Retrieve public rooms
|
||||
[[MatrixHandler sharedHandler].mxRestClient publicRooms:^(NSArray *rooms){
|
||||
publicRooms = [rooms sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
|
||||
|
||||
MXPublicRoom *firstRoom = (MXPublicRoom*)a;
|
||||
MXPublicRoom *secondRoom = (MXPublicRoom*)b;
|
||||
|
||||
return [firstRoom.displayname compare:secondRoom.displayname options:NSCaseInsensitiveSearch];
|
||||
}];
|
||||
[_publicRoomsTable reloadData];
|
||||
}
|
||||
failure:^(NSError *error){
|
||||
NSLog(@"GET public rooms failed: %@", error);
|
||||
//Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
}];
|
||||
|
||||
}
|
||||
|
||||
- (void)dismissKeyboard {
|
||||
// Hide the keyboard
|
||||
[_roomNameTextField resignFirstResponder];
|
||||
[_roomAliasTextField resignFirstResponder];
|
||||
[_participantsTextField resignFirstResponder];
|
||||
}
|
||||
|
||||
- (NSString*)alias {
|
||||
// Extract alias name from alias text field
|
||||
NSString *alias = _roomAliasTextField.text;
|
||||
if (alias.length > 1) {
|
||||
// Remove '#' character
|
||||
alias = [alias substringFromIndex:1];
|
||||
// Remove homeserver
|
||||
NSString *suffix = [NSString stringWithFormat:@":%@",[MatrixHandler sharedHandler].homeServer];
|
||||
NSRange range = [alias rangeOfString:suffix];
|
||||
alias = [alias stringByReplacingCharactersInRange:range withString:@""];
|
||||
}
|
||||
|
||||
if (! alias.length) {
|
||||
alias = nil;
|
||||
}
|
||||
|
||||
return alias;
|
||||
}
|
||||
|
||||
- (NSArray*)participantsList {
|
||||
NSMutableArray *participants = [NSMutableArray array];
|
||||
|
||||
if (_participantsTextField.text.length) {
|
||||
NSArray *components = [_participantsTextField.text componentsSeparatedByString:@";"];
|
||||
|
||||
for (NSString *component in components) {
|
||||
// Remove white space from both ends
|
||||
NSString *user = [component stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
if (user.length > 1 && [user hasPrefix:@"@"]) {
|
||||
[participants addObject:user];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (participants.count == 0) {
|
||||
participants = nil;
|
||||
}
|
||||
|
||||
return participants;
|
||||
}
|
||||
|
||||
#pragma mark - UITextField delegate
|
||||
|
||||
- (void)onTextFieldChange:(NSNotification *)notif {
|
||||
NSString *roomName = _roomNameTextField.text;
|
||||
NSString *roomAlias = _roomAliasTextField.text;
|
||||
NSString *participants = _participantsTextField.text;
|
||||
|
||||
if (roomName.length || roomAlias.length || participants.length) {
|
||||
_createRoomBtn.enabled = YES;
|
||||
_createRoomBtn.alpha = 1;
|
||||
} else {
|
||||
_createRoomBtn.enabled = NO;
|
||||
_createRoomBtn.alpha = 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)textFieldDidBeginEditing:(UITextField *)textField {
|
||||
if (textField == _roomAliasTextField) {
|
||||
textField.text = self.alias;
|
||||
textField.placeholder = @"foo";
|
||||
} else if (textField == _participantsTextField) {
|
||||
if (textField.text.length == 0) {
|
||||
textField.text = @"@";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)textFieldDidEndEditing:(UITextField *)textField {
|
||||
if (textField == _roomAliasTextField) {
|
||||
// Compute the new phone number with this string change
|
||||
NSString * alias = textField.text;
|
||||
if (alias.length) {
|
||||
// add homeserver as suffix
|
||||
textField.text = [NSString stringWithFormat:@"#%@:%@", alias, [MatrixHandler sharedHandler].homeServer];
|
||||
}
|
||||
|
||||
textField.placeholder = [NSString stringWithFormat:@"(e.g. #foo:%@)", [MatrixHandler sharedHandler].homeServer];
|
||||
} else if (textField == _participantsTextField) {
|
||||
NSArray *participants = self.participantsList;
|
||||
textField.text = [participants componentsJoinedByString:@"; "];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
|
||||
// Auto complete participant IDs
|
||||
if (textField == _participantsTextField) {
|
||||
// Auto completion is active only when the change concerns the end of the current string
|
||||
if (range.location == textField.text.length) {
|
||||
NSString *participants = [textField.text stringByReplacingCharactersInRange:range withString:string];
|
||||
|
||||
if ([string isEqualToString:@";"]) {
|
||||
// Add '@' character
|
||||
participants = [participants stringByAppendingString:@" @"];
|
||||
} else if ([string isEqualToString:@":"]) {
|
||||
// Add homeserver
|
||||
participants = [participants stringByAppendingString:[MatrixHandler sharedHandler].homeServer];
|
||||
}
|
||||
|
||||
textField.text = participants;
|
||||
|
||||
// Update Create button status
|
||||
[self onTextFieldChange:nil];
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)textFieldShouldReturn:(UITextField*) textField {
|
||||
// "Done" key has been pressed
|
||||
[textField resignFirstResponder];
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (IBAction)onButtonPressed:(id)sender {
|
||||
[self dismissKeyboard];
|
||||
|
||||
if (sender == _createRoomBtn) {
|
||||
// Disable button to prevent multiple request
|
||||
_createRoomBtn.enabled = NO;
|
||||
|
||||
NSString *roomName = _roomNameTextField.text;
|
||||
if (! roomName.length) {
|
||||
roomName = nil;
|
||||
}
|
||||
|
||||
// Create new room
|
||||
MatrixHandler *mxHandler = [MatrixHandler sharedHandler];
|
||||
[mxHandler.mxRestClient createRoom:roomName
|
||||
visibility:(_roomVisibilityControl.selectedSegmentIndex == 0) ? kMXRoomVisibilityPublic : kMXRoomVisibilityPrivate
|
||||
room_alias_name:self.alias
|
||||
topic:nil
|
||||
success:^(MXCreateRoomResponse *response) {
|
||||
// Check whether some users must be invited
|
||||
NSArray *invitedUsers = self.participantsList;
|
||||
for (NSString *userId in invitedUsers) {
|
||||
[mxHandler.mxRestClient inviteUser:userId toRoom:response.roomId success:^{
|
||||
NSLog(@"%@ has been invited (roomId: %@)", userId, response.roomId);
|
||||
} failure:^(NSError *error) {
|
||||
NSLog(@"%@ invitation failed (roomId: %@): %@", userId, response.roomId, error);
|
||||
//Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
}];
|
||||
}
|
||||
|
||||
// Reset text fields
|
||||
_roomNameTextField.text = nil;
|
||||
_roomAliasTextField.text = nil;
|
||||
_participantsTextField.text = nil;
|
||||
// Open created room
|
||||
[[AppDelegate theDelegate].masterTabBarController showRoom:response.roomId];
|
||||
} failure:^(NSError *error) {
|
||||
_createRoomBtn.enabled = YES;
|
||||
NSLog(@"Create room (%@ %@ (%@)) failed: %@", _roomNameTextField.text, self.alias, (_roomVisibilityControl.selectedSegmentIndex == 0) ? @"Public":@"Private", error);
|
||||
//Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Table view data source
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
return 1;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
return publicRooms.count;
|
||||
}
|
||||
|
||||
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
|
||||
UILabel *sectionHeader = [[UILabel alloc] initWithFrame:[tableView rectForHeaderInSection:section]];
|
||||
sectionHeader.font = [UIFont boldSystemFontOfSize:16];
|
||||
sectionHeader.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1.0];
|
||||
|
||||
if (publicRooms) {
|
||||
NSString *homeserver = [MatrixHandler sharedHandler].homeServerURL;
|
||||
if (homeserver.length) {
|
||||
sectionHeader.text = [NSString stringWithFormat:@" Public Rooms (at %@):", homeserver];
|
||||
} else {
|
||||
sectionHeader.text = @" Public Rooms:";
|
||||
}
|
||||
} else {
|
||||
sectionHeader.text = @" No Public Rooms";
|
||||
}
|
||||
|
||||
return sectionHeader;
|
||||
}
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
// Cell is larger for public room with topic
|
||||
MXPublicRoom *publicRoom = [publicRooms objectAtIndex:indexPath.row];
|
||||
if (publicRoom.topic) {
|
||||
return 60;
|
||||
}
|
||||
return 44;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
MXPublicRoom *publicRoom = [publicRooms objectAtIndex:indexPath.row];
|
||||
UITableViewCell *cell;
|
||||
|
||||
// Check whether this public room has topic
|
||||
if (publicRoom.topic) {
|
||||
cell = [_publicRoomsTable dequeueReusableCellWithIdentifier:@"PublicRoomCellSubtitle" forIndexPath:indexPath];
|
||||
cell.detailTextLabel.text = publicRoom.topic;
|
||||
} else {
|
||||
cell = [_publicRoomsTable dequeueReusableCellWithIdentifier:@"PublicRoomCellBasic" forIndexPath:indexPath];
|
||||
}
|
||||
|
||||
// Set room display name
|
||||
cell.textLabel.text = [publicRoom displayname];
|
||||
|
||||
// Highlight?
|
||||
if (cell.textLabel.text && [highlightedPublicRooms indexOfObject:cell.textLabel.text] != NSNotFound) {
|
||||
cell.textLabel.font = [UIFont boldSystemFontOfSize:20];
|
||||
cell.detailTextLabel.font = [UIFont boldSystemFontOfSize:17];
|
||||
} else {
|
||||
cell.textLabel.font = [UIFont systemFontOfSize:19];
|
||||
cell.detailTextLabel.font = [UIFont systemFontOfSize:16];
|
||||
}
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
#pragma mark - Table view delegate
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
MatrixHandler *mxHandler = [MatrixHandler sharedHandler];
|
||||
|
||||
// Check whether the user has already joined the selected public room
|
||||
MXPublicRoom *publicRoom = [publicRooms objectAtIndex:indexPath.row];
|
||||
if ([mxHandler.mxSession room:publicRoom.roomId]) {
|
||||
// Open selected room
|
||||
[[AppDelegate theDelegate].masterTabBarController showRoom:publicRoom.roomId];
|
||||
} else {
|
||||
// Join the selected room
|
||||
UIActivityIndicatorView *loadingWheel = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
|
||||
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
|
||||
if (selectedCell) {
|
||||
CGPoint center = CGPointMake(selectedCell.frame.size.width / 2, selectedCell.frame.size.height / 2);
|
||||
loadingWheel.center = center;
|
||||
[selectedCell addSubview:loadingWheel];
|
||||
}
|
||||
[loadingWheel startAnimating];
|
||||
[mxHandler.mxSession joinRoom:publicRoom.roomId success:^(MXRoom *room) {
|
||||
// Show joined room
|
||||
[loadingWheel stopAnimating];
|
||||
[loadingWheel removeFromSuperview];
|
||||
[[AppDelegate theDelegate].masterTabBarController showRoom:publicRoom.roomId];
|
||||
} failure:^(NSError *error) {
|
||||
NSLog(@"Failed to join public room (%@) failed: %@", publicRoom.displayname, error);
|
||||
//Alert user
|
||||
[loadingWheel stopAnimating];
|
||||
[loadingWheel removeFromSuperview];
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
}];
|
||||
}
|
||||
|
||||
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
||||
}
|
||||
|
||||
@end
|
22
matrixConsole/ViewController/LoginViewController.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 <UIKit/UIKit.h>
|
||||
|
||||
@interface LoginViewController : UIViewController <UITextFieldDelegate>
|
||||
|
||||
@end
|
||||
|
226
matrixConsole/ViewController/LoginViewController.m
Normal file
|
@ -0,0 +1,226 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 "LoginViewController.h"
|
||||
|
||||
#import "MatrixHandler.h"
|
||||
#import "AppDelegate.h"
|
||||
#import "CustomAlert.h"
|
||||
|
||||
NSString* const defaultHomeserver = @"http://matrix.org";
|
||||
|
||||
@interface LoginViewController ()
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *contentViewBottomConstraint;
|
||||
|
||||
@property (strong, nonatomic) IBOutlet UIScrollView *scrollView;
|
||||
@property (weak, nonatomic) IBOutlet UIView *contentView;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UITextField *homeServerTextField;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *userLoginTextField;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *passWordTextField;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIButton *loginBtn;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *createAccountBtn;
|
||||
|
||||
@property (strong, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;
|
||||
|
||||
@end
|
||||
|
||||
@implementation LoginViewController
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
// Do any additional setup after loading the view, typically from a nib.
|
||||
|
||||
// Finalize scrollView content size
|
||||
_contentViewBottomConstraint.constant = 0;
|
||||
|
||||
// Force contentView in full width
|
||||
NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:self.contentView
|
||||
attribute:NSLayoutAttributeLeading
|
||||
relatedBy:0
|
||||
toItem:self.view
|
||||
attribute:NSLayoutAttributeLeft
|
||||
multiplier:1.0
|
||||
constant:0];
|
||||
[self.view addConstraint:leftConstraint];
|
||||
|
||||
NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:self.contentView
|
||||
attribute:NSLayoutAttributeTrailing
|
||||
relatedBy:0
|
||||
toItem:self.view
|
||||
attribute:NSLayoutAttributeRight
|
||||
multiplier:1.0
|
||||
constant:0];
|
||||
[self.view addConstraint:rightConstraint];
|
||||
|
||||
// Prefill text field
|
||||
_userLoginTextField.text = [[MatrixHandler sharedHandler] userLogin];
|
||||
_homeServerTextField.text = [[MatrixHandler sharedHandler] homeServerURL];
|
||||
if (! _homeServerTextField.text.length) {
|
||||
[[MatrixHandler sharedHandler] setHomeServerURL:defaultHomeserver];
|
||||
self.homeServerTextField.text = defaultHomeserver;
|
||||
}
|
||||
_passWordTextField.text = nil;
|
||||
_loginBtn.enabled = NO;
|
||||
_loginBtn.alpha = 0.5;
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onKeyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onKeyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
|
||||
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onTextFieldChange:) name:UITextFieldTextDidChangeNotification object:nil];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
[super viewWillDisappear:animated];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:UITextFieldTextDidChangeNotification object:nil];
|
||||
}
|
||||
|
||||
- (void)onKeyboardWillShow:(NSNotification *)notif {
|
||||
NSValue *rectVal = notif.userInfo[UIKeyboardFrameEndUserInfoKey];
|
||||
CGRect endRect = rectVal.CGRectValue;
|
||||
|
||||
UIEdgeInsets insets = self.scrollView.contentInset;
|
||||
// Handle portrait/landscape mode
|
||||
insets.bottom = (endRect.origin.y == 0) ? endRect.size.width : endRect.size.height;
|
||||
self.scrollView.contentInset = insets;
|
||||
|
||||
for (UITextField *tf in @[ self.userLoginTextField, self.passWordTextField, self.homeServerTextField]) {
|
||||
if ([tf isFirstResponder]) {
|
||||
CGRect tfFrame = tf.frame;
|
||||
[self.scrollView scrollRectToVisible:tfFrame animated:YES];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)onKeyboardWillHide:(NSNotification *)notif {
|
||||
UIEdgeInsets insets = self.scrollView.contentInset;
|
||||
insets.bottom = 0;
|
||||
self.scrollView.contentInset = insets;
|
||||
}
|
||||
|
||||
- (void)dismissKeyboard
|
||||
{
|
||||
// Hide the keyboard
|
||||
[_userLoginTextField resignFirstResponder];
|
||||
[_passWordTextField resignFirstResponder];
|
||||
[_homeServerTextField resignFirstResponder];
|
||||
}
|
||||
|
||||
#pragma mark - UITextField delegate
|
||||
|
||||
- (void)onTextFieldChange:(NSNotification *)notif {
|
||||
NSString *user = _userLoginTextField.text;
|
||||
NSString *pass = _passWordTextField.text;
|
||||
NSString *homeServerURL = _homeServerTextField.text;
|
||||
|
||||
if (user.length && pass.length && homeServerURL.length) {
|
||||
_loginBtn.enabled = YES;
|
||||
_loginBtn.alpha = 1;
|
||||
} else {
|
||||
_loginBtn.enabled = NO;
|
||||
_loginBtn.alpha = 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)textFieldDidEndEditing:(UITextField *)textField
|
||||
{
|
||||
MatrixHandler *matrix = [MatrixHandler sharedHandler];
|
||||
|
||||
if (textField == _userLoginTextField) {
|
||||
[matrix setUserLogin:textField.text];
|
||||
}
|
||||
else if (textField == _homeServerTextField) {
|
||||
[matrix setHomeServerURL:textField.text];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)textFieldShouldReturn:(UITextField*) textField
|
||||
{
|
||||
if (textField == _userLoginTextField) {
|
||||
// "Next" key has been pressed
|
||||
[_passWordTextField becomeFirstResponder];
|
||||
}
|
||||
else {
|
||||
// "Done" key has been pressed
|
||||
[textField resignFirstResponder];
|
||||
|
||||
if (_loginBtn.isEnabled)
|
||||
{
|
||||
// Launch authentication now
|
||||
[self onButtonPressed:_loginBtn];
|
||||
}
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (IBAction)onButtonPressed:(id)sender
|
||||
{
|
||||
[self dismissKeyboard];
|
||||
|
||||
if (sender == _loginBtn) {
|
||||
MatrixHandler *matrix = [MatrixHandler sharedHandler];
|
||||
|
||||
if (matrix.mxRestClient)
|
||||
{
|
||||
// Disable login button to prevent multiple requests
|
||||
_loginBtn.enabled = NO;
|
||||
[_activityIndicator startAnimating];
|
||||
|
||||
[matrix.mxRestClient loginWithUser:matrix.userLogin andPassword:_passWordTextField.text
|
||||
success:^(MXCredentials *credentials){
|
||||
[_activityIndicator stopAnimating];
|
||||
|
||||
// Report credentials
|
||||
[matrix setUserId:credentials.userId];
|
||||
[matrix setAccessToken:credentials.accessToken];
|
||||
[matrix setHomeServer:credentials.homeServer];
|
||||
|
||||
[self dismissViewControllerAnimated:YES completion:nil];
|
||||
}
|
||||
failure:^(NSError *error){
|
||||
[_activityIndicator stopAnimating];
|
||||
_loginBtn.enabled = YES;
|
||||
|
||||
NSLog(@"Login failed: %@", error);
|
||||
//Alert user
|
||||
CustomAlert *alert = [[CustomAlert alloc] initWithTitle:@"Login Failed" message:@"Invalid username/password" style:CustomAlertStyleAlert];
|
||||
[alert addActionWithTitle:@"Dismiss" style:CustomAlertActionStyleCancel handler:^(CustomAlert *alert) {}];
|
||||
[alert showInViewController:self];
|
||||
}];
|
||||
}
|
||||
} else if (sender == _createAccountBtn){
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
36
matrixConsole/ViewController/MasterTabBarController.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 <UIKit/UIKit.h>
|
||||
|
||||
#define TABBAR_HOME_INDEX 0
|
||||
#define TABBAR_RECENTS_INDEX 1
|
||||
#define TABBAR_SETTINGS_INDEX 2
|
||||
#define TABBAR_COUNT 3
|
||||
|
||||
@interface MasterTabBarController : UITabBarController
|
||||
|
||||
- (void)showLoginScreen;
|
||||
- (void)showRoomCreationForm;
|
||||
- (void)showRoom:(NSString*)roomId;
|
||||
|
||||
- (void)presentMediaPicker:(UIImagePickerController*)mediaPicker;
|
||||
- (void)dismissMediaPicker;
|
||||
|
||||
@property (strong, nonatomic) NSString *visibleRoomId; // nil if no room is presently visible
|
||||
|
||||
@end
|
||||
|
137
matrixConsole/ViewController/MasterTabBarController.m
Normal file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 "MasterTabBarController.h"
|
||||
#import "MatrixHandler.h"
|
||||
|
||||
#import "RecentsViewController.h"
|
||||
|
||||
@interface MasterTabBarController () {
|
||||
UINavigationController *recentsNavigationController;
|
||||
RecentsViewController *recentsViewController;
|
||||
|
||||
UIImagePickerController *mediaPicker;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation MasterTabBarController
|
||||
|
||||
@synthesize visibleRoomId;
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
// Do any additional setup after loading the view, typically from a nib.
|
||||
|
||||
// To simplify navigation into the app, we retrieve here the navigation controller and the view controller related
|
||||
// to the recents list in Recents Tab.
|
||||
// Note: UISplitViewController is not supported on iPhone for iOS < 8.0
|
||||
UIViewController* recents = [self.viewControllers objectAtIndex:TABBAR_RECENTS_INDEX];
|
||||
recentsNavigationController = nil;
|
||||
if ([recents isKindOfClass:[UISplitViewController class]]) {
|
||||
UISplitViewController *splitViewController = (UISplitViewController *)recents;
|
||||
recentsNavigationController = [splitViewController.viewControllers objectAtIndex:0];
|
||||
} else if ([recents isKindOfClass:[UINavigationController class]]) {
|
||||
recentsNavigationController = (UINavigationController*)recents;
|
||||
}
|
||||
|
||||
if (recentsNavigationController) {
|
||||
for (UIViewController *viewController in recentsNavigationController.viewControllers) {
|
||||
if ([viewController isKindOfClass:[RecentsViewController class]]) {
|
||||
recentsViewController = (RecentsViewController*)viewController;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated {
|
||||
[super viewDidAppear:animated];
|
||||
|
||||
if (! [[MatrixHandler sharedHandler] isLogged]) {
|
||||
[self showLoginScreen];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
recentsNavigationController = nil;
|
||||
recentsViewController = nil;
|
||||
|
||||
[self dismissMediaPicker];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)restoreInitialDisplay {
|
||||
// Dismiss potential media picker
|
||||
if (mediaPicker) {
|
||||
if (mediaPicker.delegate && [mediaPicker.delegate respondsToSelector:@selector(imagePickerControllerDidCancel:)]) {
|
||||
[mediaPicker.delegate imagePickerControllerDidCancel:mediaPicker];
|
||||
} else {
|
||||
[self dismissMediaPicker];
|
||||
}
|
||||
}
|
||||
|
||||
// Force back to recents list if room details is displayed in Recents Tab
|
||||
if (recentsViewController) {
|
||||
[recentsNavigationController popToViewController:recentsViewController animated:NO];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)showLoginScreen {
|
||||
[self restoreInitialDisplay];
|
||||
|
||||
[self performSegueWithIdentifier:@"showLogin" sender:self];
|
||||
}
|
||||
|
||||
- (void)showRoomCreationForm {
|
||||
// Switch in Home Tab
|
||||
[self setSelectedIndex:TABBAR_HOME_INDEX];
|
||||
}
|
||||
|
||||
- (void)showRoom:(NSString*)roomId {
|
||||
[self restoreInitialDisplay];
|
||||
|
||||
// Switch on Recents Tab
|
||||
[self setSelectedIndex:TABBAR_RECENTS_INDEX];
|
||||
|
||||
// Select room to display its details (dispatch this action in order to let TabBarController end its refresh)
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
recentsViewController.preSelectedRoomId = roomId;
|
||||
});
|
||||
}
|
||||
|
||||
- (void)presentMediaPicker:(UIImagePickerController*)aMediaPicker {
|
||||
[self dismissMediaPicker];
|
||||
[self presentViewController:aMediaPicker animated:YES completion:^{
|
||||
mediaPicker = aMediaPicker;
|
||||
}];
|
||||
}
|
||||
- (void)dismissMediaPicker {
|
||||
if (mediaPicker) {
|
||||
[self dismissViewControllerAnimated:NO completion:nil];
|
||||
mediaPicker.delegate = nil;
|
||||
mediaPicker = nil;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
26
matrixConsole/ViewController/RecentsViewController.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 <UIKit/UIKit.h>
|
||||
|
||||
@class RoomViewController;
|
||||
|
||||
@interface RecentsViewController : UITableViewController
|
||||
|
||||
@property (strong, nonatomic) NSString *preSelectedRoomId; // set a non-nil value to this property will open room details
|
||||
|
||||
@end
|
||||
|
311
matrixConsole/ViewController/RecentsViewController.m
Normal file
|
@ -0,0 +1,311 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 "RecentsViewController.h"
|
||||
#import "RoomViewController.h"
|
||||
|
||||
#import "RecentsTableViewCell.h"
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "MatrixHandler.h"
|
||||
|
||||
@interface RecentsViewController () {
|
||||
NSMutableArray *recents;
|
||||
id recentsListener;
|
||||
|
||||
// Date formatter
|
||||
NSDateFormatter *dateFormatter;
|
||||
|
||||
RoomViewController *currentRoomViewController;
|
||||
}
|
||||
@property (strong, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;
|
||||
|
||||
@end
|
||||
|
||||
@implementation RecentsViewController
|
||||
|
||||
- (void)awakeFromNib {
|
||||
[super awakeFromNib];
|
||||
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
|
||||
self.clearsSelectionOnViewWillAppear = NO;
|
||||
self.preferredContentSize = CGSizeMake(320.0, 600.0);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
// Do any additional setup after loading the view, typically from a nib.
|
||||
self.navigationItem.leftBarButtonItem = self.editButtonItem;
|
||||
|
||||
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(createNewRoom:)];
|
||||
self.navigationItem.rightBarButtonItem = addButton;
|
||||
|
||||
// Add activity indicator
|
||||
[self.view addSubview:_activityIndicator];
|
||||
_activityIndicator.center = CGPointMake(self.view.center.x, 100);
|
||||
[self.view bringSubviewToFront:_activityIndicator];
|
||||
|
||||
// Initialisation
|
||||
recents = nil;
|
||||
|
||||
NSString *dateFormat = @"MMM dd HH:mm";
|
||||
dateFormatter = [[NSDateFormatter alloc] init];
|
||||
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:[[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0]]];
|
||||
[dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
|
||||
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
|
||||
[dateFormatter setDateFormat:dateFormat];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
if (currentRoomViewController) {
|
||||
currentRoomViewController.roomId = nil;
|
||||
}
|
||||
if (recentsListener) {
|
||||
[[MatrixHandler sharedHandler].mxSession removeListener:recentsListener];
|
||||
recentsListener = nil;
|
||||
}
|
||||
recents = nil;
|
||||
_preSelectedRoomId = nil;
|
||||
|
||||
if (dateFormatter) {
|
||||
dateFormatter = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Refresh recents table
|
||||
[self configureView];
|
||||
[[MatrixHandler sharedHandler] addObserver:self forKeyPath:@"isInitialSyncDone" options:0 context:nil];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
[super viewWillDisappear:animated];
|
||||
|
||||
// Leave potential editing mode
|
||||
[self setEditing:NO];
|
||||
|
||||
if (recentsListener) {
|
||||
[[MatrixHandler sharedHandler].mxSession removeListener:recentsListener];
|
||||
recentsListener = nil;
|
||||
}
|
||||
|
||||
_preSelectedRoomId = nil;
|
||||
[[MatrixHandler sharedHandler] removeObserver:self forKeyPath:@"isInitialSyncDone"];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)setPreSelectedRoomId:(NSString *)roomId {
|
||||
_preSelectedRoomId = nil;
|
||||
|
||||
if (roomId) {
|
||||
// Check whether recents update is in progress
|
||||
if ([_activityIndicator isAnimating]) {
|
||||
// Postpone room details display
|
||||
_preSelectedRoomId = roomId;
|
||||
return;
|
||||
}
|
||||
|
||||
// Look for the room index in recents list
|
||||
NSIndexPath *indexPath = nil;
|
||||
for (NSUInteger index = 0; index < recents.count; index++) {
|
||||
MXEvent *mxEvent = [recents objectAtIndex:index];
|
||||
if ([roomId isEqualToString:mxEvent.roomId]) {
|
||||
indexPath = [NSIndexPath indexPathForRow:index inSection:0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (indexPath) {
|
||||
// Open details view
|
||||
[self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionMiddle];
|
||||
UITableViewCell *recentCell = [self.tableView cellForRowAtIndexPath:indexPath];
|
||||
[self performSegueWithIdentifier:@"showDetail" sender:recentCell];
|
||||
} else {
|
||||
NSLog(@"We are not able to open room (%@) because it does not appear in recents yet", roomId);
|
||||
// Postpone room details display. We run activity indicator until recents are updated
|
||||
_preSelectedRoomId = roomId;
|
||||
// Start activity indicator
|
||||
[_activityIndicator startAnimating];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Internal methods
|
||||
|
||||
- (void)configureView {
|
||||
MatrixHandler *mxHandler = [MatrixHandler sharedHandler];
|
||||
|
||||
// Remove potential listener
|
||||
if (recentsListener && mxHandler.mxSession) {
|
||||
[mxHandler.mxSession removeListener:recentsListener];
|
||||
recentsListener = nil;
|
||||
}
|
||||
|
||||
[_activityIndicator startAnimating];
|
||||
|
||||
if ([mxHandler isInitialSyncDone] || [mxHandler isLogged] == NO) {
|
||||
// Update recents
|
||||
if (mxHandler.mxSession) {
|
||||
recents = [NSMutableArray arrayWithArray:mxHandler.mxSession.recents];
|
||||
// Register recent listener
|
||||
recentsListener = [mxHandler.mxSession listenToEventsOfTypes:mxHandler.mxSession.eventsFilterForMessages onEvent:^(MXEvent *event, MXEventDirection direction, id customObject) {
|
||||
// consider only live event
|
||||
if (direction == MXEventDirectionForwards) {
|
||||
// Refresh the whole recents list
|
||||
recents = [NSMutableArray arrayWithArray:mxHandler.mxSession.recents];
|
||||
// Reload table
|
||||
[self.tableView reloadData];
|
||||
[_activityIndicator stopAnimating];
|
||||
|
||||
// Check whether a room is preselected
|
||||
if (_preSelectedRoomId) {
|
||||
self.preSelectedRoomId = _preSelectedRoomId;
|
||||
}
|
||||
}
|
||||
}];
|
||||
} else {
|
||||
recents = nil;
|
||||
}
|
||||
|
||||
// Reload table
|
||||
[self.tableView reloadData];
|
||||
[_activityIndicator stopAnimating];
|
||||
|
||||
// Check whether a room is preselected
|
||||
if (_preSelectedRoomId) {
|
||||
self.preSelectedRoomId = _preSelectedRoomId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)createNewRoom:(id)sender {
|
||||
[[AppDelegate theDelegate].masterTabBarController showRoomCreationForm];
|
||||
}
|
||||
|
||||
#pragma mark - KVO
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
|
||||
{
|
||||
if ([@"isInitialSyncDone" isEqualToString:keyPath])
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self configureView];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Segues
|
||||
|
||||
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
|
||||
if ([[segue identifier] isEqualToString:@"showDetail"]) {
|
||||
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
|
||||
MXEvent *mxEvent = recents[indexPath.row];
|
||||
|
||||
UIViewController *controller;
|
||||
if ([[segue destinationViewController] isKindOfClass:[UINavigationController class]]) {
|
||||
controller = [[segue destinationViewController] topViewController];
|
||||
} else {
|
||||
controller = [segue destinationViewController];
|
||||
}
|
||||
|
||||
if ([controller isKindOfClass:[RoomViewController class]]) {
|
||||
if (currentRoomViewController) {
|
||||
if ((currentRoomViewController != controller) || (![currentRoomViewController.roomId isEqualToString:mxEvent.roomId])) {
|
||||
// Release the current one
|
||||
currentRoomViewController.roomId = nil;
|
||||
}
|
||||
}
|
||||
currentRoomViewController = (RoomViewController *)controller;
|
||||
currentRoomViewController.roomId = mxEvent.roomId;
|
||||
}
|
||||
|
||||
controller.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem;
|
||||
controller.navigationItem.leftItemsSupplementBackButton = YES;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Table View
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
return 1;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
return recents.count;
|
||||
}
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
return 70;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
RecentsTableViewCell *cell = (RecentsTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"RecentsCell" forIndexPath:indexPath];
|
||||
|
||||
MXEvent *mxEvent = recents[indexPath.row];
|
||||
MatrixHandler *mxHandler = [MatrixHandler sharedHandler];
|
||||
MXRoom *mxRoom = [mxHandler.mxSession room:mxEvent.roomId];
|
||||
|
||||
cell.roomTitle.text = [mxRoom.state displayname];
|
||||
cell.lastEventDescription.text = [mxHandler displayTextFor:mxEvent inSubtitleMode:YES];
|
||||
|
||||
// Set in bold public room name
|
||||
if (mxRoom.state.isPublic) {
|
||||
cell.roomTitle.font = [UIFont boldSystemFontOfSize:20];
|
||||
} else {
|
||||
cell.roomTitle.font = [UIFont systemFontOfSize:19];
|
||||
}
|
||||
|
||||
if (mxEvent.originServerTs != kMXUndefinedTimestamp) {
|
||||
NSDate *date = [NSDate dateWithTimeIntervalSince1970:mxEvent.originServerTs/1000];
|
||||
cell.recentDate.text = [dateFormatter stringFromDate:date];
|
||||
} else {
|
||||
cell.recentDate.text = nil;
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
// Return NO if you do not want the specified item to be editable.
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (editingStyle == UITableViewCellEditingStyleDelete) {
|
||||
// Leave the selected room
|
||||
MXEvent *mxEvent = recents[indexPath.row];
|
||||
MXRoom *mxRoom = [[MatrixHandler sharedHandler].mxSession room:mxEvent.roomId];
|
||||
[mxRoom leave:^{
|
||||
// Refresh table display
|
||||
[recents removeObjectAtIndex:indexPath.row];
|
||||
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
|
||||
} failure:^(NSError *error) {
|
||||
NSLog(@"Failed to leave room (%@) failed: %@", mxEvent.roomId, error);
|
||||
//Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
24
matrixConsole/ViewController/RoomViewController.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 <UIKit/UIKit.h>
|
||||
|
||||
@interface RoomViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIGestureRecognizerDelegate>
|
||||
|
||||
@property (strong, nonatomic) NSString *roomId;
|
||||
|
||||
@end
|
||||
|
1834
matrixConsole/ViewController/RoomViewController.m
Normal file
24
matrixConsole/ViewController/SettingsViewController.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 <UIKit/UIKit.h>
|
||||
|
||||
@interface SettingsViewController : UITableViewController <UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate>
|
||||
|
||||
- (void)reset;
|
||||
|
||||
@end
|
||||
|
517
matrixConsole/ViewController/SettingsViewController.m
Normal file
|
@ -0,0 +1,517 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 "SettingsViewController.h"
|
||||
|
||||
#import "AppDelegate.h"
|
||||
#import "AppSettings.h"
|
||||
#import "MatrixHandler.h"
|
||||
#import "MediaManager.h"
|
||||
|
||||
#import "SettingsTableViewCell.h"
|
||||
|
||||
#define SETTINGS_SECTION_NOTIFICATIONS_INDEX 0
|
||||
#define SETTINGS_SECTION_ROOMS_INDEX 1
|
||||
#define SETTINGS_SECTION_CONFIGURATION_INDEX 2
|
||||
#define SETTINGS_SECTION_COMMANDS_INDEX 3
|
||||
|
||||
NSString* const kConfigurationFormatText = @"Home server: %@\r\nIdentity server: %@\r\nUser ID: %@\r\nAccess token: %@";
|
||||
NSString* const kCommandsDescriptionText = @"The following commands are available in the room chat:\r\n\r\n /nick <display_name>: change your display name\r\n /me <action>: send the action you are doing. /me will be replaced by your display name\r\n /join <room_alias>: join a room\r\n /kick <user_id> [<reason>]: kick the user\r\n /ban <user_id> [<reason>]: ban the user\r\n /unban <user_id>: unban the user\r\n /op <user_id> <power_level>: set user power level\r\n /deop <user_id>: reset user power level to the room default value";
|
||||
|
||||
@interface SettingsViewController () {
|
||||
id imageLoader;
|
||||
|
||||
NSString *currentDisplayName;
|
||||
NSString *currentPictureURL;
|
||||
NSString *uploadedPictureURL;
|
||||
|
||||
NSMutableArray *errorAlerts;
|
||||
|
||||
UIButton *logoutBtn;
|
||||
UISwitch *notificationsSwitch;
|
||||
UISwitch *allEventsSwitch;
|
||||
UISwitch *unsupportedMsgSwitch;
|
||||
UISwitch *sortMembersSwitch;
|
||||
}
|
||||
@property (strong, nonatomic) IBOutlet UITableView *tableView;
|
||||
@property (weak, nonatomic) IBOutlet UIView *tableHeader;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *userPicture;
|
||||
@property (weak, nonatomic) IBOutlet UITextField *userDisplayName;
|
||||
@property (strong, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;
|
||||
|
||||
- (IBAction)onButtonPressed:(id)sender;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SettingsViewController
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
// Do any additional setup after loading the view, typically from a nib.
|
||||
|
||||
// Add logout button in nav bar
|
||||
logoutBtn = [UIButton buttonWithType:UIButtonTypeSystem];
|
||||
logoutBtn.frame = CGRectMake(0, 0, 60, 44);
|
||||
[logoutBtn setTitle:@"Logout" forState:UIControlStateNormal];
|
||||
[logoutBtn setTitle:@"Logout" forState:UIControlStateHighlighted];
|
||||
[logoutBtn addTarget:self action:@selector(onButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
|
||||
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:logoutBtn];
|
||||
|
||||
errorAlerts = [NSMutableArray array];
|
||||
|
||||
[self startViewConfiguration];
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
|
||||
if (imageLoader) {
|
||||
[MediaManager cancel:imageLoader];
|
||||
imageLoader = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[[MatrixHandler sharedHandler] removeObserver:self forKeyPath:@"userDisplayName"];
|
||||
[[MatrixHandler sharedHandler] removeObserver:self forKeyPath:@"userPictureURL"];
|
||||
|
||||
// Cancel picture loader (if any)
|
||||
if (imageLoader) {
|
||||
[MediaManager cancel:imageLoader];
|
||||
imageLoader = nil;
|
||||
}
|
||||
|
||||
// Cancel potential error alerts
|
||||
for (CustomAlert *alert in errorAlerts){
|
||||
[alert dismiss:NO];
|
||||
}
|
||||
errorAlerts = nil;
|
||||
|
||||
logoutBtn = nil;
|
||||
notificationsSwitch = nil;
|
||||
allEventsSwitch = nil;
|
||||
unsupportedMsgSwitch = nil;
|
||||
sortMembersSwitch = nil;
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[super viewWillAppear:animated];
|
||||
// Refresh displayed settings
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
[super viewWillDisappear:animated];
|
||||
}
|
||||
|
||||
#pragma mark - Internal methods
|
||||
|
||||
- (void)reset {
|
||||
// Cancel picture loader (if any)
|
||||
if (imageLoader) {
|
||||
[MediaManager cancel:imageLoader];
|
||||
imageLoader = nil;
|
||||
}
|
||||
|
||||
// Cancel potential error alerts
|
||||
for (CustomAlert *alert in errorAlerts){
|
||||
[alert dismiss:NO];
|
||||
}
|
||||
|
||||
currentPictureURL = nil;
|
||||
uploadedPictureURL = nil;
|
||||
UIImage *image = [UIImage imageNamed:@"default-profile"];
|
||||
[self.userPicture setImage:image forState:UIControlStateNormal];
|
||||
[self.userPicture setImage:image forState:UIControlStateHighlighted];
|
||||
|
||||
currentDisplayName = nil;
|
||||
self.userDisplayName.text = nil;
|
||||
}
|
||||
|
||||
- (void)startViewConfiguration {
|
||||
// Initialize
|
||||
[self reset];
|
||||
|
||||
// Set current user's information and add observers
|
||||
MatrixHandler *mxHandler = [MatrixHandler sharedHandler];
|
||||
[_activityIndicator startAnimating];
|
||||
// Disable user's interactions
|
||||
_userPicture.enabled = NO;
|
||||
_userDisplayName.enabled = NO;
|
||||
|
||||
// Set user's display name
|
||||
currentDisplayName = mxHandler.userDisplayName;
|
||||
self.userDisplayName.text = mxHandler.userDisplayName;
|
||||
[[MatrixHandler sharedHandler] addObserver:self forKeyPath:@"userDisplayName" options:0 context:nil];
|
||||
[mxHandler.mxRestClient displayNameForUser:mxHandler.userId success:^(NSString *displayname) {
|
||||
mxHandler.userDisplayName = displayname;
|
||||
|
||||
// Set user's picture url
|
||||
[self updateUserPicture:mxHandler.userPictureURL];
|
||||
[[MatrixHandler sharedHandler] addObserver:self forKeyPath:@"userPictureURL" options:0 context:nil];
|
||||
[mxHandler.mxRestClient avatarUrlForUser:mxHandler.userId success:^(NSString *avatar_url) {
|
||||
mxHandler.userPictureURL = avatar_url;
|
||||
[self endViewConfiguration];
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
NSLog(@"Get picture url failed: %@", error);
|
||||
//Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
[self endViewConfiguration];
|
||||
}];
|
||||
} failure:^(NSError *error) {
|
||||
NSLog(@"Get displayName failed: %@", error);
|
||||
//Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
[self endViewConfiguration];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)endViewConfiguration {
|
||||
[_activityIndicator stopAnimating];
|
||||
|
||||
_userPicture.enabled = YES;
|
||||
_userDisplayName.enabled = YES;
|
||||
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
- (void)saveDisplayName {
|
||||
// Check whether the display name has been changed
|
||||
NSString *displayname = self.userDisplayName.text;
|
||||
if ([displayname isEqualToString:currentDisplayName] == NO) {
|
||||
// Save display name
|
||||
[_activityIndicator startAnimating];
|
||||
_userDisplayName.enabled = NO;
|
||||
|
||||
MatrixHandler *mxHandler = [MatrixHandler sharedHandler];
|
||||
[mxHandler.mxRestClient setDisplayName:displayname success:^{
|
||||
currentDisplayName = displayname;
|
||||
|
||||
[_activityIndicator stopAnimating];
|
||||
_userDisplayName.enabled = YES;
|
||||
} failure:^(NSError *error) {
|
||||
NSLog(@"Set displayName failed: %@", error);
|
||||
[_activityIndicator stopAnimating];
|
||||
_userDisplayName.enabled = YES;
|
||||
|
||||
//Alert user
|
||||
NSString *title = [error.userInfo valueForKey:NSLocalizedFailureReasonErrorKey];
|
||||
if (!title) {
|
||||
title = @"Display name change failed";
|
||||
}
|
||||
NSString *msg = [error.userInfo valueForKey:NSLocalizedDescriptionKey];
|
||||
|
||||
CustomAlert *alert = [[CustomAlert alloc] initWithTitle:title message:msg style:CustomAlertStyleAlert];
|
||||
[errorAlerts addObject:alert];
|
||||
alert.cancelButtonIndex = [alert addActionWithTitle:@"Cancel" style:CustomAlertActionStyleDefault handler:^(CustomAlert *alert) {
|
||||
[errorAlerts removeObject:alert];
|
||||
// Remove change
|
||||
self.userDisplayName.text = currentDisplayName;
|
||||
}];
|
||||
[alert addActionWithTitle:@"Retry" style:CustomAlertActionStyleDefault handler:^(CustomAlert *alert) {
|
||||
[errorAlerts removeObject:alert];
|
||||
[self saveDisplayName];
|
||||
}];
|
||||
[alert showInViewController:self];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)savePicture {
|
||||
MatrixHandler *mxHandler = [MatrixHandler sharedHandler];
|
||||
|
||||
// Save picture
|
||||
[_activityIndicator startAnimating];
|
||||
_userPicture.enabled = NO;
|
||||
|
||||
if (uploadedPictureURL == nil) {
|
||||
// Upload picture
|
||||
[mxHandler.mxRestClient uploadContent:UIImageJPEGRepresentation([self.userPicture imageForState:UIControlStateNormal], 0.5)
|
||||
mimeType:@"image/jpeg"
|
||||
timeout:30
|
||||
success:^(NSString *url) {
|
||||
// Store uploaded picture url and trigger picture saving
|
||||
uploadedPictureURL = url;
|
||||
[self savePicture];
|
||||
} failure:^(NSError *error) {
|
||||
NSLog(@"Upload image failed: %@", error);
|
||||
[_activityIndicator stopAnimating];
|
||||
_userPicture.enabled = YES;
|
||||
[self handleErrorDuringPictureSaving:error];
|
||||
}];
|
||||
} else {
|
||||
[mxHandler.mxRestClient setAvatarUrl:uploadedPictureURL
|
||||
success:^{
|
||||
[MatrixHandler sharedHandler].userPictureURL = uploadedPictureURL;
|
||||
uploadedPictureURL = nil;
|
||||
|
||||
[_activityIndicator stopAnimating];
|
||||
_userPicture.enabled = YES;
|
||||
} failure:^(NSError *error) {
|
||||
NSLog(@"Set avatar url failed: %@", error);
|
||||
[_activityIndicator stopAnimating];
|
||||
_userPicture.enabled = YES;
|
||||
[self handleErrorDuringPictureSaving:error];
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleErrorDuringPictureSaving:(NSError*)error {
|
||||
NSString *title = [error.userInfo valueForKey:NSLocalizedFailureReasonErrorKey];
|
||||
if (!title) {
|
||||
title = @"Picture change failed";
|
||||
}
|
||||
NSString *msg = [error.userInfo valueForKey:NSLocalizedDescriptionKey];
|
||||
|
||||
CustomAlert *alert = [[CustomAlert alloc] initWithTitle:title message:msg style:CustomAlertStyleAlert];
|
||||
[errorAlerts addObject:alert];
|
||||
alert.cancelButtonIndex = [alert addActionWithTitle:@"Cancel" style:CustomAlertActionStyleDefault handler:^(CustomAlert *alert) {
|
||||
[errorAlerts removeObject:alert];
|
||||
// Remove change
|
||||
uploadedPictureURL = nil;
|
||||
[self updateUserPicture:[MatrixHandler sharedHandler].userPictureURL];
|
||||
}];
|
||||
[alert addActionWithTitle:@"Retry" style:CustomAlertActionStyleDefault handler:^(CustomAlert *alert) {
|
||||
[errorAlerts removeObject:alert];
|
||||
[self savePicture];
|
||||
}];
|
||||
|
||||
[alert showInViewController:self];
|
||||
}
|
||||
|
||||
- (void)updateUserPicture:(NSString *)avatar_url {
|
||||
if (currentPictureURL == nil || [currentPictureURL isEqualToString:avatar_url] == NO) {
|
||||
// Cancel previous loader (if any)
|
||||
if (imageLoader) {
|
||||
[MediaManager cancel:imageLoader];
|
||||
imageLoader = nil;
|
||||
}
|
||||
|
||||
currentPictureURL = [avatar_url isEqual:[NSNull null]] ? nil : avatar_url;
|
||||
if (currentPictureURL) {
|
||||
// Load user's picture
|
||||
imageLoader = [MediaManager loadPicture:currentPictureURL success:^(UIImage *image) {
|
||||
[self.userPicture setImage:image forState:UIControlStateNormal];
|
||||
[self.userPicture setImage:image forState:UIControlStateHighlighted];
|
||||
} failure:^(NSError *error) {
|
||||
// Reset picture URL in order to try next time
|
||||
currentPictureURL = nil;
|
||||
}];
|
||||
} else {
|
||||
// Set placeholder
|
||||
UIImage *image = [UIImage imageNamed:@"default-profile"];
|
||||
[self.userPicture setImage:image forState:UIControlStateNormal];
|
||||
[self.userPicture setImage:image forState:UIControlStateHighlighted];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - KVO
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
|
||||
if ([@"userDisplayName" isEqualToString:keyPath]) {
|
||||
// Refresh user's display name
|
||||
MatrixHandler *mxHandler = [MatrixHandler sharedHandler];
|
||||
if ([currentDisplayName isEqualToString:mxHandler.userDisplayName] == NO) {
|
||||
currentDisplayName = mxHandler.userDisplayName;
|
||||
self.userDisplayName.text = mxHandler.userDisplayName;
|
||||
}
|
||||
} else if ([@"userPictureURL" isEqualToString:keyPath]) {
|
||||
// Refresh user's picture
|
||||
MatrixHandler *mxHandler = [MatrixHandler sharedHandler];
|
||||
[self updateUserPicture:mxHandler.userPictureURL];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (IBAction)onButtonPressed:(id)sender {
|
||||
[self dismissKeyboard];
|
||||
|
||||
if (sender == _userPicture) {
|
||||
// Open picture gallery
|
||||
UIImagePickerController *mediaPicker = [[UIImagePickerController alloc] init];
|
||||
mediaPicker.delegate = self;
|
||||
mediaPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
|
||||
mediaPicker.allowsEditing = NO;
|
||||
[[AppDelegate theDelegate].masterTabBarController presentMediaPicker:mediaPicker];
|
||||
} else if (sender == logoutBtn) {
|
||||
[self reset];
|
||||
[[AppDelegate theDelegate] logout];
|
||||
} else if (sender == notificationsSwitch) {
|
||||
[AppSettings sharedSettings].enableNotifications = notificationsSwitch.on;
|
||||
} else if (sender == allEventsSwitch) {
|
||||
[AppSettings sharedSettings].displayAllEvents = allEventsSwitch.on;
|
||||
} else if (sender == unsupportedMsgSwitch) {
|
||||
[AppSettings sharedSettings].hideUnsupportedMessages = unsupportedMsgSwitch.on;
|
||||
} else if (sender == sortMembersSwitch) {
|
||||
[AppSettings sharedSettings].sortMembersUsingLastSeenTime = sortMembersSwitch.on;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - keyboard
|
||||
|
||||
- (void)dismissKeyboard
|
||||
{
|
||||
// Hide the keyboard
|
||||
[_userDisplayName resignFirstResponder];
|
||||
// Save display name change (if any)
|
||||
[self saveDisplayName];
|
||||
}
|
||||
|
||||
#pragma mark - UITextField delegate
|
||||
|
||||
- (BOOL)textFieldShouldReturn:(UITextField*) textField
|
||||
{
|
||||
// "Done" key has been pressed
|
||||
[self dismissKeyboard];
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Table view data source
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
return 4;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
if (section == SETTINGS_SECTION_NOTIFICATIONS_INDEX) {
|
||||
return 1;
|
||||
} else if (section == SETTINGS_SECTION_ROOMS_INDEX) {
|
||||
return 3;
|
||||
} else if (section == SETTINGS_SECTION_CONFIGURATION_INDEX) {
|
||||
return 1;
|
||||
} else if (section == SETTINGS_SECTION_COMMANDS_INDEX) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if (indexPath.section == SETTINGS_SECTION_NOTIFICATIONS_INDEX) {
|
||||
return 44;
|
||||
} else if (indexPath.section == SETTINGS_SECTION_ROOMS_INDEX) {
|
||||
return 44;
|
||||
} else if (indexPath.section == SETTINGS_SECTION_CONFIGURATION_INDEX) {
|
||||
UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, MAXFLOAT)];
|
||||
textView.font = [UIFont systemFontOfSize:14];
|
||||
MatrixHandler *mxHandler = [MatrixHandler sharedHandler];
|
||||
textView.text = [NSString stringWithFormat:kConfigurationFormatText, mxHandler.homeServerURL, nil, mxHandler.userId, mxHandler.accessToken];
|
||||
CGSize contentSize = [textView sizeThatFits:textView.frame.size];
|
||||
return contentSize.height + 1;
|
||||
} else if (indexPath.section == SETTINGS_SECTION_COMMANDS_INDEX) {
|
||||
UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, MAXFLOAT)];
|
||||
textView.font = [UIFont systemFontOfSize:14];
|
||||
textView.text = kCommandsDescriptionText;
|
||||
CGSize contentSize = [textView sizeThatFits:textView.frame.size];
|
||||
return contentSize.height + 1;
|
||||
}
|
||||
|
||||
return 44;
|
||||
}
|
||||
|
||||
- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
|
||||
{
|
||||
return 30;
|
||||
}
|
||||
- (CGFloat) tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
|
||||
{
|
||||
UILabel *sectionHeader = [[UILabel alloc] initWithFrame:[tableView rectForHeaderInSection:section]];
|
||||
sectionHeader.font = [UIFont boldSystemFontOfSize:16];
|
||||
sectionHeader.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1.0];
|
||||
|
||||
if (section == SETTINGS_SECTION_NOTIFICATIONS_INDEX) {
|
||||
sectionHeader.text = @" Notifications";
|
||||
} else if (section == SETTINGS_SECTION_ROOMS_INDEX) {
|
||||
sectionHeader.text = @" Rooms";
|
||||
} else if (section == SETTINGS_SECTION_CONFIGURATION_INDEX) {
|
||||
sectionHeader.text = @" Configuration";
|
||||
} else if (section == SETTINGS_SECTION_COMMANDS_INDEX) {
|
||||
sectionHeader.text = @" Commands";
|
||||
} else {
|
||||
sectionHeader = nil;
|
||||
}
|
||||
return sectionHeader;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
SettingsTableViewCell *cell = nil;
|
||||
|
||||
if (indexPath.section == SETTINGS_SECTION_NOTIFICATIONS_INDEX) {
|
||||
SettingsTableCellWithSwitch *notificationsCell = [tableView dequeueReusableCellWithIdentifier:@"SettingsCellWithSwitch" forIndexPath:indexPath];
|
||||
notificationsCell.settingLabel.text = @"Enable notifications";
|
||||
notificationsCell.settingSwitch.on = [[AppSettings sharedSettings] enableNotifications];
|
||||
notificationsSwitch = notificationsCell.settingSwitch;
|
||||
cell = notificationsCell;
|
||||
} else if (indexPath.section == SETTINGS_SECTION_ROOMS_INDEX) {
|
||||
SettingsTableCellWithSwitch *roomsSettingCell = [tableView dequeueReusableCellWithIdentifier:@"SettingsCellWithSwitch" forIndexPath:indexPath];
|
||||
if (indexPath.row == 0) {
|
||||
roomsSettingCell.settingLabel.text = @"Display all events";
|
||||
roomsSettingCell.settingSwitch.on = [[AppSettings sharedSettings] displayAllEvents];
|
||||
allEventsSwitch = roomsSettingCell.settingSwitch;
|
||||
} else if (indexPath.row == 1) {
|
||||
roomsSettingCell.settingLabel.text = @"Hide unsupported messages";
|
||||
roomsSettingCell.settingSwitch.on = [[AppSettings sharedSettings] hideUnsupportedMessages];
|
||||
unsupportedMsgSwitch = roomsSettingCell.settingSwitch;
|
||||
} else {
|
||||
roomsSettingCell.settingLabel.text = @"Sort members by last seen time";
|
||||
roomsSettingCell.settingSwitch.on = [[AppSettings sharedSettings] sortMembersUsingLastSeenTime];
|
||||
sortMembersSwitch = roomsSettingCell.settingSwitch;
|
||||
}
|
||||
cell = roomsSettingCell;
|
||||
} else if (indexPath.section == SETTINGS_SECTION_CONFIGURATION_INDEX) {
|
||||
SettingsTableCellWithTextView *configCell = [tableView dequeueReusableCellWithIdentifier:@"SettingsCellWithTextView" forIndexPath:indexPath];
|
||||
MatrixHandler *mxHandler = [MatrixHandler sharedHandler];
|
||||
configCell.settingTextView.text = [NSString stringWithFormat:kConfigurationFormatText, mxHandler.homeServerURL, nil, mxHandler.userId, mxHandler.accessToken];
|
||||
cell = configCell;
|
||||
} else if (indexPath.section == SETTINGS_SECTION_COMMANDS_INDEX) {
|
||||
SettingsTableCellWithTextView *commandsCell = [tableView dequeueReusableCellWithIdentifier:@"SettingsCellWithTextView" forIndexPath:indexPath];
|
||||
commandsCell.settingTextView.text = kCommandsDescriptionText;
|
||||
cell = commandsCell;
|
||||
}
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
# pragma mark - UIImagePickerControllerDelegate
|
||||
|
||||
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
|
||||
UIImage *selectedImage = [info objectForKey:UIImagePickerControllerOriginalImage];
|
||||
if (selectedImage) {
|
||||
[self.userPicture setImage:selectedImage forState:UIControlStateNormal];
|
||||
[self.userPicture setImage:selectedImage forState:UIControlStateHighlighted];
|
||||
[self savePicture];
|
||||
}
|
||||
[self dismissMediaPicker];
|
||||
}
|
||||
|
||||
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
|
||||
[self dismissMediaPicker];
|
||||
}
|
||||
|
||||
- (void)dismissMediaPicker {
|
||||
[[AppDelegate theDelegate].masterTabBarController dismissMediaPicker];
|
||||
}
|
||||
|
||||
@end
|
24
matrixConsole/main.m
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 <UIKit/UIKit.h>
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char * argv[]) {
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
24
matrixConsoleTests/Info.plist
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.matrix.$(PRODUCT_NAME:rfc1034identifier)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
48
matrixConsoleTests/matrixConsoleTests.m
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
Copyright 2014 OpenMarket 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 <UIKit/UIKit.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
@interface syMessagingTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation syMessagingTests
|
||||
|
||||
- (void)setUp {
|
||||
[super setUp];
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
}
|
||||
|
||||
- (void)tearDown {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
[super tearDown];
|
||||
}
|
||||
|
||||
- (void)testExample {
|
||||
// This is an example of a functional test case.
|
||||
XCTAssert(YES, @"Pass");
|
||||
}
|
||||
|
||||
- (void)testPerformanceExample {
|
||||
// This is an example of a performance test case.
|
||||
[self measureBlock:^{
|
||||
// Put the code you want to measure the time of here.
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|