Feature/update video view

This commit is contained in:
Ivan Agosto 2024-03-28 02:54:14 +00:00
parent c500ba9aa4
commit 2de1bde4cd
20 changed files with 226 additions and 68 deletions

View File

@ -6,14 +6,13 @@ plugins {
}
android {
compileSdkVersion 30
compileSdkVersion 32
defaultConfig {
applicationId "org.libre.agosto.p2play"
minSdkVersion 26
//noinspection OldTargetApi
targetSdkVersion 28
versionCode 8
versionName "0.5.2"
targetSdkVersion 32
versionCode 9
versionName "0.6.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
@ -22,7 +21,6 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
buildToolsVersion '30.0.2'
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
@ -31,6 +29,7 @@ android {
checkReleaseBuilds false
abortOnError false
}
namespace 'org.libre.agosto.p2play'
}
dependencies {
@ -40,7 +39,7 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'com.google.android.material:material:1.6.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.5.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.libre.agosto.p2play">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
@ -13,10 +12,12 @@
android:supportsRtl="true"
android:theme="@style/Theme.P2play">
<activity android:name=".ChannelActivity"
android:theme="@style/Theme.P2play.NoActionBar" />
android:theme="@style/Theme.P2play.NoActionBar"
android:exported="false" />
<activity
android:name=".SplashActivity"
android:theme="@style/Theme.P2play.NoActionBar">
android:theme="@style/Theme.P2play.NoActionBar"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@ -25,22 +26,26 @@
</activity>
<activity
android:name=".HostActivity"
android:theme="@style/Theme.P2play.NoActionBar"/>
android:theme="@style/Theme.P2play.NoActionBar"
android:exported="false" />
<activity
android:name=".MainActivity"
android:theme="@style/Theme.P2play.NoActionBar" />
android:theme="@style/Theme.P2play.NoActionBar"
android:exported="false" />
<activity
android:name=".ReproductorActivity"
android:configChanges="orientation|screenSize"
android:hardwareAccelerated="true"
android:theme="@style/Theme.P2play.NoActionBar" />
<activity android:name=".LoginActivity" />
<activity android:name=".RegisterActivity" />
<activity android:name=".AboutActivity" />
android:theme="@style/Theme.P2play.NoActionBar"
android:exported="false" />
<activity android:name=".LoginActivity" android:exported="false" />
<activity android:name=".RegisterActivity" android:exported="false" />
<activity android:name=".AboutActivity" android:exported="false" />
<activity
android:name=".SettingsActivity"
android:label="@string/title_activity_settings"
android:theme="@style/Theme.P2play"/>
android:theme="@style/Theme.P2play"
android:exported="false"/>
</application>
</manifest>

View File

@ -50,8 +50,6 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
.setAction("Action", null).show()
} */
val toggle = ActionBarDrawerToggle(this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
drawer_layout.addDrawerListener(toggle)
toggle.syncState()
@ -376,6 +374,8 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
myMenu.findItem(R.id.action_logout).isVisible = true
}
} else {
nav_view.menu.findItem(R.id.ml).isVisible = false
}
}
@ -394,7 +394,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte
this.refresh()
ManagerSingleton.Toast(getString(R.string.logout_msg), this)
setSideData()
}
private fun loadMore(){

View File

@ -1,8 +1,6 @@
package org.libre.agosto.p2play
import android.annotation.SuppressLint
import android.app.Activity
import android.content.DialogInterface
import android.content.Intent
import android.content.pm.ActivityInfo
import android.graphics.Bitmap
@ -96,7 +94,7 @@ class ReproductorActivity : AppCompatActivity() {
userImg.setOnClickListener {
val intent = Intent(this, ChannelActivity::class.java)
intent.putExtra("channel", video.getAccount())
intent.putExtra("channel", video.getChannel())
startActivity(intent)
}
}
@ -105,7 +103,7 @@ class ReproductorActivity : AppCompatActivity() {
AsyncTask.execute {
if (Looper.myLooper() == null)
Looper.prepare()
val res = this._actions.subscribe(ManagerSingleton.token.token, video.getAccount())
val res = this._actions.subscribe(ManagerSingleton.token.token, video.getChannel())
if (res == 1) {
runOnUiThread {
ManagerSingleton.Toast(getString(R.string.subscribeMsg), this)
@ -119,7 +117,7 @@ class ReproductorActivity : AppCompatActivity() {
AsyncTask.execute {
if (Looper.myLooper() == null)
Looper.prepare()
val res = this._actions.unSubscribe(ManagerSingleton.token.token, video.getAccount())
val res = this._actions.unSubscribe(ManagerSingleton.token.token, video.getChannel())
if (res == 1) {
runOnUiThread {
ManagerSingleton.Toast(getString(R.string.unSubscribeMsg), this)

View File

@ -1,6 +1,7 @@
package org.libre.agosto.p2play.adapters
import android.content.Context
import android.content.Intent
import androidx.recyclerview.widget.RecyclerView
import android.text.Html
import android.view.LayoutInflater
@ -9,6 +10,7 @@ import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import com.squareup.picasso.Picasso
import kotlinx.android.synthetic.main.view_video.view.userImg
import org.libre.agosto.p2play.*
import org.libre.agosto.p2play.models.CommentaryModel
@ -42,6 +44,7 @@ class CommentariesAdapter(private val myDataset: ArrayList<CommentaryModel>) :
// create a new view
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.view_commentary, parent, false) as View
// set the view's size, margins, paddings and layout parameters
return ViewHolder(view)
}
@ -63,6 +66,12 @@ class CommentariesAdapter(private val myDataset: ArrayList<CommentaryModel>) :
holder.commentary.text = Html.fromHtml(myDataset[position].commentary)
// TODO: Support for view and account (is different than a video channel)
// holder.userImg.setOnClickListener {
// val intent = Intent(holder.context, ChannelActivity::class.java)
// intent.putExtra("channel", myDataset[position].getAccount())
// holder.context.startActivity(intent)
// }
}
// Return the size of your dataset (invoked by the layout manager)

View File

@ -10,6 +10,7 @@ import android.widget.ImageView
import android.widget.TextView
import com.squareup.picasso.Picasso
import org.libre.agosto.p2play.*
import org.libre.agosto.p2play.helpers.mapSeconds
import org.libre.agosto.p2play.models.VideoModel
import java.io.Serializable
@ -27,6 +28,8 @@ class VideosAdapter(private val myDataset: ArrayList<VideoModel>) :
val tittle: TextView
val description: TextView
val context: Context
val duration: TextView
val isLive: TextView
init {
// Define click listener for the ViewHolder's View
@ -35,6 +38,8 @@ class VideosAdapter(private val myDataset: ArrayList<VideoModel>) :
thumb = view.findViewById(R.id.thumb)
userImg = view.findViewById(R.id.userImg)
context = view.context
duration = view.findViewById(R.id.duration)
isLive = view.findViewById(R.id.isLive)
}
}
@ -52,16 +57,17 @@ class VideosAdapter(private val myDataset: ArrayList<VideoModel>) :
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.tittle.text = myDataset[position].name
holder.tittle.setOnClickListener {
this.launchChannelActivity(myDataset[position] as Serializable, holder.context)
}
Picasso.get().load("https://"+ManagerSingleton.url+myDataset[position].thumbUrl).into(holder.thumb)
holder.thumb.setOnClickListener {
val intent = Intent(holder.context, ReproductorActivity::class.java)
intent.putExtra("video", myDataset[position] as Serializable)
holder.context.startActivity(intent)
this.launchChannelActivity(myDataset[position] as Serializable, holder.context)
}
holder.userImg.setOnClickListener {
val intent = Intent(holder.context, ChannelActivity::class.java)
intent.putExtra("channel", myDataset[position].getAccount())
intent.putExtra("channel", myDataset[position].getChannel())
holder.context.startActivity(intent)
}
@ -71,20 +77,16 @@ class VideosAdapter(private val myDataset: ArrayList<VideoModel>) :
Picasso.get().load(R.drawable.default_avatar).into(holder.userImg)
val viewsText = holder.context.getString(R.string.view_text)
var timeText = holder.context.getString(R.string.timeSec_text)
var timeString = myDataset[position].duration.toString()
val seconds = myDataset[position].duration.toInt();
if(seconds > 60 && seconds < (60 * 60)){
timeText = holder.context.getString(R.string.timeMin_text)
timeString = (seconds / 60).toString() + ":" + (seconds % 60).toString()
}
else if(seconds > (60 * 60)){
timeText = holder.context.getString(R.string.timeHrs_text)
timeString = (seconds / 60 / 60).toString() + ":" + (seconds / 60 % 60).toString()
}
val timeString = mapSeconds(seconds)
holder.description.text = myDataset[position].username+" - "+myDataset[position].views+" "+viewsText+" - "+timeString+" "+timeText
holder.duration.text = timeString
holder.description.text = myDataset[position].username+" - "+myDataset[position].views+" "+viewsText
if (myDataset[position].isLive) {
holder.isLive.visibility = View.VISIBLE
}
}
// Return the size of your dataset (invoked by the layout manager)
@ -101,5 +103,9 @@ class VideosAdapter(private val myDataset: ArrayList<VideoModel>) :
notifyItemRangeInserted(lastPos, newItems.size)
}
private fun launchChannelActivity (data: Serializable, context: Context) {
val intent = Intent(context, ReproductorActivity::class.java)
intent.putExtra("video", data)
context.startActivity(intent)
}
}

View File

@ -10,8 +10,6 @@ import java.net.HttpURLConnection
import java.net.URL
open class Client {
protected fun _newCon(uri: String, method: String, token: String = ""): HttpURLConnection {
val url = URL("https://${ManagerSingleton.url}/api/v1/$uri")
val con = url.openConnection() as HttpURLConnection
@ -67,5 +65,4 @@ open class Client {
return keys
}
}

View File

@ -0,0 +1,20 @@
package org.libre.agosto.p2play.helpers
fun mapSeconds (inputSeconds: Int): String {
val seconds = (inputSeconds % 60)
var minutes = inputSeconds / 60
var hours = 0
if (minutes > 60) {
hours = minutes / 60
minutes = minutes % 60
}
var result = minutes.toString().padStart(2, '0') + ":" + seconds.toString().padStart(2, '0')
if (hours > 0) {
result = hours.toString().padStart(2, '0') + ":" + result
}
return result
}

View File

@ -11,7 +11,8 @@ class CommentaryModel (
var userImageUrl: String = "",
var commentary: String = "",
var userHost: String = "",
var replies: Int = 0
var replies: Int = 0,
var nameChannel: String = ""
) {
fun parseCommentary(data: JsonReader) {
data.beginObject()
@ -46,6 +47,7 @@ class CommentaryModel (
}
"uuid" -> this.userUuid = data.nextString()
"host" -> this.userHost = data.nextString()
"name" -> this.nameChannel = data.nextString()
else -> data.skipValue()
}
}
@ -56,4 +58,9 @@ class CommentaryModel (
}
data.endObject()
}
fun getAccount(): String {
return "$nameChannel@$userHost"
}
}

View File

@ -0,0 +1,25 @@
package org.libre.agosto.p2play.models
import android.util.JsonReader
class StreamingModel(
var playlistUrl: String = "",
var segmentsSha256Url: String = "",
// TODO: Download Files
) {
fun parse(data: JsonReader) {
data.beginObject()
while (data.hasNext()) {
val key = data.nextName()
when (key.toString()) {
"playlistUrl"->{
this.playlistUrl = data.nextString()
}
"segmentsSha256Url"->{
this.segmentsSha256Url = data.nextString()
}
else -> data.skipValue()
}
}
}
}

View File

@ -5,21 +5,23 @@ import android.util.JsonToken
import java.io.Serializable
class VideoModel(
var id: Int = 0,
var uuid: String = "",
var name: String = "",
var description: String = "",
var thumbUrl: String = "",
var userImageUrl: String = "",
var embedUrl: String = "",
var duration: Number = 0,
var username: String = "",
var views: Number = 0,
var userUuid: String = "",
var userHost: String = "",
var nameChannel: String = ""
var id: Int = 0,
var uuid: String = "",
var name: String = "",
var description: String = "",
var thumbUrl: String = "",
var userImageUrl: String = "",
var embedUrl: String = "",
var duration: Number = 0,
var username: String = "",
var views: Number = 0,
var userUuid: String = "",
var userHost: String = "",
var nameChannel: String = "",
var isLive: Boolean = false,
var streamingData: StreamingModel? = null
):Serializable {
fun getAccount(): String {
fun getChannel(): String {
return "$nameChannel@$userHost"
}
@ -55,6 +57,18 @@ class VideoModel(
"views"->{
this.views = data.nextInt()
}
"isLive"-> {
this.isLive = data.nextBoolean()
}
"streamingPlaylists"-> {
data.beginArray()
if (data.hasNext()) {
val streamingData = StreamingModel()
streamingData.parse(data)
this.streamingData = streamingData
}
data.endArray()
}
"channel"->{
data.beginObject()
while (data.hasNext()){

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="5dp" />
<!-- This is the border color -->
<!--- This is the background color -->
<solid android:color="@color/colorDislike" />
</shape>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="5dp" />
<!-- This is the border color -->
<!--- This is the background color -->
<solid android:color="?attr/colorSecondary" />
</shape>

View File

@ -14,11 +14,54 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/thumb"
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="230dp"
app:srcCompat="@android:drawable/ic_menu_gallery" />
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/thumb"
android:layout_width="match_parent"
android:layout_height="230dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@android:drawable/ic_menu_gallery" />
<TextView
android:id="@+id/isLive"
android:layout_width="65dp"
android:layout_height="19dp"
android:layout_marginStart="8dp"
android:layout_marginBottom="16dp"
android:background="@drawable/live_shape"
android:ems="10"
android:paddingHorizontal="3dp"
android:text="@string/is_live_video"
android:textAlignment="center"
android:textColor="@color/durationColor"
android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:visibility="invisible" />
<TextView
android:id="@+id/duration"
android:layout_width="65dp"
android:layout_height="19dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="16dp"
android:textColor="?attr/colorOnSecondary"
android:background="@drawable/round_text"
android:ems="10"
android:text="00:00"
android:paddingHorizontal="3dp"
android:textAlignment="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:layout_width="match_parent"

View File

@ -48,6 +48,7 @@
<string name="timeMin_text">minutos</string>
<string name="timeHrs_text">horas</string>
<string name="nav_header_title">Inicia session</string>
<string name="is_live_video">En vivo</string>
<!-- Toast msg -->
<string name="logout_msg">Te has desconectado</string>
<!-- End Main strings -->

View File

@ -10,6 +10,9 @@
<color name="colorLike">#FF3C9100</color>
<color name="colorDislike">#ec020e</color>
<color name="colorProfile">#262626</color>
<color name="durationBackground">#88000000</color>
<color name="durationColor">#ffffff</color>
<color name="seed">#f16805</color>
<color name="md_theme_light_primary">#9F4200</color>

View File

@ -9,7 +9,6 @@
<string name="charging">Loading…</string>
<!-- End Global string -->
<!-- Start About strings -->
<string name="aboutGitUrl" translatable="false">https://gitlab.com/agosto182/p2play/</string>
<string name="aboutGnuUrl" translatable="false">https://personaljournal.ca/p2play/</string>
@ -60,6 +59,7 @@
<string name="timeHrs_text">hours</string>
<string name="nav_header_title">Log In</string>
<string name="nav_header_subtitle" translatable="false">P2Play</string>
<string name="is_live_video">Live</string>
<!-- Toast msg -->
<string name="logout_msg">You are now disconnected</string>
<!-- End Main strings -->

View File

@ -1,13 +1,13 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.6.20'
ext.kotlin_version = '1.6.21'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.4.2'
classpath 'com.android.tools.build:gradle:8.3.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

View File

@ -9,6 +9,9 @@
org.gradle.jvmargs=-Xmx1536m
android.enableJetifier=true
android.useAndroidX=true
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit

View File

@ -1,6 +1,6 @@
#Mon Mar 18 13:17:32 CST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists