diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 362d915..ce59b6c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -48,6 +48,7 @@
+
diff --git a/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/TimelineFragment.kt b/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/TimelineFragment.kt
index 3aab419..d2e64f9 100644
--- a/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/TimelineFragment.kt
+++ b/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/TimelineFragment.kt
@@ -27,6 +27,7 @@ import androidx.paging.ExperimentalPagingApi
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.SimpleItemAnimator
import at.connyduck.pixelcat.R
+import at.connyduck.pixelcat.components.timeline.detail.DetailActivity
import at.connyduck.pixelcat.components.util.extension.getDisplayWidthInPx
import at.connyduck.pixelcat.components.util.getColorForAttr
import at.connyduck.pixelcat.dagger.ViewModelFactory
@@ -101,4 +102,8 @@ class TimelineFragment : DaggerFragment(R.layout.fragment_timeline), TimeLineAct
override fun onMediaVisibilityChanged(status: StatusEntity) {
viewModel.onMediaVisibilityChanged(status)
}
+
+ override fun onDetailsOpened(status: StatusEntity) {
+ startActivity(DetailActivity.newIntent(requireContext(), status.actionableId))
+ }
}
diff --git a/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/TimelineListAdapter.kt b/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/TimelineListAdapter.kt
index 1a97eba..8242435 100644
--- a/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/TimelineListAdapter.kt
+++ b/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/TimelineListAdapter.kt
@@ -31,6 +31,7 @@ import at.connyduck.pixelcat.databinding.ItemStatusBinding
import at.connyduck.pixelcat.db.entitity.StatusEntity
import coil.api.load
import coil.transform.RoundedCornersTransformation
+import java.text.DateFormat
import java.text.SimpleDateFormat
interface TimeLineActionListener {
@@ -38,6 +39,7 @@ interface TimeLineActionListener {
fun onBoost(post: StatusEntity)
fun onReply(status: StatusEntity)
fun onMediaVisibilityChanged(status: StatusEntity)
+ fun onDetailsOpened(status: StatusEntity)
}
object TimelineDiffUtil : DiffUtil.ItemCallback() {
@@ -66,65 +68,71 @@ class TimelineListAdapter(
}
override fun onBindViewHolder(holder: BindingHolder, position: Int) {
-
getItem(position)?.let { status ->
-
- // TODO order the stuff here
-
- (holder.binding.postImages.adapter as TimelineImageAdapter).images = status.attachments
-
- val maxImageRatio = status.attachments.map {
- if(it.meta?.small?.width == null || it.meta.small.height == null) {
- 1f
- } else {
- it.meta.small.height.toFloat() / it.meta.small.width.toFloat()
- }
- }.max()?.coerceAtMost(1f) ?: 1f
-
- holder.binding.postImages.layoutParams.height = (displayWidth * maxImageRatio).toInt()
-
- holder.binding.postAvatar.load(status.account.avatar) {
- transformations(RoundedCornersTransformation(25f))
- }
-
- holder.binding.postAvatar.setOnClickListener {
- holder.binding.root.context.startActivity(ProfileActivity.newIntent(holder.binding.root.context, status.account.id))
- }
-
- holder.binding.postDisplayName.text = status.account.displayName
- holder.binding.postName.text = "@${status.account.username}"
-
- holder.binding.postLikeButton.isChecked = status.favourited
-
- holder.binding.postLikeButton.setEventListener { _, _ ->
- listener.onFavorite(status)
- true
- }
-
- holder.binding.postBoostButton.isChecked = status.reblogged
-
- holder.binding.postBoostButton.setEventListener { _, _ ->
- listener.onBoost(status)
- true
- }
-
- holder.binding.postReplyButton.setOnClickListener {
- listener.onReply(status)
- }
-
- holder.binding.postIndicator.visible = status.attachments.size > 1
-
- holder.binding.postImages.visible = status.attachments.isNotEmpty()
-
- holder.binding.postDescription.text = status.content.parseAsHtml().trim()
-
- holder.binding.postDate.text = dateTimeFormatter.format(status.createdAt)
-
- holder.binding.postSensitiveMediaOverlay.visible = status.attachments.isNotEmpty() && !status.mediaVisible
-
- holder.binding.postSensitiveMediaOverlay.setOnClickListener {
- listener.onMediaVisibilityChanged(status)
- }
+ holder.bind(status, displayWidth, listener, dateTimeFormatter)
}
}
}
+
+fun BindingHolder.bind(status: StatusEntity, displayWidth: Int, listener: TimeLineActionListener, dateTimeFormatter: DateFormat) {
+ // TODO order the stuff here
+
+ (binding.postImages.adapter as TimelineImageAdapter).images = status.attachments
+
+ val maxImageRatio = status.attachments.map {
+ if(it.meta?.small?.width == null || it.meta.small.height == null) {
+ 1f
+ } else {
+ it.meta.small.height.toFloat() / it.meta.small.width.toFloat()
+ }
+ }.max()?.coerceAtMost(1f) ?: 1f
+
+ binding.postImages.layoutParams.height = (displayWidth * maxImageRatio).toInt()
+
+ binding.postAvatar.load(status.account.avatar) {
+ transformations(RoundedCornersTransformation(25f))
+ }
+
+ binding.postAvatar.setOnClickListener {
+ binding.root.context.startActivity(ProfileActivity.newIntent(binding.root.context, status.account.id))
+ }
+
+ binding.postDisplayName.text = status.account.displayName
+ binding.postName.text = "@${status.account.username}"
+
+ binding.postLikeButton.isChecked = status.favourited
+
+ binding.postLikeButton.setEventListener { _, _ ->
+ listener.onFavorite(status)
+ true
+ }
+
+ binding.postBoostButton.isChecked = status.reblogged
+
+ binding.postBoostButton.setEventListener { _, _ ->
+ listener.onBoost(status)
+ true
+ }
+
+ binding.postReplyButton.setOnClickListener {
+ listener.onReply(status)
+ }
+
+ binding.postIndicator.visible = status.attachments.size > 1
+
+ binding.postImages.visible = status.attachments.isNotEmpty()
+
+ binding.postDescription.text = status.content.parseAsHtml().trim()
+
+ binding.postDate.text = dateTimeFormatter.format(status.createdAt)
+
+ binding.postSensitiveMediaOverlay.visible = status.attachments.isNotEmpty() && !status.mediaVisible
+
+ binding.postSensitiveMediaOverlay.setOnClickListener {
+ listener.onMediaVisibilityChanged(status)
+ }
+
+ binding.root.setOnClickListener {
+ listener.onDetailsOpened(status)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/detail/DetailActivity.kt b/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/detail/DetailActivity.kt
new file mode 100644
index 0000000..99c247f
--- /dev/null
+++ b/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/detail/DetailActivity.kt
@@ -0,0 +1,102 @@
+package at.connyduck.pixelcat.components.timeline.detail
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.viewModels
+import androidx.lifecycle.Observer
+import androidx.recyclerview.widget.MergeAdapter
+import at.connyduck.pixelcat.components.general.BaseActivity
+import at.connyduck.pixelcat.components.timeline.TimeLineActionListener
+import at.connyduck.pixelcat.components.util.Success
+import at.connyduck.pixelcat.components.util.extension.getDisplayWidthInPx
+import at.connyduck.pixelcat.components.util.extension.hide
+import at.connyduck.pixelcat.components.util.extension.show
+import at.connyduck.pixelcat.dagger.ViewModelFactory
+import at.connyduck.pixelcat.databinding.ActivityDetailBinding
+import at.connyduck.pixelcat.db.entitity.StatusEntity
+import at.connyduck.pixelcat.util.viewBinding
+import javax.inject.Inject
+
+class DetailActivity: BaseActivity(), TimeLineActionListener {
+
+ @Inject
+ lateinit var viewModelFactory: ViewModelFactory
+
+ private val viewModel: DetailViewModel by viewModels { viewModelFactory }
+
+ private val binding by viewBinding(ActivityDetailBinding::inflate)
+
+ private lateinit var statusAdapter: DetailStatusAdapter
+
+ private lateinit var repliesAdapter: DetailReplyAdapter
+
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(binding.root)
+
+ binding.root.setOnApplyWindowInsetsListener { _, insets ->
+ val top = insets.systemWindowInsetTop
+
+ binding.root.setPadding(0, top, 0, 0)
+
+ insets.consumeSystemWindowInsets()
+ }
+
+ viewModel.setStatusId(intent.getStringExtra(EXTRA_STATUS_ID)!!)
+
+ val displayWidth = getDisplayWidthInPx()
+
+ statusAdapter = DetailStatusAdapter(displayWidth, this)
+ repliesAdapter = DetailReplyAdapter(this)
+
+ binding.detailRecyclerView.adapter = MergeAdapter(statusAdapter, repliesAdapter)
+
+ viewModel.currentStatus.observe(this, Observer {
+ if(it is Success) {
+ binding.detailProgress.hide()
+ binding.detailRecyclerView.show()
+ statusAdapter.submitList(listOf(it.data))
+ }
+ })
+
+ viewModel.replies.observe(this, Observer {
+ if(it is Success) {
+ repliesAdapter.submitList(it.data)
+ }
+ })
+
+ }
+
+ override fun onFavorite(post: StatusEntity) {
+ TODO("Not yet implemented")
+ }
+
+ override fun onBoost(post: StatusEntity) {
+ TODO("Not yet implemented")
+ }
+
+ override fun onReply(status: StatusEntity) {
+ TODO("Not yet implemented")
+ }
+
+ override fun onMediaVisibilityChanged(status: StatusEntity) {
+ TODO("Not yet implemented")
+ }
+
+ override fun onDetailsOpened(status: StatusEntity) {
+ // nothing to do, we already are in details
+ }
+
+ companion object {
+ private const val EXTRA_STATUS_ID = "STATUS_ID"
+
+ fun newIntent(context: Context, statusId: String): Intent {
+ return Intent(context, DetailActivity::class.java).apply {
+ putExtra(EXTRA_STATUS_ID, statusId)
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/detail/DetailReplyAdapter.kt b/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/detail/DetailReplyAdapter.kt
new file mode 100644
index 0000000..2aefe82
--- /dev/null
+++ b/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/detail/DetailReplyAdapter.kt
@@ -0,0 +1,58 @@
+package at.connyduck.pixelcat.components.timeline.detail
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.core.text.parseAsHtml
+import androidx.recyclerview.widget.ListAdapter
+import at.connyduck.pixelcat.components.timeline.TimeLineActionListener
+import at.connyduck.pixelcat.components.timeline.TimelineDiffUtil
+import at.connyduck.pixelcat.components.util.BindingHolder
+import at.connyduck.pixelcat.databinding.ItemReplyBinding
+import at.connyduck.pixelcat.db.entitity.StatusEntity
+import coil.api.load
+import coil.transform.RoundedCornersTransformation
+import java.text.SimpleDateFormat
+
+class DetailReplyAdapter(
+ private val listener: TimeLineActionListener
+): ListAdapter>(TimelineDiffUtil) {
+
+ private val dateTimeFormatter = SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.SHORT, SimpleDateFormat.SHORT)
+
+ override fun onCreateViewHolder(
+ parent: ViewGroup,
+ viewType: Int
+ ): BindingHolder {
+ val binding = ItemReplyBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+ return BindingHolder(binding)
+ }
+
+ override fun onBindViewHolder(holder: BindingHolder, position: Int) {
+ getItem(position)?.let { status ->
+
+ holder.binding.postAvatar.load(status.account.avatar) {
+ transformations(RoundedCornersTransformation(25f))
+ }
+
+ holder.binding.postDisplayName.text = status.account.displayName
+ holder.binding.postName.text = "@${status.account.username}"
+
+ holder.binding.postDescription.text = status.content.parseAsHtml().trim()
+
+ holder.binding.postDate.text = dateTimeFormatter.format(status.createdAt)
+
+ holder.binding.postLikeButton.isChecked = status.favourited
+
+ holder.binding.postLikeButton.setEventListener { _, _ ->
+ listener.onFavorite(status)
+ true
+ }
+
+ holder.binding.postReplyButton.setOnClickListener {
+ listener.onReply(status)
+ }
+
+ }
+ }
+
+}
diff --git a/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/detail/DetailStatusAdapter.kt b/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/detail/DetailStatusAdapter.kt
new file mode 100644
index 0000000..cc01752
--- /dev/null
+++ b/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/detail/DetailStatusAdapter.kt
@@ -0,0 +1,40 @@
+package at.connyduck.pixelcat.components.timeline.detail
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.ListAdapter
+import at.connyduck.pixelcat.components.timeline.TimeLineActionListener
+import at.connyduck.pixelcat.components.timeline.TimelineDiffUtil
+import at.connyduck.pixelcat.components.timeline.TimelineImageAdapter
+import at.connyduck.pixelcat.components.timeline.bind
+import at.connyduck.pixelcat.components.util.BindingHolder
+import at.connyduck.pixelcat.databinding.ItemStatusBinding
+import at.connyduck.pixelcat.db.entitity.StatusEntity
+import java.text.SimpleDateFormat
+
+
+class DetailStatusAdapter(
+ private val displayWidth: Int,
+ private val listener: TimeLineActionListener
+): ListAdapter>(TimelineDiffUtil) {
+
+ private val dateTimeFormatter = SimpleDateFormat.getDateTimeInstance(SimpleDateFormat.SHORT, SimpleDateFormat.SHORT)
+
+ override fun onCreateViewHolder(
+ parent: ViewGroup,
+ viewType: Int
+ ): BindingHolder {
+ val binding = ItemStatusBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+ binding.postImages.adapter = TimelineImageAdapter()
+ binding.postIndicator.setViewPager(binding.postImages)
+ (binding.postImages.adapter as TimelineImageAdapter).registerAdapterDataObserver(binding.postIndicator.adapterDataObserver)
+ return BindingHolder(binding)
+ }
+
+ override fun onBindViewHolder(holder: BindingHolder, position: Int) {
+ getItem(position)?.let { status ->
+ holder.bind(status, displayWidth, listener, dateTimeFormatter)
+ }
+ }
+
+}
diff --git a/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/detail/DetailViewModel.kt b/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/detail/DetailViewModel.kt
new file mode 100644
index 0000000..776a3e0
--- /dev/null
+++ b/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/detail/DetailViewModel.kt
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2020 Conny Duck
+ *
+ * This file is part of Pixelcat.
+ *
+ * Pixelcat is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Pixelcat is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package at.connyduck.pixelcat.components.timeline.detail
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import at.connyduck.pixelcat.components.util.Loading
+import at.connyduck.pixelcat.components.util.Success
+import at.connyduck.pixelcat.components.util.UiState
+import at.connyduck.pixelcat.components.util.Error
+import at.connyduck.pixelcat.db.AccountManager
+import at.connyduck.pixelcat.db.AppDatabase
+import at.connyduck.pixelcat.db.entitity.StatusEntity
+import at.connyduck.pixelcat.db.entitity.toEntity
+import at.connyduck.pixelcat.network.FediverseApi
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+class DetailViewModel @Inject constructor(
+ val api: FediverseApi,
+ val db: AppDatabase,
+ val accountManager: AccountManager
+) : ViewModel() {
+
+ val currentStatus = MutableLiveData>()
+ val replies = MutableLiveData>>()
+
+ private var statusId = ""
+
+ fun setStatusId(statusId: String) {
+ this.statusId = statusId
+
+ currentStatus.value = Loading()
+ replies.value = Loading()
+
+ viewModelScope.launch {
+ db.statusDao().status(statusId, accountManager.activeAccount()?.id!!)?.let {
+ currentStatus.value = Success(it)
+ }
+ loadStatus()
+ }
+ viewModelScope.launch {
+ loadReplies()
+ }
+ }
+
+ fun reload() {
+ currentStatus.value = Loading()
+ replies.value = Loading()
+ viewModelScope.launch {
+ loadStatus()
+ }
+ viewModelScope.launch {
+ loadReplies()
+ }
+ }
+
+
+ private suspend fun loadStatus() {
+ api.status(statusId).fold({
+ val statusEntity = it.toEntity(accountManager.activeAccount()?.id!!)
+ db.statusDao().insertOrReplace(statusEntity)
+ currentStatus.value = Success(statusEntity)
+ }, {
+ currentStatus.value = Error(cause = it)
+ })
+ }
+
+ private suspend fun loadReplies() {
+ api.statusContext(statusId).fold({
+ replies.value = Success(it.descendants.map{
+ descendant -> descendant.toEntity(accountManager.activeAccount()?.id!!)
+ })
+ }, {
+ replies.value = Error(cause = it)
+ })
+ }
+
+}
diff --git a/app/src/main/kotlin/at/connyduck/pixelcat/dagger/ActivityModule.kt b/app/src/main/kotlin/at/connyduck/pixelcat/dagger/ActivityModule.kt
index 1a54c30..bdac11a 100644
--- a/app/src/main/kotlin/at/connyduck/pixelcat/dagger/ActivityModule.kt
+++ b/app/src/main/kotlin/at/connyduck/pixelcat/dagger/ActivityModule.kt
@@ -23,6 +23,7 @@ import at.connyduck.pixelcat.components.main.MainActivity
import at.connyduck.pixelcat.components.about.AboutActivity
import at.connyduck.pixelcat.components.about.licenses.LicenseActivity
import at.connyduck.pixelcat.components.compose.ComposeActivity
+import at.connyduck.pixelcat.components.timeline.detail.DetailActivity
import at.connyduck.pixelcat.components.login.LoginActivity
import at.connyduck.pixelcat.components.profile.ProfileActivity
import at.connyduck.pixelcat.components.settings.SettingsActivity
@@ -57,4 +58,7 @@ abstract class ActivityModule {
@ContributesAndroidInjector
abstract fun contributesComposeActivity(): ComposeActivity
+
+ @ContributesAndroidInjector
+ abstract fun contributesDetailActivity(): DetailActivity
}
diff --git a/app/src/main/kotlin/at/connyduck/pixelcat/dagger/ViewModelFactory.kt b/app/src/main/kotlin/at/connyduck/pixelcat/dagger/ViewModelFactory.kt
index d9c2b4f..9a0f565 100644
--- a/app/src/main/kotlin/at/connyduck/pixelcat/dagger/ViewModelFactory.kt
+++ b/app/src/main/kotlin/at/connyduck/pixelcat/dagger/ViewModelFactory.kt
@@ -17,13 +17,12 @@
* along with this program. If not, see .
*/
-// from https://proandroiddev.com/viewmodel-with-dagger2-architecture-components-2e06f06c9455
-
package at.connyduck.pixelcat.dagger
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import at.connyduck.pixelcat.components.compose.ComposeViewModel
+import at.connyduck.pixelcat.components.timeline.detail.DetailViewModel
import at.connyduck.pixelcat.components.login.LoginViewModel
import at.connyduck.pixelcat.components.main.MainViewModel
import at.connyduck.pixelcat.components.notifications.NotificationsViewModel
@@ -90,5 +89,10 @@ abstract class ViewModelModule {
@IntoMap
@ViewModelKey(ComposeViewModel::class)
internal abstract fun composeViewModel(viewModel: ComposeViewModel): ViewModel
+
+ @Binds
+ @IntoMap
+ @ViewModelKey(DetailViewModel::class)
+ internal abstract fun detailViewModel(viewModel: DetailViewModel): ViewModel
// Add more ViewModels here
}
diff --git a/app/src/main/kotlin/at/connyduck/pixelcat/db/TimelineDao.kt b/app/src/main/kotlin/at/connyduck/pixelcat/db/TimelineDao.kt
index 9e64da8..ce4ca4f 100644
--- a/app/src/main/kotlin/at/connyduck/pixelcat/db/TimelineDao.kt
+++ b/app/src/main/kotlin/at/connyduck/pixelcat/db/TimelineDao.kt
@@ -39,6 +39,9 @@ interface TimelineDao {
@Delete
suspend fun delete(status: StatusEntity)
+ @Query("SELECT * FROM StatusEntity WHERE id = :statusId AND accountId = :accountId")
+ suspend fun status(statusId: String, accountId: Long): StatusEntity?
+
@Query("SELECT * FROM StatusEntity WHERE accountId = :accountId ORDER BY LENGTH(id) DESC, id DESC")
fun statuses(accountId: Long): PagingSource
diff --git a/app/src/main/kotlin/at/connyduck/pixelcat/model/StatusContext.kt b/app/src/main/kotlin/at/connyduck/pixelcat/model/StatusContext.kt
new file mode 100644
index 0000000..60c0992
--- /dev/null
+++ b/app/src/main/kotlin/at/connyduck/pixelcat/model/StatusContext.kt
@@ -0,0 +1,9 @@
+package at.connyduck.pixelcat.model
+
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+data class StatusContext (
+ val ancestors: List,
+ val descendants: List
+)
diff --git a/app/src/main/kotlin/at/connyduck/pixelcat/network/FediverseApi.kt b/app/src/main/kotlin/at/connyduck/pixelcat/network/FediverseApi.kt
index 1b5c42f..e1b9cfa 100644
--- a/app/src/main/kotlin/at/connyduck/pixelcat/network/FediverseApi.kt
+++ b/app/src/main/kotlin/at/connyduck/pixelcat/network/FediverseApi.kt
@@ -19,13 +19,7 @@
package at.connyduck.pixelcat.network
-import at.connyduck.pixelcat.model.AccessToken
-import at.connyduck.pixelcat.model.Account
-import at.connyduck.pixelcat.model.AppCredentials
-import at.connyduck.pixelcat.model.Attachment
-import at.connyduck.pixelcat.model.NewStatus
-import at.connyduck.pixelcat.model.Relationship
-import at.connyduck.pixelcat.model.Status
+import at.connyduck.pixelcat.model.*
import at.connyduck.pixelcat.network.calladapter.NetworkResponse
import okhttp3.MultipartBody
import retrofit2.http.Body
@@ -183,4 +177,14 @@ interface FediverseApi {
suspend fun unreblogStatus(
@Path("id") statusId: String
): NetworkResponse
+
+ @GET("api/v1/statuses/{id}")
+ suspend fun status(
+ @Path("id") statusId: String
+ ): NetworkResponse
+
+ @GET("api/v1/statuses/{id}/context")
+ suspend fun statusContext(
+ @Path("id") statusId: String
+ ): NetworkResponse
}
diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml
new file mode 100644
index 0000000..a61b003
--- /dev/null
+++ b/app/src/main/res/layout/activity_detail.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_reply.xml b/app/src/main/res/layout/item_reply.xml
new file mode 100644
index 0000000..c2c693d
--- /dev/null
+++ b/app/src/main/res/layout/item_reply.xml
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file