Device Manager

* List linked devices
* Adding a new device
* Removing a device

TODO: design on the QRScanner

// FREEBIE
This commit is contained in:
Michael Kirk 2016-08-29 10:28:40 -04:00
parent 84156698c4
commit ef6784ed95
10 changed files with 520 additions and 34 deletions

View File

@ -22,6 +22,7 @@
458E38341D66873D0094BD24 /* OWSLinkDeviceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 458E38331D66873D0094BD24 /* OWSLinkDeviceViewController.m */; };
458E38371D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 458E38361D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m */; };
458E383A1D6699FA0094BD24 /* OWSDeviceProvisioningURLParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 458E38391D6699FA0094BD24 /* OWSDeviceProvisioningURLParserTest.m */; };
459311FC1D75C948008DD4F0 /* OWSDeviceTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 459311FB1D75C948008DD4F0 /* OWSDeviceTableViewCell.m */; };
459C3F0D1C9B3A1B003ACF51 /* TSMessageAdapterTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 459C3F0C1C9B3A1B003ACF51 /* TSMessageAdapterTest.m */; };
45C681B71D305A580050903A /* OWSCall.m in Sources */ = {isa = PBXBuildFile; fileRef = 45C681B61D305A580050903A /* OWSCall.m */; };
45C681B81D305A580050903A /* OWSCall.m in Sources */ = {isa = PBXBuildFile; fileRef = 45C681B61D305A580050903A /* OWSCall.m */; };
@ -34,6 +35,7 @@
45C681C81D305C9E0050903A /* OWSDisplayedMessageCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 45C681C31D305C9E0050903A /* OWSDisplayedMessageCollectionViewCell.xib */; };
45C681C91D305C9E0050903A /* OWSDisplayedMessageCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 45C681C31D305C9E0050903A /* OWSDisplayedMessageCollectionViewCell.xib */; };
45CB2FA81CB7146C00E1B343 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 45CB2FA71CB7146C00E1B343 /* Launch Screen.storyboard */; };
45EB32CF1D7465C900735B2E /* OWSLinkedDevicesTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 45EB32CE1D7465C900735B2E /* OWSLinkedDevicesTableViewController.m */; };
4CE0E3771B954546007210CF /* TSAnimatedAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CE0E3761B954546007210CF /* TSAnimatedAdapter.m */; };
701231B518ECAA4500D456C4 /* EvpMessageDigest.m in Sources */ = {isa = PBXBuildFile; fileRef = 701231B418ECAA4500D456C4 /* EvpMessageDigest.m */; };
70377AAB1918450100CAF501 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 70377AAA1918450100CAF501 /* MobileCoreServices.framework */; };
@ -530,6 +532,8 @@
458E38351D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSDeviceProvisioningURLParser.h; sourceTree = "<group>"; };
458E38361D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDeviceProvisioningURLParser.m; sourceTree = "<group>"; };
458E38391D6699FA0094BD24 /* OWSDeviceProvisioningURLParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OWSDeviceProvisioningURLParserTest.m; path = Models/OWSDeviceProvisioningURLParserTest.m; sourceTree = "<group>"; };
459311FA1D75C948008DD4F0 /* OWSDeviceTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSDeviceTableViewCell.h; sourceTree = "<group>"; };
459311FB1D75C948008DD4F0 /* OWSDeviceTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDeviceTableViewCell.m; sourceTree = "<group>"; };
459C3F0C1C9B3A1B003ACF51 /* TSMessageAdapterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TSMessageAdapterTest.m; path = "view controllers/Signals/TSMessageAdapters/TSMessageAdapterTest.m"; sourceTree = "<group>"; };
45C681B51D305A580050903A /* OWSCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSCall.h; sourceTree = "<group>"; };
45C681B61D305A580050903A /* OWSCall.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSCall.m; sourceTree = "<group>"; };
@ -542,6 +546,8 @@
45CB2FA71CB7146C00E1B343 /* Launch Screen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = "Launch Screen.storyboard"; path = "Signal/src/util/Launch Screen.storyboard"; sourceTree = SOURCE_ROOT; };
45E282DE1D08E67800ADD4C8 /* gl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = gl; path = translations/gl.lproj/Localizable.strings; sourceTree = "<group>"; };
45E282DF1D08E6CC00ADD4C8 /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = translations/id.lproj/Localizable.strings; sourceTree = "<group>"; };
45EB32CD1D7465C900735B2E /* OWSLinkedDevicesTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSLinkedDevicesTableViewController.h; sourceTree = "<group>"; };
45EB32CE1D7465C900735B2E /* OWSLinkedDevicesTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSLinkedDevicesTableViewController.m; sourceTree = "<group>"; };
4CE0E3751B95453C007210CF /* TSAnimatedAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSAnimatedAdapter.h; sourceTree = "<group>"; };
4CE0E3761B954546007210CF /* TSAnimatedAdapter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSAnimatedAdapter.m; sourceTree = "<group>"; };
701231B318ECAA4500D456C4 /* EvpMessageDigest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EvpMessageDigest.h; sourceTree = "<group>"; };
@ -1715,6 +1721,8 @@
76EB052E18170B33006006FC /* ContactTableViewCell.h */,
76EB052F18170B33006006FC /* ContactTableViewCell.m */,
76EB053818170B33006006FC /* xibs */,
459311FA1D75C948008DD4F0 /* OWSDeviceTableViewCell.h */,
459311FB1D75C948008DD4F0 /* OWSDeviceTableViewCell.m */,
);
name = Views;
path = views;
@ -2238,6 +2246,8 @@
FCD274EA1A5AFDDB00202277 /* AboutTableViewController.m */,
458E38321D66873D0094BD24 /* OWSLinkDeviceViewController.h */,
458E38331D66873D0094BD24 /* OWSLinkDeviceViewController.m */,
45EB32CD1D7465C900735B2E /* OWSLinkedDevicesTableViewController.h */,
45EB32CE1D7465C900735B2E /* OWSLinkedDevicesTableViewController.m */,
);
name = Settings;
sourceTree = "<group>";
@ -2761,6 +2771,7 @@
FC4FA0261A1B9DC600DA100A /* SignalsNavigationController.m in Sources */,
76EB063818170B33006006FC /* DictionaryUtil.m in Sources */,
76EB05CE18170B33006006FC /* ZrtpHandshakeResult.m in Sources */,
45EB32CF1D7465C900735B2E /* OWSLinkedDevicesTableViewController.m in Sources */,
B63761EE19E1FBE8005735D1 /* HttpRequestUtil.m in Sources */,
76EB05B618170B33006006FC /* MasterSecret.m in Sources */,
76EB05F418170B33006006FC /* CallConnectResult.m in Sources */,
@ -2802,6 +2813,7 @@
76EB05AE18170B33006006FC /* SrtpStream.m in Sources */,
E197B61318BBEC1A00F073E5 /* DesiredBufferDepthController.m in Sources */,
76EB064818170B33006006FC /* Zid.m in Sources */,
459311FC1D75C948008DD4F0 /* OWSDeviceTableViewCell.m in Sources */,
76EB05E218170B33006006FC /* SecureEndPoint.m in Sources */,
76EB05DE18170B33006006FC /* Certificate.m in Sources */,
76EB05B818170B33006006FC /* NegotiationFailed.m in Sources */,

