mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2026-02-06 02:00:17 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff78dd108e | ||
|
|
b01ce34b55 | ||
|
|
c34bb67689 | ||
|
|
84e4ce8b46 | ||
|
|
0123b51638 |
@@ -5,9 +5,15 @@
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.android.application) apply false
|
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.android) apply false
|
||||||
alias(libs.plugins.jetbrains.kotlin.kapt) 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.google.ksp) apply false
|
||||||
alias(libs.plugins.jetbrains.kotlin.parcelize) apply false
|
alias(libs.plugins.jetbrains.kotlin.parcelize) apply false
|
||||||
|
alias(libs.plugins.jetbrains.kotlin.serialization) apply false
|
||||||
alias(libs.plugins.sonarqube) apply false
|
alias(libs.plugins.sonarqube) apply false
|
||||||
}
|
}
|
||||||
|
|||||||
106
composeApp/build.gradle.kts
Normal file
106
composeApp/build.gradle.kts
Normal file
@@ -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
composeApp/src/androidMain/AndroidManifest.xml
Normal file
13
composeApp/src/androidMain/AndroidManifest.xml
Normal file
@@ -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>
|
||||||
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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()))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
composeApp/src/commonMain/kotlin/net/newpipe/app/App.kt
Normal file
27
composeApp/src/commonMain/kotlin/net/newpipe/app/App.kt
Normal file
@@ -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 {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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 {
|
||||||
|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 NewPipe contributors <https://newpipe.net>
|
||||||
|
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.newpipe.app.screens
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.SecondaryTabRow
|
||||||
|
import androidx.compose.material3.Tab
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.util.fastForEachIndexed
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import net.newpipe.app.preview.PreviewTemplate
|
||||||
|
import newpipe.composeapp.generated.resources.Res
|
||||||
|
import newpipe.composeapp.generated.resources.tab_about
|
||||||
|
import newpipe.composeapp.generated.resources.tab_licenses
|
||||||
|
import org.jetbrains.compose.resources.stringResource
|
||||||
|
import org.jetbrains.compose.ui.tooling.preview.Preview
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AboutScreen() {
|
||||||
|
ScreenContent()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun ScreenContent(onNavigateUp: () -> Unit = {}) {
|
||||||
|
Scaffold { paddingValues ->
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(paddingValues)
|
||||||
|
) {
|
||||||
|
val pages = listOf(Res.string.tab_about, Res.string.tab_licenses)
|
||||||
|
val pagerState = rememberPagerState { pages.size }
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
SecondaryTabRow(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
selectedTabIndex = pagerState.currentPage
|
||||||
|
) {
|
||||||
|
pages.fastForEachIndexed { index, pageId ->
|
||||||
|
Tab(
|
||||||
|
selected = pagerState.currentPage == index,
|
||||||
|
text = {
|
||||||
|
Text(text = stringResource(pageId))
|
||||||
|
},
|
||||||
|
onClick = {
|
||||||
|
coroutineScope.launch {
|
||||||
|
pagerState.animateScrollToPage(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HorizontalPager(
|
||||||
|
state = pagerState,
|
||||||
|
modifier = Modifier.fillMaxSize()
|
||||||
|
) { page ->
|
||||||
|
if (page == 0) {
|
||||||
|
AboutTab()
|
||||||
|
} else {
|
||||||
|
LicenseTab()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun AboutScreenPreview() {
|
||||||
|
PreviewTemplate {
|
||||||
|
ScreenContent()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 NewPipe contributors <https://newpipe.net>
|
||||||
|
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.newpipe.app.theme
|
||||||
|
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
|
||||||
|
val primaryLight = Color(0xFF904A45)
|
||||||
|
val onPrimaryLight = Color(0xFFFFFFFF)
|
||||||
|
val primaryContainerLight = Color(0xFFFFDAD6)
|
||||||
|
val onPrimaryContainerLight = Color(0xFF3B0908)
|
||||||
|
val secondaryLight = Color(0xFF775653)
|
||||||
|
val onSecondaryLight = Color(0xFFFFFFFF)
|
||||||
|
val secondaryContainerLight = Color(0xFFFFDAD6)
|
||||||
|
val onSecondaryContainerLight = Color(0xFF2C1513)
|
||||||
|
val tertiaryLight = Color(0xFF725B2E)
|
||||||
|
val onTertiaryLight = Color(0xFFFFFFFF)
|
||||||
|
val tertiaryContainerLight = Color(0xFFFEDEA6)
|
||||||
|
val onTertiaryContainerLight = Color(0xFF261900)
|
||||||
|
val errorLight = Color(0xFFBA1A1A)
|
||||||
|
val onErrorLight = Color(0xFFFFFFFF)
|
||||||
|
val errorContainerLight = Color(0xFFFFDAD6)
|
||||||
|
val onErrorContainerLight = Color(0xFF410002)
|
||||||
|
val backgroundLight = Color(0xFFFFF8F7)
|
||||||
|
val onBackgroundLight = Color(0xFF231918)
|
||||||
|
val surfaceLight = Color(0xFFFFF8F7)
|
||||||
|
val onSurfaceLight = Color(0xFF231918)
|
||||||
|
val surfaceVariantLight = Color(0xFFF5DDDB)
|
||||||
|
val onSurfaceVariantLight = Color(0xFF534342)
|
||||||
|
val outlineLight = Color(0xFF857371)
|
||||||
|
val outlineVariantLight = Color(0xFFD8C2BF)
|
||||||
|
val scrimLight = Color(0xFF000000)
|
||||||
|
val inverseSurfaceLight = Color(0xFF392E2D)
|
||||||
|
val inverseOnSurfaceLight = Color(0xFFFFEDEB)
|
||||||
|
val inversePrimaryLight = Color(0xFFFFB3AC)
|
||||||
|
val surfaceDimLight = Color(0xFFE8D6D4)
|
||||||
|
val surfaceBrightLight = Color(0xFFFFF8F7)
|
||||||
|
val surfaceContainerLowestLight = Color(0xFFFFFFFF)
|
||||||
|
val surfaceContainerLowLight = Color(0xFFFFF0EF)
|
||||||
|
val surfaceContainerLight = Color(0xFFFCEAE8)
|
||||||
|
val surfaceContainerHighLight = Color(0xFFF6E4E2)
|
||||||
|
val surfaceContainerHighestLight = Color(0xFFF1DEDC)
|
||||||
|
|
||||||
|
val primaryDark = Color(0xFFFFB3AC)
|
||||||
|
val onPrimaryDark = Color(0xFF571E1B)
|
||||||
|
val primaryContainerDark = Color(0xFF73332F)
|
||||||
|
val onPrimaryContainerDark = Color(0xFFFFDAD6)
|
||||||
|
val secondaryDark = Color(0xFFE7BDB8)
|
||||||
|
val onSecondaryDark = Color(0xFF442927)
|
||||||
|
val secondaryContainerDark = Color(0xFF5D3F3C)
|
||||||
|
val onSecondaryContainerDark = Color(0xFFFFDAD6)
|
||||||
|
val tertiaryDark = Color(0xFFE1C38C)
|
||||||
|
val onTertiaryDark = Color(0xFF402D04)
|
||||||
|
val tertiaryContainerDark = Color(0xFF584419)
|
||||||
|
val onTertiaryContainerDark = Color(0xFFFEDEA6)
|
||||||
|
val errorDark = Color(0xFFFFB4AB)
|
||||||
|
val onErrorDark = Color(0xFF690005)
|
||||||
|
val errorContainerDark = Color(0xFF93000A)
|
||||||
|
val onErrorContainerDark = Color(0xFFFFDAD6)
|
||||||
|
val backgroundDark = Color(0xFF1A1110)
|
||||||
|
val onBackgroundDark = Color(0xFFF1DEDC)
|
||||||
|
val surfaceDark = Color(0xFF1A1110)
|
||||||
|
val onSurfaceDark = Color(0xFFF1DEDC)
|
||||||
|
val surfaceVariantDark = Color(0xFF534342)
|
||||||
|
val onSurfaceVariantDark = Color(0xFFD8C2BF)
|
||||||
|
val outlineDark = Color(0xFFA08C8A)
|
||||||
|
val outlineVariantDark = Color(0xFF534342)
|
||||||
|
val scrimDark = Color(0xFF000000)
|
||||||
|
val inverseSurfaceDark = Color(0xFFF1DEDC)
|
||||||
|
val inverseOnSurfaceDark = Color(0xFF392E2D)
|
||||||
|
val inversePrimaryDark = Color(0xFF904A45)
|
||||||
|
val surfaceDimDark = Color(0xFF1A1110)
|
||||||
|
val surfaceBrightDark = Color(0xFF423735)
|
||||||
|
val surfaceContainerLowestDark = Color(0xFF140C0B)
|
||||||
|
val surfaceContainerLowDark = Color(0xFF231918)
|
||||||
|
val surfaceContainerDark = Color(0xFF271D1C)
|
||||||
|
val surfaceContainerHighDark = Color(0xFF322827)
|
||||||
|
val surfaceContainerHighestDark = Color(0xFF3D3231)
|
||||||
116
composeApp/src/commonMain/kotlin/net/newpipe/app/theme/Theme.kt
Normal file
116
composeApp/src/commonMain/kotlin/net/newpipe/app/theme/Theme.kt
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2024 NewPipe contributors <https://newpipe.net>
|
||||||
|
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.newpipe.app.theme
|
||||||
|
|
||||||
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.darkColorScheme
|
||||||
|
import androidx.compose.material3.lightColorScheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import com.russhwolf.settings.Settings
|
||||||
|
import org.koin.compose.koinInject
|
||||||
|
|
||||||
|
private val lightScheme = lightColorScheme(
|
||||||
|
primary = primaryLight,
|
||||||
|
onPrimary = onPrimaryLight,
|
||||||
|
primaryContainer = primaryContainerLight,
|
||||||
|
onPrimaryContainer = onPrimaryContainerLight,
|
||||||
|
secondary = secondaryLight,
|
||||||
|
onSecondary = onSecondaryLight,
|
||||||
|
secondaryContainer = secondaryContainerLight,
|
||||||
|
onSecondaryContainer = onSecondaryContainerLight,
|
||||||
|
tertiary = tertiaryLight,
|
||||||
|
onTertiary = onTertiaryLight,
|
||||||
|
tertiaryContainer = tertiaryContainerLight,
|
||||||
|
onTertiaryContainer = onTertiaryContainerLight,
|
||||||
|
error = errorLight,
|
||||||
|
onError = onErrorLight,
|
||||||
|
errorContainer = errorContainerLight,
|
||||||
|
onErrorContainer = onErrorContainerLight,
|
||||||
|
background = backgroundLight,
|
||||||
|
onBackground = onBackgroundLight,
|
||||||
|
surface = surfaceLight,
|
||||||
|
onSurface = onSurfaceLight,
|
||||||
|
surfaceVariant = surfaceVariantLight,
|
||||||
|
onSurfaceVariant = onSurfaceVariantLight,
|
||||||
|
outline = outlineLight,
|
||||||
|
outlineVariant = outlineVariantLight,
|
||||||
|
scrim = scrimLight,
|
||||||
|
inverseSurface = inverseSurfaceLight,
|
||||||
|
inverseOnSurface = inverseOnSurfaceLight,
|
||||||
|
inversePrimary = inversePrimaryLight,
|
||||||
|
surfaceDim = surfaceDimLight,
|
||||||
|
surfaceBright = surfaceBrightLight,
|
||||||
|
surfaceContainerLowest = surfaceContainerLowestLight,
|
||||||
|
surfaceContainerLow = surfaceContainerLowLight,
|
||||||
|
surfaceContainer = surfaceContainerLight,
|
||||||
|
surfaceContainerHigh = surfaceContainerHighLight,
|
||||||
|
surfaceContainerHighest = surfaceContainerHighestLight,
|
||||||
|
)
|
||||||
|
|
||||||
|
private val darkScheme = darkColorScheme(
|
||||||
|
primary = primaryDark,
|
||||||
|
onPrimary = onPrimaryDark,
|
||||||
|
primaryContainer = primaryContainerDark,
|
||||||
|
onPrimaryContainer = onPrimaryContainerDark,
|
||||||
|
secondary = secondaryDark,
|
||||||
|
onSecondary = onSecondaryDark,
|
||||||
|
secondaryContainer = secondaryContainerDark,
|
||||||
|
onSecondaryContainer = onSecondaryContainerDark,
|
||||||
|
tertiary = tertiaryDark,
|
||||||
|
onTertiary = onTertiaryDark,
|
||||||
|
tertiaryContainer = tertiaryContainerDark,
|
||||||
|
onTertiaryContainer = onTertiaryContainerDark,
|
||||||
|
error = errorDark,
|
||||||
|
onError = onErrorDark,
|
||||||
|
errorContainer = errorContainerDark,
|
||||||
|
onErrorContainer = onErrorContainerDark,
|
||||||
|
background = backgroundDark,
|
||||||
|
onBackground = onBackgroundDark,
|
||||||
|
surface = surfaceDark,
|
||||||
|
onSurface = onSurfaceDark,
|
||||||
|
surfaceVariant = surfaceVariantDark,
|
||||||
|
onSurfaceVariant = onSurfaceVariantDark,
|
||||||
|
outline = outlineDark,
|
||||||
|
outlineVariant = outlineVariantDark,
|
||||||
|
scrim = scrimDark,
|
||||||
|
inverseSurface = inverseSurfaceDark,
|
||||||
|
inverseOnSurface = inverseOnSurfaceDark,
|
||||||
|
inversePrimary = inversePrimaryDark,
|
||||||
|
surfaceDim = surfaceDimDark,
|
||||||
|
surfaceBright = surfaceBrightDark,
|
||||||
|
surfaceContainerLowest = surfaceContainerLowestDark,
|
||||||
|
surfaceContainerLow = surfaceContainerLowDark,
|
||||||
|
surfaceContainer = surfaceContainerDark,
|
||||||
|
surfaceContainerHigh = surfaceContainerHighDark,
|
||||||
|
surfaceContainerHighest = surfaceContainerHighestDark,
|
||||||
|
)
|
||||||
|
|
||||||
|
private val blackScheme = darkScheme.copy(surface = Color.Black)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AppTheme(
|
||||||
|
useDarkTheme: Boolean = isSystemInDarkTheme(),
|
||||||
|
settings: Settings = koinInject(),
|
||||||
|
content: @Composable () -> Unit
|
||||||
|
) {
|
||||||
|
val nightScheme = when(settings.getString("night_theme", "dark_theme")) {
|
||||||
|
"black_theme" -> blackScheme
|
||||||
|
else -> darkScheme
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialTheme(
|
||||||
|
colorScheme = when(settings.getString("theme", "auto_device_theme")) {
|
||||||
|
"light_theme" -> lightScheme
|
||||||
|
"dark_theme" -> darkScheme
|
||||||
|
"black_theme" -> blackScheme
|
||||||
|
else -> if (!useDarkTheme) lightScheme else nightScheme
|
||||||
|
},
|
||||||
|
content = content
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
class ComposeAppCommonTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun example() {
|
||||||
|
assertEquals(3, 1 + 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* 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.ui.window.ComposeUIViewController
|
||||||
|
|
||||||
|
fun MainViewController() = ComposeUIViewController { App() }
|
||||||
@@ -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.module
|
||||||
|
|
||||||
|
import com.russhwolf.settings.NSUserDefaultsSettings
|
||||||
|
import com.russhwolf.settings.Settings
|
||||||
|
import org.koin.dsl.module
|
||||||
|
import platform.Foundation.NSUserDefaults
|
||||||
|
|
||||||
|
actual val platformModule = module {
|
||||||
|
single<Settings> {
|
||||||
|
NSUserDefaultsSettings(NSUserDefaults())
|
||||||
|
}
|
||||||
|
}
|
||||||
18
composeApp/src/jvmMain/kotlin/net/newpipe/app/main.kt
Normal file
18
composeApp/src/jvmMain/kotlin/net/newpipe/app/main.kt
Normal file
@@ -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
|
||||||
|
|
||||||
|
import androidx.compose.ui.window.Window
|
||||||
|
import androidx.compose.ui.window.application
|
||||||
|
import newpipe.composeapp.generated.resources.Res
|
||||||
|
import newpipe.composeapp.generated.resources.app_name
|
||||||
|
import org.jetbrains.compose.resources.stringResource
|
||||||
|
|
||||||
|
fun main() = application {
|
||||||
|
Window(onCloseRequest = ::exitApplication, title = stringResource(Res.string.app_name)) {
|
||||||
|
App()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.module
|
||||||
|
|
||||||
|
import com.russhwolf.settings.PreferencesSettings
|
||||||
|
import com.russhwolf.settings.Settings
|
||||||
|
import org.koin.dsl.module
|
||||||
|
import java.util.prefs.Preferences
|
||||||
|
|
||||||
|
actual val platformModule = module {
|
||||||
|
single<Settings> {
|
||||||
|
PreferencesSettings(Preferences.userRoot())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
[versions]
|
[versions]
|
||||||
acra = "5.13.1"
|
acra = "5.13.1"
|
||||||
|
activity = "1.12.2"
|
||||||
agp = "8.13.2"
|
agp = "8.13.2"
|
||||||
appcompat = "1.7.1"
|
appcompat = "1.7.1"
|
||||||
assertj = "3.27.6"
|
assertj = "3.27.6"
|
||||||
@@ -15,24 +16,31 @@ cardview = "1.0.0"
|
|||||||
checkstyle = "12.2.0"
|
checkstyle = "12.2.0"
|
||||||
constraintlayout = "2.2.1"
|
constraintlayout = "2.2.1"
|
||||||
core = "1.17.0"
|
core = "1.17.0"
|
||||||
|
coroutines = "1.10.2"
|
||||||
desugar = "2.1.5"
|
desugar = "2.1.5"
|
||||||
documentfile = "1.1.0"
|
documentfile = "1.1.0"
|
||||||
exoplayer = "2.19.1"
|
exoplayer = "2.19.1"
|
||||||
fragment = "1.8.9"
|
fragment = "1.8.9"
|
||||||
groupie = "2.10.1"
|
groupie = "2.10.1"
|
||||||
|
hotreload = "1.0.0"
|
||||||
jsoup = "1.21.2"
|
jsoup = "1.21.2"
|
||||||
junit = "4.13.2"
|
junit = "4.13.2"
|
||||||
junit-ext = "1.3.0"
|
junit-ext = "1.3.0"
|
||||||
|
koin-annotations = "2.3.1"
|
||||||
|
koin-bom = "4.1.1"
|
||||||
kotlin = "2.2.21"
|
kotlin = "2.2.21"
|
||||||
ksp = "2.3.2"
|
ksp = "2.3.2"
|
||||||
ktlint = "1.8.0"
|
ktlint = "1.8.0"
|
||||||
leakcanary = "2.14"
|
leakcanary = "2.14"
|
||||||
lifecycle = "2.9.4" # Newer versions require minSdk >= 23
|
lifecycle = "2.9.4" # Newer versions require minSdk >= 23
|
||||||
|
lifecycle-jetbrains = "2.9.6"
|
||||||
localbroadcastmanager = "1.1.0"
|
localbroadcastmanager = "1.1.0"
|
||||||
markwon = "4.6.2"
|
markwon = "4.6.2"
|
||||||
material = "1.11.0" # TODO: update to newer version after bug is fixed. See https://github.com/TeamNewPipe/NewPipe/pull/13018
|
material = "1.11.0" # TODO: update to newer version after bug is fixed. See https://github.com/TeamNewPipe/NewPipe/pull/13018
|
||||||
media = "1.7.1"
|
media = "1.7.1"
|
||||||
mockitoCore = "5.21.0"
|
mockitoCore = "5.21.0"
|
||||||
|
multiplatform = "1.9.3"
|
||||||
|
navigation3 = "1.0.0-alpha06"
|
||||||
okhttp = "5.3.2"
|
okhttp = "5.3.2"
|
||||||
phoenix = "3.0.0"
|
phoenix = "3.0.0"
|
||||||
#noinspection NewerVersionAvailable,GradleDependency --> 2.8 is the last version, not 2.71828!
|
#noinspection NewerVersionAvailable,GradleDependency --> 2.8 is the last version, not 2.71828!
|
||||||
@@ -45,6 +53,8 @@ runner = "1.7.0"
|
|||||||
rxandroid = "3.0.2"
|
rxandroid = "3.0.2"
|
||||||
rxbinding = "4.0.0"
|
rxbinding = "4.0.0"
|
||||||
rxjava = "3.1.12"
|
rxjava = "3.1.12"
|
||||||
|
serialization = "1.9.0"
|
||||||
|
settings = "1.3.0"
|
||||||
sonarqube = "7.2.1.6560"
|
sonarqube = "7.2.1.6560"
|
||||||
statesaver = "1.4.1" # TODO: Drop because it is deprecated and incompatible with KSP2
|
statesaver = "1.4.1" # TODO: Drop because it is deprecated and incompatible with KSP2
|
||||||
stetho = "1.6.0"
|
stetho = "1.6.0"
|
||||||
@@ -67,6 +77,7 @@ work = "2.10.5" # Newer versions require minSdk >= 23
|
|||||||
[libraries]
|
[libraries]
|
||||||
acra-core = { module = "ch.acra:acra-core", version.ref = "acra" }
|
acra-core = { module = "ch.acra:acra-core", version.ref = "acra" }
|
||||||
android-desugar = { module = "com.android.tools:desugar_jdk_libs_nio", version.ref = "desugar" }
|
android-desugar = { module = "com.android.tools:desugar_jdk_libs_nio", version.ref = "desugar" }
|
||||||
|
androidx-activity = { module = "androidx.activity:activity-compose", version.ref = "activity" }
|
||||||
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
|
androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
|
||||||
androidx-cardview = { module = "androidx.cardview:cardview", version.ref = "cardview" }
|
androidx-cardview = { module = "androidx.cardview:cardview", version.ref = "cardview" }
|
||||||
androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" }
|
androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "constraintlayout" }
|
||||||
@@ -107,8 +118,19 @@ google-exoplayer-smoothstreaming = { module = "com.google.android.exoplayer:exop
|
|||||||
google-exoplayer-ui = { module = "com.google.android.exoplayer:exoplayer-ui", version.ref = "exoplayer" }
|
google-exoplayer-ui = { module = "com.google.android.exoplayer:exoplayer-ui", version.ref = "exoplayer" }
|
||||||
jakewharton-phoenix = { module = "com.jakewharton:process-phoenix", version.ref = "phoenix" }
|
jakewharton-phoenix = { module = "com.jakewharton:process-phoenix", version.ref = "phoenix" }
|
||||||
jakewharton-rxbinding = { module = "com.jakewharton.rxbinding4:rxbinding", version.ref = "rxbinding" }
|
jakewharton-rxbinding = { module = "com.jakewharton.rxbinding4:rxbinding", version.ref = "rxbinding" }
|
||||||
|
jetbrains-coroutines-swing = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-swing", version.ref = "coroutines" }
|
||||||
|
jetbrains-lifecycle-viewmodel = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycle-jetbrains" }
|
||||||
|
jetbrains-navigation3-ui = { module = "org.jetbrains.androidx.navigation3:navigation3-ui", version.ref = "navigation3" }
|
||||||
|
jetbrains-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization" }
|
||||||
jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
|
jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" }
|
||||||
junit = { module = "junit:junit", version.ref = "junit" }
|
junit = { module = "junit:junit", version.ref = "junit" }
|
||||||
|
koin-annotations = { module = "io.insert-koin:koin-annotations", version.ref = "koin-annotations" }
|
||||||
|
koin-compiler = { module = "io.insert-koin:koin-ksp-compiler", version.ref = "koin-annotations" }
|
||||||
|
koin-compose = { module = "io.insert-koin:koin-compose", version.ref = "koin-bom" }
|
||||||
|
koin-core = { module = "io.insert-koin:koin-core", version.ref = "koin-bom" }
|
||||||
|
koin-test = { module = "io.insert-koin:koin-test", version.ref = "koin-bom" }
|
||||||
|
koin-viewmodel = { module = "io.insert-koin:koin-compose-viewmodel", version.ref = "koin-bom" }
|
||||||
|
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
|
||||||
lisawray-groupie-core = { module = "com.github.lisawray.groupie:groupie", version.ref = "groupie" }
|
lisawray-groupie-core = { module = "com.github.lisawray.groupie:groupie", version.ref = "groupie" }
|
||||||
lisawray-groupie-viewbinding = { module = "com.github.lisawray.groupie:groupie-viewbinding", version.ref = "groupie" }
|
lisawray-groupie-viewbinding = { module = "com.github.lisawray.groupie:groupie-viewbinding", version.ref = "groupie" }
|
||||||
livefront-bridge = { module = "com.github.livefront:bridge", version.ref = "bridge" }
|
livefront-bridge = { module = "com.github.livefront:bridge", version.ref = "bridge" }
|
||||||
@@ -123,6 +145,7 @@ pinterest-ktlint = { module = "com.pinterest.ktlint:ktlint-cli", version.ref = "
|
|||||||
puppycrawl-checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" }
|
puppycrawl-checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" }
|
||||||
reactivex-rxandroid = { module = "io.reactivex.rxjava3:rxandroid", version.ref = "rxandroid" }
|
reactivex-rxandroid = { module = "io.reactivex.rxjava3:rxandroid", version.ref = "rxandroid" }
|
||||||
reactivex-rxjava = { module = "io.reactivex.rxjava3:rxjava", version.ref = "rxjava" }
|
reactivex-rxjava = { module = "io.reactivex.rxjava3:rxjava", version.ref = "rxjava" }
|
||||||
|
russhwolf-settings = { module = "com.russhwolf:multiplatform-settings", version.ref = "settings" }
|
||||||
squareup-leakcanary-core = { module = "com.squareup.leakcanary:leakcanary-android-core", version.ref = "leakcanary" }
|
squareup-leakcanary-core = { module = "com.squareup.leakcanary:leakcanary-android-core", version.ref = "leakcanary" }
|
||||||
squareup-leakcanary-plumber = { module = "com.squareup.leakcanary:plumber-android", version.ref = "leakcanary" }
|
squareup-leakcanary-plumber = { module = "com.squareup.leakcanary:plumber-android", version.ref = "leakcanary" }
|
||||||
squareup-leakcanary-watcher = { module = "com.squareup.leakcanary:leakcanary-object-watcher-android", version.ref = "leakcanary" }
|
squareup-leakcanary-watcher = { module = "com.squareup.leakcanary:leakcanary-object-watcher-android", version.ref = "leakcanary" }
|
||||||
@@ -132,8 +155,14 @@ zacsweers-autoservice-compiler = { module = "dev.zacsweers.autoservice:auto-serv
|
|||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
android-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" }
|
||||||
google-ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
|
google-ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
|
||||||
|
jetbrains-compose-hotreload = { id = "org.jetbrains.compose.hot-reload", version.ref = "hotreload" }
|
||||||
|
jetbrains-compose-multiplatform = { id = "org.jetbrains.compose", version.ref = "multiplatform" }
|
||||||
jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||||
|
jetbrains-kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
||||||
jetbrains-kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } # Needed for statesaver
|
jetbrains-kotlin-kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } # Needed for statesaver
|
||||||
|
jetbrains-kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
|
||||||
jetbrains-kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }
|
jetbrains-kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" }
|
||||||
|
jetbrains-kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
|
||||||
sonarqube = { id = "org.sonarqube", version.ref = "sonarqube" }
|
sonarqube = { id = "org.sonarqube", version.ref = "sonarqube" }
|
||||||
|
|||||||
0
iosApp/Configuration/Config.xcconfig
Normal file
0
iosApp/Configuration/Config.xcconfig
Normal file
0
iosApp/iosApp.xcodeproj/project.pbxproj
Normal file
0
iosApp/iosApp.xcodeproj/project.pbxproj
Normal file
0
iosApp/iosApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
0
iosApp/iosApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
0
iosApp/iosApp/Assets.xcassets/Contents.json
Normal file
0
iosApp/iosApp/Assets.xcassets/Contents.json
Normal file
0
iosApp/iosApp/ContentView.swift
Normal file
0
iosApp/iosApp/ContentView.swift
Normal file
0
iosApp/iosApp/Info.plist
Normal file
0
iosApp/iosApp/Info.plist
Normal file
0
iosApp/iosApp/iOSApp.swift
Normal file
0
iosApp/iosApp/iOSApp.swift
Normal file
@@ -20,6 +20,7 @@ dependencyResolutionManagement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
include (":app")
|
include (":app")
|
||||||
|
include("composeApp")
|
||||||
|
|
||||||
// Use a local copy of NewPipe Extractor by uncommenting the lines below.
|
// Use a local copy of NewPipe Extractor by uncommenting the lines below.
|
||||||
// We assume, that NewPipe and NewPipe Extractor have the same parent directory.
|
// We assume, that NewPipe and NewPipe Extractor have the same parent directory.
|
||||||
|
|||||||
Reference in New Issue
Block a user