Fist commit including jetpack compose and new Main view

This commit is contained in:
Ivan Agosto 2025-01-26 21:38:22 -06:00
parent a1deaa844c
commit e5cbedb4ef
16 changed files with 1019 additions and 9 deletions

View File

@ -22,6 +22,7 @@ android {
}
buildFeatures {
viewBinding = true
compose true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_18
@ -35,19 +36,28 @@ android {
kotlinOptions {
jvmTarget = '18'
}
composeOptions {
kotlinCompilerExtensionVersion '1.5.4'
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation 'com.squareup.picasso:picasso:2.71828'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.google.android.material:material:1.12.0'
implementation 'androidx.preference:preference-ktx:1.2.1'
implementation 'androidx.activity:activity:1.8.0'
implementation 'androidx.activity:activity-ktx:1.10.0'
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.8.7'
implementation 'androidx.activity:activity-compose:1.10.0'
implementation platform('androidx.compose:compose-bom:2024.04.01')
implementation 'androidx.compose.ui:ui'
implementation 'androidx.compose.ui:ui-graphics'
implementation 'androidx.compose.ui:ui-tooling-preview'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test:runner:1.5.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
@ -56,5 +66,21 @@ dependencies {
implementation 'androidx.media3:media3-ui:1.3.1'
implementation 'androidx.media3:media3-exoplayer-hls:1.3.1'
implementation "androidx.media3:media3-session:1.3.1"
implementation 'com.google.code.gson:gson:2.8.8'
implementation 'com.google.code.gson:gson:2.10.1'
implementation "androidx.compose.material3:material3:1.1.0"
androidTestImplementation platform('androidx.compose:compose-bom:2024.04.01')
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
debugImplementation 'androidx.compose.ui:ui-tooling'
debugImplementation 'androidx.compose.ui:ui-test-manifest'
implementation "androidx.compose.runtime:runtime"
implementation "androidx.compose.ui:ui"
implementation "androidx.compose.foundation:foundation"
implementation "androidx.compose.foundation:foundation-layout"
implementation "androidx.compose.material3:material3"
implementation "androidx.compose.runtime:runtime-livedata"
implementation "androidx.compose.ui:ui-tooling"
implementation "androidx.constraintlayout:constraintlayout-compose:1.0.1"
implementation "io.coil-kt.coil3:coil-compose:3.0.4"
implementation "io.coil-kt.coil3:coil-network-okhttp:3.0.4"
}

View File

@ -13,7 +13,10 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.P2play">
<activity
android:name=".activities.MainActivity"
android:exported="false"
android:theme="@style/Theme.P2play" />
<activity
android:name=".AccountActivity"
android:exported="false"
@ -65,6 +68,11 @@
android:name=".AboutActivity"
android:exported="false" />
<activity
android:name=".activities.HostActivityV2"
android:exported="true"
android:theme="@style/Theme.P2play" />
<service
android:name=".services.PlaybackService"
android:exported="true"

View File

@ -2,13 +2,11 @@ package org.libre.agosto.p2play
import android.content.Intent
import android.content.SharedPreferences
import android.os.AsyncTask
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.PreferenceManager
import org.libre.agosto.p2play.activities.MainActivity
import org.libre.agosto.p2play.ajax.Auth
import org.libre.agosto.p2play.helpers.TaskManager
import org.libre.agosto.p2play.models.TokenModel

View File

@ -0,0 +1,69 @@
package org.libre.agosto.p2play.activities
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ChainStyle
import androidx.constraintlayout.compose.ConstraintLayout
import org.libre.agosto.p2play.MainActivity
import org.libre.agosto.p2play.activities.ui.theme.P2playTheme
class HostActivityV2: ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
P2playTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
ConstraintLayout(modifier = Modifier.padding(innerPadding).fillMaxSize()) {
val (textLabel, emailField, passwordField) = createRefs()
Text("Iniciar session", modifier = Modifier.constrainAs(textLabel) {
top.linkTo(parent.top)
start.linkTo(parent.start)
end.linkTo(parent.end)
bottom.linkTo(emailField.top)
})
TextField("", {}, label = { Text("Email") }, modifier = Modifier.padding(10.dp).constrainAs(emailField) {
top.linkTo(textLabel.bottom)
start.linkTo(parent.start)
end.linkTo(parent.end)
bottom.linkTo(passwordField.top)
})
TextField("", {}, label = { Text("Password") }, modifier = Modifier.constrainAs(passwordField) {
top.linkTo(emailField.bottom)
start.linkTo(parent.start)
end.linkTo(parent.end)
bottom.linkTo(parent.bottom)
})
createVerticalChain(textLabel, emailField, passwordField, chainStyle = ChainStyle.Packed)
}
}
}
}
}
private fun instanceSelected () {
}
private fun startApp() {
runOnUiThread {
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
this.finish()
}
}
}

View File

