Skip to content
Closed
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
6 changes: 6 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@

plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.jetbrains.kotlin.android) apply false
alias(libs.plugins.jetbrains.kotlin.kapt) apply false
alias(libs.plugins.jetbrains.kotlin.compose) apply false
alias(libs.plugins.jetbrains.kotlin.multiplatform) apply false
alias(libs.plugins.jetbrains.compose.multiplatform) apply false
alias(libs.plugins.jetbrains.compose.hotreload) apply false
alias(libs.plugins.google.ksp) apply false
alias(libs.plugins.jetbrains.kotlin.parcelize) apply false
alias(libs.plugins.jetbrains.kotlin.serialization) apply false
alias(libs.plugins.sonarqube) apply false
}
106 changes: 106 additions & 0 deletions composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/

import org.jetbrains.compose.desktop.application.dsl.TargetFormat

plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.jetbrains.kotlin.multiplatform)
alias(libs.plugins.jetbrains.kotlin.compose)
alias(libs.plugins.jetbrains.compose.multiplatform)
alias(libs.plugins.jetbrains.compose.hotreload)
alias(libs.plugins.google.ksp)
alias(libs.plugins.jetbrains.kotlin.serialization)
}

kotlin {
jvmToolchain(17)

androidLibrary {
namespace = "net.newpipe.app"
compileSdk = 36
minSdk = 21
}

listOf(
iosArm64(),
iosSimulatorArm64()
).forEach { iosTarget ->
iosTarget.binaries.framework {
baseName = "ComposeApp"
isStatic = true
}
}

jvm()

sourceSets {
commonMain.dependencies {
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material3)
implementation(compose.ui)
implementation(compose.components.resources)
implementation(compose.components.uiToolingPreview)

// Lifecycle
implementation(libs.jetbrains.lifecycle.viewmodel)

// Koin
api(libs.koin.annotations)
implementation(libs.koin.core)
implementation(libs.koin.compose)
implementation(libs.koin.viewmodel)

// Settings
implementation(libs.russhwolf.settings)

// Navigation
implementation(libs.jetbrains.navigation3.ui)
implementation(libs.jetbrains.serialization.json)
}
commonTest.dependencies {
implementation(libs.kotlin.test)
implementation(libs.koin.test)
}
androidMain.dependencies {
implementation(compose.preview)
implementation(libs.androidx.activity)
implementation(libs.androidx.preference)
}
jvmMain.dependencies {
implementation(compose.desktop.currentOs)
implementation(libs.jetbrains.coroutines.swing)
}
}

// Koin
sourceSets.named("commonMain").configure {
kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin")
}
}

// Koin
dependencies {
add("kspCommonMainMetadata", libs.koin.annotations)
add("kspAndroid", libs.koin.compiler)
add("kspIosArm64", libs.koin.compiler)
add("kspIosSimulatorArm64", libs.koin.compiler)
}

tasks.matching { it.name.startsWith("ksp") && it.name != "kspCommonMainKotlinMetadata" }
.configureEach { dependsOn("kspCommonMainKotlinMetadata") }

compose.desktop {
application {
mainClass = "net.newpipe.app.MainKt"

nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageName = "net.newpipe.app"
packageVersion = "1.0.0"
}
}
}
13 changes: 13 additions & 0 deletions composeApp/src/androidMain/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
~ SPDX-License-Identifier: GPL-3.0-or-later
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

<application>
<activity
android:name="net.newpipe.app.ComposeActivity"
android:exported="false" />
</application>
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/

package net.newpipe.app

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge

class ComposeActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
enableEdgeToEdge()
super.onCreate(savedInstanceState)

setContent {
App()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/

package net.newpipe.app.module

import androidx.preference.PreferenceManager
import com.russhwolf.settings.Settings
import com.russhwolf.settings.SharedPreferencesSettings
import org.koin.android.ext.koin.androidContext
import org.koin.dsl.module

actual val platformModule = module {
single<Settings> {
SharedPreferencesSettings(PreferenceManager.getDefaultSharedPreferences(androidContext()))
}
}
12 changes: 12 additions & 0 deletions composeApp/src/commonMain/composeResources/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
~ SPDX-License-Identifier: GPL-3.0-or-later
-->
<resources>
<string name="app_name">NewPipe</string>

<!-- AboutScreen -->
<string name="tab_about">About \u0026 FAQ</string>
<string name="tab_licenses">Licenses</string>
</resources>
27 changes: 27 additions & 0 deletions composeApp/src/commonMain/kotlin/net/newpipe/app/App.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/

package net.newpipe.app

import androidx.compose.runtime.Composable
import net.newpipe.app.module.platformModule
import net.newpipe.app.theme.AppTheme
import org.koin.compose.KoinMultiplatformApplication
import org.koin.core.annotation.KoinExperimentalAPI
import org.koin.dsl.koinConfiguration

@OptIn(KoinExperimentalAPI::class)
@Composable
fun App() {
KoinMultiplatformApplication(
config = koinConfiguration {
modules(platformModule)
}
) {
AppTheme {

}
}
}
13 changes: 13 additions & 0 deletions composeApp/src/commonMain/kotlin/net/newpipe/app/module/Koin.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/

package net.newpipe.app.module

import org.koin.core.module.Module

/**
* Contains platform specific module; See actual implementation for more details
*/
expect val platformModule: Module
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/

package net.newpipe.app.navigation

import androidx.compose.runtime.Composable
import androidx.navigation3.runtime.NavKey
import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.runtime.rememberNavBackStack
import androidx.navigation3.ui.NavDisplay

/**
* Navigation display for compose screens
* @param startDestination Starting destination for the activity/app
*/
@Composable
fun MainNavDisplay(startDestination: NavKey) {
val backstack = rememberNavBackStack(Screen.config, startDestination)

NavDisplay(
backStack = backstack,
entryProvider = entryProvider {

}
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/

package net.newpipe.app.navigation

import androidx.navigation3.runtime.NavKey
import androidx.savedstate.serialization.SavedStateConfiguration
import kotlinx.serialization.Serializable
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.polymorphic

/**
* Destinations for navigation in compose
*/
@Serializable
sealed class Screen : NavKey {

@Serializable
data object About: Screen()

companion object {
val config = SavedStateConfiguration {
serializersModule = SerializersModule {
polymorphic(NavKey::class) {
// TODO: Add all subclasses using a for-each loop
subclass(About::class, About.serializer())
}
}
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/

package net.newpipe.app.preview

import androidx.compose.runtime.Composable
import net.newpipe.app.theme.AppTheme

/**
* Template for previewing composable with defaults
*/
@Composable
fun PreviewTemplate(content: @Composable () -> Unit) {
AppTheme(content = content)
}
Loading