feat: activity view
This commit is contained in:
parent
55ad8dccad
commit
856deb7755
16 changed files with 945 additions and 6 deletions
|
@ -139,6 +139,9 @@
|
||||||
<activity
|
<activity
|
||||||
android:name=".settings.SettingsAboutActivity"
|
android:name=".settings.SettingsAboutActivity"
|
||||||
android:parentActivityName=".MainActivity" />
|
android:parentActivityName=".MainActivity" />
|
||||||
|
<activity
|
||||||
|
android:name=".home.StatusActivity"
|
||||||
|
android:parentActivityName=".MainActivity" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".settings.SettingsAccountActivity"
|
android:name=".settings.SettingsAccountActivity"
|
||||||
android:parentActivityName=".MainActivity" />
|
android:parentActivityName=".MainActivity" />
|
||||||
|
|
|
@ -1637,7 +1637,13 @@ Page(page:$page,perPage:50) {
|
||||||
force = true
|
force = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
suspend fun getStatus(
|
||||||
|
): FeedResponse? {
|
||||||
|
return executeQuery<FeedResponse>(
|
||||||
|
"""{Page(page:1,perPage:50){activities(isFollowing: true, type:MEDIA_LIST,sort:ID_DESC){__typename ... on TextActivity{id userId type replyCount text(asHtml:true)siteUrl isLocked isSubscribed likeCount isLiked isPinned createdAt user{id name bannerImage avatar{medium large}}replies{id userId activityId text(asHtml:true)likeCount isLiked createdAt user{id name bannerImage avatar{medium large}}likes{id name bannerImage avatar{medium large}}}likes{id name bannerImage avatar{medium large}}}... on ListActivity{id userId type replyCount status progress siteUrl isLocked isSubscribed likeCount isLiked isPinned createdAt user{id name bannerImage avatar{medium large}}media{id title{english romaji native userPreferred}bannerImage coverImage{extraLarge medium large}}replies{id userId activityId text(asHtml:true)likeCount isLiked createdAt user{id name bannerImage avatar{medium large}}likes{id name bannerImage avatar{medium large}}}likes{id name bannerImage avatar{medium large}}}... on MessageActivity{id recipientId messengerId type replyCount likeCount message(asHtml:true)isLocked isSubscribed isLiked isPrivate siteUrl createdAt recipient{id name bannerImage avatar{medium large}}messenger{id name bannerImage avatar{medium large}}replies{id userId activityId text(asHtml:true)likeCount isLiked createdAt user{id name bannerImage avatar{medium large}}likes{id name bannerImage avatar{medium large}}}likes{id name bannerImage avatar{medium large}}}}}}""",
|
||||||
|
force = true
|
||||||
|
)
|
||||||
|
}
|
||||||
suspend fun getUpcomingAnime(id: String): List<Media> {
|
suspend fun getUpcomingAnime(id: String): List<Media> {
|
||||||
val res = executeQuery<Query.MediaListCollection>(
|
val res = executeQuery<Query.MediaListCollection>(
|
||||||
"""{MediaListCollection(userId:$id,type:ANIME){lists{name entries{media{id,isFavourite,title{userPreferred,romaji}coverImage{medium}nextAiringEpisode{timeUntilAiring}}}}}}""",
|
"""{MediaListCollection(userId:$id,type:ANIME){lists{name entries{media{id,isFavourite,title{userPreferred,romaji}coverImage{medium}nextAiringEpisode{timeUntilAiring}}}}}}""",
|
||||||
|
|
|
@ -11,6 +11,8 @@ import ani.dantotsu.connections.discord.Discord
|
||||||
import ani.dantotsu.connections.mal.MAL
|
import ani.dantotsu.connections.mal.MAL
|
||||||
import ani.dantotsu.media.Media
|
import ani.dantotsu.media.Media
|
||||||
import ani.dantotsu.others.AppUpdater
|
import ani.dantotsu.others.AppUpdater
|
||||||
|
import ani.dantotsu.profile.User
|
||||||
|
import ani.dantotsu.profile.activity.ActivityItemBuilder
|
||||||
import ani.dantotsu.settings.saving.PrefManager
|
import ani.dantotsu.settings.saving.PrefManager
|
||||||
import ani.dantotsu.settings.saving.PrefName
|
import ani.dantotsu.settings.saving.PrefName
|
||||||
import ani.dantotsu.snackString
|
import ani.dantotsu.snackString
|
||||||
|
@ -100,6 +102,35 @@ class AnilistHomeViewModel : ViewModel() {
|
||||||
res["plannedManga"]?.let { mangaPlanned.postValue(it) }
|
res["plannedManga"]?.let { mangaPlanned.postValue(it) }
|
||||||
res["recommendations"]?.let { recommendation.postValue(it) }
|
res["recommendations"]?.let { recommendation.postValue(it) }
|
||||||
}
|
}
|
||||||
|
private val userStatus: MutableLiveData<ArrayList<User>> =
|
||||||
|
MutableLiveData<ArrayList<User>>(null)
|
||||||
|
|
||||||
|
fun getUserStatus(): LiveData<ArrayList<User>> = userStatus
|
||||||
|
|
||||||
|
suspend fun initUserStatus() {
|
||||||
|
Anilist.query.getStatus()?.data?.page?.activities?.let { activities ->
|
||||||
|
val groupedActivities = activities
|
||||||
|
.filterNot { it.userId == Anilist.userid }
|
||||||
|
.sortedByDescending { ActivityItemBuilder.getDateTime(it.createdAt) }
|
||||||
|
.groupBy { it.userId }
|
||||||
|
val userList = groupedActivities.mapNotNull { (_, activities) ->
|
||||||
|
val user = activities.firstOrNull()?.user
|
||||||
|
user?.let {
|
||||||
|
User(
|
||||||
|
it.id,
|
||||||
|
it.name ?: "",
|
||||||
|
it.avatar?.medium,
|
||||||
|
it.bannerImage,
|
||||||
|
activity = activities
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}.toMutableList()
|
||||||
|
userList.sortByDescending { user ->
|
||||||
|
user.activity.maxByOrNull { it.createdAt }?.createdAt
|
||||||
|
}
|
||||||
|
userStatus.postValue(ArrayList(userList))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun loadMain(context: FragmentActivity) {
|
suspend fun loadMain(context: FragmentActivity) {
|
||||||
Anilist.getSavedToken()
|
Anilist.getSavedToken()
|
||||||
|
|
|
@ -174,7 +174,7 @@ data class Media(
|
||||||
|
|
||||||
// Notes for site moderators
|
// Notes for site moderators
|
||||||
@SerialName("modNotes") var modNotes: String?,
|
@SerialName("modNotes") var modNotes: String?,
|
||||||
)
|
) : java.io.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class MediaTitle(
|
data class MediaTitle(
|
||||||
|
@ -189,7 +189,7 @@ data class MediaTitle(
|
||||||
|
|
||||||
// The currently authenticated users preferred title language. Default romaji for non-authenticated
|
// The currently authenticated users preferred title language. Default romaji for non-authenticated
|
||||||
@SerialName("userPreferred") var userPreferred: String,
|
@SerialName("userPreferred") var userPreferred: String,
|
||||||
)
|
): java.io.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
enum class MediaType {
|
enum class MediaType {
|
||||||
|
|
|
@ -69,7 +69,7 @@ data class User(
|
||||||
// The user's previously used names.
|
// The user's previously used names.
|
||||||
// @SerialName("previousNames") var previousNames: List<UserPreviousName>?,
|
// @SerialName("previousNames") var previousNames: List<UserPreviousName>?,
|
||||||
|
|
||||||
)
|
): java.io.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class UserOptions(
|
data class UserOptions(
|
||||||
|
|
|
@ -314,10 +314,37 @@ class HomeFragment : Fragment() {
|
||||||
binding.homeRecommendedEmpty,
|
binding.homeRecommendedEmpty,
|
||||||
binding.homeRecommended
|
binding.homeRecommended
|
||||||
)
|
)
|
||||||
|
binding.homeUserStatusContainer.visibility = View.VISIBLE
|
||||||
|
binding.homeUserStatusProgressBar.visibility = View.VISIBLE
|
||||||
|
binding.homeUserStatusRecyclerView.visibility = View.GONE
|
||||||
|
binding.homeUserStatus.visibility = View.INVISIBLE
|
||||||
|
model.getUserStatus().observe(viewLifecycleOwner) {
|
||||||
|
binding.homeUserStatusRecyclerView.visibility = View.GONE
|
||||||
|
if (it != null) {
|
||||||
|
if (it.isNotEmpty()) {
|
||||||
|
binding.homeUserStatusRecyclerView.adapter = UserStatus(it)
|
||||||
|
binding.homeUserStatusRecyclerView.layoutManager = LinearLayoutManager(
|
||||||
|
requireContext(),
|
||||||
|
LinearLayoutManager.HORIZONTAL,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
binding.homeUserStatusRecyclerView.visibility = View.VISIBLE
|
||||||
|
binding.homeUserStatusRecyclerView.layoutAnimation =
|
||||||
|
LayoutAnimationController(setSlideIn(), 0.25f)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
binding.homeUserStatusContainer.visibility = View.GONE
|
||||||
|
}
|
||||||
|
binding.homeUserStatus.visibility = View.VISIBLE
|
||||||
|
binding.homeUserStatus.startAnimation(setSlideUp())
|
||||||
|
binding.homeUserStatusProgressBar.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
binding.homeUserAvatarContainer.startAnimation(setSlideUp())
|
binding.homeUserAvatarContainer.startAnimation(setSlideUp())
|
||||||
|
|
||||||
model.empty.observe(viewLifecycleOwner) {
|
model.empty.observe(viewLifecycleOwner)
|
||||||
|
{
|
||||||
binding.homeDantotsuContainer.visibility = if (it == true) View.VISIBLE else View.GONE
|
binding.homeDantotsuContainer.visibility = if (it == true) View.VISIBLE else View.GONE
|
||||||
(binding.homeDantotsuIcon.drawable as Animatable).start()
|
(binding.homeDantotsuIcon.drawable as Animatable).start()
|
||||||
binding.homeDantotsuContainer.startAnimation(setSlideUp())
|
binding.homeDantotsuContainer.startAnimation(setSlideUp())
|
||||||
|
@ -348,7 +375,8 @@ class HomeFragment : Fragment() {
|
||||||
)
|
)
|
||||||
|
|
||||||
val live = Refresh.activity.getOrPut(1) { MutableLiveData(false) }
|
val live = Refresh.activity.getOrPut(1) { MutableLiveData(false) }
|
||||||
live.observe(viewLifecycleOwner) {
|
live.observe(viewLifecycleOwner)
|
||||||
|
{
|
||||||
if (it) {
|
if (it) {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
|
@ -362,6 +390,7 @@ class HomeFragment : Fragment() {
|
||||||
val homeLayoutShow: List<Boolean> =
|
val homeLayoutShow: List<Boolean> =
|
||||||
PrefManager.getVal(PrefName.HomeLayoutShow)
|
PrefManager.getVal(PrefName.HomeLayoutShow)
|
||||||
runBlocking {
|
runBlocking {
|
||||||
|
model.initUserStatus()
|
||||||
model.initHomePage()
|
model.initHomePage()
|
||||||
}
|
}
|
||||||
(array.indices).forEach { i ->
|
(array.indices).forEach { i ->
|
||||||
|
|
73
app/src/main/java/ani/dantotsu/home/StatusActivity.kt
Normal file
73
app/src/main/java/ani/dantotsu/home/StatusActivity.kt
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
package ani.dantotsu.home
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.view.updateLayoutParams
|
||||||
|
import ani.dantotsu.connections.anilist.api.Activity
|
||||||
|
import ani.dantotsu.databinding.ActivityStatusBinding
|
||||||
|
import ani.dantotsu.initActivity
|
||||||
|
import ani.dantotsu.others.getSerialized
|
||||||
|
import ani.dantotsu.themes.ThemeManager
|
||||||
|
import ani.dantotsu.home.status.data.StoryItem
|
||||||
|
import ani.dantotsu.home.status.listener.StoriesCallback
|
||||||
|
import ani.dantotsu.navBarHeight
|
||||||
|
import ani.dantotsu.profile.activity.ActivityItemBuilder
|
||||||
|
import ani.dantotsu.statusBarHeight
|
||||||
|
|
||||||
|
class StatusActivity : AppCompatActivity(), StoriesCallback {
|
||||||
|
private lateinit var activity: List<Activity>
|
||||||
|
private lateinit var binding: ActivityStatusBinding
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
ThemeManager(this).applyTheme()
|
||||||
|
initActivity(this)
|
||||||
|
binding = ActivityStatusBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
|
activity = intent.getSerialized("activity")!!
|
||||||
|
binding.root.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
|
topMargin = statusBarHeight
|
||||||
|
bottomMargin = navBarHeight
|
||||||
|
}
|
||||||
|
val storiesList = activity.map { StoryItem(
|
||||||
|
id = it.userId,
|
||||||
|
activityId = it.id,
|
||||||
|
mediaId = it.media?.id,
|
||||||
|
userName = it.user?.name,
|
||||||
|
userAvatar = it.user?.avatar?.large,
|
||||||
|
time = ActivityItemBuilder.getDateTime(it.createdAt),
|
||||||
|
info = "${it.user!!.name} ${it.status} ${
|
||||||
|
it.progress
|
||||||
|
?: it.media?.title?.userPreferred
|
||||||
|
}",
|
||||||
|
cover = it.media?.coverImage?.extraLarge,
|
||||||
|
banner = it.media?.bannerImage ?: it.media?.coverImage?.extraLarge,
|
||||||
|
likes = it.likeCount ?: 0,
|
||||||
|
likedBy = it.likes,
|
||||||
|
isLiked = it.isLiked == true
|
||||||
|
) }
|
||||||
|
binding.stories.setStoriesList(storiesList, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
binding.stories.pause()
|
||||||
|
}
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
binding.stories.resume()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
||||||
|
super.onWindowFocusChanged(hasFocus)
|
||||||
|
if (hasFocus) {
|
||||||
|
binding.stories.resume()
|
||||||
|
} else {
|
||||||
|
binding.stories.pause()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
override fun onStoriesEnd() {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
53
app/src/main/java/ani/dantotsu/home/UserStatus.kt
Normal file
53
app/src/main/java/ani/dantotsu/home/UserStatus.kt
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
package ani.dantotsu.home
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import ani.dantotsu.databinding.ItemUserStatusBinding
|
||||||
|
import ani.dantotsu.loadImage
|
||||||
|
import ani.dantotsu.profile.User
|
||||||
|
import ani.dantotsu.setAnimation
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
class UserStatus(private val user: ArrayList<User>) :
|
||||||
|
RecyclerView.Adapter< UserStatus.UsersViewHolder>() {
|
||||||
|
|
||||||
|
inner class UsersViewHolder(val binding: ItemUserStatusBinding) :
|
||||||
|
RecyclerView.ViewHolder(binding.root) {
|
||||||
|
init {
|
||||||
|
itemView.setOnClickListener {
|
||||||
|
ContextCompat.startActivity(
|
||||||
|
itemView.context,
|
||||||
|
Intent(
|
||||||
|
itemView.context,
|
||||||
|
StatusActivity::class.java
|
||||||
|
).putExtra("activity", user[bindingAdapterPosition].activity as Serializable),
|
||||||
|
null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UsersViewHolder {
|
||||||
|
return UsersViewHolder(
|
||||||
|
ItemUserStatusBinding.inflate(
|
||||||
|
LayoutInflater.from(parent.context),
|
||||||
|
parent,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: UsersViewHolder, position: Int) {
|
||||||
|
val b = holder.binding
|
||||||
|
setAnimation(b.root.context, b.root)
|
||||||
|
val user = user[position]
|
||||||
|
b.profileUserAvatar.loadImage(user.pfp)
|
||||||
|
b.profileUserName.text = user.name
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = user.size
|
||||||
|
}
|
413
app/src/main/java/ani/dantotsu/home/status/Stories.kt
Normal file
413
app/src/main/java/ani/dantotsu/home/status/Stories.kt
Normal file
|
@ -0,0 +1,413 @@
|
||||||
|
package ani.dantotsu.home.status
|
||||||
|
|
||||||
|
import android.animation.Animator
|
||||||
|
import android.animation.ObjectAnimator
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.graphics.Rect
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
|
import android.view.animation.LinearInterpolator
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.ProgressBar
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
import androidx.constraintlayout.widget.ConstraintSet
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import androidx.webkit.internal.ApiFeature.T
|
||||||
|
import ani.dantotsu.R
|
||||||
|
import ani.dantotsu.blurImage
|
||||||
|
import ani.dantotsu.connections.anilist.Anilist
|
||||||
|
import ani.dantotsu.home.status.data.StoryItem
|
||||||
|
import ani.dantotsu.home.status.listener.StoriesCallback
|
||||||
|
import ani.dantotsu.loadImage
|
||||||
|
import ani.dantotsu.media.MediaDetailsActivity
|
||||||
|
import ani.dantotsu.profile.ProfileActivity
|
||||||
|
import ani.dantotsu.profile.User
|
||||||
|
import ani.dantotsu.profile.UsersDialogFragment
|
||||||
|
import ani.dantotsu.snackString
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import java.util.Calendar
|
||||||
|
|
||||||
|
|
||||||
|
class Stories @JvmOverloads
|
||||||
|
constructor(
|
||||||
|
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
||||||
|
) : ConstraintLayout(context, attrs, defStyleAttr), View.OnTouchListener {
|
||||||
|
|
||||||
|
private lateinit var storiesList: List<StoryItem>
|
||||||
|
private lateinit var activ: FragmentActivity
|
||||||
|
private lateinit var loadingViewLayout: ConstraintLayout
|
||||||
|
private lateinit var leftTouchPanel: FrameLayout
|
||||||
|
private lateinit var rightTouchPanel: FrameLayout
|
||||||
|
private lateinit var statusUserContainer: LinearLayout
|
||||||
|
private lateinit var imageContentView: ImageView
|
||||||
|
private lateinit var loadingView: ProgressBar
|
||||||
|
private lateinit var activityLikeCount: TextView
|
||||||
|
private lateinit var activityLike: ImageView
|
||||||
|
private lateinit var userName: TextView
|
||||||
|
private lateinit var userAvatar: ImageView
|
||||||
|
private lateinit var time: TextView
|
||||||
|
private lateinit var infoText: TextView
|
||||||
|
private lateinit var coverImage: ImageView
|
||||||
|
private var storyDuration: String = "4"
|
||||||
|
private lateinit var animation: ObjectAnimator
|
||||||
|
private var storyIndex: Int = 1
|
||||||
|
private var userClicked: Boolean = false
|
||||||
|
private lateinit var storiesListener: StoriesCallback
|
||||||
|
private var oldStoryItem = StoryItem()
|
||||||
|
|
||||||
|
init {
|
||||||
|
initLayout()
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
private fun initLayout() {
|
||||||
|
val inflater: LayoutInflater = LayoutInflater.from(context)
|
||||||
|
val view = inflater.inflate(R.layout.fragment_status, this, false)
|
||||||
|
addView(view)
|
||||||
|
|
||||||
|
if (context is StoriesCallback)
|
||||||
|
storiesListener = context as StoriesCallback
|
||||||
|
|
||||||
|
|
||||||
|
loadingViewLayout = findViewById(R.id.progressBarContainer)
|
||||||
|
leftTouchPanel = findViewById(R.id.leftTouchPanel)
|
||||||
|
rightTouchPanel = findViewById(R.id.rightTouchPanel)
|
||||||
|
imageContentView = findViewById(R.id.contentImageView)
|
||||||
|
statusUserContainer = findViewById(R.id.statusUserContainer)
|
||||||
|
loadingView = findViewById(R.id.androidStoriesLoadingView)
|
||||||
|
coverImage = findViewById(R.id.coverImage)
|
||||||
|
userName = findViewById(R.id.statusUserName)
|
||||||
|
userAvatar = findViewById(R.id.statusUserAvatar)
|
||||||
|
time = findViewById(R.id.statusUserTime)
|
||||||
|
infoText = findViewById(R.id.infoText)
|
||||||
|
activityLikeCount = findViewById(R.id.activityLikeCount)
|
||||||
|
activityLike = findViewById(R.id.activityLike)
|
||||||
|
|
||||||
|
leftTouchPanel.setOnTouchListener(this)
|
||||||
|
rightTouchPanel.setOnTouchListener(this)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun setStoriesList(storiesList: List<StoryItem>, activity: FragmentActivity) {
|
||||||
|
this.storiesList = storiesList
|
||||||
|
this.activ = activity
|
||||||
|
addLoadingViews(storiesList)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addLoadingViews(storiesList: List<StoryItem>) {
|
||||||
|
var idCounter = 1
|
||||||
|
for (story in storiesList) {
|
||||||
|
val progressBar = ProgressBar(context, null, android.R.attr.progressBarStyleHorizontal)
|
||||||
|
progressBar.visibility = View.VISIBLE
|
||||||
|
progressBar.id = idCounter
|
||||||
|
progressBar.tag = "story${idCounter++}"
|
||||||
|
val params = LayoutParams(0, LayoutParams.WRAP_CONTENT)
|
||||||
|
params.marginEnd = 5
|
||||||
|
params.marginStart = 5
|
||||||
|
loadingViewLayout.addView(progressBar, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
val constraintSet = ConstraintSet()
|
||||||
|
constraintSet.clone(loadingViewLayout)
|
||||||
|
|
||||||
|
var counter = storiesList.size
|
||||||
|
for (story in storiesList) {
|
||||||
|
val progressBar = findViewWithTag<ProgressBar>("story${counter}")
|
||||||
|
if (progressBar != null) {
|
||||||
|
if (storiesList.size > 1) {
|
||||||
|
when (counter) {
|
||||||
|
storiesList.size -> {
|
||||||
|
constraintSet.connect(
|
||||||
|
getId("story${counter}"),
|
||||||
|
ConstraintSet.END,
|
||||||
|
LayoutParams.PARENT_ID,
|
||||||
|
ConstraintSet.END
|
||||||
|
)
|
||||||
|
constraintSet.connect(
|
||||||
|
getId("story${counter}"),
|
||||||
|
ConstraintSet.TOP,
|
||||||
|
LayoutParams.PARENT_ID,
|
||||||
|
ConstraintSet.TOP
|
||||||
|
)
|
||||||
|
constraintSet.connect(
|
||||||
|
getId("story${counter}"),
|
||||||
|
ConstraintSet.START,
|
||||||
|
getId("story${counter - 1}"),
|
||||||
|
ConstraintSet.END
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
1 -> {
|
||||||
|
constraintSet.connect(
|
||||||
|
getId("story${counter}"),
|
||||||
|
ConstraintSet.TOP,
|
||||||
|
LayoutParams.PARENT_ID,
|
||||||
|
ConstraintSet.TOP
|
||||||
|
)
|
||||||
|
constraintSet.connect(
|
||||||
|
getId("story${counter}"),
|
||||||
|
ConstraintSet.START,
|
||||||
|
LayoutParams.PARENT_ID,
|
||||||
|
ConstraintSet.START
|
||||||
|
)
|
||||||
|
constraintSet.connect(
|
||||||
|
getId("story${counter}"),
|
||||||
|
ConstraintSet.END,
|
||||||
|
getId("story${counter + 1}"),
|
||||||
|
ConstraintSet.START
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
constraintSet.connect(
|
||||||
|
getId("story${counter}"),
|
||||||
|
ConstraintSet.TOP,
|
||||||
|
LayoutParams.PARENT_ID,
|
||||||
|
ConstraintSet.TOP
|
||||||
|
)
|
||||||
|
constraintSet.connect(
|
||||||
|
getId("story${counter}"),
|
||||||
|
ConstraintSet.START,
|
||||||
|
getId("story${counter - 1}"),
|
||||||
|
ConstraintSet.END
|
||||||
|
)
|
||||||
|
constraintSet.connect(
|
||||||
|
getId("story${counter}"),
|
||||||
|
ConstraintSet.END,
|
||||||
|
getId("story${counter + 1}"),
|
||||||
|
ConstraintSet.START
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
constraintSet.connect(
|
||||||
|
getId("story${counter}"),
|
||||||
|
ConstraintSet.END,
|
||||||
|
LayoutParams.PARENT_ID,
|
||||||
|
ConstraintSet.END
|
||||||
|
)
|
||||||
|
constraintSet.connect(
|
||||||
|
getId("story${counter}"),
|
||||||
|
ConstraintSet.TOP,
|
||||||
|
LayoutParams.PARENT_ID,
|
||||||
|
ConstraintSet.TOP
|
||||||
|
)
|
||||||
|
constraintSet.connect(
|
||||||
|
getId("story${counter}"),
|
||||||
|
ConstraintSet.START,
|
||||||
|
LayoutParams.PARENT_ID,
|
||||||
|
ConstraintSet.START
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
counter--
|
||||||
|
}
|
||||||
|
constraintSet.applyTo(loadingViewLayout)
|
||||||
|
startShowContent()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startShowContent() {
|
||||||
|
showStory()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showStory() {
|
||||||
|
val progressBar = findViewWithTag<ProgressBar>("story${storyIndex}")
|
||||||
|
loadingView.visibility = View.VISIBLE
|
||||||
|
animation = ObjectAnimator.ofInt(progressBar, "progress", 0, 100)
|
||||||
|
animation.duration = secondsToMillis(storyDuration)
|
||||||
|
animation.interpolator = LinearInterpolator()
|
||||||
|
animation.addListener(object : Animator.AnimatorListener {
|
||||||
|
override fun onAnimationStart(animator: Animator) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAnimationEnd(animator: Animator) {
|
||||||
|
if (storyIndex - 1 <= storiesList.size) {
|
||||||
|
if (userClicked) {
|
||||||
|
userClicked = false
|
||||||
|
} else {
|
||||||
|
if (storyIndex < storiesList.size) {
|
||||||
|
storyIndex += 1
|
||||||
|
showStory()
|
||||||
|
} else {
|
||||||
|
// on stories end
|
||||||
|
loadingView.visibility = View.GONE
|
||||||
|
onStoriesCompleted()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// on stories end
|
||||||
|
loadingView.visibility = View.GONE
|
||||||
|
onStoriesCompleted()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAnimationCancel(animator: Animator) {
|
||||||
|
progressBar.progress = 100
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAnimationRepeat(animator: Animator) {}
|
||||||
|
})
|
||||||
|
loadStory(storiesList[storyIndex - 1])
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getId(tag: String): Int {
|
||||||
|
return findViewWithTag<ProgressBar>(tag).id
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun secondsToMillis(seconds: String): Long {
|
||||||
|
return (seconds.toLongOrNull() ?: 3).times(1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resetProgressBar(storyIndex: Int) {
|
||||||
|
val currentProgressBar = findViewWithTag<ProgressBar>("story${storyIndex}")
|
||||||
|
val lastProgressBar = findViewWithTag<ProgressBar>("story${storyIndex - 1}")
|
||||||
|
currentProgressBar?.let {
|
||||||
|
it.progress = 0
|
||||||
|
}
|
||||||
|
lastProgressBar?.let {
|
||||||
|
it.progress = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun completeProgressBar(storyIndex: Int) {
|
||||||
|
val lastProgressBar = findViewWithTag<ProgressBar>("story${storyIndex}")
|
||||||
|
lastProgressBar?.let {
|
||||||
|
it.progress = 100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private var startClickTime = 0L
|
||||||
|
override fun onTouch(view: View?, event: MotionEvent?): Boolean {
|
||||||
|
val maxClickDuration = 200
|
||||||
|
when (event?.action) {
|
||||||
|
MotionEvent.ACTION_DOWN -> {
|
||||||
|
startClickTime = Calendar.getInstance().timeInMillis
|
||||||
|
animation.pause()
|
||||||
|
}
|
||||||
|
|
||||||
|
MotionEvent.ACTION_UP -> {
|
||||||
|
val clickDuration = Calendar.getInstance().timeInMillis - startClickTime
|
||||||
|
if (clickDuration < maxClickDuration) {
|
||||||
|
//click occurred
|
||||||
|
view?.let {
|
||||||
|
if (it.id == R.id.leftTouchPanel) {
|
||||||
|
leftPanelTouch()
|
||||||
|
} else if (it.id == R.id.rightTouchPanel) {
|
||||||
|
rightPanelTouch()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//hold click occurred
|
||||||
|
animation.resume()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rightPanelTouch() {
|
||||||
|
if (storyIndex == storiesList.size) {
|
||||||
|
completeProgressBar(storyIndex)
|
||||||
|
onStoriesCompleted()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
userClicked = true
|
||||||
|
animation.end()
|
||||||
|
if (storyIndex < storiesList.size)
|
||||||
|
storyIndex += 1
|
||||||
|
showStory()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun leftPanelTouch() {
|
||||||
|
userClicked = true
|
||||||
|
animation.end()
|
||||||
|
resetProgressBar(storyIndex)
|
||||||
|
if (storyIndex > 1)
|
||||||
|
storyIndex -= 1
|
||||||
|
showStory()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onStoriesCompleted() {
|
||||||
|
if (::storiesListener.isInitialized)
|
||||||
|
storiesListener.onStoriesEnd()
|
||||||
|
}
|
||||||
|
fun pause() {
|
||||||
|
animation.pause()
|
||||||
|
}
|
||||||
|
fun resume() {
|
||||||
|
animation.resume()
|
||||||
|
}
|
||||||
|
private fun loadStory(story: StoryItem) {
|
||||||
|
loadingView.visibility = View.GONE
|
||||||
|
animation.start()
|
||||||
|
blurImage(imageContentView, story.banner)
|
||||||
|
userAvatar.loadImage(story.userAvatar)
|
||||||
|
coverImage.loadImage(story.cover)
|
||||||
|
userName.text = story.userName
|
||||||
|
time.text = story.time
|
||||||
|
infoText.text = story.info
|
||||||
|
statusUserContainer.setOnClickListener {
|
||||||
|
ContextCompat.startActivity(context, Intent(context, ProfileActivity::class.java).putExtra("userId", story.id), null)
|
||||||
|
}
|
||||||
|
coverImage.setOnClickListener{
|
||||||
|
ContextCompat.startActivity(context, Intent(context, MediaDetailsActivity::class.java).putExtra("mediaId", story.mediaId), null)
|
||||||
|
}
|
||||||
|
val likeColor = ContextCompat.getColor(context, R.color.yt_red)
|
||||||
|
val notLikeColor = ContextCompat.getColor(context, R.color.bg_opp)
|
||||||
|
activityLikeCount.text = story.likes.toString()
|
||||||
|
activityLike.setColorFilter(if (story.isLiked) likeColor else notLikeColor)
|
||||||
|
activityLike.setOnClickListener {
|
||||||
|
val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
||||||
|
scope.launch {
|
||||||
|
val res = Anilist.query.toggleLike(story.activityId!!, "ACTIVITY")
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
if (res != null) {
|
||||||
|
|
||||||
|
if (story.isLiked) {
|
||||||
|
story.likes = story.likes.minus(1)
|
||||||
|
} else {
|
||||||
|
story.likes = story.likes.plus(1)
|
||||||
|
}
|
||||||
|
activityLikeCount.text = (story.likes ?: 0).toString()
|
||||||
|
story.isLiked = !story.isLiked
|
||||||
|
activityLike.setColorFilter(if (story.isLiked) likeColor else notLikeColor)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
snackString("Failed to like activity")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val userList = arrayListOf<User>()
|
||||||
|
story.likedBy?.forEach { i ->
|
||||||
|
userList.add(User(i.id, i.name.toString(), i.avatar?.medium, i.bannerImage))
|
||||||
|
}
|
||||||
|
|
||||||
|
activityLike.setOnLongClickListener {
|
||||||
|
UsersDialogFragment().apply {
|
||||||
|
userList(userList)
|
||||||
|
show(activ.supportFragmentManager, "dialog")
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
oldStoryItem = story
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
20
app/src/main/java/ani/dantotsu/home/status/data/StoryItem.kt
Normal file
20
app/src/main/java/ani/dantotsu/home/status/data/StoryItem.kt
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
package ani.dantotsu.home.status.data
|
||||||
|
|
||||||
|
import ani.dantotsu.connections.anilist.api.User
|
||||||
|
|
||||||
|
data class StoryItem(
|
||||||
|
val id : Int? = null,
|
||||||
|
val activityId : Int? = null,
|
||||||
|
val mediaId: Int? = null,
|
||||||
|
val userName: String? = null,
|
||||||
|
val userAvatar: String? = null,
|
||||||
|
val time: String? = null,
|
||||||
|
val info: String? = null,
|
||||||
|
val cover: String? = null,
|
||||||
|
val banner: String? = null,
|
||||||
|
var likes : Int = 0,
|
||||||
|
val likedBy: List<User>? = null,
|
||||||
|
var isLiked : Boolean = false
|
||||||
|
)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
package ani.dantotsu.home.status.listener
|
||||||
|
|
||||||
|
interface StoriesCallback {
|
||||||
|
|
||||||
|
fun onStoriesEnd()
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package ani.dantotsu.profile
|
package ani.dantotsu.profile
|
||||||
|
|
||||||
|
import ani.dantotsu.connections.anilist.api.Activity
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
@ -14,6 +15,7 @@ data class User(
|
||||||
val progress: Int? = null,
|
val progress: Int? = null,
|
||||||
val totalEpisodes: Int? = null,
|
val totalEpisodes: Int? = null,
|
||||||
val nextAiringEpisode: Int? = null,
|
val nextAiringEpisode: Int? = null,
|
||||||
|
val activity: List<Activity> = mutableListOf(),
|
||||||
) : java.io.Serializable {
|
) : java.io.Serializable {
|
||||||
companion object {
|
companion object {
|
||||||
private const val serialVersionUID: Long = 1
|
private const val serialVersionUID: Long = 1
|
||||||
|
|
13
app/src/main/res/layout/activity_status.xml
Normal file
13
app/src/main/res/layout/activity_status.xml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout 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"
|
||||||
|
tools:context=".MainActivity">
|
||||||
|
|
||||||
|
<ani.dantotsu.home.status.Stories
|
||||||
|
android:id="@+id/stories"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -309,7 +309,50 @@
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/homeUserStatusContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/homeUserStatus"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:fontFamily="@font/poppins_bold"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:text="@string/social"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:minHeight="100dp">
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/homeUserStatusProgressBar"
|
||||||
|
style="?android:attr/progressBarStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_margin="90dp" />
|
||||||
|
|
||||||
|
<ani.dantotsu.FadingEdgeRecyclerView
|
||||||
|
android:id="@+id/homeUserStatusRecyclerView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:paddingStart="20dp"
|
||||||
|
android:paddingEnd="20dp"
|
||||||
|
android:requiresFadingEdge="horizontal"
|
||||||
|
tools:itemCount="4"
|
||||||
|
tools:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
|
tools:listitem="@layout/item_user_status"
|
||||||
|
tools:orientation="horizontal" />
|
||||||
|
</FrameLayout>
|
||||||
|
</LinearLayout>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/homeContinueWatchingContainer"
|
android:id="@+id/homeContinueWatchingContainer"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
210
app/src/main/res/layout/fragment_status.xml
Normal file
210
app/src/main/res/layout/fragment_status.xml
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
<?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:ignore="ContentDescription">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/contentImageView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
android:scaleType="centerCrop" />
|
||||||
|
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/leftTouchPanel"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintWidth_percent="0.5" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/rightTouchPanel"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintWidth_percent="0.5" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:ignore="MissingConstraints">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:id="@+id/progressBarContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/statusUserContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:id="@+id/statusUserAvatarContainer"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="start"
|
||||||
|
android:layout_margin="12dp"
|
||||||
|
android:backgroundTint="@color/transparent"
|
||||||
|
app:cardCornerRadius="64dp"
|
||||||
|
app:strokeColor="@color/transparent">
|
||||||
|
|
||||||
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
|
android:id="@+id/statusUserAvatar"
|
||||||
|
android:layout_width="32dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
app:srcCompat="@drawable/ic_round_add_circle_24"
|
||||||
|
tools:ignore="ContentDescription,ImageContrastCheck"
|
||||||
|
tools:tint="@color/bg_black_50" />
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/statusUserName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="4dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:fontFamily="@font/poppins_bold"
|
||||||
|
android:paddingTop="1dp"
|
||||||
|
android:paddingBottom="0dp"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="Username"
|
||||||
|
android:textSize="16sp"
|
||||||
|
tools:ignore="HardcodedText,RtlSymmetry" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="4dp"
|
||||||
|
android:alpha="0.6"
|
||||||
|
android:fontFamily="@font/poppins_semi_bold"
|
||||||
|
android:text="•"
|
||||||
|
android:textSize="18sp"
|
||||||
|
tools:ignore="HardcodedText,RtlSymmetry" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/statusUserTime"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="6dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:alpha="0.6"
|
||||||
|
android:fontFamily="@font/poppins_semi_bold"
|
||||||
|
android:text="Time"
|
||||||
|
android:textSize="14sp"
|
||||||
|
tools:ignore="HardcodedText,RtlSymmetry" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="12dp"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:ignore="UseCompoundDrawables">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/activityLike"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/ic_round_favorite_24"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/activityLikeCount"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:fontFamily="@font/poppins_semi_bold"
|
||||||
|
android:textSize="15sp"
|
||||||
|
tools:text="12" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<androidx.cardview.widget.CardView
|
||||||
|
android:id="@+id/itemCompactCard"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:translationZ="8dp"
|
||||||
|
app:cardCornerRadius="16dp"
|
||||||
|
app:cardElevation="4dp"
|
||||||
|
android:layout_marginBottom="124dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
|
android:id="@+id/coverImage"
|
||||||
|
android:layout_width="172dp"
|
||||||
|
android:layout_height="256dp"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:transitionName="mediaCover"
|
||||||
|
app:shapeAppearanceOverlay="@style/roundedImageView"
|
||||||
|
tools:ignore="ContentDescription,ImageContrastCheck"
|
||||||
|
tools:srcCompat="@tools:sample/backgrounds/scenic" />
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="start"
|
||||||
|
android:layout_marginTop="124dp"
|
||||||
|
android:layout_marginStart="12dp"
|
||||||
|
android:layout_marginEnd="12dp"
|
||||||
|
android:backgroundTint="@color/transparent"
|
||||||
|
app:cardCornerRadius="124dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/itemCompactCard"
|
||||||
|
app:strokeColor="@color/transparent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/infoText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/colorSurfaceVariant"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:paddingHorizontal="12dp"
|
||||||
|
android:fontFamily="@font/poppins_semi_bold"
|
||||||
|
android:lineSpacingExtra="-8sp"
|
||||||
|
android:maxLines="3"
|
||||||
|
android:textAlignment="center"
|
||||||
|
android:textColor="@color/bg_opp"
|
||||||
|
android:textSize="24dp"
|
||||||
|
android:transitionName="mediaTitle"
|
||||||
|
tools:ignore="SpUsage"
|
||||||
|
tools:text="@string/slogan" />
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/androidStoriesLoadingView"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
37
app/src/main/res/layout/item_user_status.xml
Normal file
37
app/src/main/res/layout/item_user_status.xml
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout 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="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="8dp">
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:id="@+id/profileUserAvatarContainer"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:backgroundTint="@color/bg_white"
|
||||||
|
app:cardCornerRadius="124dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/profileUserAvatar"
|
||||||
|
android:layout_width="64dp"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
tools:ignore="ContentDescription,ImageContrastCheck"
|
||||||
|
tools:tint="@color/transparent" />
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/profileUserName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal|center_vertical"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:text="@string/username"
|
||||||
|
android:textColor="?attr/colorOnBackground"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
Loading…
Add table
Add a link
Reference in a new issue