Merge branch 'refactor' into pr11282
This commit is contained in:
commit
aaf337421d
210
app/build.gradle
210
app/build.gradle
|
@ -4,15 +4,15 @@ import com.android.tools.profgen.DexFile
|
||||||
import com.mikepenz.aboutlibraries.plugin.DuplicateMode
|
import com.mikepenz.aboutlibraries.plugin.DuplicateMode
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id "com.android.application"
|
alias libs.plugins.android.application
|
||||||
id "kotlin-android"
|
alias libs.plugins.kotlin.android
|
||||||
id "kotlin-kapt"
|
alias libs.plugins.kotlin.compose
|
||||||
id "kotlin-parcelize"
|
alias libs.plugins.kotlin.kapt
|
||||||
id "checkstyle"
|
alias libs.plugins.kotlin.parcelize
|
||||||
id "org.sonarqube" version "4.0.0.2929"
|
alias libs.plugins.checkstyle
|
||||||
id "org.jetbrains.kotlin.plugin.compose" version "${kotlin_version}"
|
alias libs.plugins.sonarqube
|
||||||
id 'com.google.dagger.hilt.android'
|
alias libs.plugins.hilt
|
||||||
id 'com.mikepenz.aboutlibraries.plugin'
|
alias libs.plugins.aboutlibraries
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
@ -111,25 +111,6 @@ android {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ext {
|
|
||||||
checkstyleVersion = '10.12.1'
|
|
||||||
|
|
||||||
androidxLifecycleVersion = '2.6.2'
|
|
||||||
androidxRoomVersion = '2.6.1'
|
|
||||||
androidxWorkVersion = '2.8.1'
|
|
||||||
|
|
||||||
stateSaverVersion = '1.4.1'
|
|
||||||
exoPlayerVersion = '2.18.7'
|
|
||||||
googleAutoServiceVersion = '1.1.1'
|
|
||||||
groupieVersion = '2.10.1'
|
|
||||||
markwonVersion = '4.6.2'
|
|
||||||
|
|
||||||
leakCanaryVersion = '2.12'
|
|
||||||
stethoVersion = '1.6.0'
|
|
||||||
|
|
||||||
coilVersion = '3.0.3'
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
checkstyle
|
checkstyle
|
||||||
ktlint
|
ktlint
|
||||||
|
@ -139,7 +120,7 @@ checkstyle {
|
||||||
getConfigDirectory().set(rootProject.file("checkstyle"))
|
getConfigDirectory().set(rootProject.file("checkstyle"))
|
||||||
ignoreFailures false
|
ignoreFailures false
|
||||||
showViolations true
|
showViolations true
|
||||||
toolVersion = checkstyleVersion
|
toolVersion = libs.versions.checkstyle.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('runCheckstyle', Checkstyle) {
|
tasks.register('runCheckstyle', Checkstyle) {
|
||||||
|
@ -181,11 +162,13 @@ tasks.register('formatKtlint', JavaExec) {
|
||||||
jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED")
|
jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
apply from: 'check-dependencies.gradle'
|
||||||
|
|
||||||
afterEvaluate {
|
afterEvaluate {
|
||||||
if (!System.properties.containsKey('skipFormatKtlint')) {
|
if (!System.properties.containsKey('skipFormatKtlint')) {
|
||||||
preDebugBuild.dependsOn formatKtlint
|
preDebugBuild.dependsOn formatKtlint
|
||||||
}
|
}
|
||||||
preDebugBuild.dependsOn runCheckstyle, runKtlint
|
preDebugBuild.dependsOn runCheckstyle, runKtlint, checkDependenciesOrder
|
||||||
}
|
}
|
||||||
|
|
||||||
sonar {
|
sonar {
|
||||||
|
@ -209,146 +192,143 @@ aboutLibraries {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
/** Desugaring **/
|
/** Desugaring **/
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs_nio:2.0.4'
|
coreLibraryDesugaring libs.desugar.jdk.libs.nio
|
||||||
|
|
||||||
/** NewPipe libraries **/
|
/** NewPipe libraries **/
|
||||||
// You can use a local version by uncommenting a few lines in settings.gradle
|
implementation libs.teamnewpipe.nanojson
|
||||||
// Or you can use a commit you pushed to GitHub by just replacing TeamNewPipe with your GitHub
|
implementation libs.teamnewpipe.newpipe.extractor
|
||||||
// name and the commit hash with the commit hash of the (pushed) commit you want to test
|
implementation libs.teamnewpipe.nononsense.filepicker
|
||||||
// This works thanks to JitPack: https://jitpack.io/
|
|
||||||
implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751'
|
|
||||||
// WORKAROUND: v0.24.2 can't be resolved by jitpack -> use git commit hash instead
|
|
||||||
implementation 'com.github.TeamNewPipe:NewPipeExtractor:d3d5f2b3f03a5f2b479b9f6fdf1c2555cbb9de0e'
|
|
||||||
implementation 'com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0'
|
|
||||||
|
|
||||||
/** Checkstyle **/
|
/** Checkstyle **/
|
||||||
checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}"
|
checkstyle libs.tools.checkstyle
|
||||||
ktlint 'com.pinterest:ktlint:0.45.2'
|
ktlint libs.tools.ktlint
|
||||||
|
|
||||||
/** Kotlin **/
|
/** Kotlin **/
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}"
|
implementation libs.kotlin.stdlib
|
||||||
|
|
||||||
/** AndroidX **/
|
/** AndroidX **/
|
||||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
implementation libs.androidx.appcompat
|
||||||
implementation 'androidx.cardview:cardview:1.0.0'
|
implementation libs.androidx.cardview
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
implementation libs.androidx.constraintlayout
|
||||||
implementation 'androidx.core:core-ktx:1.12.0'
|
implementation libs.androidx.core.ktx
|
||||||
implementation 'androidx.documentfile:documentfile:1.0.1'
|
implementation libs.androidx.documentfile
|
||||||
implementation 'androidx.fragment:fragment-compose:1.8.2'
|
implementation libs.androidx.fragment.compose
|
||||||
implementation "androidx.lifecycle:lifecycle-livedata-ktx:${androidxLifecycleVersion}"
|
implementation libs.androidx.lifecycle.livedata
|
||||||
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:${androidxLifecycleVersion}"
|
implementation libs.androidx.lifecycle.viewmodel
|
||||||
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0'
|
implementation libs.androidx.localbroadcastmanager
|
||||||
implementation 'androidx.media:media:1.7.0'
|
implementation libs.androidx.media
|
||||||
implementation 'androidx.preference:preference:1.2.1'
|
implementation libs.androidx.preference
|
||||||
implementation 'androidx.recyclerview:recyclerview:1.3.2'
|
implementation libs.androidx.recyclerview
|
||||||
implementation "androidx.room:room-runtime:${androidxRoomVersion}"
|
implementation libs.androidx.room.runtime
|
||||||
implementation "androidx.room:room-rxjava3:${androidxRoomVersion}"
|
implementation libs.androidx.room.rxjava3
|
||||||
kapt "androidx.room:room-compiler:${androidxRoomVersion}"
|
kapt libs.androidx.room.compiler
|
||||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
implementation libs.androidx.swiperefreshlayout
|
||||||
implementation "androidx.work:work-runtime-ktx:${androidxWorkVersion}"
|
// Newer version specified to prevent accessibility regressions with RecyclerView, see:
|
||||||
implementation "androidx.work:work-rxjava3:${androidxWorkVersion}"
|
// https://developer.android.com/jetpack/androidx/releases/viewpager2#1.1.0-alpha01
|
||||||
implementation 'com.google.android.material:material:1.11.0'
|
implementation libs.androidx.viewpager2
|
||||||
|
implementation libs.androidx.work.runtime
|
||||||
|
implementation libs.androidx.work.rxjava3
|
||||||
|
implementation libs.androidx.material
|
||||||
|
|
||||||
/** Third-party libraries **/
|
/** Third-party libraries **/
|
||||||
// Instance state boilerplate elimination
|
// Instance state boilerplate elimination
|
||||||
implementation 'com.github.livefront:bridge:v2.0.2'
|
implementation libs.livefront.bridge
|
||||||
implementation "com.evernote:android-state:$stateSaverVersion"
|
implementation libs.android.state
|
||||||
kapt "com.evernote:android-state-processor:$stateSaverVersion"
|
kapt libs.android.state.processor
|
||||||
|
|
||||||
// HTML parser
|
// HTML parser
|
||||||
implementation "org.jsoup:jsoup:1.17.2"
|
implementation libs.jsoup
|
||||||
|
|
||||||
// HTTP client
|
// HTTP client
|
||||||
implementation "com.squareup.okhttp3:okhttp:4.12.0"
|
implementation libs.okhttp
|
||||||
|
|
||||||
// Media player
|
// Media player
|
||||||
implementation "com.google.android.exoplayer:exoplayer-core:${exoPlayerVersion}"
|
implementation libs.exoplayer.core
|
||||||
implementation "com.google.android.exoplayer:exoplayer-dash:${exoPlayerVersion}"
|
implementation libs.exoplayer.dash
|
||||||
implementation "com.google.android.exoplayer:exoplayer-database:${exoPlayerVersion}"
|
implementation libs.exoplayer.database
|
||||||
implementation "com.google.android.exoplayer:exoplayer-datasource:${exoPlayerVersion}"
|
implementation libs.exoplayer.datasource
|
||||||
implementation "com.google.android.exoplayer:exoplayer-hls:${exoPlayerVersion}"
|
implementation libs.exoplayer.hls
|
||||||
implementation "com.google.android.exoplayer:exoplayer-smoothstreaming:${exoPlayerVersion}"
|
implementation libs.exoplayer.smoothstreaming
|
||||||
implementation "com.google.android.exoplayer:exoplayer-ui:${exoPlayerVersion}"
|
implementation libs.exoplayer.ui
|
||||||
implementation "com.google.android.exoplayer:extension-mediasession:${exoPlayerVersion}"
|
implementation libs.extension.mediasession
|
||||||
|
|
||||||
// Metadata generator for service descriptors
|
// Metadata generator for service descriptors
|
||||||
compileOnly "com.google.auto.service:auto-service-annotations:${googleAutoServiceVersion}"
|
compileOnly libs.auto.service
|
||||||
kapt "com.google.auto.service:auto-service:${googleAutoServiceVersion}"
|
kapt libs.auto.service.kapt
|
||||||
|
|
||||||
// Manager for complex RecyclerView layouts
|
// Manager for complex RecyclerView layouts
|
||||||
implementation "com.github.lisawray.groupie:groupie:${groupieVersion}"
|
implementation libs.lisawray.groupie
|
||||||
implementation "com.github.lisawray.groupie:groupie-viewbinding:${groupieVersion}"
|
implementation libs.lisawray.groupie.viewbinding
|
||||||
|
|
||||||
// Image loading
|
// Image loading
|
||||||
implementation "io.coil-kt.coil3:coil-compose:${coilVersion}"
|
implementation libs.coil.compose
|
||||||
implementation "io.coil-kt.coil3:coil-network-okhttp:${coilVersion}"
|
|
||||||
|
|
||||||
// Markdown library for Android
|
// Markdown library for Android
|
||||||
implementation "io.noties.markwon:core:${markwonVersion}"
|
implementation libs.markwon.core
|
||||||
implementation "io.noties.markwon:linkify:${markwonVersion}"
|
implementation libs.markwon.linkify
|
||||||
|
|
||||||
// Crash reporting
|
// Crash reporting
|
||||||
implementation "ch.acra:acra-core:5.11.3"
|
implementation libs.acra.core
|
||||||
|
|
||||||
// Properly restarting
|
// Properly restarting
|
||||||
implementation 'com.jakewharton:process-phoenix:2.1.2'
|
implementation libs.process.phoenix
|
||||||
|
|
||||||
// Reactive extensions for Java VM
|
// Reactive extensions for Java VM
|
||||||
implementation "io.reactivex.rxjava3:rxjava:3.1.8"
|
implementation libs.rxjava3.rxjava
|
||||||
implementation "io.reactivex.rxjava3:rxandroid:3.0.2"
|
implementation libs.rxjava3.rxandroid
|
||||||
// RxJava binding APIs for Android UI widgets
|
// RxJava binding APIs for Android UI widgets
|
||||||
implementation "com.jakewharton.rxbinding4:rxbinding:4.0.0"
|
implementation libs.rxbinding4.rxbinding
|
||||||
|
|
||||||
// Date and time formatting
|
// Date and time formatting
|
||||||
implementation "org.ocpsoft.prettytime:prettytime:5.0.8.Final"
|
implementation libs.prettytime
|
||||||
|
|
||||||
// Jetpack Compose
|
// Jetpack Compose
|
||||||
implementation(platform('androidx.compose:compose-bom:2024.11.00'))
|
implementation(platform(libs.androidx.compose.bom))
|
||||||
implementation 'androidx.compose.material3:material3'
|
implementation libs.androidx.compose.material3
|
||||||
implementation 'androidx.compose.material3.adaptive:adaptive'
|
implementation libs.androidx.compose.adaptive
|
||||||
implementation 'androidx.activity:activity-compose'
|
implementation libs.androidx.activity.compose
|
||||||
implementation 'androidx.compose.ui:ui-tooling-preview'
|
implementation libs.androidx.compose.ui.tooling.preview
|
||||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose'
|
implementation libs.androidx.lifecycle.viewmodel.compose
|
||||||
implementation 'androidx.compose.ui:ui-text' // Needed for parsing HTML to AnnotatedString
|
implementation libs.androidx.compose.ui.text // Needed for parsing HTML to AnnotatedString
|
||||||
implementation 'androidx.compose.material:material-icons-extended'
|
implementation libs.androidx.compose.material.icons.extended
|
||||||
|
|
||||||
// Jetpack Compose related dependencies
|
// Jetpack Compose related dependencies
|
||||||
implementation 'androidx.paging:paging-compose:3.3.2'
|
implementation libs.androidx.paging.compose
|
||||||
implementation "androidx.navigation:navigation-compose:2.8.3"
|
implementation libs.androidx.navigation.compose
|
||||||
|
|
||||||
// Coroutines interop
|
// Coroutines interop
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-rx3:1.8.1'
|
implementation libs.kotlinx.coroutines.rx3
|
||||||
|
|
||||||
// Library loading for About screen
|
// Library loading for About screen
|
||||||
implementation "com.mikepenz:aboutlibraries-compose-m3:$about_libs"
|
implementation libs.aboutlibraries.compose.m3
|
||||||
|
|
||||||
// Hilt
|
// Hilt
|
||||||
implementation("com.google.dagger:hilt-android:2.51.1")
|
implementation libs.hilt.android
|
||||||
kapt("com.google.dagger:hilt-compiler:2.51.1")
|
kapt(libs.hilt.compiler)
|
||||||
|
|
||||||
// Scroll
|
// Scroll
|
||||||
implementation 'com.github.nanihadesuka:LazyColumnScrollbar:2.2.0'
|
implementation libs.lazycolumnscrollbar
|
||||||
|
|
||||||
/** Debugging **/
|
/** Debugging **/
|
||||||
// Memory leak detection
|
// Memory leak detection
|
||||||
debugImplementation "com.squareup.leakcanary:leakcanary-object-watcher-android:${leakCanaryVersion}"
|
debugImplementation libs.leakcanary.object.watcher
|
||||||
debugImplementation "com.squareup.leakcanary:plumber-android:${leakCanaryVersion}"
|
debugImplementation libs.leakcanary.plumber.android
|
||||||
debugImplementation "com.squareup.leakcanary:leakcanary-android-core:${leakCanaryVersion}"
|
debugImplementation libs.leakcanary.android.core
|
||||||
// Debug bridge for Android
|
// Debug bridge for Android
|
||||||
debugImplementation "com.facebook.stetho:stetho:${stethoVersion}"
|
debugImplementation libs.stetho
|
||||||
debugImplementation "com.facebook.stetho:stetho-okhttp3:${stethoVersion}"
|
debugImplementation libs.stetho.okhttp3
|
||||||
|
|
||||||
// Jetpack Compose
|
// Jetpack Compose
|
||||||
debugImplementation 'androidx.compose.ui:ui-tooling'
|
debugImplementation libs.androidx.compose.ui.tooling
|
||||||
|
|
||||||
/** Testing **/
|
/** Testing **/
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation libs.junit
|
||||||
testImplementation 'org.mockito:mockito-core:5.6.0'
|
testImplementation libs.mockito.core
|
||||||
|
|
||||||
androidTestImplementation "androidx.test.ext:junit:1.1.5"
|
androidTestImplementation libs.androidx.junit
|
||||||
androidTestImplementation "androidx.test:runner:1.5.2"
|
androidTestImplementation libs.androidx.runner
|
||||||
androidTestImplementation "androidx.room:room-testing:${androidxRoomVersion}"
|
androidTestImplementation libs.androidx.room.testing
|
||||||
androidTestImplementation "org.assertj:assertj-core:3.24.2"
|
androidTestImplementation libs.assertj.core
|
||||||
}
|
}
|
||||||
|
|
||||||
static String getGitWorkingBranch() {
|
static String getGitWorkingBranch() {
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
tasks.register('checkDependenciesOrder') {
|
||||||
|
group = 'verification'
|
||||||
|
description = 'Checks that each section in libs.versions.toml is sorted alphabetically'
|
||||||
|
|
||||||
|
def tomlFile = file('../gradle/libs.versions.toml')
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
if (!tomlFile.exists()) {
|
||||||
|
throw new GradleException('TOML file not found')
|
||||||
|
}
|
||||||
|
|
||||||
|
def lines = tomlFile.readLines()
|
||||||
|
def nonSortedBlocks = []
|
||||||
|
def currentBlock = []
|
||||||
|
def prevLine = ''
|
||||||
|
def prevIndex = 0
|
||||||
|
|
||||||
|
lines.eachWithIndex { line, lineIndex ->
|
||||||
|
if (line.trim() && !line.startsWith('#')) {
|
||||||
|
if (line.startsWith('[')) {
|
||||||
|
prevLine = ''
|
||||||
|
} else {
|
||||||
|
def currIndex = lineIndex + 1
|
||||||
|
if (prevLine > line) {
|
||||||
|
if (currentBlock && currentBlock[-1] == "${prevIndex}: ${prevLine}") {
|
||||||
|
currentBlock.add("${currIndex}: ${line}")
|
||||||
|
} else {
|
||||||
|
if (!currentBlock.isEmpty()) {
|
||||||
|
nonSortedBlocks.add(currentBlock)
|
||||||
|
currentBlock = []
|
||||||
|
}
|
||||||
|
currentBlock.add("${prevIndex}: ${prevLine}")
|
||||||
|
currentBlock.add("${currIndex}: ${line}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prevLine = line
|
||||||
|
prevIndex = lineIndex + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!currentBlock.isEmpty()) {
|
||||||
|
nonSortedBlocks.add(currentBlock)
|
||||||
|
throw new GradleException("The following lines were not sorted:\n" +
|
||||||
|
nonSortedBlocks.collect { it.join("\n") }.join("\n\n"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,9 +6,11 @@ import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.compose.ui.platform.ComposeView;
|
||||||
|
|
||||||
import org.schabi.newpipe.BaseFragment;
|
import org.schabi.newpipe.BaseFragment;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateUtil;
|
||||||
|
|
||||||
public class EmptyFragment extends BaseFragment {
|
public class EmptyFragment extends BaseFragment {
|
||||||
private static final String SHOW_MESSAGE = "SHOW_MESSAGE";
|
private static final String SHOW_MESSAGE = "SHOW_MESSAGE";
|
||||||
|
@ -26,8 +28,10 @@ public class EmptyFragment extends BaseFragment {
|
||||||
final Bundle savedInstanceState) {
|
final Bundle savedInstanceState) {
|
||||||
final boolean showMessage = getArguments().getBoolean(SHOW_MESSAGE);
|
final boolean showMessage = getArguments().getBoolean(SHOW_MESSAGE);
|
||||||
final View view = inflater.inflate(R.layout.fragment_empty, container, false);
|
final View view = inflater.inflate(R.layout.fragment_empty, container, false);
|
||||||
view.findViewById(R.id.empty_state_view).setVisibility(
|
|
||||||
showMessage ? View.VISIBLE : View.GONE);
|
final ComposeView composeView = view.findViewById(R.id.empty_state_view);
|
||||||
|
EmptyStateUtil.setEmptyStateComposable(composeView);
|
||||||
|
composeView.setVisibility(showMessage ? View.VISIBLE : View.GONE);
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import android.graphics.Color;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.TypedValue;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
|
@ -45,6 +44,8 @@ import org.schabi.newpipe.fragments.detail.TabAdapter;
|
||||||
import org.schabi.newpipe.ktx.AnimationType;
|
import org.schabi.newpipe.ktx.AnimationType;
|
||||||
import org.schabi.newpipe.local.feed.notifications.NotificationHelper;
|
import org.schabi.newpipe.local.feed.notifications.NotificationHelper;
|
||||||
import org.schabi.newpipe.local.subscription.SubscriptionManager;
|
import org.schabi.newpipe.local.subscription.SubscriptionManager;
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateSpec;
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateUtil;
|
||||||
import org.schabi.newpipe.util.ChannelTabHelper;
|
import org.schabi.newpipe.util.ChannelTabHelper;
|
||||||
import org.schabi.newpipe.util.Constants;
|
import org.schabi.newpipe.util.Constants;
|
||||||
import org.schabi.newpipe.util.ExtractorHelper;
|
import org.schabi.newpipe.util.ExtractorHelper;
|
||||||
|
@ -199,6 +200,11 @@ public class ChannelFragment extends BaseStateFragment<ChannelInfo>
|
||||||
protected void initViews(final View rootView, final Bundle savedInstanceState) {
|
protected void initViews(final View rootView, final Bundle savedInstanceState) {
|
||||||
super.initViews(rootView, savedInstanceState);
|
super.initViews(rootView, savedInstanceState);
|
||||||
|
|
||||||
|
EmptyStateUtil.setEmptyStateComposable(
|
||||||
|
binding.emptyStateView,
|
||||||
|
EmptyStateSpec.Companion.getContentNotSupported()
|
||||||
|
);
|
||||||
|
|
||||||
tabAdapter = new TabAdapter(getChildFragmentManager());
|
tabAdapter = new TabAdapter(getChildFragmentManager());
|
||||||
binding.viewPager.setAdapter(tabAdapter);
|
binding.viewPager.setAdapter(tabAdapter);
|
||||||
binding.tabLayout.setupWithViewPager(binding.viewPager);
|
binding.tabLayout.setupWithViewPager(binding.viewPager);
|
||||||
|
@ -645,8 +651,6 @@ public class ChannelFragment extends BaseStateFragment<ChannelInfo>
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.errorContentNotSupported.setVisibility(View.VISIBLE);
|
binding.emptyStateView.setVisibility(View.VISIBLE);
|
||||||
binding.channelKaomoji.setText("(︶︹︺)");
|
|
||||||
binding.channelKaomoji.setTextSize(TypedValue.COMPLEX_UNIT_SP, 45f);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@ import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
||||||
import org.schabi.newpipe.fragments.list.playlist.PlaylistControlViewHolder;
|
import org.schabi.newpipe.fragments.list.playlist.PlaylistControlViewHolder;
|
||||||
import org.schabi.newpipe.player.playqueue.ChannelTabPlayQueue;
|
import org.schabi.newpipe.player.playqueue.ChannelTabPlayQueue;
|
||||||
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateUtil;
|
||||||
import org.schabi.newpipe.util.ChannelTabHelper;
|
import org.schabi.newpipe.util.ChannelTabHelper;
|
||||||
import org.schabi.newpipe.util.ExtractorHelper;
|
import org.schabi.newpipe.util.ExtractorHelper;
|
||||||
import org.schabi.newpipe.util.PlayButtonHelper;
|
import org.schabi.newpipe.util.PlayButtonHelper;
|
||||||
|
@ -79,6 +80,12 @@ public class ChannelTabFragment extends BaseListInfoFragment<InfoItem, ChannelTa
|
||||||
return inflater.inflate(R.layout.fragment_channel_tab, container, false);
|
return inflater.inflate(R.layout.fragment_channel_tab, container, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(@NonNull final View rootView, final Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(rootView, savedInstanceState);
|
||||||
|
EmptyStateUtil.setEmptyStateComposable(rootView.findViewById(R.id.empty_state_view));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
|
|
|
@ -64,6 +64,8 @@ import org.schabi.newpipe.ktx.AnimationType;
|
||||||
import org.schabi.newpipe.ktx.ExceptionUtils;
|
import org.schabi.newpipe.ktx.ExceptionUtils;
|
||||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||||
import org.schabi.newpipe.settings.NewPipeSettings;
|
import org.schabi.newpipe.settings.NewPipeSettings;
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateSpec;
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateUtil;
|
||||||
import org.schabi.newpipe.util.Constants;
|
import org.schabi.newpipe.util.Constants;
|
||||||
import org.schabi.newpipe.util.DeviceUtils;
|
import org.schabi.newpipe.util.DeviceUtils;
|
||||||
import org.schabi.newpipe.util.ExtractorHelper;
|
import org.schabi.newpipe.util.ExtractorHelper;
|
||||||
|
@ -344,6 +346,10 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||||
protected void initViews(final View rootView, final Bundle savedInstanceState) {
|
protected void initViews(final View rootView, final Bundle savedInstanceState) {
|
||||||
super.initViews(rootView, savedInstanceState);
|
super.initViews(rootView, savedInstanceState);
|
||||||
|
|
||||||
|
EmptyStateUtil.setEmptyStateComposable(
|
||||||
|
searchBinding.emptyStateView,
|
||||||
|
EmptyStateSpec.Companion.getNoSearchResult());
|
||||||
|
|
||||||
searchBinding.suggestionsList.setAdapter(suggestionListAdapter);
|
searchBinding.suggestionsList.setAdapter(suggestionListAdapter);
|
||||||
// animations are just strange and useless, since the suggestions keep changing too much
|
// animations are just strange and useless, since the suggestions keep changing too much
|
||||||
searchBinding.suggestionsList.setItemAnimator(null);
|
searchBinding.suggestionsList.setItemAnimator(null);
|
||||||
|
|
|
@ -38,6 +38,8 @@ import org.schabi.newpipe.local.holder.LocalBookmarkPlaylistItemHolder;
|
||||||
import org.schabi.newpipe.local.holder.RemoteBookmarkPlaylistItemHolder;
|
import org.schabi.newpipe.local.holder.RemoteBookmarkPlaylistItemHolder;
|
||||||
import org.schabi.newpipe.local.playlist.LocalPlaylistManager;
|
import org.schabi.newpipe.local.playlist.LocalPlaylistManager;
|
||||||
import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
|
import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateSpec;
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateUtil;
|
||||||
import org.schabi.newpipe.util.NavigationHelper;
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
import org.schabi.newpipe.util.OnClickGesture;
|
import org.schabi.newpipe.util.OnClickGesture;
|
||||||
import org.schabi.newpipe.util.debounce.DebounceSavable;
|
import org.schabi.newpipe.util.debounce.DebounceSavable;
|
||||||
|
@ -123,6 +125,10 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
|
||||||
super.initViews(rootView, savedInstanceState);
|
super.initViews(rootView, savedInstanceState);
|
||||||
|
|
||||||
itemListAdapter.setUseItemHandle(true);
|
itemListAdapter.setUseItemHandle(true);
|
||||||
|
EmptyStateUtil.setEmptyStateComposable(
|
||||||
|
rootView.findViewById(R.id.empty_state_view),
|
||||||
|
EmptyStateSpec.Companion.getNoBookmarkedPlaylist()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -74,6 +74,7 @@ import org.schabi.newpipe.ktx.slideUp
|
||||||
import org.schabi.newpipe.local.feed.item.StreamItem
|
import org.schabi.newpipe.local.feed.item.StreamItem
|
||||||
import org.schabi.newpipe.local.feed.service.FeedLoadService
|
import org.schabi.newpipe.local.feed.service.FeedLoadService
|
||||||
import org.schabi.newpipe.local.subscription.SubscriptionManager
|
import org.schabi.newpipe.local.subscription.SubscriptionManager
|
||||||
|
import org.schabi.newpipe.ui.emptystate.setEmptyStateComposable
|
||||||
import org.schabi.newpipe.util.DeviceUtils
|
import org.schabi.newpipe.util.DeviceUtils
|
||||||
import org.schabi.newpipe.util.Localization
|
import org.schabi.newpipe.util.Localization
|
||||||
import org.schabi.newpipe.util.NavigationHelper
|
import org.schabi.newpipe.util.NavigationHelper
|
||||||
|
@ -132,6 +133,7 @@ class FeedFragment : BaseStateFragment<FeedState>() {
|
||||||
override fun onViewCreated(rootView: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(rootView: View, savedInstanceState: Bundle?) {
|
||||||
// super.onViewCreated() calls initListeners() which require the binding to be initialized
|
// super.onViewCreated() calls initListeners() which require the binding to be initialized
|
||||||
_feedBinding = FragmentFeedBinding.bind(rootView)
|
_feedBinding = FragmentFeedBinding.bind(rootView)
|
||||||
|
feedBinding.emptyStateView.setEmptyStateComposable()
|
||||||
super.onViewCreated(rootView, savedInstanceState)
|
super.onViewCreated(rootView, savedInstanceState)
|
||||||
|
|
||||||
val factory = FeedViewModel.getFactory(requireContext(), groupId)
|
val factory = FeedViewModel.getFactory(requireContext(), groupId)
|
||||||
|
|
|
@ -56,6 +56,7 @@ import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService
|
||||||
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.PREVIOUS_EXPORT_MODE
|
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.PREVIOUS_EXPORT_MODE
|
||||||
import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard
|
import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard
|
||||||
import org.schabi.newpipe.streams.io.StoredFileHelper
|
import org.schabi.newpipe.streams.io.StoredFileHelper
|
||||||
|
import org.schabi.newpipe.ui.emptystate.setEmptyStateComposable
|
||||||
import org.schabi.newpipe.util.NavigationHelper
|
import org.schabi.newpipe.util.NavigationHelper
|
||||||
import org.schabi.newpipe.util.OnClickGesture
|
import org.schabi.newpipe.util.OnClickGesture
|
||||||
import org.schabi.newpipe.util.ServiceHelper
|
import org.schabi.newpipe.util.ServiceHelper
|
||||||
|
@ -257,6 +258,8 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
||||||
binding.itemsList.adapter = groupAdapter
|
binding.itemsList.adapter = groupAdapter
|
||||||
binding.itemsList.itemAnimator = null
|
binding.itemsList.itemAnimator = null
|
||||||
|
|
||||||
|
binding.emptyStateView.setEmptyStateComposable()
|
||||||
|
|
||||||
viewModel = ViewModelProvider(this)[SubscriptionViewModel::class.java]
|
viewModel = ViewModelProvider(this)[SubscriptionViewModel::class.java]
|
||||||
viewModel.stateLiveData.observe(viewLifecycleOwner) { it?.let(this::handleResult) }
|
viewModel.stateLiveData.observe(viewLifecycleOwner) { it?.let(this::handleResult) }
|
||||||
viewModel.feedGroupsLiveData.observe(viewLifecycleOwner) {
|
viewModel.feedGroupsLiveData.observe(viewLifecycleOwner) {
|
||||||
|
|
|
@ -3,14 +3,18 @@ package org.schabi.newpipe.local.subscription.item
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import com.xwray.groupie.viewbinding.BindableItem
|
import com.xwray.groupie.viewbinding.BindableItem
|
||||||
import org.schabi.newpipe.R
|
import org.schabi.newpipe.R
|
||||||
import org.schabi.newpipe.databinding.ListEmptyViewBinding
|
import org.schabi.newpipe.databinding.ListEmptyViewSubscriptionsBinding
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateSpec
|
||||||
|
import org.schabi.newpipe.ui.emptystate.setEmptyStateComposable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When there are no subscriptions, show a hint to the user about how to import subscriptions
|
* When there are no subscriptions, show a hint to the user about how to import subscriptions
|
||||||
*/
|
*/
|
||||||
class ImportSubscriptionsHintPlaceholderItem : BindableItem<ListEmptyViewBinding>() {
|
class ImportSubscriptionsHintPlaceholderItem : BindableItem<ListEmptyViewSubscriptionsBinding>() {
|
||||||
override fun getLayout(): Int = R.layout.list_empty_view_subscriptions
|
override fun getLayout(): Int = R.layout.list_empty_view_subscriptions
|
||||||
override fun bind(viewBinding: ListEmptyViewBinding, position: Int) {}
|
override fun bind(viewBinding: ListEmptyViewSubscriptionsBinding, position: Int) {
|
||||||
override fun getSpanSize(spanCount: Int, position: Int): Int = spanCount
|
viewBinding.root.setEmptyStateComposable(EmptyStateSpec.NoSubscriptionsHint)
|
||||||
override fun initializeViewBinding(view: View) = ListEmptyViewBinding.bind(view)
|
}
|
||||||
|
override fun getSpanSize(spanCount: Int, position: Int): Int = spanCount
|
||||||
|
override fun initializeViewBinding(view: View) = ListEmptyViewSubscriptionsBinding.bind(view)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.compose.ui.platform.ComposeView;
|
||||||
import androidx.fragment.app.DialogFragment;
|
import androidx.fragment.app.DialogFragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
@ -19,6 +20,8 @@ import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.database.subscription.SubscriptionEntity;
|
import org.schabi.newpipe.database.subscription.SubscriptionEntity;
|
||||||
import org.schabi.newpipe.error.ErrorUtil;
|
import org.schabi.newpipe.error.ErrorUtil;
|
||||||
import org.schabi.newpipe.local.subscription.SubscriptionManager;
|
import org.schabi.newpipe.local.subscription.SubscriptionManager;
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateSpec;
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateUtil;
|
||||||
import org.schabi.newpipe.util.ThemeHelper;
|
import org.schabi.newpipe.util.ThemeHelper;
|
||||||
import org.schabi.newpipe.util.image.CoilHelper;
|
import org.schabi.newpipe.util.image.CoilHelper;
|
||||||
|
|
||||||
|
@ -57,7 +60,7 @@ public class SelectChannelFragment extends DialogFragment {
|
||||||
private OnCancelListener onCancelListener = null;
|
private OnCancelListener onCancelListener = null;
|
||||||
|
|
||||||
private ProgressBar progressBar;
|
private ProgressBar progressBar;
|
||||||
private TextView emptyView;
|
private ComposeView emptyView;
|
||||||
private RecyclerView recyclerView;
|
private RecyclerView recyclerView;
|
||||||
|
|
||||||
private List<SubscriptionEntity> subscriptions = new Vector<>();
|
private List<SubscriptionEntity> subscriptions = new Vector<>();
|
||||||
|
@ -91,6 +94,9 @@ public class SelectChannelFragment extends DialogFragment {
|
||||||
|
|
||||||
progressBar = v.findViewById(R.id.progressBar);
|
progressBar = v.findViewById(R.id.progressBar);
|
||||||
emptyView = v.findViewById(R.id.empty_state_view);
|
emptyView = v.findViewById(R.id.empty_state_view);
|
||||||
|
|
||||||
|
EmptyStateUtil.setEmptyStateComposable(emptyView,
|
||||||
|
EmptyStateSpec.Companion.getNoSubscriptions());
|
||||||
progressBar.setVisibility(View.VISIBLE);
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
recyclerView.setVisibility(View.GONE);
|
recyclerView.setVisibility(View.GONE);
|
||||||
emptyView.setVisibility(View.GONE);
|
emptyView.setVisibility(View.GONE);
|
||||||
|
|
|
@ -11,6 +11,7 @@ import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.compose.ui.platform.ComposeView;
|
||||||
import androidx.fragment.app.DialogFragment;
|
import androidx.fragment.app.DialogFragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
@ -27,6 +28,8 @@ import org.schabi.newpipe.error.ErrorUtil;
|
||||||
import org.schabi.newpipe.error.UserAction;
|
import org.schabi.newpipe.error.UserAction;
|
||||||
import org.schabi.newpipe.local.playlist.LocalPlaylistManager;
|
import org.schabi.newpipe.local.playlist.LocalPlaylistManager;
|
||||||
import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
|
import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateSpec;
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateUtil;
|
||||||
import org.schabi.newpipe.util.image.CoilHelper;
|
import org.schabi.newpipe.util.image.CoilHelper;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -40,7 +43,7 @@ public class SelectPlaylistFragment extends DialogFragment {
|
||||||
private OnSelectedListener onSelectedListener = null;
|
private OnSelectedListener onSelectedListener = null;
|
||||||
|
|
||||||
private ProgressBar progressBar;
|
private ProgressBar progressBar;
|
||||||
private TextView emptyView;
|
private ComposeView emptyView;
|
||||||
private RecyclerView recyclerView;
|
private RecyclerView recyclerView;
|
||||||
private Disposable disposable = null;
|
private Disposable disposable = null;
|
||||||
|
|
||||||
|
@ -62,6 +65,8 @@ public class SelectPlaylistFragment extends DialogFragment {
|
||||||
recyclerView = v.findViewById(R.id.items_list);
|
recyclerView = v.findViewById(R.id.items_list);
|
||||||
emptyView = v.findViewById(R.id.empty_state_view);
|
emptyView = v.findViewById(R.id.empty_state_view);
|
||||||
|
|
||||||
|
EmptyStateUtil.setEmptyStateComposable(emptyView,
|
||||||
|
EmptyStateSpec.Companion.getNoBookmarkedPlaylist());
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
final SelectPlaylistAdapter playlistAdapter = new SelectPlaylistAdapter();
|
final SelectPlaylistAdapter playlistAdapter = new SelectPlaylistAdapter();
|
||||||
recyclerView.setAdapter(playlistAdapter);
|
recyclerView.setAdapter(playlistAdapter);
|
||||||
|
|
|
@ -11,6 +11,8 @@ import androidx.fragment.app.Fragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
|
||||||
import org.schabi.newpipe.databinding.SettingsPreferencesearchFragmentBinding;
|
import org.schabi.newpipe.databinding.SettingsPreferencesearchFragmentBinding;
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateSpec;
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateUtil;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -39,6 +41,9 @@ public class PreferenceSearchFragment extends Fragment {
|
||||||
binding = SettingsPreferencesearchFragmentBinding.inflate(inflater, container, false);
|
binding = SettingsPreferencesearchFragmentBinding.inflate(inflater, container, false);
|
||||||
|
|
||||||
binding.searchResults.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.searchResults.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
|
EmptyStateUtil.setEmptyStateComposable(
|
||||||
|
binding.emptyStateView,
|
||||||
|
EmptyStateSpec.Companion.getNoSearchMaxSizeResult());
|
||||||
|
|
||||||
adapter = new PreferenceSearchAdapter();
|
adapter = new PreferenceSearchAdapter();
|
||||||
adapter.setOnItemClickListener(this::onItemClicked);
|
adapter.setOnItemClickListener(this::onItemClicked);
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
package org.schabi.newpipe.ui.components.common
|
|
||||||
|
|
||||||
import android.content.res.Configuration
|
|
||||||
import androidx.annotation.StringRes
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.wrapContentSize
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Surface
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
import org.schabi.newpipe.R
|
|
||||||
import org.schabi.newpipe.ui.theme.AppTheme
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun NoItemsMessage(@StringRes message: Int) {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.wrapContentSize(Alignment.Center),
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
|
||||||
) {
|
|
||||||
Text(text = "(╯°-°)╯", fontSize = 35.sp)
|
|
||||||
Text(text = stringResource(id = message), fontSize = 24.sp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Preview(name = "Light mode", uiMode = Configuration.UI_MODE_NIGHT_NO)
|
|
||||||
@Preview(name = "Dark mode", uiMode = Configuration.UI_MODE_NIGHT_YES)
|
|
||||||
@Composable
|
|
||||||
private fun NoItemsMessagePreview() {
|
|
||||||
AppTheme {
|
|
||||||
Surface(color = MaterialTheme.colorScheme.background) {
|
|
||||||
NoItemsMessage(message = R.string.no_videos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -26,9 +26,10 @@ import org.schabi.newpipe.R
|
||||||
import org.schabi.newpipe.extractor.stream.StreamInfo
|
import org.schabi.newpipe.extractor.stream.StreamInfo
|
||||||
import org.schabi.newpipe.extractor.stream.StreamType
|
import org.schabi.newpipe.extractor.stream.StreamType
|
||||||
import org.schabi.newpipe.info_list.ItemViewMode
|
import org.schabi.newpipe.info_list.ItemViewMode
|
||||||
import org.schabi.newpipe.ui.components.common.NoItemsMessage
|
|
||||||
import org.schabi.newpipe.ui.components.items.ItemList
|
import org.schabi.newpipe.ui.components.items.ItemList
|
||||||
import org.schabi.newpipe.ui.components.items.stream.StreamInfoItem
|
import org.schabi.newpipe.ui.components.items.stream.StreamInfoItem
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateComposable
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateSpec
|
||||||
import org.schabi.newpipe.ui.theme.AppTheme
|
import org.schabi.newpipe.ui.theme.AppTheme
|
||||||
import org.schabi.newpipe.util.NO_SERVICE_ID
|
import org.schabi.newpipe.util.NO_SERVICE_ID
|
||||||
|
|
||||||
|
@ -41,9 +42,6 @@ fun RelatedItems(info: StreamInfo) {
|
||||||
mutableStateOf(sharedPreferences.getBoolean(key, false))
|
mutableStateOf(sharedPreferences.getBoolean(key, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.relatedItems.isEmpty()) {
|
|
||||||
NoItemsMessage(message = R.string.no_videos)
|
|
||||||
} else {
|
|
||||||
ItemList(
|
ItemList(
|
||||||
items = info.relatedItems,
|
items = info.relatedItems,
|
||||||
mode = ItemViewMode.LIST,
|
mode = ItemViewMode.LIST,
|
||||||
|
@ -75,10 +73,14 @@ fun RelatedItems(info: StreamInfo) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (info.relatedItems.isEmpty()) {
|
||||||
|
item {
|
||||||
|
EmptyStateComposable(EmptyStateSpec.NoVideos)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Preview(name = "Light mode", uiMode = Configuration.UI_MODE_NIGHT_NO)
|
@Preview(name = "Light mode", uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||||
@Preview(name = "Dark mode", uiMode = Configuration.UI_MODE_NIGHT_YES)
|
@Preview(name = "Dark mode", uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||||
|
|
|
@ -20,6 +20,7 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
|
import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
|
||||||
import androidx.compose.ui.res.pluralStringResource
|
import androidx.compose.ui.res.pluralStringResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.tooling.preview.datasource.LoremIpsum
|
import androidx.compose.ui.tooling.preview.datasource.LoremIpsum
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
@ -38,7 +39,8 @@ import org.schabi.newpipe.extractor.stream.Description
|
||||||
import org.schabi.newpipe.paging.CommentRepliesSource
|
import org.schabi.newpipe.paging.CommentRepliesSource
|
||||||
import org.schabi.newpipe.ui.components.common.LazyColumnThemedScrollbar
|
import org.schabi.newpipe.ui.components.common.LazyColumnThemedScrollbar
|
||||||
import org.schabi.newpipe.ui.components.common.LoadingIndicator
|
import org.schabi.newpipe.ui.components.common.LoadingIndicator
|
||||||
import org.schabi.newpipe.ui.components.common.NoItemsMessage
|
import org.schabi.newpipe.ui.emptystate.EmptyStateComposable
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateSpec
|
||||||
import org.schabi.newpipe.ui.theme.AppTheme
|
import org.schabi.newpipe.ui.theme.AppTheme
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
@ -130,13 +132,17 @@ private fun CommentRepliesDialog(
|
||||||
val refresh = comments.loadState.refresh
|
val refresh = comments.loadState.refresh
|
||||||
if (refresh is LoadState.Loading) {
|
if (refresh is LoadState.Loading) {
|
||||||
LoadingIndicator(modifier = Modifier.padding(top = 8.dp))
|
LoadingIndicator(modifier = Modifier.padding(top = 8.dp))
|
||||||
} else {
|
} else if (refresh is LoadState.Error) {
|
||||||
val message = if (refresh is LoadState.Error) {
|
// TODO use error panel instead
|
||||||
R.string.error_unable_to_load_comments
|
EmptyStateComposable(
|
||||||
} else {
|
EmptyStateSpec.DisabledComments.copy(
|
||||||
R.string.no_comments
|
descriptionText = {
|
||||||
|
stringResource(R.string.error_unable_to_load_comments)
|
||||||
}
|
}
|
||||||
NoItemsMessage(message)
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
EmptyStateComposable(EmptyStateSpec.NoComments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -13,6 +13,7 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
|
import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
|
||||||
import androidx.compose.ui.res.pluralStringResource
|
import androidx.compose.ui.res.pluralStringResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
@ -28,7 +29,8 @@ import org.schabi.newpipe.extractor.comments.CommentsInfoItem
|
||||||
import org.schabi.newpipe.extractor.stream.Description
|
import org.schabi.newpipe.extractor.stream.Description
|
||||||
import org.schabi.newpipe.ui.components.common.LazyColumnThemedScrollbar
|
import org.schabi.newpipe.ui.components.common.LazyColumnThemedScrollbar
|
||||||
import org.schabi.newpipe.ui.components.common.LoadingIndicator
|
import org.schabi.newpipe.ui.components.common.LoadingIndicator
|
||||||
import org.schabi.newpipe.ui.components.common.NoItemsMessage
|
import org.schabi.newpipe.ui.emptystate.EmptyStateComposable
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateSpec
|
||||||
import org.schabi.newpipe.ui.theme.AppTheme
|
import org.schabi.newpipe.ui.theme.AppTheme
|
||||||
import org.schabi.newpipe.viewmodels.CommentsViewModel
|
import org.schabi.newpipe.viewmodels.CommentsViewModel
|
||||||
import org.schabi.newpipe.viewmodels.util.Resource
|
import org.schabi.newpipe.viewmodels.util.Resource
|
||||||
|
@ -66,11 +68,11 @@ private fun CommentSection(
|
||||||
|
|
||||||
if (commentInfo.isCommentsDisabled) {
|
if (commentInfo.isCommentsDisabled) {
|
||||||
item {
|
item {
|
||||||
NoItemsMessage(R.string.comments_are_disabled)
|
EmptyStateComposable(EmptyStateSpec.DisabledComments)
|
||||||
}
|
}
|
||||||
} else if (count == 0) {
|
} else if (count == 0) {
|
||||||
item {
|
item {
|
||||||
NoItemsMessage(R.string.no_comments)
|
EmptyStateComposable(EmptyStateSpec.NoComments)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// do not show anything if the comment count is unknown
|
// do not show anything if the comment count is unknown
|
||||||
|
@ -95,7 +97,14 @@ private fun CommentSection(
|
||||||
|
|
||||||
is LoadState.Error -> {
|
is LoadState.Error -> {
|
||||||
item {
|
item {
|
||||||
NoItemsMessage(R.string.error_unable_to_load_comments)
|
// TODO use error panel instead
|
||||||
|
EmptyStateComposable(
|
||||||
|
EmptyStateSpec.DisabledComments.copy(
|
||||||
|
descriptionText = {
|
||||||
|
stringResource(R.string.error_unable_to_load_comments)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +119,14 @@ private fun CommentSection(
|
||||||
|
|
||||||
is Resource.Error -> {
|
is Resource.Error -> {
|
||||||
item {
|
item {
|
||||||
NoItemsMessage(R.string.error_unable_to_load_comments)
|
// TODO use error panel instead
|
||||||
|
EmptyStateComposable(
|
||||||
|
EmptyStateSpec.DisabledComments.copy(
|
||||||
|
descriptionText = {
|
||||||
|
stringResource(R.string.error_unable_to_load_comments)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
package org.schabi.newpipe.ui.emptystate
|
||||||
|
|
||||||
|
import android.graphics.Color
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.heightIn
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import org.schabi.newpipe.R
|
||||||
|
import org.schabi.newpipe.ui.theme.AppTheme
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun EmptyStateComposable(
|
||||||
|
spec: EmptyStateSpec,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) = EmptyStateComposable(
|
||||||
|
modifier = spec.modifier(modifier),
|
||||||
|
emojiText = spec.emojiText(),
|
||||||
|
descriptionText = spec.descriptionText(),
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun EmptyStateComposable(
|
||||||
|
emojiText: String,
|
||||||
|
descriptionText: String,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = modifier,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = emojiText,
|
||||||
|
style = MaterialTheme.typography.titleLarge,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(top = 6.dp)
|
||||||
|
.padding(horizontal = 16.dp),
|
||||||
|
text = descriptionText,
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview(showBackground = true, backgroundColor = Color.WHITE.toLong())
|
||||||
|
@Composable
|
||||||
|
fun EmptyStateComposableGenericErrorPreview() {
|
||||||
|
AppTheme {
|
||||||
|
EmptyStateComposable(EmptyStateSpec.GenericError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview(showBackground = true, backgroundColor = Color.WHITE.toLong())
|
||||||
|
@Composable
|
||||||
|
fun EmptyStateComposableNoCommentPreview() {
|
||||||
|
AppTheme {
|
||||||
|
EmptyStateComposable(EmptyStateSpec.NoComments)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class EmptyStateSpec(
|
||||||
|
val modifier: (Modifier) -> Modifier,
|
||||||
|
val emojiText: @Composable () -> String,
|
||||||
|
val descriptionText: @Composable () -> String,
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
val GenericError =
|
||||||
|
EmptyStateSpec(
|
||||||
|
modifier = {
|
||||||
|
it
|
||||||
|
.fillMaxWidth()
|
||||||
|
.heightIn(min = 128.dp)
|
||||||
|
},
|
||||||
|
emojiText = { "¯\\_(ツ)_/¯" },
|
||||||
|
descriptionText = { stringResource(id = R.string.empty_list_subtitle) },
|
||||||
|
)
|
||||||
|
|
||||||
|
val NoVideos =
|
||||||
|
EmptyStateSpec(
|
||||||
|
modifier = {
|
||||||
|
it
|
||||||
|
.fillMaxWidth()
|
||||||
|
.heightIn(min = 128.dp)
|
||||||
|
},
|
||||||
|
emojiText = { "(╯°-°)╯" },
|
||||||
|
descriptionText = { stringResource(id = R.string.no_videos) },
|
||||||
|
)
|
||||||
|
|
||||||
|
val NoComments =
|
||||||
|
EmptyStateSpec(
|
||||||
|
modifier = {
|
||||||
|
it
|
||||||
|
.fillMaxWidth()
|
||||||
|
.heightIn(min = 128.dp)
|
||||||
|
},
|
||||||
|
emojiText = { "¯\\_(╹x╹)_/¯" },
|
||||||
|
descriptionText = { stringResource(id = R.string.no_comments) },
|
||||||
|
)
|
||||||
|
|
||||||
|
val DisabledComments =
|
||||||
|
NoComments.copy(
|
||||||
|
descriptionText = { stringResource(id = R.string.comments_are_disabled) },
|
||||||
|
)
|
||||||
|
|
||||||
|
val NoSearchResult =
|
||||||
|
NoComments.copy(
|
||||||
|
modifier = { it },
|
||||||
|
emojiText = { "╰(°●°╰)" },
|
||||||
|
descriptionText = { stringResource(id = R.string.search_no_results) }
|
||||||
|
)
|
||||||
|
|
||||||
|
val NoSearchMaxSizeResult =
|
||||||
|
NoSearchResult.copy(
|
||||||
|
modifier = { it.fillMaxSize() },
|
||||||
|
)
|
||||||
|
|
||||||
|
val ContentNotSupported =
|
||||||
|
NoComments.copy(
|
||||||
|
modifier = { it.padding(top = 90.dp) },
|
||||||
|
emojiText = { "(︶︹︺)" },
|
||||||
|
descriptionText = { stringResource(id = R.string.content_not_supported) },
|
||||||
|
)
|
||||||
|
|
||||||
|
val NoBookmarkedPlaylist =
|
||||||
|
EmptyStateSpec(
|
||||||
|
modifier = { it },
|
||||||
|
emojiText = { "(╥﹏╥)" },
|
||||||
|
descriptionText = { stringResource(id = R.string.no_playlist_bookmarked_yet) },
|
||||||
|
)
|
||||||
|
|
||||||
|
val NoSubscriptionsHint =
|
||||||
|
EmptyStateSpec(
|
||||||
|
modifier = { it },
|
||||||
|
emojiText = { "(꩜ᯅ꩜)" },
|
||||||
|
descriptionText = { stringResource(id = R.string.import_subscriptions_hint) },
|
||||||
|
)
|
||||||
|
|
||||||
|
val NoSubscriptions =
|
||||||
|
NoSubscriptionsHint.copy(
|
||||||
|
descriptionText = { stringResource(id = R.string.no_channel_subscribed_yet) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
@file:JvmName("EmptyStateUtil")
|
||||||
|
|
||||||
|
package org.schabi.newpipe.ui.emptystate
|
||||||
|
|
||||||
|
import androidx.compose.material3.LocalContentColor
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.contentColorFor
|
||||||
|
import androidx.compose.runtime.CompositionLocalProvider
|
||||||
|
import androidx.compose.ui.platform.ComposeView
|
||||||
|
import androidx.compose.ui.platform.ViewCompositionStrategy
|
||||||
|
import org.schabi.newpipe.ui.theme.AppTheme
|
||||||
|
|
||||||
|
@JvmOverloads
|
||||||
|
fun ComposeView.setEmptyStateComposable(
|
||||||
|
spec: EmptyStateSpec = EmptyStateSpec.GenericError,
|
||||||
|
strategy: ViewCompositionStrategy = ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed,
|
||||||
|
) = apply {
|
||||||
|
setViewCompositionStrategy(strategy)
|
||||||
|
setContent {
|
||||||
|
AppTheme {
|
||||||
|
CompositionLocalProvider(
|
||||||
|
LocalContentColor provides contentColorFor(MaterialTheme.colorScheme.background)
|
||||||
|
) {
|
||||||
|
EmptyStateComposable(
|
||||||
|
spec = spec
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ import androidx.activity.result.ActivityResultLauncher;
|
||||||
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult;
|
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.compose.ui.platform.ComposeView;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.preference.PreferenceManager;
|
import androidx.preference.PreferenceManager;
|
||||||
import androidx.recyclerview.widget.GridLayoutManager;
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
@ -34,6 +35,7 @@ import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.settings.NewPipeSettings;
|
import org.schabi.newpipe.settings.NewPipeSettings;
|
||||||
import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard;
|
import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard;
|
||||||
import org.schabi.newpipe.streams.io.StoredFileHelper;
|
import org.schabi.newpipe.streams.io.StoredFileHelper;
|
||||||
|
import org.schabi.newpipe.ui.emptystate.EmptyStateUtil;
|
||||||
import org.schabi.newpipe.util.FilePickerActivityHelper;
|
import org.schabi.newpipe.util.FilePickerActivityHelper;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -108,7 +110,8 @@ public class MissionsFragment extends Fragment {
|
||||||
mContext.bindService(new Intent(mContext, DownloadManagerService.class), mConnection, Context.BIND_AUTO_CREATE);
|
mContext.bindService(new Intent(mContext, DownloadManagerService.class), mConnection, Context.BIND_AUTO_CREATE);
|
||||||
|
|
||||||
// Views
|
// Views
|
||||||
mEmpty = v.findViewById(R.id.list_empty_view);
|
mEmpty = v.findViewById(R.id.empty_state_view);
|
||||||
|
EmptyStateUtil.setEmptyStateComposable((ComposeView) mEmpty);
|
||||||
mList = v.findViewById(R.id.mission_recycler);
|
mList = v.findViewById(R.id.mission_recycler);
|
||||||
|
|
||||||
// Init layouts managers
|
// Init layouts managers
|
||||||
|
|
|
@ -24,15 +24,15 @@
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<include
|
<androidx.compose.ui.platform.ComposeView
|
||||||
android:id="@+id/empty_state_view"
|
android:id="@+id/empty_state_view"
|
||||||
layout="@layout/list_empty_view"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:layout_marginTop="50dp"
|
android:layout_marginTop="50dp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible"
|
||||||
|
/>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -168,37 +168,14 @@
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.compose.ui.platform.ComposeView
|
||||||
android:id="@+id/empty_state_view"
|
android:id="@+id/empty_state_view"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingTop="90dp"
|
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible">
|
tools:visibility="visible"
|
||||||
|
/>
|
||||||
<org.schabi.newpipe.views.NewPipeTextView
|
|
||||||
android:id="@+id/channel_kaomoji"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_marginBottom="10dp"
|
|
||||||
android:fontFamily="monospace"
|
|
||||||
android:text="(︶︹︺)"
|
|
||||||
android:textSize="35sp"
|
|
||||||
tools:ignore="HardcodedText" />
|
|
||||||
|
|
||||||
<org.schabi.newpipe.views.NewPipeTextView
|
|
||||||
android:id="@+id/error_content_not_supported"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="20dp"
|
|
||||||
android:text="@string/content_not_supported"
|
|
||||||
android:textSize="15sp"
|
|
||||||
android:visibility="gone" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<!--ERROR PANEL-->
|
<!--ERROR PANEL-->
|
||||||
<include
|
<include
|
||||||
|
|
|
@ -20,15 +20,15 @@
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<include
|
<androidx.compose.ui.platform.ComposeView
|
||||||
android:id="@+id/empty_state_view"
|
android:id="@+id/empty_state_view"
|
||||||
layout="@layout/list_empty_view"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible"
|
||||||
|
/>
|
||||||
|
|
||||||
<!--ERROR PANEL-->
|
<!--ERROR PANEL-->
|
||||||
<include
|
<include
|
||||||
|
|
|
@ -20,36 +20,14 @@
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.compose.ui.platform.ComposeView
|
||||||
android:id="@+id/empty_state_view"
|
android:id="@+id/empty_state_view"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:orientation="vertical"
|
|
||||||
android:paddingTop="90dp"
|
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible">
|
tools:visibility="visible"
|
||||||
|
/>
|
||||||
<org.schabi.newpipe.views.NewPipeTextView
|
|
||||||
android:id="@+id/channel_kaomoji"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_marginBottom="10dp"
|
|
||||||
android:fontFamily="monospace"
|
|
||||||
android:text="(╯°-°)╯"
|
|
||||||
android:textSize="35sp"
|
|
||||||
tools:ignore="HardcodedText,UnusedAttribute" />
|
|
||||||
|
|
||||||
<org.schabi.newpipe.views.NewPipeTextView
|
|
||||||
android:id="@+id/channel_no_videos"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:text="@string/empty_view_no_videos"
|
|
||||||
android:textSize="24sp" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<!--ERROR PANEL-->
|
<!--ERROR PANEL-->
|
||||||
<include
|
<include
|
||||||
|
|
|
@ -7,12 +7,13 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<include
|
<androidx.compose.ui.platform.ComposeView
|
||||||
android:id="@+id/empty_state_view"
|
android:id="@+id/empty_state_view"
|
||||||
layout="@layout/list_empty_view"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
android:layout_marginTop="90dp" />
|
android:layout_marginTop="90dp"
|
||||||
|
/>
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
|
@ -140,15 +140,15 @@
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<include
|
<androidx.compose.ui.platform.ComposeView
|
||||||
android:id="@+id/empty_state_view"
|
android:id="@+id/empty_state_view"
|
||||||
layout="@layout/list_empty_view"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:layout_marginTop="50dp"
|
android:layout_marginTop="50dp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible"
|
||||||
|
/>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -52,33 +52,14 @@
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.compose.ui.platform.ComposeView
|
||||||
android:id="@+id/empty_state_view"
|
android:id="@+id/empty_state_view"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:orientation="vertical"
|
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible">
|
tools:visibility="visible"
|
||||||
|
/>
|
||||||
<org.schabi.newpipe.views.NewPipeTextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_marginBottom="10dp"
|
|
||||||
android:fontFamily="monospace"
|
|
||||||
android:text="╰(°●°╰)"
|
|
||||||
android:textSize="35sp"
|
|
||||||
tools:ignore="HardcodedText,UnusedAttribute" />
|
|
||||||
|
|
||||||
<org.schabi.newpipe.views.NewPipeTextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:text="@string/search_no_results"
|
|
||||||
android:textSize="24sp" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/suggestions_panel"
|
android:id="@+id/suggestions_panel"
|
||||||
|
|
|
@ -24,16 +24,16 @@
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<include
|
<androidx.compose.ui.platform.ComposeView
|
||||||
android:id="@+id/empty_state_view"
|
android:id="@+id/empty_state_view"
|
||||||
layout="@layout/list_empty_view"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/items_list"
|
android:layout_below="@id/items_list"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:layout_marginTop="50dp"
|
android:layout_marginTop="50dp"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible"
|
||||||
|
/>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center"
|
|
||||||
android:minHeight="128dp"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<org.schabi.newpipe.views.NewPipeTextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="¯\\_(ツ)_/¯"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
|
||||||
tools:ignore="HardcodedText" />
|
|
||||||
|
|
||||||
<org.schabi.newpipe.views.NewPipeTextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_marginTop="6dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingHorizontal="16dp"
|
|
||||||
android:text="@string/empty_list_subtitle" />
|
|
||||||
</LinearLayout>
|
|
|
@ -1,25 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.compose.ui.platform.ComposeView
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:gravity="center"
|
|
||||||
android:minHeight="128dp"
|
android:minHeight="128dp"
|
||||||
android:orientation="vertical">
|
xmlns:android="http://schemas.android.com/apk/res/android" />
|
||||||
|
|
||||||
<org.schabi.newpipe.views.NewPipeTextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="¯\\_(ツ)_/¯"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
|
||||||
tools:ignore="HardcodedText" />
|
|
||||||
|
|
||||||
<org.schabi.newpipe.views.NewPipeTextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_marginTop="6dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:paddingHorizontal="16dp"
|
|
||||||
android:text="@string/import_subscriptions_hint" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
|
@ -3,10 +3,11 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<include
|
<androidx.compose.ui.platform.ComposeView
|
||||||
android:id="@+id/list_empty_view"
|
android:id="@+id/empty_state_view"
|
||||||
layout="@layout/list_empty_view"
|
android:layout_width="match_parent"
|
||||||
android:visibility="gone" />
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="128dp" />
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/mission_recycler"
|
android:id="@+id/mission_recycler"
|
||||||
|
|
|
@ -24,14 +24,11 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
tools:listitem="@layout/select_channel_item" />
|
tools:listitem="@layout/select_channel_item" />
|
||||||
|
|
||||||
|
<androidx.compose.ui.platform.ComposeView
|
||||||
<org.schabi.newpipe.views.NewPipeTextView
|
|
||||||
android:id="@+id/empty_state_view"
|
android:id="@+id/empty_state_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp" />
|
||||||
android:text="@string/no_channel_subscribed_yet"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceListItem" />
|
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progressBar"
|
android:id="@+id/progressBar"
|
||||||
|
|
|
@ -26,14 +26,11 @@
|
||||||
|
|
||||||
</androidx.recyclerview.widget.RecyclerView>
|
</androidx.recyclerview.widget.RecyclerView>
|
||||||
|
|
||||||
|
<androidx.compose.ui.platform.ComposeView
|
||||||
<org.schabi.newpipe.views.NewPipeTextView
|
|
||||||
android:id="@+id/empty_state_view"
|
android:id="@+id/empty_state_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp" />
|
||||||
android:text="@string/no_playlist_bookmarked_yet"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceListItem" />
|
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progressBar"
|
android:id="@+id/progressBar"
|
||||||
|
|
|
@ -12,33 +12,14 @@
|
||||||
android:layout_height="4dp"
|
android:layout_height="4dp"
|
||||||
android:background="?attr/toolbar_shadow" />
|
android:background="?attr/toolbar_shadow" />
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.compose.ui.platform.ComposeView
|
||||||
android:id="@+id/empty_state_view"
|
android:id="@+id/empty_state_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:visibility="gone">
|
tools:visibility="gone"
|
||||||
|
/>
|
||||||
<org.schabi.newpipe.views.NewPipeTextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_marginBottom="10dp"
|
|
||||||
android:fontFamily="monospace"
|
|
||||||
android:text="╰(°●°╰)"
|
|
||||||
android:textSize="35sp"
|
|
||||||
tools:ignore="HardcodedText,UnusedAttribute" />
|
|
||||||
|
|
||||||
<org.schabi.newpipe.views.NewPipeTextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:text="@string/search_no_results"
|
|
||||||
android:textSize="24sp" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/searchResults"
|
android:id="@+id/searchResults"
|
||||||
|
|
12
build.gradle
12
build.gradle
|
@ -1,20 +1,16 @@
|
||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext {
|
|
||||||
kotlin_version = '2.0.21'
|
|
||||||
about_libs = '11.2.3'
|
|
||||||
}
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
maven { url "https://plugins.gradle.org/m2/" }
|
maven { url "https://plugins.gradle.org/m2/" }
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:8.7.2'
|
classpath libs.android.tools.build.gradle
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath libs.kotlin.gradle.plugin
|
||||||
classpath 'com.google.dagger:hilt-android-gradle-plugin:2.51.1'
|
classpath libs.hilt.android.gradle.plugin
|
||||||
classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:$about_libs"
|
classpath libs.aboutlibraries.plugin
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
[versions]
|
||||||
|
aboutLibraries = "11.2.3"
|
||||||
|
acraCore = "5.11.3"
|
||||||
|
androidState = "1.4.1"
|
||||||
|
androidx-junit = "1.1.5"
|
||||||
|
appcompat = "1.6.1"
|
||||||
|
assertjCore = "3.24.2"
|
||||||
|
auto-service = "1.1.1"
|
||||||
|
bridge = "2.0.2"
|
||||||
|
cardview = "1.0.0"
|
||||||
|
checkstyle = "10.12.1"
|
||||||
|
coil = "3.0.3"
|
||||||
|
constraintlayout = "2.1.4"
|
||||||
|
core-ktx = "1.12.0"
|
||||||
|
desugar-jdk-libs-nio = "2.0.4"
|
||||||
|
documentFile = "1.0.1"
|
||||||
|
exoplayer = "2.18.7"
|
||||||
|
fragment-compose = "1.8.2"
|
||||||
|
gradle = "8.7.1"
|
||||||
|
groupie = "2.10.1"
|
||||||
|
hilt = "2.51.1"
|
||||||
|
jetpack-compose = "2024.10.01"
|
||||||
|
jsoup = "1.17.2"
|
||||||
|
junit = "4.13.2"
|
||||||
|
kotlin = "2.0.21"
|
||||||
|
kotlinxCoroutinesRx3 = "1.8.1"
|
||||||
|
ktlint = "0.45.2"
|
||||||
|
lazycolumnscrollbar = "2.2.0"
|
||||||
|
leakcanary = "2.12"
|
||||||
|
lifecycle = "2.6.2"
|
||||||
|
localbroadcastmanager = "1.1.0"
|
||||||
|
markwon = "4.6.2"
|
||||||
|
material = "1.11.0"
|
||||||
|
media = "1.7.0"
|
||||||
|
mockitoCore = "5.6.0"
|
||||||
|
navigationCompose = "2.8.3"
|
||||||
|
okhttp = "4.12.0"
|
||||||
|
pagingCompose = "3.3.2"
|
||||||
|
preference = "1.2.1"
|
||||||
|
prettytime = "5.0.8.Final"
|
||||||
|
processPhoenix = "2.1.2"
|
||||||
|
recyclerview = "1.3.2"
|
||||||
|
room = "2.6.1"
|
||||||
|
runner = "1.5.2"
|
||||||
|
rxandroid = "3.0.2"
|
||||||
|
rxbinding = "4.0.0"
|
||||||
|
rxjava = "3.1.8"
|
||||||
|
sonarqube = "4.0.0.2929"
|
||||||
|
stetho = "1.6.0"
|
||||||
|
swiperefreshlayout = "1.1.0"
|
||||||
|
# You can use a local version by uncommenting a few lines in settings.gradle
|
||||||
|
# Or you can use a commit you pushed to GitHub by just replacing TeamNewPipe with your GitHub
|
||||||
|
# name and the commit hash with the commit hash of the (pushed) commit you want to test
|
||||||
|
# This works thanks to JitPack: https://jitpack.io/
|
||||||
|
teamnewpipe-filepicker = "5.0.0"
|
||||||
|
teamnewpipe-nanojson = "1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751"
|
||||||
|
teamnewpipe-newpipe-extractor = "d3d5f2b3f03a5f2b479b9f6fdf1c2555cbb9de0e"
|
||||||
|
viewpager2 = "1.1.0-beta02"
|
||||||
|
work = "2.8.1"
|
||||||
|
|
||||||
|
[plugins]
|
||||||
|
aboutlibraries = { id = "com.mikepenz.aboutlibraries.plugin" }
|
||||||
|
android-application = { id = "com.android.application" }
|
||||||
|
checkstyle = { id = "checkstyle" }
|
||||||
|
hilt = { id = "com.google.dagger.hilt.android" }
|
||||||
|
kotlin-android = { id = "kotlin-android" }
|
||||||
|
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
||||||
|
kotlin-kapt = { id = "kotlin-kapt" }
|
||||||
|
kotlin-parcelize = { id = "kotlin-parcelize" }
|
||||||
|
sonarqube = { id = "org.sonarqube", version.ref = "sonarqube" }
|
||||||
|
|
||||||
|
[libraries]
|
||||||
|
aboutlibraries-compose-m3 = { group = "com.mikepenz", name = "aboutlibraries-compose-m3", version.ref = "aboutLibraries" }
|
||||||
|
aboutlibraries-plugin = { group = "com.mikepenz.aboutlibraries.plugin", name = "aboutlibraries-plugin", version.ref = "aboutLibraries" }
|
||||||
|
acra-core = { group = "ch.acra", name = "acra-core", version.ref = "acraCore" }
|
||||||
|
android-state = { group = "com.evernote", name = "android-state", version.ref = "androidState" }
|
||||||
|
android-state-processor = { group = "com.evernote", name = "android-state-processor", version.ref = "androidState" }
|
||||||
|
android-tools-build-gradle = { group = "com.android.tools.build", name = "gradle", version.ref = "gradle" }
|
||||||
|
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose" }
|
||||||
|
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
|
||||||
|
androidx-cardview = { group = "androidx.cardview", name = "cardview", version.ref = "cardview" }
|
||||||
|
androidx-compose-adaptive = { group = "androidx.compose.material3.adaptive", name = "adaptive" }
|
||||||
|
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "jetpack-compose" }
|
||||||
|
androidx-compose-material-icons-extended = { group = "androidx.compose.material", name = "material-icons-extended" }
|
||||||
|
androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" }
|
||||||
|
androidx-compose-ui-text = { group = "androidx.compose.ui", name = "ui-text" }
|
||||||
|
androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
|
||||||
|
androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
|
||||||
|
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
|
||||||
|
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
|
||||||
|
androidx-documentfile = { group = "androidx.documentfile", name = "documentfile", version.ref = "documentFile" }
|
||||||
|
androidx-fragment-compose = { group = "androidx.fragment", name = "fragment-compose", version.ref = "fragment-compose" }
|
||||||
|
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-junit" }
|
||||||
|
androidx-lifecycle-livedata = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycle" }
|
||||||
|
androidx-lifecycle-viewmodel = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycle" }
|
||||||
|
androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose" }
|
||||||
|
androidx-localbroadcastmanager = { group = "androidx.localbroadcastmanager", name = "localbroadcastmanager", version.ref = "localbroadcastmanager" }
|
||||||
|
androidx-material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
||||||
|
androidx-media = { group = "androidx.media", name = "media", version.ref = "media" }
|
||||||
|
androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" }
|
||||||
|
androidx-paging-compose = { group = "androidx.paging", name = "paging-compose", version.ref = "pagingCompose" }
|
||||||
|
androidx-preference = { group = "androidx.preference", name = "preference", version.ref = "preference" }
|
||||||
|
androidx-recyclerview = { group = "androidx.recyclerview", name = "recyclerview", version.ref = "recyclerview" }
|
||||||
|
androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
|
||||||
|
androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
|
||||||
|
androidx-room-rxjava3 = { group = "androidx.room", name = "room-rxjava3", version.ref = "room" }
|
||||||
|
androidx-room-testing = { group = "androidx.room", name = "room-testing", version.ref = "room" }
|
||||||
|
androidx-runner = { group = "androidx.test", name = "runner", version.ref = "runner" }
|
||||||
|
androidx-swiperefreshlayout = { group = "androidx.swiperefreshlayout", name = "swiperefreshlayout", version.ref = "swiperefreshlayout" }
|
||||||
|
androidx-viewpager2 = { group = "androidx.viewpager2", name = "viewpager2", version.ref = "viewpager2" }
|
||||||
|
androidx-work-runtime = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "work" }
|
||||||
|
androidx-work-rxjava3 = { group = "androidx.work", name = "work-rxjava3", version.ref = "work" }
|
||||||
|
assertj-core = { group = "org.assertj", name = "assertj-core", version.ref = "assertjCore" }
|
||||||
|
auto-service = { group = "com.google.auto.service", name = "auto-service-annotations", version.ref = "auto-service" }
|
||||||
|
auto-service-kapt = { group = "com.google.auto.service", name = "auto-service", version.ref = "auto-service" }
|
||||||
|
coil-compose = { group = "io.coil-kt.coil3", name = 'coil-compose', version.ref = "coil" }
|
||||||
|
desugar-jdk-libs-nio = { group = "com.android.tools", name = "desugar_jdk_libs_nio", version.ref = "desugar-jdk-libs-nio" }
|
||||||
|
exoplayer-core = { group = "com.google.android.exoplayer", name = "exoplayer-core", version.ref = "exoplayer" }
|
||||||
|
exoplayer-dash = { module = "com.google.android.exoplayer:exoplayer-dash", version.ref = "exoplayer" }
|
||||||
|
exoplayer-database = { group = "com.google.android.exoplayer", name = "exoplayer-database", version.ref = "exoplayer" }
|
||||||
|
exoplayer-datasource = { group = "com.google.android.exoplayer", name = "exoplayer-datasource", version.ref = "exoplayer" }
|
||||||
|
exoplayer-hls = { group = "com.google.android.exoplayer", name = "exoplayer-hls", version.ref = "exoplayer" }
|
||||||
|
exoplayer-smoothstreaming = { group = "com.google.android.exoplayer", name = "exoplayer-smoothstreaming", version.ref = "exoplayer" }
|
||||||
|
exoplayer-ui = { group = "com.google.android.exoplayer", name = "exoplayer-ui", version.ref = "exoplayer" }
|
||||||
|
extension-mediasession = { group = "com.google.android.exoplayer", name = "extension-mediasession", version.ref = "exoplayer" }
|
||||||
|
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
|
||||||
|
hilt-android-gradle-plugin = { group = "com.google.dagger", name = "hilt-android-gradle-plugin", version.ref = "hilt" }
|
||||||
|
hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" }
|
||||||
|
jsoup = { group = "org.jsoup", name = "jsoup", version.ref = "jsoup" }
|
||||||
|
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||||
|
kotlin-gradle-plugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }
|
||||||
|
kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlin" }
|
||||||
|
kotlinx-coroutines-rx3 = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-rx3", version.ref = "kotlinxCoroutinesRx3" }
|
||||||
|
lazycolumnscrollbar = { group = "com.github.nanihadesuka", name = "LazyColumnScrollbar", version.ref = "lazycolumnscrollbar" }
|
||||||
|
leakcanary-android-core = { module = "com.squareup.leakcanary:leakcanary-android-core", version.ref = "leakcanary" }
|
||||||
|
leakcanary-object-watcher = { group = "com.squareup.leakcanary", name = "leakcanary-object-watcher-android", version.ref = "leakcanary" }
|
||||||
|
leakcanary-plumber-android = { group = "com.squareup.leakcanary", name = "plumber-android", version.ref = "leakcanary" }
|
||||||
|
lisawray-groupie = { group = "com.github.lisawray.groupie", name = "groupie", version.ref = "groupie" }
|
||||||
|
lisawray-groupie-viewbinding = { group = "com.github.lisawray.groupie", name = "groupie-viewbinding", version.ref = "groupie" }
|
||||||
|
livefront-bridge = { group = "com.github.livefront", name = "bridge", version.ref = "bridge" }
|
||||||
|
markwon-core = { group = "io.noties.markwon", name = "core", version.ref = "markwon" }
|
||||||
|
markwon-linkify = { group = "io.noties.markwon", name = "linkify", version.ref = "markwon" }
|
||||||
|
mockito-core = { group = "org.mockito", name = "mockito-core", version.ref = "mockitoCore" }
|
||||||
|
okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
|
||||||
|
prettytime = { group = "org.ocpsoft.prettytime", name = "prettytime", version.ref = "prettytime" }
|
||||||
|
process-phoenix = { group = "com.jakewharton", name = "process-phoenix", version.ref = "processPhoenix" }
|
||||||
|
rxbinding4-rxbinding = { group = "com.jakewharton.rxbinding4", name = "rxbinding", version.ref = "rxbinding" }
|
||||||
|
rxjava3-rxandroid = { group = "io.reactivex.rxjava3", name = "rxandroid", version.ref = "rxandroid" }
|
||||||
|
rxjava3-rxjava = { group = "io.reactivex.rxjava3", name = "rxjava", version.ref = "rxjava" }
|
||||||
|
stetho = { group = "com.facebook.stetho", name = "stetho", version.ref = "stetho" }
|
||||||
|
stetho-okhttp3 = { group = "com.facebook.stetho", name = "stetho-okhttp3", version.ref = "stetho" }
|
||||||
|
teamnewpipe-nanojson = { group = "com.github.TeamNewPipe", name = "nanojson", version.ref = "teamnewpipe-nanojson" }
|
||||||
|
teamnewpipe-newpipe-extractor = { group = "com.github.TeamNewPipe", name = "NewPipeExtractor", version.ref = "teamnewpipe-newpipe-extractor" }
|
||||||
|
teamnewpipe-nononsense-filepicker = { group = "com.github.TeamNewPipe", name = "NoNonsense-FilePicker", version.ref = "teamnewpipe-filepicker" }
|
||||||
|
tools-checkstyle = { group = "com.puppycrawl.tools", name = "checkstyle", version.ref = "checkstyle" }
|
||||||
|
tools-ktlint = { group = "com.pinterest", name = "ktlint", version.ref = "ktlint" }
|
Loading…
Reference in New Issue