View File

@ -4,6 +4,7 @@
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
</dependencies>
<scenes>
<!--Conversations-->
@ -379,7 +380,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>
@ -744,7 +745,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">
@ -1349,6 +1350,98 @@ A0 09 9A FF A8 8A 09 99</string>
</objects>
<point key="canvasLocation" x="-4372" y="-1537.8599999999999"/>
</scene>
<!--Linked Devices-->
<scene sceneID="R59-ey-Ucx">
<objects>
<tableViewController id="euf-gj-Iag" customClass="OWSLinkedDevicesTableViewController" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="18" sectionFooterHeight="18" id="zqK-o2-Psk">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<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="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"/>
<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">
<rect key="frame" x="17" y="8" width="129" height="20"/>
<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" 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" 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"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstAttribute="bottomMargin" secondItem="Kek-MK-oLy" secondAttribute="bottom" id="5Wg-pN-nfp"/>
<constraint firstItem="57o-uV-YOg" firstAttribute="leading" secondItem="XqL-QG-IbY" secondAttribute="leadingMargin" constant="9" id="7T0-ym-8gM"/>
<constraint firstItem="uL2-wj-OZr" firstAttribute="top" secondItem="57o-uV-YOg" secondAttribute="bottom" id="7dw-uu-TZK"/>
<constraint firstItem="Kek-MK-oLy" firstAttribute="top" secondItem="uL2-wj-OZr" secondAttribute="bottom" id="CPN-Tu-AVN"/>
<constraint firstItem="Kek-MK-oLy" firstAttribute="leading" secondItem="57o-uV-YOg" secondAttribute="leading" id="JEA-wB-KbQ"/>
<constraint firstItem="uL2-wj-OZr" firstAttribute="height" secondItem="57o-uV-YOg" secondAttribute="height" multiplier="15/17" id="O61-fc-qwm"/>
<constraint firstItem="uL2-wj-OZr" firstAttribute="leading" secondItem="57o-uV-YOg" secondAttribute="leading" id="T5V-13-qDK"/>
<constraint firstItem="57o-uV-YOg" firstAttribute="top" secondItem="XqL-QG-IbY" secondAttribute="topMargin" id="asn-zh-Ubj"/>
<constraint firstItem="Kek-MK-oLy" firstAttribute="height" secondItem="uL2-wj-OZr" secondAttribute="height" id="hXw-bD-8Rq"/>
</constraints>
</tableViewCellContentView>
<connections>
<outlet property="lastSeenLabel" destination="Kek-MK-oLy" id="hnT-Gu-wAF"/>
<outlet property="linkedLabel" destination="uL2-wj-OZr" id="XoU-iO-eDe"/>
<outlet property="nameLabel" destination="57o-uV-YOg" id="yZG-PJ-JOY"/>
</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="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"/>
<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="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" 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"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
<connections>
<segue destination="tWr-1v-Sq9" kind="push" id="23M-9X-9xV"/>
</connections>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="euf-gj-Iag" id="R6C-wt-F6o"/>
<outlet property="delegate" destination="euf-gj-Iag" id="Smu-kk-c7F"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Linked Devices" id="HAh-b7-E4Q"/>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="tUY-HM-TQP" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-2400" y="-3228"/>
</scene>
<!--_7.0 - Settings-->
<scene sceneID="BD7-1h-slc">
<objects>
@ -1364,7 +1457,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">
@ -1405,11 +1498,11 @@ 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">
<rect key="frame" x="15" y="12" width="200" height="19.5"/>
<rect key="frame" x="15" y="12" width="200" height="20"/>
<constraints>
<constraint firstAttribute="width" constant="200" id="q6L-Sa-lrA"/>
</constraints>
@ -1444,14 +1537,14 @@ 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" cocoaTouchSystemColor="darkTextColor"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@ -1461,14 +1554,14 @@ 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" cocoaTouchSystemColor="darkTextColor"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@ -1478,34 +1571,34 @@ 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" cocoaTouchSystemColor="darkTextColor"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
<connections>
<segue destination="tWr-1v-Sq9" kind="push" id="LTQ-a4-Xbb"/>
<segue destination="euf-gj-Iag" kind="push" id="Mpp-7k-YTc"/>
</connections>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="dkL-Nz-E6H" style="IBUITableViewCellStyleDefault" id="Xx7-pz-aLN" userLabel="Advanced Cell">
<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" cocoaTouchSystemColor="darkTextColor"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@ -1515,14 +1608,14 @@ 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" cocoaTouchSystemColor="darkTextColor"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
@ -1536,7 +1629,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">
@ -1615,7 +1708,7 @@ A0 09 9A FF A8 8A 09 99</string>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="lPR-Bk-TZT" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-2415" y="-3154"/>
<point key="canvasLocation" x="-2023" y="-3228"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="aWR-d3-s5V">
@ -1649,7 +1742,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">
@ -1708,11 +1801,11 @@ A0 09 9A FF A8 8A 09 99</string>
<viewControllerLayoutGuide type="bottom" id="kH6-9L-pzh"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="P0X-AM-Yjw">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<rect key="frame" x="0.0" y="64" width="320" height="504"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Ukg-om-VX3" userLabel="Group Details">
<rect key="frame" x="0.0" y="20" width="320" height="100"/>
<rect key="frame" x="0.0" y="0.0" width="320" height="100"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Ul8-NY-i4c">
<rect key="frame" x="8" y="20" width="60" height="60"/>
@ -1747,14 +1840,14 @@ A0 09 9A FF A8 8A 09 99</string>
</constraints>
</view>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" allowsMultipleSelection="YES" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="cFo-AT-Srf">
<rect key="frame" x="0.0" y="128" width="320" height="440"/>
<rect key="frame" x="0.0" y="108" width="320" height="396"/>
<color key="backgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="calibratedRGB"/>
<view key="tableHeaderView" contentMode="scaleToFill" id="ekO-kw-iHV" userLabel="Header View">
<rect key="frame" x="0.0" y="0.0" width="320" height="40"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Add people:" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="daD-wf-IGn">
<rect key="frame" x="10" y="10" width="98.5" height="20.5"/>
<rect key="frame" x="10" y="10" width="99" height="21"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
@ -1772,11 +1865,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"/>
@ -1864,7 +1957,7 @@ A0 09 9A FF A8 8A 09 99</string>
<image name="speaker-inactive" width="80" height="80"/>
</resources>
<inferredMetricsTieBreakers>
<segue reference="D0d-4f-lcI"/>
<segue reference="xo7-5J-BJb"/>
<segue reference="gZ1-lh-srF"/>
</inferredMetricsTieBreakers>
</document>