@ -0,0 +1,45 @@
package org.libre.agosto.p2play.activities
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import org.libre.agosto.p2play.MainActivity
import org.libre.agosto.p2play.activities.ui.theme.P2playTheme
import org.libre.agosto.p2play.components.MainNavigationBar
import org.libre.agosto.p2play.components.MainTopAppBar
import org.libre.agosto.p2play.components.organisms.VideoItem
import org.libre.agosto.p2play.components.views.VideosView
import org.libre.agosto.p2play.models.VideoModel
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
P2playTheme {
Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = { MainTopAppBar() },
bottomBar = { MainNavigationBar() }
) { innerPadding ->
VideosView(
modifier = Modifier.padding(innerPadding)
) {
}
}
}
}
}
}

View File

@ -0,0 +1,226 @@
package org.libre.agosto.p2play.activities.ui.theme
import androidx.compose.ui.graphics.Color
val primaryLight = Color(0xFF8A5022)
val onPrimaryLight = Color(0xFFFFFFFF)
val primaryContainerLight = Color(0xFFFFDCC6)
val onPrimaryContainerLight = Color(0xFF6D390C)
val secondaryLight = Color(0xFF755845)
val onSecondaryLight = Color(0xFFFFFFFF)
val secondaryContainerLight = Color(0xFFFFDCC6)
val onSecondaryContainerLight = Color(0xFF5B412F)
val tertiaryLight = Color(0xFF5F6135)
val onTertiaryLight = Color(0xFFFFFFFF)
val tertiaryContainerLight = Color(0xFFE4E6AE)
val onTertiaryContainerLight = Color(0xFF47491F)
val errorLight = Color(0xFFBA1A1A)
val onErrorLight = Color(0xFFFFFFFF)
val errorContainerLight = Color(0xFFFFDAD6)
val onErrorContainerLight = Color(0xFF93000A)
val backgroundLight = Color(0xFFFFF8F5)
val onBackgroundLight = Color(0xFF221A15)
val surfaceLight = Color(0xFFFFF8F5)
val onSurfaceLight = Color(0xFF221A15)
val surfaceVariantLight = Color(0xFFF3DED2)
val onSurfaceVariantLight = Color(0xFF52443B)
val outlineLight = Color(0xFF84746A)
val outlineVariantLight = Color(0xFFD7C3B7)
val scrimLight = Color(0xFF000000)
val inverseSurfaceLight = Color(0xFF382F29)
val inverseOnSurfaceLight = Color(0xFFFEEDE4)
val inversePrimaryLight = Color(0xFFFFB784)
val surfaceDimLight = Color(0xFFE7D7CE)
val surfaceBrightLight = Color(0xFFFFF8F5)
val surfaceContainerLowestLight = Color(0xFFFFFFFF)
val surfaceContainerLowLight = Color(0xFFFFF1EA)
val surfaceContainerLight = Color(0xFFFBEBE2)
val surfaceContainerHighLight = Color(0xFFF6E5DC)
val surfaceContainerHighestLight = Color(0xFFF0DFD6)
val primaryLightMediumContrast = Color(0xFF582900)
val onPrimaryLightMediumContrast = Color(0xFFFFFFFF)
val primaryContainerLightMediumContrast = Color(0xFF9C5E2F)
val onPrimaryContainerLightMediumContrast = Color(0xFFFFFFFF)
val secondaryLightMediumContrast = Color(0xFF493120)
val onSecondaryLightMediumContrast = Color(0xFFFFFFFF)
val secondaryContainerLightMediumContrast = Color(0xFF856753)
val onSecondaryContainerLightMediumContrast = Color(0xFFFFFFFF)
val tertiaryLightMediumContrast = Color(0xFF363810)
val onTertiaryLightMediumContrast = Color(0xFFFFFFFF)
val tertiaryContainerLightMediumContrast = Color(0xFF6E7042)
val onTertiaryContainerLightMediumContrast = Color(0xFFFFFFFF)
val errorLightMediumContrast = Color(0xFF740006)
val onErrorLightMediumContrast = Color(0xFFFFFFFF)
val errorContainerLightMediumContrast = Color(0xFFCF2C27)
val onErrorContainerLightMediumContrast = Color(0xFFFFFFFF)
val backgroundLightMediumContrast = Color(0xFFFFF8F5)
val onBackgroundLightMediumContrast = Color(0xFF221A15)
val surfaceLightMediumContrast = Color(0xFFFFF8F5)
val onSurfaceLightMediumContrast = Color(0xFF17100B)
val surfaceVariantLightMediumContrast = Color(0xFFF3DED2)
val onSurfaceVariantLightMediumContrast = Color(0xFF40342B)
val outlineLightMediumContrast = Color(0xFF5E5047)
val outlineVariantLightMediumContrast = Color(0xFF7A6A60)
val scrimLightMediumContrast = Color(0xFF000000)
val inverseSurfaceLightMediumContrast = Color(0xFF382F29)
val inverseOnSurfaceLightMediumContrast = Color(0xFFFEEDE4)
val inversePrimaryLightMediumContrast = Color(0xFFFFB784)
val surfaceDimLightMediumContrast = Color(0xFFD3C3BB)
val surfaceBrightLightMediumContrast = Color(0xFFFFF8F5)
val surfaceContainerLowestLightMediumContrast = Color(0xFFFFFFFF)
val surfaceContainerLowLightMediumContrast = Color(0xFFFFF1EA)
val surfaceContainerLightMediumContrast = Color(0xFFF6E5DC)
val surfaceContainerHighLightMediumContrast = Color(0xFFEADAD1)
val surfaceContainerHighestLightMediumContrast = Color(0xFFDECFC6)
val primaryLightHighContrast = Color(0xFF492100)
val onPrimaryLightHighContrast = Color(0xFFFFFFFF)
val primaryContainerLightHighContrast = Color(0xFF703B0E)
val onPrimaryContainerLightHighContrast = Color(0xFFFFFFFF)
val secondaryLightHighContrast = Color(0xFF3D2717)
val onSecondaryLightHighContrast = Color(0xFFFFFFFF)
val secondaryContainerLightHighContrast = Color(0xFF5E4432)
val onSecondaryContainerLightHighContrast = Color(0xFFFFFFFF)
val tertiaryLightHighContrast = Color(0xFF2C2E07)
val onTertiaryLightHighContrast = Color(0xFFFFFFFF)
val tertiaryContainerLightHighContrast = Color(0xFF494C22)
val onTertiaryContainerLightHighContrast = Color(0xFFFFFFFF)
val errorLightHighContrast = Color(0xFF600004)
val onErrorLightHighContrast = Color(0xFFFFFFFF)
val errorContainerLightHighContrast = Color(0xFF98000A)
val onErrorContainerLightHighContrast = Color(0xFFFFFFFF)
val backgroundLightHighContrast = Color(0xFFFFF8F5)
val onBackgroundLightHighContrast = Color(0xFF221A15)
val surfaceLightHighContrast = Color(0xFFFFF8F5)
val onSurfaceLightHighContrast = Color(0xFF000000)
val surfaceVariantLightHighContrast = Color(0xFFF3DED2)
val onSurfaceVariantLightHighContrast = Color(0xFF000000)
val outlineLightHighContrast = Color(0xFF362A22)
val outlineVariantLightHighContrast = Color(0xFF54463E)
val scrimLightHighContrast = Color(0xFF000000)
val inverseSurfaceLightHighContrast = Color(0xFF382F29)
val inverseOnSurfaceLightHighContrast = Color(0xFFFFFFFF)
val inversePrimaryLightHighContrast = Color(0xFFFFB784)
val surfaceDimLightHighContrast = Color(0xFFC5B6AD)
val surfaceBrightLightHighContrast = Color(0xFFFFF8F5)
val surfaceContainerLowestLightHighContrast = Color(0xFFFFFFFF)
val surfaceContainerLowLightHighContrast = Color(0xFFFEEDE4)
val surfaceContainerLightHighContrast = Color(0xFFF0DFD6)
val surfaceContainerHighLightHighContrast = Color(0xFFE1D1C9)
val surfaceContainerHighestLightHighContrast = Color(0xFFD3C3BB)
val primaryDark = Color(0xFFFFB784)
val onPrimaryDark = Color(0xFF4F2500)
val primaryContainerDark = Color(0xFF6D390C)
val onPrimaryContainerDark = Color(0xFFFFDCC6)
val secondaryDark = Color(0xFFE4BFA8)
val onSecondaryDark = Color(0xFF422B1B)
val secondaryContainerDark = Color(0xFF5B412F)
val onSecondaryContainerDark = Color(0xFFFFDCC6)
val tertiaryDark = Color(0xFFC8CA94)
val onTertiaryDark = Color(0xFF30330B)
val tertiaryContainerDark = Color(0xFF47491F)
val onTertiaryContainerDark = Color(0xFFE4E6AE)
val errorDark = Color(0xFFFFB4AB)
val onErrorDark = Color(0xFF690005)
val errorContainerDark = Color(0xFF93000A)
val onErrorContainerDark = Color(0xFFFFDAD6)
val backgroundDark = Color(0xFF19120D)
val onBackgroundDark = Color(0xFFF0DFD6)
val surfaceDark = Color(0xFF19120D)
val onSurfaceDark = Color(0xFFF0DFD6)
val surfaceVariantDark = Color(0xFF52443B)
val onSurfaceVariantDark = Color(0xFFD7C3B7)
val outlineDark = Color(0xFF9F8D83)
val outlineVariantDark = Color(0xFF52443B)
val scrimDark = Color(0xFF000000)
val inverseSurfaceDark = Color(0xFFF0DFD6)
val inverseOnSurfaceDark = Color(0xFF382F29)
val inversePrimaryDark = Color(0xFF8A5022)
val surfaceDimDark = Color(0xFF19120D)
val surfaceBrightDark = Color(0xFF413731)
val surfaceContainerLowestDark = Color(0xFF140D08)
val surfaceContainerLowDark = Color(0xFF221A15)
val surfaceContainerDark = Color(0xFF261E18)
val surfaceContainerHighDark = Color(0xFF312822)
val surfaceContainerHighestDark = Color(0xFF3C332D)
val primaryDarkMediumContrast = Color(0xFFFFD4B8)
val onPrimaryDarkMediumContrast = Color(0xFF3F1C00)
val primaryContainerDarkMediumContrast = Color(0xFFC5814F)
val onPrimaryContainerDarkMediumContrast = Color(0xFF000000)
val secondaryDarkMediumContrast = Color(0xFFFBD5BC)
val onSecondaryDarkMediumContrast = Color(0xFF362111)
val secondaryContainerDarkMediumContrast = Color(0xFFAB8A75)
val onSecondaryContainerDarkMediumContrast = Color(0xFF000000)
val tertiaryDarkMediumContrast = Color(0xFFDEE0A8)
val onTertiaryDarkMediumContrast = Color(0xFF262802)
val tertiaryContainerDarkMediumContrast = Color(0xFF929462)
val onTertiaryContainerDarkMediumContrast = Color(0xFF000000)
val errorDarkMediumContrast = Color(0xFFFFD2CC)
val onErrorDarkMediumContrast = Color(0xFF540003)
val errorContainerDarkMediumContrast = Color(0xFFFF5449)
val onErrorContainerDarkMediumContrast = Color(0xFF000000)
val backgroundDarkMediumContrast = Color(0xFF19120D)
val onBackgroundDarkMediumContrast = Color(0xFFF0DFD6)
val surfaceDarkMediumContrast = Color(0xFF19120D)
val onSurfaceDarkMediumContrast = Color(0xFFFFFFFF)
val surfaceVariantDarkMediumContrast = Color(0xFF52443B)
val onSurfaceVariantDarkMediumContrast = Color(0xFFEDD8CC)
val outlineDarkMediumContrast = Color(0xFFC1AEA3)
val outlineVariantDarkMediumContrast = Color(0xFF9E8D82)
val scrimDarkMediumContrast = Color(0xFF000000)
val inverseSurfaceDarkMediumContrast = Color(0xFFF0DFD6)
val inverseOnSurfaceDarkMediumContrast = Color(0xFF312822)
val inversePrimaryDarkMediumContrast = Color(0xFF6F3A0D)
val surfaceDimDarkMediumContrast = Color(0xFF19120D)
val surfaceBrightDarkMediumContrast = Color(0xFF4D423C)
val surfaceContainerLowestDarkMediumContrast = Color(0xFF0C0603)
val surfaceContainerLowDarkMediumContrast = Color(0xFF241C17)
val surfaceContainerDarkMediumContrast = Color(0xFF2F2620)
val surfaceContainerHighDarkMediumContrast = Color(0xFF3A312B)
val surfaceContainerHighestDarkMediumContrast = Color(0xFF463C35)
val primaryDarkHighContrast = Color(0xFFFFECE2)
val onPrimaryDarkHighContrast = Color(0xFF000000)
val primaryContainerDarkHighContrast = Color(0xFFFEB17B)
val onPrimaryContainerDarkHighContrast = Color(0xFF180700)
val secondaryDarkHighContrast = Color(0xFFFFECE2)
val onSecondaryDarkHighContrast = Color(0xFF000000)
val secondaryContainerDarkHighContrast = Color(0xFFE0BBA4)
val onSecondaryContainerDarkHighContrast = Color(0xFF170700)
val tertiaryDarkHighContrast = Color(0xFFF2F4BB)
val onTertiaryDarkHighContrast = Color(0xFF000000)
val tertiaryContainerDarkHighContrast = Color(0xFFC4C690)
val onTertiaryContainerDarkHighContrast = Color(0xFF0B0C00)
val errorDarkHighContrast = Color(0xFFFFECE9)
val onErrorDarkHighContrast = Color(0xFF000000)
val errorContainerDarkHighContrast = Color(0xFFFFAEA4)
val onErrorContainerDarkHighContrast = Color(0xFF220001)
val backgroundDarkHighContrast = Color(0xFF19120D)
val onBackgroundDarkHighContrast = Color(0xFFF0DFD6)
val surfaceDarkHighContrast = Color(0xFF19120D)
val onSurfaceDarkHighContrast = Color(0xFFFFFFFF)
val surfaceVariantDarkHighContrast = Color(0xFF52443B)
val onSurfaceVariantDarkHighContrast = Color(0xFFFFFFFF)
val outlineDarkHighContrast = Color(0xFFFFECE2)
val outlineVariantDarkHighContrast = Color(0xFFD2BFB3)
val scrimDarkHighContrast = Color(0xFF000000)
val inverseSurfaceDarkHighContrast = Color(0xFFF0DFD6)
val inverseOnSurfaceDarkHighContrast = Color(0xFF000000)
val inversePrimaryDarkHighContrast = Color(0xFF6F3A0D)
val surfaceDimDarkHighContrast = Color(0xFF19120D)
val surfaceBrightDarkHighContrast = Color(0xFF594E47)
val surfaceContainerLowestDarkHighContrast = Color(0xFF000000)
val surfaceContainerLowDarkHighContrast = Color(0xFF261E18)
val surfaceContainerDarkHighContrast = Color(0xFF382F29)
val surfaceContainerHighDarkHighContrast = Color(0xFF433933)
val surfaceContainerHighestDarkHighContrast = Color(0xFF4F453E)

