search fragment + suggestion

This commit is contained in:
rimthekid 2021-12-28 00:07:07 +04:00
parent c356f9b426
commit 21d29ad4af
19 changed files with 314 additions and 157 deletions

3
.idea/misc.xml generated
View File

@ -5,6 +5,7 @@
<map> <map>
<entry key="app/src/main/res/drawable/ic_close.xml" value="0.17135416666666667" /> <entry key="app/src/main/res/drawable/ic_close.xml" value="0.17135416666666667" />
<entry key="app/src/main/res/drawable/ic_play.xml" value="0.17135416666666667" /> <entry key="app/src/main/res/drawable/ic_play.xml" value="0.17135416666666667" />
<entry key="app/src/main/res/drawable/ic_search2.xml" value="0.17135416666666667" />
<entry key="app/src/main/res/layout-land/fragment_player.xml" value="0.1" /> <entry key="app/src/main/res/layout-land/fragment_player.xml" value="0.1" />
<entry key="app/src/main/res/layout/activity_main.xml" value="0.1" /> <entry key="app/src/main/res/layout/activity_main.xml" value="0.1" />
<entry key="app/src/main/res/layout/activity_player.xml" value="0.1" /> <entry key="app/src/main/res/layout/activity_player.xml" value="0.1" />
@ -12,10 +13,12 @@
<entry key="app/src/main/res/layout/fragment_home.xml" value="0.16" /> <entry key="app/src/main/res/layout/fragment_home.xml" value="0.16" />
<entry key="app/src/main/res/layout/fragment_library.xml" value="0.11956521739130435" /> <entry key="app/src/main/res/layout/fragment_library.xml" value="0.11956521739130435" />
<entry key="app/src/main/res/layout/fragment_player.xml" value="0.1" /> <entry key="app/src/main/res/layout/fragment_player.xml" value="0.1" />
<entry key="app/src/main/res/layout/fragment_search.xml" value="0.25" />
<entry key="app/src/main/res/layout/fragment_subscriptions.xml" value="0.1" /> <entry key="app/src/main/res/layout/fragment_subscriptions.xml" value="0.1" />
<entry key="app/src/main/res/layout/styled_quality_list.xml" value="0.15520833333333334" /> <entry key="app/src/main/res/layout/styled_quality_list.xml" value="0.15520833333333334" />
<entry key="app/src/main/res/layout/styled_quality_list_item.xml" value="0.15520833333333334" /> <entry key="app/src/main/res/layout/styled_quality_list_item.xml" value="0.15520833333333334" />
<entry key="app/src/main/res/layout/trending_row.xml" value="0.33" /> <entry key="app/src/main/res/layout/trending_row.xml" value="0.33" />
<entry key="app/src/main/res/menu/action_bar.xml" value="0.2" />
<entry key="app/src/main/res/menu/bottom_menu.xml" value="0.15520833333333334" /> <entry key="app/src/main/res/menu/bottom_menu.xml" value="0.15520833333333334" />
<entry key="app/src/main/res/xml-land/player_scene.xml" value="0.13139329805996472" /> <entry key="app/src/main/res/xml-land/player_scene.xml" value="0.13139329805996472" />
<entry key="app/src/main/res/xml/network_security_config.xml" value="0.15520833333333334" /> <entry key="app/src/main/res/xml/network_security_config.xml" value="0.15520833333333334" />

View File

@ -50,5 +50,6 @@ dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-jackson:2.9.0' implementation 'com.squareup.retrofit2:converter-jackson:2.9.0'
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.13.0'
} }

View File

