Skip to content

Commit 3239e5c

Browse files
committed
Initial support for compose multiplatform
Signed-off-by: Aayush Gupta <[email protected]>
1 parent 7283701 commit 3239e5c

File tree

22 files changed

+199
-0
lines changed

22 files changed

+199
-0
lines changed

build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@
55

66
plugins {
77
alias(libs.plugins.android.application) apply false
8+
alias(libs.plugins.android.library) apply false
89
alias(libs.plugins.jetbrains.kotlin.android) apply false
910
alias(libs.plugins.jetbrains.kotlin.kapt) apply false
11+
alias(libs.plugins.jetbrains.kotlin.compose) apply false
12+
alias(libs.plugins.jetbrains.kotlin.multiplatform) apply false
13+
alias(libs.plugins.jetbrains.compose.multiplatform) apply false
14+
alias(libs.plugins.jetbrains.compose.hotreload) apply false
1015
alias(libs.plugins.google.ksp) apply false
1116
alias(libs.plugins.jetbrains.kotlin.parcelize) apply false
1217
alias(libs.plugins.sonarqube) apply false

composeApp/build.gradle.kts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
3+
* SPDX-License-Identifier: GPL-3.0-or-later
4+
*/
5+
6+
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
7+
8+
plugins {
9+
alias(libs.plugins.android.library)
10+
alias(libs.plugins.jetbrains.kotlin.multiplatform)
11+
alias(libs.plugins.jetbrains.kotlin.compose)
12+
alias(libs.plugins.jetbrains.compose.multiplatform)
13+
alias(libs.plugins.jetbrains.compose.hotreload)
14+
alias(libs.plugins.google.ksp)
15+
alias(libs.plugins.jetbrains.kotlin.parcelize)
16+
}
17+
18+
kotlin {
19+
jvmToolchain(17)
20+
21+
androidLibrary {
22+
namespace = "net.newpipe.app"
23+
compileSdk = 36
24+
minSdk = 21
25+
}
26+
27+
listOf(
28+
iosArm64(),
29+
iosSimulatorArm64()
30+
).forEach { iosTarget ->
31+
iosTarget.binaries.framework {
32+
baseName = "ComposeApp"
33+
isStatic = true
34+
}
35+
}
36+
37+
jvm()
38+
39+
sourceSets {
40+
commonMain.dependencies {
41+
implementation(compose.runtime)
42+
implementation(compose.foundation)
43+
implementation(compose.material3)
44+
implementation(compose.ui)
45+
implementation(compose.components.resources)
46+
implementation(compose.components.uiToolingPreview)
47+
implementation(libs.jetbrains.lifecycle.viewmodel)
48+
}
49+
commonTest.dependencies {
50+
implementation(libs.kotlin.test)
51+
}
52+
androidMain.dependencies {
53+
implementation(compose.preview)
54+
implementation(libs.androidx.activity)
55+
}
56+
jvmMain.dependencies {
57+
implementation(compose.desktop.currentOs)
58+
implementation(libs.jetbrains.kotlinx.coroutinesSwing)
59+
}
60+
}
61+
}
62+
63+
compose.desktop {
64+
application {
65+
mainClass = "net.newpipe.app.MainKt"
66+
67+
nativeDistributions {
68+
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
69+
packageName = "net.newpipe.app"
70+
packageVersion = "1.0.0"
71+
}
72+
}
73+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
~ SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
4+
~ SPDX-License-Identifier: GPL-3.0-or-later
5+
-->
6+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
7+
8+
<application>
9+
<activity
10+
android:name="net.newpipe.app.ComposeActivity"
11+
android:exported="false" />
12+
</application>
13+
</manifest>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
3+
* SPDX-License-Identifier: GPL-3.0-or-later
4+
*/
5+
6+
package net.newpipe.app
7+
8+
import android.os.Bundle
9+
import androidx.activity.ComponentActivity
10+
import androidx.activity.compose.setContent
11+
import androidx.activity.enableEdgeToEdge
12+
13+
class ComposeActivity : ComponentActivity() {
14+
override fun onCreate(savedInstanceState: Bundle?) {
15+
enableEdgeToEdge()
16+
super.onCreate(savedInstanceState)
17+
18+
setContent {
19+
App()
20+
}
21+
}
22+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
~ SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
4+
~ SPDX-License-Identifier: GPL-3.0-or-later
5+
-->
6+
<resources>
7+
<string name="app_name">NewPipe</string>
8+
</resources>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
3+
* SPDX-License-Identifier: GPL-3.0-or-later
4+
*/
5+
6+
package net.newpipe.app
7+
8+
import androidx.compose.material3.MaterialTheme
9+
import androidx.compose.runtime.Composable
10+
import org.jetbrains.compose.ui.tooling.preview.Preview
11+
12+
@Composable
13+
@Preview
14+
fun App() {
15+
MaterialTheme {
16+
17+
}
18+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
3+
* SPDX-License-Identifier: GPL-3.0-or-later
4+
*/
5+
6+
package net.newpipe.app
7+
8+
import kotlin.test.Test
9+
import kotlin.test.assertEquals
10+
11+
class ComposeAppCommonTest {
12+
13+
@Test
14+
fun example() {
15+
assertEquals(3, 1 + 2)
16+
}
17+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
3+
* SPDX-License-Identifier: GPL-3.0-or-later
4+
*/
5+
6+
package net.newpipe.app
7+
8+
import androidx.compose.ui.window.ComposeUIViewController
9+
10+
fun MainViewController() = ComposeUIViewController { App() }
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
3+
* SPDX-License-Identifier: GPL-3.0-or-later
4+
*/
5+
6+
package net.newpipe.app
7+
8+
import androidx.compose.ui.window.Window
9+
import androidx.compose.ui.window.application
10+
import newpipe.composeapp.generated.resources.Res
11+
import newpipe.composeapp.generated.resources.app_name
12+
import org.jetbrains.compose.resources.stringResource
13+
14+
fun main() = application {
15+
Window(onCloseRequest = ::exitApplication, title = stringResource(Res.string.app_name)) {
16+
App()
17+
}
18+
}

gradle/libs.versions.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
[versions]
77
acra = "5.13.1"
8+
activity = "1.12.2"
89
agp = "8.13.2"
910
appcompat = "1.7.1"
1011
assertj = "3.27.6"
@@ -15,11 +16,13 @@ cardview = "1.0.0"
1516
checkstyle = "12.2.0"
1617
constraintlayout = "2.2.1"
1718
core = "1.17.0"
19+
coroutines = "1.10.2"
1820
desugar = "2.1.5"
1921
documentfile = "1.1.0"
2022
exoplayer = "2.19.1"
2123
fragment = "1.8.9"
2224
groupie = "2.10.1"
25+
hotreload = "1.0.0"
2326
jsoup = "1.21.2"
2427
junit = "4.13.2"
2528
junit-ext = "1.3.0"
@@ -28,11 +31,13 @@ ksp = "2.3.2"
2831
ktlint = "1.8.0"
2932
leakcanary = "2.14"
3033
lifecycle = "2.9.4" # Newer versions require minSdk >= 23
34+
lifecycle-jetbrains = "2.9.6"
3135
localbroadcastmanager = "1.1.0"
3236
markwon = "4.6.2"
3337
material = "1.13.0"
3438
media = "1.7.1"
3539
mockitoCore = "5.21.0"
40+
multiplatform = "1.9.3"
3641
okhttp = "5.3.2"
3742
phoenix = "3.0.0"
3843
#noinspection NewerVersionAvailable,GradleDependency --> 2.8 is the last version, not 2.71828!
@@ -67,6 +72,7 @@ work = "2.10.5" # Newer versions require minSdk >= 23
6772
[libraries]
6873
acra-core = { module = "ch.acra:acra-core", version.ref = "acra" }
6974
android-desugar = { module = "com.android.tools:desugar_jdk_libs_nio", version.ref = "desugar" }
75+
androidx-activity = { module = "androidx.activity:activity-compose", version.ref = "activity" }
7076
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
7177
androidx-cardview = { module = "androidx.cardview:cardview", version.ref = "cardview" }
7278
androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" }
@@ -107,8 +113,11 @@ google-exoplayer-smoothstreaming = { module = "com.google.android.exoplayer:exop
107113
google-exoplayer-ui = { module = "com.google.android.exoplayer:exoplayer-ui", version.ref = "exoplayer" }
108114
jakewharton-phoenix = { module = "com.jakewharton:process-phoenix", version.ref = "phoenix" }
109115
jakewharton-rxbinding = { module = "com.jakewharton.rxbinding4:rxbinding", version.ref = "rxbinding" }
116+
jetbrains-kotlinx-coroutinesSwing = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-swing", version.ref = "coroutines" }
117+
jetbrains-lifecycle-viewmodel = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycle-jetbrains" }
110118
jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
111119
junit = { module = "junit:junit", version.ref = "junit" }
120+
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
112121
lisawray-groupie-core = { module = "com.github.lisawray.groupie:groupie", version.ref = "groupie" }
113122
lisawray-groupie-viewbinding = { module = "com.github.lisawray.groupie:groupie-viewbinding", version.ref = "groupie" }
114123
livefront-bridge = { module = "com.github.livefront:bridge", version.ref = "bridge" }
@@ -132,8 +141,13 @@ zacsweers-autoservice-compiler = { module = "dev.zacsweers.autoservice:auto-serv
132141

133142
[plugins]
134143
android-application = { id = "com.android.application", version.ref = "agp" }
144+
android-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" }
135145
google-ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
146+
jetbrains-compose-hotreload = { id = "org.jetbrains.compose.hot-reload", version.ref = "hotreload" }
147+
jetbrains-compose-multiplatform = { id = "org.jetbrains.compose", version.ref = "multiplatform" }
136148
jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
149+
jetbrains-kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
137150
jetbrains-kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } # Needed for statesaver
151+
jetbrains-kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
138152
jetbrains-kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }
139153
sonarqube = { id = "org.sonarqube", version.ref = "sonarqube" }

0 commit comments

Comments
 (0)