Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
29 changes: 29 additions & 0 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Build

on:
pull_request:
branches: [ main ]
workflow_dispatch:

env:
GRADLE_OPTS: "-Dorg.gradle.jvmargs=-Xmx4096M -Dorg.gradle.daemon=false -Dorg.gradle.parallel=true -Dorg.gradle.caching=true"
jobs:
build-android:
name: Build Android
runs-on: ubuntu-latest
needs: test
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Gradle setup
uses: ./.github/actions/gradle-setup

- name: Build Android debug APK
run: ./gradlew :mobile:assembleDebug

- name: Upload Android debug APK
uses: actions/upload-artifact@v4
with:
name: android-apk
path: mobile/build/outputs/apk/debug/*.apk
37 changes: 37 additions & 0 deletions .github/workflows/ios.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Build

on:
pull_request:
branches: [ main ]
workflow_dispatch:

env:
GRADLE_OPTS: "-Dorg.gradle.jvmargs=-Xmx4096M -Dorg.gradle.daemon=false -Dorg.gradle.parallel=true -Dorg.gradle.caching=true"
jobs:
#...
build-ios:
name: Build iOS simulator app
runs-on: macos-latest
needs: test
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Gradle setup
uses: ./.github/actions/gradle-setup

- name: Build iOS simulator app
run: |
xcodebuild build \
-project JetcasterMigration/JetcasterMigration.xcodeproj \
-configuration Debug \
-scheme JetcasterMigration \
-sdk iphonesimulator \
-derivedDataPath ./build \
-verbose

- name: Upload app folder
uses: actions/upload-artifact@v4
with:
name: iphonesimulator-app
path: build/Build/Products/Debug-iphonesimulator/*
27 changes: 26 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ androidx-espresso = "3.7.0"
androidx-lifecycle = "2.11.0-beta01"
androidx-testExt = "1.3.0"
composeMultiplatform = "1.11.1"
iconsMaterialSymbolsOutlinedCmp = "2.2.1"
iconsLucideCmp = "2.2.1"
junit = "4.13.2"
kotlin = "2.4.0"
material3 = "1.11.0-alpha07"
Expand All @@ -25,10 +27,15 @@ jetbrainsKotlinJvm = "2.4.0"
room = "2.8.4"
sqlite = "2.6.2"
kermit = "2.0.5"

multiplatform-nav3-ui = "1.1.1"
compose-multiplatform-adaptive = "1.3.0-beta02"
compose-multiplatform-lifecycle = "2.10.0"
coil3 = "3.5.0"


[libraries]
icons-lucide-cmp = { module = "com.composables:icons-lucide-cmp", version.ref = "iconsLucideCmp" }
icons-material-symbols-outlined-cmp = { module = "com.composables:icons-material-symbols-outlined-cmp", version.ref = "iconsMaterialSymbolsOutlinedCmp" }
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
kotlin-testJunit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" }
junit = { module = "junit:junit", version.ref = "junit" }
Expand All @@ -55,15 +62,26 @@ ktor-client-darwin = { module = "io.ktor:ktor-client-darwin", version.ref = "kto
ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
kotlinx-serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinSeralization" }
#metro-compiler = { module = "dev.zacsweers.metro:compiler", version.ref = "metro" }
metro-viewmodel = { module = "dev.zacsweers.metro:metrox-viewmodel-compose", version.ref = "metro" }
kermit = { module = "co.touchlab:kermit", version.ref = "kermit" }

#Room3
androidx-sqlite-bundled = { module = "androidx.sqlite:sqlite-bundled", version.ref = "sqlite" }
androidx-room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }

#Navigation
jetbrains-navigation3-ui = { module = "org.jetbrains.androidx.navigation3:navigation3-ui", version.ref = "multiplatform-nav3-ui" }
jetbrains-material3-adaptiveNavigation3 = { module = "org.jetbrains.compose.material3.adaptive:adaptive-navigation3", version.ref = "compose-multiplatform-adaptive" }
jetbrains-lifecycle-viewmodelNavigation3 = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-navigation3", version.ref = "compose-multiplatform-lifecycle" }
#androidx-room-sqlite-wrapper = { module = "androidx.room:room-sqlite-wrapper", version.ref = "room" }


#Coil3
coil-compose = { module = "io.coil-kt.coil3:coil-compose", version.ref = "coil3" }
coil-compose-core = { module = "io.coil-kt.coil3:coil-compose-core", version.ref = "coil3" }
coil-network-ktor3 = { module = "io.coil-kt.coil3:coil-network-ktor3", version.ref = "coil3" }

[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
androidMultiplatformLibrary = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" }
Expand All @@ -75,3 +93,10 @@ metro-di = {id = "dev.zacsweers.metro", version.ref = "metro"}
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp"}
android-library = { id = "com.android.library", version.ref = "agp" }
androidx-room = { id = "androidx.room", version.ref = "room" }

[bundles]
coil = [
"coil-compose",
"coil-compose-core",
"coil-network-ktor3"
]
25 changes: 24 additions & 1 deletion shared/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
alias(libs.plugins.kotlinMultiplatform)
Expand Down Expand Up @@ -27,6 +26,11 @@ kotlin {
}
}

compilerOptions {
freeCompilerArgs.add("-Xexplicit-backing-fields")
}


androidLibrary {
namespace = "com.wahid.newscmp.shared"
compileSdk = libs.versions.android.compileSdk.get().toInt()
Expand Down Expand Up @@ -60,13 +64,24 @@ kotlin {
implementation(libs.androidx.lifecycle.viewmodelCompose)
implementation(libs.androidx.lifecycle.runtimeCompose)

//navigation
implementation(libs.jetbrains.navigation3.ui)
implementation(libs.jetbrains.material3.adaptiveNavigation3)
implementation(libs.jetbrains.lifecycle.viewmodelNavigation3)

//Ktor
implementation(libs.ktor.serialization.kotlinx.json)
implementation(libs.ktor.client.core)
implementation(libs.ktor.logging)
implementation(libs.ktor.client.content.negotiation)
implementation(libs.kotlinx.serialization)

//Metro
implementation(libs.metro.viewmodel)

//Coil3
implementation(libs.bundles.coil)


//Room3
implementation(libs.androidx.room.runtime)
Expand All @@ -76,6 +91,14 @@ kotlin {
implementation(libs.kermit)




implementation(libs.icons.material.symbols.outlined.cmp)

// Lucide Icons (1.6k icons)
implementation(libs.icons.lucide.cmp)


}
iosMain.dependencies {
implementation(libs.ktor.client.darwin)
Expand Down

This file was deleted.

26 changes: 12 additions & 14 deletions shared/src/commonMain/kotlin/com/wahid/newscmp/App.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package com.wahid.newscmp

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import co.touchlab.kermit.Logger
import com.wahid.newscmp.di.AppGraph
import com.wahid.newscmp.presentation.navigation.AppNavigationHost
import dev.zacsweers.metro.createGraph
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.onEach
import dev.zacsweers.metrox.viewmodel.LocalMetroViewModelFactory


val appGraph = createGraph<AppGraph>()
Expand All @@ -18,18 +21,13 @@ val logger = Logger.withTag("NewsScreen")
@Preview
fun App() {
MaterialTheme {
CompositionLocalProvider(
LocalMetroViewModelFactory provides appGraph.metroViewModelFactory

LaunchedEffect(Unit){
newsRepository.getAllNews(mapOf("q" to "bitcoin"),false)
.onEach { articles ->
logger.d { "Articles count: ${articles.size}" }
logger.d { "First: ${articles.firstOrNull()}" }
}
.catch { e -> logger.e(e) { "Flow error" } }
.collect { articles ->
// update UI state
}

) {
AppNavigationHost(
modifier = Modifier.fillMaxSize()
)
}
}
}
9 changes: 0 additions & 9 deletions shared/src/commonMain/kotlin/com/wahid/newscmp/Greeting.kt

This file was deleted.

This file was deleted.

7 changes: 0 additions & 7 deletions shared/src/commonMain/kotlin/com/wahid/newscmp/Platform.kt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.wahid.newscmp.data.local.room.entity
import androidx.room.Entity
import kotlin.time.Instant

@Entity(tableName = "Article",primaryKeys = ["id"])
@Entity(tableName = "Article",primaryKeys = ["url"])
data class ArticleEntity(
val id: String,
val isFavorite: Boolean,
Expand All @@ -12,6 +12,7 @@ data class ArticleEntity(
val description: String,
val publishedAt: String,
val title: String,
val source: String,
val url: String,
val urlToImage: String,
val lastUpdate: Instant
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package com.wahid.newscmp.data.remote.datasource

import com.wahid.newscmp.data.remote.dto.NewsResponse
import com.wahid.newscmp.utils.Result

interface NewsRemoteDatasource {
suspend fun getAllNews(query: Map<String, String>): NewsResponse
suspend fun getHeadlinesNews(query: Map<String, String>): NewsResponse
suspend fun getAllNews(query: Map<String, String>): Result<NewsResponse>
suspend fun getHeadlinesNews(query: Map<String, String>): Result<NewsResponse>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.wahid.newscmp.data.remote.datasource

import com.wahid.newscmp.data.remote.dto.NewsResponse
import com.wahid.newscmp.data.remote.service.NewsService
import com.wahid.newscmp.utils.Result
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding
import dev.zacsweers.metro.Inject
Expand All @@ -12,11 +13,11 @@ import dev.zacsweers.metro.Inject
class NewsRemoteDatasourceImpl(
private val newsService: NewsService
): NewsRemoteDatasource {
override suspend fun getAllNews(query: Map<String, String>): NewsResponse {
override suspend fun getAllNews(query: Map<String, String>): Result<NewsResponse> {
return newsService.getAllNews(query = query)
}

override suspend fun getHeadlinesNews(query: Map<String, String>): NewsResponse {
override suspend fun getHeadlinesNews(query: Map<String, String>): Result<NewsResponse> {
return newsService.getHeadlinesNews(query = query)
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
package com.wahid.newscmp.data.remote.service

import com.wahid.newscmp.data.remote.dto.NewsResponse
import com.wahid.newscmp.utils.Result
import com.wahid.newscmp.utils.getQueryUrlString
import com.wahid.newscmp.utils.getResults
import dev.zacsweers.metro.Inject
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.request.url

@Inject
class NewsService(private val httpClient: HttpClient) {

suspend fun getAllNews(query: Map<String, String>): NewsResponse {
val url = "everything${query.getQueryUrlString()}"
return httpClient.get(urlString = url).body<NewsResponse>()
}
suspend fun getAllNews(query: Map<String, String>): Result<NewsResponse> =
httpClient.getResults<NewsResponse> {
url("everything${query.getQueryUrlString()}")
}


suspend fun getHeadlinesNews(query: Map<String, String>): Result<NewsResponse> =
httpClient.getResults<NewsResponse> {
url("top-headlines${query.getQueryUrlString()}")
}

suspend fun getHeadlinesNews(query: Map<String, String>): NewsResponse {
val url = "top-headlines${query.getQueryUrlString()}"
return httpClient.get(urlString = url).body<NewsResponse>()
}

}
Loading