View File

@ -0,0 +1,278 @@
package org.libre.agosto.p2play.activities.ui.theme
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
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 mediumContrastLightColorScheme = lightColorScheme(
primary = primaryLightMediumContrast,
onPrimary = onPrimaryLightMediumContrast,
primaryContainer = primaryContainerLightMediumContrast,
onPrimaryContainer = onPrimaryContainerLightMediumContrast,
secondary = secondaryLightMediumContrast,
onSecondary = onSecondaryLightMediumContrast,
secondaryContainer = secondaryContainerLightMediumContrast,
onSecondaryContainer = onSecondaryContainerLightMediumContrast,
tertiary = tertiaryLightMediumContrast,
onTertiary = onTertiaryLightMediumContrast,
tertiaryContainer = tertiaryContainerLightMediumContrast,
onTertiaryContainer = onTertiaryContainerLightMediumContrast,
error = errorLightMediumContrast,
onError = onErrorLightMediumContrast,
errorContainer = errorContainerLightMediumContrast,
onErrorContainer = onErrorContainerLightMediumContrast,
background = backgroundLightMediumContrast,
onBackground = onBackgroundLightMediumContrast,
surface = surfaceLightMediumContrast,
onSurface = onSurfaceLightMediumContrast,
surfaceVariant = surfaceVariantLightMediumContrast,
onSurfaceVariant = onSurfaceVariantLightMediumContrast,
outline = outlineLightMediumContrast,
outlineVariant = outlineVariantLightMediumContrast,
scrim = scrimLightMediumContrast,
inverseSurface = inverseSurfaceLightMediumContrast,
inverseOnSurface = inverseOnSurfaceLightMediumContrast,
inversePrimary = inversePrimaryLightMediumContrast,
surfaceDim = surfaceDimLightMediumContrast,
surfaceBright = surfaceBrightLightMediumContrast,
surfaceContainerLowest = surfaceContainerLowestLightMediumContrast,
surfaceContainerLow = surfaceContainerLowLightMediumContrast,
surfaceContainer = surfaceContainerLightMediumContrast,
surfaceContainerHigh = surfaceContainerHighLightMediumContrast,
surfaceContainerHighest = surfaceContainerHighestLightMediumContrast,
)
private val highContrastLightColorScheme = lightColorScheme(
primary = primaryLightHighContrast,
onPrimary = onPrimaryLightHighContrast,
primaryContainer = primaryContainerLightHighContrast,
onPrimaryContainer = onPrimaryContainerLightHighContrast,
secondary = secondaryLightHighContrast,
onSecondary = onSecondaryLightHighContrast,
secondaryContainer = secondaryContainerLightHighContrast,
onSecondaryContainer = onSecondaryContainerLightHighContrast,
tertiary = tertiaryLightHighContrast,
onTertiary = onTertiaryLightHighContrast,
tertiaryContainer = tertiaryContainerLightHighContrast,
onTertiaryContainer = onTertiaryContainerLightHighContrast,
error = errorLightHighContrast,
onError = onErrorLightHighContrast,
errorContainer = errorContainerLightHighContrast,
onErrorContainer = onErrorContainerLightHighContrast,
background = backgroundLightHighContrast,
onBackground = onBackgroundLightHighContrast,
surface = surfaceLightHighContrast,
onSurface = onSurfaceLightHighContrast,
surfaceVariant = surfaceVariantLightHighContrast,
onSurfaceVariant = onSurfaceVariantLightHighContrast,
outline = outlineLightHighContrast,
outlineVariant = outlineVariantLightHighContrast,
scrim = scrimLightHighContrast,
inverseSurface = inverseSurfaceLightHighContrast,
inverseOnSurface = inverseOnSurfaceLightHighContrast,
inversePrimary = inversePrimaryLightHighContrast,
surfaceDim = surfaceDimLightHighContrast,
surfaceBright = surfaceBrightLightHighContrast,
surfaceContainerLowest = surfaceContainerLowestLightHighContrast,
surfaceContainerLow = surfaceContainerLowLightHighContrast,
surfaceContainer = surfaceContainerLightHighContrast,
surfaceContainerHigh = surfaceContainerHighLightHighContrast,
surfaceContainerHighest = surfaceContainerHighestLightHighContrast,
)
private val mediumContrastDarkColorScheme = darkColorScheme(
primary = primaryDarkMediumContrast,
onPrimary = onPrimaryDarkMediumContrast,
primaryContainer = primaryContainerDarkMediumContrast,
onPrimaryContainer = onPrimaryContainerDarkMediumContrast,
secondary = secondaryDarkMediumContrast,
onSecondary = onSecondaryDarkMediumContrast,
secondaryContainer = secondaryContainerDarkMediumContrast,
onSecondaryContainer = onSecondaryContainerDarkMediumContrast,
tertiary = tertiaryDarkMediumContrast,
onTertiary = onTertiaryDarkMediumContrast,
tertiaryContainer = tertiaryContainerDarkMediumContrast,
onTertiaryContainer = onTertiaryContainerDarkMediumContrast,
error = errorDarkMediumContrast,
onError = onErrorDarkMediumContrast,
errorContainer = errorContainerDarkMediumContrast,
onErrorContainer = onErrorContainerDarkMediumContrast,
background = backgroundDarkMediumContrast,
onBackground = onBackgroundDarkMediumContrast,
surface = surfaceDarkMediumContrast,
onSurface = onSurfaceDarkMediumContrast,
surfaceVariant = surfaceVariantDarkMediumContrast,
onSurfaceVariant = onSurfaceVariantDarkMediumContrast,
outline = outlineDarkMediumContrast,
outlineVariant = outlineVariantDarkMediumContrast,
scrim = scrimDarkMediumContrast,
inverseSurface = inverseSurfaceDarkMediumContrast,
inverseOnSurface = inverseOnSurfaceDarkMediumContrast,
inversePrimary = inversePrimaryDarkMediumContrast,
surfaceDim = surfaceDimDarkMediumContrast,
surfaceBright = surfaceBrightDarkMediumContrast,
surfaceContainerLowest = surfaceContainerLowestDarkMediumContrast,
surfaceContainerLow = surfaceContainerLowDarkMediumContrast,
surfaceContainer = surfaceContainerDarkMediumContrast,
surfaceContainerHigh = surfaceContainerHighDarkMediumContrast,
surfaceContainerHighest = surfaceContainerHighestDarkMediumContrast,
)
private val highContrastDarkColorScheme = darkColorScheme(
primary = primaryDarkHighContrast,
onPrimary = onPrimaryDarkHighContrast,
primaryContainer = primaryContainerDarkHighContrast,
onPrimaryContainer = onPrimaryContainerDarkHighContrast,
secondary = secondaryDarkHighContrast,
onSecondary = onSecondaryDarkHighContrast,
secondaryContainer = secondaryContainerDarkHighContrast,
onSecondaryContainer = onSecondaryContainerDarkHighContrast,
tertiary = tertiaryDarkHighContrast,
onTertiary = onTertiaryDarkHighContrast,
tertiaryContainer = tertiaryContainerDarkHighContrast,
onTertiaryContainer = onTertiaryContainerDarkHighContrast,
error = errorDarkHighContrast,
onError = onErrorDarkHighContrast,
errorContainer = errorContainerDarkHighContrast,
onErrorContainer = onErrorContainerDarkHighContrast,
background = backgroundDarkHighContrast,
onBackground = onBackgroundDarkHighContrast,
surface = surfaceDarkHighContrast,
onSurface = onSurfaceDarkHighContrast,
surfaceVariant = surfaceVariantDarkHighContrast,
onSurfaceVariant = onSurfaceVariantDarkHighContrast,
outline = outlineDarkHighContrast,
outlineVariant = outlineVariantDarkHighContrast,
scrim = scrimDarkHighContrast,
inverseSurface = inverseSurfaceDarkHighContrast,
inverseOnSurface = inverseOnSurfaceDarkHighContrast,
inversePrimary = inversePrimaryDarkHighContrast,
surfaceDim = surfaceDimDarkHighContrast,
surfaceBright = surfaceBrightDarkHighContrast,
surfaceContainerLowest = surfaceContainerLowestDarkHighContrast,
surfaceContainerLow = surfaceContainerLowDarkHighContrast,
surfaceContainer = surfaceContainerDarkHighContrast,
surfaceContainerHigh = surfaceContainerHighDarkHighContrast,
surfaceContainerHighest = surfaceContainerHighestDarkHighContrast,
)
@Immutable
data class ColorFamily(
val color: Color,
val onColor: Color,
val colorContainer: Color,
val onColorContainer: Color
)
val unspecified_scheme = ColorFamily(
Color.Unspecified, Color.Unspecified, Color.Unspecified, Color.Unspecified
)
@Composable
fun P2playTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+
dynamicColor: Boolean = true,
content: @Composable() () -> Unit
) {
val colorScheme = when {
// dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
// val context = LocalContext.current
// if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
//}
darkTheme -> darkScheme
else -> lightScheme
}
MaterialTheme(
colorScheme = colorScheme,
typography = AppTypography,
content = content
)
}

