channel fragment

This commit is contained in:
rimthekid 2022-02-04 22:55:05 +04:00
parent 4b61871e74
commit 42760f76c2
14 changed files with 242 additions and 66 deletions

View File

@ -0,0 +1,82 @@
package com.github.libretube
import android.os.Bundle
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.lifecycle.lifecycleScope
import com.github.libretube.adapters.TrendingAdapter
import com.squareup.picasso.Picasso
import retrofit2.HttpException
import java.io.IOException
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
/**
* A simple [Fragment] subclass.
* Use the [ChannelFragment.newInstance] factory method to
* create an instance of this fragment.
*/
class ChannelFragment : Fragment() {
// TODO: Rename and change types of parameters
private var channel_id: String? = null
private val TAG = "ChannelFragment"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
channel_id = it.getString("channel_id")
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_channel, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
channel_id = channel_id!!.replace("/channel/","")
view.findViewById<TextView>(R.id.channel_name).text=channel_id
fetchChannel(view)
}
private fun fetchChannel(view: View){
fun run() {
lifecycleScope.launchWhenCreated {
val response = try {
RetrofitInstance.api.getChannel(channel_id!!)
}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
}
runOnUiThread {
view.findViewById<TextView>(R.id.channel_name).text=response.name
view.findViewById<TextView>(R.id.channel_subs).text=response.subscriberCount.videoViews() + " subscribers"
view.findViewById<TextView>(R.id.channel_description).text=response.description
val bannerImage = view.findViewById<ImageView>(R.id.channel_banner)
val channelImage = view.findViewById<ImageView>(R.id.channel_image)
Picasso.get().load(response.bannerUrl).into(bannerImage)
Picasso.get().load(response.avatarUrl).into(channelImage)
}
}
}
run()
}
private fun Fragment?.runOnUiThread(action: () -> Unit) {
this ?: return
if (!isAdded) return // Fragment not attached to an Activity
activity?.runOnUiThread(action)
}
}

View File

@ -21,7 +21,7 @@ import java.io.IOException
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1" private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2" private const val ARG_PARAM2 = "param2"
const val TAG = "HomeFragment"
/** /**
* A simple [Fragment] subclass. * A simple [Fragment] subclass.
* Use the [Home.newInstance] factory method to * Use the [Home.newInstance] factory method to
@ -31,7 +31,7 @@ class Home : Fragment() {
// TODO: Rename and change types of parameters // TODO: Rename and change types of parameters
private var param1: String? = null private var param1: String? = null
private var param2: String? = null private var param2: String? = null
private val TAG = "HomeFragment"
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
arguments?.let { arguments?.let {

View File

@ -1,5 +1,6 @@
package com.github.libretube package com.github.libretube
import com.github.libretube.obj.Channel
import retrofit2.http.GET import retrofit2.http.GET
import retrofit2.http.Path import retrofit2.http.Path
import retrofit2.http.Query import retrofit2.http.Query
@ -22,4 +23,7 @@ interface PipedApi {
@GET("suggestions") @GET("suggestions")
suspend fun getSuggestions(@Query("query") query: String): List<String> suspend fun getSuggestions(@Query("query") query: String): List<String>
@GET("channel/{channelId}")
suspend fun getChannel(@Path("channelId") channelId: String): Channel
} }

View File

@ -51,6 +51,7 @@ import android.text.Html
import android.util.Log import android.util.Log
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.os.bundleOf
import androidx.core.text.PrecomputedTextCompat import androidx.core.text.PrecomputedTextCompat
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
@ -88,6 +89,7 @@ private const val ARG_PARAM2 = "param2"
*/ */
class PlayerFragment : Fragment() { class PlayerFragment : Fragment() {
// TODO: Rename and change types of parameters // TODO: Rename and change types of parameters
private val TAG = "PlayerFragment"
private var videoId: String? = null private var videoId: String? = null
private var param2: String? = null private var param2: String? = null
private var lastProgress: Float = 0.toFloat() private var lastProgress: Float = 0.toFloat()
@ -267,7 +269,7 @@ class PlayerFragment : Fragment() {
lifecycleScope.launchWhenCreated { lifecycleScope.launchWhenCreated {
val response = try { val response = try {
RetrofitInstance.api.getStreams(videoId!!) RetrofitInstance.api.getStreams(videoId!!)
}catch(e: IOException) { } catch(e: IOException) {
println(e) println(e)
Log.e(TAG, "IOException, you might not have internet connection") Log.e(TAG, "IOException, you might not have internet connection")
return@launchWhenCreated return@launchWhenCreated
@ -383,6 +385,14 @@ class PlayerFragment : Fragment() {
val channelImage = view.findViewById<ImageView>(R.id.player_channelImage) val channelImage = view.findViewById<ImageView>(R.id.player_channelImage)
Picasso.get().load(response.uploaderAvatar).into(channelImage) Picasso.get().load(response.uploaderAvatar).into(channelImage)
view.findViewById<TextView>(R.id.player_channelName).text=response.uploader view.findViewById<TextView>(R.id.player_channelName).text=response.uploader
view.findViewById<RelativeLayout>(R.id.player_channel).setOnClickListener {
val activity = view.context as MainActivity
val bundle = bundleOf("channel_id" to response.uploaderUrl)
activity.navController.navigate(R.id.channel,bundle)
activity.findViewById<MotionLayout>(R.id.mainMotionLayout).transitionToEnd()
view.findViewById<MotionLayout>(R.id.playerMotionLayout).transitionToEnd()
}
} }
} }

View File

@ -32,6 +32,8 @@ private const val ARG_PARAM2 = "param2"
*/ */
class SearchFragment : Fragment() { class SearchFragment : Fragment() {
// TODO: Rename and change types of parameters // TODO: Rename and change types of parameters
private val TAG = "SearchFragment"
private var param1: String? = null private var param1: String? = null
private var param2: String? = null private var param2: String? = null
@ -96,7 +98,7 @@ class SearchFragment : Fragment() {
Log.e(TAG, "HttpException, unexpected response") Log.e(TAG, "HttpException, unexpected response")
return@launchWhenCreated return@launchWhenCreated
} }
val adapter = ArrayAdapter(context!!, android.R.layout.simple_list_item_1, response) val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_list_item_1, response)
autoTextView.setAdapter(adapter) autoTextView.setAdapter(adapter)
} }
} }