View File

@ -184,8 +184,7 @@
TSOutgoingMessage *message =
[[TSOutgoingMessage alloc] initWithTimestamp:[NSDate ows_millisecondTimeStamp]
inThread:thread
messageBody:responseInfo[UIUserNotificationActionResponseTypedTextKey]
attachmentIds:nil];
messageBody:responseInfo[UIUserNotificationActionResponseTypedTextKey]];
[[TSMessagesManager sharedManager] sendMessage:message
inThread:thread
success:^{

View File

@ -2,6 +2,10 @@
#import "OWSQRCodeScanningViewController.h"
@class OWSLinkedDevicesTableViewController;
@interface OWSLinkDeviceViewController : OWSQRCodeScanningViewController
@property OWSLinkedDevicesTableViewController *linkedDevicesTableViewController;
@end

View File

@ -2,6 +2,8 @@
#import "OWSLinkDeviceViewController.h"
#import "OWSDeviceProvisioningURLParser.h"
#import "OWSLinkedDevicesTableViewController.h"
#import "SettingsTableViewController.h"
#import <SignalServiceKit/ECKeyPair+OWSPrivateKey.h>
#import <SignalServiceKit/OWSDeviceProvisioner.h>
#import <SignalServiceKit/TSStorageManager+IdentityKeyStore.h>
@ -14,6 +16,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = NSLocalizedString(@"Link New Device", "Navigation title when scanning QR code to add new device.");
}
- (void)viewDidAppear:(BOOL)animated
@ -22,6 +25,37 @@ NS_ASSUME_NONNULL_BEGIN
}
- (void)didDetectQRCodeWithString:(NSString *)string
{
NSString *title = NSLocalizedString(@"Link this device?", @"Alert title");
NSString *linkingDescription = NSLocalizedString(@"This device will be able to see your groups and contacts, read "
@"all your messages, and send messages in your name.",
@"Alert body confirmation when linking a new device");
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title
message:linkingDescription
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction =
[UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", nil)
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.navigationController popViewControllerAnimated:YES];
});
}];
[alertController addAction:cancelAction];
UIAlertAction *proceedAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Link New Device", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[self provisionWithString:string];
}];
[alertController addAction:proceedAction];
[self presentViewController:alertController animated:YES completion:nil];
}
- (void)provisionWithString:(NSString *)string
{
OWSDeviceProvisioningURLParser *parser = [[OWSDeviceProvisioningURLParser alloc] initWithProvisioningURL:string];
@ -42,12 +76,48 @@ NS_ASSUME_NONNULL_BEGIN
[provisioner provisionWithSuccess:^{
DDLogInfo(@"Successfully provisioned device.");
dispatch_async(dispatch_get_main_queue(), ^{
self.linkedDevicesTableViewController.expectMoreDevices = YES;
[self.navigationController popToViewController:self.linkedDevicesTableViewController animated:YES];
});
}
failure:^(NSError *error) {
DDLogError(@"Failed to provision device with error: %@", error);
dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:[self retryAlertControllerWithError:error
retryBlock:^{
[self provisionWithString:string];
}]
animated:YES
completion:nil];
});
}];
}
// TODO show progress. Maybe even incremental with progress callback in provisioner.
- (UIAlertController *)retryAlertControllerWithError:(NSError *)error retryBlock:(void (^)())retryBlock
{
NSString *title = NSLocalizedString(@"Linking Device Failed", @"Alert Title");
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title
message:error.localizedDescription
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *retryAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"RETRY_BUTTON_TEXT", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
retryBlock();
}];
[alertController addAction:retryAction];
UIAlertAction *cancelAction =
[UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", nil)
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action) {
dispatch_async(dispatch_get_main_queue(), ^{
[self dismissViewControllerAnimated:YES completion:nil];
});
}];
[alertController addAction:cancelAction];
return alertController;
}
@end

