/* * Nextcloud Android client application * * @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 * License as published by the Free Software Foundation; either * version 3 of the License, or 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 . */ package com.nextcloud.ui import android.accounts.Account import android.annotation.SuppressLint import android.app.Dialog import android.content.Context import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.annotation.VisibleForTesting import androidx.fragment.app.DialogFragment import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.dialog.MaterialAlertDialogBuilder 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.lib.resources.users.StatusType import com.owncloud.android.ui.activity.BaseActivity import com.owncloud.android.ui.adapter.PredefinedStatusClickListener import com.owncloud.android.ui.adapter.PredefinedStatusListAdapter 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(), 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 private lateinit var adapter: PredefinedStatusListAdapter private var selectedPredefinedMessageId: String? = null @Inject lateinit var arbitraryDataProvider: ArbitraryDataProvider @Inject lateinit var asyncRunner: AsyncRunner @Inject lateinit var clientFactory: ClientFactory override fun onCreate(savedInstanceState: Bundle?) { 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) if (json.isNotEmpty()) { val myType = object : TypeToken>() {}.type predefinedStatus = Gson().fromJson(json, myType) } } } @SuppressLint("InflateParams") override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { dialogView = LayoutInflater.from(requireContext()).inflate(R.layout.dialog_set_status, null) return MaterialAlertDialogBuilder(requireContext()) .setView(dialogView) .create() } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) accountManager = (activity as BaseActivity).userAccountManager 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 { 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 { 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 { 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 { override fun invoke(): Boolean { val client = OwnCloudClientFactory.createNextcloudClient(account, context) return ClearStatusMessageRemoteOperation().execute(client).isSuccess } } /** * Fragment creator */ companion object { @JvmStatic fun newInstance(user: User, status: Status?) = SetStatusDialogFragment().apply { arguments = Bundle().apply { putParcelable(ARG_CURRENT_USER_PARAM, user) putParcelable(ARG_CURRENT_STATUS_PARAM, status) } } } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return dialogView } override fun onClick(predefinedStatus: PredefinedStatus) { selectedPredefinedMessageId = predefinedStatus.id emoji.text = predefinedStatus.icon customStatusInput.text.clear() customStatusInput.text.append(predefinedStatus.message) } @VisibleForTesting fun setPredefinedStatus(predefinedStatus: ArrayList) { adapter.list = predefinedStatus predefinedStatusList.adapter?.notifyDataSetChanged() } }