New Fingerprint Format
Rather than verifying eachothers keys separately, you now verify the privacy with your recipient by sharing a single composite number or QRCode. This is a breaking change, in coordination with Desktop and Android. UX -- Fingeprint is no longer in line with identity key error. Instead you have the option of going to the full-screen safety number verification experience. Overhauled fingerprint design ----------------------------- * use same modal dismiss button as elsewhere * remove fingerprint from settings. * quick slide in animation vs slow fade * existing was painfully slow * blur effect is better metaphor for something slide over top * anyway there was a rendering glitch in the end of fade where underlying navbar would "snap" out Also Fixed ---------- Always provide a name string for contact * Centralize all the nil-checking * Fall back to "unknown contact" allow multi-line error messages // FREEBIE
This commit is contained in:
parent
cc2a25b184
commit
11a586a835
3
Podfile
3
Podfile
|
@ -3,12 +3,13 @@ source 'https://github.com/CocoaPods/Specs.git'
|
|||
|
||||
target 'Signal' do
|
||||
pod 'SocketRocket', :git => 'https://github.com/facebook/SocketRocket.git'
|
||||
pod 'SignalServiceKit', git: 'https://github.com/WhisperSystems/SignalServiceKit.git'
|
||||
pod 'SignalServiceKit', git: 'https://github.com/WhisperSystems/SignalServiceKit.git', branch: 'new-fingerprint-format'
|
||||
#pod 'SignalServiceKit', path: '../SignalServiceKit'
|
||||
pod 'OpenSSL', '~> 1.0.208'
|
||||
pod 'PastelogKit', '~> 1.3'
|
||||
pod 'FFCircularProgressView', '~> 0.5'
|
||||
pod 'SCWaveformView', '~> 1.0'
|
||||
pod 'ZXingObjC'
|
||||
pod 'DJWActionSheet'
|
||||
pod 'JSQMessagesViewController'
|
||||
target 'SignalTests' do
|
||||
|
|
12
Podfile.lock
12
Podfile.lock
|
@ -111,6 +111,9 @@ PODS:
|
|||
- YapDatabase/SQLCipher/Core
|
||||
- YapDatabase/SQLCipher/Extensions/Views (2.9.2):
|
||||
- YapDatabase/SQLCipher/Core
|
||||
- ZXingObjC (3.1.0):
|
||||
- ZXingObjC/All (= 3.1.0)
|
||||
- ZXingObjC/All (3.1.0)
|
||||
|
||||
DEPENDENCIES:
|
||||
- DJWActionSheet
|
||||
|
@ -119,18 +122,20 @@ DEPENDENCIES:
|
|||
- OpenSSL (~> 1.0.208)
|
||||
- PastelogKit (~> 1.3)
|
||||
- SCWaveformView (~> 1.0)
|
||||
- SignalServiceKit (from `https://github.com/WhisperSystems/SignalServiceKit.git`)
|
||||
- SignalServiceKit (from `https://github.com/WhisperSystems/SignalServiceKit.git`, branch `new-fingerprint-format`)
|
||||
- SocketRocket (from `https://github.com/facebook/SocketRocket.git`)
|
||||
- ZXingObjC
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
SignalServiceKit:
|
||||
:branch: new-fingerprint-format
|
||||
:git: https://github.com/WhisperSystems/SignalServiceKit.git
|
||||
SocketRocket:
|
||||
:git: https://github.com/facebook/SocketRocket.git
|
||||
|
||||
CHECKOUT OPTIONS:
|
||||
SignalServiceKit:
|
||||
:commit: ce1aa04b6193b47b82b44d529cca12c62fae4c48
|
||||
:commit: 2b612e9ab72b427b310b125b1dc82eef1d3f85ec
|
||||
:git: https://github.com/WhisperSystems/SignalServiceKit.git
|
||||
SocketRocket:
|
||||
:commit: 41b57bb2fc292a814f758441a05243eb38457027
|
||||
|
@ -160,7 +165,8 @@ SPEC CHECKSUMS:
|
|||
TwistedOakCollapsingFutures: f359b90f203e9ab13dfb92c9ff41842a7fe1cd0c
|
||||
UnionFind: c33be5adb12983981d6e827ea94fc7f9e370f52d
|
||||
YapDatabase: b1e43555a34a5298e23a045be96817a5ef0da58f
|
||||
ZXingObjC: bf15b3814f7a105b6d99f47da2333c93a063650a
|
||||
|
||||
PODFILE CHECKSUM: 5dccee4c1c1ba5d4bf9575a81eeede82d1e89e8b
|
||||
PODFILE CHECKSUM: d4204cf787649f9512dc74e5844f48d2570d5b2e
|
||||
|
||||
COCOAPODS: 1.0.1
|
||||
|
|
|
@ -159,8 +159,6 @@
|
|||
A547DD741A70A87800103EC7 /* DJWActionSheet+OWS.m in Sources */ = {isa = PBXBuildFile; fileRef = A547DD721A70A87800103EC7 /* DJWActionSheet+OWS.m */; };
|
||||
A5509ECA1A69AB8B00ABA4BC /* Storyboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A5509EC91A69AB8B00ABA4BC /* Storyboard.storyboard */; };
|
||||
A5509ECD1A69B1D600ABA4BC /* CountryCodeTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = A5509ECC1A69B1D600ABA4BC /* CountryCodeTableViewCell.m */; };
|
||||
A56977911A351BC400173BF2 /* ScanIdentityBarcodeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A569778E1A351BC400173BF2 /* ScanIdentityBarcodeViewController.m */; };
|
||||
A56977921A351BC400173BF2 /* PresentIdentityQRCodeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A569778F1A351BC400173BF2 /* PresentIdentityQRCodeViewController.m */; };
|
||||
A5D0699B1A50E9CB004CB540 /* ShowGroupMembersViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A5D069991A50E9CB004CB540 /* ShowGroupMembersViewController.m */; };
|
||||
A5E9D4BB1A65FAD800E4481C /* TSVideoAttachmentAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = A5E9D4B91A65FAD800E4481C /* TSVideoAttachmentAdapter.m */; };
|
||||
AD41D7B51A6F6F0600241130 /* play_button.png in Resources */ = {isa = PBXBuildFile; fileRef = AD41D7B31A6F6F0600241130 /* play_button.png */; };
|
||||
|
@ -789,10 +787,6 @@
|
|||
A5509EC91A69AB8B00ABA4BC /* Storyboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Storyboard.storyboard; path = Storyboard/Storyboard.storyboard; sourceTree = "<group>"; };
|
||||
A5509ECB1A69B1D600ABA4BC /* CountryCodeTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CountryCodeTableViewCell.h; sourceTree = "<group>"; };
|
||||
A5509ECC1A69B1D600ABA4BC /* CountryCodeTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CountryCodeTableViewCell.m; sourceTree = "<group>"; };
|
||||
A569778D1A351BC400173BF2 /* ScanIdentityBarcodeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScanIdentityBarcodeViewController.h; sourceTree = "<group>"; };
|
||||
A569778E1A351BC400173BF2 /* ScanIdentityBarcodeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScanIdentityBarcodeViewController.m; sourceTree = "<group>"; };
|
||||
A569778F1A351BC400173BF2 /* PresentIdentityQRCodeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PresentIdentityQRCodeViewController.m; sourceTree = "<group>"; };
|
||||
A56977901A351BC400173BF2 /* PresentIdentityQRCodeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PresentIdentityQRCodeViewController.h; sourceTree = "<group>"; };
|
||||
A5D069991A50E9CB004CB540 /* ShowGroupMembersViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = ShowGroupMembersViewController.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
|
||||
A5D0699A1A50E9CB004CB540 /* ShowGroupMembersViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShowGroupMembersViewController.h; sourceTree = "<group>"; };
|
||||
A5E9D4B91A65FAD800E4481C /* TSVideoAttachmentAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSVideoAttachmentAdapter.m; sourceTree = "<group>"; };
|
||||
|
@ -2301,10 +2295,6 @@
|
|||
FC3196321A08142D0094C78E /* Signals */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
A569778D1A351BC400173BF2 /* ScanIdentityBarcodeViewController.h */,
|
||||
A569778E1A351BC400173BF2 /* ScanIdentityBarcodeViewController.m */,
|
||||
A56977901A351BC400173BF2 /* PresentIdentityQRCodeViewController.h */,
|
||||
A569778F1A351BC400173BF2 /* PresentIdentityQRCodeViewController.m */,
|
||||
FC3196281A067D8F0094C78E /* MessageComposeTableViewController.h */,
|
||||
FC3196291A067D8F0094C78E /* MessageComposeTableViewController.m */,
|
||||
FCAC963A19FEF9280046DFC5 /* SignalsViewController.h */,
|
||||
|
@ -2688,7 +2678,6 @@
|
|||
A5509ECD1A69B1D600ABA4BC /* CountryCodeTableViewCell.m in Sources */,
|
||||
76EB05F618170B33006006FC /* CallConnectUtil.m in Sources */,
|
||||
76EB061218170B33006006FC /* LoggingUtil.m in Sources */,
|
||||
A56977921A351BC400173BF2 /* PresentIdentityQRCodeViewController.m in Sources */,
|
||||
76EB060E18170B33006006FC /* DecayingSampleEstimator.m in Sources */,
|
||||
76EB05BA18170B33006006FC /* CommitPacket.m in Sources */,
|
||||
76EB060218170B33006006FC /* InitiatorSessionDescriptor.m in Sources */,
|
||||
|
@ -2719,7 +2708,6 @@
|
|||
FCD274EB1A5AFDDB00202277 /* AboutTableViewController.m in Sources */,
|
||||
E197B61618BBEC1A00F073E5 /* StretchFactorController.m in Sources */,
|
||||
FCFD257F1A154B2C00F4C644 /* RegistrationViewController.m in Sources */,
|
||||
A56977911A351BC400173BF2 /* ScanIdentityBarcodeViewController.m in Sources */,
|
||||
701231B518ECAA4500D456C4 /* EvpMessageDigest.m in Sources */,
|
||||
76EB062218170B33006006FC /* CyclicalBuffer.m in Sources */,
|
||||
76EB063C18170B33006006FC /* NumberUtil.m in Sources */,
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.5.3</string>
|
||||
<string>2.6.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
@ -38,7 +38,7 @@
|
|||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2.5.3.4</string>
|
||||
<string>2.6.0.1</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<false/>
|
||||
<key>LOGS_EMAIL</key>
|
||||
|
|
|
@ -40,13 +40,6 @@ static NSString *const kURLHostVerifyPrefix = @"verify";
|
|||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
[self setupAppearance];
|
||||
[[PushManager sharedManager] registerPushKitNotificationFuture];
|
||||
|
||||
if (getenv("runningTests_dontStartApp")) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
// Initializing logger
|
||||
CategorizingLogger *logger = [CategorizingLogger categorizingLogger];
|
||||
[logger addLoggingCallback:^(NSString *category, id details, NSUInteger index){
|
||||
|
@ -55,6 +48,13 @@ static NSString *const kURLHostVerifyPrefix = @"verify";
|
|||
// Setting up environment
|
||||
[Environment setCurrent:[Release releaseEnvironmentWithLogging:logger]];
|
||||
|
||||
[self setupAppearance];
|
||||
[[PushManager sharedManager] registerPushKitNotificationFuture];
|
||||
|
||||
if (getenv("runningTests_dontStartApp")) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if ([TSAccountManager isRegistered]) {
|
||||
[Environment.getCurrent.contactsManager doAfterEnvironmentInitSetup];
|
||||
}
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
|
||||
TSMessageAdapter *message = (TSMessageAdapter *)messageData;
|
||||
if (message.messageType == TSInfoMessageAdapter || message.messageType == TSErrorMessageAdapter) {
|
||||
|
||||
// Prevent cropping message text by accounting for message container/icon
|
||||
superSize.height = OWSDisplayedMessageCellHeight;
|
||||
// But also allow for multi-line error messages.
|
||||
superSize.height = fmax(superSize.height, OWSDisplayedMessageCellHeight);
|
||||
}
|
||||
|
||||
return superSize;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15G31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="tuk-0x-yCb">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15G1004" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="tuk-0x-yCb">
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||
|
@ -114,7 +114,7 @@
|
|||
</barButtonItem>
|
||||
</navigationItem>
|
||||
<connections>
|
||||
<segue destination="urv-62-RsD" kind="modal" identifier="fingerprintSegue" animates="NO" modalPresentationStyle="overCurrentContext" id="Zjl-QX-tHE"/>
|
||||
<segue destination="urv-62-RsD" kind="modal" identifier="fingerprintSegue" modalPresentationStyle="overCurrentContext" modalTransitionStyle="coverVertical" id="Zjl-QX-tHE"/>
|
||||
<segue destination="bDi-2Q-XOC" kind="push" identifier="updateGroupSegue" id="gZ1-lh-srF"/>
|
||||
<segue destination="JeZ-9g-U61" kind="push" identifier="showGroupMembersSegue" id="Gc6-AD-JV1"/>
|
||||
</connections>
|
||||
|
@ -135,236 +135,184 @@
|
|||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<visualEffectView opaque="NO" contentMode="left" translatesAutoresizingMaskIntoConstraints="NO" id="VCu-vN-Pjg">
|
||||
<visualEffectView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="X9c-nY-Re0">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="kEV-0h-NsX">
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="GUy-oN-Va6">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="zFI-eF-Feb" userLabel="Their Fingerprint">
|
||||
<rect key="frame" x="0.0" y="0.0" width="400" height="221"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="AwQ-ec-WBO">
|
||||
<rect key="frame" x="0.0" y="220" width="400" height="1"/>
|
||||
<color key="backgroundColor" white="0.61676562499999998" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="1" id="yMD-Sw-sDy"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<imageView userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="btnCamera--white" translatesAutoresizingMaskIntoConstraints="NO" id="HyV-ht-MrM">
|
||||
<rect key="frame" x="19" y="73" width="75" height="75"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="75" id="Yxr-T5-Jck"/>
|
||||
<constraint firstAttribute="width" constant="75" id="bRq-v9-94p"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Momo's Fingerprint" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ii9-7N-hCc">
|
||||
<rect key="frame" x="115" y="35" width="250" height="21"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="21" id="epx-el-0T8"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" lineBreakMode="tailTruncation" numberOfLines="4" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="kBW-ix-mdQ">
|
||||
<rect key="frame" x="115" y="73" width="250" height="75"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="75" id="jaw-8F-c1C"/>
|
||||
</constraints>
|
||||
<string key="text">A0 09 9A FF A8 8A 09 99
|
||||
1E 5C 7B 8A 56 2B 1F 65
|
||||
B3 83 8D 1D D0 FA 9C E3
|
||||
A0 09 9A FF A8 8A 09 99</string>
|
||||
<fontDescription key="fontDescription" name="Courier" family="Courier" pointSize="16"/>
|
||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Tap to scan another user's fingerprint" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ge0-8K-A4F">
|
||||
<rect key="frame" x="115" y="160" width="213" height="44"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="44" id="HyF-Kt-KmB"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="14"/>
|
||||
<color key="textColor" white="0.75" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<gestureRecognizers/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="HyV-ht-MrM" secondAttribute="trailing" constant="306" id="1XO-7v-R7T"/>
|
||||
<constraint firstAttribute="height" constant="221" id="HBq-Ly-0qj"/>
|
||||
<constraint firstItem="AwQ-ec-WBO" firstAttribute="leading" secondItem="zFI-eF-Feb" secondAttribute="leading" id="HfI-Gb-ykL"/>
|
||||
<constraint firstItem="ge0-8K-A4F" firstAttribute="leading" secondItem="zFI-eF-Feb" secondAttribute="leading" constant="115" id="Io8-J3-g1q"/>
|
||||
<constraint firstAttribute="trailing" secondItem="AwQ-ec-WBO" secondAttribute="trailing" id="LGK-WL-NBq"/>
|
||||
<constraint firstItem="AwQ-ec-WBO" firstAttribute="top" secondItem="zFI-eF-Feb" secondAttribute="top" constant="220" id="ML3-4p-6ML"/>
|
||||
<constraint firstItem="ge0-8K-A4F" firstAttribute="top" secondItem="zFI-eF-Feb" secondAttribute="top" constant="160" id="MR1-lO-oHk"/>
|
||||
<constraint firstItem="HyV-ht-MrM" firstAttribute="top" secondItem="zFI-eF-Feb" secondAttribute="top" constant="73" id="Wyq-lm-CaG"/>
|
||||
<constraint firstItem="Ii9-7N-hCc" firstAttribute="top" secondItem="zFI-eF-Feb" secondAttribute="top" constant="35" id="Zd1-Oz-JmD"/>
|
||||
<constraint firstItem="HyV-ht-MrM" firstAttribute="leading" secondItem="zFI-eF-Feb" secondAttribute="leading" constant="19" id="dgg-gQ-GPY"/>
|
||||
<constraint firstItem="kBW-ix-mdQ" firstAttribute="leading" secondItem="zFI-eF-Feb" secondAttribute="leading" constant="115" id="fYR-kP-vRN"/>
|
||||
<constraint firstAttribute="trailing" secondItem="kBW-ix-mdQ" secondAttribute="trailing" constant="35" id="jVG-sA-F3W"/>
|
||||
<constraint firstItem="Ii9-7N-hCc" firstAttribute="leading" secondItem="zFI-eF-Feb" secondAttribute="leading" constant="115" id="nrS-05-Uru"/>
|
||||
<constraint firstItem="kBW-ix-mdQ" firstAttribute="top" secondItem="zFI-eF-Feb" secondAttribute="top" constant="73" id="o0C-aS-9NZ"/>
|
||||
<constraint firstAttribute="trailing" secondItem="Ii9-7N-hCc" secondAttribute="trailing" constant="35" id="vKr-Nz-ISB"/>
|
||||
<constraint firstAttribute="trailing" secondItem="ge0-8K-A4F" secondAttribute="trailing" constant="72" id="xBr-5Q-660"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outletCollection property="gestureRecognizers" destination="fRl-Lt-y39" appends="YES" id="wIa-Aj-hqy"/>
|
||||
</connections>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Compare both fingerprints to verify your contact's identity and the integrity of the message." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DV4-GV-ZPf">
|
||||
<rect key="frame" x="22" y="460" width="356" height="44"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="44" id="bif-t1-qQO"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||
<color key="textColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="B4o-Rc-z68" userLabel="My Fingerprint">
|
||||
<rect key="frame" x="0.0" y="221" width="400" height="221"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="WhZ-e0-THb">
|
||||
<rect key="frame" x="0.0" y="220" width="400" height="1"/>
|
||||
<color key="backgroundColor" white="0.61676562499999998" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="1" id="XgI-5W-uMZ"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Your Fingerprint" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5De-Jq-XWv">
|
||||
<rect key="frame" x="115" y="35" width="250" height="21"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="21" id="475-f9-1TO"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="btnQRShow--white" highlightedImage="btnQRShow--white-1" translatesAutoresizingMaskIntoConstraints="NO" id="YOs-e5-ee3">
|
||||
<rect key="frame" x="19" y="73" width="75" height="75"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="75" id="5IR-xd-6uL"/>
|
||||
<constraint firstAttribute="height" constant="75" id="Nfl-jf-HzC"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Tap to display your fingerprint for another user" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9Wg-UP-VDC">
|
||||
<rect key="frame" x="115" y="160" width="208" height="43"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="43" id="xb1-B9-MyR"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="14"/>
|
||||
<color key="textColor" white="0.75" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" lineBreakMode="tailTruncation" numberOfLines="4" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="e7E-iS-3Oc">
|
||||
<rect key="frame" x="115" y="73" width="250" height="75"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="75" id="k9r-Fg-1QJ"/>
|
||||
</constraints>
|
||||
<string key="text">A0 09 9A FF A8 8A 09 99
|
||||
1E 5C 7B 8A 56 2B 1F 65
|
||||
B3 83 8D 1D D0 FA 9C E3
|
||||
A0 09 9A FF A8 8A 09 99</string>
|
||||
<fontDescription key="fontDescription" name="Courier" family="Courier" pointSize="17"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<gestureRecognizers/>
|
||||
<constraints>
|
||||
<constraint firstItem="9Wg-UP-VDC" firstAttribute="leading" secondItem="B4o-Rc-z68" secondAttribute="leading" constant="115" id="3zq-WB-ASq"/>
|
||||
<constraint firstAttribute="trailing" secondItem="5De-Jq-XWv" secondAttribute="trailing" constant="35" id="8wL-8Y-SSo"/>
|
||||
<constraint firstAttribute="trailing" secondItem="e7E-iS-3Oc" secondAttribute="trailing" constant="35" id="CbM-nY-P0U"/>
|
||||
<constraint firstItem="9Wg-UP-VDC" firstAttribute="top" secondItem="B4o-Rc-z68" secondAttribute="top" constant="160" id="DDh-3a-uIm"/>
|
||||
<constraint firstItem="WhZ-e0-THb" firstAttribute="leading" secondItem="B4o-Rc-z68" secondAttribute="leading" id="EIo-e5-i5c"/>
|
||||
<constraint firstAttribute="trailing" secondItem="WhZ-e0-THb" secondAttribute="trailing" id="Isj-Bf-lu6"/>
|
||||
<constraint firstItem="5De-Jq-XWv" firstAttribute="leading" secondItem="B4o-Rc-z68" secondAttribute="leading" constant="115" id="RmR-Hh-1Ys"/>
|
||||
<constraint firstItem="YOs-e5-ee3" firstAttribute="top" secondItem="B4o-Rc-z68" secondAttribute="top" constant="73" id="VaC-nb-QHZ"/>
|
||||
<constraint firstAttribute="height" constant="221" id="a12-JK-RBy"/>
|
||||
<constraint firstItem="e7E-iS-3Oc" firstAttribute="leading" secondItem="B4o-Rc-z68" secondAttribute="leading" constant="115" id="clq-cu-8Hq"/>
|
||||
<constraint firstItem="WhZ-e0-THb" firstAttribute="top" secondItem="B4o-Rc-z68" secondAttribute="top" constant="220" id="fDt-eB-0Lh"/>
|
||||
<constraint firstAttribute="trailing" secondItem="YOs-e5-ee3" secondAttribute="trailing" constant="306" id="flI-Gp-aWH"/>
|
||||
<constraint firstAttribute="trailing" secondItem="9Wg-UP-VDC" secondAttribute="trailing" constant="77" id="mLc-13-Wcv"/>
|
||||
<constraint firstItem="YOs-e5-ee3" firstAttribute="leading" secondItem="B4o-Rc-z68" secondAttribute="leading" constant="19" id="md2-eV-aBb"/>
|
||||
<constraint firstItem="e7E-iS-3Oc" firstAttribute="top" secondItem="B4o-Rc-z68" secondAttribute="top" constant="73" id="mif-35-C1B"/>
|
||||
<constraint firstItem="5De-Jq-XWv" firstAttribute="top" secondItem="B4o-Rc-z68" secondAttribute="top" constant="35" id="pCa-lD-NlC"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outletCollection property="gestureRecognizers" destination="Mg3-ad-PGG" appends="YES" id="fDZ-ZY-J04"/>
|
||||
</connections>
|
||||
</view>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Yoz-ex-1gK">
|
||||
<rect key="frame" x="19" y="492" width="50" height="50"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="50" id="Ie5-wL-XEo"/>
|
||||
<constraint firstAttribute="height" constant="50" id="aq2-hO-WY0"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="60"/>
|
||||
<state key="normal" title="×">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="closeButtonAction:" destination="urv-62-RsD" eventType="touchUpInside" id="m15-1K-9gB"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="Yoz-ex-1gK" secondAttribute="bottom" constant="26" id="EVw-Jr-67j"/>
|
||||
<constraint firstAttribute="trailing" secondItem="zFI-eF-Feb" secondAttribute="trailing" id="Jfg-Ac-5SC"/>
|
||||
<constraint firstItem="zFI-eF-Feb" firstAttribute="leading" secondItem="kEV-0h-NsX" secondAttribute="leading" id="Lh4-K4-lK4"/>
|
||||
<constraint firstItem="B4o-Rc-z68" firstAttribute="leading" secondItem="kEV-0h-NsX" secondAttribute="leading" id="Pe1-Ko-Er7"/>
|
||||
<constraint firstItem="Yoz-ex-1gK" firstAttribute="leading" secondItem="kEV-0h-NsX" secondAttribute="leading" constant="19" id="Ptp-Na-ekf"/>
|
||||
<constraint firstItem="zFI-eF-Feb" firstAttribute="top" secondItem="kEV-0h-NsX" secondAttribute="top" id="cBU-ru-0Nv"/>
|
||||
<constraint firstItem="DV4-GV-ZPf" firstAttribute="leading" secondItem="kEV-0h-NsX" secondAttribute="leading" constant="22" id="eVX-2q-T74"/>
|
||||
<constraint firstAttribute="trailing" secondItem="B4o-Rc-z68" secondAttribute="trailing" id="iKt-RZ-COk"/>
|
||||
<constraint firstAttribute="trailing" secondItem="DV4-GV-ZPf" secondAttribute="trailing" constant="22" id="qbq-AK-HjD"/>
|
||||
<constraint firstItem="B4o-Rc-z68" firstAttribute="top" secondItem="kEV-0h-NsX" secondAttribute="top" constant="221" id="rE0-BW-UQv"/>
|
||||
<constraint firstItem="DV4-GV-ZPf" firstAttribute="top" secondItem="kEV-0h-NsX" secondAttribute="top" constant="460" id="tPa-CI-8ak"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<blurEffect style="dark"/>
|
||||
</visualEffectView>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="8DU-2J-HAz" userLabel="Scanner Container">
|
||||
<rect key="frame" x="0.0" y="-284" width="320" height="284"/>
|
||||
<subviews>
|
||||
<containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="MhA-kC-nBb" userLabel="Scanner">
|
||||
<rect key="frame" x="0.0" y="66" width="320" height="218"/>
|
||||
<connections>
|
||||
<segue destination="EFG-13-FgR" kind="embed" identifier="embedIdentityQRScanner" id="0sF-Is-2kw"/>
|
||||
</connections>
|
||||
</containerView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="MhA-kC-nBb" firstAttribute="leading" secondItem="8DU-2J-HAz" secondAttribute="leading" id="EwE-x7-nyJ"/>
|
||||
<constraint firstAttribute="trailing" secondItem="MhA-kC-nBb" secondAttribute="trailing" id="Hj7-wD-3wR"/>
|
||||
<constraint firstItem="MhA-kC-nBb" firstAttribute="top" secondItem="8DU-2J-HAz" secondAttribute="top" constant="66" id="JTj-zm-L8f"/>
|
||||
<constraint firstAttribute="bottom" secondItem="MhA-kC-nBb" secondAttribute="bottom" id="RuO-nQ-fOf"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="b7W-j4-3S1" userLabel="QR Container">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="284"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="lA7-b4-o6C" userLabel="QR Frame">
|
||||
<rect key="frame" x="54" y="66" width="212" height="212"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" image="btnQRShow--white" highlightedImage="btnQRShow--white-1" translatesAutoresizingMaskIntoConstraints="NO" id="YOs-e5-ee3" userLabel="Privacy Verification QR">
|
||||
<rect key="frame" x="33" y="33" width="136" height="136"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="YOs-e5-ee3" secondAttribute="height" multiplier="1:1" id="lN0-BE-w2c"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="lA7-b4-o6C" secondAttribute="height" multiplier="1:1" id="01p-Ui-d1b"/>
|
||||
<constraint firstItem="YOs-e5-ee3" firstAttribute="centerY" secondItem="lA7-b4-o6C" secondAttribute="centerY" id="ZRp-fU-qZu"/>
|
||||
<constraint firstItem="YOs-e5-ee3" firstAttribute="centerX" secondItem="lA7-b4-o6C" secondAttribute="centerX" id="oWJ-Z4-8ke"/>
|
||||
<constraint firstItem="YOs-e5-ee3" firstAttribute="height" secondItem="lA7-b4-o6C" secondAttribute="height" multiplier="2/3" id="svC-b9-cy9"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="lA7-b4-o6C" firstAttribute="width" secondItem="b7W-j4-3S1" secondAttribute="width" multiplier="2/3" id="axL-M0-aaE"/>
|
||||
<constraint firstItem="lA7-b4-o6C" firstAttribute="centerY" secondItem="b7W-j4-3S1" secondAttribute="centerY" constant="30" id="uHm-ee-HVb"/>
|
||||
<constraint firstItem="lA7-b4-o6C" firstAttribute="centerX" secondItem="b7W-j4-3S1" secondAttribute="centerX" id="zzE-ab-Qv9"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="B4o-Rc-z68" userLabel="Instructions Container">
|
||||
<rect key="frame" x="0.0" y="284" width="320" height="284"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="12345 54432 83456 89456 24327 87547 90123 31523 91052 84930 89304 00234" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="3" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="e7E-iS-3Oc" userLabel="Privacy Verification Key Text">
|
||||
<rect key="frame" x="36" y="0.0" width="248" height="70"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="70" id="k9r-Fg-1QJ"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" name="Menlo-Regular" family="Menlo" pointSize="24"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Scan the code on your contacts phone, or ask them to scan your code to verify that your messages are end-to-end encrypted." lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" adjustsLetterSpacingToFitWidth="YES" translatesAutoresizingMaskIntoConstraints="NO" id="DV4-GV-ZPf" userLabel="Instructions ">
|
||||
<rect key="frame" x="16" y="78" width="288" height="104"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="44" id="bif-t1-qQO"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<color key="textColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="top" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="RX6-CJ-FV1">
|
||||
<rect key="frame" x="90" y="202" width="141" height="70"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="70" id="g0E-XL-o8K"/>
|
||||
</constraints>
|
||||
<inset key="titleEdgeInsets" minX="-50" minY="44" maxX="0.0" maxY="0.0"/>
|
||||
<inset key="imageEdgeInsets" minX="43" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
<state key="normal" title="Scan Code" image="btnCamera--white">
|
||||
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="didTouchUpInsideScanButton:" destination="urv-62-RsD" eventType="touchUpInside" id="YJi-1a-Pg7"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<gestureRecognizers/>
|
||||
<constraints>
|
||||
<constraint firstItem="RX6-CJ-FV1" firstAttribute="centerX" secondItem="B4o-Rc-z68" secondAttribute="centerX" id="3Tz-CS-vgs"/>
|
||||
<constraint firstItem="e7E-iS-3Oc" firstAttribute="leading" secondItem="B4o-Rc-z68" secondAttribute="leading" constant="36" id="7cQ-4a-DIS"/>
|
||||
<constraint firstAttribute="bottom" secondItem="RX6-CJ-FV1" secondAttribute="bottom" constant="12" id="IFA-AS-nVw"/>
|
||||
<constraint firstItem="e7E-iS-3Oc" firstAttribute="top" secondItem="B4o-Rc-z68" secondAttribute="top" id="NVF-Sc-fff"/>
|
||||
<constraint firstItem="DV4-GV-ZPf" firstAttribute="top" secondItem="e7E-iS-3Oc" secondAttribute="bottom" constant="8" id="WaE-z7-y2j"/>
|
||||
<constraint firstItem="RX6-CJ-FV1" firstAttribute="top" secondItem="DV4-GV-ZPf" secondAttribute="bottom" constant="20" id="XN2-Ok-U7y"/>
|
||||
<constraint firstAttribute="trailing" secondItem="DV4-GV-ZPf" secondAttribute="trailing" constant="16" id="dFu-ak-X2j"/>
|
||||
<constraint firstAttribute="trailing" secondItem="e7E-iS-3Oc" secondAttribute="trailing" constant="36" id="daW-7v-6MP"/>
|
||||
<constraint firstItem="DV4-GV-ZPf" firstAttribute="leading" secondItem="B4o-Rc-z68" secondAttribute="leading" constant="16" id="sZ7-tO-0jJ"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outletCollection property="gestureRecognizers" destination="Mg3-ad-PGG" appends="YES" id="fDZ-ZY-J04"/>
|
||||
</connections>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="eyu-sj-AbV" userLabel="Top Bar">
|
||||
<rect key="frame" x="0.0" y="22" width="320" height="44"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Yoz-ex-1gK">
|
||||
<rect key="frame" x="0.0" y="0.0" width="44" height="44"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="44" id="Ie5-wL-XEo"/>
|
||||
<constraint firstAttribute="height" constant="44" id="aq2-hO-WY0"/>
|
||||
</constraints>
|
||||
<state key="normal" image="btnCancel--white"/>
|
||||
<connections>
|
||||
<action selector="closeButtonAction:" destination="urv-62-RsD" eventType="touchUpInside" id="m15-1K-9gB"/>
|
||||
</connections>
|
||||
</button>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Safety Number for Momo" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vR4-Y9-ryx" userLabel="Safety Number for Momo">
|
||||
<rect key="frame" x="40" y="0.0" width="240" height="45"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
|
||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="Yoz-ex-1gK" firstAttribute="leading" secondItem="eyu-sj-AbV" secondAttribute="leading" id="3YT-t8-R98"/>
|
||||
<constraint firstItem="vR4-Y9-ryx" firstAttribute="centerY" secondItem="eyu-sj-AbV" secondAttribute="centerY" id="9dS-Pk-hvb"/>
|
||||
<constraint firstItem="Yoz-ex-1gK" firstAttribute="top" secondItem="eyu-sj-AbV" secondAttribute="top" id="Rfl-RX-bgS"/>
|
||||
<constraint firstItem="vR4-Y9-ryx" firstAttribute="width" secondItem="eyu-sj-AbV" secondAttribute="width" multiplier="3/4" id="TaA-GT-RI3"/>
|
||||
<constraint firstAttribute="height" constant="44" id="cMD-p0-7XC"/>
|
||||
<constraint firstItem="vR4-Y9-ryx" firstAttribute="centerX" secondItem="eyu-sj-AbV" secondAttribute="centerX" id="oE0-Zr-7Kv"/>
|
||||
<constraint firstItem="vR4-Y9-ryx" firstAttribute="top" secondItem="eyu-sj-AbV" secondAttribute="top" id="tED-yF-Auq"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="hdo-6G-gXy" firstAttribute="top" secondItem="VCu-vN-Pjg" secondAttribute="bottom" id="1dB-W2-GMz"/>
|
||||
<constraint firstAttribute="centerX" secondItem="VCu-vN-Pjg" secondAttribute="centerX" id="5Wt-QM-aQa"/>
|
||||
<constraint firstItem="VCu-vN-Pjg" firstAttribute="top" secondItem="8Oc-YZ-y0M" secondAttribute="bottom" constant="-20" id="KIN-pk-9pP"/>
|
||||
<constraint firstAttribute="width" secondItem="VCu-vN-Pjg" secondAttribute="width" id="gOw-BF-mQC"/>
|
||||
<constraint firstAttribute="height" secondItem="VCu-vN-Pjg" secondAttribute="height" id="nEQ-Wa-OyH"/>
|
||||
<constraint firstAttribute="centerY" secondItem="VCu-vN-Pjg" secondAttribute="centerY" id="sho-vB-Yk8"/>
|
||||
<constraint firstItem="8DU-2J-HAz" firstAttribute="leading" secondItem="StY-nr-mRe" secondAttribute="leading" id="00e-Rm-0Uk"/>
|
||||
<constraint firstAttribute="trailing" secondItem="eyu-sj-AbV" secondAttribute="trailing" id="2mP-vt-cG0"/>
|
||||
<constraint firstAttribute="trailing" secondItem="B4o-Rc-z68" secondAttribute="trailing" id="3ii-xe-El5"/>
|
||||
<constraint firstItem="X9c-nY-Re0" firstAttribute="top" secondItem="StY-nr-mRe" secondAttribute="topMargin" id="4jD-8p-9y8"/>
|
||||
<constraint firstItem="hdo-6G-gXy" firstAttribute="top" secondItem="B4o-Rc-z68" secondAttribute="bottom" id="ChJ-qg-hLJ"/>
|
||||
<constraint firstItem="eyu-sj-AbV" firstAttribute="leading" secondItem="StY-nr-mRe" secondAttribute="leading" id="Dno-eX-doN"/>
|
||||
<constraint firstItem="eyu-sj-AbV" firstAttribute="top" secondItem="StY-nr-mRe" secondAttribute="topMargin" constant="22" id="FwQ-7E-lv5"/>
|
||||
<constraint firstItem="b7W-j4-3S1" firstAttribute="leading" secondItem="StY-nr-mRe" secondAttribute="leading" id="H4U-cb-hW7"/>
|
||||
<constraint firstItem="X9c-nY-Re0" firstAttribute="leading" secondItem="StY-nr-mRe" secondAttribute="leading" id="JO9-ay-ebd"/>
|
||||
<constraint firstItem="B4o-Rc-z68" firstAttribute="leading" secondItem="StY-nr-mRe" secondAttribute="leading" id="KhC-UZ-RCj"/>
|
||||
<constraint firstAttribute="trailing" secondItem="b7W-j4-3S1" secondAttribute="trailing" id="PRX-ZC-wpQ"/>
|
||||
<constraint firstItem="B4o-Rc-z68" firstAttribute="top" secondItem="b7W-j4-3S1" secondAttribute="bottom" id="V05-1p-r0f"/>
|
||||
<constraint firstItem="b7W-j4-3S1" firstAttribute="top" secondItem="StY-nr-mRe" secondAttribute="topMargin" id="byY-vN-ywN"/>
|
||||
<constraint firstItem="8DU-2J-HAz" firstAttribute="bottom" secondItem="b7W-j4-3S1" secondAttribute="top" id="fOH-xt-epL"/>
|
||||
<constraint firstAttribute="trailing" secondItem="8DU-2J-HAz" secondAttribute="trailing" id="s7e-Xw-wGe"/>
|
||||
<constraint firstItem="8DU-2J-HAz" firstAttribute="height" secondItem="StY-nr-mRe" secondAttribute="height" multiplier="1/2" id="sBp-BU-UlW"/>
|
||||
<constraint firstItem="b7W-j4-3S1" firstAttribute="height" secondItem="StY-nr-mRe" secondAttribute="height" multiplier="1/2" id="wXF-0d-U9i"/>
|
||||
<constraint firstAttribute="trailing" secondItem="X9c-nY-Re0" secondAttribute="trailing" id="xdd-Qu-mV8"/>
|
||||
<constraint firstItem="hdo-6G-gXy" firstAttribute="top" secondItem="X9c-nY-Re0" secondAttribute="bottom" id="ySw-OZ-TGq"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" id="Gye-4f-x42"/>
|
||||
<simulatedStatusBarMetrics key="simulatedStatusBarMetrics" statusBarStyle="lightContent"/>
|
||||
<connections>
|
||||
<outlet property="closeButton" destination="Yoz-ex-1gK" id="Z51-R1-bmj"/>
|
||||
<outlet property="contactFingerprintLabel" destination="kBW-ix-mdQ" id="RN4-U7-Cpm"/>
|
||||
<outlet property="contactFingerprintTitleLabel" destination="Ii9-7N-hCc" id="adg-hK-fTW"/>
|
||||
<outlet property="contactImageView" destination="HyV-ht-MrM" id="eg1-Cw-B8S"/>
|
||||
<outlet property="infoMyFingerprint" destination="9Wg-UP-VDC" id="78r-JU-b4l"/>
|
||||
<outlet property="infoTheirFingerprint" destination="ge0-8K-A4F" id="DyU-To-aJG"/>
|
||||
<outlet property="myFPBorderView" destination="WhZ-e0-THb" id="SrI-AN-3OJ"/>
|
||||
<outlet property="myFingerprintView" destination="B4o-Rc-z68" id="FjV-Xs-aV8"/>
|
||||
<outlet property="presentationLabel" destination="DV4-GV-ZPf" id="pz1-G0-dVx"/>
|
||||
<outlet property="theirFingerprintView" destination="zFI-eF-Feb" id="UqY-Fb-DLM"/>
|
||||
<outlet property="userFingerprintLabel" destination="e7E-iS-3Oc" id="aR7-ww-NCi"/>
|
||||
<outlet property="userFingerprintTitleLabel" destination="5De-Jq-XWv" id="68F-0n-IMn"/>
|
||||
<outlet property="userImageView" destination="YOs-e5-ee3" id="zC3-Wp-ew3"/>
|
||||
<segue destination="7qX-e8-QDY" kind="modal" identifier="ScanIdentityBarcodeViewSegue" modalTransitionStyle="crossDissolve" id="aSp-qz-VlO"/>
|
||||
<segue destination="in8-UP-6ff" kind="modal" identifier="PresentIdentityQRCodeViewSegue" modalTransitionStyle="crossDissolve" id="mQB-3L-0HK"/>
|
||||
<outlet property="instructionsContainer" destination="B4o-Rc-z68" id="Rc4-wf-8jw"/>
|
||||
<outlet property="instructionsLabel" destination="DV4-GV-ZPf" id="f1p-P7-QOi"/>
|
||||
<outlet property="privacyVerificationFingerprint" destination="e7E-iS-3Oc" id="IA0-ZU-vKJ"/>
|
||||
<outlet property="privacyVerificationQRCode" destination="YOs-e5-ee3" id="Sbg-HQ-tnD"/>
|
||||
<outlet property="privacyVerificationQRCodeFrame" destination="lA7-b4-o6C" id="ngQ-6e-F2W"/>
|
||||
<outlet property="qrCodeCenterConstraint" destination="uHm-ee-HVb" id="8DE-qh-Qif"/>
|
||||
<outlet property="qrContainer" destination="b7W-j4-3S1" id="IpY-w1-yk6"/>
|
||||
<outlet property="qrScanningView" destination="MhA-kC-nBb" id="gNX-7s-wIG"/>
|
||||
<outlet property="scanButton" destination="RX6-CJ-FV1" id="BKY-4g-g3U"/>
|
||||
<outlet property="scanningContainer" destination="8DU-2J-HAz" id="FH9-yo-8uI"/>
|
||||
<outlet property="titleLabel" destination="vR4-Y9-ryx" id="l8Y-0N-eKa"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="sd1-mY-rAe" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
<tapGestureRecognizer id="fRl-Lt-y39">
|
||||
<connections>
|
||||
<action selector="scanFingerprint" destination="urv-62-RsD" id="e0q-jy-keh"/>
|
||||
</connections>
|
||||
</tapGestureRecognizer>
|
||||
<tapGestureRecognizer id="Mg3-ad-PGG">
|
||||
<connections>
|
||||
<action selector="showFingerprint" destination="urv-62-RsD" id="wcQ-Di-UbR"/>
|
||||
</connections>
|
||||
</tapGestureRecognizer>
|
||||
<tapGestureRecognizer id="fRl-Lt-y39"/>
|
||||
<tapGestureRecognizer id="Mg3-ad-PGG"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-1944" y="-2339"/>
|
||||
</scene>
|
||||
|
@ -381,7 +329,7 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
<rect key="frame" x="0.0" y="22" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="hyn-Ss-OAa" id="4XE-JO-Upr">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
|
@ -397,107 +345,6 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
</objects>
|
||||
<point key="canvasLocation" x="-1935.2" y="-1537.8599999999999"/>
|
||||
</scene>
|
||||
<!--Present IdentityQR Code View Controller-->
|
||||
<scene sceneID="b0A-fL-uiD">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="PresentIdentityQRCodeViewController" id="in8-UP-6ff" customClass="PresentIdentityQRCodeViewController" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="EEv-2N-b9z"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="PWz-Os-GfE"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="8fX-rK-XSk">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FVU-rR-RPG">
|
||||
<rect key="frame" x="16" y="510" width="50" height="50"/>
|
||||
<state key="normal" image="quit.png">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<connections>
|
||||
<segue destination="MWg-NL-WXh" kind="unwind" unwindAction="unwindIdentityVerificationCancel:" id="zG6-lN-44J"/>
|
||||
</connections>
|
||||
</button>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="I4l-hR-EdB">
|
||||
<rect key="frame" x="35" y="159" width="250" height="250"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="250" id="WS4-Wb-iXP"/>
|
||||
<constraint firstAttribute="width" constant="250" id="n5C-hu-0F6"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Your Fingerprint" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Psg-eI-6bn">
|
||||
<rect key="frame" x="50" y="130" width="220" height="21"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="220" id="IoY-EK-Qhk"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" weight="heavy" pointSize="17"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstItem="FVU-rR-RPG" firstAttribute="leading" secondItem="8fX-rK-XSk" secondAttribute="leadingMargin" id="4fp-jK-Pgt"/>
|
||||
<constraint firstAttribute="centerX" secondItem="I4l-hR-EdB" secondAttribute="centerX" id="He1-BL-c7O"/>
|
||||
<constraint firstAttribute="centerY" secondItem="I4l-hR-EdB" secondAttribute="centerY" id="dyA-NM-Zc5"/>
|
||||
<constraint firstItem="Psg-eI-6bn" firstAttribute="centerX" secondItem="8fX-rK-XSk" secondAttribute="centerX" id="gFt-YV-WTg"/>
|
||||
<constraint firstItem="PWz-Os-GfE" firstAttribute="top" secondItem="FVU-rR-RPG" secondAttribute="bottom" constant="8" symbolic="YES" id="k4n-8r-ocu"/>
|
||||
<constraint firstItem="I4l-hR-EdB" firstAttribute="top" secondItem="Psg-eI-6bn" secondAttribute="bottom" constant="8.5" id="nyu-mu-lcL"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" id="zty-sG-NJJ"/>
|
||||
<connections>
|
||||
<outlet property="qrCodeView" destination="I4l-hR-EdB" id="Fzf-BD-z9y"/>
|
||||
<outlet property="yourFingerprintLabel" destination="Psg-eI-6bn" id="1Ze-k1-zMv"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="Zk1-cK-ftT" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
<exit id="MWg-NL-WXh" userLabel="Exit" sceneMemberID="exit"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-1495" y="-1940"/>
|
||||
</scene>
|
||||
<!--Scan Identity Barcode View Controller-->
|
||||
<scene sceneID="f84-pF-1is">
|
||||
<objects>
|
||||
<viewController storyboardIdentifier="ScanIdentityBarcodeViewController" id="7qX-e8-QDY" customClass="ScanIdentityBarcodeViewController" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="VoP-Af-AZ2"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="vey-9m-z4V"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="Du7-nD-ScY">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="bag-cN-IZy">
|
||||
<rect key="frame" x="16" y="498" width="50" height="50"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="50" id="Odb-rK-4Va"/>
|
||||
<constraint firstAttribute="height" constant="50" id="ZPA-Mg-Y3j"/>
|
||||
</constraints>
|
||||
<state key="normal" image="quit.png">
|
||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</state>
|
||||
<connections>
|
||||
<segue destination="aQ6-9V-CJA" kind="unwind" unwindAction="unwindIdentityVerificationCancel:" id="bx5-cq-tqn"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstItem="bag-cN-IZy" firstAttribute="leading" secondItem="Du7-nD-ScY" secondAttribute="leadingMargin" id="vL9-x7-knG"/>
|
||||
<constraint firstAttribute="bottom" secondItem="bag-cN-IZy" secondAttribute="bottom" constant="20" symbolic="YES" id="zaD-R1-jw2"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" id="I7H-1E-cUg"/>
|
||||
<connections>
|
||||
<segue destination="aQ6-9V-CJA" kind="unwind" identifier="UnwindToIdentityKeyWasVerifiedSegue" unwindAction="unwindToIdentityKeyWasVerified:" id="Eyg-Zl-I3n"/>
|
||||
</connections>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="VTv-Ry-X99" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
<exit id="aQ6-9V-CJA" userLabel="Exit" sceneMemberID="exit"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-1495" y="-2584"/>
|
||||
</scene>
|
||||
<!--_1.0 Registration Screen-->
|
||||
<scene sceneID="okO-46-HuB">
|
||||
<objects>
|
||||
|
@ -746,7 +593,7 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
<rect key="frame" x="0.0" y="130" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="hpG-pz-GPZ" id="gVo-Nw-ff7" userLabel="Country Code Table Row">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" tag="1" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="United states" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="SDz-Ag-lp3">
|
||||
|
@ -1361,10 +1208,10 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
<color key="backgroundColor" red="0.93725490199999995" green="0.93725490199999995" blue="0.95686274510000002" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="ExistingDevice" rowHeight="72" id="XjV-oU-jSb" customClass="OWSDeviceTableViewCell">
|
||||
<rect key="frame" x="0.0" y="113.5" width="320" height="72"/>
|
||||
<rect key="frame" x="0.0" y="114" width="320" height="72"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="XjV-oU-jSb" id="XqL-QG-IbY">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="71.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="71"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Signal on Chrome" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="57o-uV-YOg">
|
||||
|
@ -1373,13 +1220,13 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Linked: Jun 12, 2016" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uL2-wj-OZr">
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" misplaced="YES" text="Linked: Jun 12, 2016" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uL2-wj-OZr">
|
||||
<rect key="frame" x="17" y="28" width="116" height="17"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleFootnote"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Last Seen: Aug 25, 2016" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Kek-MK-oLy">
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" misplaced="YES" text="Last Seen: Aug 25, 2016" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Kek-MK-oLy">
|
||||
<rect key="frame" x="17" y="45" width="138" height="18"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleFootnote"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
|
@ -1405,21 +1252,21 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="AddNewDevice" textLabel="w80-IJ-E6R" detailTextLabel="8ft-2u-wBF" style="IBUITableViewCellStyleSubtitle" id="6h2-gg-1C6">
|
||||
<rect key="frame" x="0.0" y="185.5" width="320" height="44"/>
|
||||
<rect key="frame" x="0.0" y="186" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="6h2-gg-1C6" id="RKi-c6-pzb">
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Link New Device" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="w80-IJ-E6R">
|
||||
<rect key="frame" x="15" y="5" width="120.5" height="19.5"/>
|
||||
<rect key="frame" x="15" y="4" width="121" height="20"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Scan QR Code" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="8ft-2u-wBF">
|
||||
<rect key="frame" x="15" y="24.5" width="82" height="14.5"/>
|
||||
<rect key="frame" x="15" y="24" width="82" height="15"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleFootnote"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
|
@ -1458,7 +1305,7 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
<rect key="frame" x="0.0" y="64" width="320" height="118"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="5zF-Ko-9qU" id="gr7-Sm-bcs">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="117.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="117"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="1 (708) 000-1234" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ipE-BI-sLL">
|
||||
|
@ -1499,7 +1346,7 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
<rect key="frame" x="0.0" y="182" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="8rk-06-1ZS" id="hqv-P5-du9">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Network Status" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uNq-FV-lwt">
|
||||
|
@ -1539,11 +1386,11 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
<rect key="frame" x="0.0" y="226" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="ITG-sW-Zn0" id="vOb-SA-SH2">
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Privacy" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="i1f-DT-7rL">
|
||||
<rect key="frame" x="15" y="0.0" width="270" height="43.5"/>
|
||||
<rect key="frame" x="15" y="0.0" width="270" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
|
@ -1556,11 +1403,11 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
<rect key="frame" x="0.0" y="270" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="jp5-vZ-AhJ" id="sji-CJ-bhq">
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Notifications" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="tRQ-1p-6aT">
|
||||
<rect key="frame" x="15" y="0.0" width="270" height="43.5"/>
|
||||
<rect key="frame" x="15" y="0.0" width="270" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
|
@ -1573,11 +1420,11 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
<rect key="frame" x="0.0" y="314" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="wZ8-fs-Ylw" id="Ua5-nw-s2z">
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Linked Devices" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hrc-lZ-NeA">
|
||||
<rect key="frame" x="15" y="0.0" width="270" height="43.5"/>
|
||||
<rect key="frame" x="15" y="0.0" width="270" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
|
@ -1593,11 +1440,11 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
<rect key="frame" x="0.0" y="358" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Xx7-pz-aLN" id="pMA-vR-8Ae">
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Advanced" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="dkL-Nz-E6H">
|
||||
<rect key="frame" x="15" y="0.0" width="270" height="43.5"/>
|
||||
<rect key="frame" x="15" y="0.0" width="270" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
|
@ -1610,11 +1457,11 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
<rect key="frame" x="0.0" y="402" width="320" height="44"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="EI4-kQ-MMA" id="czg-5p-aVz">
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="287" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="About" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="qeN-f1-cIQ">
|
||||
<rect key="frame" x="15" y="0.0" width="270" height="43.5"/>
|
||||
<rect key="frame" x="15" y="0.0" width="270" height="43"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
|
@ -1631,7 +1478,7 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
<rect key="frame" x="0.0" y="446" width="320" height="100"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="R82-FT-SEA" id="Ok9-fE-WhB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="99.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="99"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4Mk-ly-6fq">
|
||||
|
@ -1729,7 +1576,7 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Scan the QR code displayed on the device to link." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="3D8-yn-TJ8">
|
||||
<rect key="frame" x="0.0" y="161" width="288" height="20"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
|
@ -1815,7 +1662,7 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
<rect key="frame" x="0.0" y="22" width="320" height="48"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Ld5-sX-pB8" id="EqP-87-4hZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="47.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="47"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="urb-Me-knG">
|
||||
|
@ -1938,11 +1785,11 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
<rect key="frame" x="0.0" y="62" width="320" height="60"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="yfF-Jl-bZ1" id="f0v-od-N9K">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="59.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="59"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="a4j-OQ-ala">
|
||||
<rect key="frame" x="15" y="0.0" width="290" height="59.5"/>
|
||||
<rect key="frame" x="15" y="0.0" width="290" height="59"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="20"/>
|
||||
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
|
@ -2009,10 +1856,10 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
</objects>
|
||||
<point key="canvasLocation" x="-4372" y="-732.72000000000003"/>
|
||||
</scene>
|
||||
<!--Code Scanning View Controller-->
|
||||
<!--Device QR Scanner-->
|
||||
<scene sceneID="f3S-St-vF2">
|
||||
<objects>
|
||||
<viewController id="xDh-Mk-Yo9" customClass="OWSQRCodeScanningViewController" sceneMemberID="viewController">
|
||||
<viewController title="Device QR Scanner" id="xDh-Mk-Yo9" customClass="OWSQRCodeScanningViewController" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="YV9-ra-E3e"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="s4y-gf-WU5"/>
|
||||
|
@ -2027,6 +1874,24 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
</objects>
|
||||
<point key="canvasLocation" x="-1632" y="-3228"/>
|
||||
</scene>
|
||||
<!--Identity QR Scanner-->
|
||||
<scene sceneID="BBm-xb-dFO">
|
||||
<objects>
|
||||
<viewController title="Identity QR Scanner" id="EFG-13-FgR" customClass="OWSQRCodeScanningViewController" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="xM5-Dm-A1I"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="w3c-y6-c5W"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="Z7D-4g-GIf">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="218"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="ExB-N2-kxx" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="-1516" y="-2450"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="_arrow_button" width="12" height="23"/>
|
||||
|
@ -2043,7 +1908,6 @@ A0 09 9A FF A8 8A 09 99</string>
|
|||
<image name="logoSignal" width="138" height="139"/>
|
||||
<image name="mute-active" width="80" height="80"/>
|
||||
<image name="mute-inactive" width="80" height="80"/>
|
||||
<image name="quit.png" width="50" height="50"/>
|
||||
<image name="settings" width="44" height="44"/>
|
||||
<image name="speaker-active" width="80" height="80"/>
|
||||
<image name="speaker-inactive" width="80" height="80"/>
|
||||
|
|
|
@ -398,6 +398,10 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in
|
|||
}
|
||||
|
||||
- (NSString *)nameStringForPhoneIdentifier:(NSString *)identifier {
|
||||
if (!identifier) {
|
||||
return NSLocalizedString(@"UNKNOWN_CONTACT_NAME",
|
||||
@"Displayed if for some reason we can't determine a contacts phone number *or* name");
|
||||
}
|
||||
for (Contact *contact in self.allContacts) {
|
||||
for (PhoneNumber *phoneNumber in contact.parsedPhoneNumbers) {
|
||||
if ([phoneNumber.toE164 isEqualToString:identifier]) {
|
||||
|
@ -405,7 +409,7 @@ void onAddressBookChanged(ABAddressBookRef notifyAddressBook, CFDictionaryRef in
|
|||
}
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
return identifier;
|
||||
}
|
||||
|
||||
- (UIImage *)imageForPhoneIdentifier:(NSString *)identifier {
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
|
||||
#define TXT_CANCEL_TITLE NSLocalizedString(@"TXT_CANCEL_TITLE", @"")
|
||||
#define TXT_SEARCH_PLACEHOLDER_TEXT NSLocalizedString(@"TXT_SEARCH_PLACEHOLDER_TEXT", @"")
|
||||
#define UNKNOWN_CONTACT_NAME NSLocalizedString(@"UNKNOWN_CONTACT_NAME", @"")
|
||||
|
||||
#pragma mark - Inbox View
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
@interface NotificationsManager ()
|
||||
|
||||
@property SystemSoundID newMessageSound;
|
||||
@property (nonatomic, readonly) id<ContactsManagerProtocol> contactsManager;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -33,6 +34,8 @@
|
|||
return self;
|
||||
}
|
||||
|
||||
_contactsManager = [TextSecureKitEnv sharedEnv].contactsManager;
|
||||
|
||||
NSURL *newMessageURL = [[NSBundle mainBundle] URLForResource:@"NewMessage" withExtension:@"aifc"];
|
||||
AudioServicesCreateSystemSoundID((__bridge CFURLRef)newMessageURL, &_newMessageSound);
|
||||
|
||||
|
@ -110,12 +113,7 @@
|
|||
@{Signal_Thread_UserInfo_Key : thread.uniqueId, Signal_Message_UserInfo_Key : message.uniqueId};
|
||||
|
||||
if ([thread isGroupThread]) {
|
||||
NSString *sender =
|
||||
[[TextSecureKitEnv sharedEnv].contactsManager nameStringForPhoneIdentifier:message.authorId];
|
||||
if (!sender) {
|
||||
sender = message.authorId;
|
||||
}
|
||||
|
||||
NSString *sender = [self.contactsManager nameStringForPhoneIdentifier:message.authorId];
|
||||
NSString *threadName = [NSString stringWithFormat:@"\"%@\"", name];
|
||||
notification.alertBody =
|
||||
[NSString stringWithFormat:NSLocalizedString(@"APN_MESSAGE_IN_GROUP_DETAILED", nil),
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
@property UILocalNotification *lastCallNotification;
|
||||
@property (nonatomic, retain) NSMutableArray *currentNotifications;
|
||||
@property (nonatomic) UIBackgroundTaskIdentifier callBackgroundTask;
|
||||
@property (nonatomic, readonly) OWSContactsManager *contactsManager;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -44,17 +45,20 @@
|
|||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.notificationTracker = [NotificationTracker notificationTracker];
|
||||
self.missingPermissionsAlertView =
|
||||
[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"ACTION_REQUIRED_TITLE", @"")
|
||||
message:NSLocalizedString(@"PUSH_SETTINGS_MESSAGE", @"")
|
||||
delegate:nil
|
||||
cancelButtonTitle:NSLocalizedString(@"OK", @"")
|
||||
otherButtonTitles:nil, nil];
|
||||
_callBackgroundTask = UIBackgroundTaskInvalid;
|
||||
self.currentNotifications = [NSMutableArray array];
|
||||
if (!self) {
|
||||
return self;
|
||||
}
|
||||
|
||||
_contactsManager = [Environment getCurrent].contactsManager;
|
||||
_notificationTracker = [NotificationTracker notificationTracker];
|
||||
_missingPermissionsAlertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"ACTION_REQUIRED_TITLE", @"")
|
||||
message:NSLocalizedString(@"PUSH_SETTINGS_MESSAGE", @"")
|
||||
delegate:nil
|
||||
cancelButtonTitle:NSLocalizedString(@"OK", @"")
|
||||
otherButtonTitles:nil, nil];
|
||||
_callBackgroundTask = UIBackgroundTaskInvalid;
|
||||
_currentNotifications = [NSMutableArray array];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
@ -86,9 +90,7 @@
|
|||
UILocalNotification *notification = [[UILocalNotification alloc] init];
|
||||
|
||||
NSString *callerId = call.initiatorNumber.toE164;
|
||||
NSString *nameString = [[Environment getCurrent].contactsManager nameStringForPhoneIdentifier:callerId];
|
||||
|
||||
NSString *displayName = nameString ? nameString : callerId;
|
||||
NSString *displayName = [self.contactsManager nameStringForPhoneIdentifier:callerId];
|
||||
PropertyListPreferences *prefs = [Environment preferences];
|
||||
|
||||
notification.alertBody = @"☎️ ";
|
||||
|
@ -211,7 +213,7 @@
|
|||
} else if ([identifier isEqualToString:Signal_CallBack_Identifier]) {
|
||||
NSString *contactId = notification.userInfo[Signal_Call_UserInfo_Key];
|
||||
PhoneNumber *number = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:contactId];
|
||||
Contact *contact = [[Environment.getCurrent contactsManager] latestContactForPhoneNumber:number];
|
||||
Contact *contact = [self.contactsManager latestContactForPhoneNumber:number];
|
||||
[Environment.phoneManager initiateOutgoingCallToContact:contact atRemoteNumber:number];
|
||||
} else if ([identifier isEqualToString:Signal_Message_MarkAsRead_Identifier]) {
|
||||
[self markAllInThreadAsRead:notification.userInfo completionHandler:completionHandler];
|
||||
|
|
|
@ -6,46 +6,17 @@
|
|||
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "MessagesViewController.h"
|
||||
#import "TSContactThread.h"
|
||||
#import "OWSQRCodeScanningViewController.h"
|
||||
|
||||
@interface FingerprintViewController : UIViewController
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (void)configWithThread:(TSThread *)thread;
|
||||
@class OWSFingerprint;
|
||||
|
||||
@property (nonatomic, strong) IBOutlet UILabel *presentationLabel;
|
||||
@interface FingerprintViewController : UIViewController <OWSQRScannerDelegate>
|
||||
|
||||
@property (nonatomic, strong) IBOutlet UIView *myFingerprintView;
|
||||
@property (nonatomic, strong) IBOutlet UIView *theirFingerprintView;
|
||||
- (void)configureWithFingerprint:(OWSFingerprint *)fingerprint contactName:(NSString *)contactName;
|
||||
- (void)controller:(OWSQRCodeScanningViewController *)controller didDetectQRCodeWithData:(NSData *)data;
|
||||
|
||||
|
||||
@property (nonatomic, strong) IBOutlet UIImageView *contactImageView;
|
||||
@property (nonatomic, strong) IBOutlet UILabel *contactFingerprintTitleLabel;
|
||||
@property (nonatomic, strong) IBOutlet UILabel *contactFingerprintLabel;
|
||||
|
||||
@property (nonatomic, strong) IBOutlet UIImageView *userImageView;
|
||||
@property (nonatomic, strong) IBOutlet UILabel *userFingerprintTitleLabel;
|
||||
@property (nonatomic, strong) IBOutlet UILabel *userFingerprintLabel;
|
||||
|
||||
@property (nonatomic, strong) IBOutlet UILabel *infoMyFingerprint;
|
||||
@property (nonatomic, strong) IBOutlet UILabel *infoTheirFingerprint;
|
||||
@property (nonatomic, strong) IBOutlet UIImageView *infoArrowTop;
|
||||
@property (nonatomic, strong) IBOutlet UIImageView *infoArrowBottom;
|
||||
|
||||
@property (nonatomic, strong) IBOutlet UIButton *closeButton;
|
||||
@property (nonatomic, strong) IBOutlet UIView *myFPBorderView;
|
||||
|
||||
|
||||
// returns my public identity key as NSData
|
||||
- (NSData *)getMyPublicIdentityKey;
|
||||
// returns recipient's public identity key as NSData
|
||||
- (NSData *)getTheirPublicIdentityKey;
|
||||
|
||||
// This is called when the recipient's public key is verified. Later can be used to mark as such if we want a step above
|
||||
// TOFU in UX.
|
||||
- (IBAction)unwindToIdentityKeyWasVerified:(UIStoryboardSegue *)segue;
|
||||
// Just a cancelation of the user's request to verify reciepient fingerprint or have their fingerprint verified by
|
||||
// recipient
|
||||
- (IBAction)unwindIdentityVerificationCancel:(UIStoryboardSegue *)segue;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -7,102 +7,112 @@
|
|||
//
|
||||
|
||||
#import "FingerprintViewController.h"
|
||||
|
||||
#import <25519/Curve25519.h>
|
||||
#import <AxolotlKit/NSData+keyVersionByte.h>
|
||||
#import "DJWActionSheet+OWS.h"
|
||||
#import "PresentIdentityQRCodeViewController.h"
|
||||
#import "ScanIdentityBarcodeViewController.h"
|
||||
#import "SignalsNavigationController.h"
|
||||
#import <SignalServiceKit/OWSFingerprint.h>
|
||||
#import <SignalServiceKit/TSStorageManager+IdentityKeyStore.h>
|
||||
#import <SignalServiceKit/TSStorageManager+SessionStore.h>
|
||||
#import <SignalServiceKit/TSStorageManager+keyingMaterial.h>
|
||||
|
||||
#import "TSFingerprintGenerator.h"
|
||||
#import "TSStorageHeaders.h"
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FingerprintViewController ()
|
||||
@property TSContactThread *thread;
|
||||
@property (nonatomic) BOOL isPresentingDialog;
|
||||
@end
|
||||
|
||||
static NSString *const kPresentIdentityQRCodeViewSegue = @"PresentIdentityQRCodeViewSegue";
|
||||
static NSString *const kScanIdentityBarcodeViewSegue = @"ScanIdentityBarcodeViewSegue";
|
||||
@property (strong, nonatomic) TSStorageManager *storageManager;
|
||||
@property (nonatomic) BOOL isPresentingDialog;
|
||||
@property (strong, atomic) OWSFingerprint *fingerprint;
|
||||
@property (strong, atomic) NSString *contactName;
|
||||
@property (strong, nonatomic) OWSQRCodeScanningViewController *qrScanningController;
|
||||
|
||||
@property (strong, nonatomic) IBOutlet UIView *qrScanningView;
|
||||
@property (strong, nonatomic) IBOutlet UIView *scanningContainer;
|
||||
@property (strong, nonatomic) IBOutlet UIView *instructionsContainer;
|
||||
@property (strong, nonatomic) IBOutlet UIView *qrContainer;
|
||||
@property (strong, nonatomic) IBOutlet UIView *privacyVerificationQRCodeFrame;
|
||||
@property (strong, nonatomic) IBOutlet UIImageView *privacyVerificationQRCode;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *privacyVerificationFingerprint;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *instructionsLabel;
|
||||
@property (strong, nonatomic) IBOutlet UILabel *titleLabel;
|
||||
@property (strong, nonatomic) IBOutlet UIButton *scanButton;
|
||||
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *qrCodeCenterConstraint;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FingerprintViewController
|
||||
|
||||
- (void)configWithThread:(TSThread *)thread {
|
||||
self.thread = (TSContactThread *)thread;
|
||||
- (void)configureWithFingerprint:(OWSFingerprint *)fingerprint contactName:(NSString *)contactName
|
||||
{
|
||||
self.fingerprint = fingerprint;
|
||||
self.contactName = contactName;
|
||||
}
|
||||
|
||||
|
||||
- (void)viewDidLoad {
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
[self.view setAlpha:0];
|
||||
self.storageManager = [TSStorageManager sharedManager];
|
||||
self.qrScanningView.hidden = YES;
|
||||
|
||||
// HACK to get full width preview layer
|
||||
CGRect oldFrame = self.qrScanningView.frame;
|
||||
CGRect newFrame = CGRectMake(oldFrame.origin.x,
|
||||
oldFrame.origin.y,
|
||||
self.view.frame.size.width,
|
||||
self.view.frame.size.height / 2.0f - oldFrame.origin.y);
|
||||
self.qrScanningView.frame = newFrame;
|
||||
// END HACK to get full width preview layer
|
||||
|
||||
self.titleLabel.text = NSLocalizedString(@"PRIVACY_VERIFICATION_TITLE", @"Navbar title");
|
||||
NSString *instructionsFormat = NSLocalizedString(@"PRIVACY_VERIFICATION_INSTRUCTIONS",
|
||||
@"Paragraph(s) shown alongside keying material when verifying privacy with {{contact name}}");
|
||||
self.instructionsLabel.text = [NSString stringWithFormat:instructionsFormat, self.contactName];
|
||||
|
||||
self.scanButton.titleLabel.text = NSLocalizedString(@"SCAN_CODE_ACTION",
|
||||
@"Button label presented with camera icon while verifying privacy credentials. Shows the camera interface.");
|
||||
|
||||
// Safety numbers and QR Code
|
||||
self.privacyVerificationFingerprint.text = self.fingerprint.displayableText;
|
||||
self.privacyVerificationQRCode.image = self.fingerprint.image;
|
||||
|
||||
// Don't antialias QRCode
|
||||
self.privacyVerificationQRCode.layer.magnificationFilter = kCAFilterNearest;
|
||||
|
||||
// Add session reset action.
|
||||
UILongPressGestureRecognizer *longpressToResetSession =
|
||||
[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(shredAndDelete:)];
|
||||
[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(didLongpressToResetSession:)];
|
||||
longpressToResetSession.minimumPressDuration = 1.0;
|
||||
[self.view addGestureRecognizer:longpressToResetSession];
|
||||
_infoTheirFingerprint.text = NSLocalizedString(@"FINGERPRINT_INFO_THEIRS", @"");
|
||||
_infoMyFingerprint.text = NSLocalizedString(@"FINGERPRINT_INFO_YOURS", @"");
|
||||
_presentationLabel.text = NSLocalizedString(@"FINGERPRINT_INFO_ABOUT", @"");
|
||||
_userFingerprintTitleLabel.text = NSLocalizedString(@"FINGERPRINT_YOURS", @"");
|
||||
}
|
||||
|
||||
if ([UIScreen mainScreen].bounds.size.height <= 480) {
|
||||
self.presentationLabel.hidden = YES;
|
||||
self.myFPBorderView.hidden = YES;
|
||||
- (void)viewDidLayoutSubviews
|
||||
{
|
||||
[super viewDidLayoutSubviews];
|
||||
|
||||
self.privacyVerificationQRCodeFrame.layer.masksToBounds = YES;
|
||||
self.privacyVerificationQRCodeFrame.layer.cornerRadius = self.privacyVerificationQRCodeFrame.frame.size.height / 2;
|
||||
}
|
||||
|
||||
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(nullable id)sender
|
||||
{
|
||||
if ([segue.identifier isEqualToString:@"embedIdentityQRScanner"]) {
|
||||
OWSQRCodeScanningViewController *qrScanningController
|
||||
= (OWSQRCodeScanningViewController *)segue.destinationViewController;
|
||||
self.qrScanningController = qrScanningController;
|
||||
qrScanningController.scanDelegate = self;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
[self setTheirKeyInformation];
|
||||
|
||||
NSData *myPublicKey = [[TSStorageManager sharedManager] identityKeyPair].publicKey;
|
||||
self.userFingerprintLabel.text = [TSFingerprintGenerator getFingerprintForDisplay:myPublicKey];
|
||||
|
||||
[UIView animateWithDuration:0.6
|
||||
delay:0.
|
||||
options:UIViewAnimationOptionCurveEaseInOut
|
||||
animations:^{
|
||||
[self.view setAlpha:1];
|
||||
}
|
||||
completion:nil];
|
||||
}
|
||||
|
||||
- (void)setTheirKeyInformation {
|
||||
self.contactFingerprintTitleLabel.text = self.thread.name;
|
||||
NSData *identityKey = [[TSStorageManager sharedManager] identityKeyForRecipientId:self.thread.contactIdentifier];
|
||||
self.contactFingerprintLabel.text = [TSFingerprintGenerator getFingerprintForDisplay:identityKey];
|
||||
|
||||
if ([self.contactFingerprintLabel.text length] == 0) {
|
||||
// no fingerprint, hide this view
|
||||
_presentationLabel.hidden = YES;
|
||||
_theirFingerprintView.hidden = YES;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSData *)getMyPublicIdentityKey {
|
||||
return [[TSStorageManager sharedManager] identityKeyPair].publicKey;
|
||||
}
|
||||
|
||||
- (NSData *)getTheirPublicIdentityKey {
|
||||
return [[TSStorageManager sharedManager] identityKeyForRecipientId:self.thread.contactIdentifier];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Action
|
||||
- (IBAction)closeButtonAction:(id)sender {
|
||||
[UIView animateWithDuration:0.6
|
||||
delay:0.
|
||||
options:UIViewAnimationOptionCurveEaseInOut
|
||||
animations:^{
|
||||
[self.view setAlpha:0];
|
||||
}
|
||||
completion:^(BOOL succeeded) {
|
||||
[self dismissViewControllerAnimated:NO completion:nil];
|
||||
}];
|
||||
- (IBAction)closeButtonAction:(id)sender
|
||||
{
|
||||
[self dismissViewControllerAnimated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (IBAction)didTouchUpInsideScanButton:(id)sender
|
||||
{
|
||||
[self showScanner];
|
||||
}
|
||||
|
||||
- (IBAction)shredAndDelete:(id)sender {
|
||||
- (IBAction)didLongpressToResetSession:(id)sender
|
||||
{
|
||||
if (!_isPresentingDialog) {
|
||||
_isPresentingDialog = YES;
|
||||
[DJWActionSheet showInView:self.view
|
||||
|
@ -119,7 +129,7 @@ static NSString *const kScanIdentityBarcodeViewSegue = @"ScanIdentityBarcodeVi
|
|||
} else {
|
||||
switch (tappedButtonIndex) {
|
||||
case 0:
|
||||
[self shredKeyingMaterial];
|
||||
[self resetSession];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -129,57 +139,117 @@ static NSString *const kScanIdentityBarcodeViewSegue = @"ScanIdentityBarcodeVi
|
|||
}
|
||||
}
|
||||
|
||||
- (void)showScanner
|
||||
{
|
||||
DDLogInfo(@"%@ Showing Scanner", self.tag);
|
||||
self.qrScanningView.hidden = NO;
|
||||
|
||||
- (IBAction)showFingerprint {
|
||||
[self performSegueWithIdentifier:kPresentIdentityQRCodeViewSegue sender:self];
|
||||
// Recommended before animating a constraint.
|
||||
[self.view layoutIfNeeded];
|
||||
|
||||
// Shift QRCode up within it's own frame, while shifting it's whole
|
||||
// frame down.
|
||||
self.qrCodeCenterConstraint.constant = 0.0f;
|
||||
[UIView animateWithDuration:0.4
|
||||
delay:0.0
|
||||
options:UIViewAnimationOptionCurveEaseInOut
|
||||
animations:^{
|
||||
|
||||
self.scanningContainer.frame = self.qrContainer.frame;
|
||||
self.qrContainer.frame = self.instructionsContainer.frame;
|
||||
self.instructionsContainer.alpha = 0.0f;
|
||||
// animate constraint smoothly
|
||||
[self.view layoutIfNeeded];
|
||||
}
|
||||
completion:nil];
|
||||
|
||||
[self.qrScanningController startCapture];
|
||||
}
|
||||
|
||||
|
||||
- (IBAction)scanFingerprint {
|
||||
[self performSegueWithIdentifier:kScanIdentityBarcodeViewSegue sender:self];
|
||||
- (void)resetSession
|
||||
{
|
||||
[self.storageManager removeIdentityKeyForRecipient:self.fingerprint.theirStableId];
|
||||
[self.storageManager deleteAllSessionsForContact:self.fingerprint.theirStableId];
|
||||
}
|
||||
|
||||
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
|
||||
if ([[segue identifier] isEqualToString:kPresentIdentityQRCodeViewSegue]) {
|
||||
[segue.destinationViewController setIdentityKey:[[self getMyPublicIdentityKey] prependKeyType]];
|
||||
} else if ([[segue identifier] isEqualToString:kScanIdentityBarcodeViewSegue]) {
|
||||
[segue.destinationViewController setIdentityKey:[[self getTheirPublicIdentityKey] prependKeyType]];
|
||||
// pragma mark - OWSQRScannerDelegate
|
||||
- (void)controller:(OWSQRCodeScanningViewController *)controller didDetectQRCodeWithData:(NSData *)data;
|
||||
{
|
||||
[self verifyCombinedFingerprintData:data];
|
||||
}
|
||||
|
||||
- (void)verifyCombinedFingerprintData:(NSData *)combinedFingerprintData
|
||||
{
|
||||
NSError *error;
|
||||
if ([self.fingerprint matchesCombinedFingerprintData:combinedFingerprintData error:&error]) {
|
||||
DDLogInfo(@"%@ Successfully verified privacy.", self.tag);
|
||||
NSString *successTitle = NSLocalizedString(@"SUCCESSFUL_VERIFICATION_TITLE", nil);
|
||||
NSString *dismissText = NSLocalizedString(@"DISMISS_BUTTON_TEXT", nil);
|
||||
NSString *descriptionFormat = NSLocalizedString(
|
||||
@"SUCCESSFUL_VERIFICATION_DESCRIPTION", @"Alert body after verifying privacy with {{other user's name}}");
|
||||
NSString *successDescription = [NSString stringWithFormat:descriptionFormat, self.contactName];
|
||||
UIAlertController *successAlertController =
|
||||
[UIAlertController alertControllerWithTitle:successTitle
|
||||
message:successDescription
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
UIAlertAction *dismissAction =
|
||||
[UIAlertAction actionWithTitle:dismissText
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
[self dismissViewControllerAnimated:YES completion:nil];
|
||||
}];
|
||||
[successAlertController addAction:dismissAction];
|
||||
|
||||
[self presentViewController:successAlertController animated:YES completion:nil];
|
||||
} else {
|
||||
[self failVerificationWithError:error];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)failVerificationWithError:(NSError *)error
|
||||
{
|
||||
NSString *failureTitle = NSLocalizedString(@"FAILED_VERIFICATION_TITLE", @"alert title");
|
||||
UIAlertController *failureAlertController =
|
||||
[UIAlertController alertControllerWithTitle:failureTitle
|
||||
message:error.localizedDescription
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
- (IBAction)unwindToIdentityKeyWasVerified:(UIStoryboardSegue *)segue {
|
||||
// Can later be used to mark identity key as verified if we want step above TOFU in UX
|
||||
NSString *cancelText = NSLocalizedString(@"TXT_CANCEL_TITLE", nil);
|
||||
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:cancelText
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction *_Nonnull action) {
|
||||
[self dismissViewControllerAnimated:YES completion:nil];
|
||||
}];
|
||||
[failureAlertController addAction:cancelAction];
|
||||
|
||||
// TODO
|
||||
// NSString retryText = NSLocalizedString(@"RETRY_BUTTON_TEXT", nil);
|
||||
// UIAlertAction *retryAction = [UIAlertAction actionWithTitle:retryText style:UIAlertActionStyleDefault
|
||||
// handler:^(UIAlertAction * _Nonnull action) {
|
||||
//
|
||||
// }];
|
||||
// [failureAlertController addAction:retryAction];
|
||||
[self presentViewController:failureAlertController animated:YES completion:nil];
|
||||
|
||||
DDLogWarn(@"%@ Identity verification failed with error: %@", self.tag, error);
|
||||
}
|
||||
|
||||
|
||||
- (IBAction)unwindIdentityVerificationCancel:(UIStoryboardSegue *)segue {
|
||||
DDLogDebug(@"action cancelled");
|
||||
// Can later be used to mark identity key as verified if we want step above TOFU in UX
|
||||
- (void)dismissViewControllerAnimated:(BOOL)flag completion:(nullable void (^)(void))completion
|
||||
{
|
||||
self.qrScanningView.hidden = YES;
|
||||
[super dismissViewControllerAnimated:flag completion:completion];
|
||||
}
|
||||
|
||||
#pragma mark - Shredding & Deleting
|
||||
|
||||
- (void)shredKeyingMaterial {
|
||||
[[TSStorageManager sharedManager] removeIdentityKeyForRecipient:self.thread.contactIdentifier];
|
||||
[[TSStorageManager sharedManager] deleteAllSessionsForContact:self.thread.contactIdentifier];
|
||||
[self setTheirKeyInformation];
|
||||
+ (NSString *)tag
|
||||
{
|
||||
return [NSString stringWithFormat:@"[%@]", self.class];
|
||||
}
|
||||
|
||||
- (void)shredDiscussionsWithContact {
|
||||
UINavigationController *nVC = (UINavigationController *)self.presentingViewController;
|
||||
for (UIViewController __strong *vc in nVC.viewControllers) {
|
||||
if ([vc isKindOfClass:[MessagesViewController class]]) {
|
||||
vc = nil;
|
||||
}
|
||||
}
|
||||
|
||||
[self.thread remove]; // this removes the thread and all it's discussion (YapDatabaseRelationships)
|
||||
__block SignalsNavigationController *vc = (SignalsNavigationController *)[self presentingViewController];
|
||||
[vc dismissViewControllerAnimated:YES
|
||||
completion:^{
|
||||
[vc popToRootViewControllerAnimated:YES];
|
||||
}];
|
||||
- (NSString *)tag
|
||||
{
|
||||
return self.class.tag;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#import "SignalKeyingStorage.h"
|
||||
#import "TSAttachmentPointer.h"
|
||||
#import "TSCall.h"
|
||||
#import "TSContactThread.h"
|
||||
#import "TSContentAdapters.h"
|
||||
#import "TSDatabaseView.h"
|
||||
#import "TSErrorMessage.h"
|
||||
|
@ -49,6 +50,7 @@
|
|||
#import <JSQSystemSoundPlayer.h>
|
||||
#import <MobileCoreServices/UTCoreTypes.h>
|
||||
#import <SignalServiceKit/MimeTypeUtil.h>
|
||||
#import <SignalServiceKit/OWSFingerprint.h>
|
||||
#import <SignalServiceKit/SignalRecipient.h>
|
||||
#import <SignalServiceKit/TSAccountManager.h>
|
||||
#import <YapDatabase/YapDatabaseView.h>
|
||||
|
@ -98,14 +100,16 @@ typedef enum : NSUInteger {
|
|||
@property (nonatomic, retain) UIButton *attachButton;
|
||||
|
||||
@property (nonatomic, retain) NSIndexPath *lastDeliveredMessageIndexPath;
|
||||
@property (nonatomic, retain) UIGestureRecognizer *showFingerprintDisplay;
|
||||
@property (nonatomic, retain) UITapGestureRecognizer *toggleContactPhoneDisplay;
|
||||
@property (nonatomic, retain) UIGestureRecognizer *showFingerprintGesture;
|
||||
@property (nonatomic, retain) UITapGestureRecognizer *toggleContactPhoneGesture;
|
||||
@property (nonatomic) BOOL displayPhoneAsTitle;
|
||||
|
||||
@property NSUInteger page;
|
||||
@property (nonatomic) BOOL composeOnOpen;
|
||||
@property (nonatomic) BOOL peek;
|
||||
|
||||
@property (nonatomic, readonly) TSStorageManager *storageManager;
|
||||
@property (nonatomic, readonly) OWSContactsManager *contactsManager;
|
||||
@property NSCache *messageAdapterCache;
|
||||
|
||||
@end
|
||||
|
@ -122,6 +126,32 @@ typedef enum : NSUInteger {
|
|||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (!self) {
|
||||
return self;
|
||||
}
|
||||
|
||||
_contactsManager = [[Environment getCurrent] contactsManager];
|
||||
_storageManager = [TSStorageManager sharedManager];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)aDecoder
|
||||
{
|
||||
self = [super initWithCoder:aDecoder];
|
||||
if (!self) {
|
||||
return self;
|
||||
}
|
||||
|
||||
_contactsManager = [[Environment getCurrent] contactsManager];
|
||||
_storageManager = [TSStorageManager sharedManager];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)peekSetup {
|
||||
_peek = YES;
|
||||
[self setComposeOnOpen:NO];
|
||||
|
@ -187,12 +217,11 @@ typedef enum : NSUInteger {
|
|||
|
||||
self.messageAdapterCache = [[NSCache alloc] init];
|
||||
|
||||
_showFingerprintDisplay =
|
||||
self.showFingerprintGesture =
|
||||
[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(showFingerprint)];
|
||||
|
||||
_toggleContactPhoneDisplay =
|
||||
self.toggleContactPhoneGesture =
|
||||
[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(toggleContactPhone)];
|
||||
_toggleContactPhoneDisplay.numberOfTapsRequired = 1;
|
||||
|
||||
_attachButton = [[UIButton alloc] init];
|
||||
[_attachButton setFrame:CGRectMake(0,
|
||||
|
@ -521,8 +550,8 @@ typedef enum : NSUInteger {
|
|||
if ([label.text isEqualToString:self.title]) {
|
||||
[self.navView setUserInteractionEnabled:YES];
|
||||
[aView setUserInteractionEnabled:YES];
|
||||
[aView addGestureRecognizer:_showFingerprintDisplay];
|
||||
[aView addGestureRecognizer:_toggleContactPhoneDisplay];
|
||||
[aView addGestureRecognizer:self.showFingerprintGesture];
|
||||
[aView addGestureRecognizer:self.toggleContactPhoneGesture];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -542,8 +571,8 @@ typedef enum : NSUInteger {
|
|||
if ([label.text isEqualToString:self.title]) {
|
||||
[self.navView setUserInteractionEnabled:NO];
|
||||
[aView setUserInteractionEnabled:NO];
|
||||
[aView removeGestureRecognizer:_showFingerprintDisplay];
|
||||
[aView removeGestureRecognizer:_toggleContactPhoneDisplay];
|
||||
[aView removeGestureRecognizer:self.showFingerprintGesture];
|
||||
[aView removeGestureRecognizer:self.toggleContactPhoneGesture];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -581,9 +610,25 @@ typedef enum : NSUInteger {
|
|||
|
||||
#pragma mark - Fingerprints
|
||||
|
||||
- (void)showFingerprint {
|
||||
- (void)showFingerprint
|
||||
{
|
||||
// Show fingerprint for their most recently accepted identity
|
||||
NSString *theirSignalId = self.thread.contactIdentifier;
|
||||
NSData *theirIdentityKey = [self.storageManager identityKeyForRecipientId:theirSignalId];
|
||||
[self showFingerprintWithTheirIdentityKey:theirIdentityKey theirSignalId:theirSignalId];
|
||||
}
|
||||
|
||||
- (void)showFingerprintWithTheirIdentityKey:(NSData *)theirIdentityKey theirSignalId:(NSString *)theirSignalId
|
||||
{
|
||||
NSString *mySignalId = [self.storageManager localNumber];
|
||||
NSData *myIdentityKey = [self.storageManager identityKeyPair].publicKey;
|
||||
OWSFingerprint *fingerprint = [OWSFingerprint fingerprintWithMyStableId:mySignalId
|
||||
myIdentityKey:myIdentityKey
|
||||
theirStableId:theirSignalId
|
||||
theirIdentityKey:theirIdentityKey];
|
||||
|
||||
[self markAllMessagesAsRead];
|
||||
[self performSegueWithIdentifier:kFingerprintSegueIdentifier sender:self];
|
||||
[self performSegueWithIdentifier:kFingerprintSegueIdentifier sender:fingerprint];
|
||||
}
|
||||
|
||||
|
||||
|
@ -591,8 +636,7 @@ typedef enum : NSUInteger {
|
|||
_displayPhoneAsTitle = !_displayPhoneAsTitle;
|
||||
|
||||
if (!_thread.isGroupThread) {
|
||||
Contact *contact =
|
||||
[[[Environment getCurrent] contactsManager] latestContactForPhoneNumber:[self phoneNumberForThread]];
|
||||
Contact *contact = [self.contactsManager latestContactForPhoneNumber:[self phoneNumberForThread]];
|
||||
if (!contact) {
|
||||
if (!(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(NSFoundationVersionNumber_iOS_9))) {
|
||||
ABUnknownPersonViewController *view = [[ABUnknownPersonViewController alloc] init];
|
||||
|
@ -614,7 +658,7 @@ typedef enum : NSUInteger {
|
|||
[self.navigationController pushViewController:view animated:YES];
|
||||
}
|
||||
} else {
|
||||
CNContactStore *contactStore = [Environment getCurrent].contactsManager.contactStore;
|
||||
CNContactStore *contactStore = self.contactsManager.contactStore;
|
||||
|
||||
CNMutableContact *cncontact = [[CNMutableContact alloc] init];
|
||||
cncontact.phoneNumbers = @[
|
||||
|
@ -697,7 +741,7 @@ typedef enum : NSUInteger {
|
|||
- (void)callAction {
|
||||
if ([self canCall]) {
|
||||
PhoneNumber *number = [self phoneNumberForThread];
|
||||
Contact *contact = [[Environment.getCurrent contactsManager] latestContactForPhoneNumber:number];
|
||||
Contact *contact = [self.contactsManager latestContactForPhoneNumber:number];
|
||||
[Environment.phoneManager initiateOutgoingCallToContact:contact atRemoteNumber:number];
|
||||
} else {
|
||||
DDLogWarn(@"Tried to initiate a call but thread is not callable.");
|
||||
|
@ -1023,8 +1067,7 @@ typedef enum : NSUInteger {
|
|||
}
|
||||
|
||||
if ([self.thread isKindOfClass:[TSGroupThread class]]) {
|
||||
NSString *name = [[Environment getCurrent].contactsManager nameStringForPhoneIdentifier:msg.senderId];
|
||||
name = name ? name : msg.senderId;
|
||||
NSString *name = [self.contactsManager nameStringForPhoneIdentifier:msg.senderId];
|
||||
|
||||
if (!name) {
|
||||
name = @"";
|
||||
|
@ -1391,75 +1434,72 @@ typedef enum : NSUInteger {
|
|||
}];
|
||||
}
|
||||
|
||||
- (void)handleErrorMessageTap:(TSErrorMessage *)message {
|
||||
- (void)handleErrorMessageTap:(TSErrorMessage *)message
|
||||
{
|
||||
if ([message isKindOfClass:[TSInvalidIdentityKeyErrorMessage class]]) {
|
||||
TSInvalidIdentityKeyErrorMessage *errorMessage = (TSInvalidIdentityKeyErrorMessage *)message;
|
||||
NSString *newKeyFingerprint = [errorMessage newIdentityFingerprint];
|
||||
|
||||
NSString *keyOwner;
|
||||
if ([message isKindOfClass:[TSInvalidIdentityKeySendingErrorMessage class]]) {
|
||||
TSInvalidIdentityKeySendingErrorMessage *m = (TSInvalidIdentityKeySendingErrorMessage *)message;
|
||||
keyOwner = [[[Environment getCurrent] contactsManager] nameStringForPhoneIdentifier:m.recipientId];
|
||||
} else {
|
||||
keyOwner = [self.thread name];
|
||||
}
|
||||
|
||||
NSString *messageString = [NSString
|
||||
stringWithFormat:NSLocalizedString(@"ACCEPT_IDENTITYKEY_QUESTION", @""), keyOwner, newKeyFingerprint];
|
||||
NSArray *actions = @[
|
||||
NSLocalizedString(@"ACCEPT_IDENTITYKEY_BUTTON", @""),
|
||||
NSLocalizedString(@"COPY_IDENTITYKEY_BUTTON", @"")
|
||||
];
|
||||
|
||||
[self dismissKeyBoard];
|
||||
|
||||
[DJWActionSheet showInView:self.parentViewController.view
|
||||
withTitle:messageString
|
||||
cancelButtonTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"")
|
||||
destructiveButtonTitle:NSLocalizedString(@"TXT_DELETE_TITLE", @"")
|
||||
otherButtonTitles:actions
|
||||
tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) {
|
||||
if (tappedButtonIndex == actionSheet.cancelButtonIndex) {
|
||||
DDLogDebug(@"User Cancelled");
|
||||
} else if (tappedButtonIndex == actionSheet.destructiveButtonIndex) {
|
||||
[self.editingDatabaseConnection
|
||||
readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) {
|
||||
[message removeWithTransaction:transaction];
|
||||
}];
|
||||
} else {
|
||||
switch (tappedButtonIndex) {
|
||||
case 0:
|
||||
[errorMessage acceptNewIdentityKey];
|
||||
break;
|
||||
case 1:
|
||||
[[UIPasteboard generalPasteboard] setString:newKeyFingerprint];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}];
|
||||
[self tappedInvalidIdentityKeyErrorMessage:(TSInvalidIdentityKeyErrorMessage *)message];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)tappedInvalidIdentityKeyErrorMessage:(TSInvalidIdentityKeyErrorMessage *)errorMessage
|
||||
{
|
||||
NSString *keyOwner = [self.contactsManager nameStringForPhoneIdentifier:errorMessage.theirSignalId];
|
||||
NSString *titleFormat = NSLocalizedString(@"SAFETY_NUMBERS_ACTIONSHEET_TITLE", @"Action sheet heading");
|
||||
NSString *titleText = [NSString stringWithFormat:titleFormat, keyOwner];
|
||||
NSArray *actions = @[
|
||||
NSLocalizedString(@"SHOW_SAFETY_NUMBER_ACTION", @"Action sheet item"),
|
||||
NSLocalizedString(@"ACCEPT_NEW_IDENTITY_ACTION", @"Action sheet item")
|
||||
];
|
||||
|
||||
[self dismissKeyBoard];
|
||||
|
||||
[DJWActionSheet showInView:self.parentViewController.view
|
||||
withTitle:titleText
|
||||
cancelButtonTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", @"")
|
||||
destructiveButtonTitle:nil
|
||||
otherButtonTitles:actions
|
||||
tapBlock:^(DJWActionSheet *actionSheet, NSInteger tappedButtonIndex) {
|
||||
if (tappedButtonIndex == actionSheet.cancelButtonIndex) {
|
||||
DDLogDebug(@"%@ Remote Key Changed actions: Tapped cancel", self.tag);
|
||||
} else {
|
||||
switch (tappedButtonIndex) {
|
||||
case 0:
|
||||
DDLogInfo(@"%@ Remote Key Changed actions: Show fingerprint display", self.tag);
|
||||
[self showFingerprintWithTheirIdentityKey:errorMessage.newIdentityKey
|
||||
theirSignalId:errorMessage.theirSignalId];
|
||||
break;
|
||||
case 1:
|
||||
DDLogInfo(@"%@ Remote Key Changed actions: Accepted new identity key", self.tag);
|
||||
[errorMessage acceptNewIdentityKey];
|
||||
break;
|
||||
default:
|
||||
DDLogInfo(@"%@ Remote Key Changed actions: Unhandled button pressed: %d",
|
||||
self.tag,
|
||||
(int)tappedButtonIndex);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Navigation
|
||||
|
||||
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
|
||||
if ([segue.identifier isEqualToString:kFingerprintSegueIdentifier]) {
|
||||
FingerprintViewController *vc = [segue destinationViewController];
|
||||
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
[vc configWithThread:self.thread];
|
||||
}];
|
||||
if ([sender isKindOfClass:[OWSFingerprint class]]) {
|
||||
OWSFingerprint *fingerprint = (OWSFingerprint *)sender;
|
||||
NSString *contactName = [self.contactsManager nameStringForPhoneIdentifier:fingerprint.theirStableId];
|
||||
[vc configureWithFingerprint:fingerprint contactName:contactName];
|
||||
} else {
|
||||
DDLogError(@"%@ Attempting to segueu to fingerprint VC without a valid fingerprint: %@", self.tag, sender);
|
||||
}
|
||||
} else if ([segue.identifier isEqualToString:kUpdateGroupSegueIdentifier]) {
|
||||
NewGroupViewController *vc = [segue destinationViewController];
|
||||
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
[vc configWithThread:(TSGroupThread *)self.thread];
|
||||
}];
|
||||
[vc configWithThread:(TSGroupThread *)self.thread];
|
||||
} else if ([segue.identifier isEqualToString:kShowGroupMembersSegue]) {
|
||||
ShowGroupMembersViewController *vc = [segue destinationViewController];
|
||||
[self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) {
|
||||
[vc configWithThread:(TSGroupThread *)self.thread];
|
||||
}];
|
||||
[vc configWithThread:(TSGroupThread *)self.thread];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1715,7 +1755,7 @@ typedef enum : NSUInteger {
|
|||
- (YapDatabaseConnection *)uiDatabaseConnection {
|
||||
NSAssert([NSThread isMainThread], @"Must access uiDatabaseConnection on main thread!");
|
||||
if (!_uiDatabaseConnection) {
|
||||
_uiDatabaseConnection = [[TSStorageManager sharedManager] newDatabaseConnection];
|
||||
_uiDatabaseConnection = [self.storageManager newDatabaseConnection];
|
||||
[_uiDatabaseConnection beginLongLivedReadTransaction];
|
||||
}
|
||||
return _uiDatabaseConnection;
|
||||
|
@ -1723,7 +1763,7 @@ typedef enum : NSUInteger {
|
|||
|
||||
- (YapDatabaseConnection *)editingDatabaseConnection {
|
||||
if (!_editingDatabaseConnection) {
|
||||
_editingDatabaseConnection = [[TSStorageManager sharedManager] newDatabaseConnection];
|
||||
_editingDatabaseConnection = [self.storageManager newDatabaseConnection];
|
||||
}
|
||||
return _editingDatabaseConnection;
|
||||
}
|
||||
|
@ -2142,4 +2182,14 @@ typedef enum : NSUInteger {
|
|||
return @[];
|
||||
}
|
||||
|
||||
+ (NSString *)tag
|
||||
{
|
||||
return [NSString stringWithFormat:@"[%@]", self.class];
|
||||
}
|
||||
|
||||
- (NSString *)tag
|
||||
{
|
||||
return self.class.tag;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -8,4 +8,6 @@
|
|||
|
||||
@property OWSLinkedDevicesTableViewController *linkedDevicesTableViewController;
|
||||
|
||||
- (void)controller:(OWSQRCodeScanningViewController *)controller didDetectQRCodeWithString:(NSString *)string;
|
||||
|
||||
@end
|
||||
|
|
|
@ -28,8 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
// HACK to get full width preview layer
|
||||
CGRect oldFrame = self.qrScanningView.frame;
|
||||
self.qrScanningView.frame = CGRectMake(
|
||||
oldFrame.origin.x, oldFrame.origin.y, self.view.frame.size.width, self.view.frame.size.height / 2.0 - 32.0);
|
||||
[self.qrScanningController resizeViews];
|
||||
oldFrame.origin.x, oldFrame.origin.y, self.view.frame.size.width, self.view.frame.size.height / 2.0f - 32.0f);
|
||||
// END HACK to get full width preview layer
|
||||
|
||||
self.scanningInstructionsLabel.text = NSLocalizedString(@"LINK_DEVICE_SCANNING_INSTRUCTIONS",
|
||||
|
@ -43,6 +42,12 @@ NS_ASSUME_NONNULL_BEGIN
|
|||
[super viewWillAppear:animated];
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated
|
||||
{
|
||||
[super viewDidAppear:animated];
|
||||
[self.qrScanningController startCapture];
|
||||
}
|
||||
|
||||
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(nullable id)sender
|
||||
{
|
||||
if ([segue.identifier isEqualToString:@"embedDeviceQRScanner"]) {
|
||||
|
|
|
@ -307,7 +307,7 @@ int const OWSLinkedDevicesTableViewControllerSectionAddDevice = 1;
|
|||
OWSDevice *device = [self deviceForRowAtIndexPath:indexPath];
|
||||
[self touchedUnlinkControlForDevice:device
|
||||
success:^{
|
||||
DDLogInfo(@"Removing unlinked device with deviceId: %ld", device.deviceId);
|
||||
DDLogInfo(@"Removing unlinked device with deviceId: %ld", (long)device.deviceId);
|
||||
[device remove];
|
||||
}];
|
||||
}
|
||||
|
|
|
@ -2,27 +2,23 @@
|
|||
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <ZXingObjC/ZXingObjC.h>
|
||||
|
||||
@class OWSQRCodeScanningViewController;
|
||||
|
||||
@protocol OWSQRScannerDelegate
|
||||
|
||||
- (void)controller:(OWSQRCodeScanningViewController *)controller didDetectQRCodeWithString:(NSString *)scannedString;
|
||||
@optional
|
||||
|
||||
- (void)controller:(OWSQRCodeScanningViewController *)controller didDetectQRCodeWithString:(NSString *)string;
|
||||
- (void)controller:(OWSQRCodeScanningViewController *)controller didDetectQRCodeWithData:(NSData *)data;
|
||||
|
||||
@end
|
||||
|
||||
@interface OWSQRCodeScanningViewController : UIViewController <AVCaptureMetadataOutputObjectsDelegate>
|
||||
@interface OWSQRCodeScanningViewController
|
||||
: UIViewController <AVCaptureMetadataOutputObjectsDelegate, ZXCaptureDelegate>
|
||||
|
||||
@property (nonatomic, strong) AVCaptureSession *session;
|
||||
@property (nonatomic, strong) AVCaptureDevice *device;
|
||||
@property (nonatomic, strong) AVCaptureDeviceInput *input;
|
||||
@property (nonatomic, strong) AVCaptureMetadataOutput *output;
|
||||
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *prevLayer;
|
||||
|
||||
@property (nonatomic, strong) UIView *highlightView;
|
||||
@property (nonatomic, weak) UIViewController<OWSQRScannerDelegate> *scanDelegate;
|
||||
|
||||
// HACK to resize views after embedding. Better would be to specify layout of preview layer as constraints.
|
||||
- (void)resizeViews;
|
||||
- (void)startCapture;
|
||||
|
||||
@end
|
||||
|
|
|
@ -2,99 +2,172 @@
|
|||
|
||||
#import "OWSQRCodeScanningViewController.h"
|
||||
#import "UIColor+OWS.h"
|
||||
//#import <ZXingObjC/ZXingObjC.h>
|
||||
|
||||
|
||||
@interface OWSQRCodeScanningViewController ()
|
||||
|
||||
@property (nonatomic) BOOL captureEnabled;
|
||||
@property (nonatomic, strong) ZXCapture *capture;
|
||||
@property UIView *maskingView;
|
||||
@property CALayer *maskingLayer;
|
||||
|
||||
|
||||
@end
|
||||
|
||||
@implementation OWSQRCodeScanningViewController
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[self.capture.layer removeFromSuperlayer];
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (!self) {
|
||||
return self;
|
||||
}
|
||||
|
||||
_captureEnabled = NO;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)aDecoder
|
||||
{
|
||||
self = [super initWithCoder:aDecoder];
|
||||
if (!self) {
|
||||
return self;
|
||||
}
|
||||
|
||||
_captureEnabled = NO;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
self.title = NSLocalizedString(@"SCAN_KEY", @"");
|
||||
self.highlightView = [[UIView alloc] init];
|
||||
self.highlightView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin
|
||||
| UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
|
||||
self.highlightView.layer.borderColor = [UIColor ows_greenColor].CGColor;
|
||||
self.highlightView.layer.borderWidth = 4;
|
||||
[self.view addSubview:self.highlightView];
|
||||
|
||||
self.session = [[AVCaptureSession alloc] init];
|
||||
self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
|
||||
NSError *error = nil;
|
||||
|
||||
self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:&error];
|
||||
if (self.input) {
|
||||
[self.session addInput:self.input];
|
||||
} else {
|
||||
DDLogDebug(@"Error: %@", error);
|
||||
}
|
||||
|
||||
self.output = [[AVCaptureMetadataOutput alloc] init];
|
||||
[self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
|
||||
[self.session addOutput:self.output];
|
||||
|
||||
self.output.metadataObjectTypes = [self.output availableMetadataObjectTypes];
|
||||
|
||||
self.prevLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
|
||||
|
||||
self.prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
|
||||
[self.view.layer insertSublayer:self.prevLayer atIndex:0];
|
||||
|
||||
[self.view bringSubviewToFront:self.highlightView];
|
||||
self.maskingView = [[UIView alloc] initWithFrame:self.view.frame];
|
||||
[self.view addSubview:self.maskingView];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
[self resizeViews];
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated
|
||||
{
|
||||
[super viewDidAppear:animated];
|
||||
[self.session startRunning];
|
||||
}
|
||||
|
||||
- (void)resizeViews
|
||||
{
|
||||
self.prevLayer.frame = self.view.bounds;
|
||||
}
|
||||
|
||||
- (void)captureOutput:(AVCaptureOutput *)captureOutput
|
||||
didOutputMetadataObjects:(NSArray *)metadataObjects
|
||||
fromConnection:(AVCaptureConnection *)connection
|
||||
{
|
||||
CGRect highlightViewRect = CGRectZero;
|
||||
AVMetadataMachineReadableCodeObject *barCodeObject;
|
||||
NSString *detectionString = nil;
|
||||
NSArray *barCodeTypes = @[ AVMetadataObjectTypeQRCode ];
|
||||
|
||||
for (AVMetadataObject *metadata in metadataObjects) {
|
||||
for (NSString *type in barCodeTypes) {
|
||||
if ([metadata.type isEqualToString:type]) {
|
||||
barCodeObject = (AVMetadataMachineReadableCodeObject *)[self.prevLayer
|
||||
transformedMetadataObjectForMetadataObject:(AVMetadataMachineReadableCodeObject *)metadata];
|
||||
highlightViewRect = barCodeObject.bounds;
|
||||
detectionString = [(AVMetadataMachineReadableCodeObject *)metadata stringValue];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (detectionString != nil) {
|
||||
[self didDetectQRCodeWithString:detectionString];
|
||||
[self.session stopRunning];
|
||||
break;
|
||||
}
|
||||
if (self.captureEnabled) {
|
||||
[self startCapture];
|
||||
}
|
||||
|
||||
self.highlightView.frame = highlightViewRect;
|
||||
}
|
||||
|
||||
- (void)didDetectQRCodeWithString:(NSString *)string
|
||||
- (void)viewDidLayoutSubviews
|
||||
{
|
||||
DDLogDebug(@"Scanned QRCode with string value: %@", string);
|
||||
[super viewDidLayoutSubviews];
|
||||
[self layoutMaskingView];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated
|
||||
{
|
||||
[super viewWillDisappear:animated];
|
||||
[self stopCapture];
|
||||
}
|
||||
|
||||
- (void)layoutMaskingView
|
||||
{
|
||||
self.maskingView.frame = self.view.frame;
|
||||
if (self.maskingLayer) {
|
||||
[self.maskingLayer removeFromSuperlayer];
|
||||
}
|
||||
self.maskingLayer = [self buildCircularMaskingLayer];
|
||||
[self.maskingView.layer addSublayer:self.maskingLayer];
|
||||
}
|
||||
|
||||
- (void)startCapture
|
||||
{
|
||||
self.captureEnabled = YES;
|
||||
if (!self.capture) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
self.capture = [[ZXCapture alloc] init];
|
||||
self.capture.camera = self.capture.back;
|
||||
self.capture.focusMode = AVCaptureFocusModeContinuousAutoFocus;
|
||||
self.capture.layer.frame = self.view.frame;
|
||||
self.capture.delegate = self;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.view.layer addSublayer:self.capture.layer];
|
||||
[self.view bringSubviewToFront:self.maskingView];
|
||||
});
|
||||
});
|
||||
}
|
||||
[self.capture start];
|
||||
}
|
||||
|
||||
- (void)stopCapture
|
||||
{
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
[self.capture stop];
|
||||
});
|
||||
}
|
||||
|
||||
- (CAShapeLayer *)buildCircularMaskingLayer
|
||||
{
|
||||
// Add a circular mask
|
||||
UIBezierPath *path = [UIBezierPath
|
||||
bezierPathWithRoundedRect:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)
|
||||
cornerRadius:0];
|
||||
CGFloat verticalMargin = 8.0;
|
||||
CGFloat radius = self.view.frame.size.height / 2.0f - verticalMargin;
|
||||
|
||||
// Center the circle's bounding rectangle
|
||||
CGFloat horizontalMargin = (self.view.frame.size.width - 2.0f * radius) / 2.0f;
|
||||
UIBezierPath *circlePath = [UIBezierPath
|
||||
bezierPathWithRoundedRect:CGRectMake(horizontalMargin, verticalMargin, 2.0f * radius, 2.0f * radius)
|
||||
cornerRadius:radius];
|
||||
[path appendPath:circlePath];
|
||||
[path setUsesEvenOddFillRule:YES];
|
||||
|
||||
CAShapeLayer *fillLayer = [CAShapeLayer layer];
|
||||
fillLayer.path = path.CGPath;
|
||||
fillLayer.fillRule = kCAFillRuleEvenOdd;
|
||||
fillLayer.fillColor = [UIColor grayColor].CGColor;
|
||||
fillLayer.opacity = 0.5;
|
||||
return fillLayer;
|
||||
}
|
||||
|
||||
- (void)captureResult:(ZXCapture *)capture result:(ZXResult *)result
|
||||
{
|
||||
[self stopCapture];
|
||||
|
||||
// TODO bounding rectangle
|
||||
|
||||
// Vibrate
|
||||
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
|
||||
|
||||
if (self.scanDelegate) {
|
||||
[self.scanDelegate controller:self didDetectQRCodeWithString:string];
|
||||
if ([self.scanDelegate respondsToSelector:@selector(controller:didDetectQRCodeWithData:)]) {
|
||||
DDLogInfo(@"%@ Scanned Data Code.", self.tag);
|
||||
ZXByteArray *byteArray = result.resultMetadata[@(kResultMetadataTypeByteSegments)][0];
|
||||
NSData *decodedData = [NSData dataWithBytes:byteArray.array length:byteArray.length];
|
||||
|
||||
[self.scanDelegate controller:self didDetectQRCodeWithData:decodedData];
|
||||
}
|
||||
|
||||
if ([self.scanDelegate respondsToSelector:@selector(controller:didDetectQRCodeWithString:)]) {
|
||||
DDLogInfo(@"%@ Scanned String Code.", self.tag);
|
||||
[self.scanDelegate controller:self didDetectQRCodeWithString:result.text];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSString *)tag
|
||||
{
|
||||
return [NSString stringWithFormat:@"[%@]", self.class];
|
||||
}
|
||||
|
||||
- (NSString *)tag
|
||||
{
|
||||
return self.class.tag;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
//
|
||||
// PresentIdentityQRCodeViewController.h
|
||||
// Signal-iOS
|
||||
//
|
||||
// Created by Christine Corbett Moran on 3/30/14.
|
||||
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface PresentIdentityQRCodeViewController : UIViewController
|
||||
@property (nonatomic, strong) IBOutlet UIImageView *qrCodeView;
|
||||
@property (nonatomic, strong) IBOutlet UILabel *yourFingerprintLabel;
|
||||
@property (nonatomic, strong) NSData *identityKey;
|
||||
|
||||
@end
|
|
@ -1,41 +0,0 @@
|
|||
//
|
||||
// PresentIdentityQRCodeViewController.m
|
||||
// Signal-iOS
|
||||
//
|
||||
// Created by Christine Corbett Moran on 3/30/14.
|
||||
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NSData+Base64.h"
|
||||
#import "PresentIdentityQRCodeViewController.h"
|
||||
#import "UIImage+normalizeImage.h"
|
||||
|
||||
|
||||
@implementation PresentIdentityQRCodeViewController
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
|
||||
CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
|
||||
|
||||
[filter setDefaults];
|
||||
|
||||
[filter setValue:[[self.identityKey base64EncodedString] dataUsingEncoding:NSUTF8StringEncoding]
|
||||
forKey:@"inputMessage"];
|
||||
|
||||
CIImage *outputImage = [filter outputImage];
|
||||
|
||||
CIContext *context = [CIContext contextWithOptions:nil];
|
||||
CGImageRef cgImage = [context createCGImage:outputImage fromRect:[outputImage extent]];
|
||||
|
||||
UIImage *image = [UIImage imageWithCGImage:cgImage scale:1. orientation:UIImageOrientationUp];
|
||||
|
||||
// Resize without interpolating
|
||||
UIImage *resized = [image resizedWithQuality:kCGInterpolationNone rate:5.0];
|
||||
|
||||
self.qrCodeView.image = resized;
|
||||
_yourFingerprintLabel.text = NSLocalizedString(@"FINGERPRINT_YOURS", @"");
|
||||
CGImageRelease(cgImage);
|
||||
}
|
||||
|
||||
@end
|
|
@ -12,21 +12,13 @@
|
|||
#import "DJWActionSheet+OWS.h"
|
||||
#import "Environment.h"
|
||||
#import "PreferencesUtil.h"
|
||||
#import "TSFingerprintGenerator.h"
|
||||
#import "UIUtil.h"
|
||||
|
||||
@interface PrivacySettingsTableViewController ()
|
||||
|
||||
@property (nonatomic, strong) UITableViewCell *enableScreenSecurityCell;
|
||||
@property (nonatomic, strong) UITableViewCell *clearHistoryLogCell;
|
||||
@property (nonatomic, strong) UITableViewCell *fingerprintCell;
|
||||
@property (nonatomic, strong) UITableViewCell *shareFingerprintCell;
|
||||
|
||||
@property (nonatomic, strong) UISwitch *enableScreenSecuritySwitch;
|
||||
|
||||
@property (nonatomic, strong) UILabel *fingerprintLabel;
|
||||
|
||||
@property (nonatomic, strong) NSTimer *copiedTimer;
|
||||
@property (nonatomic, strong) UITableViewCell *clearHistoryLogCell;
|
||||
|
||||
@end
|
||||
|
||||
|
@ -51,51 +43,25 @@
|
|||
// Enable Screen Security Cell
|
||||
self.enableScreenSecurityCell = [[UITableViewCell alloc] init];
|
||||
self.enableScreenSecurityCell.textLabel.text = NSLocalizedString(@"SETTINGS_SCREEN_SECURITY", @"");
|
||||
|
||||
self.enableScreenSecuritySwitch = [[UISwitch alloc] initWithFrame:CGRectZero];
|
||||
|
||||
self.enableScreenSecurityCell.accessoryView = self.enableScreenSecuritySwitch;
|
||||
self.enableScreenSecurityCell.userInteractionEnabled = YES;
|
||||
[self.enableScreenSecuritySwitch setOn:[Environment.preferences screenSecurityIsEnabled]];
|
||||
[self.enableScreenSecuritySwitch addTarget:self
|
||||
action:@selector(didToggleScreenSecuritySwitch:)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
|
||||
// Clear History Log Cell
|
||||
self.clearHistoryLogCell = [[UITableViewCell alloc] init];
|
||||
self.clearHistoryLogCell.textLabel.text = NSLocalizedString(@"SETTINGS_CLEAR_HISTORY", @"");
|
||||
self.clearHistoryLogCell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
||||
|
||||
// Fingerprint Cell
|
||||
self.fingerprintCell =
|
||||
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"Identifier"];
|
||||
self.fingerprintCell.textLabel.text = NSLocalizedString(@"SETTINGS_FINGERPRINT", @"");
|
||||
self.fingerprintCell.detailTextLabel.text = NSLocalizedString(@"SETTINGS_FINGERPRINT_COPY", nil);
|
||||
self.fingerprintCell.detailTextLabel.textColor = [UIColor lightGrayColor];
|
||||
|
||||
self.fingerprintLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 150, 25)];
|
||||
self.fingerprintLabel.textColor = [UIColor lightGrayColor];
|
||||
self.fingerprintLabel.font = [UIFont ows_regularFontWithSize:16.0f];
|
||||
self.fingerprintLabel.lineBreakMode = NSLineBreakByTruncatingMiddle;
|
||||
|
||||
self.fingerprintCell.accessoryView = self.fingerprintLabel;
|
||||
|
||||
[self setValues];
|
||||
[self subsribeToEvents];
|
||||
}
|
||||
|
||||
- (void)subsribeToEvents {
|
||||
[self.enableScreenSecuritySwitch addTarget:self
|
||||
action:@selector(didToggleSwitch:)
|
||||
forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
|
||||
- (void)setValues {
|
||||
[self.enableScreenSecuritySwitch setOn:[Environment.preferences screenSecurityIsEnabled]];
|
||||
self.fingerprintLabel.text =
|
||||
[TSFingerprintGenerator getFingerprintForDisplay:[[TSStorageManager sharedManager] identityKeyPair].publicKey];
|
||||
}
|
||||
|
||||
#pragma mark - Table view data source
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
return 3;
|
||||
return 2;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
|
@ -104,8 +70,9 @@
|
|||
return 1;
|
||||
case 1:
|
||||
return 1;
|
||||
case 2:
|
||||
return 1;
|
||||
// TODO: optionally non-blocking
|
||||
// case 2:
|
||||
// return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -126,13 +93,9 @@
|
|||
return self.enableScreenSecurityCell;
|
||||
case 1:
|
||||
return self.clearHistoryLogCell;
|
||||
case 2:
|
||||
switch (indexPath.row) {
|
||||
case 0:
|
||||
return self.fingerprintCell;
|
||||
case 1:
|
||||
return self.shareFingerprintCell;
|
||||
}
|
||||
// TODO - safetynumber settings
|
||||
// case 2:
|
||||
// return [UITableViewCell new];
|
||||
}
|
||||
|
||||
return nil;
|
||||
|
@ -141,11 +104,11 @@
|
|||
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
|
||||
switch (section) {
|
||||
case 0:
|
||||
return NSLocalizedString(@"SETTINGS_SECURITY_TITLE", @"");
|
||||
return NSLocalizedString(@"SETTINGS_SECURITY_TITLE", @"Section header");
|
||||
case 1:
|
||||
return NSLocalizedString(@"SETTINGS_HISTORYLOG_TITLE", @"");
|
||||
return NSLocalizedString(@"SETTINGS_HISTORYLOG_TITLE", @"Section header");
|
||||
case 2:
|
||||
return NSLocalizedString(@"SETTINGS_FINGERPRINT", @"");
|
||||
return NSLocalizedString(@"SETTINGS_PRIVACY_VERIFICATION_TITLE", @"Section header");
|
||||
default:
|
||||
return nil;
|
||||
}
|
||||
|
@ -174,31 +137,6 @@
|
|||
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
switch (indexPath.row) {
|
||||
case 0: {
|
||||
// Timer to change label to copied (NSTextAttachment checkmark)
|
||||
if (self.copiedTimer == nil) {
|
||||
self.copiedTimer = [NSTimer scheduledTimerWithTimeInterval:2.0f
|
||||
target:self
|
||||
selector:@selector(endTimer:)
|
||||
userInfo:nil
|
||||
repeats:NO];
|
||||
self.fingerprintCell.detailTextLabel.text =
|
||||
NSLocalizedString(@"SETTINGS_FINGERPRINT_COPY_SUCCESS", @"");
|
||||
} else {
|
||||
self.fingerprintCell.detailTextLabel.text =
|
||||
NSLocalizedString(@"SETTINGS_FINGERPRINT_COPY", nil);
|
||||
}
|
||||
[[UIPasteboard generalPasteboard] setString:self.fingerprintLabel.text];
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -206,16 +144,23 @@
|
|||
|
||||
#pragma mark - Toggle
|
||||
|
||||
- (void)didToggleSwitch:(UISwitch *)sender {
|
||||
[Environment.preferences setScreenSecurity:self.enableScreenSecuritySwitch.isOn];
|
||||
- (void)didToggleScreenSecuritySwitch:(UISwitch *)sender
|
||||
{
|
||||
BOOL enabled = self.enableScreenSecuritySwitch.isOn;
|
||||
DDLogInfo(@"%@ toggled screen security: %@", self.tag, enabled ? @"ON" : @"OFF");
|
||||
[Environment.preferences setScreenSecurity:enabled];
|
||||
}
|
||||
|
||||
#pragma mark - Timer
|
||||
#pragma mark - Log util
|
||||
|
||||
- (void)endTimer:(id)sender {
|
||||
self.fingerprintCell.detailTextLabel.text = NSLocalizedString(@"SETTINGS_FINGERPRINT_COPY", nil);
|
||||
[self.copiedTimer invalidate];
|
||||
self.copiedTimer = nil;
|
||||
+ (NSString *)tag
|
||||
{
|
||||
return [NSString stringWithFormat:@"[%@]", self.class];
|
||||
}
|
||||
|
||||
- (NSString *)tag
|
||||
{
|
||||
return self.class.tag;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
//
|
||||
// ScanIdentityBarcodeViewController.h
|
||||
// Signal-iOS
|
||||
//
|
||||
// Created by Christine Corbett Moran on 3/29/14.
|
||||
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
||||
|
||||
#import "OWSQRCodeScanningViewController.h"
|
||||
|
||||
@interface ScanIdentityBarcodeViewController : OWSQRCodeScanningViewController
|
||||
|
||||
@property (nonatomic, strong) NSData *identityKey;
|
||||
|
||||
@end
|
|
@ -1,53 +0,0 @@
|
|||
//
|
||||
// ScanIdentityBarcodeViewController.m
|
||||
// Signal-iOS
|
||||
//
|
||||
// Created by Christine Corbett Moran on 3/29/14.
|
||||
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#import "ScanIdentityBarcodeViewController.h"
|
||||
#import "NSData+Base64.h"
|
||||
|
||||
@implementation ScanIdentityBarcodeViewController
|
||||
|
||||
- (void)didDetectQRCodeWithString:(NSString *)string
|
||||
{
|
||||
NSData *data = [NSData dataFromBase64String:string];
|
||||
NSString *dialogTitle;
|
||||
NSString *dialogDescription;
|
||||
|
||||
if ([data isEqualToData:self.identityKey]) {
|
||||
dialogTitle = NSLocalizedString(@"SCAN_KEY_VERIFIED_TITLE", @"");
|
||||
dialogDescription = NSLocalizedString(@"SCAN_KEY_VERIFIED_TEXT", @"");
|
||||
} else {
|
||||
dialogTitle = NSLocalizedString(@"SCAN_KEY_CONFLICT_TITLE", @"");
|
||||
dialogDescription = NSLocalizedString(@"SCAN_KEY_CONFLICT_TEXT", @"");
|
||||
}
|
||||
|
||||
UIAlertController *controller = [UIAlertController alertControllerWithTitle:dialogTitle
|
||||
message:dialogDescription
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
[self
|
||||
presentViewController:controller
|
||||
animated:YES
|
||||
completion:^{
|
||||
[self performSelector:@selector(dismissScannerAfterSuccesfullScan) withObject:nil afterDelay:5];
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Action
|
||||
|
||||
- (void)dismissScannerAfterSuccesfullScan {
|
||||
[self dismissViewControllerAnimated:YES
|
||||
completion:^{
|
||||
[self closeButtonAction:nil];
|
||||
}];
|
||||
}
|
||||
|
||||
- (IBAction)closeButtonAction:(id)sender {
|
||||
[self performSegueWithIdentifier:@"UnwindToIdentityKeyWasVerifiedSegue" sender:self];
|
||||
}
|
||||
|
||||
@end
|
|
@ -28,7 +28,7 @@
|
|||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qCf-bs-dBd" userLabel="textContainer">
|
||||
<rect key="frame" x="0.0" y="42" width="320" height="48"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Info Message" textAlignment="center" lineBreakMode="wordWrap" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="OVa-Xw-5vl" customClass="JSQMessagesLabel">
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Info Message" textAlignment="center" lineBreakMode="wordWrap" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" numberOfLines="0" translatesAutoresizingMaskIntoConstraints="NO" id="OVa-Xw-5vl" customClass="JSQMessagesLabel">
|
||||
<rect key="frame" x="8" y="12" width="304" height="28"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="14" id="fed-2c-dqd"/>
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue