mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 17:18:52 -06:00
Implement database access (with migrations)
This commit is contained in:
@@ -67,6 +67,7 @@ dependencies {
|
||||
implementation 'com.android.support:appcompat-v7:28.0.0'
|
||||
implementation files("../core/build/libs/core-jvm.jar")
|
||||
implementation "com.facebook.react:react-native:0.57.8"
|
||||
implementation 'org.sqldroid:sqldroid:1.0.3'
|
||||
implementation project(':react-native-svg')
|
||||
|
||||
testImplementation 'junit:junit:4.12'
|
||||
|
||||
19
android/gradle/wrapper/gradle-wrapper.properties
vendored
19
android/gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,3 +1,22 @@
|
||||
#
|
||||
# Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-bin.zip
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.habits
|
||||
|
||||
import junit.framework.Assert.*
|
||||
import org.isoron.uhabits.utils.*
|
||||
import org.junit.*
|
||||
|
||||
class AndroidDatabaseTest : BaseTest() {
|
||||
@Test
|
||||
fun testUsage() {
|
||||
val dbFile = fileOpener.openUserFile("test.sqlite3")
|
||||
if (dbFile.exists()) dbFile.delete()
|
||||
val db = databaseOpener.open(dbFile)
|
||||
|
||||
var stmt = db.prepareStatement("drop table if exists demo")
|
||||
stmt.step()
|
||||
stmt.finalize()
|
||||
|
||||
stmt = db.prepareStatement("begin")
|
||||
stmt.step()
|
||||
stmt.finalize()
|
||||
|
||||
stmt = db.prepareStatement("create table if not exists demo(key int, value text)")
|
||||
stmt.step()
|
||||
stmt.finalize()
|
||||
|
||||
stmt = db.prepareStatement("insert into demo(key, value) values (?1, ?2)")
|
||||
stmt.bindInt(1, 42)
|
||||
stmt.bindText(2, "Hello World")
|
||||
stmt.step()
|
||||
stmt.finalize()
|
||||
|
||||
stmt = db.prepareStatement("select * from demo where key > ?1")
|
||||
stmt.bindInt(1, 10)
|
||||
var result = stmt.step()
|
||||
assertEquals(result, StepResult.ROW)
|
||||
assertEquals(stmt.getInt(0), 42)
|
||||
assertEquals(stmt.getText(1), "Hello World")
|
||||
result = stmt.step()
|
||||
assertEquals(result, StepResult.DONE)
|
||||
stmt.finalize()
|
||||
|
||||
stmt = db.prepareStatement("drop table demo")
|
||||
stmt.step()
|
||||
stmt.finalize()
|
||||
|
||||
stmt = db.prepareStatement("commit")
|
||||
stmt.step()
|
||||
stmt.finalize()
|
||||
|
||||
db.close()
|
||||
dbFile.delete()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.habits
|
||||
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
import java.io.*
|
||||
|
||||
class AndroidFilesTest : BaseTest() {
|
||||
|
||||
@Test
|
||||
fun testUserFiles() {
|
||||
val file = File(context.filesDir, "test.txt")
|
||||
file.writeText("Hello world!")
|
||||
|
||||
val af = fileOpener.openUserFile("test.txt")
|
||||
assertTrue(af.exists())
|
||||
af.delete()
|
||||
assertFalse(af.exists())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testResourceFiles() {
|
||||
val file = fileOpener.openResourceFile("migrations/010.sql")
|
||||
val lines = file.readLines()
|
||||
assertEquals("delete from Score", lines[0])
|
||||
}
|
||||
}
|
||||
28
android/src/androidTest/java/org/isoron/habits/BaseTest.kt
Normal file
28
android/src/androidTest/java/org/isoron/habits/BaseTest.kt
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.habits
|
||||
|
||||
import android.support.test.*
|
||||
|
||||
open class BaseTest {
|
||||
val context = InstrumentationRegistry.getTargetContext()
|
||||
val fileOpener = AndroidFileOpener(context)
|
||||
val databaseOpener = AndroidDatabaseOpener()
|
||||
}
|
||||
1
android/src/main/assets
Symbolic link
1
android/src/main/assets
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../core/assets/main/
|
||||
Binary file not shown.
33
android/src/main/java/org/isoron/habits/AndroidDatabase.kt
Normal file
33
android/src/main/java/org/isoron/habits/AndroidDatabase.kt
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.habits
|
||||
|
||||
import org.isoron.uhabits.database.*
|
||||
import org.isoron.uhabits.utils.*
|
||||
import java.sql.*
|
||||
|
||||
class AndroidDatabaseOpener : DatabaseOpener {
|
||||
override fun open(file: UserFile): Database {
|
||||
val platformFile = file as AndroidUserFile
|
||||
DriverManager.registerDriver(Class.forName("org.sqldroid.SQLDroidDriver").newInstance() as Driver)
|
||||
val conn = DriverManager.getConnection("jdbc:sqlite:${platformFile.file.absolutePath}")
|
||||
return JavaDatabase(conn, AndroidLog())
|
||||
}
|
||||
}
|
||||
62
android/src/main/java/org/isoron/habits/AndroidFiles.kt
Normal file
62
android/src/main/java/org/isoron/habits/AndroidFiles.kt
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.habits
|
||||
|
||||
import android.content.*
|
||||
import org.isoron.uhabits.utils.*
|
||||
import java.io.*
|
||||
import java.util.*
|
||||
|
||||
|
||||
class AndroidFileOpener(val context: Context) : FileOpener {
|
||||
override fun openUserFile(filename: String): UserFile {
|
||||
return AndroidUserFile(File(context.filesDir, filename))
|
||||
}
|
||||
|
||||
override fun openResourceFile(filename: String): ResourceFile {
|
||||
return AndroidResourceFile(context, filename)
|
||||
}
|
||||
}
|
||||
|
||||
class AndroidResourceFile(val context: Context,
|
||||
val filename: String) : ResourceFile {
|
||||
|
||||
override fun readLines(): List<String> {
|
||||
val asset = context.assets.open(filename)
|
||||
val reader = BufferedReader(InputStreamReader(asset))
|
||||
val lines = ArrayList<String>()
|
||||
while (true) {
|
||||
val line = reader.readLine() ?: break
|
||||
lines.add(line)
|
||||
}
|
||||
return lines
|
||||
}
|
||||
}
|
||||
|
||||
class AndroidUserFile(val file: File) : UserFile {
|
||||
override fun delete() {
|
||||
file.delete()
|
||||
}
|
||||
|
||||
override fun exists(): Boolean {
|
||||
return file.exists()
|
||||
}
|
||||
|
||||
}
|
||||
32
android/src/main/java/org/isoron/habits/AndroidLog.kt
Normal file
32
android/src/main/java/org/isoron/habits/AndroidLog.kt
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2019 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.isoron.habits
|
||||
|
||||
import org.isoron.uhabits.utils.*
|
||||
|
||||
class AndroidLog : Log {
|
||||
override fun debug(msg: String) {
|
||||
android.util.Log.d("LOOP", msg)
|
||||
}
|
||||
|
||||
override fun info(msg: String) {
|
||||
android.util.Log.i("LOOP", msg)
|
||||
}
|
||||
}
|
||||
@@ -24,24 +24,17 @@ import com.facebook.react.modules.core.DeviceEventManagerModule.*
|
||||
import org.isoron.uhabits.*
|
||||
|
||||
|
||||
class CoreModule(
|
||||
private val context: ReactApplicationContext
|
||||
) : ReactContextBaseJavaModule(context) {
|
||||
class CoreModule(private val context: ReactApplicationContext) : ReactContextBaseJavaModule(context) {
|
||||
|
||||
private var backend = Backend(AndroidDatabaseOpener(),
|
||||
AndroidFileOpener(context),
|
||||
AndroidLog())
|
||||
|
||||
private var backend = Backend()
|
||||
private lateinit var emitter: RCTDeviceEventEmitter
|
||||
|
||||
override fun initialize() {
|
||||
super.initialize()
|
||||
emitter = context.getJSModule(RCTDeviceEventEmitter::class.java)
|
||||
backend.createHabit("Wake up early")
|
||||
backend.createHabit("Wash clothes")
|
||||
backend.createHabit("Exercise")
|
||||
backend.createHabit("Meditate")
|
||||
backend.createHabit("Take vitamins")
|
||||
backend.createHabit("Write 'the quick brown fox jumps over the lazy dog' daily")
|
||||
backend.createHabit("Write journal")
|
||||
backend.createHabit("Study French")
|
||||
}
|
||||
|
||||
override fun getName(): String {
|
||||
@@ -50,15 +43,17 @@ class CoreModule(
|
||||
|
||||
@ReactMethod
|
||||
fun requestHabitList() {
|
||||
val params = Arguments.createArray()
|
||||
for ((id, data) in backend.getHabitList()) {
|
||||
params.pushMap(Arguments.createMap().apply {
|
||||
putString("key", id.toString())
|
||||
putString("name", data["name"] as String)
|
||||
putInt("color", data["color"] as Int)
|
||||
val result = backend.getHabitList()
|
||||
val data = Arguments.createArray()
|
||||
for (r in result) {
|
||||
data.pushMap(Arguments.createMap().apply {
|
||||
for ((key, value) in r) {
|
||||
if (value is String) putString(key, value)
|
||||
else if (value is Int) putInt(key, value)
|
||||
}
|
||||
})
|
||||
}
|
||||
emitter.emit("onHabitList", params)
|
||||
emitter.emit("onHabitList", data)
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
|
||||
Reference in New Issue
Block a user