diff --git a/app/src/main/java/com/lagradost/cloudstream3/plugins/PluginManager.kt b/app/src/main/java/com/lagradost/cloudstream3/plugins/PluginManager.kt index c0f35601..b9c775c0 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/plugins/PluginManager.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/plugins/PluginManager.kt @@ -1,40 +1,39 @@ package com.lagradost.cloudstream3.plugins import android.app.* -import dalvik.system.PathClassLoader -import com.google.gson.Gson +import android.content.Context import android.content.res.AssetManager import android.content.res.Resources -import android.os.Environment -import android.widget.Toast -import android.content.Context import android.os.Build +import android.os.Environment import android.util.Log +import android.widget.Toast import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import com.fasterxml.jackson.annotation.JsonProperty +import com.google.gson.Gson import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.APIHolder.removePluginMapping import com.lagradost.cloudstream3.AcraApplication.Companion.getKey import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey import com.lagradost.cloudstream3.AcraApplication.Companion.setKey -import com.lagradost.cloudstream3.plugins.RepositoryManager.ONLINE_PLUGINS_FOLDER -import com.lagradost.cloudstream3.plugins.RepositoryManager.downloadPluginToFile import com.lagradost.cloudstream3.CommonActivity.showToast -import com.lagradost.cloudstream3.plugins.RepositoryManager.getRepoPlugins -import com.lagradost.cloudstream3.ui.settings.extensions.REPOSITORIES_KEY -import com.lagradost.cloudstream3.ui.settings.extensions.RepositoryData -import com.lagradost.cloudstream3.utils.VideoDownloadManager.sanitizeFilename -import com.lagradost.cloudstream3.APIHolder.removePluginMapping import com.lagradost.cloudstream3.MainActivity.Companion.afterPluginsLoadedEvent import com.lagradost.cloudstream3.mvvm.debugPrint import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.normalSafeApiCall +import com.lagradost.cloudstream3.plugins.RepositoryManager.ONLINE_PLUGINS_FOLDER import com.lagradost.cloudstream3.plugins.RepositoryManager.PREBUILT_REPOSITORIES -import com.lagradost.cloudstream3.utils.Coroutines.ioSafe +import com.lagradost.cloudstream3.plugins.RepositoryManager.downloadPluginToFile +import com.lagradost.cloudstream3.plugins.RepositoryManager.getRepoPlugins +import com.lagradost.cloudstream3.ui.settings.extensions.REPOSITORIES_KEY +import com.lagradost.cloudstream3.ui.settings.extensions.RepositoryData import com.lagradost.cloudstream3.utils.Coroutines.main import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.UIHelper.colorFromAttribute +import com.lagradost.cloudstream3.utils.VideoDownloadManager.sanitizeFilename import com.lagradost.cloudstream3.utils.extractorApis +import dalvik.system.PathClassLoader import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import java.io.File @@ -217,7 +216,7 @@ object PluginManager { * 3. If outdated download and load the plugin * 4. Else load the plugin normally **/ - fun updateAllOnlinePluginsAndLoadThem(activity: Activity) = ioSafe { + fun updateAllOnlinePluginsAndLoadThem(activity: Activity) { // Load all plugins as fast as possible! loadAllOnlinePlugins(activity) @@ -227,7 +226,7 @@ object PluginManager { val urls = (getKey>(REPOSITORIES_KEY) ?: emptyArray()) + PREBUILT_REPOSITORIES - val onlinePlugins = urls.toList().amap { + val onlinePlugins = urls.toList().apmap { getRepoPlugins(it.url)?.toList() ?: emptyList() }.flatten().distinctBy { it.second.url } @@ -248,7 +247,7 @@ object PluginManager { val updatedPlugins = mutableListOf() - outdatedPlugins.amap { pluginData -> + outdatedPlugins.apmap { pluginData -> if (pluginData.isDisabled) { //updatedPlugins.add(activity.getString(R.string.single_plugin_disabled, pluginData.onlineData.second.name)) unloadPlugin(pluginData.savedData.filePath) @@ -279,9 +278,9 @@ object PluginManager { /** * Use updateAllOnlinePluginsAndLoadThem * */ - fun loadAllOnlinePlugins(activity: Activity) = ioSafe { + fun loadAllOnlinePlugins(activity: Activity) { // Load all plugins as fast as possible! - (getPluginsOnline()).toList().amap { pluginData -> + (getPluginsOnline()).toList().apmap { pluginData -> loadPlugin( activity, File(pluginData.filePath), @@ -290,7 +289,7 @@ object PluginManager { } } - fun loadAllLocalPlugins(activity: Activity) = ioSafe { + fun loadAllLocalPlugins(activity: Activity) { val dir = File(LOCAL_PLUGINS_PATH) removeKey(PLUGINS_KEY_LOCAL) @@ -298,7 +297,7 @@ object PluginManager { val res = dir.mkdirs() if (!res) { Log.w(TAG, "Failed to create local directories") - return@ioSafe + return } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt index a2dd469c..4b9dd5be 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt @@ -1,6 +1,5 @@ package com.lagradost.cloudstream3.ui.home -import android.animation.LayoutTransition import android.annotation.SuppressLint import android.app.Activity import android.content.Context @@ -26,13 +25,13 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.transition.ChangeBounds import androidx.transition.TransitionManager +import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.button.MaterialButton import com.google.android.material.chip.Chip import com.google.android.material.chip.ChipGroup import com.lagradost.cloudstream3.* -import com.lagradost.cloudstream3.APIHolder.allProviders import com.lagradost.cloudstream3.APIHolder.apis import com.lagradost.cloudstream3.APIHolder.filterProviderByPreferredMedia import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull @@ -554,7 +553,9 @@ class HomeFragment : Fragment() { is Resource.Success -> { home_preview?.isVisible = true (home_preview_viewpager?.adapter as? HomeScrollAdapter)?.apply { - setItems(preview.value) + if (!setItems(preview.value.second, preview.value.first)) { + home_preview_viewpager?.setCurrentItem(0, false) + } // home_preview_viewpager?.setCurrentItem(1000, false) } @@ -563,6 +564,10 @@ class HomeFragment : Fragment() { //} } else -> { + (home_preview_viewpager?.adapter as? HomeScrollAdapter)?.setItems( + listOf(), + false + ) home_preview?.isVisible = false context?.fixPaddingStatusbar(home_watch_holder) } @@ -577,59 +582,75 @@ class HomeFragment : Fragment() { } home_preview_viewpager?.apply { - setPageTransformer(false, HomeScrollTransformer()) - adapter = HomeScrollAdapter { load -> - load.apply { - home_preview_title_holder?.let { parent -> - TransitionManager.beginDelayedTransition(parent, ChangeBounds()) - } - - home_preview_tags?.text = tags?.joinToString(" • ") ?: "" - home_preview_tags?.isGone = tags.isNullOrEmpty() - home_preview_image?.setImage(posterUrl, posterHeaders) - home_preview_title?.text = name - - home_preview_play?.setOnClickListener { - activity?.loadResult(url, apiName, START_ACTION_RESUME_LATEST) - //activity.loadSearchResult(url, START_ACTION_RESUME_LATEST) - } - home_preview_info?.setOnClickListener { - activity?.loadResult(url, apiName) - //activity.loadSearchResult(random) - } - // very ugly code, but I dont care - val watchType = DataStoreHelper.getResultWatchState(load.getId()) - home_preview_bookmark?.setText(watchType.stringRes) - home_preview_bookmark?.setCompoundDrawablesWithIntrinsicBounds( - null, - getDrawable(home_preview_bookmark.context, watchType.iconRes), - null, - null - ) - home_preview_bookmark?.setOnClickListener { fab -> - activity?.showBottomDialog( - WatchType.values().map { fab.context.getString(it.stringRes) } - .toList(), - DataStoreHelper.getResultWatchState(load.getId()).ordinal, - fab.context.getString(R.string.action_add_to_bookmarks), - showApply = false, - {}) { - val newValue = WatchType.values()[it] - home_preview_bookmark?.setCompoundDrawablesWithIntrinsicBounds( - null, - getDrawable(home_preview_bookmark.context, newValue.iconRes), - null, - null - ) - home_preview_bookmark?.setText(newValue.stringRes) - - updateWatchStatus(load, newValue) - reloadStored() + setPageTransformer(HomeScrollTransformer()) + val callback: OnPageChangeCallback = object : OnPageChangeCallback() { + override fun onPageSelected(position: Int) { + (home_preview_viewpager?.adapter as? HomeScrollAdapter)?.apply { + if (position >= itemCount - 1 && hasMoreItems) { + hasMoreItems = false // dont make two requests + homeViewModel.loadMoreHomeScrollResponses() } + + getItem(position) + ?.apply { + home_preview_title_holder?.let { parent -> + TransitionManager.beginDelayedTransition(parent, ChangeBounds()) + } + + // home_preview_tags?.text = tags?.joinToString(" • ") ?: "" + // home_preview_tags?.isGone = tags.isNullOrEmpty() + // home_preview_image?.setImage(posterUrl, posterHeaders) + // home_preview_title?.text = name + + home_preview_play?.setOnClickListener { + activity?.loadResult(url, apiName, START_ACTION_RESUME_LATEST) + //activity.loadSearchResult(url, START_ACTION_RESUME_LATEST) + } + home_preview_info?.setOnClickListener { + activity?.loadResult(url, apiName) + //activity.loadSearchResult(random) + } + // very ugly code, but I dont care + val watchType = DataStoreHelper.getResultWatchState(this.getId()) + home_preview_bookmark?.setText(watchType.stringRes) + home_preview_bookmark?.setCompoundDrawablesWithIntrinsicBounds( + null, + getDrawable(home_preview_bookmark.context, watchType.iconRes), + null, + null + ) + home_preview_bookmark?.setOnClickListener { fab -> + activity?.showBottomDialog( + WatchType.values() + .map { fab.context.getString(it.stringRes) } + .toList(), + DataStoreHelper.getResultWatchState(this.getId()).ordinal, + fab.context.getString(R.string.action_add_to_bookmarks), + showApply = false, + {}) { + val newValue = WatchType.values()[it] + home_preview_bookmark?.setCompoundDrawablesWithIntrinsicBounds( + null, + getDrawable( + home_preview_bookmark.context, + newValue.iconRes + ), + null, + null + ) + home_preview_bookmark?.setText(newValue.stringRes) + + updateWatchStatus(this, newValue) + reloadStored() + } + } + + } } } - } + registerOnPageChangeCallback(callback) + adapter = HomeScrollAdapter() } observe(homeViewModel.apiName) { apiName -> diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollAdapter.kt index b36d7582..a3eaf7c7 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollAdapter.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollAdapter.kt @@ -1,60 +1,89 @@ package com.lagradost.cloudstream3.ui.home +import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.ImageView -import androidx.viewpager.widget.PagerAdapter +import androidx.core.view.isGone +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.RecyclerView import com.lagradost.cloudstream3.LoadResponse +import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.utils.UIHelper.setImage +import kotlinx.android.synthetic.main.home_scroll_view.view.* -class HomeScrollAdapter(private val onPrimaryCallback: (LoadResponse) -> Unit) : PagerAdapter() { - private var items: List = listOf() +class HomeScrollAdapter : RecyclerView.Adapter() { + private var items: MutableList = mutableListOf() + var hasMoreItems: Boolean = false - fun setItems(newItems: List) { - items = newItems - - notifyDataSetChanged() + fun getItem(position: Int) : LoadResponse? { + return items.getOrNull(position) } - override fun getCount(): Int { - return Int.MAX_VALUE//items.size + fun setItems(newItems: List, hasNext: Boolean): Boolean { + val isSame = newItems.firstOrNull()?.url == items.firstOrNull()?.url + hasMoreItems = hasNext + + val diffResult = DiffUtil.calculateDiff( + HomeScrollDiffCallback(this.items, newItems) + ) + + items.clear() + items.addAll(newItems) + + + diffResult.dispatchUpdatesTo(this) + + return isSame } - override fun getItemPosition(`object`: Any): Int { - return POSITION_NONE//super.getItemPosition(`object`) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + return CardViewHolder( + LayoutInflater.from(parent.context).inflate(R.layout.home_scroll_view, parent, false), + ) } - private fun getItemAtPosition(idx: Int): LoadResponse { - return items[idx % items.size] + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + when (holder) { + is CardViewHolder -> { + holder.bind(items[position]) + } + } } - override fun setPrimaryItem(container: ViewGroup, position: Int, `object`: Any) { - super.setPrimaryItem(container, position, `object`) - onPrimaryCallback.invoke(getItemAtPosition(position)) + class CardViewHolder + constructor( + itemView: View, + ) : + RecyclerView.ViewHolder(itemView) { + + fun bind(card: LoadResponse) { + card.apply { + itemView.home_scroll_preview_tags?.text = tags?.joinToString(" • ") ?: "" + itemView.home_scroll_preview_tags?.isGone = tags.isNullOrEmpty() + itemView.home_scroll_preview?.setImage(posterUrl, posterHeaders) + itemView.home_scroll_preview_title?.text = name + } + } } - override fun instantiateItem(container: ViewGroup, position: Int): Any { - val image = ImageView(container.context) - val item = getItemAtPosition(position) - image.scaleType = ImageView.ScaleType.CENTER_CROP - image.setImage(item.posterUrl ?: item.backgroundPosterUrl, item.posterHeaders) + class HomeScrollDiffCallback( + private val oldList: List, + private val newList: List + ) : + DiffUtil.Callback() { + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int) = + oldList[oldItemPosition].url == newList[newItemPosition].url - // val itemView: View = mLayoutInflater.inflate(R.layout.pager_item, container, false) + override fun getOldListSize() = oldList.size - // val imageView: ImageView = itemView.findViewById(R.id.imageView) as ImageView - // imageView.setImageResource(mResources.get(position)) + override fun getNewListSize() = newList.size - container.addView(image) - - return image + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) = + oldList[oldItemPosition] == newList[newItemPosition] } - override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) { - container.removeView(`object` as View) - } - - override fun isViewFromObject(view: View, `object`: Any): Boolean { - return view === `object` + override fun getItemCount(): Int { + return items.size } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollTransformer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollTransformer.kt index 04b6964b..2d6757f9 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollTransformer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollTransformer.kt @@ -1,13 +1,23 @@ package com.lagradost.cloudstream3.ui.home import android.view.View -import androidx.viewpager.widget.ViewPager +import androidx.viewpager2.widget.ViewPager2 -class HomeScrollTransformer : ViewPager.PageTransformer { +class HomeScrollTransformer : ViewPager2.PageTransformer { override fun transformPage(page: View, position: Float) { + //page.translationX = -position * page.width / 2.0f + + //val params = RecyclerView.LayoutParams( + // RecyclerView.LayoutParams.MATCH_PARENT, + // 0 + //) + //page.layoutParams = params + //progressBar?.layoutParams = params + + val padding = (-position * page.width / 2).toInt() page.setPadding( - maxOf(0, (-position * page.width / 2).toInt()), 0, - maxOf(0, (position * page.width / 2).toInt()), 0 + padding, 0, + -padding, 0 ) } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt index 43d849cf..9d75b0f0 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeViewModel.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.APIHolder.apis import com.lagradost.cloudstream3.APIHolder.filterHomePageListByFilmQuality import com.lagradost.cloudstream3.APIHolder.filterProviderByPreferredMedia @@ -12,17 +13,12 @@ import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull import com.lagradost.cloudstream3.AcraApplication.Companion.context import com.lagradost.cloudstream3.AcraApplication.Companion.getKey import com.lagradost.cloudstream3.AcraApplication.Companion.setKey -import com.lagradost.cloudstream3.HomePageList -import com.lagradost.cloudstream3.LoadResponse -import com.lagradost.cloudstream3.MainAPI -import com.lagradost.cloudstream3.SearchResponse import com.lagradost.cloudstream3.mvvm.* import com.lagradost.cloudstream3.ui.APIRepository import com.lagradost.cloudstream3.ui.APIRepository.Companion.noneApi import com.lagradost.cloudstream3.ui.APIRepository.Companion.randomApi import com.lagradost.cloudstream3.ui.WatchType import com.lagradost.cloudstream3.utils.Coroutines.ioSafe -import com.lagradost.cloudstream3.utils.Coroutines.ioWork import com.lagradost.cloudstream3.utils.DOWNLOAD_HEADER_CACHE import com.lagradost.cloudstream3.utils.DataStoreHelper import com.lagradost.cloudstream3.utils.DataStoreHelper.getAllResumeStateIds @@ -35,7 +31,6 @@ import com.lagradost.cloudstream3.utils.USER_SELECTED_HOMEPAGE_API import com.lagradost.cloudstream3.utils.VideoDownloadHelper import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job -import kotlinx.coroutines.async import kotlinx.coroutines.withContext import java.util.* import kotlin.collections.set @@ -49,6 +44,8 @@ class HomeViewModel : ViewModel() { private val _randomItems = MutableLiveData?>(null) val randomItems: LiveData?> = _randomItems + private var currentShuffledList: List = listOf() + private fun autoloadRepo(): APIRepository { return APIRepository(apis.first { it.hasMainPage }) } @@ -61,9 +58,12 @@ class HomeViewModel : ViewModel() { val bookmarks: LiveData>> = _bookmarks private val _resumeWatching = MutableLiveData>() - private val _preview = MutableLiveData>>() + private val _preview = MutableLiveData>>>() + private val previewResponses = mutableListOf() + private val previewResponsesAdded = mutableSetOf() + val resumeWatching: LiveData> = _resumeWatching - val preview: LiveData>> = _preview + val preview: LiveData>>> = _preview fun loadResumeWatching() = viewModelScope.launchSafe { val resumeWatching = withContext(Dispatchers.IO) { @@ -212,6 +212,40 @@ class HomeViewModel : ViewModel() { expandAndReturn(name) } + // returns the amount of items added and modifies current + private suspend fun updatePreviewResponses( + current: MutableList, + alreadyAdded: MutableSet, + shuffledList: List, + size: Int + ): Int { + var count = 0 + + val addItems = arrayListOf() + for (searchResponse in shuffledList) { + if (!alreadyAdded.contains(searchResponse.url)) { + addItems.add(searchResponse) + previewResponsesAdded.add(searchResponse.url) + if (++count >= size) { + break + } + } + } + + val add = addItems.amap { searchResponse -> + repo?.load(searchResponse.url) + }.mapNotNull { if (it != null && it is Resource.Success) it.value else null } + current.addAll(add) + return add.size + } + + private var addJob: Job? = null + fun loadMoreHomeScrollResponses() { + addJob = ioSafe { + updatePreviewResponses(previewResponses, previewResponsesAdded, currentShuffledList, 1) + _preview.postValue(Resource.Success((previewResponsesAdded.size < currentShuffledList.size) to previewResponses)) + } + } private fun load(api: MainAPI?) = ioSafe { repo = if (api != null) { @@ -226,6 +260,7 @@ class HomeViewModel : ViewModel() { if (repo?.hasMainPage == true) { _page.postValue(Resource.Loading()) _preview.postValue(Resource.Loading()) + addJob?.cancel() when (val data = repo?.getMainPage(1, null)) { is Resource.Success -> { @@ -241,64 +276,10 @@ class HomeViewModel : ViewModel() { } val items = data.value.mapNotNull { it?.items }.flatten() - val responses = ioWork { - items.flatMap { it.list }.shuffled().take(6).map { searchResponse -> - async { repo?.load(searchResponse.url) } - }.map { it.await() }.mapNotNull { if (it != null && it is Resource.Success) it.value else null } } - //.amap { searchResponse -> - // repo?.load(searchResponse.url) - ///} - - //.map { searchResponse -> - // async { repo?.load(searchResponse.url) } - // }.map { it.await() } - if (responses.isEmpty()) { - _preview.postValue( - Resource.Failure( - false, - null, - null, - "No homepage responses" - ) - ) - } else { - _preview.postValue(Resource.Success(responses)) - } - - /* - items.randomOrNull()?.list?.randomOrNull()?.url?.let { url -> - // backup request in case first fails - var first = repo?.load(url) - if(first == null ||first is Resource.Failure) { - first = repo?.load(items.random().list.random().url) - } - first?.let { - _preview.postValue(it) - } ?: run { - _preview.postValue( - Resource.Failure( - false, - null, - null, - "No repo found, this should never happen" - ) - ) - } - } ?: run { - _preview.postValue( - Resource.Failure( - false, - null, - null, - "No homepage items" - ) - ) - }*/ - - _page.postValue(Resource.Success(expandable)) - + previewResponses.clear() + previewResponsesAdded.clear() //val home = data.value if (items.isNotEmpty()) { @@ -313,9 +294,30 @@ class HomeViewModel : ViewModel() { context?.filterSearchResultByFilmQuality(currentList.shuffled()) ?: currentList.shuffled() + updatePreviewResponses( + previewResponses, + previewResponsesAdded, + randomItems, + 3 + ) + _randomItems.postValue(randomItems) + currentShuffledList = randomItems } } + if (previewResponses.isEmpty()) { + _preview.postValue( + Resource.Failure( + false, + null, + null, + "No homepage responses" + ) + ) + } else { + _preview.postValue(Resource.Success((previewResponsesAdded.size < currentShuffledList.size) to previewResponses)) + } + _page.postValue(Resource.Success(expandable)) } catch (e: Exception) { _randomItems.postValue(emptyList()) logError(e) diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 99fee606..4eb7b9ee 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -287,39 +287,23 @@ android:visibility="gone" tools:visibility="visible"> - + android:layout_height="match_parent" + android:orientation="horizontal"> - + - - - - - - - + + + + + + + + + + + + + + + + \ No newline at end of file