Signed-off-by: tobiasKaminsky <tobias@kaminsky.me>
This commit is contained in:
tobiasKaminsky 2020-10-26 13:07:20 +01:00 committed by Andy Scherzinger
parent ad5ca22e23
commit fcb0147d71
No known key found for this signature in database
GPG key ID: 6CADC7E3523C308B
6 changed files with 171 additions and 57 deletions

View file

@ -61,6 +61,7 @@ class ChooseAccountDialogFragment : DialogFragment(),
private lateinit var dialogView: View
private var currentUser: User? = null
private lateinit var accountManager: UserAccountManager
private lateinit var currentStatus: Status
@Inject
lateinit var clientFactory: ClientFactory
@ -131,7 +132,7 @@ class ChooseAccountDialogFragment : DialogFragment(),
}
set_status.setOnClickListener {
val setStatusDialog = SetStatusDialogFragment.newInstance(accountManager.user)
val setStatusDialog = SetStatusDialogFragment.newInstance(accountManager.user, currentStatus)
setStatusDialog.show((activity as DrawerActivity).supportFragmentManager, "fragment_set_status")
dismiss()
@ -196,6 +197,8 @@ class ChooseAccountDialogFragment : DialogFragment(),
}
fun setStatus(newStatus: Status) {
currentStatus = newStatus
val size = DisplayUtils.convertDpToPixel(9f, context)
ticker.background = null
ticker.setImageDrawable(StatusDrawable(newStatus, size.toFloat(), context))

View file

@ -1,8 +1,8 @@
/*
* Nextcloud Android client application
*
* @author Infomaniak Network SA
* Copyright (C) 2020 Infomaniak Network SA
* @author Tobias Kaminsky
* Copyright (C) 2020 Nextcloud GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
@ -20,14 +20,14 @@
package com.nextcloud.ui
import android.accounts.Account
import android.annotation.SuppressLint
import android.app.Dialog
import android.graphics.drawable.Drawable
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.annotation.VisibleForTesting
import androidx.fragment.app.DialogFragment
import androidx.recyclerview.widget.LinearLayoutManager
@ -36,38 +36,45 @@ import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.nextcloud.client.account.User
import com.nextcloud.client.account.UserAccountManager
import com.nextcloud.client.core.AsyncRunner
import com.nextcloud.client.di.Injectable
import com.nextcloud.client.network.ClientFactory
import com.owncloud.android.R
import com.owncloud.android.datamodel.ArbitraryDataProvider
import com.owncloud.android.lib.common.OwnCloudClientFactory
import com.owncloud.android.lib.resources.users.ClearStatusMessageRemoteOperation
import com.owncloud.android.lib.resources.users.PredefinedStatus
import com.owncloud.android.lib.resources.users.SetPredefinedCustomStatusMessageRemoteOperation
import com.owncloud.android.lib.resources.users.SetStatusRemoteOperation
import com.owncloud.android.lib.resources.users.SetUserDefinedCustomStatusMessageRemoteOperation
import com.owncloud.android.lib.resources.users.Status
import com.owncloud.android.ui.StatusDrawable
import com.owncloud.android.lib.resources.users.StatusType
import com.owncloud.android.ui.activity.BaseActivity
import com.owncloud.android.ui.activity.DrawerActivity
import com.owncloud.android.ui.adapter.PredefinedStatusClickListener
import com.owncloud.android.ui.adapter.PredefinedStatusListAdapter
import com.owncloud.android.ui.adapter.UserListAdapter
import com.owncloud.android.utils.DisplayUtils
import com.owncloud.android.utils.DisplayUtils.AvatarGenerationListener
import kotlinx.android.synthetic.main.account_item.*
import kotlinx.android.synthetic.main.dialog_set_status.*
import java.util.ArrayList
import javax.inject.Inject
private const val ARG_CURRENT_USER_PARAM = "currentUser"
private const val ARG_CURRENT_STATUS_PARAM = "currentStatus"
class SetStatusDialogFragment : DialogFragment(),
AvatarGenerationListener,
UserListAdapter.ClickListener,
PredefinedStatusClickListener,
Injectable {
private lateinit var dialogView: View
private var currentUser: User? = null
private var currentStatus: Status? = null
private lateinit var accountManager: UserAccountManager
private lateinit var predefinedStatus: ArrayList<PredefinedStatus>
private lateinit var adapter: PredefinedStatusListAdapter
private var selectedPredefinedMessageId: String? = null
@Inject
lateinit var arbitraryDataProvider: ArbitraryDataProvider
private lateinit var adapter: PredefinedStatusListAdapter
@Inject
lateinit var asyncRunner: AsyncRunner
@Inject
lateinit var clientFactory: ClientFactory
@ -76,6 +83,7 @@ class SetStatusDialogFragment : DialogFragment(),
super.onCreate(savedInstanceState)
arguments?.let {
currentUser = it.getParcelable(ARG_CURRENT_USER_PARAM)
currentStatus = it.getParcelable(ARG_CURRENT_STATUS_PARAM)
val json = arbitraryDataProvider.getValue(currentUser, ArbitraryDataProvider.PREDEFINED_STATUS)
@ -98,12 +106,110 @@ class SetStatusDialogFragment : DialogFragment(),
super.onViewCreated(view, savedInstanceState)
accountManager = (activity as BaseActivity).userAccountManager
adapter = PredefinedStatusListAdapter(requireContext())
currentStatus?.let {
emoji.text = it.icon
customStatusInput.text.clear()
customStatusInput.text.append(it.message)
}
adapter = PredefinedStatusListAdapter(this, requireContext())
if (this::predefinedStatus.isInitialized) {
adapter.list = predefinedStatus
}
predefinedStatusList.adapter = adapter
predefinedStatusList.layoutManager = LinearLayoutManager(context)
onlineStatus.setOnClickListener { setStatus(StatusType.ONLINE) }
dndStatus.setOnClickListener { setStatus(StatusType.DND) }
awayStatus.setOnClickListener { setStatus(StatusType.AWAY) }
invisibleStatus.setOnClickListener { setStatus(StatusType.INVISIBLE) }
clearStatus.setOnClickListener { clearStatus() }
setStatus.setOnClickListener { setStatusMessage() }
}
private fun clearStatus() {
asyncRunner.postQuickTask(ClearStatusTask(accountManager.currentOwnCloudAccount?.savedAccount, context),
{ dismiss(it) })
}
private fun setStatus(statusType: StatusType) {
asyncRunner.postQuickTask(
SetStatusTask(
statusType,
accountManager.currentOwnCloudAccount?.savedAccount,
context)
)
}
private fun setStatusMessage() {
if (selectedPredefinedMessageId != null) {
asyncRunner.postQuickTask(
SetPredefinedCustomStatusTask(
selectedPredefinedMessageId!!,
1603719631,
accountManager.currentOwnCloudAccount?.savedAccount,
context),
{ dismiss(it) }
)
} else {
asyncRunner.postQuickTask(
SetUserDefinedCustomStatusTask(
customStatusInput.text.toString(),
emoji.text.toString(),
1603719631,
accountManager.currentOwnCloudAccount?.savedAccount,
context),
{ dismiss(it) }
)
}
}
private fun dismiss(boolean: Boolean) {
if (boolean) {
dismiss()
}
}
private class SetPredefinedCustomStatusTask(val messageId: String,
val clearAt: Long,
val account: Account?,
val context: Context?) : Function0<Boolean> {
override fun invoke(): Boolean {
val client = OwnCloudClientFactory.createNextcloudClient(account, context)
return SetPredefinedCustomStatusMessageRemoteOperation(messageId, clearAt).execute(client).isSuccess
}
}
private class SetUserDefinedCustomStatusTask(val message: String,
val icon: String,
val clearAt: Long,
val account: Account?,
val context: Context?) : Function0<Boolean> {
override fun invoke(): Boolean {
val client = OwnCloudClientFactory.createNextcloudClient(account, context)
return SetUserDefinedCustomStatusMessageRemoteOperation(message, icon, clearAt).execute(client).isSuccess
}
}
private class SetStatusTask(val statusType: StatusType,
val account: Account?,
val context: Context?) : Function0<Boolean> {
override fun invoke(): Boolean {
val client = OwnCloudClientFactory.createNextcloudClient(account, context)
return SetStatusRemoteOperation(statusType).execute(client).isSuccess
}
}
private class ClearStatusTask(val account: Account?, val context: Context?) : Function0<Boolean> {
override fun invoke(): Boolean {
val client = OwnCloudClientFactory.createNextcloudClient(account, context)
return ClearStatusMessageRemoteOperation().execute(client).isSuccess
}
}
/**
@ -111,10 +217,11 @@ class SetStatusDialogFragment : DialogFragment(),
*/
companion object {
@JvmStatic
fun newInstance(user: User) =
fun newInstance(user: User, status: Status?) =
SetStatusDialogFragment().apply {
arguments = Bundle().apply {
putParcelable(ARG_CURRENT_USER_PARAM, user)
putParcelable(ARG_CURRENT_STATUS_PARAM, status)
}
}
}
@ -123,39 +230,11 @@ class SetStatusDialogFragment : DialogFragment(),
return dialogView
}
override fun shouldCallGeneratedCallback(tag: String?, callContext: Any?): Boolean {
return (callContext as ImageView).tag.toString() == tag
}
override fun avatarGenerated(avatarDrawable: Drawable?, callContext: Any?) {
if (user_icon != null) {
user_icon.setImageDrawable(avatarDrawable)
}
}
override fun onAccountClicked(user: User?) {
(activity as DrawerActivity).accountClicked(user.hashCode())
}
override fun onOptionItemClicked(user: User?, view: View?) {
// Un-needed for this context
}
fun setStatus(newStatus: Status) {
val size = DisplayUtils.convertDpToPixel(9f, context)
ticker.background = null
ticker.setImageDrawable(StatusDrawable(newStatus, size.toFloat(), context))
ticker.visibility = View.VISIBLE
if (newStatus.message.isNullOrBlank()) {
status.text = ""
status.visibility = View.GONE
} else {
status.text = newStatus.message
status.visibility = View.VISIBLE
}
view?.invalidate()
override fun onClick(predefinedStatus: PredefinedStatus) {
selectedPredefinedMessageId = predefinedStatus.id
emoji.text = predefinedStatus.icon
customStatusInput.text.clear()
customStatusInput.text.append(predefinedStatus.message)
}
@VisibleForTesting

View file

@ -0,0 +1,29 @@
/*
*
* Nextcloud Android client application
*
* @author Tobias Kaminsky
* Copyright (C) 2020 Tobias Kaminsky
* Copyright (C) 2020 Nextcloud GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.owncloud.android.ui.adapter
import com.owncloud.android.lib.resources.users.PredefinedStatus
interface PredefinedStatusClickListener {
fun onClick(predefinedStatus: PredefinedStatus)
}

View file

@ -29,7 +29,8 @@ import androidx.recyclerview.widget.RecyclerView
import com.owncloud.android.databinding.PredefinedStatusBinding
import com.owncloud.android.lib.resources.users.PredefinedStatus
class PredefinedStatusListAdapter(val context: Context) : RecyclerView.Adapter<PredefinedStatusViewHolder>() {
class PredefinedStatusListAdapter(private val clickListener: PredefinedStatusClickListener,
val context: Context) : RecyclerView.Adapter<PredefinedStatusViewHolder>() {
internal var list: List<PredefinedStatus> = emptyList()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PredefinedStatusViewHolder {
@ -38,7 +39,7 @@ class PredefinedStatusListAdapter(val context: Context) : RecyclerView.Adapter<P
}
override fun onBindViewHolder(holder: PredefinedStatusViewHolder, position: Int) {
holder.bind(list[position], context)
holder.bind(list[position], clickListener, context)
}
override fun getItemCount(): Int {

View file

@ -30,7 +30,8 @@ import com.owncloud.android.lib.resources.users.PredefinedStatus
import com.owncloud.android.utils.DisplayUtils
class PredefinedStatusViewHolder(private val binding: PredefinedStatusBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(status: PredefinedStatus, context: Context) {
fun bind(status: PredefinedStatus, clickListener: PredefinedStatusClickListener, context: Context) {
binding.root.setOnClickListener { clickListener.onClick(status) }
binding.icon.text = status.icon
binding.name.text = status.message

View file

@ -165,12 +165,13 @@
tools:layout_editor_absoluteX="201dp"
tools:layout_editor_absoluteY="141dp">
<ImageButton
android:id="@+id/imageButton"
android:layout_width="wrap_content"
<TextView
android:id="@+id/emoji"
android:layout_width="48dp"
android:layout_height="match_parent"
android:contentDescription="@string/set_status_icon"
android:src="@drawable/ic_cloud_sync_on" />
android:textSize="25sp"
android:gravity="center"
tools:text="☁️" />
<EditText
android:id="@+id/customStatusInput"