@ -3,23 +3,51 @@ package xyz.btcland.libretube
import android.content.res.Configuration import android.content.res.Configuration
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle import android.os.Bundle
import android.view.Menu
import android.view.MenuItem
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.constraintlayout.motion.widget.MotionLayout import androidx.constraintlayout.motion.widget.MotionLayout
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.Navigation
import com.google.android.material.bottomnavigation.BottomNavigationView import com.google.android.material.bottomnavigation.BottomNavigationView
import androidx.navigation.findNavController import androidx.navigation.findNavController
import androidx.navigation.ui.NavigationUI.onNavDestinationSelected
import androidx.navigation.ui.setupWithNavController import androidx.navigation.ui.setupWithNavController
import com.google.android.exoplayer2.ExoPlayer import com.google.android.exoplayer2.ExoPlayer
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
lateinit var exoPlayer:ExoPlayer lateinit var bottomNavigationView: BottomNavigationView
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main) setContentView(R.layout.activity_main)
val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottomNav) bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottomNav)
val navController = findNavController(R.id.fragment) val navController = findNavController(R.id.fragment)
bottomNavigationView.setupWithNavController(navController) bottomNavigationView.setupWithNavController(navController)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId){
R.id.action_search -> {
val navController = findNavController(R.id.fragment)
navController.popBackStack()
navController.navigate(R.id.searchFragment)
//bottomNavigationView.clearFocus()
//val navController = findNavController(R.id.fragment)
//navController.navigate(R.id.searchFragment)
//navController.navigate(R.id.home2)
true
}
R.id.action_settings -> {
true
}
else -> {
super.onOptionsItemSelected(item)
}
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.action_bar,menu)
return true
} }
override fun onConfigurationChanged(newConfig: Configuration) { override fun onConfigurationChanged(newConfig: Configuration) {

View File

@ -12,4 +12,13 @@ interface PipedApi {
@GET("streams/{videoId}") @GET("streams/{videoId}")
suspend fun getStreams(@Path("videoId") videoId: String): Streams suspend fun getStreams(@Path("videoId") videoId: String): Streams
@GET("search")
suspend fun getSearchResults(
@Query("q") searchQuery: String,
@Query("filter") filer: String
): List<StreamItem>
@GET("suggestions")
suspend fun getSuggestions(@Query("query") query: String): List<String>
} }

View File

@ -230,6 +230,7 @@ class PlayerFragment : Fragment() {
override fun onStop() { override fun onStop() {
super.onStop() super.onStop()
try { try {
(activity as MainActivity).supportActionBar?.show()
exoPlayer.stop() exoPlayer.stop()
}catch (e: Exception){} }catch (e: Exception){}
@ -256,135 +257,7 @@ class PlayerFragment : Fragment() {
} }
private fun fetchJson(view: View) { private fun fetchJson(view: View) {
//val client = OkHttpClient()
fun run() { fun run() {
/* val request = Request.Builder()
.url("http://piped-api.alefvanoon.xyz/streams/$videoId")
.build()
*//* val retrofit = Retrofit.Builder()
.baseUrl("http://piped-api.alefvanoon.xyz/")
.addConverterFactory(JacksonConverterFactory.create())
.build()
val videoInPlayer2 = retrofit.create(vidVid::class.java).vidIn(videoId)*//*
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
e.printStackTrace()
}
override fun onResponse(call: Call, response: Response) {
response.use {
if (!response.isSuccessful) throw IOException("Unexpected code $response")
val body = response.body!!.string()
println(body)
val gson = GsonBuilder().create()
val videoInPlayer = gson.fromJson(body, VideoInPlayer::class.java)
var videosNameArray: Array<CharSequence> = arrayOf()
videosNameArray += "HLS"
for (vid in videoInPlayer.videoStreams){
val name = vid.quality +" "+ vid.format
videosNameArray += name
}
runOnUiThread {
var subtitle = mutableListOf<SubtitleConfiguration>()
if(videoInPlayer.subtitles.isNotEmpty()){
subtitle?.add(SubtitleConfiguration.Builder(videoInPlayer.subtitles[0].url.toUri())
.setMimeType(videoInPlayer.subtitles[0].mimeType) // The correct MIME type (required).
.setLanguage(videoInPlayer.subtitles[0].code) // The subtitle language (optional).
.build())}
val mediaItem: MediaItem = MediaItem.Builder()
.setUri(videoInPlayer.hls)
.setSubtitleConfigurations(subtitle)
.build()
exoPlayer = ExoPlayer.Builder(view.context)
.build()
exoPlayerView.setShowSubtitleButton(true)
exoPlayerView.setShowNextButton(false)
exoPlayerView.setShowPreviousButton(false)
//exoPlayerView.controllerShowTimeoutMs = 1500
exoPlayerView.controllerHideOnTouch = true
exoPlayerView.player = exoPlayer
exoPlayer.setMediaItem(mediaItem)
///exoPlayer.getMediaItemAt(5)
exoPlayer.prepare()
exoPlayer.play()
view.findViewById<TextView>(R.id.title_textView).text = videoInPlayer.title
view.findViewById<ImageButton>(R.id.quality_select).setOnClickListener{
//Dialog for quality selection
val builder: AlertDialog.Builder? = activity?.let {
AlertDialog.Builder(it)
}
builder!!.setTitle(R.string.choose_quality_dialog)
.setItems(videosNameArray,
DialogInterface.OnClickListener { _, which ->
whichQuality = which
if(videoInPlayer.subtitles.isNotEmpty()) {
var subtitle =
mutableListOf<SubtitleConfiguration>()
subtitle?.add(
SubtitleConfiguration.Builder(videoInPlayer.subtitles[0].url.toUri())
.setMimeType(videoInPlayer.subtitles[0].mimeType) // The correct MIME type (required).
.setLanguage(videoInPlayer.subtitles[0].code) // The subtitle language (optional).
.build()
)
}
if(which==0){
val mediaItem: MediaItem = MediaItem.Builder()
.setUri(videoInPlayer.hls)
.setSubtitleConfigurations(subtitle)
.build()
exoPlayer.setMediaItem(mediaItem)
}else{
val dataSourceFactory: DataSource.Factory =
DefaultHttpDataSource.Factory()
val videoItem: MediaItem = MediaItem.Builder()
.setUri(videoInPlayer.videoStreams[which-1].url)
.setSubtitleConfigurations(subtitle)
.build()
val videoSource: MediaSource = DefaultMediaSourceFactory(dataSourceFactory)
.createMediaSource(videoItem)
var audioSource: MediaSource = DefaultMediaSourceFactory(dataSourceFactory)
.createMediaSource(fromUri(videoInPlayer.audioStreams[0].url))
if (videoInPlayer.videoStreams[which-1].quality=="720p" || videoInPlayer.videoStreams[which-1].quality=="1080p" || videoInPlayer.videoStreams[which-1].quality=="480p" ){
audioSource = ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(fromUri(videoInPlayer.audioStreams[getMostBitRate(videoInPlayer.audioStreams)].url))
//println("fuckkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkitttttttttttttttttttttt")
}
val mergeSource: MediaSource = MergingMediaSource(videoSource,audioSource)
exoPlayer.setMediaSource(mergeSource)
}
view.findViewById<TextView>(R.id.quality_text).text=videosNameArray[which]
})
val dialog: AlertDialog? = builder?.create()
dialog?.show()
}
//Listener for play and pause icon change
exoPlayer!!.addListener(object : com.google.android.exoplayer2.Player.Listener {
override fun onPlayerStateChanged(playWhenReady: Boolean,playbackState: Int) {
if (playWhenReady && playbackState == Player.STATE_READY) {
// media actually playing
view.findViewById<ImageView>(R.id.play_imageView).setImageResource(R.drawable.ic_pause)
} else if (playWhenReady) {
// might be idle (plays after prepare()),
// buffering (plays when data available)
// or ended (plays when seek away from end)
view.findViewById<ImageView>(R.id.play_imageView).setImageResource(R.drawable.ic_play)
} else {
// player paused in any state
view.findViewById<ImageView>(R.id.play_imageView).setImageResource(R.drawable.ic_play)
}
}
})
}
}
}
})*/
lifecycleScope.launchWhenCreated { lifecycleScope.launchWhenCreated {
val response = try { val response = try {
RetrofitInstance.api.getStreams(videoId!!) RetrofitInstance.api.getStreams(videoId!!)

View File

@ -0,0 +1,123 @@
package xyz.btcland.libretube
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.AutoCompleteTextView
import androidx.lifecycle.lifecycleScope
import retrofit2.HttpException
import java.io.IOException
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [SearchFragment.newInstance] factory method to
* create an instance of this fragment.
*/
class SearchFragment : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_search, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val autoTextView = view.findViewById<AutoCompleteTextView>(R.id.autoCompleteTextView)
autoTextView.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(
s: CharSequence?,
start: Int,
count: Int,
after: Int
) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if(s!! != ""){
println(s.toString())
fetchSuggestions(s.toString(), autoTextView)
}
}
override fun afterTextChanged(s: Editable?) {
}
})
}
private fun fetchSuggestions(query: String, autoTextView: AutoCompleteTextView){
lifecycleScope.launchWhenCreated {
val response = try {
RetrofitInstance.api.getSuggestions(query)
} catch (e: IOException) {
println(e)
Log.e(TAG, "IOException, you might not have internet connection")
return@launchWhenCreated
} catch (e: HttpException) {
Log.e(TAG, "HttpException, unexpected response")
return@launchWhenCreated
}
val adapter = ArrayAdapter(context!!, android.R.layout.simple_list_item_1, response)
autoTextView.setAdapter(adapter)
}
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment SearchFragment.
*/
// TODO: Rename and change types and number of parameters
@JvmStatic
fun newInstance(param1: String, param2: String) =
SearchFragment().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
private fun Fragment?.runOnUiThread(action: () -> Unit) {
this ?: return
if (!isAdded) return // Fragment not attached to an Activity
activity?.runOnUiThread(action)
}
}

View File

@ -1,23 +0,0 @@
package xyz.btcland.libretube.obj;
import java.util.List;
public class Playlist {
public String name, thumbnailUrl, bannerUrl, nextpage, uploader, uploaderUrl, uploaderAvatar;
public int videos;
public List<StreamItem> relatedStreams;
public Playlist(String name, String thumbnailUrl, String bannerUrl, String nextpage, String uploader,
String uploaderUrl, String uploaderAvatar, int videos, List<StreamItem> relatedStreams) {
this.name = name;
this.thumbnailUrl = thumbnailUrl;
this.bannerUrl = bannerUrl;
this.nextpage = nextpage;
this.videos = videos;
this.uploader = uploader;
this.uploaderUrl = uploaderUrl;
this.uploaderAvatar = uploaderAvatar;
this.relatedStreams = relatedStreams;
}
}

View File

@ -0,0 +1,13 @@
package xyz.btcland.libretube.obj
data class Playlist(
var name: String? = null,
var thumbnailUrl: String? = null,
var bannerUrl: String? = null,
var nextpage: String? = null,
var uploader: String? = null,
var uploaderUrl: String? = null,
var uploaderAvatar: String? = null,
var videos: Int = 0,
var relatedStreams: List<StreamItem?>? = null,
)

View File

@ -1,5 +1,15 @@
package xyz.btcland.libretube.obj package xyz.btcland.libretube.obj
import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonTypeInfo
import xyz.btcland.libretube.obj.search.SearchChannel
import xyz.btcland.libretube.obj.search.SearchPlaylist
@JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION)
@JsonSubTypes(value =[
JsonSubTypes.Type(SearchChannel::class),
JsonSubTypes.Type(SearchPlaylist::class)
])
data class StreamItem( data class StreamItem(
var url: String?, var url: String?,
var title: String?, var title: String?,

View File

@ -0,0 +1,11 @@
package xyz.btcland.libretube.obj.search
data class SearchChannel(
var name: String? = null,
var thumbnail: String? = null,
var url: String? = null,
var description: String? = null,
var subscribers: Long? = -1,
var videos: Long? = -1,
var verified: Boolean? = null
)

View File

@ -0,0 +1,10 @@
package xyz.btcland.libretube.obj.search
data class SearchPlaylist(
var name: String? = null,
var thumbnail: String? = null,
var url: String? = null,
var uploaderName: String? =null,
var videos: Long = -1
)

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
</vector>

View File

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="35dp"
android:height="35dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M19.14,12.94c0.04,-0.3 0.06,-0.61 0.06,-0.94c0,-0.32 -0.02,-0.64 -0.07,-0.94l2.03,-1.58c0.18,-0.14 0.23,-0.41 0.12,-0.61l-1.92,-3.32c-0.12,-0.22 -0.37,-0.29 -0.59,-0.22l-2.39,0.96c-0.5,-0.38 -1.03,-0.7 -1.62,-0.94L14.4,2.81c-0.04,-0.24 -0.24,-0.41 -0.48,-0.41h-3.84c-0.24,0 -0.43,0.17 -0.47,0.41L9.25,5.35C8.66,5.59 8.12,5.92 7.63,6.29L5.24,5.33c-0.22,-0.08 -0.47,0 -0.59,0.22L2.74,8.87C2.62,9.08 2.66,9.34 2.86,9.48l2.03,1.58C4.84,11.36 4.8,11.69 4.8,12s0.02,0.64 0.07,0.94l-2.03,1.58c-0.18,0.14 -0.23,0.41 -0.12,0.61l1.92,3.32c0.12,0.22 0.37,0.29 0.59,0.22l2.39,-0.96c0.5,0.38 1.03,0.7 1.62,0.94l0.36,2.54c0.05,0.24 0.24,0.41 0.48,0.41h3.84c0.24,0 0.44,-0.17 0.47,-0.41l0.36,-2.54c0.59,-0.24 1.13,-0.56 1.62,-0.94l2.39,0.96c0.22,0.08 0.47,0 0.59,-0.22l1.92,-3.32c0.12,-0.22 0.07,-0.47 -0.12,-0.61L19.14,12.94zM12,15.6c-1.98,0 -3.6,-1.62 -3.6,-3.6s1.62,-3.6 3.6,-3.6s3.6,1.62 3.6,3.6S13.98,15.6 12,15.6z"/>
</vector>

View File

@ -0,0 +1,45 @@
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SearchFragment">
<AutoCompleteTextView
android:id="@+id/autoCompleteTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="7dp"
android:hint="@string/search_hint"
android:imeOptions="actionSearch"
android:inputType="text"
android:maxLines="1"
android:minHeight="48dp"
app:layout_constraintEnd_toStartOf="@+id/imageView_Search"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/imageView_Search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="7dp"
android:src="@drawable/ic_search2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/search_recycler"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/autoCompleteTextView" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:title="Search"
android:icon="@drawable/ic_search"
android:id="@+id/action_search"
app:showAsAction="always"
/>
<item android:title="Settings"
android:icon="@drawable/ic_settings"
android:id="@+id/action_settings"
app:showAsAction="ifRoom"
/>
</menu>

View File

@ -4,5 +4,6 @@
<item android:id="@+id/home2" android:title="Home" android:icon="@drawable/ic_home"/> <item android:id="@+id/home2" android:title="Home" android:icon="@drawable/ic_home"/>
<item android:id="@+id/subscriptions" android:title="Subscriptions" android:icon="@drawable/ic_subscriptions"/> <item android:id="@+id/subscriptions" android:title="Subscriptions" android:icon="@drawable/ic_subscriptions"/>
<item android:id="@+id/library" android:title="Library" android:icon="@drawable/ic_library"/> <item android:id="@+id/library" android:title="Library" android:icon="@drawable/ic_library"/>
<item android:id="@+id/searchFragment" android:visible="false"/>
</menu> </menu>

View File

@ -9,15 +9,32 @@
android:id="@+id/home2" android:id="@+id/home2"
android:name="xyz.btcland.libretube.Home" android:name="xyz.btcland.libretube.Home"
android:label="fragment_home" android:label="fragment_home"
tools:layout="@layout/fragment_home" /> tools:layout="@layout/fragment_home" >
<action
android:id="@+id/action_home2_to_searchFragment"
app:destination="@id/searchFragment" />
</fragment>
<fragment <fragment
android:id="@+id/subscriptions" android:id="@+id/subscriptions"
android:name="xyz.btcland.libretube.Subscriptions" android:name="xyz.btcland.libretube.Subscriptions"
android:label="fragment_subscriptions" android:label="fragment_subscriptions"
tools:layout="@layout/fragment_subscriptions" /> tools:layout="@layout/fragment_subscriptions" >
<action
android:id="@+id/action_subscriptions_to_searchFragment"
app:destination="@id/searchFragment" />
</fragment>
<fragment <fragment
android:id="@+id/library" android:id="@+id/library"
android:name="xyz.btcland.libretube.Library" android:name="xyz.btcland.libretube.Library"
android:label="fragment_library" android:label="fragment_library"
tools:layout="@layout/fragment_library" /> tools:layout="@layout/fragment_library" >
<action
android:id="@+id/action_library_to_searchFragment"
app:destination="@id/searchFragment" />
</fragment>
<fragment
android:id="@+id/searchFragment"
android:name="xyz.btcland.libretube.SearchFragment"
android:label="fragment_search"
tools:layout="@layout/fragment_search" />
</navigation> </navigation>

View File

@ -1,6 +1,7 @@
<resources> <resources>
<string name="app_name">LibreTube</string> <string name="app_name">LibreTube</string>
<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string> <string name="hello_blank_fragment">Hello blank fragment</string>
<string name="choose_quality_dialog">Choose Quality:</string> <string name="choose_quality_dialog">Choose Quality:</string>
<string name="search_hint">Search</string>
</resources> </resources>