Commit e20e7d69 authored by Kateryna Kostiuk's avatar Kateryna Kostiuk Committed by Andreas Traczyk

database: create database and tables

this patch:
- adds sqlite.swift to dependencies
- creates database
- creates tables
- adds basics queries

Change-Id: I178097aebaa62d73886132ee7a86bb4a9734d25b
Reviewed-by: Andreas Traczyk's avatarAndreas Traczyk <andreas.traczyk@savoirfairelinux.com>
parent 120ecee4
......@@ -6,3 +6,4 @@ github "SwiftyBeaver/SwiftyBeaver" ~> 1.0
github "ViccAlexander/Chameleon"
github "andreamazz/AMPopTip"
github "ashleymills/Reachability.swift"
github "stephencelis/SQLite.swift" ~> 0.11.4
......@@ -8,3 +8,4 @@ github "andreamazz/AMPopTip" "3.0.2"
github "ashleymills/Reachability.swift" "v4.1.0"
github "pkluz/PKHUD" "5.0.0"
github "realm/realm-cocoa" "v3.0.1"
github "stephencelis/SQLite.swift" "0.11.4"
......@@ -80,6 +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 */; };
0E0FF1A71FC38070003898C2 /* SQLite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E0FF1A61FC38070003898C2 /* SQLite.framework */; };
0E0FF1AA1FC3843E003898C2 /* RingDB.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0FF1A91FC3843E003898C2 /* RingDB.swift */; };
0E0FF1AF1FC38CBC003898C2 /* ProfileDataHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0FF1AE1FC38CBC003898C2 /* ProfileDataHelper.swift */; };
0E0FF1B51FC3947B003898C2 /* DBBridging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0FF1B41FC3947B003898C2 /* DBBridging.swift */; };
0E0FF1B71FC398B3003898C2 /* ConversationDataHepler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0FF1B61FC398B3003898C2 /* ConversationDataHepler.swift */; };
0E0FF1B91FC398C5003898C2 /* InteractionDataHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E0FF1B81FC398C5003898C2 /* InteractionDataHelper.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 */; };
......@@ -318,6 +324,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>"; };
0E0FF1A61FC38070003898C2 /* SQLite.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SQLite.framework; path = Carthage/Build/iOS/SQLite.framework; sourceTree = "<group>"; };
0E0FF1A91FC3843E003898C2 /* RingDB.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RingDB.swift; sourceTree = "<group>"; };
0E0FF1AE1FC38CBC003898C2 /* ProfileDataHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileDataHelper.swift; sourceTree = "<group>"; };
0E0FF1B41FC3947B003898C2 /* DBBridging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DBBridging.swift; sourceTree = "<group>"; };
0E0FF1B61FC398B3003898C2 /* ConversationDataHepler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationDataHepler.swift; sourceTree = "<group>"; };
0E0FF1B81FC398C5003898C2 /* InteractionDataHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InteractionDataHelper.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>"; };
......@@ -466,6 +478,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0E0FF1A71FC38070003898C2 /* SQLite.framework in Frameworks */,
5C093F011FB495830011D90E /* Differentiator.framework in Frameworks */,
0ED666101F9FED1C00743D42 /* AMPopTip.framework in Frameworks */,
0EEFBA3C1F83DA21000EDBAD /* libsecp256k1.a in Frameworks */,
......@@ -576,6 +589,7 @@
02AED8171DD4C4B000F740BA /* Frameworks */ = {
isa = PBXGroup;
children = (
0E0FF1A61FC38070003898C2 /* SQLite.framework */,
5C093F001FB495830011D90E /* Differentiator.framework */,
0ED6660F1F9FED1C00743D42 /* AMPopTip.framework */,
62DFAB2B1F9FF030002D6F9C /* Reachability.framework */,
......@@ -710,6 +724,7 @@
043999F51D1C2D9D00E99CD9 /* Ring */ = {
isa = PBXGroup;
children = (
0E0FF1A81FC38409003898C2 /* Database */,
02E1A0261DDE4C2E00D75B59 /* Services */,
1A2D18B81F2916BA00B2C785 /* Models */,
564C44571E8D7F68000F92B1 /* Constants */,
......@@ -819,6 +834,26 @@
name = SYS_DEPS;
sourceTree = "<group>";
};
0E0FF1A81FC38409003898C2 /* Database */ = {
isa = PBXGroup;
children = (
0E0FF1AB1FC38BD1003898C2 /* DBHelpers */,
0E0FF1A91FC3843E003898C2 /* RingDB.swift */,
0E0FF1B41FC3947B003898C2 /* DBBridging.swift */,
);
path = Database;
sourceTree = "<group>";
};
0E0FF1AB1FC38BD1003898C2 /* DBHelpers */ = {
isa = PBXGroup;
children = (
0E0FF1AE1FC38CBC003898C2 /* ProfileDataHelper.swift */,
0E0FF1B61FC398B3003898C2 /* ConversationDataHepler.swift */,
0E0FF1B81FC398C5003898C2 /* InteractionDataHelper.swift */,
);
path = DBHelpers;
sourceTree = "<group>";
};
0E5AFE0A1F8EBC040040D539 /* Cells */ = {
isa = PBXGroup;
children = (
......@@ -1317,6 +1352,7 @@
"$(SRCROOT)/Carthage/build/iOS/AMPopTip.framework",
"$(SRCROOT)/Carthage/Build/iOS/Reachability.framework",
"$(SRCROOT)/Carthage/Build/iOS/Differentiator.framework",
"$(SRCROOT)/Carthage/Build/iOS/SQLite.framework",
);
name = "⚙️ Copy Frameworks";
outputPaths = (
......@@ -1332,6 +1368,7 @@
"$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/Chameleon.framework",
"$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/AMPopTip.framework",
"$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/Differentiator.framework",
"$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/SQLite.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
......@@ -1406,9 +1443,12 @@
1ABE07D31F0D8FE800D36361 /* Storyboards.swift in Sources */,
0EDE34C71F868E1200FFA15C /* EditProfileViewController.swift in Sources */,
62A88D3B1F6C3ACC00F8AB18 /* PresenceService.swift in Sources */,
0E0FF1B51FC3947B003898C2 /* DBBridging.swift in Sources */,
1A2D18E51F29197100B2C785 /* MessageAccessoryView.swift in Sources */,
0E0FF1B91FC398C5003898C2 /* InteractionDataHelper.swift in Sources */,
1A2D18C61F29180700B2C785 /* ConversationModel.swift in Sources */,
0EE1B54E1F75ACDE00BA98EE /* CNContactVCardSerialization+Helpers.swift in Sources */,
0E0FF1AA1FC3843E003898C2 /* RingDB.swift in Sources */,
56308BA71EA00E5700660275 /* NameRegistrationResponse.m in Sources */,
1A3CA32D1F13DA7200283748 /* Chameleon+Ring.swift in Sources */,
0ED2B6FC1F96A158001572F0 /* LinkNewDeviceViewController.swift in Sources */,
......@@ -1436,6 +1476,7 @@
1A2D18B71F29164700B2C785 /* SmartlistViewModel.swift in Sources */,
04399AAE1D1C304300E99CD9 /* Utils.mm in Sources */,
56BBC9A31ED714DF00CDAF8B /* ConversationsService.swift in Sources */,
0E0FF1AF1FC38CBC003898C2 /* ProfileDataHelper.swift in Sources */,
563AEC771EA664C0003A5641 /* RegistrationResponse.m in Sources */,
564C445B1E8EA44E000F92B1 /* Durations.swift in Sources */,
0EB479951FA28A7300106AFD /* ButtonTransparentBackground.swift in Sources */,
......@@ -1459,6 +1500,7 @@
564C44621E943DE6000F92B1 /* NameService.swift in Sources */,
1A5DC02C1F3565250075E8EF /* MeViewController.swift in Sources */,
1A2041801F1E903B00C08435 /* CreateProfileViewController.swift in Sources */,
0E0FF1B71FC398B3003898C2 /* ConversationDataHepler.swift in Sources */,
62DFAB2E1F9FF0D0002D6F9C /* NetworkService.swift in Sources */,
0EDE34C91F8691BB00FFA15C /* EditProfileViewModel.swift in Sources */,
04399AAD1D1C304300E99CD9 /* DRingAdapter.mm in Sources */,
......
......@@ -91,7 +91,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
self.window?.rootViewController = self.appCoordinator.rootViewController
self.window?.makeKeyAndVisible()
self.appCoordinator.start()
self.startDB()
return true
}
......@@ -124,4 +124,18 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
log.error("Unknown error in Daemon stop.")
}
}
private func startDB() {
do {
let dbManager = DBBridging(profileHepler: ProfileDataHelper(),
conversationHelper: ConversationDataHelper(),
interactionHepler: InteractionDataHelper())
try dbManager.start()
} catch {
let time = DispatchTime.now() + 1
DispatchQueue.main.asyncAfter(deadline: time) {
self.appCoordinator.showDatabaseError()
}
}
}
}
......@@ -30,6 +30,10 @@ enum L10n {
static let accountNoNetworkMessage = L10n.tr("Localizable", "alerts.accountNoNetworkMessage")
/// Can't connect to the network
static let accountNoNetworkTitle = L10n.tr("Localizable", "alerts.accountNoNetworkTitle")
/// Please close application and try to open it again
static let dbFailedMessage = L10n.tr("Localizable", "alerts.dbFailedMessage")
/// An error happned when launching Ring
static let dbFailedTitle = L10n.tr("Localizable", "alerts.dbFailedTitle")
/// Cancel
static let profileCancelPhoto = L10n.tr("Localizable", "alerts.profileCancelPhoto")
/// Take photo
......
......@@ -81,6 +81,13 @@ class AppCoordinator: Coordinator, StateableResponsive {
}).disposed(by: self.disposeBag)
}
func showDatabaseError() {
let alertController = UIAlertController(title: L10n.Alerts.dbFailedTitle,
message: L10n.Alerts.dbFailedMessage,
preferredStyle: .alert)
self.present(viewController: alertController, withStyle: .present, withAnimation: false)
}
private func showWalkthrough () {
let walkthroughCoordinator = WalkthroughCoordinator(with: self.injectionBag)
self.addChildCoordinator(childCoordinator: walkthroughCoordinator)
......
/*
* 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 Foundation
import RxSwift
enum ProfileType: String {
case ring = "RING"
case sip = "SIP"
}
enum ProfileStatus: String {
case trusted = "TRUSTED"
case untrasted = "UNTRUSTED"
}
enum MessageDirection {
case incoming
case outgoing
}
enum InteractionStatus: String {
case invalid = "INVALID"
case unknown = "UNKNOWN"
case sending = "SENDING"
case failed = "FAILED"
case succeed = "SUCCEED"
case read = "READ"
case unread = "UNREAD"
func toMessageStatus() -> MessageStatus {
switch self {
case .invalid:
return MessageStatus.unknown
case .unknown:
return MessageStatus.unknown
case .sending:
return MessageStatus.sending
case .failed:
return MessageStatus.failure
case .succeed:
return MessageStatus.sent
case .read:
return MessageStatus.read
case .unread:
return MessageStatus.unknown
}
}
}
enum InteractionType: String {
case invalid = "INVALID"
case text = "TEXT"
case call = "CALL"
case contact = "CONTACT"
}
final class DBBridging {
let profileHepler: ProfileDataHelper
let conversationHelper: ConversationDataHelper
let interactionHepler: InteractionDataHelper
// used to create object to save to db. When inserting in table defaultID will be replaced by autoincrementedID
let defaultID: Int64 = 1
init(profileHepler: ProfileDataHelper, conversationHelper: ConversationDataHelper,
interactionHepler: InteractionDataHelper) {
self.profileHepler = profileHepler
self.conversationHelper = conversationHelper
self.interactionHepler = interactionHepler
}
func start() throws {
try profileHepler.createTable()
try conversationHelper.createTable()
try interactionHepler.createTable()
}
}
/*
* 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 SQLite
typealias Conversation = (
id: Int64,
participantID: Int64
)
final class ConversationDataHelper {
let table = RingDB.instance.tableConversations
let id = Expression<Int64>("id")
let participantId = Expression<Int64>("participant_id")
func createTable() throws {
guard let dataBase = RingDB.instance.ringDB else {
throw DataAccessError.datastoreConnectionError
}
do {
try dataBase.run(table.create(ifNotExists: true) { table in
table.column(id)
table.column(participantId)
table.foreignKey(participantId, references: RingDB.instance.tableProfiles, id, delete: .noAction)
})
} catch _ {
print("Table already exists")
}
}
func insert(item: Conversation) -> Bool {
guard let dataBase = RingDB.instance.ringDB else {
return false
}
let query = table.insert(id <- item.id,
participantId <- item.participantID)
do {
let rowId = try dataBase.run(query)
guard rowId > 0 else {
return false
}
return true
} catch _ {
return false
}
}
func delete (item: Conversation) -> Bool {
guard let dataBase = RingDB.instance.ringDB else {
return false
}
let conversationId = item.id
let query = table.filter(id == conversationId)
do {
let deletedRows = try dataBase.run(query.delete())
guard deletedRows == 1 else {
return false
}
return true
} catch _ {
return false
}
}
func selectConversations (conversationId: Int64) throws -> [Conversation]? {
guard let dataBase = RingDB.instance.ringDB else {
throw DataAccessError.datastoreConnectionError
}
let query = table.filter(id == conversationId)
var conversations = [Conversation]()
let items = try dataBase.prepare(query)
for item in items {
conversations.append(Conversation(id: item[id], participantID: item[participantId]))
}
return conversations
}
func selectAll() throws -> [Conversation]? {
guard let dataBase = RingDB.instance.ringDB else {
throw DataAccessError.datastoreConnectionError
}
var conversations = [Conversation]()
let items = try dataBase.prepare(table)
for item in items {
conversations.append(Conversation(id: item[id], participantID: item[participantId]))
}
return conversations
}
func selectConversationsForProfile(profileId: Int64) throws -> [Conversation]? {
guard let dataBase = RingDB.instance.ringDB else {
throw DataAccessError.datastoreConnectionError
}
var conversations = [Conversation]()
let query = table.filter(participantId == profileId)
let items = try dataBase.prepare(query)
for item in items {
conversations.append(Conversation(id: item[id], participantID: item[participantId]))
}
return conversations
}
func deleteConversations(conversationID: Int64) -> Bool {
guard let dataBase = RingDB.instance.ringDB else {
return false
}
let query = table.filter(id == conversationID)
do {
if try dataBase.run(query.delete()) > 0 {
return true
} else {
return false
}
} catch {
return false
}
}
}
This diff is collapsed.
/*
* 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 SQLite
import SwiftyBeaver
typealias Profile = (
id: Int64,
uri: String,
alias: String?,
photo: String?,
type: String,
status: String
)
final class ProfileDataHelper {
let table = RingDB.instance.tableProfiles
let id = Expression<Int64>("id")
let uri = Expression<String>("uri")
let alias = Expression<String?>("alias")
let photo = Expression<String?>("photo")
let type = Expression<String>("type")
let status = Expression<String>("status")
private let log = SwiftyBeaver.self
func createTable() throws {
guard let dataBase = RingDB.instance.ringDB else {
throw DataAccessError.datastoreConnectionError
}
do {
try dataBase.run(table.create(ifNotExists: true) { table in
table.column(id, primaryKey: .autoincrement)
table.column(uri)
table.column(alias)
table.column(photo)
table.column(type)
table.column(status)
})
} catch _ {
log.error("Table exists")
}
}
func insert(item: Profile) -> Bool {
guard let dataBase = RingDB.instance.ringDB else {
return false
}
let query = table.insert(uri <- item.uri,
alias <- item.alias,
photo <- item.photo,
type <- item.type,
status <- item.status)
do {
let rowId = try dataBase.run(query)
guard rowId > 0 else {
return false
}
return true
} catch _ {
return false
}
}
func delete(item: Profile) -> Bool {
guard let dataBase = RingDB.instance.ringDB else {
return false
}
let profileId = item.id
let query = table.filter(id == profileId)
do {
let deletedRows = try dataBase.run(query.delete())
guard deletedRows == 1 else {
return false
}
return true
} catch _ {
return false
}
}
func selectProfile(profileId: Int64) throws -> Profile? {
guard let dataBase = RingDB.instance.ringDB else {
throw DataAccessError.datastoreConnectionError
}
let query = table.filter(id == profileId)
let items = try dataBase.prepare(query)
for item in items {
return Profile(id: item[id], uri: item[uri], alias: item[alias],
photo: item[photo], type: item[type], status: item[status])
}
return nil
}
func selectAll() throws -> [Profile]? {
guard let dataBase = RingDB.instance.ringDB else {
throw DataAccessError.datastoreConnectionError
}
var profiles = [Profile]()
let items = try dataBase.prepare(table)
for item in items {
profiles.append(Profile(id: item[id], uri: item[uri], alias: item[alias],
photo: item[photo], type: item[type], status: item[status]))
}
return profiles
}
func selectProfile(accountURI: String) throws -> Profile? {
guard let dataBase = RingDB.instance.ringDB else {
throw DataAccessError.datastoreConnectionError
}
let query = table.filter(uri == accountURI)
let items = try dataBase.prepare(query)
// for one URI we should have only one profile
for item in items {
return Profile(id: item[id], uri: item[uri], alias: item[alias],
photo: item[photo], type: item[type], status: item[status])
}
return nil
}
}
/*
* 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 SQLite
import SwiftyBeaver
enum DataAccessError: Error {
case datastoreConnectionError
case databaseError
}
final class RingDB {
static let instance = RingDB()
let ringDB: Connection?
private let log = SwiftyBeaver.self
private let dbName = "ring.db"
//tables
var tableProfiles = Table("profiles")
var tableConversations = Table("conversations")
var tableInteractionss = Table("interactions")
private init() {
let path = NSSearchPathForDirectoriesInDomains(
.documentDirectory, .userDomainMask, true
).first!
do {
ringDB = try Connection("\(path)/" + dbName)
} catch {
ringDB = nil
log.error("Unable to open database")
}
}
}
......@@ -81,6 +81,8 @@
"alerts.profileUploadPhoto" = "Upload photo";
"alerts.profileCancelPhoto" = "Cancel";
"alerts.accountLinkedTitle" = "Linking account";
"alerts.dbFailedTitle" = "An error happned when launching Ring";
"alerts.dbFailedMessage" = "Please close application and try to open it again";
//Account Page
"accountPage.devicesListHeader" = "Devices";
......
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