Commit 44fb2400 authored by Kateryna Kostiuk's avatar Kateryna Kostiuk

Account: add linked devices

In account page add table with linked devices

Change-Id: I33c1a079a580644164e1817d95f03254d332b976
Reviewed-by: Andreas Traczyk's avatarAndreas Traczyk <andreas.traczyk@savoirfairelinux.com>
parent aeb46e0c
......@@ -80,8 +80,12 @@
04399B141D1C341A00E99CD9 /* libx264.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 04399AE21D1C341A00E99CD9 /* libx264.a */; };
04399B151D1C341A00E99CD9 /* libyaml-cpp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 04399AE31D1C341A00E99CD9 /* libyaml-cpp.a */; };
0586C94B1F684DF600613517 /* UIImage+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0586C94A1F684DF600613517 /* UIImage+Helpers.swift */; };
0E2D5F531F9145C800D574BF /* LinkNewDeviceCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E2D5F521F9145C800D574BF /* LinkNewDeviceCell.swift */; };
0E2D5F551F9145F200D574BF /* LinkNewDeviceCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E2D5F541F9145F200D574BF /* LinkNewDeviceCell.xib */; };
0E403F811F7D797300C80BC2 /* MessageCellGenerated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E403F801F7D797300C80BC2 /* MessageCellGenerated.swift */; };
0E403F831F7D79B000C80BC2 /* MessageCellGenerated.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0E403F821F7D79B000C80BC2 /* MessageCellGenerated.xib */; };
0EB1A5CF1F8EBE03009923E2 /* DeviceCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0EB1A5CE1F8EBE03009923E2 /* DeviceCell.xib */; };
0EB1A5D11F8EBE23009923E2 /* DeviceCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB1A5D01F8EBE23009923E2 /* DeviceCell.swift */; };
0EDE34C71F868E1200FFA15C /* EditProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE34C61F868E1200FFA15C /* EditProfileViewController.swift */; };
0EDE34C91F8691BB00FFA15C /* EditProfileViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EDE34C81F8691BB00FFA15C /* EditProfileViewModel.swift */; };
0EE1B54E1F75ACDE00BA98EE /* CNContactVCardSerialization+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EE1B54D1F75ACDE00BA98EE /* CNContactVCardSerialization+Helpers.swift */; };
......@@ -302,8 +306,12 @@
04399AE21D1C341A00E99CD9 /* libx264.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libx264.a; path = ../fat/lib/libx264.a; sourceTree = "<group>"; };
04399AE31D1C341A00E99CD9 /* libyaml-cpp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libyaml-cpp.a"; path = "../fat/lib/libyaml-cpp.a"; sourceTree = "<group>"; };
0586C94A1F684DF600613517 /* UIImage+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIImage+Helpers.swift"; sourceTree = "<group>"; };
0E2D5F521F9145C800D574BF /* LinkNewDeviceCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LinkNewDeviceCell.swift; sourceTree = "<group>"; };
0E2D5F541F9145F200D574BF /* LinkNewDeviceCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LinkNewDeviceCell.xib; sourceTree = "<group>"; };
0E403F801F7D797300C80BC2 /* MessageCellGenerated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageCellGenerated.swift; sourceTree = "<group>"; };
0E403F821F7D79B000C80BC2 /* MessageCellGenerated.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MessageCellGenerated.xib; sourceTree = "<group>"; };
0EB1A5CE1F8EBE03009923E2 /* DeviceCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DeviceCell.xib; sourceTree = "<group>"; };
0EB1A5D01F8EBE23009923E2 /* DeviceCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceCell.swift; sourceTree = "<group>"; };
0EDE34C61F868E1200FFA15C /* EditProfileViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditProfileViewController.swift; sourceTree = "<group>"; };
0EDE34C81F8691BB00FFA15C /* EditProfileViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EditProfileViewModel.swift; sourceTree = "<group>"; };
0EE1B54D1F75ACDE00BA98EE /* CNContactVCardSerialization+Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CNContactVCardSerialization+Helpers.swift"; sourceTree = "<group>"; };
......@@ -778,6 +786,25 @@
name = SYS_DEPS;
sourceTree = "<group>";
};
0E5AFE0A1F8EBC040040D539 /* Cells */ = {
isa = PBXGroup;
children = (
0E5AFE0B1F8EBC1E0040D539 /* DeviceCell */,
);
name = Cells;
sourceTree = "<group>";
};
0E5AFE0B1F8EBC1E0040D539 /* DeviceCell */ = {
isa = PBXGroup;
children = (
0EB1A5CE1F8EBE03009923E2 /* DeviceCell.xib */,
0EB1A5D01F8EBE23009923E2 /* DeviceCell.swift */,
0E2D5F521F9145C800D574BF /* LinkNewDeviceCell.swift */,
0E2D5F541F9145F200D574BF /* LinkNewDeviceCell.xib */,
);
name = DeviceCell;
sourceTree = "<group>";
};
0EDE34C51F868D2D00FFA15C /* Shared */ = {
isa = PBXGroup;
children = (
......@@ -949,6 +976,7 @@
1A2D18D91F2918F300B2C785 /* Me */ = {
isa = PBXGroup;
children = (
0E5AFE0A1F8EBC040040D539 /* Cells */,
1A2D18EC1F2919D800B2C785 /* MeViewController.storyboard */,
1A5DC02B1F3565250075E8EF /* MeViewController.swift */,
1A2D18FE1F29352D00B2C785 /* MeViewModel.swift */,
......@@ -1181,12 +1209,14 @@
0E403F831F7D79B000C80BC2 /* MessageCellGenerated.xib in Resources */,
04399A031D1C2D9D00E99CD9 /* Images.xcassets in Resources */,
1A2041841F1EA0FC00C08435 /* CreateAccountViewController.storyboard in Resources */,
0E2D5F551F9145F200D574BF /* LinkNewDeviceCell.xib in Resources */,
1A2D18ED1F2919D800B2C785 /* MeViewController.storyboard in Resources */,
1A20417E1F1E8DDA00C08435 /* CreateProfileViewController.storyboard in Resources */,
1ABE07DF1F0D91A800D36361 /* LaunchScreen.storyboard in Resources */,
1A5DC0381F35675E0075E8EF /* ContactRequestCell.xib in Resources */,
1A0C4EDA1F1D4B1B00550433 /* WelcomeViewController.storyboard in Resources */,
1A5DC03E1F35678D0075E8EF /* ContactRequestsViewController.storyboard in Resources */,
0EB1A5CF1F8EBE03009923E2 /* DeviceCell.xib in Resources */,
1A2D18B31F2915C500B2C785 /* ConversationViewController.storyboard in Resources */,
1A2D18A01F27A6D600B2C785 /* LinkDeviceViewController.storyboard in Resources */,
);
......@@ -1279,6 +1309,7 @@
buildActionMask = 2147483647;
files = (
557086521E8ADB9D001A7CE4 /* SystemAdapter.mm in Sources */,
0E2D5F531F9145C800D574BF /* LinkNewDeviceCell.swift in Sources */,
0586C94B1F684DF600613517 /* UIImage+Helpers.swift in Sources */,
621231F91F880EDF009B86F0 /* UILabel+Ring.swift in Sources */,
1A2D18AC1F29149D00B2C785 /* MeCoordinator.swift in Sources */,
......@@ -1339,6 +1370,7 @@
56BBC9A31ED714DF00CDAF8B /* ConversationsService.swift in Sources */,
563AEC771EA664C0003A5641 /* RegistrationResponse.m in Sources */,
564C445B1E8EA44E000F92B1 /* Durations.swift in Sources */,
0EB1A5D11F8EBE23009923E2 /* DeviceCell.swift in Sources */,
56C715FF1F0D36C600770048 /* ContactsAdapter.mm in Sources */,
1A5DC0281F3564AA0075E8EF /* MessageModel.swift in Sources */,
56BBC9DF1EDDC9D300CDAF8B /* LookupNameResponse.m in Sources */,
......
......@@ -65,4 +65,7 @@
- (NSDictionary *)getKnownRingDevices:(NSString *)accountID;
- (Boolean)exportOnRing:(NSString *)accountID
password: (NSString *)password;
@end
......@@ -64,6 +64,22 @@ static id <AccountAdapterDelegate> _delegate;
}
}));
confHandlers.insert(exportable_callback<ConfigurationSignal::ExportOnRingEnded>([&](const std::string& account_id, int state, const std::string& pin) {
if (AccountAdapter.delegate) {
NSString* accountId = [NSString stringWithUTF8String:account_id.c_str()];
NSInteger stateN = state;
NSString* pinN = [NSString stringWithUTF8String:pin.c_str()];
[AccountAdapter.delegate exportOnRingEndededForAccout:accountId state:stateN pin:pinN];
}
}));
confHandlers.insert(exportable_callback<ConfigurationSignal::KnownDevicesChanged>([&](const std::string& account_id, const std::map<std::string, std::string>& devices) {
if (AccountAdapter.delegate) {
NSString* accountId = [NSString stringWithUTF8String:account_id.c_str()];
NSMutableDictionary* knDev = [Utils mapToDictionnary:devices];
[AccountAdapter.delegate knownDevicesChangedFor:accountId devices:knDev];
}
}));
registerConfHandlers(confHandlers);
}
#pragma mark -
......@@ -129,4 +145,11 @@ static id <AccountAdapterDelegate> _delegate;
}
#pragma mark -
#pragma mark -
- (Boolean)exportOnRing:(NSString *)accountID
password: (NSString *)password {
return exportOnRing(std::string([accountID UTF8String]), std::string([password UTF8String]));
}
@end
......@@ -47,6 +47,7 @@ struct ColorAsset {
enum Asset {
static let addPerson = ImageAsset(name: "add_person")
static let backgroundRing = ImageAsset(name: "background_ring")
static let device = ImageAsset(name: "device")
static let icContactPicture = ImageAsset(name: "ic_contact_picture")
static let logoRingBeta2Blanc = ImageAsset(name: "logo-ring-beta2-blanc")
......@@ -56,6 +57,7 @@ enum Asset {
static let allImages: [ImageAsset] = [
addPerson,
backgroundRing,
device,
icContactPicture,
logoRingBeta2Blanc,
]
......
......@@ -7,6 +7,11 @@ import Foundation
// swiftlint:disable explicit_type_interface identifier_name line_length nesting type_body_length type_name
enum L10n {
enum Accountpage {
/// Devices
static let devicesListHeader = L10n.tr("Localizable", "accountPage.devicesListHeader")
}
enum Alerts {
/// Account Added
static let accountAddedTitle = L10n.tr("Localizable", "alerts.accountAddedTitle")
......
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import UIKit
import Reusable
import RxSwift
class DeviceCell: UITableViewCell, NibReusable {
@IBOutlet weak var deviceIdLabel: UILabel!
}
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="15" id="Fgg-CE-GkC" customClass="DeviceCell" customModule="Ring" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Fgg-CE-GkC" id="fvy-0B-phe">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Device ID" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="OQs-TS-z4j">
<rect key="frame" x="40" y="5" width="325" height="33.5"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="device" translatesAutoresizingMaskIntoConstraints="NO" id="rQq-Mc-A6A">
<rect key="frame" x="10" y="12" width="20" height="20"/>
<constraints>
<constraint firstAttribute="width" constant="20" id="GWa-IT-XzN"/>
<constraint firstAttribute="height" constant="20" id="yTt-mK-xNR"/>
</constraints>
</imageView>
</subviews>
<constraints>
<constraint firstItem="OQs-TS-z4j" firstAttribute="centerY" secondItem="fvy-0B-phe" secondAttribute="centerY" id="1ub-Tt-uhc"/>
<constraint firstItem="OQs-TS-z4j" firstAttribute="top" secondItem="fvy-0B-phe" secondAttribute="top" constant="5" id="Bm7-bn-pZ8"/>
<constraint firstItem="rQq-Mc-A6A" firstAttribute="leading" secondItem="fvy-0B-phe" secondAttribute="leading" constant="10" id="CCb-8S-cPs"/>
<constraint firstItem="OQs-TS-z4j" firstAttribute="leading" secondItem="rQq-Mc-A6A" secondAttribute="trailing" constant="10" id="SBZ-1f-gmH"/>
<constraint firstAttribute="trailing" secondItem="OQs-TS-z4j" secondAttribute="trailing" constant="10" id="c1v-0c-oUl"/>
<constraint firstAttribute="bottom" secondItem="OQs-TS-z4j" secondAttribute="bottom" constant="5" id="uZX-qs-oIK"/>
<constraint firstItem="rQq-Mc-A6A" firstAttribute="centerY" secondItem="fvy-0B-phe" secondAttribute="centerY" id="vxW-wo-3mL"/>
</constraints>
</tableViewCellContentView>
<connections>
<outlet property="deviceIdLabel" destination="OQs-TS-z4j" id="UZg-Z8-A28"/>
</connections>
<point key="canvasLocation" x="85.5" y="124"/>
</tableViewCell>
</objects>
<resources>
<image name="device" width="24" height="24"/>
</resources>
</document>
/*
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
import UIKit
import Reusable
import RxSwift
class LinkNewDeviceCell: UITableViewCell, NibReusable {
@IBOutlet weak var addDeviceButton: UIButton!
let disposeBag = DisposeBag()
}
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="Nv7-EG-n6R" customClass="LinkNewDeviceCell" customModule="Ring" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Nv7-EG-n6R" id="fhq-ul-0n8">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="contactAdd" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qQU-vB-ZuD">
<rect key="frame" x="8" y="13.5" width="30" height="30"/>
<constraints>
<constraint firstAttribute="width" constant="30" id="14X-by-AdX"/>
<constraint firstAttribute="height" constant="30" id="7T1-tR-Nku"/>
</constraints>
<color key="tintColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</button>
</subviews>
<constraints>
<constraint firstItem="qQU-vB-ZuD" firstAttribute="top" secondItem="fhq-ul-0n8" secondAttribute="topMargin" constant="5" id="h6n-CF-6dY"/>
<constraint firstItem="qQU-vB-ZuD" firstAttribute="leading" secondItem="fhq-ul-0n8" secondAttribute="leadingMargin" id="rDw-yi-5yG"/>
</constraints>
</tableViewCellContentView>
<connections>
<outlet property="addDeviceButton" destination="qQU-vB-ZuD" id="63f-uV-UkV"/>
</connections>
<point key="canvasLocation" x="38.5" y="124"/>
</tableViewCell>
</objects>
</document>
......@@ -81,9 +81,14 @@
<color key="textColor" red="0.20000000300000001" green="0.20000000300000001" blue="0.20000000300000001" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="eg8-N7-lDA">
<rect key="frame" x="0.0" y="243" width="375" height="424"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</tableView>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="tam-QD-Xpf" firstAttribute="top" secondItem="eg8-N7-lDA" secondAttribute="bottom" id="2zg-J2-7oF"/>
<constraint firstAttribute="trailingMargin" secondItem="rC6-Ga-QjY" secondAttribute="trailing" constant="5" id="4mU-no-jxy"/>
<constraint firstItem="tS0-P7-fYT" firstAttribute="leading" secondItem="nkh-py-Uar" secondAttribute="leading" constant="20" id="6OH-dg-fT7"/>
<constraint firstAttribute="trailingMargin" secondItem="w8x-Sv-T50" secondAttribute="trailing" constant="5" id="Bm3-S8-KXr"/>
......@@ -93,12 +98,15 @@
<constraint firstItem="8HY-Zl-94u" firstAttribute="centerX" secondItem="nkh-py-Uar" secondAttribute="centerX" id="H4W-Vc-cHV"/>
<constraint firstAttribute="trailingMargin" secondItem="GCe-jT-OCG" secondAttribute="trailing" constant="20" id="I2l-64-P0x"/>
<constraint firstItem="tS0-P7-fYT" firstAttribute="centerX" secondItem="nkh-py-Uar" secondAttribute="centerX" id="JBF-Pu-rcp"/>
<constraint firstItem="eg8-N7-lDA" firstAttribute="top" secondItem="w8x-Sv-T50" secondAttribute="bottom" constant="8" id="Nfa-oZ-Zfg"/>
<constraint firstItem="GCe-jT-OCG" firstAttribute="leading" secondItem="nkh-py-Uar" secondAttribute="leadingMargin" constant="20" id="Sp4-fa-qoR"/>
<constraint firstAttribute="trailing" secondItem="tS0-P7-fYT" secondAttribute="trailing" constant="20" id="Uvb-ZR-7rf"/>
<constraint firstItem="GCe-jT-OCG" firstAttribute="centerX" secondItem="nkh-py-Uar" secondAttribute="centerX" id="WO3-X1-ObR"/>
<constraint firstItem="rC6-Ga-QjY" firstAttribute="leading" secondItem="nkh-py-Uar" secondAttribute="leadingMargin" constant="5" id="g4K-vz-fbY"/>
<constraint firstItem="w8x-Sv-T50" firstAttribute="top" secondItem="rC6-Ga-QjY" secondAttribute="bottom" constant="5" id="kSt-bN-hIG"/>
<constraint firstItem="eg8-N7-lDA" firstAttribute="leading" secondItem="nkh-py-Uar" secondAttribute="leading" id="lt1-n4-Wb9"/>
<constraint firstItem="w8x-Sv-T50" firstAttribute="leading" secondItem="rC6-Ga-QjY" secondAttribute="leading" id="t75-yu-OEC"/>
<constraint firstAttribute="trailing" secondItem="eg8-N7-lDA" secondAttribute="trailing" id="tv6-ma-ze2"/>
<constraint firstItem="rC6-Ga-QjY" firstAttribute="top" secondItem="tS0-P7-fYT" secondAttribute="bottom" constant="21" id="yve-5B-6tl"/>
</constraints>
</view>
......@@ -110,6 +118,7 @@
<outlet property="profileImageView" destination="8HY-Zl-94u" id="cY6-cO-WEq"/>
<outlet property="profileName" destination="GCe-jT-OCG" id="FDX-fX-Fye"/>
<outlet property="ringIdLabel" destination="rC6-Ga-QjY" id="nsg-Jw-OTS"/>
<outlet property="settingsTable" destination="eg8-N7-lDA" id="gJV-8a-jA3"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="MXJ-Bb-hGu" userLabel="First Responder" sceneMemberID="firstResponder"/>
......
......@@ -2,6 +2,7 @@
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Edric Ladent-Milaret <edric.ladent-milaret@savoirfairelinux.com>
* Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -21,12 +22,15 @@
import UIKit
import Reusable
import RxSwift
import RxCocoa
import RxDataSources
class MeViewController: EditProfileViewController, StoryboardBased, ViewModelBased {
// MARK: - outlets
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var ringIdLabel: UILabel!
@IBOutlet weak var settingsTable: UITableView!
// MARK: - members
var viewModel: MeViewModel!
......@@ -50,5 +54,56 @@ class MeViewController: EditProfileViewController, StoryboardBased, ViewModelBas
.disposed(by: disposeBag)
super.setupUI()
//setup Table
self.settingsTable.estimatedRowHeight = 50
self.settingsTable.rowHeight = UITableViewAutomaticDimension
self.settingsTable.separatorStyle = .none
//Register cell
self.setUpDataSource()
self.settingsTable.register(cellType: DeviceCell.self)
self.settingsTable.register(cellType: LinkNewDeviceCell.self)
}
func setUpDataSource() {
let settingsItmeDataSource = RxTableViewSectionedReloadDataSource<SettingsSection>()
let configureCell: (TableViewSectionedDataSource, UITableView, IndexPath, SettingsSection.Item)
-> UITableViewCell = {
( dataSource: TableViewSectionedDataSource<SettingsSection>,
tableView: UITableView,
indexPath: IndexPath,
item: SettingsSection.Item) in
switch dataSource[indexPath] {
case .device(let device):
let cell = tableView.dequeueReusableCell(for: indexPath, cellType: DeviceCell.self)
cell.deviceIdLabel.text = device.deviceId
cell.selectionStyle = .none
return cell
case .linkNew:
let cell = tableView.dequeueReusableCell(for: indexPath, cellType: LinkNewDeviceCell.self)
cell.addDeviceButton.rx.tap.subscribe(onNext: { [unowned self] in
self.viewModel.linkDevice()
}).disposed(by: cell.disposeBag)
cell.selectionStyle = .none
return cell
}
}
settingsItmeDataSource.configureCell = configureCell
self.viewModel.settings
.bind(to: self.settingsTable.rx.items(dataSource: settingsItmeDataSource))
.disposed(by: disposeBag)
//Set header titles
settingsItmeDataSource.titleForHeaderInSection = { dataSource, index in
return dataSource.sectionModels[index].header
}
}
}
......@@ -2,6 +2,7 @@
* Copyright (C) 2017 Savoir-faire Linux Inc.
*
* Author: Thibault Wittemberg <thibault.wittemberg@savoirfairelinux.com>
* Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -20,6 +21,52 @@
import Foundation
import RxSwift
import RxDataSources
enum SettingsSection: SectionModelType {
typealias Item = SectionRow
case linkedDevices(header: String, items: [SectionRow])
case linkNewDevice(header: String, items: [SectionRow])
enum SectionRow {
case device(device: DeviceModel)
case linkNew
}
var header: String {
switch self {
case .linkedDevices(let header, _):
return header
case .linkNewDevice(let header, _):
return header
}
}
var items: [SectionRow] {
switch self {
case .linkedDevices(_, let items):
return items
case .linkNewDevice(_, let items):
return items
}
}
public init(original: SettingsSection, items: [SectionRow]) {
switch original {
case .linkedDevices(let header, _):
self = .linkedDevices(header: header, items: items)
case .linkNewDevice(let header, _):
self = .linkNewDevice(header: header, items: items)
}
}
}
class MeViewModel: ViewModel, Stateable {
......@@ -33,9 +80,57 @@ class MeViewModel: ViewModel, Stateable {
return self.stateSubject.asObservable()
}()
let disposeBag = DisposeBag()
let accountService: AccountsService
//table section
var settings: Observable<[SettingsSection]> = Observable.just([SettingsSection]())
required init(with injectionBag: InjectionBag) {
let accountService = injectionBag.accountService
self.accountService = injectionBag.accountService
self.userName = Single.just(accountService.currentAccount?.volatileDetails?.get(withConfigKeyModel: ConfigKeyModel(withKey: ConfigKey.accountRegisteredName)))
self.ringId = Single.just(accountService.currentAccount?.details?.get(withConfigKeyModel: ConfigKeyModel(withKey: .accountUsername)))
if let account = accountService.currentAccount {
let accountHelper = AccountModelHelper(withAccount: account)
let uri = accountHelper.ringId
let devices = Observable.from(optional: account.devices)
let accountDevice: Observable<[DeviceModel]> = self.accountService
.sharedResponseStream
.filter({ (event) in
return event.eventType == ServiceEventType.knownDevicesChanged &&
event.getEventInput(ServiceEventInput.uri) == uri
}).map({ _ in
return account.devices
})
self.settings = devices.concat(accountDevice)
.map { devices in
let addNewDevice = SettingsSection.linkNewDevice(header: "", items: [SettingsSection.SectionRow.linkNew])
var rows: [SettingsSection.SectionRow]?
if !devices.isEmpty {
rows = [SettingsSection.SectionRow.device(device: devices[0])]
for i in 1 ..< devices.count {
let device = devices[i]
rows!.append (SettingsSection.SectionRow.device(device: device))
}
}
if rows != nil {
let devicesSection = SettingsSection.linkedDevices(header: L10n.Accountpage.devicesListHeader, items: rows!)
return [devicesSection, addNewDevice]
} else {
return [addNewDevice]
}
}
}
}
func linkDevice() {
}
}
......@@ -55,7 +55,7 @@ class AccountModel: Equatable {
self.id = accountId
self.details = details
self.volatileDetails = volatileDetails
self.devices.append(contentsOf: devices)
self.devices = devices
}
public static func == (lhs: AccountModel, rhs: AccountModel) -> Bool {
......
{
"images" : [
{
"idiom" : "universal",
"filename" : "ic_devices.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "ic_devices_2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "ic_devices_3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
......@@ -69,3 +69,6 @@
"alerts.profileTakePhoto" = "Take photo";
"alerts.profileUploadPhoto" = "Upload photo";
"alerts.profileCancelPhoto" = "Cancel";
//Account Page
"accountPage.devicesListHeader" = "Devices";
......@@ -22,5 +22,6 @@
func accountsChanged()
func registrationStateChanged(with response: RegistrationResponse)
func knownDevicesChanged(for account: String, devices: [String: String])
func exportOnRingEndeded(forAccout account: String, state: Int, pin: String)
}
......@@ -24,6 +24,10 @@ import RxSwift
import RealmSwift
import SwiftyBeaver
enum LinkNewDeviceError: Error {
case unknownError
}
enum AddAccountError: Error {
case templateNotConform
case unknownError
......@@ -157,7 +161,7 @@ class AccountsService: AccountAdapterDelegate {
for account in accountList {
account.details = self.getAccountDetails(fromAccountId: account.id)
account.volatileDetails = self.getVolatileAccountDetails(fromAccountId: account.id)
account.devices.append(contentsOf: getKnownRingDevices(fromAccountId: account.id))
account.devices = getKnownRingDevices(fromAccountId: account.id)
do {
let credentialDetails = try self.getAccountCredentials(fromAccountId: account.id)
......@@ -378,4 +382,35 @@ class AccountsService: AccountAdapterDelegate {
self.responseStream.onNext(event)
}
func knownDevicesChanged(for account: String, devices: [String: String]) {
reloadAccounts()
let changedAccount = getAccount(fromAccountId: account)
if let changedAccount = changedAccount {
let accountHelper = AccountModelHelper(withAccount: changedAccount)
if let uri = accountHelper.ringId {
var event = ServiceEvent(withEventType: .knownDevicesChanged)
event.addEventInput(.uri, value: uri)
self.responseStream.onNext(event)
}
}
}
func exportOnRing(withPassword password: String)
-> Completable {
return Completable.create { [unowned self] completable in
let export = self.accountAdapter.export(onRing: self.currentAccount?.id, password: password)
if export {
completable(.completed)
} else {
completable(.error(LinkNewDeviceError.unknownError))
}
return Disposables.create { }
}
}
func exportOnRingEndeded(forAccout account: String, state: Int, pin: String) {
log.info(pin)
}
}
......@@ -30,6 +30,7 @@ enum ServiceEventType {
case registrationStateChanged
case presenceUpdated
case messageStateChanged
case knownDevicesChanged
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment