diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..3f25798e
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,2 @@
+[*.{kt,kts}]
+ktlint_code_style = android_studio
\ No newline at end of file
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 7829f3cf..aca9a1ab 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -6,8 +6,6 @@
-
-
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 4e6d9d06..0b730406 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -18,15 +18,20 @@ android {
buildTypes {
getByName("release") {
isMinifyEnabled = false
- proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
+ proguardFiles(
+ getDefaultProguardFile("proguard-android-optimize.txt"),
+ "proguard-rules.pro"
+ )
}
}
compileOptions {
isCoreLibraryDesugaringEnabled = true
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = "1.8"
}
-
lint {
warningsAsErrors = false
abortOnError = true
diff --git a/build.gradle.kts b/build.gradle.kts
index 153b5796..20c8a830 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,14 +1,10 @@
-
-// https://youtrack.jetbrains.com/issue/KTIJ-19369
-@Suppress("DSL_SCOPE_VIOLATION")
plugins {
- alias(libs.plugins.gradleVersions)
alias(libs.plugins.ktlint) apply false
-
- kotlin("multiplatform") version libs.versions.kotlin.get() apply false
- kotlin("plugin.serialization") version libs.versions.kotlin.get() apply false
- id("app.cash.sqldelight") version libs.versions.sqlDelight.get() apply false
- id("com.android.library") version libs.versions.android.gradle.plugin.get() apply false
+ alias(libs.plugins.kotlin.multiplatform) apply false
+ alias(libs.plugins.sqlDelight) apply false
+ alias(libs.plugins.android.library) apply false
+ alias(libs.plugins.kotlin.serialization) apply false
+ alias(libs.plugins.skie) apply false
}
allprojects {
@@ -19,11 +15,10 @@ allprojects {
}
subprojects {
- // TODO libs doesn't resolve if we do this
- // apply(plugin = libs.plugins.ktlint.get().pluginId)
- apply(plugin = "org.jlleitschuh.gradle.ktlint")
+ apply(plugin = rootProject.libs.plugins.ktlint.get().pluginId)
configure {
+ version.set("1.0.0")
enableExperimentalRules.set(true)
verbose.set(true)
filter {
diff --git a/docs/DEBUGGING_KOTLIN_IN_XCODE.md b/docs/DEBUGGING_KOTLIN_IN_XCODE.md
index acaedfa6..93254776 100644
--- a/docs/DEBUGGING_KOTLIN_IN_XCODE.md
+++ b/docs/DEBUGGING_KOTLIN_IN_XCODE.md
@@ -1,5 +1,7 @@
# Debugging Kotlin in Xcode
+> Note that if there is a [known issue](https://github.com/touchlab/xcode-kotlin/issues/95) with `xcode-kotlin` plugin on Xcode 15
+
By this point you should be able to build and run KaMP Kit in iOS using Xcode. Great! Maybe you've
changed a variable and want to see if it actually updated successfully, but how do you do that? Well
we at Touchlab have actually created a way to **debug kotlin code in Xcode**.
diff --git a/gradle.properties b/gradle.properties
index cb13eb29..57029690 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -15,5 +15,3 @@ android.useAndroidX=true
kotlin.code.style=official
# Tell the KMM plugin where the iOS project lives
xcodeproj=./ios
-# New Android source-set layout
-kotlin.mpp.androidSourceSetLayoutVersion=2
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index ebe41e10..a68d36cf 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,37 +1,36 @@
[versions]
-kotlin = "1.9.0"
-
## SDK Versions
minSdk = "21"
targetSdk = "34"
compileSdk = "34"
# Dependencies
-android-gradle-plugin = "8.0.2"
-ktlint-gradle = "11.4.2"
-gradle-versions = "0.47.0"
+kotlin = "1.9.10"
+
+android-gradle-plugin = "8.1.1"
+ktlint-gradle = "11.6.0"
-compose = "1.5.0"
-composeCompiler = "1.5.2"
+compose = "1.5.2"
+composeCompiler = "1.5.3"
android-desugaring = "2.0.3"
-androidx-core = "1.10.1"
+androidx-core = "1.12.0"
androidx-test-junit = "1.1.5"
androidx-activity-compose = "1.7.2"
-androidx-lifecycle = "2.6.1"
+androidx-lifecycle = "2.6.2"
junit = "4.13.2"
coroutines = "1.7.3"
-kotlinx-datetime = "0.4.0"
-ktor = "2.3.3"
+kotlinx-datetime = "0.4.1"
+ktor = "2.3.4"
robolectric = "4.10.3"
-kermit = "2.0.0-RC3"
+kermit = "2.0.1"
skie = "0.5.0"
-koin = "3.4.3"
+koin = "3.5.0"
multiplatformSettings = "1.0.0"
turbine = "1.0.0"
sqlDelight = "2.0.0"
@@ -90,7 +89,11 @@ kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotl
[plugins]
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint-gradle" }
-gradleVersions = { id = "com.github.ben-manes.versions", version.ref = "gradle-versions" }
+kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
+sqlDelight = { id = "app.cash.sqldelight", version.ref = "sqlDelight" }
+android-library = { id = "com.android.library", version.ref = "android-gradle-plugin" }
+kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
+skie = { id = "co.touchlab.skie", version.ref = "skie" }
[bundles]
app-ui = [
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 7454180f..ccebba77 100644
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 8d99c1fb..a3638774 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Tue Aug 29 21:56:54 EDT 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
+networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index 744e882e..79a61d42 100755
--- a/gradlew
+++ b/gradlew
@@ -1,7 +1,7 @@
-#!/usr/bin/env sh
+#!/bin/sh
#
-# Copyright 2015 the original author or authors.
+# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -17,67 +17,101 @@
#
##############################################################################
-##
-## Gradle start up script for UN*X
-##
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
##############################################################################
# Attempt to set APP_HOME
+
# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-APP_NAME="Gradle"
-APP_BASE_NAME=`basename "$0"`
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD="maximum"
+MAX_FD=maximum
warn () {
echo "$*"
-}
+} >&2
die () {
echo
echo "$*"
echo
exit 1
-}
+} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
-case "`uname`" in
- CYGWIN* )
- cygwin=true
- ;;
- Darwin* )
- darwin=true
- ;;
- MSYS* | MINGW* )
- msys=true
- ;;
- NONSTOP* )
- nonstop=true
- ;;
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
+ JAVACMD=$JAVA_HOME/jre/sh/java
else
- JAVACMD="$JAVA_HOME/bin/java"
+ JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
- JAVACMD="java"
+ JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
@@ -106,80 +140,105 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
- MAX_FD_LIMIT=`ulimit -H -n`
- if [ $? -eq 0 ] ; then
- if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
- MAX_FD="$MAX_FD_LIMIT"
- fi
- ulimit -n $MAX_FD
- if [ $? -ne 0 ] ; then
- warn "Could not set maximum file descriptor limit: $MAX_FD"
- fi
- else
- warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
- fi
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
fi
-# For Darwin, add options to specify how the application appears in the dock
-if $darwin; then
- GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
-fi
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
-if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
- APP_HOME=`cygpath --path --mixed "$APP_HOME"`
- CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
-
- JAVACMD=`cygpath --unix "$JAVACMD"`
-
- # We build the pattern for arguments to be converted via cygpath
- ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
- SEP=""
- for dir in $ROOTDIRSRAW ; do
- ROOTDIRS="$ROOTDIRS$SEP$dir"
- SEP="|"
- done
- OURCYGPATTERN="(^($ROOTDIRS))"
- # Add a user-defined pattern to the cygpath arguments
- if [ "$GRADLE_CYGPATTERN" != "" ] ; then
- OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
- fi
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
# Now convert the arguments - kludge to limit ourselves to /bin/sh
- i=0
- for arg in "$@" ; do
- CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
- CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
-
- if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
- eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
- else
- eval `echo args$i`="\"$arg\""
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
fi
- i=`expr $i + 1`
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
done
- case $i in
- 0) set -- ;;
- 1) set -- "$args0" ;;
- 2) set -- "$args0" "$args1" ;;
- 3) set -- "$args0" "$args1" "$args2" ;;
- 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
- 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
- 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
- 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
- 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
- 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
- esac
fi
-# Escape application args
-save () {
- for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
- echo " "
-}
-APP_ARGS=`save "$@"`
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
-# Collect all arguments for the java command, following the shell quoting and substitution rules
-eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
index ac1b06f9..6689b85b 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -14,7 +14,7 @@
@rem limitations under the License.
@rem
-@if "%DEBUG%" == "" @echo off
+@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -25,7 +25,8 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
-if "%DIRNAME%" == "" set DIRNAME=.
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto execute
+if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end
@rem End local scope for the variables with windows NT shell
-if "%ERRORLEVEL%"=="0" goto mainEnd
+if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
-if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
-exit /b 1
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 8361448c..0f262d4a 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -15,9 +15,9 @@ EXTERNAL SOURCES:
:path: "../shared/"
SPEC CHECKSUMS:
- shared: 200db62f38a2c4a9e496216a640f3782fc761e46
+ shared: ea50f7840493e1a81d5081cf342309e93b0dfa57
SwiftLint: c585ebd615d9520d7fbdbe151f527977b0534f1e
PODFILE CHECKSUM: 3130ca9ec3cd58f2c60cfe8a432d7d96d89938bf
-COCOAPODS: 1.13.0
+COCOAPODS: 1.12.1
diff --git a/ios/Pods/Local Podspecs/shared.podspec.json b/ios/Pods/Local Podspecs/shared.podspec.json
index 24f1aa51..aae8ed6f 100644
--- a/ios/Pods/Local Podspecs/shared.podspec.json
+++ b/ios/Pods/Local Podspecs/shared.podspec.json
@@ -22,11 +22,12 @@
"script": " if [ \"YES\" = \"$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED\" ]; then\n echo \"Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \"YES\"\"\n exit 0\n fi\n set -ev\n REPO_ROOT=\"$PODS_TARGET_SRCROOT\"\n \"$REPO_ROOT/../gradlew\" -p \"$REPO_ROOT\" $KOTLIN_PROJECT_PATH:syncFramework -Pkotlin.native.cocoapods.platform=$PLATFORM_NAME -Pkotlin.native.cocoapods.archs=\"$ARCHS\" -Pkotlin.native.cocoapods.configuration=\"$CONFIGURATION\"\n"
}
],
+ "swift_versions": "5.0",
"platforms": {
"osx": null,
"ios": null,
"tvos": null,
- "visionos": null,
"watchos": null
- }
+ },
+ "swift_version": "5.0"
}
diff --git a/ios/Pods/Manifest.lock b/ios/Pods/Manifest.lock
index 8361448c..0f262d4a 100644
--- a/ios/Pods/Manifest.lock
+++ b/ios/Pods/Manifest.lock
@@ -15,9 +15,9 @@ EXTERNAL SOURCES:
:path: "../shared/"
SPEC CHECKSUMS:
- shared: 200db62f38a2c4a9e496216a640f3782fc761e46
+ shared: ea50f7840493e1a81d5081cf342309e93b0dfa57
SwiftLint: c585ebd615d9520d7fbdbe151f527977b0534f1e
PODFILE CHECKSUM: 3130ca9ec3cd58f2c60cfe8a432d7d96d89938bf
-COCOAPODS: 1.13.0
+COCOAPODS: 1.12.1
diff --git a/ios/Pods/Pods.xcodeproj/project.pbxproj b/ios/Pods/Pods.xcodeproj/project.pbxproj
index 7525eb7b..19e6e65b 100644
--- a/ios/Pods/Pods.xcodeproj/project.pbxproj
+++ b/ios/Pods/Pods.xcodeproj/project.pbxproj
@@ -257,8 +257,8 @@
46EB2E00000000 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastSwiftUpdateCheck = 1500;
- LastUpgradeCheck = 1500;
+ LastSwiftUpdateCheck = 1240;
+ LastUpgradeCheck = 1240;
};
buildConfigurationList = 46EB2E00000030 /* Build configuration list for PBXProject "Pods" */;
compatibilityVersion = "Xcode 10.0";
diff --git a/ios/Pods/Target Support Files/Pods-KaMPKitiOS/Pods-KaMPKitiOS-frameworks.sh b/ios/Pods/Target Support Files/Pods-KaMPKitiOS/Pods-KaMPKitiOS-frameworks.sh
index 4339d470..1e57ae2b 100755
--- a/ios/Pods/Target Support Files/Pods-KaMPKitiOS/Pods-KaMPKitiOS-frameworks.sh
+++ b/ios/Pods/Target Support Files/Pods-KaMPKitiOS/Pods-KaMPKitiOS-frameworks.sh
@@ -18,7 +18,7 @@ echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}"
-SWIFT_STDLIB_PATH="${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
+SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
BCSYMBOLMAP_DIR="BCSymbolMaps"
diff --git a/ios/Pods/Target Support Files/Pods-KaMPKitiOS/Pods-KaMPKitiOS.debug.xcconfig b/ios/Pods/Target Support Files/Pods-KaMPKitiOS/Pods-KaMPKitiOS.debug.xcconfig
index 3f303bf1..edfc6a8e 100644
--- a/ios/Pods/Target Support Files/Pods-KaMPKitiOS/Pods-KaMPKitiOS.debug.xcconfig
+++ b/ios/Pods/Target Support Files/Pods-KaMPKitiOS/Pods-KaMPKitiOS.debug.xcconfig
@@ -1,8 +1,11 @@
+ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/../../shared/build/cocoapods/framework"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
-LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
+LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks'
+LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
OTHER_LDFLAGS = $(inherited) -l"c++" -framework "shared"
+OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
diff --git a/ios/Pods/Target Support Files/Pods-KaMPKitiOS/Pods-KaMPKitiOS.release.xcconfig b/ios/Pods/Target Support Files/Pods-KaMPKitiOS/Pods-KaMPKitiOS.release.xcconfig
index 3f303bf1..edfc6a8e 100644
--- a/ios/Pods/Target Support Files/Pods-KaMPKitiOS/Pods-KaMPKitiOS.release.xcconfig
+++ b/ios/Pods/Target Support Files/Pods-KaMPKitiOS/Pods-KaMPKitiOS.release.xcconfig
@@ -1,8 +1,11 @@
+ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/../../shared/build/cocoapods/framework"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
-LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
+LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks'
+LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
OTHER_LDFLAGS = $(inherited) -l"c++" -framework "shared"
+OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
diff --git a/ios/Pods/Target Support Files/shared/shared.debug.xcconfig b/ios/Pods/Target Support Files/shared/shared.debug.xcconfig
index ee6cdedd..30c20002 100644
--- a/ios/Pods/Target Support Files/shared/shared.debug.xcconfig
+++ b/ios/Pods/Target Support Files/shared/shared.debug.xcconfig
@@ -3,7 +3,9 @@ CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/shared
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/../../shared/build/cocoapods/framework"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
KOTLIN_PROJECT_PATH = :shared
+LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
OTHER_LDFLAGS = $(inherited) -l"c++"
+OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
diff --git a/ios/Pods/Target Support Files/shared/shared.release.xcconfig b/ios/Pods/Target Support Files/shared/shared.release.xcconfig
index ee6cdedd..30c20002 100644
--- a/ios/Pods/Target Support Files/shared/shared.release.xcconfig
+++ b/ios/Pods/Target Support Files/shared/shared.release.xcconfig
@@ -3,7 +3,9 @@ CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/shared
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/../../shared/build/cocoapods/framework"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
KOTLIN_PROJECT_PATH = :shared
+LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
OTHER_LDFLAGS = $(inherited) -l"c++"
+OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts
index 6f93ca1f..e271496b 100644
--- a/shared/build.gradle.kts
+++ b/shared/build.gradle.kts
@@ -1,15 +1,18 @@
@file:Suppress("UnstableApiUsage")
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
plugins {
kotlin("multiplatform")
kotlin("native.cocoapods")
kotlin("plugin.serialization")
id("com.android.library")
id("app.cash.sqldelight")
- id("co.touchlab.skie") version "0.5.0"
+ id("co.touchlab.skie")
}
android {
+ namespace = "co.touchlab.kampkit"
compileSdk = libs.versions.compileSdk.get().toInt()
defaultConfig {
minSdk = libs.versions.minSdk.get().toInt()
@@ -25,17 +28,21 @@ android {
warningsAsErrors = true
abortOnError = true
}
- namespace = "co.touchlab.kampkit"
-
compileOptions {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
}
}
+tasks.withType {
+ kotlinOptions.jvmTarget = "1.8"
+}
+
version = "1.2"
kotlin {
+ @Suppress("OPT_IN_USAGE")
+ targetHierarchy.default()
androidTarget()
ios()
// Note: iosSimulatorArm64 target requires that all dependencies have M1 support
@@ -86,13 +93,6 @@ kotlin {
api(libs.touchlab.kermit.simple)
}
}
- val iosTest by getting
- val iosSimulatorArm64Main by getting {
- dependsOn(iosMain)
- }
- val iosSimulatorArm64Test by getting {
- dependsOn(iosTest)
- }
}
cocoapods {
@@ -103,6 +103,7 @@ kotlin {
linkerOpts("-lsqlite3")
export(libs.touchlab.kermit.simple)
}
+ extraSpecAttributes["swift_version"] = "\"5.0\"" // <- SKIE Needs this!
podfile = project.file("../ios/Podfile")
}
}
diff --git a/shared/shared.podspec b/shared/shared.podspec
index dc2ff960..c9d5fc99 100644
--- a/shared/shared.podspec
+++ b/shared/shared.podspec
@@ -35,5 +35,5 @@ Pod::Spec.new do |spec|
SCRIPT
}
]
-
+ spec.swift_version = "5.0"
end
\ No newline at end of file
diff --git a/shared/src/androidUnitTest/kotlin/co/touchlab/kampkit/KoinTest.kt b/shared/src/androidUnitTest/kotlin/co/touchlab/kampkit/KoinTest.kt
index 4be2ca84..ba8c2b8b 100644
--- a/shared/src/androidUnitTest/kotlin/co/touchlab/kampkit/KoinTest.kt
+++ b/shared/src/androidUnitTest/kotlin/co/touchlab/kampkit/KoinTest.kt
@@ -5,6 +5,8 @@ import android.content.Context
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
import co.touchlab.kermit.Logger
+import kotlin.test.AfterTest
+import kotlin.test.Test
import org.junit.experimental.categories.Category
import org.junit.runner.RunWith
import org.koin.core.context.stopKoin
@@ -13,8 +15,6 @@ import org.koin.dsl.module
import org.koin.test.category.CheckModuleTest
import org.koin.test.check.checkModules
import org.robolectric.annotation.Config
-import kotlin.test.AfterTest
-import kotlin.test.Test
@RunWith(AndroidJUnit4::class)
@Category(CheckModuleTest::class)
diff --git a/shared/src/commonMain/kotlin/co/touchlab/kampkit/DatabaseHelper.kt b/shared/src/commonMain/kotlin/co/touchlab/kampkit/DatabaseHelper.kt
index 66075ac0..6575c122 100644
--- a/shared/src/commonMain/kotlin/co/touchlab/kampkit/DatabaseHelper.kt
+++ b/shared/src/commonMain/kotlin/co/touchlab/kampkit/DatabaseHelper.kt
@@ -19,12 +19,11 @@ class DatabaseHelper(
) {
private val dbRef: KaMPKitDb = KaMPKitDb(sqlDriver)
- fun selectAllItems(): Flow> =
- dbRef.tableQueries
- .selectAll()
- .asFlow()
- .mapToList(Dispatchers.Default)
- .flowOn(backgroundDispatcher)
+ fun selectAllItems(): Flow> = dbRef.tableQueries
+ .selectAll()
+ .asFlow()
+ .mapToList(Dispatchers.Default)
+ .flowOn(backgroundDispatcher)
suspend fun insertBreeds(breeds: List) {
log.d { "Inserting ${breeds.size} breeds into database" }
@@ -35,12 +34,11 @@ class DatabaseHelper(
}
}
- fun selectById(id: Long): Flow> =
- dbRef.tableQueries
- .selectById(id)
- .asFlow()
- .mapToList(Dispatchers.Default)
- .flowOn(backgroundDispatcher)
+ fun selectById(id: Long): Flow> = dbRef.tableQueries
+ .selectById(id)
+ .asFlow()
+ .mapToList(Dispatchers.Default)
+ .flowOn(backgroundDispatcher)
suspend fun deleteAll() {
log.i { "Database Cleared" }
diff --git a/shared/src/commonMain/kotlin/co/touchlab/kampkit/Koin.kt b/shared/src/commonMain/kotlin/co/touchlab/kampkit/Koin.kt
index db7c2df1..f954ec0b 100644
--- a/shared/src/commonMain/kotlin/co/touchlab/kampkit/Koin.kt
+++ b/shared/src/commonMain/kotlin/co/touchlab/kampkit/Koin.kt
@@ -62,7 +62,8 @@ private val coreModule = module {
// uses you *may* want to have a more robust configuration from the native platform. In KaMP Kit,
// that would likely go into platformModule expect/actual.
// See https://github.com/touchlab/Kermit
- val baseLogger = Logger(config = StaticConfig(logWriterList = listOf(platformLogWriter())), "KampKit")
+ val baseLogger =
+ Logger(config = StaticConfig(logWriterList = listOf(platformLogWriter())), "KampKit")
factory { (tag: String?) -> if (tag != null) baseLogger.withTag(tag) else baseLogger }
single {
diff --git a/shared/src/commonMain/kotlin/co/touchlab/kampkit/ktor/DogApiImpl.kt b/shared/src/commonMain/kotlin/co/touchlab/kampkit/ktor/DogApiImpl.kt
index d82c2187..b4c4eeb7 100644
--- a/shared/src/commonMain/kotlin/co/touchlab/kampkit/ktor/DogApiImpl.kt
+++ b/shared/src/commonMain/kotlin/co/touchlab/kampkit/ktor/DogApiImpl.kt
@@ -1,20 +1,20 @@
package co.touchlab.kampkit.ktor
import co.touchlab.kampkit.response.BreedResult
+import co.touchlab.kermit.Logger as KermitLogger
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.engine.HttpClientEngine
import io.ktor.client.plugins.HttpTimeout
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.plugins.logging.LogLevel
+import io.ktor.client.plugins.logging.Logger as KtorLogger
import io.ktor.client.plugins.logging.Logging
import io.ktor.client.request.HttpRequestBuilder
import io.ktor.client.request.get
import io.ktor.http.encodedPath
import io.ktor.http.takeFrom
import io.ktor.serialization.kotlinx.json.json
-import co.touchlab.kermit.Logger as KermitLogger
-import io.ktor.client.plugins.logging.Logger as KtorLogger
class DogApiImpl(private val log: KermitLogger, engine: HttpClientEngine) : DogApi {
diff --git a/shared/src/commonMain/kotlin/co/touchlab/kampkit/models/BreedViewModel.kt b/shared/src/commonMain/kotlin/co/touchlab/kampkit/models/BreedViewModel.kt
index 16467436..5dffe451 100644
--- a/shared/src/commonMain/kotlin/co/touchlab/kampkit/models/BreedViewModel.kt
+++ b/shared/src/commonMain/kotlin/co/touchlab/kampkit/models/BreedViewModel.kt
@@ -95,10 +95,14 @@ class BreedViewModel(
log.e(throwable) { "Error downloading breed list" }
mutableBreedState.update {
when (it) {
- is BreedViewState.Content -> it.copy(isLoading = false) // Just let it fail silently if we have a cache
+ is BreedViewState.Content -> it.copy(
+ isLoading = false
+ ) // Just let it fail silently if we have a cache
is BreedViewState.Empty,
is BreedViewState.Error,
- is BreedViewState.Initial -> BreedViewState.Error(error = "Unable to refresh breed list")
+ is BreedViewState.Initial -> BreedViewState.Error(
+ error = "Unable to refresh breed list"
+ )
}
}
}
diff --git a/shared/src/commonMain/kotlin/co/touchlab/kampkit/sqldelight/CoroutinesExtensions.kt b/shared/src/commonMain/kotlin/co/touchlab/kampkit/sqldelight/CoroutinesExtensions.kt
index 12fe6c71..b383cc0e 100644
--- a/shared/src/commonMain/kotlin/co/touchlab/kampkit/sqldelight/CoroutinesExtensions.kt
+++ b/shared/src/commonMain/kotlin/co/touchlab/kampkit/sqldelight/CoroutinesExtensions.kt
@@ -2,8 +2,8 @@ package co.touchlab.kampkit.sqldelight
import app.cash.sqldelight.Transacter
import app.cash.sqldelight.TransactionWithoutReturn
-import kotlinx.coroutines.withContext
import kotlin.coroutines.CoroutineContext
+import kotlinx.coroutines.withContext
suspend fun Transacter.transactionWithContext(
coroutineContext: CoroutineContext,
diff --git a/shared/src/commonTest/kotlin/co/touchlab/kampkit/BreedRepositoryTest.kt b/shared/src/commonTest/kotlin/co/touchlab/kampkit/BreedRepositoryTest.kt
index 9656b8d3..da9a59d5 100644
--- a/shared/src/commonTest/kotlin/co/touchlab/kampkit/BreedRepositoryTest.kt
+++ b/shared/src/commonTest/kotlin/co/touchlab/kampkit/BreedRepositoryTest.kt
@@ -8,14 +8,14 @@ import co.touchlab.kampkit.models.BreedRepository
import co.touchlab.kermit.Logger
import co.touchlab.kermit.StaticConfig
import com.russhwolf.settings.MapSettings
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.test.runTest
-import kotlinx.datetime.Clock
import kotlin.test.AfterTest
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFails
import kotlin.time.Duration.Companion.hours
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.test.runTest
+import kotlinx.datetime.Clock
class BreedRepositoryTest {
@@ -32,7 +32,8 @@ class BreedRepositoryTest {
// Need to start at non-zero time because the default value for db timestamp is 0
private val clock = ClockMock(Clock.System.now())
- private val repository: BreedRepository = BreedRepository(dbHelper, settings, ktorApi, kermit, clock)
+ private val repository: BreedRepository =
+ BreedRepository(dbHelper, settings, ktorApi, kermit, clock)
companion object {
private val appenzeller = Breed(1, "appenzeller", false)
@@ -60,7 +61,9 @@ class BreedRepositoryTest {
@Test
fun `Get updated breeds with cache and preserve favorites`() = runTest {
val successResult = ktorApi.successResult()
- val resultWithExtraBreed = successResult.copy(message = successResult.message + ("extra" to emptyList()))
+ val resultWithExtraBreed = successResult.copy(
+ message = successResult.message + ("extra" to emptyList())
+ )
ktorApi.prepareResult(resultWithExtraBreed)
dbHelper.insertBreeds(breedNames)
@@ -78,10 +81,15 @@ class BreedRepositoryTest {
@Test
fun `Get updated breeds when stale and preserve favorites`() = runTest {
- settings.putLong(BreedRepository.DB_TIMESTAMP_KEY, (clock.currentInstant - 2.hours).toEpochMilliseconds())
+ settings.putLong(
+ BreedRepository.DB_TIMESTAMP_KEY,
+ (clock.currentInstant - 2.hours).toEpochMilliseconds()
+ )
val successResult = ktorApi.successResult()
- val resultWithExtraBreed = successResult.copy(message = successResult.message + ("extra" to emptyList()))
+ val resultWithExtraBreed = successResult.copy(
+ message = successResult.message + ("extra" to emptyList())
+ )
ktorApi.prepareResult(resultWithExtraBreed)
dbHelper.insertBreeds(breedNames)
@@ -110,7 +118,10 @@ class BreedRepositoryTest {
@Test
fun `No web call if data is not stale`() = runTest {
- settings.putLong(BreedRepository.DB_TIMESTAMP_KEY, clock.currentInstant.toEpochMilliseconds())
+ settings.putLong(
+ BreedRepository.DB_TIMESTAMP_KEY,
+ clock.currentInstant.toEpochMilliseconds()
+ )
ktorApi.prepareResult(ktorApi.successResult())
repository.refreshBreedsIfStale()
@@ -132,7 +143,10 @@ class BreedRepositoryTest {
@Test
fun `Rethrow on API error when stale`() = runTest {
- settings.putLong(BreedRepository.DB_TIMESTAMP_KEY, (clock.currentInstant - 2.hours).toEpochMilliseconds())
+ settings.putLong(
+ BreedRepository.DB_TIMESTAMP_KEY,
+ (clock.currentInstant - 2.hours).toEpochMilliseconds()
+ )
ktorApi.throwOnCall(RuntimeException("Test error"))
val throwable = assertFails {
diff --git a/shared/src/commonTest/kotlin/co/touchlab/kampkit/BreedViewModelTest.kt b/shared/src/commonTest/kotlin/co/touchlab/kampkit/BreedViewModelTest.kt
index 6dcc9021..55a2ddcb 100644
--- a/shared/src/commonTest/kotlin/co/touchlab/kampkit/BreedViewModelTest.kt
+++ b/shared/src/commonTest/kotlin/co/touchlab/kampkit/BreedViewModelTest.kt
@@ -12,6 +12,11 @@ import co.touchlab.kampkit.response.BreedResult
import co.touchlab.kermit.Logger
import co.touchlab.kermit.StaticConfig
import com.russhwolf.settings.MapSettings
+import kotlin.test.AfterTest
+import kotlin.test.BeforeTest
+import kotlin.test.Test
+import kotlin.test.assertEquals
+import kotlin.time.Duration.Companion.hours
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
@@ -19,11 +24,6 @@ import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import kotlinx.datetime.Clock
-import kotlin.test.AfterTest
-import kotlin.test.BeforeTest
-import kotlin.test.Test
-import kotlin.test.assertEquals
-import kotlin.time.Duration.Companion.hours
class BreedViewModelTest {
private var kermit = Logger(StaticConfig())
@@ -39,7 +39,8 @@ class BreedViewModelTest {
// Need to start at non-zero time because the default value for db timestamp is 0
private val clock = ClockMock(Clock.System.now())
- private val repository: BreedRepository = BreedRepository(dbHelper, settings, ktorApi, kermit, clock)
+ private val repository: BreedRepository =
+ BreedRepository(dbHelper, settings, ktorApi, kermit, clock)
private val viewModel by lazy {
BreedViewModel(repository, kermit)
@@ -96,10 +97,15 @@ class BreedViewModelTest {
@Test
fun `Get updated breeds with cache and preserve favorites`() = runTest {
- settings.putLong(BreedRepository.DB_TIMESTAMP_KEY, clock.currentInstant.toEpochMilliseconds())
+ settings.putLong(
+ BreedRepository.DB_TIMESTAMP_KEY,
+ clock.currentInstant.toEpochMilliseconds()
+ )
val successResult = ktorApi.successResult()
- val resultWithExtraBreed = successResult.copy(message = successResult.message + ("extra" to emptyList()))
+ val resultWithExtraBreed = successResult.copy(
+ message = successResult.message + ("extra" to emptyList())
+ )
ktorApi.prepareResult(resultWithExtraBreed)
dbHelper.insertBreeds(breedNames)
@@ -112,7 +118,9 @@ class BreedViewModelTest {
viewModel.refreshBreeds()
// id is 5 here because it incremented twice when trying to insert duplicate breeds
assertEquals(
- BreedViewState.Content(breedViewStateSuccessFavorite.breeds + Breed(5, "extra", false)),
+ BreedViewState.Content(
+ breedViewStateSuccessFavorite.breeds + Breed(5, "extra", false)
+ ),
awaitItemPrecededBy(breedViewStateSuccessFavorite.copy(isLoading = true))
)
}
@@ -120,10 +128,15 @@ class BreedViewModelTest {
@Test
fun `Get updated breeds when stale and preserve favorites`() = runTest {
- settings.putLong(BreedRepository.DB_TIMESTAMP_KEY, (clock.currentInstant - 2.hours).toEpochMilliseconds())
+ settings.putLong(
+ BreedRepository.DB_TIMESTAMP_KEY,
+ (clock.currentInstant - 2.hours).toEpochMilliseconds()
+ )
val successResult = ktorApi.successResult()
- val resultWithExtraBreed = successResult.copy(message = successResult.message + ("extra" to emptyList()))
+ val resultWithExtraBreed = successResult.copy(
+ message = successResult.message + ("extra" to emptyList())
+ )
ktorApi.prepareResult(resultWithExtraBreed)
dbHelper.insertBreeds(breedNames)
@@ -132,7 +145,9 @@ class BreedViewModelTest {
viewModel.breedState.test {
// id is 5 here because it incremented twice when trying to insert duplicate breeds
assertEquals(
- BreedViewState.Content(breedViewStateSuccessFavorite.breeds + Breed(5, "extra", false)),
+ BreedViewState.Content(
+ breedViewStateSuccessFavorite.breeds + Breed(5, "extra", false)
+ ),
awaitItemPrecededBy(BreedViewState.Initial, breedViewStateSuccessFavorite)
)
}
@@ -140,7 +155,10 @@ class BreedViewModelTest {
@Test
fun `Toggle favorite cached breed`() = runTest {
- settings.putLong(BreedRepository.DB_TIMESTAMP_KEY, clock.currentInstant.toEpochMilliseconds())
+ settings.putLong(
+ BreedRepository.DB_TIMESTAMP_KEY,
+ clock.currentInstant.toEpochMilliseconds()
+ )
dbHelper.insertBreeds(breedNames)
dbHelper.updateFavorite(australianLike.id, true)
@@ -159,12 +177,18 @@ class BreedViewModelTest {
@Test
fun `No web call if data is not stale`() = runTest {
- settings.putLong(BreedRepository.DB_TIMESTAMP_KEY, clock.currentInstant.toEpochMilliseconds())
+ settings.putLong(
+ BreedRepository.DB_TIMESTAMP_KEY,
+ clock.currentInstant.toEpochMilliseconds()
+ )
ktorApi.prepareResult(ktorApi.successResult())
dbHelper.insertBreeds(breedNames)
viewModel.breedState.test {
- assertEquals(breedViewStateSuccessNoFavorite, awaitItemPrecededBy(BreedViewState.Initial))
+ assertEquals(
+ breedViewStateSuccessNoFavorite,
+ awaitItemPrecededBy(BreedViewState.Initial)
+ )
assertEquals(0, ktorApi.calledCount)
expectNoEvents()
@@ -192,7 +216,10 @@ class BreedViewModelTest {
@Test
fun `Ignore API error with cache`() = runTest {
dbHelper.insertBreeds(breedNames)
- settings.putLong(BreedRepository.DB_TIMESTAMP_KEY, (clock.currentInstant - 2.hours).toEpochMilliseconds())
+ settings.putLong(
+ BreedRepository.DB_TIMESTAMP_KEY,
+ (clock.currentInstant - 2.hours).toEpochMilliseconds()
+ )
ktorApi.throwOnCall(RuntimeException("Test error"))
viewModel.breedState.test {
@@ -235,7 +262,10 @@ class BreedViewModelTest {
@Test
fun `Show API error on refresh without cache`() = runTest {
- settings.putLong(BreedRepository.DB_TIMESTAMP_KEY, clock.currentInstant.toEpochMilliseconds())
+ settings.putLong(
+ BreedRepository.DB_TIMESTAMP_KEY,
+ clock.currentInstant.toEpochMilliseconds()
+ )
ktorApi.throwOnCall(RuntimeException("Test error"))
viewModel.breedState.test {
@@ -253,7 +283,9 @@ class BreedViewModelTest {
// There's a race condition where intermediate states can get missed if the next state comes too fast.
// This function addresses that by awaiting an item that may or may not be preceded by the specified other items
-private suspend fun ReceiveTurbine.awaitItemPrecededBy(vararg items: BreedViewState): BreedViewState {
+private suspend fun ReceiveTurbine.awaitItemPrecededBy(
+ vararg items: BreedViewState
+): BreedViewState {
var nextItem = awaitItem()
for (item in items) {
if (item == nextItem) {
diff --git a/shared/src/commonTest/kotlin/co/touchlab/kampkit/DogApiTest.kt b/shared/src/commonTest/kotlin/co/touchlab/kampkit/DogApiTest.kt
index 77998e35..d390d87b 100644
--- a/shared/src/commonTest/kotlin/co/touchlab/kampkit/DogApiTest.kt
+++ b/shared/src/commonTest/kotlin/co/touchlab/kampkit/DogApiTest.kt
@@ -13,10 +13,10 @@ import io.ktor.http.ContentType
import io.ktor.http.HttpHeaders
import io.ktor.http.HttpStatusCode
import io.ktor.http.headersOf
-import kotlinx.coroutines.test.runTest
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
+import kotlinx.coroutines.test.runTest
class DogApiTest {
private val emptyLogger = Logger(
@@ -32,8 +32,13 @@ class DogApiTest {
val engine = MockEngine {
assertEquals("https://dog.ceo/api/breeds/list/all", it.url.toString())
respond(
- content = """{"message":{"affenpinscher":[],"african":["shepherd"]},"status":"success"}""",
- headers = headersOf(HttpHeaders.ContentType, ContentType.Application.Json.toString())
+ content = """
+ {"message":{"affenpinscher":[],"african":["shepherd"]},"status":"success"}
+ """.trimIndent(),
+ headers = headersOf(
+ HttpHeaders.ContentType,
+ ContentType.Application.Json.toString()
+ )
)
}
val dogApi = DogApiImpl(emptyLogger, engine)
diff --git a/shared/src/commonTest/kotlin/co/touchlab/kampkit/SqlDelightTest.kt b/shared/src/commonTest/kotlin/co/touchlab/kampkit/SqlDelightTest.kt
index 1bb86861..609a8f8e 100644
--- a/shared/src/commonTest/kotlin/co/touchlab/kampkit/SqlDelightTest.kt
+++ b/shared/src/commonTest/kotlin/co/touchlab/kampkit/SqlDelightTest.kt
@@ -2,13 +2,13 @@ package co.touchlab.kampkit
import co.touchlab.kermit.Logger
import co.touchlab.kermit.StaticConfig
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.test.runTest
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.test.runTest
class SqlDelightTest {
diff --git a/shared/src/iosMain/kotlin/co/touchlab/kampkit/KoinIOS.kt b/shared/src/iosMain/kotlin/co/touchlab/kampkit/KoinIOS.kt
index 5dd611ee..148244db 100644
--- a/shared/src/iosMain/kotlin/co/touchlab/kampkit/KoinIOS.kt
+++ b/shared/src/iosMain/kotlin/co/touchlab/kampkit/KoinIOS.kt
@@ -37,8 +37,7 @@ actual val platformModule = module {
// Access from Swift to create a logger
@Suppress("unused")
-fun Koin.loggerWithTag(tag: String) =
- get(qualifier = null) { parametersOf(tag) }
+fun Koin.loggerWithTag(tag: String) = get(qualifier = null) { parametersOf(tag) }
@Suppress("unused") // Called from Swift
object KotlinDependencies : KoinComponent {
diff --git a/shared/src/iosTest/kotlin/co/touchlab/kampkit/KoinTest.kt b/shared/src/iosTest/kotlin/co/touchlab/kampkit/KoinTest.kt
index 99cf751d..834b8dfc 100644
--- a/shared/src/iosTest/kotlin/co/touchlab/kampkit/KoinTest.kt
+++ b/shared/src/iosTest/kotlin/co/touchlab/kampkit/KoinTest.kt
@@ -1,12 +1,12 @@
package co.touchlab.kampkit
import co.touchlab.kermit.Logger
+import kotlin.test.AfterTest
+import kotlin.test.Test
import org.koin.core.context.stopKoin
import org.koin.core.parameter.parametersOf
import org.koin.test.check.checkModules
import platform.Foundation.NSUserDefaults
-import kotlin.test.AfterTest
-import kotlin.test.Test
class KoinTest {
@Test