From 4984a6875011404c11d9118db427f98ebbf2dc9b Mon Sep 17 00:00:00 2001 From: Konrad Pozniak Date: Sat, 13 Jun 2020 19:55:36 +0200 Subject: [PATCH] add sensitive media overlay --- .../components/timeline/TimelineFragment.kt | 6 +- .../timeline/TimelineListAdapter.kt | 7 + .../components/timeline/TimelineViewModel.kt | 37 +-- .../at/connyduck/pixelcat/db/TimelineDao.kt | 3 + .../db/entitity/TimelineStatusEntity.kt | 2 +- app/src/main/res/layout/item_status.xml | 256 +++++++++--------- app/src/main/res/values/strings.xml | 1 + 7 files changed, 169 insertions(+), 143 deletions(-) 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 f6d970b..9044bdb 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 @@ -46,7 +46,7 @@ class TimelineFragment : DaggerFragment(R.layout.fragment_timeline), TimeLineAct binding.timelineRecyclerView.addItemDecoration(DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL)) lifecycleScope.launch { - viewModel.flow.collectLatest { pagingData -> + viewModel.statusFlow.collectLatest { pagingData -> adapter.submitData(pagingData) } } @@ -77,4 +77,8 @@ class TimelineFragment : DaggerFragment(R.layout.fragment_timeline), TimeLineAct override fun onReply(status: StatusEntity) { TODO("Not yet implemented") } + + override fun onMediaVisibilityChanged(status: StatusEntity) { + viewModel.onMediaVisibilityChanged(status) + } } 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 e1534d8..b577192 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 @@ -18,6 +18,7 @@ interface TimeLineActionListener { fun onFavorite(post: StatusEntity) fun onBoost(post: StatusEntity) fun onReply(status: StatusEntity) + fun onMediaVisibilityChanged(status: StatusEntity) } object TimelineDiffUtil : DiffUtil.ItemCallback() { @@ -82,6 +83,12 @@ class TimelineListAdapter( 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) + } } } } diff --git a/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/TimelineViewModel.kt b/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/TimelineViewModel.kt index 0aa4467..db05bc3 100644 --- a/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/TimelineViewModel.kt +++ b/app/src/main/kotlin/at/connyduck/pixelcat/components/timeline/TimelineViewModel.kt @@ -1,6 +1,5 @@ package at.connyduck.pixelcat.components.timeline -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.paging.ExperimentalPagingApi @@ -11,37 +10,39 @@ import at.connyduck.pixelcat.db.AccountManager import at.connyduck.pixelcat.db.AppDatabase import at.connyduck.pixelcat.db.entitity.StatusEntity import at.connyduck.pixelcat.network.FediverseApi +import kotlinx.coroutines.FlowPreview +import kotlinx.coroutines.flow.asFlow +import kotlinx.coroutines.flow.flatMapConcat import kotlinx.coroutines.launch import javax.inject.Inject class TimelineViewModel @Inject constructor( - // private val repository: TimelineRepo, private val accountManager: AccountManager, private val db: AppDatabase, fediverseApi: FediverseApi ) : ViewModel() { - private val accountId = MutableLiveData() - - init { - viewModelScope.launch { - val currentAccountId = accountManager.activeAccount()?.id!! - accountId.postValue(currentAccountId) - } - } - + @OptIn(FlowPreview::class) @ExperimentalPagingApi - val flow = Pager( - // Configure how data is loaded by passing additional properties to - // PagingConfig, such as prefetchDistance. - config = PagingConfig(pageSize = 10, enablePlaceholders = false), - remoteMediator = TimelineRemoteMediator(0, fediverseApi, db), - pagingSourceFactory = { db.statusDao().statuses(0) } - ).flow.cachedIn(viewModelScope) + val statusFlow = accountManager::activeAccount.asFlow() + .flatMapConcat { activeAccount -> + Pager( + config = PagingConfig(pageSize = 10, enablePlaceholders = false), + remoteMediator = TimelineRemoteMediator(activeAccount?.id!!, fediverseApi, db), + pagingSourceFactory = { db.statusDao().statuses(activeAccount.id) } + ).flow + } + .cachedIn(viewModelScope) fun onFavorite(status: StatusEntity) { viewModelScope.launch { // repository.onFavorite(status, accountManager.activeAccount()?.id!!) } } + + fun onMediaVisibilityChanged(status: StatusEntity) { + viewModelScope.launch { + db.statusDao().changeMediaVisibility(!status.mediaVisible, status.id, accountManager.activeAccount()?.id!!) + } + } } 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 62cd56a..ae8bf3f 100644 --- a/app/src/main/kotlin/at/connyduck/pixelcat/db/TimelineDao.kt +++ b/app/src/main/kotlin/at/connyduck/pixelcat/db/TimelineDao.kt @@ -25,4 +25,7 @@ interface TimelineDao { @Query("DELETE FROM StatusEntity WHERE accountId = :accountId") suspend fun clearAll(accountId: Long) + + @Query("UPDATE StatusEntity SET mediaVisible = :visible WHERE id = :statusId AND accountId = :accountId") + suspend fun changeMediaVisibility(visible: Boolean, statusId: String, accountId: Long) } diff --git a/app/src/main/kotlin/at/connyduck/pixelcat/db/entitity/TimelineStatusEntity.kt b/app/src/main/kotlin/at/connyduck/pixelcat/db/entitity/TimelineStatusEntity.kt index 016fe19..936e9fa 100644 --- a/app/src/main/kotlin/at/connyduck/pixelcat/db/entitity/TimelineStatusEntity.kt +++ b/app/src/main/kotlin/at/connyduck/pixelcat/db/entitity/TimelineStatusEntity.kt @@ -32,7 +32,7 @@ data class StatusEntity( val mediaVisible: Boolean ) -fun Status.toEntity(accountId: Long, mediaPosition: Int = 0, mediaVisible: Boolean = this.sensitive) = StatusEntity( +fun Status.toEntity(accountId: Long, mediaPosition: Int = 0, mediaVisible: Boolean = !this.sensitive) = StatusEntity( accountId = accountId, id = id, url = actionableStatus.url, diff --git a/app/src/main/res/layout/item_status.xml b/app/src/main/res/layout/item_status.xml index aa529d4..363d4e3 100644 --- a/app/src/main/res/layout/item_status.xml +++ b/app/src/main/res/layout/item_status.xml @@ -1,137 +1,147 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:sparkbutton="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingBottom="8dp"> + android:id="@+id/postAvatar" + android:layout_width="50dp" + android:layout_height="50dp" + android:layout_marginStart="16dp" + android:layout_marginTop="8dp" + android:importantForAccessibility="no" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:background="#f00" /> + android:id="@+id/postDisplayName" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:ellipsize="end" + android:lines="1" + android:textStyle="bold" + app:layout_constraintBottom_toTopOf="@id/postName" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@id/postAvatar" + app:layout_constraintTop_toTopOf="@id/postAvatar" + tools:text="Conny Duck" /> + android:id="@+id/postName" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:ellipsize="end" + android:lines="1" + app:layout_constraintBottom_toBottomOf="@id/postAvatar" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@id/postAvatar" + app:layout_constraintTop_toBottomOf="@id/postDisplayName" + tools:text="\@connyduck\@chaos.social" /> - - - - - - - - - - + android:id="@+id/postImages" + android:layout_width="match_parent" + android:layout_height="200dp" + android:layout_marginTop="8dp" + android:background="#000" + android:orientation="horizontal" + app:layout_constraintTop_toBottomOf="@id/postAvatar" /> + android:id="@+id/postSensitiveMediaOverlay" + android:layout_width="match_parent" + android:layout_height="0dp" + android:background="#ccc" + android:gravity="center" + android:textStyle="bold" + android:text="@string/sensitive_media" + app:layout_constraintBottom_toBottomOf="@id/postImages" + app:layout_constraintTop_toTopOf="@id/postImages" /> + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4b09863..6d370f6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -74,5 +74,6 @@ Menu Accounts Add Account + Sensitive media