diff --git a/core/assets/main/migrations/023.sql b/core/assets/main/migrations/023.sql new file mode 100644 index 000000000..456a4d071 --- /dev/null +++ b/core/assets/main/migrations/023.sql @@ -0,0 +1 @@ +create table Preferences(key text unique not null, value text not null) \ No newline at end of file diff --git a/core/src/commonMain/kotlin/org/isoron/uhabits/Config.kt b/core/src/commonMain/kotlin/org/isoron/uhabits/Config.kt index 38568d2da..fe543e044 100644 --- a/core/src/commonMain/kotlin/org/isoron/uhabits/Config.kt +++ b/core/src/commonMain/kotlin/org/isoron/uhabits/Config.kt @@ -19,4 +19,4 @@ package org.isoron.uhabits -const val LOOP_DATABASE_VERSION = 22 \ No newline at end of file +const val LOOP_DATABASE_VERSION = 23 \ No newline at end of file diff --git a/core/src/commonMain/kotlin/org/isoron/uhabits/backend/Backend.kt b/core/src/commonMain/kotlin/org/isoron/uhabits/backend/Backend.kt index 200f4095a..62b45d81e 100644 --- a/core/src/commonMain/kotlin/org/isoron/uhabits/backend/Backend.kt +++ b/core/src/commonMain/kotlin/org/isoron/uhabits/backend/Backend.kt @@ -47,6 +47,8 @@ class Backend(databaseName: String, val strings = localeHelper.getStringsForCurrentLocale() + val preferences: Preferences + var theme: Theme = LightTheme() init { @@ -57,6 +59,7 @@ class Backend(databaseName: String, } database = databaseOpener.open(dbFile) database.migrateTo(LOOP_DATABASE_VERSION, fileOpener, log) + preferences = Preferences(PreferencesRepository(database)) habitsRepository = HabitRepository(database) checkmarkRepository = CheckmarkRepository(database) taskRunner.runInBackground { diff --git a/core/src/commonMain/kotlin/org/isoron/uhabits/models/Preferences.kt b/core/src/commonMain/kotlin/org/isoron/uhabits/models/Preferences.kt new file mode 100644 index 000000000..2c5e51449 --- /dev/null +++ b/core/src/commonMain/kotlin/org/isoron/uhabits/models/Preferences.kt @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2016-2019 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker 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. + * + * Loop Habit Tracker 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, see . + */ + +package org.isoron.uhabits.models + +class Preferences(private val repository: PreferencesRepository) { + var showArchived = repository.getBoolean("show_archived", false) + set(value) { + repository.putBoolean("show_archived", value) + field = value + } + + var showCompleted = repository.getBoolean("show_completed", true) + set(value) { + repository.putBoolean("show_completed", value) + field = value + } + + var nightMode = repository.getBoolean("night_mode", false) + set(value) { + repository.putBoolean("night_mode", value) + field = value + } +} \ No newline at end of file diff --git a/core/src/commonMain/kotlin/org/isoron/uhabits/models/PreferencesRepository.kt b/core/src/commonMain/kotlin/org/isoron/uhabits/models/PreferencesRepository.kt new file mode 100644 index 000000000..8c0d77f06 --- /dev/null +++ b/core/src/commonMain/kotlin/org/isoron/uhabits/models/PreferencesRepository.kt @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2016-2019 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker 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. + * + * Loop Habit Tracker 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, see . + */ + +package org.isoron.uhabits.models + +import org.isoron.platform.io.* + +class PreferencesRepository(private val db: Database) { + + private val insertStatement = db.prepareStatement("insert into Preferences(key, value) values (?, ?)") + private val deleteStatement = db.prepareStatement("delete from Preferences where key=?") + private val selectStatement = db.prepareStatement("select value from Preferences where key=?") + + fun putBoolean(key: String, value: Boolean) { + putString(key, value.toString()) + } + + fun getBoolean(key: String, default: Boolean): Boolean { + val value = getString(key, "NULL") + return if (value == "NULL") default else value.toBoolean() + } + + fun putLong(key: String, value: Long) { + putString(key, value.toString()) + } + + fun getLong(key: String, default: Long): Long { + val value = getString(key, "NULL") + return if (value == "NULL") default else value.toLong() + } + + fun putString(key: String, value: String) { + deleteStatement.bindText(0, key) + deleteStatement.step() + deleteStatement.reset() + insertStatement.bindText(0, key) + insertStatement.bindText(1, value) + insertStatement.step() + insertStatement.reset() + } + + fun getString(key: String, default: String): String { + selectStatement.bindText(0, key) + if (selectStatement.step() == StepResult.DONE) { + selectStatement.reset() + return default + } else { + val value = selectStatement.getText(0) + selectStatement.reset() + return value + } + } +} \ No newline at end of file diff --git a/core/src/jvmTest/kotlin/org/isoron/platform/JavaDatabaseTest.kt b/core/src/jvmTest/kotlin/org/isoron/platform/io/JavaDatabaseTest.kt similarity index 98% rename from core/src/jvmTest/kotlin/org/isoron/platform/JavaDatabaseTest.kt rename to core/src/jvmTest/kotlin/org/isoron/platform/io/JavaDatabaseTest.kt index 261698d7e..a6b82ec70 100644 --- a/core/src/jvmTest/kotlin/org/isoron/platform/JavaDatabaseTest.kt +++ b/core/src/jvmTest/kotlin/org/isoron/platform/io/JavaDatabaseTest.kt @@ -17,7 +17,7 @@ * with this program. If not, see . */ -package org.isoron.platform +package org.isoron.platform.io import org.isoron.platform.io.* import org.isoron.uhabits.BaseTest diff --git a/core/src/jvmTest/kotlin/org/isoron/uhabits/backend/BackendTest.kt b/core/src/jvmTest/kotlin/org/isoron/uhabits/backend/BackendTest.kt index 6087423b0..48eca06d3 100644 --- a/core/src/jvmTest/kotlin/org/isoron/uhabits/backend/BackendTest.kt +++ b/core/src/jvmTest/kotlin/org/isoron/uhabits/backend/BackendTest.kt @@ -32,21 +32,21 @@ class BackendTest : BaseTest() { val dbFilename = "uhabits${Random().nextInt()}.db" val dbFile = fileOpener.openUserFile(dbFilename) - @Before - override fun setUp() { - super.setUp() - if (dbFile.exists()) dbFile.delete() - backend = Backend(dbFilename, - databaseOpener, - fileOpener, - log, - taskRunner) - } - - @After - fun tearDown() { - dbFile.delete() - } +// @Before +// override fun setUp() { +// super.setUp() +// if (dbFile.exists()) dbFile.delete() +// backend = Backend(dbFilename, +// databaseOpener, +// fileOpener, +// log, +// taskRunner) +// } +// +// @After +// fun tearDown() { +// dbFile.delete() +// } // @Test // fun testMainScreenDataSource() { diff --git a/core/src/jvmTest/kotlin/org/isoron/uhabits/models/PreferencesRepositoryTest.kt b/core/src/jvmTest/kotlin/org/isoron/uhabits/models/PreferencesRepositoryTest.kt new file mode 100644 index 000000000..6787f8ddb --- /dev/null +++ b/core/src/jvmTest/kotlin/org/isoron/uhabits/models/PreferencesRepositoryTest.kt @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2016-2019 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker 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. + * + * Loop Habit Tracker 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, see . + */ + +package org.isoron.uhabits.models + +import junit.framework.TestCase.* +import org.isoron.uhabits.* +import org.junit.* + +class PreferencesRepositoryTest : BaseTest() { + @Test + fun testUsage() { + val prefs = PreferencesRepository(db) + + assertEquals("default", prefs.getString("non_existing_key", "default")) + prefs.putString("ringtone_path", "/tmp") + assertEquals("/tmp", prefs.getString("ringtone_path", "none")) + + assertEquals(42, prefs.getLong("non_existing_key", 42)) + prefs.putLong("times_launched", 130) + assertEquals(130, prefs.getLong("times_launched", 0)) + + assertEquals(true, prefs.getBoolean("non_existing_key", true)) + assertEquals(false, prefs.getBoolean("non_existing_key", false)) + prefs.putBoolean("show_archived", true) + assertEquals(true, prefs.getBoolean("show_archived", false)) + } +} \ No newline at end of file diff --git a/ios/Application/Info.plist b/ios/Application/Info.plist index b189a173c..bb68c7e1f 100644 --- a/ios/Application/Info.plist +++ b/ios/Application/Info.plist @@ -2,12 +2,10 @@ - UIAppFonts - - fonts/FontAwesome.ttf - CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Loop CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -24,6 +22,12 @@ 1 LSRequiresIPhoneOS + UIAppFonts + + fonts/FontAwesome.ttf + + UILaunchStoryboardName + Launch.storyboard UIRequiredDeviceCapabilities armv7 @@ -34,8 +38,6 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight - UILaunchStoryboardName - Launch.storyboard UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait diff --git a/ios/Application/Platform/IosDatabase.swift b/ios/Application/Platform/IosDatabase.swift index 62e9833da..cd5954661 100644 --- a/ios/Application/Platform/IosDatabase.swift +++ b/ios/Application/Platform/IosDatabase.swift @@ -100,7 +100,6 @@ class IosDatabase : NSObject, Database { if sql.isEmpty { fatalError("Provided SQL query is empty") } - log.debug(tag: "IosDatabase", msg: "Preparing: \(sql)") var statement : OpaquePointer? let result = sqlite3_prepare_v2(db, sql, -1, &statement, nil) if result == SQLITE_OK { diff --git a/ios/uhabits.xcodeproj/project.pbxproj b/ios/uhabits.xcodeproj/project.pbxproj index 3f967f475..c0e4f2891 100644 --- a/ios/uhabits.xcodeproj/project.pbxproj +++ b/ios/uhabits.xcodeproj/project.pbxproj @@ -253,7 +253,7 @@ attributes = { LastSwiftUpdateCheck = 1010; LastUpgradeCheck = 1010; - ORGANIZATIONNAME = "Loop Habit Tracker"; + ORGANIZATIONNAME = Loop; TargetAttributes = { 00A5B42322009F590024E00C = { CreatedOnToolsVersion = 10.1; @@ -492,6 +492,7 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = R5YTHGE3PS; ENABLE_BITCODE = NO; @@ -507,6 +508,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = org.isoron.uhabits; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = Application/BridgingHeader.h; SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; @@ -517,6 +519,7 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = R5YTHGE3PS; ENABLE_BITCODE = NO; @@ -532,6 +535,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = org.isoron.uhabits; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_OBJC_BRIDGING_HEADER = Application/BridgingHeader.h; SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2";