Merge pull request #656 from Bnyro/master

Watch History
This commit is contained in:
Bnyro 2022-07-01 19:48:47 +02:00 committed by GitHub
commit ddd31aa859
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 437 additions and 31 deletions

View File

@ -79,28 +79,28 @@ class MainActivity : AppCompatActivity() {
// hide the trending page if enabled // hide the trending page if enabled
val hideTrendingPage = PreferenceHelper.getBoolean(this, "hide_trending_page", false) val hideTrendingPage = PreferenceHelper.getBoolean(this, "hide_trending_page", false)
if (hideTrendingPage) bottomNavigationView.menu.findItem(R.id.home2).isVisible = false if (hideTrendingPage) bottomNavigationView.menu.findItem(R.id.homeFragment).isVisible = false
// navigate to the default start tab // navigate to the default start tab
when (PreferenceHelper.getString(this, "default_tab", "home")) { when (PreferenceHelper.getString(this, "default_tab", "home")) {
"home" -> navController.navigate(R.id.home2) "home" -> navController.navigate(R.id.homeFragment)
"subscriptions" -> navController.navigate(R.id.subscriptions) "subscriptions" -> navController.navigate(R.id.subscriptionsFragment)
"library" -> navController.navigate(R.id.library) "library" -> navController.navigate(R.id.libraryFragment)
} }
binding.bottomNav.setOnItemSelectedListener { binding.bottomNav.setOnItemSelectedListener {
when (it.itemId) { when (it.itemId) {
R.id.home2 -> { R.id.homeFragment -> {
navController.backQueue.clear() navController.backQueue.clear()
navController.navigate(R.id.home2) navController.navigate(R.id.homeFragment)
} }
R.id.subscriptions -> { R.id.subscriptionsFragment -> {
// navController.backQueue.clear() // navController.backQueue.clear()
navController.navigate(R.id.subscriptions) navController.navigate(R.id.subscriptionsFragment)
} }
R.id.library -> { R.id.libraryFragment -> {
// navController.backQueue.clear() // navController.backQueue.clear()
navController.navigate(R.id.library) navController.navigate(R.id.libraryFragment)
} }
} }
false false
@ -176,7 +176,7 @@ class MainActivity : AppCompatActivity() {
channel = channel!!.replace("/c/", "") channel = channel!!.replace("/c/", "")
channel = channel.replace("/user/", "") channel = channel.replace("/user/", "")
val bundle = bundleOf("channel_id" to channel) val bundle = bundleOf("channel_id" to channel)
navController.navigate(R.id.channel, bundle) navController.navigate(R.id.channelFragment, bundle)
} else if (data.path!!.contains("/playlist")) { } else if (data.path!!.contains("/playlist")) {
Log.i(TAG, "URI Type: Playlist") Log.i(TAG, "URI Type: Playlist")
var playlist = data.query!! var playlist = data.query!!

View File

@ -69,7 +69,7 @@ class CommentsAdapter(
commentorImage.setOnClickListener { commentorImage.setOnClickListener {
val activity = holder.v.context as MainActivity val activity = holder.v.context as MainActivity
val bundle = bundleOf("channel_id" to comment.commentorUrl) val bundle = bundleOf("channel_id" to comment.commentorUrl)
activity.navController.navigate(R.id.channel, bundle) activity.navController.navigate(R.id.channelFragment, bundle)
try { try {
val mainMotionLayout = val mainMotionLayout =
activity.findViewById<MotionLayout>(R.id.mainMotionLayout) activity.findViewById<MotionLayout>(R.id.mainMotionLayout)

View File

@ -61,7 +61,7 @@ class RepliesAdapter(
commentorImage.setOnClickListener { commentorImage.setOnClickListener {
val activity = holder.v.context as MainActivity val activity = holder.v.context as MainActivity
val bundle = bundleOf("channel_id" to reply.commentorUrl) val bundle = bundleOf("channel_id" to reply.commentorUrl)
activity.navController.navigate(R.id.channel, bundle) activity.navController.navigate(R.id.channelFragment, bundle)
try { try {
val mainMotionLayout = val mainMotionLayout =
activity.findViewById<MotionLayout>(R.id.mainMotionLayout) activity.findViewById<MotionLayout>(R.id.mainMotionLayout)

View File

@ -117,7 +117,7 @@ class SearchViewHolder(
channelImage.setOnClickListener { channelImage.setOnClickListener {
val activity = v.context as MainActivity val activity = v.context as MainActivity
val bundle = bundleOf("channel_id" to item.uploaderUrl) val bundle = bundleOf("channel_id" to item.uploaderUrl)
activity.navController.navigate(R.id.channel, bundle) activity.navController.navigate(R.id.channelFragment, bundle)
} }
} }
@ -134,7 +134,7 @@ class SearchViewHolder(
v.setOnClickListener { v.setOnClickListener {
val activity = v.context as MainActivity val activity = v.context as MainActivity
val bundle = bundleOf("channel_id" to item.url) val bundle = bundleOf("channel_id" to item.url)
activity.navController.navigate(R.id.channel, bundle) activity.navController.navigate(R.id.channelFragment, bundle)
} }
// todo sub button // todo sub button
} }

View File

@ -62,7 +62,7 @@ class SubscriptionAdapter(
channelImage.setOnClickListener { channelImage.setOnClickListener {
val activity = holder.v.context as MainActivity val activity = holder.v.context as MainActivity
val bundle = bundleOf("channel_id" to trending.uploaderUrl) val bundle = bundleOf("channel_id" to trending.uploaderUrl)
activity.navController.navigate(R.id.channel, bundle) activity.navController.navigate(R.id.channelFragment, bundle)
try { try {
val mainMotionLayout = val mainMotionLayout =
activity.findViewById<MotionLayout>(R.id.mainMotionLayout) activity.findViewById<MotionLayout>(R.id.mainMotionLayout)

View File

@ -48,7 +48,7 @@ class SubscriptionChannelAdapter(private val subscriptions: MutableList<Subscrip
root.setOnClickListener { root.setOnClickListener {
val activity = holder.v.context as MainActivity val activity = holder.v.context as MainActivity
val bundle = bundleOf("channel_id" to subscription.url) val bundle = bundleOf("channel_id" to subscription.url)
activity.navController.navigate(R.id.channel, bundle) activity.navController.navigate(R.id.channelFragment, bundle)
} }
subscriptionSubscribe.setOnClickListener { subscriptionSubscribe.setOnClickListener {
if (!isLoading) { if (!isLoading) {

View File

@ -53,7 +53,7 @@ class TrendingAdapter(
channelImage.setOnClickListener { channelImage.setOnClickListener {
val activity = holder.v.context as MainActivity val activity = holder.v.context as MainActivity
val bundle = bundleOf("channel_id" to trending.uploaderUrl) val bundle = bundleOf("channel_id" to trending.uploaderUrl)
activity.navController.navigate(R.id.channel, bundle) activity.navController.navigate(R.id.channelFragment, bundle)
try { try {
val mainMotionLayout = val mainMotionLayout =
activity.findViewById<MotionLayout>(R.id.mainMotionLayout) activity.findViewById<MotionLayout>(R.id.mainMotionLayout)

View File

@ -0,0 +1,96 @@
package com.github.libretube.adapters
import android.os.Bundle
import android.text.format.DateUtils
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.core.os.bundleOf
import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.R
import com.github.libretube.activities.MainActivity
import com.github.libretube.databinding.WatchHistoryRowBinding
import com.github.libretube.dialogs.VideoOptionsDialog
import com.github.libretube.fragments.PlayerFragment
import com.github.libretube.obj.WatchHistoryItem
import com.squareup.picasso.Picasso
class WatchHistoryAdapter(
private val watchHistory: MutableList<WatchHistoryItem>,
private val childFragmentManager: FragmentManager
) :
RecyclerView.Adapter<WatchHistoryViewHolder>() {
private val TAG = "WatchHistoryAdapter"
private lateinit var binding: WatchHistoryRowBinding
fun clear() {
val size = watchHistory.size
watchHistory.clear()
notifyItemRangeRemoved(0, size)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WatchHistoryViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
binding = WatchHistoryRowBinding.inflate(layoutInflater, parent, false)
return WatchHistoryViewHolder(binding.root)
}
override fun onBindViewHolder(holder: WatchHistoryViewHolder, position: Int) {
val video = watchHistory[position]
binding.apply {
videoTitle.text = video.title
channelName.text = video.uploader
uploadDate.text = video.uploadDate
thumbnailDuration.text = DateUtils.formatElapsedTime(video.duration?.toLong()!!)
Picasso.get().load(video.thumbnailUrl).into(thumbnail)
Picasso.get().load(video.uploaderAvatar).into(channelImage)
channelImage.setOnClickListener {
val activity = holder.v.context as MainActivity
val bundle = bundleOf("channel_id" to video.uploaderUrl)
activity.navController.navigate(R.id.channelFragment, bundle)
try {
val mainMotionLayout =
activity.findViewById<MotionLayout>(R.id.mainMotionLayout)
if (mainMotionLayout.progress == 0.toFloat()) {
mainMotionLayout.transitionToEnd()
activity.findViewById<MotionLayout>(R.id.playerMotionLayout)
.transitionToEnd()
}
} catch (e: Exception) {
}
}
root.setOnClickListener {
var bundle = Bundle()
bundle.putString("videoId", video.videoId)
var frag = PlayerFragment()
frag.arguments = bundle
val activity = holder.v.context as AppCompatActivity
activity.supportFragmentManager.beginTransaction()
.remove(PlayerFragment())
.commit()
activity.supportFragmentManager.beginTransaction()
.replace(R.id.container, frag)
.commitNow()
}
root.setOnLongClickListener {
VideoOptionsDialog(video.videoId!!, holder.v.context)
.show(childFragmentManager, VideoOptionsDialog.TAG)
true
}
}
}
override fun getItemCount(): Int {
return watchHistory.size
}
}
class WatchHistoryViewHolder(val v: View) : RecyclerView.ViewHolder(v) {
init {
}
}

View File

@ -8,6 +8,7 @@ import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.github.libretube.R import com.github.libretube.R
import com.github.libretube.adapters.PlaylistsAdapter import com.github.libretube.adapters.PlaylistsAdapter
@ -43,6 +44,17 @@ class LibraryFragment : Fragment() {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
binding.playlistRecView.layoutManager = LinearLayoutManager(view.context) binding.playlistRecView.layoutManager = LinearLayoutManager(view.context)
token = PreferenceHelper.getToken(requireContext()) token = PreferenceHelper.getToken(requireContext())
// hide watch history button of history disabled
val watchHistoryEnabled = PreferenceHelper.getBoolean(requireContext(), "watch_history_toggle", true)
if (!watchHistoryEnabled) {
binding.showWatchHistory.visibility = View.GONE
} else {
binding.showWatchHistory.setOnClickListener {
findNavController().navigate(R.id.watchHistoryFragment)
}
}
if (token != "") { if (token != "") {
binding.boogh.visibility = View.GONE binding.boogh.visibility = View.GONE
binding.textLike.visibility = View.GONE binding.textLike.visibility = View.GONE

View File

@ -455,6 +455,11 @@ class PlayerFragment : Fragment() {
if (!relatedStreamsEnabled) toggleComments() if (!relatedStreamsEnabled) toggleComments()
// prepare for autoplay // prepare for autoplay
initAutoPlay() initAutoPlay()
val watchHistoryEnabled =
PreferenceHelper.getBoolean(requireContext(), "Watch_history_toggle", true)
if (watchHistoryEnabled) {
PreferenceHelper.addToWatchHistory(requireContext(), videoId!!, response)
}
} }
} }
} }
@ -742,7 +747,7 @@ class PlayerFragment : Fragment() {
binding.playerChannel.setOnClickListener { binding.playerChannel.setOnClickListener {
val activity = view.context as MainActivity val activity = view.context as MainActivity
val bundle = bundleOf("channel_id" to response.uploaderUrl) val bundle = bundleOf("channel_id" to response.uploaderUrl)
activity.navController.navigate(R.id.channel, bundle) activity.navController.navigate(R.id.channelFragment, bundle)
activity.binding.mainMotionLayout.transitionToEnd() activity.binding.mainMotionLayout.transitionToEnd()
binding.playerMotionLayout.transitionToEnd() binding.playerMotionLayout.transitionToEnd()
} }

View File

@ -0,0 +1,45 @@
package com.github.libretube.fragments
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.LinearLayoutManager
import com.github.libretube.adapters.WatchHistoryAdapter
import com.github.libretube.databinding.FragmentWatchHistoryBinding
import com.github.libretube.util.PreferenceHelper
class WatchHistoryFragment : Fragment() {
private val TAG = "WatchHistoryFragment"
private lateinit var binding: FragmentWatchHistoryBinding
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentWatchHistoryBinding.inflate(layoutInflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val watchHistory = PreferenceHelper.getWatchHistory(requireContext())
val watchHistoryAdapter = WatchHistoryAdapter(watchHistory, childFragmentManager)
binding.watchHistoryRecView.adapter = watchHistoryAdapter
binding.clearHistory.setOnClickListener {
PreferenceHelper.removePreference(requireContext(), "watch_history")
watchHistoryAdapter.clear()
}
// reverse order
val linearLayoutManager = LinearLayoutManager(view.context)
linearLayoutManager.reverseLayout = true
linearLayoutManager.stackFromEnd = true
binding.watchHistoryRecView.layoutManager = linearLayoutManager
}
}

View File

@ -0,0 +1,12 @@
package com.github.libretube.obj
data class WatchHistoryItem(
val videoId: String?,
val title: String?,
val uploadDate: String?,
val uploader: String?,
val uploaderUrl: String?,
val uploaderAvatar: String?,
val thumbnailUrl: String?,
val duration: Int?
)

View File

@ -18,12 +18,20 @@ class AdvancedSettings : PreferenceFragmentCompat() {
val settingsActivity = activity as SettingsActivity val settingsActivity = activity as SettingsActivity
settingsActivity.binding.topBarTextView.text = getString(R.string.advanced) settingsActivity.binding.topBarTextView.text = getString(R.string.advanced)
// clear search history
val clearHistory = findPreference<Preference>("clear_history") val clearHistory = findPreference<Preference>("clear_history")
clearHistory?.setOnPreferenceClickListener { clearHistory?.setOnPreferenceClickListener {
PreferenceHelper.removePreference(requireContext(), "search_history") PreferenceHelper.removePreference(requireContext(), "search_history")
true true
} }
// clear watch history
val clearWatchHistory = findPreference<Preference>("clear_watch_history")
clearWatchHistory?.setOnPreferenceClickListener {
PreferenceHelper.removePreference(requireContext(), "watch_history")
true
}
val resetSettings = findPreference<Preference>("reset_settings") val resetSettings = findPreference<Preference>("reset_settings")
resetSettings?.setOnPreferenceClickListener { resetSettings?.setOnPreferenceClickListener {
showResetDialog() showResetDialog()

View File

@ -4,11 +4,15 @@ import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.github.libretube.obj.CustomInstance import com.github.libretube.obj.CustomInstance
import com.github.libretube.obj.Streams
import com.github.libretube.obj.WatchHistoryItem
import com.google.common.reflect.TypeToken import com.google.common.reflect.TypeToken
import com.google.gson.Gson import com.google.gson.Gson
import java.lang.reflect.Type import java.lang.reflect.Type
object PreferenceHelper { object PreferenceHelper {
private val TAG = "PreferenceHelper"
fun setString(context: Context, key: String?, value: String?) { fun setString(context: Context, key: String?, value: String?) {
val editor = getDefaultSharedPreferencesEditor(context) val editor = getDefaultSharedPreferencesEditor(context)
editor.putString(key, value) editor.putString(key, value)
@ -122,6 +126,48 @@ object PreferenceHelper {
editor.putStringSet("search_history", set).apply() editor.putStringSet("search_history", set).apply()
} }
fun addToWatchHistory(context: Context, videoId: String, streams: Streams) {
val editor = getDefaultSharedPreferencesEditor(context)
val gson = Gson()
val watchHistoryItem = WatchHistoryItem(
videoId,
streams.title,
streams.uploadDate,
streams.uploader,
streams.uploaderUrl?.replace("/channel/", ""),
streams.uploaderAvatar,
streams.thumbnailUrl,
streams.duration
)
val watchHistory = getWatchHistory(context)
// delete entries that have the same videoId
var indexToRemove = Int.MAX_VALUE
watchHistory.forEachIndexed { index, item ->
if (item.videoId == videoId) indexToRemove = index
}
if (indexToRemove != Int.MAX_VALUE) watchHistory.removeAt(indexToRemove)
watchHistory += watchHistoryItem
val json = gson.toJson(watchHistory)
editor.putString("watch_history", json).apply()
}
fun getWatchHistory(context: Context): ArrayList<WatchHistoryItem> {
val settings = getDefaultSharedPreferences(context)
val gson = Gson()
val json: String = settings.getString("watch_history", "")!!
val type: Type = object : TypeToken<List<WatchHistoryItem?>?>() {}.type
return try {
gson.fromJson(json, type)
} catch (e: Exception) {
arrayListOf()
}
}
private fun getDefaultSharedPreferences(context: Context): SharedPreferences { private fun getDefaultSharedPreferences(context: Context): SharedPreferences {
return PreferenceManager.getDefaultSharedPreferences(context) return PreferenceManager.getDefaultSharedPreferences(context)
} }

View File

@ -6,6 +6,27 @@
android:layout_height="match_parent" android:layout_height="match_parent"
tools:context=".fragments.LibraryFragment"> tools:context=".fragments.LibraryFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/showWatchHistory"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:background="?attr/selectableItemBackground"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/watch_history"
android:textSize="20sp"/>
</LinearLayout>
<RelativeLayout <RelativeLayout
android:id="@+id/loginOrRegister2" android:id="@+id/loginOrRegister2"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -64,6 +85,8 @@
</ScrollView> </ScrollView>
</com.github.libretube.util.CustomSwipeToRefresh> </com.github.libretube.util.CustomSwipeToRefresh>
</LinearLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/create_playlist" android:id="@+id/create_playlist"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="8dp"
android:layout_marginBottom="8dp" >
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/watch_history"
android:layout_weight="1"
android:textSize="16sp" />
<ImageButton
android:id="@+id/clearHistory"
android:layout_gravity="center"
android:layout_width="16dp"
android:layout_height="16dp"
android:src="@drawable/ic_trash"/>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/watchHistoryRecView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:nestedScrollingEnabled="false"/>
</LinearLayout>

View File

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/video_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:background="?android:attr/selectableItemBackground">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent=".45" />
<com.google.android.material.card.MaterialCardView
android:id="@+id/thumbnail_card"
android:layout_width="0dp"
android:layout_height="0dp"
app:cardCornerRadius="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="16:9"
app:layout_constraintEnd_toStartOf="@+id/guideline"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0"
app:strokeWidth="0dp">
<ImageView
android:id="@+id/thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:srcCompat="@tools:sample/backgrounds/scenic" />
<androidx.cardview.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginEnd="5dp"
android:layout_marginBottom="3dp"
app:cardBackgroundColor="@color/duration_background_color"
app:cardCornerRadius="8dp"
app:cardElevation="0dp">
<TextView
android:id="@+id/thumbnail_duration"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="6dp"
android:paddingTop="2dp"
android:paddingEnd="6dp"
android:paddingBottom="2dp"
android:textColor="@color/duration_text_color"
android:textSize="11sp"
tools:text="05:36" />
</androidx.cardview.widget.CardView>
</com.google.android.material.card.MaterialCardView>
<TextView
android:id="@+id/video_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:ellipsize="end"
android:maxLines="2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/thumbnail_card"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/upload_date"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/thumbnail_card"
app:layout_constraintTop_toBottomOf="@id/video_title" />
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/channel_image"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toBottomOf="@id/upload_date" />
<TextView
android:id="@+id/channel_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="12dp"
android:ellipsize="end"
android:maxLines="1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/channel_image"
app:layout_constraintTop_toBottomOf="@id/upload_date" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -2,15 +2,15 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu xmlns:android="http://schemas.android.com/apk/res/android">
<item <item
android:id="@+id/home2" android:id="@+id/homeFragment"
android:icon="@drawable/ic_home" android:icon="@drawable/ic_home"
android:title="@string/startpage" /> android:title="@string/startpage" />
<item <item
android:id="@+id/subscriptions" android:id="@+id/subscriptionsFragment"
android:icon="@drawable/ic_subscriptions" android:icon="@drawable/ic_subscriptions"
android:title="@string/subscriptions" /> android:title="@string/subscriptions" />
<item <item
android:id="@+id/library" android:id="@+id/libraryFragment"
android:icon="@drawable/ic_library" android:icon="@drawable/ic_library"
android:title="@string/library" /> android:title="@string/library" />

View File

@ -3,20 +3,20 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nav" android:id="@+id/nav"
app:startDestination="@id/home2"> app:startDestination="@id/homeFragment">
<fragment <fragment
android:id="@+id/home2" android:id="@+id/homeFragment"
android:name="com.github.libretube.fragments.HomeFragment" android:name="com.github.libretube.fragments.HomeFragment"
android:label="fragment_home" android:label="fragment_home"
tools:layout="@layout/fragment_home" /> tools:layout="@layout/fragment_home" />
<fragment <fragment
android:id="@+id/subscriptions" android:id="@+id/subscriptionsFragment"
android:name="com.github.libretube.fragments.SubscriptionsFragment" android:name="com.github.libretube.fragments.SubscriptionsFragment"
android:label="fragment_subscriptions" android:label="fragment_subscriptions"
tools:layout="@layout/fragment_subscriptions" /> tools:layout="@layout/fragment_subscriptions" />
<fragment <fragment
android:id="@+id/library" android:id="@+id/libraryFragment"
android:name="com.github.libretube.fragments.LibraryFragment" android:name="com.github.libretube.fragments.LibraryFragment"
android:label="fragment_library" android:label="fragment_library"
tools:layout="@layout/fragment_library"></fragment> tools:layout="@layout/fragment_library"></fragment>
@ -26,7 +26,7 @@
android:label="fragment_search" android:label="fragment_search"
tools:layout="@layout/fragment_search" /> tools:layout="@layout/fragment_search" />
<fragment <fragment
android:id="@+id/channel" android:id="@+id/channelFragment"
android:name="com.github.libretube.fragments.ChannelFragment" android:name="com.github.libretube.fragments.ChannelFragment"
android:label="channel" android:label="channel"
tools:layout="@layout/fragment_channel"> tools:layout="@layout/fragment_channel">
@ -44,7 +44,8 @@
app:argType="string" /> app:argType="string" />
</fragment> </fragment>
<fragment <fragment
android:id="@+id/settings" android:id="@+id/watchHistoryFragment"
android:name="com.github.libretube.SettingsActivity$SettingsFragment" android:name="com.github.libretube.fragments.WatchHistoryFragment"
android:label="Settings" /> android:label="@string/watch_history"
tools:layout="@layout/fragment_watch_history"/>
</navigation> </navigation>

View File

@ -79,7 +79,7 @@
<string name="okay">OK</string> <string name="okay">OK</string>
<string name="history">History</string> <string name="history">History</string>
<string name="search_history">Search History</string> <string name="search_history">Search History</string>
<string name="clear_history">Clear History</string> <string name="clear_history">Clear history</string>
<string name="music_songs">YT Music Songs</string> <string name="music_songs">YT Music Songs</string>
<string name="music_videos">YT Music Videos</string> <string name="music_videos">YT Music Videos</string>
<string name="music_albums">YT Music Albums</string> <string name="music_albums">YT Music Albums</string>
@ -207,4 +207,5 @@
<string name="deleteAccount_summary">Delete your Piped account</string> <string name="deleteAccount_summary">Delete your Piped account</string>
<string name="account">Account</string> <string name="account">Account</string>
<string name="restore">Restore</string> <string name="restore">Restore</string>
<string name="watch_history">Watch history</string>
</resources> </resources>

View File

@ -46,6 +46,21 @@
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory app:title="@string/watch_history">
<SwitchPreference
android:defaultValue="true"
android:icon="@drawable/ic_history_filled"
app:key="watch_history_toggle"
app:title="@string/watch_history" />
<Preference
android:icon="@drawable/ic_trash"
app:key="clear_watch_history"
app:title="@string/clear_history" />
</PreferenceCategory>
<PreferenceCategory> <PreferenceCategory>
<Preference <Preference