Merge branch 'develop' into 'master'

Release

See merge request sschueller/peertube!49
This commit is contained in:
Stefan Schüller 2022-01-01 18:48:39 +00:00
commit e35d25a292
7 changed files with 172 additions and 62 deletions

View File

@ -175,11 +175,11 @@ public class AccountActivity extends CommonActivity {
if (response.isSuccessful()) {
Account account = response.body();
String owner = MetaDataHelper.getOwnerString(account.getName(),
account.getHost(),
AccountActivity.this
String owner = MetaDataHelper.getOwnerString(account,
AccountActivity.this, true
);
// set view data
TextView ownerStringView = findViewById(R.id.account_owner_string);
ownerStringView.setText(owner);

View File

@ -94,15 +94,15 @@ public class ChannelAdapter extends RecyclerView.Adapter<ChannelAdapter.AccountV
holder.videoMeta.setText(
MetaDataHelper.getMetaString(videoList.get(position).getCreatedAt(),
videoList.get(position).getViews(),
context
context,
false
)
);
// set owner
holder.videoOwner.setText(
MetaDataHelper.getOwnerString(videoList.get(position).getAccount().getName(),
videoList.get(position).getAccount().getHost(),
context
MetaDataHelper.getOwnerString(videoList.get(position).getAccount(),
context, true
)
);

View File

@ -16,7 +16,9 @@
*/
package net.schueller.peertube.adapter
import android.app.AlertDialog
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.util.Log
import android.view.MenuItem
@ -39,10 +41,14 @@ import net.schueller.peertube.helper.MetaDataHelper.getDuration
import net.schueller.peertube.helper.MetaDataHelper.getMetaString
import net.schueller.peertube.helper.MetaDataHelper.getOwnerString
import com.mikepenz.iconics.Iconics.Builder
import net.schueller.peertube.R
import net.schueller.peertube.R.id
import net.schueller.peertube.R.menu
import net.schueller.peertube.databinding.*
import net.schueller.peertube.fragment.VideoMetaDataFragment
import net.schueller.peertube.helper.MetaDataHelper.getCreatorAvatar
import net.schueller.peertube.helper.MetaDataHelper.getCreatorString
import net.schueller.peertube.helper.MetaDataHelper.getTagsString
import net.schueller.peertube.intents.Intents
import net.schueller.peertube.model.*
import net.schueller.peertube.model.ui.VideoMetaViewItem
@ -55,7 +61,7 @@ import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import net.schueller.peertube.R
import net.schueller.peertube.helper.MetaDataHelper.isChannel
import net.schueller.peertube.network.GetUserService
@ -190,10 +196,26 @@ sealed class MultiViewRecyclerViewHolder(binding: ViewBinding) : RecyclerView.Vi
binding.videoDownloadWrapper.visibility = GONE
}
val account = video.account
// created at / views
binding.videoMeta.text = getMetaString(
video.createdAt,
video.views,
context,
true
)
// owner / creator
val displayNameAndHost = getOwnerString(video.account, context)
if (isChannel(video)) {
binding.videoBy.text = context.resources.getString(string.video_by_line, displayNameAndHost)
} else {
binding.videoBy.visibility = GONE
}
binding.videoOwner.text = getCreatorString(video, context)
// owner / creator Avatar
val avatar = account.avatar
val avatar = getCreatorAvatar(video, context)
if (avatar != null) {
val baseUrl = APIUrlHelper.getUrl(context)
val avatarPath = avatar.path
@ -201,22 +223,25 @@ sealed class MultiViewRecyclerViewHolder(binding: ViewBinding) : RecyclerView.Vi
.load(baseUrl + avatarPath)
.into(binding.avatar)
}
// created at / views
binding.videoMeta.text = getMetaString(
video.createdAt,
video.views,
context!!
)
// owner / creator
binding.videoOwner.text = getOwnerString(
video.account.name,
video.account.host,
context
)
// videoOwnerSubscribers
binding.videoOwnerSubscribers.text = video.account.followersCount.toString()
binding.videoOwnerSubscribers.text = context.resources.getQuantityString(R.plurals.video_channel_subscribers, video.channel.followersCount, video.channel.followersCount)
// video owner click
binding.videoCreatorInfo.setOnClickListener {
val intent = Intent(context, AccountActivity::class.java)
intent.putExtra(VideoListActivity.EXTRA_ACCOUNTDISPLAYNAME, displayNameAndHost)
context.startActivity(intent)
}
// avatar click
binding.avatar.setOnClickListener {
val intent = Intent(context, AccountActivity::class.java)
intent.putExtra(Companion.EXTRA_ACCOUNTDISPLAYNAME, displayNameAndHost)
context.startActivity(intent)
}
// get subscription status
@ -231,7 +256,7 @@ sealed class MultiViewRecyclerViewHolder(binding: ViewBinding) : RecyclerView.Vi
// {"video.channel.name + "@" + video.channel.host":true}
if (response.body()?.get(video.channel.name + "@" + video.channel.host)!!.asBoolean) {
binding.videoOwnerSubscribeButton.setText(string.unsubscribe)
isSubscribed = true;
isSubscribed = true
} else {
binding.videoOwnerSubscribeButton.setText(string.subscribe)
}
@ -244,6 +269,7 @@ sealed class MultiViewRecyclerViewHolder(binding: ViewBinding) : RecyclerView.Vi
}
// TODO: update subscriber count
binding.videoOwnerSubscribeButton.setOnClickListener {
if (Session.getInstance().isLoggedIn) {
if (!isSubscribed) {
@ -265,6 +291,11 @@ sealed class MultiViewRecyclerViewHolder(binding: ViewBinding) : RecyclerView.Vi
}
})
} else {
AlertDialog.Builder(context)
.setTitle(context.getString(string.video_sub_del_alert_title))
.setMessage(context.getString(string.video_sub_del_alert_msg))
.setPositiveButton(android.R.string.ok) { _: DialogInterface?, _: Int ->
// Yes
val payload = video.channel.name + "@" + video.channel.host
val call = userService.unsubscribe(payload)
call.enqueue(object : Callback<ResponseBody?> {
@ -282,6 +313,12 @@ sealed class MultiViewRecyclerViewHolder(binding: ViewBinding) : RecyclerView.Vi
}
})
}
.setNegativeButton(android.R.string.cancel) { _: DialogInterface?, _: Int ->
// No
}
.setIcon(android.R.drawable.ic_dialog_alert)
.show()
}
} else {
Toast.makeText(
context,
@ -337,7 +374,7 @@ sealed class MultiViewRecyclerViewHolder(binding: ViewBinding) : RecyclerView.Vi
.into(binding.thumb)
// Avatar
val avatar: Avatar? = video.account.avatar
val avatar = getCreatorAvatar(video, context)
if (avatar != null) {
val avatarPath = avatar.path
Picasso.get()
@ -364,12 +401,8 @@ sealed class MultiViewRecyclerViewHolder(binding: ViewBinding) : RecyclerView.Vi
)
// set owner
val displayNameAndHost = getOwnerString(
video.account.name,
video.account.host,
context
)
binding.videoOwner.text = displayNameAndHost
val displayNameAndHost = getOwnerString(video.account, context, true)
binding.videoOwner.text = getCreatorString(video, context, true)
// video owner click
binding.videoOwner.setOnClickListener {

View File

@ -18,31 +18,91 @@ package net.schueller.peertube.helper
import android.content.Context
import android.text.format.DateUtils
import net.schueller.peertube.R
import net.schueller.peertube.R.string
import net.schueller.peertube.model.Account
import net.schueller.peertube.model.Avatar
import net.schueller.peertube.model.Video
import org.ocpsoft.prettytime.PrettyTime
import java.util.Date
import java.util.Locale
import kotlin.math.absoluteValue
object MetaDataHelper {
@JvmStatic
fun getMetaString(getCreatedAt: Date, viewCount: Int, context: Context): String {
fun getMetaString(getCreatedAt: Date, viewCount: Int, context: Context, reversed: Boolean = false): String {
// Compatible with SDK 21+
val currentLanguage = Locale.getDefault().displayLanguage
val p = PrettyTime(currentLanguage)
val relativeTime = p.format(Date(getCreatedAt.time))
return relativeTime +
return if (reversed) {
viewCount.toString() +
context.resources.getString(string.meta_data_views) +
context.resources.getString(string.meta_data_seperator) +
relativeTime
} else {
relativeTime +
context.resources.getString(string.meta_data_seperator) +
viewCount + context.resources.getString(string.meta_data_views)
}
}
fun getTagsString(video: Video): String {
return if (video.tags.isNotEmpty()) {
" #" + video.tags.joinToString(" #", "", "", 3, "")
} else {
" "
}
}
@JvmStatic
fun getOwnerString(accountName: String, serverHost: String, context: Context): String {
return accountName +
context.resources.getString(string.meta_data_owner_seperator) +
serverHost
fun getCreatorString(video: Video, context: Context, fqdn: Boolean = false): String {
return if (isChannel(video)) {
if (!fqdn) {
video.channel.displayName
} else {
getConcatFqdnString(video.channel.name, video.channel.host, context)
}
} else {
getOwnerString(video.account, context, fqdn)
}
}
@JvmStatic
fun getOwnerString(account: Account, context: Context, fqdn: Boolean = true): String {
return if (!fqdn) {
account.name
} else {
getConcatFqdnString(account.name, account.host, context)
}
}
private fun getConcatFqdnString(user: String, host: String, context: Context): String {
return context.resources.getString(string.video_owner_fqdn_line, user, host)
}
@JvmStatic
fun getCreatorAvatar(video: Video, context: Context): Avatar? {
return if (isChannel(video)) {
if (video.channel.avatar == null) {
video.account.avatar
} else {
video.channel.avatar
}
} else {
video.account.avatar
}
}
@JvmStatic
fun isChannel(video: Video): Boolean {
// c285b523-d688-43c5-a9ad-f745ff09bbd1
return !video.channel.name.matches("[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}".toRegex())
}
@JvmStatic
fun getDuration(duration: Long?): String {

View File

@ -13,6 +13,7 @@
<!-- Video Title Block -->
<RelativeLayout
android:background="?android:selectableItemBackground"
android:id="@+id/video_title_block"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@ -331,20 +332,20 @@
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/avatar"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:contentDescription="@string/video_row_account_avatar"
android:paddingStart="12dp"
android:paddingTop="12dp"
android:paddingEnd="12dp" />
android:paddingStart="6dp"
android:paddingEnd="6dp" />
<LinearLayout
android:id="@+id/video_creator_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="12dp"
android:layout_marginStart="6dp"
android:layout_toEndOf="@+id/avatar"
android:orientation="vertical">
@ -354,6 +355,13 @@
android:layout_height="wrap_content"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Subhead" />
<TextView
android:id="@+id/videoBy"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="3dp"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Caption" />
<TextView
android:id="@+id/videoOwnerSubscribers"
android:layout_width="wrap_content"
@ -367,11 +375,13 @@
android:id="@+id/videoOwnerSubscribeButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginTop="0dp"
android:layout_marginEnd="0dp"
android:gravity="end"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:text=""
android:textAppearance="@style/Base.TextAppearance.AppCompat.Button" />

View File

@ -58,7 +58,6 @@
<string name="video_download_icon" translatable="false">{faw-download}</string>
<string name="video_save_icon" translatable="false">{faw-save}</string>
<string name="meta_data_owner_seperator" translatable="false">\@</string>
<string name="meta_data_seperator" translatable="false">\u0020-\u0020</string>
<string name="title_activity_video_play" translatable="false">VideoPlayActivity</string>

View File

@ -376,4 +376,12 @@
<string name="subscribe">Subscribe</string>
<string name="unsubscribe">Unsubscribe</string>
<string name="video_comments_title">Comments</string>
<plurals name="video_channel_subscribers">
<item quantity="one">%1$d subscriber</item>
<item quantity="other">%1$d subscribers</item>
</plurals>
<string name="video_by_line">By %1$s</string>
<string name="video_owner_fqdn_line">%1$s@%2$s</string>
<string name="video_sub_del_alert_title">Unsubscribe</string>
<string name="video_sub_del_alert_msg">Are you sure you would like to unsubscribe?</string>
</resources>