View File

@ -0,0 +1,9 @@
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import <UIKit/UIKit.h>
@interface OWSLinkedDevicesTableViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate>
@property BOOL expectMoreDevices;
@end

View File

@ -0,0 +1,255 @@
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "OWSLinkedDevicesTableViewController.h"
#import "OWSDeviceTableViewCell.h"
#import "OWSLinkDeviceViewController.h"
#import <SignalServiceKit/OWSDevice.h>
#import <SignalServiceKit/OWSDevicesService.h>
@interface OWSLinkedDevicesTableViewController ()
@property NSArray<OWSDevice *> *secondaryDevices;
@end
int const OWSLinkedDevicesTableViewControllerSectionExistingDevices = 0;
int const OWSLinkedDevicesTableViewControllerSectionAddDevice = 1;
@implementation OWSLinkedDevicesTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.expectMoreDevices = NO;
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 70;
self.refreshControl = [UIRefreshControl new];
[self.refreshControl addTarget:self action:@selector(refreshDevices) forControlEvents:UIControlEventValueChanged];
// Since this table is primarily for deleting items...
[self setEditing:YES animated:NO];
// So we can still tap on "add new device"
self.tableView.allowsSelectionDuringEditing = YES;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.secondaryDevices = [OWSDevice secondaryDevices];
// If we're returning from just adding a device, show that something's happening.
if (self.expectMoreDevices) {
[self.refreshControl beginRefreshing];
[self.tableView setContentOffset:CGPointMake(0, -self.refreshControl.frame.size.height) animated:NO];
}
[self refreshDevices];
}
- (void)refreshDevices
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[OWSDevicesService new] getDevicesWithSuccess:^(NSArray<OWSDevice *> *devices) {
if (devices.count > [OWSDevice numberOfKeysInCollection]) {
// Got our new device, we can stop refreshing.
self.expectMoreDevices = NO;
}
[OWSDevice replaceAll:devices];
self.secondaryDevices = [OWSDevice secondaryDevices];
if (self.expectMoreDevices) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC),
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
^{
[self refreshDevices];
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[self.refreshControl endRefreshing];
[self.tableView reloadData];
});
}
}
failure:^(NSError *error) {
DDLogError(@"Failed to fetch devices in linkedDevices controller with error: %@", error);
NSString *alertTitle = NSLocalizedString(
@"Failed to update device list.", @"Alert title that can occur when viewing device manager.");
UIAlertController *alertController =
[UIAlertController alertControllerWithTitle:alertTitle
message:error.localizedDescription
preferredStyle:UIAlertControllerStyleAlert];
NSString *retryTitle = NSLocalizedString(
@"RETRY_BUTTON_TEXT", @"Generic text for button that retries whatever the last action was.");
UIAlertAction *retryAction = [UIAlertAction actionWithTitle:retryTitle
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[self refreshDevices];
}];
[alertController addAction:retryAction];
NSString *dismissTitle
= NSLocalizedString(@"DISMISS_BUTTON_TEXT", @"Generic short text for button to dismiss a dialog");
UIAlertAction *dismissAction =
[UIAlertAction actionWithTitle:dismissTitle style:UIAlertActionStyleCancel handler:nil];
[alertController addAction:dismissAction];
dispatch_async(dispatch_get_main_queue(), ^{
[self.refreshControl endRefreshing];
[self presentViewController:alertController animated:YES completion:nil];
});
}];
});
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
switch (section) {
case OWSLinkedDevicesTableViewControllerSectionExistingDevices:
return (NSInteger)self.secondaryDevices.count;
case OWSLinkedDevicesTableViewControllerSectionAddDevice:
return 1;
default:
DDLogError(@"Unknown section: %ld", (long)section);
return 0;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == OWSLinkedDevicesTableViewControllerSectionAddDevice) {
return [tableView dequeueReusableCellWithIdentifier:@"AddNewDevice" forIndexPath:indexPath];
} else if (indexPath.section == OWSLinkedDevicesTableViewControllerSectionExistingDevices) {
OWSDeviceTableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:@"ExistingDevice" forIndexPath:indexPath];
OWSDevice *device = [self deviceForRowAtIndexPath:indexPath];
[cell configureWithDevice:device];
return cell;
} else {
DDLogError(@"Unknown section: %@", indexPath);
return nil;
}
}
- (OWSDevice *)deviceForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == OWSLinkedDevicesTableViewControllerSectionExistingDevices) {
return self.secondaryDevices[(NSUInteger)indexPath.row];
}
return nil;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return indexPath.section == OWSLinkedDevicesTableViewControllerSectionExistingDevices;
}
- (nullable NSString *)tableView:(UITableView *)tableView
titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
{
return NSLocalizedString(@"Unlink", "Action title for unlinking a device");
}
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
OWSDevice *device = [self deviceForRowAtIndexPath:indexPath];
[self touchedUnlinkControlForDevice:device
success:^{
DDLogInfo(@"Removing unlinked device with deviceId: %ld", device.deviceId);
[device remove];
self.secondaryDevices = [OWSDevice secondaryDevices];
[tableView deleteRowsAtIndexPaths:@[ indexPath ]
withRowAnimation:UITableViewRowAnimationFade];
}];
}
}
- (void)touchedUnlinkControlForDevice:(OWSDevice *)device success:(void (^)())successCallback
{
NSString *confirmationTitleFormat
= NSLocalizedString(@"Unlink \"%@\"?", @"Alert title for confirming device deletion");
NSString *confirmationTitle = [NSString stringWithFormat:confirmationTitleFormat, device.name];
NSString *confirmationMessage
= NSLocalizedString(@"By unlinking this device, it will no longer be able to send or receive messages.",
@"Alert description shown to confirm unlinking a device.");
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:confirmationTitle
message:confirmationMessage
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", nil)
style:UIAlertActionStyleCancel
handler:nil];
[alertController addAction:cancelAction];
UIAlertAction *unlinkAction =
[UIAlertAction actionWithTitle:NSLocalizedString(@"Unlink", "Action title for unlinking a device")
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction *action) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self unlinkDevice:device success:successCallback];
});
}];
[alertController addAction:unlinkAction];
dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:alertController animated:YES completion:nil];
});
}
- (void)unlinkDevice:(OWSDevice *)device success:(void (^)())successCallback
{
[[OWSDevicesService new] unlinkDevice:device
success:successCallback
failure:^(NSError *error) {
NSString *title = NSLocalizedString(@"Signal was unable to delete your device.",
@"Alert title when unlinking device fails");
UIAlertController *alertController =
[UIAlertController alertControllerWithTitle:title
message:error.localizedDescription
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *retryAction =
[UIAlertAction actionWithTitle:NSLocalizedString(@"RETRY_BUTTON_TEXT", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *aaction) {
[self unlinkDevice:device success:successCallback];
}];
[alertController addAction:retryAction];
UIAlertAction *cancelRetryAction =
[UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", nil)
style:UIAlertActionStyleCancel
handler:nil];
[alertController addAction:cancelRetryAction];
dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:alertController animated:YES completion:nil];
});
}];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.destinationViewController isKindOfClass:[OWSLinkDeviceViewController class]]) {
OWSLinkDeviceViewController *controller = (OWSLinkDeviceViewController *)segue.destinationViewController;
controller.linkedDevicesTableViewController = self;
}
}
@end

View File

@ -0,0 +1,18 @@
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import <SignalServiceKit/OWSDevice.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface OWSDeviceTableViewCell : UITableViewCell
@property (strong, nonatomic) IBOutlet UILabel *nameLabel;
@property (strong, nonatomic) IBOutlet UILabel *linkedLabel;
@property (strong, nonatomic) IBOutlet UILabel *lastSeenLabel;
- (void)configureWithDevice:(OWSDevice *)device;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,26 @@
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "OWSDeviceTableViewCell.h"
#import "DateUtil.h"
NS_ASSUME_NONNULL_BEGIN
@implementation OWSDeviceTableViewCell
- (void)configureWithDevice:(OWSDevice *)device
{
self.nameLabel.text = device.name;
NSString *linkedFormatString = NSLocalizedString(@"Linked: %@", @"{{Short Date}} when device was linked.");
self.linkedLabel.text =
[NSString stringWithFormat:linkedFormatString, [DateUtil.dateFormatter stringFromDate:device.createdAt]];
NSString *lastSeenFormatString
= NSLocalizedString(@"Last active: %@", @"{{Short Date}} when device last communicated with Signal Server.");
self.lastSeenLabel.text =
[NSString stringWithFormat:lastSeenFormatString, [DateUtil.dateFormatter stringFromDate:device.createdAt]];
}
@end
NS_ASSUME_NONNULL_END