WIP: Implement local database caching/networking with KMP

This commit is contained in:
William Brawner 2020-12-24 18:02:05 -07:00
parent f1e36df8c4
commit cf4226d20c
19 changed files with 280 additions and 11 deletions

View file

@ -77,8 +77,8 @@ class CategoryFormActivity : AppCompatActivity() {
return true return true
} }
override fun onOptionsItemSelected(item: MenuItem?): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item?.itemId) { when (item.itemId) {
android.R.id.home -> { android.R.id.home -> {
val upIntent: Intent? = NavUtils.getParentActivityIntent(this) val upIntent: Intent? = NavUtils.getParentActivityIntent(this)

View file

@ -171,8 +171,8 @@ class TransactionFormActivity : AppCompatActivity(), CoroutineScope {
return true return true
} }
override fun onOptionsItemSelected(item: MenuItem?): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item?.itemId) { when (item.itemId) {
android.R.id.home -> onNavigateUp() android.R.id.home -> onNavigateUp()
R.id.action_save -> { R.id.action_save -> {
val date = GregorianCalendar.getInstance().apply { val date = GregorianCalendar.getInstance().apply {

View file

@ -4,11 +4,11 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
android { android {
compileSdkVersion 29 compileSdkVersion 30
defaultConfig { defaultConfig {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 29 targetSdkVersion 30
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

View file

@ -16,6 +16,7 @@ buildscript {
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.1.1' classpath 'com.android.tools.build:gradle:4.1.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.squareup.sqldelight:gradle-plugin:1.4.3'
} }
} }

View file

@ -4,12 +4,12 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
android { android {
compileSdkVersion 29 compileSdkVersion 30
defaultConfig { defaultConfig {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 29 targetSdkVersion 30
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"

View file

@ -1 +1 @@
include ':android', ':budgetlib', ':common', ':storage' include ':android', ':budgetlib', ':common', ':storage', ':shared'

1
shared/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/build

98
shared/build.gradle.kts Normal file
View file

@ -0,0 +1,98 @@
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
kotlin("multiplatform")
id("com.android.library")
id("kotlin-android-extensions")
kotlin("plugin.serialization") version "1.4.10"
id("com.squareup.sqldelight")
}
group = "com.wbrawner.twigs"
version = "1.0-SNAPSHOT"
repositories {
gradlePluginPortal()
google()
jcenter()
mavenCentral()
}
kotlin {
android()
ios {
binaries {
framework {
baseName = "twigs"
}
}
}
sourceSets {
val commonMain by getting {
dependencies {
implementation("io.ktor:ktor-client-core:1.4.2")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.1")
implementation("io.ktor:ktor-client-serialization:1.4.2")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val androidMain by getting {
dependencies {
implementation("com.google.android.material:material:1.2.0")
implementation("com.squareup.sqldelight:android-driver:1.4.3")
api("io.ktor:ktor-client-android:1.4.2")
}
}
val androidTest by getting {
dependencies {
implementation(kotlin("test-junit"))
implementation("junit:junit:4.12")
}
}
val iosMain by getting {
dependencies {
implementation("io.ktor:ktor-client-ios:1.4.2")
implementation("com.squareup.sqldelight:native-driver:1.4.3")
}
}
val iosTest by getting
}
}
sqldelight {
database("TwigsDatabase") {
packageName = "com.wbrawner.twigs"
}
}
android {
compileSdkVersion(30)
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdkVersion(23)
targetSdkVersion(30)
versionCode = 1
versionName = "1.0"
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
}
}
}
val packForXcode by tasks.creating(Sync::class) {
group = "build"
val mode = System.getenv("CONFIGURATION") ?: "DEBUG"
val sdkName = System.getenv("SDK_NAME") ?: "iphonesimulator"
val targetName = "ios" + if (sdkName.startsWith("iphoneos")) "Arm64" else "X64"
val framework = kotlin.targets.getByName<KotlinNativeTarget>(targetName).binaries.getFramework(mode)
inputs.property("mode", mode)
dependsOn(framework.linkTask)
val targetDir = File(buildDir, "xcode-frameworks")
from({ framework.outputDirectory })
into(targetDir)
}
tasks.getByName("build").dependsOn(packForXcode)

21
shared/proguard-rules.pro vendored Normal file
View file

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.kts.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.wbrawner.twigs.android"/>

View file

@ -0,0 +1,12 @@
package com.wbrawner.twigs.shared
import android.content.Context
import com.squareup.sqldelight.android.AndroidSqliteDriver
import com.squareup.sqldelight.db.SqlDriver
import com.wbrawner.twigs.TwigsDatabase
actual class DriverFactory(private val context: Context) {
actual fun createDriver(): SqlDriver {
return AndroidSqliteDriver(TwigsDatabase.Schema, context, "twigs.db")
}
}

View file

@ -0,0 +1,84 @@
package com.wbrawner.twigs.shared
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
data class Summary(
@SerialName("domains_being_blocked")
val domainsBeingBlocked: String,
@SerialName("dns_queries_today")
val dnsQueriesToday: String,
@SerialName("ads_blocked_today")
val adsBlockedToday: String,
@SerialName("ads_percentage_today")
val adsPercentageToday: String,
@SerialName("unique_domains")
val uniqueDomains: String,
@SerialName("queries_forwarded")
val queriesForwarded: String,
@SerialName("clients_ever_seen")
val clientsEverSeen: String,
@SerialName("unique_clients")
val uniqueClients: String,
@SerialName("dns_queries_all_types")
val dnsQueriesAllTypes: String,
@SerialName("queries_cached")
val queriesCached: String,
@SerialName("no_data_replies")
val noDataReplies: String? = null,
@SerialName("nx_domain_replies")
val nxDomainReplies: String? = null,
@SerialName("cname_replies")
val cnameReplies: String? = null,
@SerialName("in_replies")
val ipReplies: String? = null,
@SerialName("privacy_level")
val privacyLevel: String,
override val status: Status,
@SerialName("gravity_last_updated")
val gravity: Gravity? = null,
val type: String? = null,
val version: Int? = null
) : StatusProvider
@Serializable
enum class Status {
@SerialName("enabled")
ENABLED,
@SerialName("disabled")
DISABLED
}
@Serializable
data class Gravity(
@SerialName("file_exists")
val fileExists: Boolean,
val absolute: Int,
val relative: Relative
)
@Serializable
data class Relative(
val days: String,
val hours: String,
val minutes: String
)
@Serializable
data class VersionResponse(val version: Int)
@Serializable
data class TopItemsResponse(
@SerialName("top_queries") val topQueries: Map<String, String>,
@SerialName("top_ads") val topAds: Map<String, Double>
)
@Serializable
data class StatusResponse(
override val status: Status
) : StatusProvider
interface StatusProvider {
val status: Status
}

View file

@ -0,0 +1,16 @@
package com.wbrawner.twigs.shared
import com.squareup.sqldelight.db.SqlDriver
import com.wbrawner.twigs.TwigsDatabase
expect class DriverFactory {
fun createDriver(): SqlDriver
}
fun createDatabase(driverFactory: DriverFactory): TwigsDatabase {
val driver = driverFactory.createDriver()
val database = TwigsDatabase(driver)
// Do more work with the database (see below).
return database
}

View file

@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS budget (
id TEXT PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
description TEXT,
currencyCode TEXT
);

View file

@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS budget (
id TEXT PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
description TEXT,
currencyCode TEXT
);

View file

@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS budget (
id TEXT PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
description TEXT,
currencyCode TEXT
);

View file

@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS budget (
id TEXT PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
description TEXT,
currencyCode TEXT
);

View file

@ -0,0 +1,10 @@
package com.wbrawner.twigs.shared
import com.squareup.sqldelight.db.SqlDriver
import com.wbrawner.twigs.TwigsDatabase
actual class DriverFactory {
actual fun createDriver(): SqlDriver {
return NativeSqliteDriver(TwigsDatabase.Schema, "twigs.db")
}
}

View file

@ -4,12 +4,12 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
android { android {
compileSdkVersion 29 compileSdkVersion 30
defaultConfig { defaultConfig {
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 29 targetSdkVersion 30
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"