View File

@ -10,7 +10,9 @@ import android.widget.TextView
import android.widget.VideoView import android.widget.VideoView
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.os.bundleOf
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.MainActivity
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import com.github.libretube.PlayerFragment import com.github.libretube.PlayerFragment
import com.github.libretube.R import com.github.libretube.R
@ -83,6 +85,11 @@ class CustomViewHolder1(private val v: View): RecyclerView.ViewHolder(v){
channelName.text = item.name channelName.text = item.name
val channelViews = v.findViewById<TextView>(R.id.search_views) val channelViews = v.findViewById<TextView>(R.id.search_views)
channelViews.text = item.subscribers.videoViews() + "subscribers • "+ item.videos + " videos" channelViews.text = item.subscribers.videoViews() + "subscribers • "+ item.videos + " videos"
v.setOnClickListener {
val activity = v.context as MainActivity
val bundle = bundleOf("channel_id" to item.url)
activity.navController.navigate(R.id.channel,bundle)
}
//todo sub button //todo sub button
} }
private fun bindPlaylist(item: SearchItem) { private fun bindPlaylist(item: SearchItem) {

View File

@ -7,7 +7,9 @@ import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.os.bundleOf
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.github.libretube.MainActivity
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import com.github.libretube.PlayerFragment import com.github.libretube.PlayerFragment
import com.github.libretube.R import com.github.libretube.R
@ -32,8 +34,9 @@ class TrendingAdapter(private val videoFeed: List<StreamItem>): RecyclerView.Ada
val thumbnailImage = holder.v.findViewById<ImageView>(R.id.thumbnail) val thumbnailImage = holder.v.findViewById<ImageView>(R.id.thumbnail)
val channelImage = holder.v.findViewById<ImageView>(R.id.channel_image) val channelImage = holder.v.findViewById<ImageView>(R.id.channel_image)
channelImage.setOnClickListener{ channelImage.setOnClickListener{
println("channel clicked") val activity = holder.v.context as MainActivity
//TODO val bundle = bundleOf("channel_id" to trending.uploaderUrl)
activity.navController.navigate(R.id.channel, bundle)
} }
Picasso.get().load(trending.thumbnail).into(thumbnailImage) Picasso.get().load(trending.thumbnail).into(thumbnailImage)
Picasso.get().load(trending.uploaderAvatar).into(channelImage) Picasso.get().load(trending.uploaderAvatar).into(channelImage)

View File

@ -1,23 +0,0 @@
package com.github.libretube.obj;
import java.util.List;
public class Channel {
public String id, name, avatarUrl, bannerUrl, description, nextpage;
public long subscriberCount;
public boolean verified;
public List<StreamItem> relatedStreams;
public Channel(String id, String name, String avatarUrl, String bannerUrl, String description, long subscriberCount,
boolean verified, String nextpage, List<StreamItem> relatedStreams) {
this.id = id;
this.name = name;
this.avatarUrl = avatarUrl;
this.bannerUrl = bannerUrl;
this.description = description;
this.subscriberCount = subscriberCount;
this.verified = verified;
this.nextpage = nextpage;
this.relatedStreams = relatedStreams;
}
}

View File

@ -0,0 +1,13 @@
package com.github.libretube.obj
data class Channel(
var id: String? = null,
var name: String? = null,
var avatarUrl: String? = null,
var bannerUrl: String? = null,
var description: String? = null,
var nextpage: String? = null,
var subscriberCount: Long = 0,
var verified: Boolean = false,
var relatedStreams: List<StreamItem?>? = null
)

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ChannelFragment">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/channel_banner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/channel_image"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_horizontal"
/>
<TextView
android:id="@+id/channel_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Mia Plays"
android:textSize="20sp"
android:textStyle="bold" />
<Button
android:id="@+id/channel_subscribe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="@android:color/transparent"
android:text="@string/subscribe"
android:textColor="@color/colorPrimary"
/>
<TextView
android:id="@+id/channel_subs"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="@string/app_name"/>
<TextView
android:id="@+id/channel_description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text=""
android:textAlignment="center"
android:padding="8dp"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/channel_recView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="false" />
</RelativeLayout>
</LinearLayout>
</ScrollView>

View File

@ -146,6 +146,7 @@
</LinearLayout> </LinearLayout>
<RelativeLayout <RelativeLayout
android:id="@+id/player_channel"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
@ -176,7 +177,7 @@
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:background="@android:color/transparent" android:background="@android:color/transparent"
android:text="SUBSCRIBE" android:text="@string/subscribe"
android:textColor="@color/colorPrimary" /> android:textColor="@color/colorPrimary" />
</RelativeLayout> </RelativeLayout>

View File

@ -14,8 +14,9 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical" android:orientation="vertical"
app:layout_constraintGuide_percent=".5"/> app:layout_constraintGuide_percent=".5"/>
<ImageView <com.google.android.material.card.MaterialCardView
android:id="@+id/search_thumbnail" android:id="@+id/card_playlist"
app:cardCornerRadius="8dp"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
@ -24,42 +25,42 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" app:layout_constraintVertical_bias="0.0"
app:layout_constraintEnd_toStartOf="@+id/guideline" app:layout_constraintEnd_toStartOf="@+id/guideline">
<ImageView
android:id="@+id/search_thumbnail"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:srcCompat="@tools:sample/backgrounds/scenic" /> tools:srcCompat="@tools:sample/backgrounds/scenic" />
<RelativeLayout
android:layout_width="100dp"
android:layout_height="match_parent"
android:layout_gravity="right"
android:background="#CC000000"
>
<RelativeLayout <TextView
android:layout_width="100dp" android:id="@+id/search_playlist_number"
android:layout_height="0dp" android:layout_width="wrap_content"
android:background="#CC000000" android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent" android:text="10"
app:layout_constraintEnd_toStartOf="@+id/guideline" android:textColor="#ECE4E4"
app:layout_constraintHorizontal_bias="1.0" android:layout_centerVertical="true"
app:layout_constraintStart_toStartOf="parent" android:layout_centerHorizontal="true"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintVertical_bias="0.0"
>
<TextView <ImageView
android:id="@+id/search_playlist_number" android:id="@+id/imageView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="10" app:srcCompat="@drawable/ic_playlist"
android:textColor="#ECE4E4" android:layout_centerHorizontal="true"
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_centerHorizontal="true" android:layout_below="@+id/search_playlist_number"
/> />
<ImageView </RelativeLayout>
android:id="@+id/imageView" </com.google.android.material.card.MaterialCardView>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_playlist"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_below="@+id/search_playlist_number"
/>
</RelativeLayout>
<TextView <TextView
android:id="@+id/search_description" android:id="@+id/search_description"
android:layout_width="0dp" android:layout_width="0dp"
@ -69,7 +70,7 @@
android:text="TextView" android:text="TextView"
android:textColor="#000000" android:textColor="#000000"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/search_thumbnail" app:layout_constraintStart_toEndOf="@+id/card_playlist"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<TextView <TextView
@ -79,7 +80,7 @@
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:text="TextView" android:text="TextView"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/search_thumbnail" app:layout_constraintStart_toEndOf="@+id/card_playlist"
app:layout_constraintTop_toBottomOf="@+id/search_description" /> app:layout_constraintTop_toBottomOf="@+id/search_description" />
<TextView <TextView

View File

@ -17,7 +17,7 @@
app:layout_constraintGuide_percent=".5"/> app:layout_constraintGuide_percent=".5"/>
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
android:id="@+id/card_search_thumbnail" android:id="@+id/card_search_thumbnail"
app:cardCornerRadius="20dp" app:cardCornerRadius="8dp"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"

View File

@ -36,4 +36,13 @@
android:name="com.github.libretube.SearchFragment" android:name="com.github.libretube.SearchFragment"
android:label="fragment_search" android:label="fragment_search"
tools:layout="@layout/fragment_search" /> tools:layout="@layout/fragment_search" />
<fragment
android:id="@+id/channel"
android:name="com.github.libretube.ChannelFragment"
android:label="channel"
tools:layout="@layout/fragment_channel" >
<argument
android:name="channel_id"
app:argType="string" />
</fragment>
</navigation> </navigation>