View File

@ -0,0 +1,9 @@
package org.libre.agosto.p2play.activities.ui.theme
import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
val AppTypography = Typography()

View File

@ -0,0 +1,44 @@
package org.libre.agosto.p2play.components
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.AccountCircle
import androidx.compose.material.icons.filled.Home
import androidx.compose.material3.Icon
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.sp
import org.libre.agosto.p2play.R
@Composable
fun MainNavigationBar () {
NavigationBar {
NavigationBarItem(
icon = { Icon(Icons.Filled.Home, "home") },
label = { Text(text = stringResource(R.string.nav_menu_videos), fontSize = 11.sp) },
selected = true,
onClick = {},
)
NavigationBarItem(
icon = { Icon(painterResource(R.drawable.ic_live_tv_black_24dp), "home") },
label = { Text(stringResource(R.string.nav_subscriptions), fontSize = 11.sp) },
selected = false,
onClick = {}
)
NavigationBarItem(
icon = { Icon(painterResource(R.drawable.ic_menu_slideshow), "home") },
label = { Text(stringResource(R.string.playlists), fontSize = 11.sp) },
selected = false,
onClick = {}
)
NavigationBarItem(
icon = { Icon(Icons.Filled.AccountCircle, "home") },
label = { Text(stringResource(R.string.you), fontSize = 11.sp) },
selected = false,
onClick = {}
)
}
}

View File

@ -0,0 +1,31 @@
package org.libre.agosto.p2play.components
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Notifications
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import org.libre.agosto.p2play.R
@OptIn(ExperimentalMaterial3Api::class)
@Preview(showSystemUi = true)
@Composable
fun MainTopAppBar(modifier: Modifier = Modifier) {
TopAppBar(
{ Text(stringResource(R.string.nav_menu_videos)) },
modifier,
actions = {
IconButton({}) { Icon(Icons.Default.Search, "More") }
IconButton({}) { Icon(Icons.Default.Notifications, "More") }
IconButton({}) { Icon(Icons.Default.MoreVert, "More") }
}
)
}

View File

@ -0,0 +1,36 @@
package org.libre.agosto.p2play.components.lists
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.snapshotFlow
import org.libre.agosto.p2play.components.organisms.VideoItem
import org.libre.agosto.p2play.models.VideoModel
@Composable
fun VideoList (videos: ArrayList<VideoModel>, header: @Composable (() -> Unit)?, onLoadMore: (() -> Unit)? = null) {
val lazyState = rememberLazyListState()
LazyColumn {
if (header !== null) {
item { header() }
}
items (videos) {
VideoItem(it)
}
}
if (onLoadMore !== null) {
LaunchedEffect(lazyState) {
snapshotFlow { lazyState.layoutInfo.visibleItemsInfo }
.collect { visibleItems ->
if (visibleItems.isNotEmpty() &&
visibleItems.last().index >= videos.size - 1) {
onLoadMore()
}
}
}
}
}

View File

@ -0,0 +1,47 @@
package org.libre.agosto.p2play.components.molecules
import android.graphics.drawable.Icon
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material3.FilterChip
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.unit.dp
interface ChipValues<T> {
val text: String
val value: T
val icon: ImageVector?
}
@Composable
fun <T> ChipSelector (values: ArrayList<ChipValues<T>>, value: T? = null, modifier: Modifier = Modifier, callback: (T) -> Unit) {
Row (modifier.horizontalScroll(rememberScrollState())) {
Spacer(modifier.width(10.dp))
for (v in values) {
val isSelected = value == v.value
FilterChip(
selected = isSelected,
{ callback(v.value) },
label = { Text(v.text) },
leadingIcon = {
if (isSelected) {
Icon(Icons.Default.Check, "", Modifier.height(20.dp))
} else if (v.icon !== null) {
Icon(v.icon!!, "", Modifier.height(20.dp))
}
}
)
Spacer(modifier.width(10.dp))
}
}
}

View File

@ -0,0 +1,118 @@
package org.libre.agosto.p2play.components.organisms
import android.content.Intent
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.Card
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.constraintlayout.compose.ChainStyle
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.constraintlayout.compose.Dimension
import coil3.compose.AsyncImage
import org.libre.agosto.p2play.ChannelActivity
import org.libre.agosto.p2play.MainActivity
import org.libre.agosto.p2play.ManagerSingleton
import org.libre.agosto.p2play.R
import org.libre.agosto.p2play.ReproductorActivity
import org.libre.agosto.p2play.activities.ui.theme.AppTypography
import org.libre.agosto.p2play.helpers.mapSeconds
import org.libre.agosto.p2play.models.VideoModel
@Composable
fun VideoItem (
videoData: VideoModel
) {
val context = LocalContext.current
val userImgSource = if (videoData.userImageUrl !== "") {
"https://${ManagerSingleton.url}${videoData.userImageUrl}"
} else {
R.drawable.default_avatar
}
Card({
val intent = Intent(context, ReproductorActivity::class.java)
intent.putExtra("video", videoData)
context.startActivity(intent)
}, modifier = Modifier.padding(vertical = 10.dp)) {
ConstraintLayout() {
val (thumbailImg, durationTxt, titleTxt, infoBox, userImg) = createRefs()
Box(modifier = Modifier.fillMaxWidth().aspectRatio(16f / 9f).constrainAs(thumbailImg) {
top.linkTo(parent.top)
start.linkTo(parent.start)
end.linkTo(parent.end)
}) {
AsyncImage(
"https://${ManagerSingleton.url}${videoData.thumbUrl}",
videoData.name,
contentScale = ContentScale.Crop,
modifier = Modifier.matchParentSize()
)
}
Text(mapSeconds(videoData.duration.toInt()), color = Color.Black, modifier = Modifier.alpha(0.5F).padding(5.dp).background(Color.White).constrainAs(durationTxt) {
end.linkTo(thumbailImg.end)
bottom.linkTo(thumbailImg.bottom)
})
Box(modifier = Modifier.constrainAs(userImg) {
top.linkTo(thumbailImg.bottom)
start.linkTo(parent.start)
bottom.linkTo(parent.bottom)
}.clickable {
val intent = Intent(context, ChannelActivity::class.java)
intent.putExtra("channel", videoData.getChannel())
context.startActivity(intent)
}) {
AsyncImage(
userImgSource,
"Profile photo",
contentScale = ContentScale.Fit,
modifier = Modifier.padding(10.dp).size(40.dp).clip(CircleShape),
)
}
Text(
videoData.name,
style = AppTypography.titleMedium,
overflow = TextOverflow.Ellipsis,
lineHeight = 19.sp,
textAlign = TextAlign.Left,
modifier = Modifier.constrainAs(titleTxt) {
top.linkTo(thumbailImg.bottom)
start.linkTo(userImg.end)
}.padding(top = 12.dp, end = 70.dp)
)
Row (modifier = Modifier.constrainAs(infoBox) {
top.linkTo(titleTxt.bottom)
start.linkTo(userImg.end)
}.padding(bottom = 5.dp)) {
Text(videoData.nameChannel, style = AppTypography.labelSmall)
Text(" - ", style = AppTypography.labelSmall)
Text("${videoData.views.toString()} ${stringResource(R.string.view_text)}", style = AppTypography.labelSmall)
}
// createVerticalChain(thumbailImg, titleTxt, infoBox, chainStyle = ChainStyle.Packed)
}
}
}

View File

@ -0,0 +1,2 @@
package org.libre.agosto.p2play.components.views

View File

@ -0,0 +1,73 @@
package org.libre.agosto.p2play.components.views
import android.annotation.SuppressLint
import androidx.compose.foundation.layout.Column
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Star
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import org.libre.agosto.p2play.R
import org.libre.agosto.p2play.ajax.Videos
import org.libre.agosto.p2play.components.lists.VideoList
import org.libre.agosto.p2play.components.molecules.ChipSelector
import org.libre.agosto.p2play.components.molecules.ChipValues
import org.libre.agosto.p2play.helpers.TaskManager
import org.libre.agosto.p2play.models.VideoModel
@SuppressLint("MutableCollectionMutableState")
@Composable
fun VideosView (modifier: Modifier, click: (VideoModel) -> Unit) {
val client: Videos = Videos()
var videoFilter by rememberSaveable { mutableStateOf("trending") }
val chips = arrayListOf(
object : ChipValues<String> {
override val text = stringResource(R.string.nav_trending)
override val value = "trending"
override val icon = ImageVector.vectorResource(R.drawable.ic_trending_up_black_24dp)
},
object : ChipValues<String> {
override val text = stringResource(R.string.nav_likes)
override val value = "likes"
override val icon = ImageVector.vectorResource(R.drawable.ic_thumb_up_black_24dp)
},
object : ChipValues<String> {
override val text = stringResource(R.string.nav_popular)
override val value = "popular"
override val icon = Icons.Filled.Star
},
object : ChipValues<String> {
override val text = stringResource(R.string.nav_recent)
override val value = "recent"
override val icon = ImageVector.vectorResource(R.drawable.ic_add_circle_black_24dp)
},
object : ChipValues<String> {
override val text = stringResource(R.string.nav_local)
override val value = "local"
override val icon = ImageVector.vectorResource(R.drawable.ic_home_black_24dp)
}
)
var videos by rememberSaveable { mutableStateOf<ArrayList<VideoModel>>(arrayListOf<VideoModel>()) }
val task = TaskManager<ArrayList<VideoModel>>()
task.runTask({ client.getLastVideos() }) {
videos = it
}
Column (modifier) {
VideoList(
videos,
header = {
ChipSelector(chips, videoFilter) {
videoFilter = it
}
}
)
}
}

View File

@ -128,7 +128,7 @@
<!-- Start Prompt string -->
<string name="reportDialog">Reason to report this video:</string>
<string name="reportDialogMsg">You reported the video</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
<!-- End Prompt strings -->
<string name="playlists">Playlists</string>
<string name="you">You</string>
</resources>