diff --git a/Ring/Ring.xcodeproj/project.pbxproj b/Ring/Ring.xcodeproj/project.pbxproj index 2db63a59b1639d029f9a6ddcd24c8ba27accb106..a48b35acf1d49b0357c1c47c7dbef2567653a877 100644 --- a/Ring/Ring.xcodeproj/project.pbxproj +++ b/Ring/Ring.xcodeproj/project.pbxproj @@ -11,12 +11,16 @@ 02419BD01DC3E75700DF0734 /* libboost_system.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 02419BCE1DC3E75700DF0734 /* libboost_system.a */; }; 02419BD21DC3E76A00DF0734 /* libcryptopp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 02419BD11DC3E76A00DF0734 /* libcryptopp.a */; }; 02AED8191DD4C4B100F740BA /* librestbed.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 02AED8181DD4C4B100F740BA /* librestbed.a */; }; + 02B22DFC1DF755BB000358C9 /* AccountModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02B22DFA1DF755BB000358C9 /* AccountModel.swift */; }; + 02B22DFD1DF755BB000358C9 /* AccountViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02B22DFB1DF755BB000358C9 /* AccountViewModel.swift */; }; + 02B22DFF1DF755DB000358C9 /* AccountsService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02B22DFE1DF755DB000358C9 /* AccountsService.swift */; }; + 02B22E011DF755E5000358C9 /* MainTabBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02B22E001DF755E5000358C9 /* MainTabBarViewController.swift */; }; + 02B22E031DF755F7000358C9 /* WalkthroughStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 02B22E021DF755F7000358C9 /* WalkthroughStoryboard.storyboard */; }; + 02B22E051DF75605000358C9 /* NotificationNames.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02B22E041DF75605000358C9 /* NotificationNames.swift */; }; + 02E1A0251DDE4ABA00D75B59 /* BoolStringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 043866371D2304A700E06CE2 /* BoolStringExtension.swift */; }; 043866211D218B1100E06CE2 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 043866201D218B1100E06CE2 /* AudioToolbox.framework */; }; - 043866241D22C3BC00E06CE2 /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = 043866231D22C3BC00E06CE2 /* Account.swift */; }; - 043866261D22C42F00E06CE2 /* AccountModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 043866251D22C42F00E06CE2 /* AccountModel.swift */; }; 043866331D22CE8C00E06CE2 /* MeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 043866321D22CE8C00E06CE2 /* MeViewController.swift */; }; 043866361D22D06500E06CE2 /* AccountTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 043866351D22D06500E06CE2 /* AccountTableViewCell.swift */; }; - 043866381D2304A700E06CE2 /* BoolStringExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 043866371D2304A700E06CE2 /* BoolStringExtension.swift */; }; 0438663B1D2313B700E06CE2 /* AccountDetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0438663A1D2313B700E06CE2 /* AccountDetailsViewController.swift */; }; 043999F71D1C2D9D00E99CD9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 043999F61D1C2D9D00E99CD9 /* AppDelegate.swift */; }; 043999FA1D1C2D9D00E99CD9 /* Ring.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 043999F81D1C2D9D00E99CD9 /* Ring.xcdatamodeld */; }; @@ -104,12 +108,16 @@ 02419BCE1DC3E75700DF0734 /* libboost_system.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libboost_system.a; path = ../fat/lib/libboost_system.a; sourceTree = "<group>"; }; 02419BD11DC3E76A00DF0734 /* libcryptopp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libcryptopp.a; path = ../fat/lib/libcryptopp.a; sourceTree = "<group>"; }; 02AED8181DD4C4B100F740BA /* librestbed.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = librestbed.a; path = ../DEPS/x86_64/lib/librestbed.a; sourceTree = "<group>"; }; + 02B22DFA1DF755BB000358C9 /* AccountModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AccountModel.swift; path = Account/AccountModel.swift; sourceTree = "<group>"; }; + 02B22DFB1DF755BB000358C9 /* AccountViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AccountViewModel.swift; path = Account/AccountViewModel.swift; sourceTree = "<group>"; }; + 02B22DFE1DF755DB000358C9 /* AccountsService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AccountsService.swift; path = Services/AccountsService.swift; sourceTree = "<group>"; }; + 02B22E001DF755E5000358C9 /* MainTabBarViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MainTabBarViewController.swift; path = MainTabBar/MainTabBarViewController.swift; sourceTree = "<group>"; }; + 02B22E021DF755F7000358C9 /* WalkthroughStoryboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = WalkthroughStoryboard.storyboard; path = Walkthrough/WalkthroughStoryboard.storyboard; sourceTree = "<group>"; }; + 02B22E041DF75605000358C9 /* NotificationNames.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = NotificationNames.swift; path = Extensions/NotificationNames.swift; sourceTree = "<group>"; }; 043866201D218B1100E06CE2 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; - 043866231D22C3BC00E06CE2 /* Account.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Account.swift; sourceTree = "<group>"; }; - 043866251D22C42F00E06CE2 /* AccountModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountModel.swift; sourceTree = "<group>"; }; 043866321D22CE8C00E06CE2 /* MeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MeViewController.swift; sourceTree = "<group>"; }; 043866351D22D06500E06CE2 /* AccountTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountTableViewCell.swift; sourceTree = "<group>"; }; - 043866371D2304A700E06CE2 /* BoolStringExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BoolStringExtension.swift; sourceTree = "<group>"; }; + 043866371D2304A700E06CE2 /* BoolStringExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BoolStringExtension.swift; path = Extensions/BoolStringExtension.swift; sourceTree = "<group>"; }; 0438663A1D2313B700E06CE2 /* AccountDetailsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountDetailsViewController.swift; sourceTree = "<group>"; }; 043999F31D1C2D9D00E99CD9 /* Ring.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Ring.app; sourceTree = BUILT_PRODUCTS_DIR; }; 043999F61D1C2D9D00E99CD9 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; @@ -277,19 +285,36 @@ 02DE64671DDD15FC007D20EC /* Storyboards */ = { isa = PBXGroup; children = ( + 02B22E021DF755F7000358C9 /* WalkthroughStoryboard.storyboard */, 043999FF1D1C2D9D00E99CD9 /* Main.storyboard */, 04399A041D1C2D9D00E99CD9 /* LaunchScreen.storyboard */, ); name = Storyboards; sourceTree = "<group>"; }; - 043866221D22C38400E06CE2 /* Models */ = { + 02E1A0261DDE4C2E00D75B59 /* Services */ = { isa = PBXGroup; children = ( - 043866231D22C3BC00E06CE2 /* Account.swift */, - 043866251D22C42F00E06CE2 /* AccountModel.swift */, + 02B22DFE1DF755DB000358C9 /* AccountsService.swift */, ); - name = Models; + name = Services; + sourceTree = "<group>"; + }; + 02E1A0271DDE4C3900D75B59 /* Account */ = { + isa = PBXGroup; + children = ( + 02B22DFA1DF755BB000358C9 /* AccountModel.swift */, + 02B22DFB1DF755BB000358C9 /* AccountViewModel.swift */, + ); + name = Account; + sourceTree = "<group>"; + }; + 02F9B1C21DDDFF0E00FE123D /* MainTabBar */ = { + isa = PBXGroup; + children = ( + 02B22E001DF755E5000358C9 /* MainTabBarViewController.swift */, + ); + name = MainTabBar; sourceTree = "<group>"; }; 0438662D1D22C87500E06CE2 /* ViewController */ = { @@ -312,6 +337,7 @@ 043866391D2307C000E06CE2 /* Extensions */ = { isa = PBXGroup; children = ( + 02B22E041DF75605000358C9 /* NotificationNames.swift */, 043866371D2304A700E06CE2 /* BoolStringExtension.swift */, ); name = Extensions; @@ -343,16 +369,18 @@ 043999F51D1C2D9D00E99CD9 /* Ring */ = { isa = PBXGroup; children = ( + 02E1A0271DDE4C3900D75B59 /* Account */, + 02E1A0261DDE4C2E00D75B59 /* Services */, + 02F9B1C21DDDFF0E00FE123D /* MainTabBar */, 02DE64671DDD15FC007D20EC /* Storyboards */, 043866341D22D04E00E06CE2 /* UI */, 0438662D1D22C87500E06CE2 /* ViewController */, - 043866221D22C38400E06CE2 /* Models */, + 043866391D2307C000E06CE2 /* Extensions */, 04399AAF1D1C305600E99CD9 /* DRingAdaptator */, 043999F61D1C2D9D00E99CD9 /* AppDelegate.swift */, 04399A021D1C2D9D00E99CD9 /* Assets.xcassets */, 04399A071D1C2D9D00E99CD9 /* Info.plist */, 043999F81D1C2D9D00E99CD9 /* Ring.xcdatamodeld */, - 043866391D2307C000E06CE2 /* Extensions */, ); path = Ring; sourceTree = "<group>"; @@ -568,6 +596,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 02B22E031DF755F7000358C9 /* WalkthroughStoryboard.storyboard in Resources */, 04399A061D1C2D9D00E99CD9 /* LaunchScreen.storyboard in Resources */, 04399A031D1C2D9D00E99CD9 /* Assets.xcassets in Resources */, 04399A011D1C2D9D00E99CD9 /* Main.storyboard in Resources */, @@ -595,17 +624,20 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 02E1A0251DDE4ABA00D75B59 /* BoolStringExtension.swift in Sources */, 04399AAC1D1C304300E99CD9 /* ConfigurationManagerAdaptator.mm in Sources */, + 02B22E011DF755E5000358C9 /* MainTabBarViewController.swift in Sources */, 043999F71D1C2D9D00E99CD9 /* AppDelegate.swift in Sources */, - 043866381D2304A700E06CE2 /* BoolStringExtension.swift in Sources */, + 02B22DFC1DF755BB000358C9 /* AccountModel.swift in Sources */, 043866331D22CE8C00E06CE2 /* MeViewController.swift in Sources */, - 043866261D22C42F00E06CE2 /* AccountModel.swift in Sources */, 04399AAE1D1C304300E99CD9 /* Utils.mm in Sources */, + 02B22DFD1DF755BB000358C9 /* AccountViewModel.swift in Sources */, 043999FA1D1C2D9D00E99CD9 /* Ring.xcdatamodeld in Sources */, 0438663B1D2313B700E06CE2 /* AccountDetailsViewController.swift in Sources */, 043866361D22D06500E06CE2 /* AccountTableViewCell.swift in Sources */, + 02B22E051DF75605000358C9 /* NotificationNames.swift in Sources */, 04399AAD1D1C304300E99CD9 /* DRingAdaptator.mm in Sources */, - 043866241D22C3BC00E06CE2 /* Account.swift in Sources */, + 02B22DFF1DF755DB000358C9 /* AccountsService.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Ring/Ring/Account.swift b/Ring/Ring/Account.swift deleted file mode 100644 index 4922e4ff0452c01e382fde621becdc336a966e20..0000000000000000000000000000000000000000 --- a/Ring/Ring/Account.swift +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2016 Savoir-faire Linux Inc. - * - * Author: Edric Ladent-Milaret <edric.ladent-milaret@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 Foundation - -enum AccountType: String { - case SIP = "SIP" - case RING = "RING" -} - -struct Account { - - // MARK: - Properties - let id: String - - // FIXME: This should be private - var details: Dictionary<String, String> - - var alias: String? { - get { - return details["Account.alias"] - } - set { - details["Account.alias"] = newValue - } - } - - var videoEnabled: Bool { - get { - return (details["Account.videoEnabled"]?.toBool())! - } - set { - details["Account.videoEnabled"] = newValue.toString() - } - } - var username: String? { - get { - return details["Account.username"] - } - set { - details["Account.username"] = newValue - } - } - - var autoAnswer: Bool { - get { - return (details["Account.autoAnswer"]?.toBool())! - } - set { - details["Account.autoAnswer"] = newValue.toString() - } - } - - var turnEnabled: Bool { - get { - return (details["TURN.enable"]?.toBool())! - } - set { - details["TURN.enable"] = newValue.toString() - } - } - - var turnUsername: String? { - get { - return details["TURN.username"] - } - set { - details["TURN.username"] = newValue - } - } - - var turnServer: String? { - get { - return details["TURN.server"] - } - set { - details["TURN.server"] = newValue - } - } - - var turnPassword: String? { - get { - return details["TURN.password"] - } - set { - details["TURN.password"] = newValue - } - } - - var isEnabled: Bool { - get { - return (details["Account.enable"]?.toBool())! - } - set { - details["Account.enable"] = newValue.toString() - (ConfigurationManagerAdaptator.sharedManager() as AnyObject).setAccountActive(self.id, active: newValue) - } - } - - var upnpEnabled: Bool { - get { - return (details["Account.upnpEnabled"]?.toBool())! - } - set { - details["Account.upnpEnabled"] = newValue.toString() - } - } - - var accountHostname: String? { - get { - return details["Account.hostname"] - } - set { - details["Account.hostname"] = newValue - } - } - - var accountType: AccountType { - get { - return AccountType(rawValue: details["Account.type"]!)! - } - set { - details["Account.type"] = newValue.rawValue - } - } - - var displayName: String? { - get { - return details["Account.displayName"] - } - set { - details["Account.displayName"] = newValue - } - } - - // MARK: - Init - init(accID: String) { - id = accID - details = (ConfigurationManagerAdaptator.sharedManager() as AnyObject).getAccountDetails(id) as! Dictionary<String, String> - } - - func save() { - (ConfigurationManagerAdaptator.sharedManager() as AnyObject).setAccountDetails(id, details: details) - } -} diff --git a/Ring/Ring/Account/AccountModel.swift b/Ring/Ring/Account/AccountModel.swift new file mode 100644 index 0000000000000000000000000000000000000000..a4839e05222d6ebc8252cab3c58127d65656a6d6 --- /dev/null +++ b/Ring/Ring/Account/AccountModel.swift @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2016 Savoir-faire Linux Inc. + * + * Author: Edric Ladent-Milaret <edric.ladent-milaret@savoirfairelinux.com> + * Author: Romain Bertozzi <romain.bertozzi@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 Foundation + +enum AccountType: String { + case SIP = "SIP" + case RING = "RING" +} + +struct AccountModel { + + // MARK: - Keys + fileprivate let accountAliasKey = "Account.alias" + fileprivate let accountVideoEnabledKey = "Account.videoEnabled" + fileprivate let accountUsernameKey = "Account.username" + fileprivate let accountAutoAnswerKey = "Account.autoAnswer" + fileprivate let accountTurnEnabledKey = "TURN.enable" + fileprivate let accountTurnUsernameKey = "TURN.username" + fileprivate let accountTurnServerKey = "TURN.server" + fileprivate let accountTurnPasswordKey = "TURN.password" + fileprivate let accountEnabledKey = "Account.enable" + fileprivate let accountUpnpEnabledKey = "Account.upnpEnabled" + fileprivate let accountHostnameKey = "Account.hostname" + fileprivate let accountTypeKey = "Account.type" + fileprivate let accountDisplayNameKey = "Account.displayName" + + // MARK: - Properties + let id: String + + fileprivate var details: Dictionary<String, String> + + var alias: String? { + get {return details[accountAliasKey]} + set {details[accountAliasKey] = newValue} + } + + var videoEnabled: Bool { + get {return (details[accountVideoEnabledKey]?.toBool())!} + set {details[accountVideoEnabledKey] = newValue.toString()} + } + var username: String? { + get {return details[accountUsernameKey]} + set {details[accountUsernameKey] = newValue} + } + + var autoAnswer: Bool { + get {return (details[accountAutoAnswerKey]?.toBool())!} + set {details[accountAutoAnswerKey] = newValue.toString()} + } + + var turnEnabled: Bool { + get {return (details[accountTurnEnabledKey]?.toBool())!} + set {details[accountTurnEnabledKey] = newValue.toString()} + } + + var turnUsername: String? { + get {return details[accountTurnUsernameKey]} + set {details[accountTurnUsernameKey] = newValue} + } + + var turnServer: String? { + get {return details[accountTurnServerKey]} + set {details[accountTurnServerKey] = newValue} + } + + var turnPassword: String? { + get {return details[accountTurnPasswordKey]} + set {details[accountTurnPasswordKey] = newValue} + } + + var isEnabled: Bool { + get {return (details[accountEnabledKey]?.toBool())!} + set { + details[accountEnabledKey] = newValue.toString() + (ConfigurationManagerAdaptator.sharedManager() as AnyObject).setAccountActive(self.id, active: newValue) + } + } + + var upnpEnabled: Bool { + get {return (details[accountUpnpEnabledKey]?.toBool())!} + set {details[accountUpnpEnabledKey] = newValue.toString()} + } + + var accountHostname: String? { + get {return details[accountHostnameKey]} + set {details[accountHostnameKey] = newValue} + } + + var accountType: AccountType { + get {return AccountType(rawValue: details[accountTypeKey]!)!} + set {details[accountTypeKey] = newValue.rawValue} + } + + var displayName: String? { + get {return details[accountDisplayNameKey]} + set {details[accountDisplayNameKey] = newValue} + } + + // MARK: - Init + init(accountID: String) { + id = accountID + details = (ConfigurationManagerAdaptator.sharedManager() as AnyObject).getAccountDetails(id) as! Dictionary<String, String> + } + + func save() { + (ConfigurationManagerAdaptator.sharedManager() as AnyObject).setAccountDetails(id, details: details) + } +} diff --git a/Ring/Ring/Account/AccountViewModel.swift b/Ring/Ring/Account/AccountViewModel.swift new file mode 100644 index 0000000000000000000000000000000000000000..f3a8b6bb4fbd391aa25d78d0d1935ff8fc0486db --- /dev/null +++ b/Ring/Ring/Account/AccountViewModel.swift @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2016 Savoir-faire Linux Inc. + * + * Author: Romain Bertozzi <romain.bertozzi@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 + +struct AccountViewModel { + fileprivate var account: AccountModel + + init (withAccount account: AccountModel) { + self.account = account + } +} diff --git a/Ring/Ring/AccountDetailsViewController.swift b/Ring/Ring/AccountDetailsViewController.swift index 59f8a03a3488ccada965e83a3724329aebfa624b..a5dbc4a223e4b49997f795a3d499884a719a9db6 100644 --- a/Ring/Ring/AccountDetailsViewController.swift +++ b/Ring/Ring/AccountDetailsViewController.swift @@ -23,16 +23,13 @@ import UIKit class AccountDetailsViewController: UIViewController { // MARK: - Properties - var account: Account! + var account: AccountModel! @IBOutlet weak var detailsLabel: UILabel! // MARK: - UIViewController override func viewDidLoad() { super.viewDidLoad() - - // FIXME: This is just a placeholder - detailsLabel.text = account.details.description } override func didReceiveMemoryWarning() { diff --git a/Ring/Ring/AccountModel.swift b/Ring/Ring/AccountModel.swift deleted file mode 100644 index 535b8fcb59cdde3b70f5dfbc7438969b99a9414e..0000000000000000000000000000000000000000 --- a/Ring/Ring/AccountModel.swift +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2016 Savoir-faire Linux Inc. - * - * Author: Edric Ladent-Milaret <edric.ladent-milaret@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 Foundation - -class AccountModel { - - // MARK: - Properties - let confAdapt = ConfigurationManagerAdaptator.sharedManager() as AnyObject - var accountList: Array<Account> = [] - - // MARK: - Singleton - static let sharedInstance = AccountModel() - - fileprivate init() { - NotificationCenter.default.addObserver(forName: NSNotification.Name(rawValue: "AccountsChanged"), object: nil, queue: nil, using: { _ in - self.reload() - }) - } - - // MARK: - Methods - func reload() { - accountList.removeAll() - for acc in confAdapt.getAccountList() { - let accID = acc as! String - accountList.append(Account(accID: accID)) - } - } - - func addAccount() { - // TODO: This need work for all account type - let details:NSMutableDictionary? = confAdapt.getAccountTemplate("RING") - if details == nil { - print("Error retrieving Ring account template, can not continue"); - return; - } - details!.setValue("iOS", forKey: "Account.alias") - details!.setValue("iOS", forKey: "Account.displayName") - let convertedDetails = details as NSDictionary? as? [AnyHashable: Any] ?? [:] - let addResult:String! = confAdapt.addAccount(convertedDetails) - print(addResult); - } - - func removeAccount(_ row: Int) { - if row < accountList.count { - confAdapt.removeAccount(accountList[row].id) - } - } - -} diff --git a/Ring/Ring/AccountTableViewCell.swift b/Ring/Ring/AccountTableViewCell.swift index e56a930aed6fbd627ed772391de42404232c669e..c1f6c45e82a75bb2d061f05eb8d64ee8e242c1cc 100644 --- a/Ring/Ring/AccountTableViewCell.swift +++ b/Ring/Ring/AccountTableViewCell.swift @@ -27,7 +27,7 @@ class AccountTableViewCell: UITableViewCell { @IBOutlet weak var accountNameLabel: UILabel! @IBOutlet weak var accountTypeLabel: UILabel! - var account: Account! + var account: AccountModel! // MARK: - UITableViewCell override func awakeFromNib() { diff --git a/Ring/Ring/AppDelegate.swift b/Ring/Ring/AppDelegate.swift index fd15792655e5e28ae7cd9ddcd15d956b5110a8d1..bcd814576baac96285c36c7632d510d4ea2381dd 100644 --- a/Ring/Ring/AppDelegate.swift +++ b/Ring/Ring/AppDelegate.swift @@ -31,7 +31,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { if (dRingAdapt.initDaemon() == true) { if (dRingAdapt.startDaemon() == true) { Timer.scheduledTimer(timeInterval: 0.05, target: self, selector: #selector(AppDelegate.pollFunction), userInfo: nil, repeats: true) - AccountModel.sharedInstance.reload() + AccountsService.sharedInstance.reload() } } return true diff --git a/Ring/Ring/Base.lproj/Main.storyboard b/Ring/Ring/Base.lproj/Main.storyboard index b1befa3d2b5a931295dbe33762bec82b3be2b753..86038420c245d7e7b2f0e3e3057b2df0b5db1421 100644 --- a/Ring/Ring/Base.lproj/Main.storyboard +++ b/Ring/Ring/Base.lproj/Main.storyboard @@ -50,7 +50,7 @@ <rect key="frame" x="0.0" y="28" width="320" height="44"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="i1O-Yc-WGd" id="Bz1-A3-Z3f"> - <rect key="frame" x="0.0" y="0.0" width="320" height="43"/> + <rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/> <autoresizingMask key="autoresizingMask"/> <subviews> <switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bm0-lC-K2F"> @@ -96,7 +96,7 @@ <rect key="frame" x="0.0" y="72" width="320" height="44"/> <autoresizingMask key="autoresizingMask"/> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Ok2-8L-eMm" id="m64-AI-t2h"> - <rect key="frame" x="0.0" y="0.0" width="320" height="43"/> + <rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/> <autoresizingMask key="autoresizingMask"/> <subviews> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Add Account" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kZv-uf-BsD" userLabel="Account Name Label"> @@ -251,7 +251,7 @@ <!--Ring--> <scene sceneID="oqo-zJ-m0o"> <objects> - <tabBarController title="Ring" id="qdG-Sd-QaE" sceneMemberID="viewController"> + <tabBarController title="Ring" id="qdG-Sd-QaE" customClass="MainTabBarViewController" sceneMemberID="viewController"> <tabBar key="tabBar" contentMode="scaleToFill" id="zN5-xb-CQh"> <rect key="frame" x="0.0" y="0.0" width="320" height="49"/> <autoresizingMask key="autoresizingMask"/> diff --git a/Ring/Ring/BoolStringExtension.swift b/Ring/Ring/Extensions/BoolStringExtension.swift similarity index 99% rename from Ring/Ring/BoolStringExtension.swift rename to Ring/Ring/Extensions/BoolStringExtension.swift index 90b3f4ed7544edf340919d1e0e9bf9ae48627637..ce59513bd96bad3b91a5a187b0ebd9ad15820cd1 100644 --- a/Ring/Ring/BoolStringExtension.swift +++ b/Ring/Ring/Extensions/BoolStringExtension.swift @@ -40,4 +40,4 @@ extension Bool { } return "false" } -} \ No newline at end of file +} diff --git a/Ring/Ring/Extensions/NotificationNames.swift b/Ring/Ring/Extensions/NotificationNames.swift new file mode 100644 index 0000000000000000000000000000000000000000..85d545241d53b4ef663d290a497322d0116da459 --- /dev/null +++ b/Ring/Ring/Extensions/NotificationNames.swift @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2016 Savoir-faire Linux Inc. + * + * Author: Romain Bertozzi <romain.bertozzi@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 + +extension Notification.Name { + static let accountsChanged = Notification.Name("AccountsChanged") +} diff --git a/Ring/Ring/MainTabBar/MainTabBarViewController.swift b/Ring/Ring/MainTabBar/MainTabBarViewController.swift new file mode 100644 index 0000000000000000000000000000000000000000..5e4fe14943b04cb053a1725008e4c1a9fd0fd6d1 --- /dev/null +++ b/Ring/Ring/MainTabBar/MainTabBarViewController.swift @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 Savoir-faire Linux Inc. + * + * Author: Romain Bertozzi <romain.bertozzi@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 + +class MainTabBarViewController: UITabBarController { + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + if !AccountsService.sharedInstance.hasAccounts() { + self.presentWalkthrough() + } + } + + fileprivate func presentWalkthrough() { + let storyboard = UIStoryboard(name: "WalkthroughStoryboard", bundle: nil) + let viewController = storyboard.instantiateInitialViewController()! + self.present(viewController, animated: false, completion: nil) + } +} diff --git a/Ring/Ring/MeViewController.swift b/Ring/Ring/MeViewController.swift index 80a19bac06f3c16e16994a56fd7086f37d66e993..a47f82c5234a9179f1efe24b48443e9b1c28b68b 100644 --- a/Ring/Ring/MeViewController.swift +++ b/Ring/Ring/MeViewController.swift @@ -23,7 +23,7 @@ import UIKit class MeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { // MARK: - Properties - let accountModel = AccountModel.sharedInstance + let accountService = AccountsService.sharedInstance @IBOutlet weak var accountTableView: UITableView! @IBOutlet weak var nameLabel: UILabel! @IBOutlet weak var qrImageView: UIImageView! @@ -32,8 +32,8 @@ class MeViewController: UIViewController, UITableViewDelegate, UITableViewDataSo override func viewDidLoad() { super.viewDidLoad() - if accountModel.accountList.count > 0 { - let acc = accountModel.accountList[0] + if accountService.accounts.count > 0 { + let acc = accountService.accounts[0] nameLabel.text = acc.displayName if let username = acc.username { createQRFromString(username); @@ -68,14 +68,14 @@ class MeViewController: UIViewController, UITableViewDelegate, UITableViewDataSo } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return accountModel.accountList.count + 1 + return accountService.accounts.count + 1 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - if indexPath.row < accountModel.accountList.count { + if indexPath.row < accountService.accounts.count { let cell = tableView.dequeueReusableCell(withIdentifier: "accountTableCell", for: indexPath) as! AccountTableViewCell - let account = accountModel.accountList[indexPath.row] + let account = accountService.accounts[indexPath.row] cell.account = account cell.accountNameLabel.text = account.alias @@ -91,14 +91,14 @@ class MeViewController: UIViewController, UITableViewDelegate, UITableViewDataSo } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - if indexPath.row == accountModel.accountList.count { - accountModel.addAccount() + if indexPath.row == accountService.accounts.count { + accountService.addAccount() accountTableView.reloadData() } } func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { - if indexPath.row == accountModel.accountList.count { + if indexPath.row == accountService.accounts.count { return false } return true @@ -106,14 +106,14 @@ class MeViewController: UIViewController, UITableViewDelegate, UITableViewDataSo func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { if (editingStyle == UITableViewCellEditingStyle.delete) { - accountModel.removeAccount(indexPath.row) + accountService.removeAccount(indexPath.row) accountTableView.reloadData() } } // MARK: - Actions @IBAction func addAccountClicked(_ sender: AnyObject) { - let index = IndexPath(row: accountModel.accountList.count, section: 0) + let index = IndexPath(row: accountService.accounts.count, section: 0) accountTableView.selectRow(at: index, animated: false, scrollPosition: UITableViewScrollPosition.none) tableView(accountTableView, didSelectRowAt: index) } diff --git a/Ring/Ring/Services/AccountsService.swift b/Ring/Ring/Services/AccountsService.swift new file mode 100644 index 0000000000000000000000000000000000000000..d149f3b03d49df692f9d83a603026fb8e146fa91 --- /dev/null +++ b/Ring/Ring/Services/AccountsService.swift @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2016 Savoir-faire Linux Inc. + * + * Authors: Edric Ladent-Milaret <edric.ladent-milaret@savoirfairelinux.com> + * Romain Bertozzi <romain.bertozzi@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. + */ + +class AccountsService { + // MARK: - Properties + fileprivate let confAdapter = ConfigurationManagerAdaptator.sharedManager() as AnyObject + + /// Fileprivate Accounts list. + /// + /// Can be used for all the operations, but won't be accessed from outside this file. + /// + /// - SeeAlso: `accounts` + fileprivate var accountList: Array<AccountModel> + + /// Accounts list public interface + /// + /// Can be used to access by constant the list of accounts. + fileprivate(set) var accounts: Array<AccountModel> { + set { + accountList = newValue + } + get { + let lAccounts = accountList + return lAccounts + } + } + + // MARK: - Singleton + static let sharedInstance = AccountsService() + + fileprivate init() { + accountList = [] + + NotificationCenter.default.addObserver(forName: .accountsChanged, + object: nil, + queue: nil, + using: { _ in + self.reload() + }) + } + + // MARK: - Methods + func hasAccounts() -> Bool { + return accountList.count > 0 + } + + func reload() { + accountList.removeAll() + for account in confAdapter.getAccountList() { + let accountID = account as! String + accountList.append(AccountModel(accountID: accountID)) + } + } + + func addAccount() { + // TODO: This need work for all account type + let details:NSMutableDictionary? = confAdapter.getAccountTemplate("RING") + if details == nil { + print("Error retrieving Ring account template, can not continue"); + return; + } + details!.setValue("iOS", forKey: "Account.alias") + details!.setValue("iOS", forKey: "Account.displayName") + let convertedDetails = details as NSDictionary? as? [AnyHashable: Any] ?? [:] + let addResult:String! = confAdapter.addAccount(convertedDetails) + print(addResult); + } + + func removeAccount(_ row: Int) { + if row < accountList.count { + confAdapter.removeAccount(accountList[row].id) + } + } +} diff --git a/Ring/Ring/Walkthrough/WalkthroughStoryboard.storyboard b/Ring/Ring/Walkthrough/WalkthroughStoryboard.storyboard new file mode 100644 index 0000000000000000000000000000000000000000..f2a4bd2dfb811d19080c21467257f204ad3f1e21 --- /dev/null +++ b/Ring/Ring/Walkthrough/WalkthroughStoryboard.storyboard @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11542" systemVersion="15G1108" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="GnB-zf-djy"> + <device id="retina4_7" orientation="portrait"> + <adaptation id="fullscreen"/> + </device> + <dependencies> + <deployment identifier="iOS"/> + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11524"/> + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> + </dependencies> + <scenes> + <!--Navigation Controller--> + <scene sceneID="azk-5X-z35"> + <objects> + <navigationController storyboardIdentifier="WalkthroughStoryboard" navigationBarHidden="YES" id="GnB-zf-djy" sceneMemberID="viewController"> + <navigationBar key="navigationBar" contentMode="scaleToFill" id="Pgv-sV-7YL"> + <rect key="frame" x="0.0" y="0.0" width="375" height="44"/> + <autoresizingMask key="autoresizingMask"/> + </navigationBar> + <connections> + <segue destination="zOM-us-BHp" kind="relationship" relationship="rootViewController" id="Cs0-7s-oVR"/> + </connections> + </navigationController> + <placeholder placeholderIdentifier="IBFirstResponder" id="c5B-LX-9rY" userLabel="First Responder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="-566" y="143"/> + </scene> + <!--View Controller--> + <scene sceneID="BPo-UM-NNL"> + <objects> + <viewController id="zOM-us-BHp" sceneMemberID="viewController"> + <layoutGuides> + <viewControllerLayoutGuide type="top" id="Lps-eE-m7k"/> + <viewControllerLayoutGuide type="bottom" id="OgW-31-HCB"/> + </layoutGuides> + <view key="view" contentMode="scaleToFill" id="GmX-eQ-kCs"> + <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> + <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> + </view> + <navigationItem key="navigationItem" id="LPh-IM-uvN"/> + </viewController> + <placeholder placeholderIdentifier="IBFirstResponder" id="PWI-c5-979" userLabel="First Responder" sceneMemberID="firstResponder"/> + </objects> + <point key="canvasLocation" x="249" y="143"/> + </scene> + </scenes> +</document>