mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-30 23:03:00 +00:00 
			
		
		
		
	Merge branch 'refactor' into pr11282
This commit is contained in:
		
							
								
								
									
										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() { | ||||||
|   | |||||||
							
								
								
									
										48
									
								
								app/check-dependencies.gradle
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								app/check-dependencies.gradle
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||||
|   | |||||||
							
								
								
									
										156
									
								
								gradle/libs.versions.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								gradle/libs.versions.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -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" } | ||||||
		Reference in New Issue
	
	Block a user
	 Stypox
					Stypox