Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions Fruitties/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[*.{kt,kts}]
# Kotlin style typically requires functions to start with a lowercase letter.
# Composable functions should start with a capital letter.
ktlint_function_naming_ignore_when_annotated_with = Composable
Comment thread
cartland marked this conversation as resolved.

# ktlint always puts a new line after a multi-line assignment, like this:
# val colors =
# if (darkTheme) {
# darkColorScheme(
# primary = Color(0xFFBB86FC),
# secondary = Color(0xFF03DAC5),
# tertiary = Color(0xFF3700B3),
# )
# } else {
# lightColorScheme(
# primary = Color(0xFF6200EE),
# secondary = Color(0xFF03DAC5),
# tertiary = Color(0xFF3700B3),
# )
# }
# But we actually prefer to keep some multi-line assignments on the same line, like this:
# val colors = if (darkTheme) {
# darkColorScheme(
# primary = Color(0xFFBB86FC),
# secondary = Color(0xFF03DAC5),
# tertiary = Color(0xFF3700B3),
# )
# } else {
# lightColorScheme(
# primary = Color(0xFF6200EE),
# secondary = Color(0xFF03DAC5),
# tertiary = Color(0xFF3700B3),
# )
# }
ktlint_standard_multiline-expression-wrapping = disabled
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import com.example.fruitties.di.Factory
class App : Application() {
/** AppContainer instance used by the rest of classes to obtain dependencies */
lateinit var container: AppContainer

override fun onCreate() {
super.onCreate()
container = AppContainer(Factory(this))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ fun ListScreen() {
topBar = {
CenterAlignedTopAppBar(
title = {
Text(text = stringResource(R.string.frutties),)
Text(text = stringResource(R.string.frutties))
},
colors = TopAppBarColors(
containerColor = MaterialTheme.colorScheme.primary,
Expand All @@ -105,7 +105,7 @@ fun ListScreen() {
contentWindowInsets = WindowInsets.safeDrawing.only(
// Do not include Bottom so scrolled content is drawn below system bars.
// Include Horizontal because some devices have camera cutouts on the side.
WindowInsetsSides.Top + WindowInsetsSides.Horizontal
WindowInsetsSides.Top + WindowInsetsSides.Horizontal,
),
) { paddingValues ->
Column(
Expand Down Expand Up @@ -145,8 +145,8 @@ fun ListScreen() {
item {
Spacer(
Modifier.windowInsetsBottomHeight(
WindowInsets.systemBars
)
WindowInsets.systemBars,
),
)
}
}
Expand Down Expand Up @@ -216,7 +216,10 @@ fun FruittieItem(
}

@Composable
fun CartDetailsView(cart: List<CartItemDetails>, modifier: Modifier = Modifier) {
fun CartDetailsView(
cart: List<CartItemDetails>,
modifier: Modifier = Modifier,
) {
Column(
modifier.padding(horizontal = 32.dp),
) {
Expand Down
4 changes: 2 additions & 2 deletions Fruitties/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ dataStore = "1.1.4"
kotlin = "2.1.10"
kotlinx-coroutines = "1.10.1"
kotlinxDatetime = "0.6.1"
ksp = "2.1.10-1.0.29"
ksp = "2.1.10-1.0.30"
ktorVersion = "3.0.3"
pagingComposeAndroid = "3.3.6"
skie = "0.10.1"
Expand Down Expand Up @@ -54,7 +54,7 @@ compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview"
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
kotlinx-atomicfu = { module = "org.jetbrains.kotlinx:atomicfu", version.ref = "atomicfu" }
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" }
kotlinx-coroutines-core-iosarm64 = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core-iossimulatorarm64", version.ref = "kotlinx-coroutines" }
kotlinx-coroutines-core-iosarm64 = { module = "org.jetbrains.kotlinx:kotlinx-kotlinx-coroutines-core-iosarm64", version.ref = "kotlinx-coroutines" }
kotlinx-coroutines-core-iossimulatorarm64 = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core-iossimulatorarm64", version.ref = "kotlinx-coroutines" }
Comment thread
cartland marked this conversation as resolved.
Outdated
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinxDatetime" }
ktor-client-android = { module = "io.ktor:ktor-client-android", version.ref = "ktorVersion" }
Expand Down
4 changes: 2 additions & 2 deletions Fruitties/iosApp/iosApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@
"-framework",
shared,
);
PRODUCT_BUNDLE_IDENTIFIER = orgIdentifier.iosApp;
PRODUCT_BUNDLE_IDENTIFIER = com.example.fruitties.ios;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
Expand Down Expand Up @@ -362,7 +362,7 @@
"-framework",
shared,
);
PRODUCT_BUNDLE_IDENTIFIER = orgIdentifier.iosApp;
PRODUCT_BUNDLE_IDENTIFIER = com.example.fruitties.ios;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
Expand Down
6 changes: 3 additions & 3 deletions Fruitties/iosApp/iosApp/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
</dict>
<key>UILaunchScreen</key>
<dict/>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
Expand All @@ -42,7 +44,5 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UILaunchScreen</key>
<dict/>
</dict>
</plist>
</plist>
7 changes: 4 additions & 3 deletions Fruitties/shared/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
alias(libs.plugins.kotlinMultiplatform)
Expand Down Expand Up @@ -53,22 +51,26 @@ kotlin {
// project can be found here:
// https://developer.android.com/kotlin/multiplatform/migrate
val xcfName = "shared"
val iosBundleId = "com.example.fruitties.ios"
Comment thread
cartland marked this conversation as resolved.
Outdated

iosX64 {
binaries.framework {
baseName = xcfName
binaryOptions["bundleId"] = iosBundleId
}
}

iosArm64 {
binaries.framework {
baseName = xcfName
binaryOptions["bundleId"] = iosBundleId
}
}

iosSimulatorArm64 {
binaries.framework {
baseName = xcfName
binaryOptions["bundleId"] = iosBundleId
}
}

Expand Down Expand Up @@ -138,7 +140,6 @@ kotlin {
}
}
}

}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,31 @@ import androidx.room.Room
import androidx.sqlite.driver.bundled.BundledSQLiteDriver
import com.example.fruitties.database.AppDatabase
import com.example.fruitties.database.CartDataStore
import com.example.fruitties.database.dbFileName
import com.example.fruitties.database.DB_FILE_NAME
import com.example.fruitties.network.FruittieApi
import kotlinx.coroutines.Dispatchers

actual class Factory(private val app: Application) {
actual class Factory(
private val app: Application,
) {
actual fun createRoomDatabase(): AppDatabase {
val dbFile = app.getDatabasePath(dbFileName)
return Room.databaseBuilder<AppDatabase>(
context = app,
name = dbFile.absolutePath,
)
.setDriver(BundledSQLiteDriver())
val dbFile = app.getDatabasePath(DB_FILE_NAME)
return Room
.databaseBuilder<AppDatabase>(
context = app,
name = dbFile.absolutePath,
).setDriver(BundledSQLiteDriver())
.setQueryCoroutineContext(Dispatchers.IO)
.build()
}

actual fun createCartDataStore(): CartDataStore {
return CartDataStore {
app.filesDir.resolve(
"cart.json",
).absolutePath
actual fun createCartDataStore(): CartDataStore =
CartDataStore {
app.filesDir
.resolve(
"cart.json",
).absolutePath
}
}

actual fun createApi(): FruittieApi = commonCreateApi()
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,7 @@ class DataRepository(
return loadData()
}

fun loadData(): Flow<List<Fruittie>> {
return database.fruittieDao().getAllAsFlow()
}
fun loadData(): Flow<List<Fruittie>> = database.fruittieDao().getAllAsFlow()

suspend fun refreshData() {
val response = api.getData()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ abstract class AppDatabase : RoomDatabase() {
expect object AppDatabaseConstructor : RoomDatabaseConstructor<AppDatabase> {
override fun initialize(): AppDatabase
}
internal const val dbFileName = "fruits.db"

internal const val DB_FILE_NAME = "fruits.db"
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,28 @@ import okio.use
data class Cart(
val items: List<CartItem>,
)

@Serializable
data class CartItem(
val id: Long,
val count: Int,
)

internal object CartJsonSerializer : OkioSerializer<Cart> {
override val defaultValue: Cart = Cart(emptyList())
override suspend fun readFrom(source: BufferedSource): Cart {
return json.decodeFromString<Cart>(source.readUtf8())
}
override suspend fun writeTo(t: Cart, sink: BufferedSink) {

override suspend fun readFrom(source: BufferedSource): Cart = json.decodeFromString<Cart>(source.readUtf8())

override suspend fun writeTo(
t: Cart,
sink: BufferedSink,
) {
sink.use {
it.writeUtf8(json.encodeToString(Cart.serializer(), t))
}
}
}

class CartDataStore(
private val produceFilePath: () -> String,
) {
Expand All @@ -63,9 +69,15 @@ class CartDataStore(
)
val cart: Flow<Cart>
get() = db.data

suspend fun add(fruittie: Fruittie) = update(fruittie, 1)

suspend fun remove(fruittie: Fruittie) = update(fruittie, -1)
suspend fun update(fruittie: Fruittie, diff: Int) {

suspend fun update(
fruittie: Fruittie,
diff: Int,
) {
db.updateData { prevCart ->
val newItems = mutableListOf<CartItem>()
var found = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import kotlinx.coroutines.flow.Flow

@Dao
interface FruittieDao {

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(fruittie: Fruittie)

Expand All @@ -46,5 +45,5 @@ interface FruittieDao {
@MapColumn(columnName = "id")
Long,
Fruittie,
>
>
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,20 @@ import kotlinx.serialization.json.Json

expect class Factory {
fun createRoomDatabase(): AppDatabase

fun createApi(): FruittieApi

fun createCartDataStore(): CartDataStore
}

internal fun commonCreateApi(): FruittieApi = FruittieNetworkApi(
client = HttpClient {
install(ContentNegotiation) {
json(json, contentType = ContentType.Any)
}
},
apiUrl = "https://android.github.io/kotlin-multiplatform-samples/fruitties-api",
)
internal fun commonCreateApi(): FruittieApi =
FruittieNetworkApi(
client = HttpClient {
install(ContentNegotiation) {
json(json, contentType = ContentType.Any)
}
},
apiUrl = "https://android.github.io/kotlin-multiplatform-samples/fruitties-api",
)

val json = Json { ignoreUnknownKeys = true }
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ interface FruittieApi {
suspend fun getData(pageNumber: Int = 0): FruittiesResponse
}

class FruittieNetworkApi(private val client: HttpClient, private val apiUrl: String) : FruittieApi {

class FruittieNetworkApi(
private val client: HttpClient,
private val apiUrl: String,
) : FruittieApi {
override suspend fun getData(pageNumber: Int): FruittiesResponse {
val url = "$apiUrl/$pageNumber.json"
return try {
Expand Down
Loading