mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2024-12-24 00:50:32 +00:00
Update replies fragment to use the comment composable as well
This commit is contained in:
parent
1620668966
commit
341cc37ce7
@ -106,7 +106,7 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
composeOptions {
|
composeOptions {
|
||||||
kotlinCompilerExtensionVersion = "1.5.13"
|
kotlinCompilerExtensionVersion = "1.5.14"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,11 +289,15 @@ dependencies {
|
|||||||
implementation "org.ocpsoft.prettytime:prettytime:5.0.8.Final"
|
implementation "org.ocpsoft.prettytime:prettytime:5.0.8.Final"
|
||||||
|
|
||||||
// Jetpack Compose
|
// Jetpack Compose
|
||||||
implementation(platform('androidx.compose:compose-bom:2024.05.00'))
|
implementation(platform('androidx.compose:compose-bom:2024.06.00'))
|
||||||
implementation 'androidx.compose.material3:material3'
|
implementation 'androidx.compose.material3:material3'
|
||||||
implementation 'androidx.activity:activity-compose'
|
implementation 'androidx.activity:activity-compose'
|
||||||
implementation 'androidx.compose.ui:ui-tooling-preview'
|
implementation 'androidx.compose.ui:ui-tooling-preview'
|
||||||
|
|
||||||
|
// Paging
|
||||||
|
implementation 'androidx.paging:paging-rxjava3:3.3.0'
|
||||||
|
implementation 'androidx.paging:paging-compose:3.3.0'
|
||||||
|
|
||||||
/** Debugging **/
|
/** Debugging **/
|
||||||
// Memory leak detection
|
// Memory leak detection
|
||||||
debugImplementation "com.squareup.leakcanary:leakcanary-object-watcher-android:${leakCanaryVersion}"
|
debugImplementation "com.squareup.leakcanary:leakcanary-object-watcher-android:${leakCanaryVersion}"
|
||||||
|
@ -66,7 +66,6 @@ import org.schabi.newpipe.databinding.ToolbarLayoutBinding;
|
|||||||
import org.schabi.newpipe.error.ErrorUtil;
|
import org.schabi.newpipe.error.ErrorUtil;
|
||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
import org.schabi.newpipe.extractor.StreamingService;
|
import org.schabi.newpipe.extractor.StreamingService;
|
||||||
import org.schabi.newpipe.extractor.comments.CommentsInfoItem;
|
|
||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance;
|
import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance;
|
||||||
import org.schabi.newpipe.fragments.BackPressable;
|
import org.schabi.newpipe.fragments.BackPressable;
|
||||||
@ -868,10 +867,9 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// the root comment is the comment for which the user opened the replies page
|
// the root comment is the comment for which the user opened the replies page
|
||||||
@Nullable final CommentRepliesFragment repliesFragment =
|
final var repliesFragment = (CommentRepliesFragment)
|
||||||
(CommentRepliesFragment) fm.findFragmentByTag(CommentRepliesFragment.TAG);
|
fm.findFragmentByTag(CommentRepliesFragment.TAG);
|
||||||
@Nullable final CommentsInfoItem rootComment =
|
final var rootComment = repliesFragment == null ? null : repliesFragment.getComment();
|
||||||
repliesFragment == null ? null : repliesFragment.getCommentsInfoItem();
|
|
||||||
|
|
||||||
// sometimes this function pops the backstack, other times it's handled by the system
|
// sometimes this function pops the backstack, other times it's handled by the system
|
||||||
if (popBackStack) {
|
if (popBackStack) {
|
||||||
|
@ -73,6 +73,7 @@ fun Comment(comment: CommentsInfoItem) {
|
|||||||
color = MaterialTheme.colorScheme.secondary
|
color = MaterialTheme.colorScheme.secondary
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO: Handle HTML and Markdown formats.
|
||||||
Text(
|
Text(
|
||||||
text = comment.commentText.content,
|
text = comment.commentText.content,
|
||||||
// If the comment is expanded, we display all its content
|
// If the comment is expanded, we display all its content
|
||||||
@ -110,16 +111,33 @@ fun Comment(comment: CommentsInfoItem) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun CommentsInfoItem(
|
||||||
|
serviceId: Int = 1,
|
||||||
|
url: String = "",
|
||||||
|
name: String = "",
|
||||||
|
commentText: Description,
|
||||||
|
uploaderName: String,
|
||||||
|
textualUploadDate: String = "5 months ago",
|
||||||
|
likeCount: Int = 100,
|
||||||
|
isHeartedByUploader: Boolean = true,
|
||||||
|
isPinned: Boolean = true,
|
||||||
|
) = CommentsInfoItem(serviceId, url, name).apply {
|
||||||
|
this.commentText = commentText
|
||||||
|
this.uploaderName = uploaderName
|
||||||
|
this.textualUploadDate = textualUploadDate
|
||||||
|
this.likeCount = likeCount
|
||||||
|
this.isHeartedByUploader = isHeartedByUploader
|
||||||
|
this.isPinned = isPinned
|
||||||
|
}
|
||||||
|
|
||||||
@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)
|
||||||
@Composable
|
@Composable
|
||||||
fun CommentPreview() {
|
private fun CommentPreview() {
|
||||||
val comment = CommentsInfoItem(1, "", "")
|
val comment = CommentsInfoItem(
|
||||||
comment.commentText = Description("Hello world!\n\nThis line should be hidden by default.", Description.PLAIN_TEXT)
|
commentText = Description("Hello world!\n\nThis line should be hidden by default.", Description.PLAIN_TEXT),
|
||||||
comment.uploaderName = "Test"
|
uploaderName = "Test",
|
||||||
comment.likeCount = 100
|
)
|
||||||
comment.isHeartedByUploader = true
|
|
||||||
comment.isPinned = true
|
|
||||||
|
|
||||||
AppTheme {
|
AppTheme {
|
||||||
Comment(comment)
|
Comment(comment)
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
package org.schabi.newpipe.fragments.list.comments
|
||||||
|
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.paging.PagingData
|
||||||
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
import org.schabi.newpipe.extractor.comments.CommentsInfoItem
|
||||||
|
import org.schabi.newpipe.extractor.stream.Description
|
||||||
|
import org.schabi.newpipe.ui.theme.AppTheme
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun CommentReplies(
|
||||||
|
comment: CommentsInfoItem,
|
||||||
|
flow: Flow<PagingData<CommentsInfoItem>>,
|
||||||
|
disposables: CompositeDisposable
|
||||||
|
) {
|
||||||
|
val replies = flow.collectAsLazyPagingItems()
|
||||||
|
|
||||||
|
Column {
|
||||||
|
CommentRepliesHeader(comment = comment, disposables = disposables)
|
||||||
|
HorizontalDivider(thickness = 1.dp)
|
||||||
|
LazyColumn {
|
||||||
|
items(replies.itemCount) {
|
||||||
|
Comment(comment = replies[it]!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview(name = "Light mode", uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||||
|
@Preview(name = "Dark mode", uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||||
|
@Composable
|
||||||
|
private fun CommentRepliesPreview() {
|
||||||
|
val comment = CommentsInfoItem(
|
||||||
|
commentText = Description("Hello world!", Description.PLAIN_TEXT),
|
||||||
|
uploaderName = "Test",
|
||||||
|
)
|
||||||
|
|
||||||
|
val reply1 = CommentsInfoItem(
|
||||||
|
commentText = Description("This is a reply", Description.PLAIN_TEXT),
|
||||||
|
uploaderName = "Test 2",
|
||||||
|
)
|
||||||
|
val reply2 = CommentsInfoItem(
|
||||||
|
commentText = Description("This is another reply.<br>This is another line.", Description.HTML),
|
||||||
|
uploaderName = "Test 3",
|
||||||
|
)
|
||||||
|
val flow = flowOf(PagingData.from(listOf(reply1, reply2)))
|
||||||
|
|
||||||
|
AppTheme {
|
||||||
|
CommentReplies(comment = comment, flow = flow, disposables = CompositeDisposable())
|
||||||
|
}
|
||||||
|
}
|
@ -4,104 +4,50 @@ import android.os.Bundle
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.platform.ComposeView
|
import androidx.compose.ui.platform.ComposeView
|
||||||
import icepick.State
|
import androidx.fragment.app.Fragment
|
||||||
import io.reactivex.rxjava3.core.Single
|
import androidx.paging.Pager
|
||||||
|
import androidx.paging.PagingConfig
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
import org.schabi.newpipe.R
|
|
||||||
import org.schabi.newpipe.error.UserAction
|
|
||||||
import org.schabi.newpipe.extractor.ListExtractor.InfoItemsPage
|
|
||||||
import org.schabi.newpipe.extractor.comments.CommentsInfoItem
|
import org.schabi.newpipe.extractor.comments.CommentsInfoItem
|
||||||
import org.schabi.newpipe.fragments.list.BaseListInfoFragment
|
import org.schabi.newpipe.ktx.serializable
|
||||||
import org.schabi.newpipe.info_list.ItemViewMode
|
|
||||||
import org.schabi.newpipe.ui.theme.AppTheme
|
import org.schabi.newpipe.ui.theme.AppTheme
|
||||||
import org.schabi.newpipe.util.ExtractorHelper
|
|
||||||
import org.schabi.newpipe.util.Localization
|
|
||||||
import java.util.Queue
|
|
||||||
import java.util.function.Supplier
|
|
||||||
|
|
||||||
class CommentRepliesFragment() : BaseListInfoFragment<CommentsInfoItem, CommentRepliesInfo>(UserAction.REQUESTED_COMMENT_REPLIES) {
|
class CommentRepliesFragment : Fragment() {
|
||||||
/**
|
|
||||||
* @return the comment to which the replies are shown
|
|
||||||
*/
|
|
||||||
@State
|
|
||||||
lateinit var commentsInfoItem: CommentsInfoItem // the comment to show replies of
|
|
||||||
private val disposables = CompositeDisposable()
|
private val disposables = CompositeDisposable()
|
||||||
|
lateinit var comment: CommentsInfoItem
|
||||||
constructor(commentsInfoItem: CommentsInfoItem) : this() {
|
|
||||||
this.commentsInfoItem = commentsInfoItem
|
|
||||||
// setting "" as title since the title will be properly set right after
|
|
||||||
setInitialData(commentsInfoItem.serviceId, commentsInfoItem.url, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View {
|
): View {
|
||||||
return inflater.inflate(R.layout.fragment_comments, container, false)
|
comment = requireArguments().serializable<CommentsInfoItem>(COMMENT_KEY)!!
|
||||||
}
|
return ComposeView(requireContext()).apply {
|
||||||
|
setContent {
|
||||||
|
val flow = remember(comment) {
|
||||||
|
Pager(PagingConfig(pageSize = 20, enablePlaceholders = false)) {
|
||||||
|
CommentRepliesSource(comment)
|
||||||
|
}.flow
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
AppTheme {
|
||||||
disposables.clear()
|
CommentReplies(comment = comment, flow = flow, disposables = disposables)
|
||||||
super.onDestroyView()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getListHeaderSupplier(): Supplier<View> {
|
|
||||||
return Supplier {
|
|
||||||
ComposeView(requireContext()).apply {
|
|
||||||
setContent {
|
|
||||||
AppTheme {
|
|
||||||
CommentRepliesHeader(commentsInfoItem, disposables)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
override fun onDestroyView() {
|
||||||
// State saving
|
super.onDestroyView()
|
||||||
////////////////////////////////////////////////////////////////////////// */
|
disposables.clear()
|
||||||
override fun writeTo(objectsToSave: Queue<Any>) {
|
|
||||||
super.writeTo(objectsToSave)
|
|
||||||
objectsToSave.add(commentsInfoItem)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Throws(Exception::class)
|
|
||||||
override fun readFrom(savedObjects: Queue<Any>) {
|
|
||||||
super.readFrom(savedObjects)
|
|
||||||
commentsInfoItem = savedObjects.poll() as CommentsInfoItem
|
|
||||||
}
|
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
|
||||||
// Data loading
|
|
||||||
////////////////////////////////////////////////////////////////////////// */
|
|
||||||
override fun loadResult(forceLoad: Boolean): Single<CommentRepliesInfo> {
|
|
||||||
return Single.fromCallable {
|
|
||||||
CommentRepliesInfo(
|
|
||||||
commentsInfoItem, // the reply count string will be shown as the activity title
|
|
||||||
Localization.replyCount(requireContext(), commentsInfoItem.replyCount)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun loadMoreItemsLogic(): Single<InfoItemsPage<CommentsInfoItem?>>? {
|
|
||||||
// commentsInfoItem.getUrl() should contain the url of the original
|
|
||||||
// ListInfo<CommentsInfoItem>, which should be the stream url
|
|
||||||
return ExtractorHelper.getMoreCommentItems(
|
|
||||||
serviceId, commentsInfoItem.url, currentNextPage
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
|
||||||
// Utils
|
|
||||||
////////////////////////////////////////////////////////////////////////// */
|
|
||||||
override fun getItemViewMode(): ItemViewMode {
|
|
||||||
return ItemViewMode.LIST
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@JvmField
|
@JvmField
|
||||||
val TAG: String = CommentRepliesFragment::class.java.simpleName
|
val TAG = CommentRepliesFragment::class.simpleName!!
|
||||||
|
|
||||||
|
const val COMMENT_KEY = "comment"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,14 +136,8 @@ fun CommentRepliesHeader(comment: CommentsInfoItem, disposables: CompositeDispos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview(
|
@Preview(name = "Light mode", uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||||
name = "Light mode",
|
@Preview(name = "Dark mode", uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||||
uiMode = Configuration.UI_MODE_NIGHT_NO
|
|
||||||
)
|
|
||||||
@Preview(
|
|
||||||
name = "Dark mode",
|
|
||||||
uiMode = Configuration.UI_MODE_NIGHT_YES
|
|
||||||
)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CommentRepliesHeaderPreview() {
|
fun CommentRepliesHeaderPreview() {
|
||||||
val disposables = CompositeDisposable()
|
val disposables = CompositeDisposable()
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
package org.schabi.newpipe.fragments.list.comments;
|
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.ListInfo;
|
|
||||||
import org.schabi.newpipe.extractor.comments.CommentsInfoItem;
|
|
||||||
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
public final class CommentRepliesInfo extends ListInfo<CommentsInfoItem> {
|
|
||||||
/**
|
|
||||||
* This class is used to wrap the comment replies page into a ListInfo object.
|
|
||||||
*
|
|
||||||
* @param comment the comment from which to get replies
|
|
||||||
* @param name will be shown as the fragment title
|
|
||||||
*/
|
|
||||||
public CommentRepliesInfo(final CommentsInfoItem comment, final String name) {
|
|
||||||
super(comment.getServiceId(),
|
|
||||||
new ListLinkHandler("", "", "", Collections.emptyList(), null), name);
|
|
||||||
setNextPage(comment.getReplies());
|
|
||||||
setRelatedItems(Collections.emptyList()); // since it must be non-null
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,22 @@
|
|||||||
|
package org.schabi.newpipe.fragments.list.comments
|
||||||
|
|
||||||
|
import androidx.paging.PagingState
|
||||||
|
import androidx.paging.rxjava3.RxPagingSource
|
||||||
|
import io.reactivex.rxjava3.core.Single
|
||||||
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import org.schabi.newpipe.extractor.Page
|
||||||
|
import org.schabi.newpipe.extractor.comments.CommentsInfoItem
|
||||||
|
import org.schabi.newpipe.util.ExtractorHelper
|
||||||
|
|
||||||
|
class CommentRepliesSource(
|
||||||
|
private val commentsInfoItem: CommentsInfoItem,
|
||||||
|
) : RxPagingSource<Page, CommentsInfoItem>() {
|
||||||
|
override fun loadSingle(params: LoadParams<Page>): Single<LoadResult<Page, CommentsInfoItem>> {
|
||||||
|
val nextPage = params.key ?: commentsInfoItem.replies
|
||||||
|
return ExtractorHelper.getMoreCommentItems(commentsInfoItem.serviceId, commentsInfoItem.url, nextPage)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.map { LoadResult.Page(it.items, null, it.nextPage) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getRefreshKey(state: PagingState<Page, CommentsInfoItem>) = null
|
||||||
|
}
|
@ -1,9 +1,25 @@
|
|||||||
package org.schabi.newpipe.ktx
|
package org.schabi.newpipe.ktx
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import androidx.core.os.BundleCompat
|
import androidx.core.os.BundleCompat
|
||||||
|
import java.io.Serializable
|
||||||
|
import kotlin.reflect.safeCast
|
||||||
|
|
||||||
inline fun <reified T : Parcelable> Bundle.parcelableArrayList(key: String?): ArrayList<T>? {
|
inline fun <reified T : Parcelable> Bundle.parcelableArrayList(key: String?): ArrayList<T>? {
|
||||||
return BundleCompat.getParcelableArrayList(this, key, T::class.java)
|
return BundleCompat.getParcelableArrayList(this, key, T::class.java)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun <reified T : Serializable> Bundle.serializable(key: String?): T? {
|
||||||
|
return getSerializable(this, key, T::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : Serializable> getSerializable(bundle: Bundle, key: String?, clazz: Class<T>): T? {
|
||||||
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||||
|
bundle.getSerializable(key, clazz)
|
||||||
|
} else {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
clazz.kotlin.safeCast(bundle.getSerializable(key))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -9,6 +9,7 @@ import android.content.Context;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
@ -503,8 +504,11 @@ public final class NavigationHelper {
|
|||||||
|
|
||||||
public static void openCommentRepliesFragment(@NonNull final FragmentActivity activity,
|
public static void openCommentRepliesFragment(@NonNull final FragmentActivity activity,
|
||||||
@NonNull final CommentsInfoItem comment) {
|
@NonNull final CommentsInfoItem comment) {
|
||||||
|
final var bundle = new Bundle();
|
||||||
|
bundle.putSerializable(CommentRepliesFragment.COMMENT_KEY, comment);
|
||||||
|
|
||||||
defaultTransaction(activity.getSupportFragmentManager())
|
defaultTransaction(activity.getSupportFragmentManager())
|
||||||
.replace(R.id.fragment_holder, new CommentRepliesFragment(comment),
|
.replace(R.id.fragment_holder, CommentRepliesFragment.class, bundle,
|
||||||
CommentRepliesFragment.TAG)
|
CommentRepliesFragment.TAG)
|
||||||
.addToBackStack(CommentRepliesFragment.TAG)
|
.addToBackStack(CommentRepliesFragment.TAG)
|
||||||
.commit();
|
.commit();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// 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 = '1.9.23'
|
ext.kotlin_version = '1.9.24'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
Loading…
Reference in New Issue
Block a user