Fix up magical stuff

Signed-off-by: Mario Danic <mario@lovelyhq.com>
This commit is contained in:
Mario Danic 2019-09-16 12:49:12 +02:00
parent 0b7ce8295c
commit 85b75b7da5
6 changed files with 316 additions and 7 deletions

View File

@ -39,8 +39,6 @@ import android.view.inputmethod.EditorInfo;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import com.afollestad.materialdialogs.LayoutMode;
import com.afollestad.materialdialogs.MaterialDialog;
import com.bluelinelabs.conductor.RouterTransaction;
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler;
import com.bluelinelabs.logansquare.LoganSquare;
@ -57,7 +55,6 @@ import com.nextcloud.talk.controllers.bottomsheet.EntryMenuController;
import com.nextcloud.talk.controllers.bottomsheet.OperationsMenuController;
import com.nextcloud.talk.events.BottomSheetLockEvent;
import com.nextcloud.talk.jobs.AddParticipantsToConversation;
import com.nextcloud.talk.jobs.DeleteConversationWorker;
import com.nextcloud.talk.models.RetrofitBucket;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.autocomplete.AutocompleteOverall;

View File

@ -54,6 +54,9 @@ import com.nextcloud.talk.adapters.items.UserItem
import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.controllers.base.BaseController
import com.nextcloud.talk.controllers.bottomsheet.items.BasicListItemWithImage
import com.nextcloud.talk.controllers.bottomsheet.items.ListItemWithImage
import com.nextcloud.talk.controllers.bottomsheet.items.listItemsWithImage
import com.nextcloud.talk.events.BottomSheetLockEvent
import com.nextcloud.talk.events.EventStatus
import com.nextcloud.talk.jobs.DeleteConversationWorker
@ -593,9 +596,9 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
if (participant.userId != conversationUser!!.userId) {
val items = mutableListOf(
context.getString(R.string.nc_promote),
context.getString(R.string.nc_demote),
context.getString(R.string.nc_remove_participant)
BasicListItemWithImage(R.drawable.ic_pencil_grey600_24dp, context.getString(R.string.nc_promote)),
BasicListItemWithImage(R.drawable.ic_pencil_grey600_24dp, context.getString(R.string.nc_demote)),
BasicListItemWithImage(R.drawable.ic_delete_grey600_24dp, context.getString(R.string.nc_remove_participant))
)
if (participant.type == Participant.ParticipantType.MODERATOR) {
@ -610,8 +613,9 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
MaterialDialog(activity!!, BottomSheet(WRAP_CONTENT)).show {
cornerRadius(res = R.dimen.corner_radius)
title(text = participant.displayName)
listItems(items = items) { dialog, index, text ->
listItemsWithImage(items = items) { dialog, index, _ ->
if (index == 0) {
if (participant.type == Participant.ParticipantType.MODERATOR) {

View File

@ -0,0 +1,38 @@
/*
* Nextcloud Talk application
*
* @author Mario Danic
* Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
*
* This program 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.
*
* 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 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 <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.talk.controllers.bottomsheet.items
import android.widget.ImageView
import androidx.annotation.DrawableRes
interface ListItemWithImage {
val title: String
fun populateIcon(imageView: ImageView)
}
data class BasicListItemWithImage(
@DrawableRes val iconRes: Int,
override val title: String) : ListItemWithImage {
override fun populateIcon(imageView: ImageView) {
imageView.setImageResource(iconRes)
}
}

View File

@ -0,0 +1,151 @@
/*
* Nextcloud Talk application
*
* @author Mario Danic
* Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
*
* This program 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.
*
* 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 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 <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.talk.controllers.bottomsheet.items
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.WhichButton
import com.afollestad.materialdialogs.actions.hasActionButton
import com.afollestad.materialdialogs.actions.hasActionButtons
import com.afollestad.materialdialogs.internal.list.DialogAdapter
import com.afollestad.materialdialogs.internal.rtl.RtlTextView
import com.afollestad.materialdialogs.list.getItemSelector
import com.afollestad.materialdialogs.utils.MDUtil.inflate
import com.afollestad.materialdialogs.utils.MDUtil.maybeSetTextColor
import com.google.android.material.textview.MaterialTextView
import com.nextcloud.talk.R
private const val KEY_ACTIVATED_INDEX = "activated_index"
internal class ListItemViewHolder(
itemView: View,
private val adapter: ListIconDialogAdapter<*>) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
init {
itemView.setOnClickListener(this)
}
val iconView: ImageView = itemView.findViewById(R.id.icon)
val titleView: RtlTextView = itemView.findViewById(R.id.title)
override fun onClick(view: View) = adapter.itemClicked(adapterPosition)
}
internal class ListIconDialogAdapter<IT : ListItemWithImage>(
private var dialog: MaterialDialog,
private var items: List<IT>,
disabledItems: IntArray?,
private var waitForPositiveButton: Boolean,
private var selection: ListItemListener<IT>) : RecyclerView.Adapter<ListItemViewHolder>(), DialogAdapter<IT, ListItemListener<IT>> {
private var disabledIndices: IntArray = disabledItems ?: IntArray(0)
fun itemClicked(index: Int) {
if (waitForPositiveButton && dialog.hasActionButton(WhichButton.POSITIVE)) {
// Wait for positive action button, mark clicked item as activated so that we can call the
// selection listener when the button is pressed.
val lastActivated = dialog.config[KEY_ACTIVATED_INDEX] as? Int
dialog.config[KEY_ACTIVATED_INDEX] = index
if (lastActivated != null) {
notifyItemChanged(lastActivated)
}
notifyItemChanged(index)
} else {
// Don't wait for action buttons, call listener and dismiss if auto dismiss is applicable
this.selection?.invoke(dialog, index, this.items[index])
if (dialog.autoDismissEnabled && !dialog.hasActionButtons()) {
dialog.dismiss()
}
}
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int): ListItemViewHolder {
val listItemView: View = parent.inflate(dialog.windowContext, R.layout.menu_item_sheet)
val viewHolder = ListItemViewHolder(
itemView = listItemView,
adapter = this
)
viewHolder.titleView.maybeSetTextColor(dialog.windowContext, R.attr.md_color_content)
return viewHolder
}
override fun getItemCount() = items.size
override fun onBindViewHolder(
holder: ListItemViewHolder,
position: Int) {
holder.itemView.isEnabled = !disabledIndices.contains(position)
val currentItem = items[position]
holder.titleView.text = currentItem.title
holder.itemView.background = dialog.getItemSelector()
currentItem.populateIcon(holder.iconView)
val activatedIndex = dialog.config[KEY_ACTIVATED_INDEX] as? Int
holder.itemView.isActivated = activatedIndex != null && activatedIndex == position
if (dialog.bodyFont != null) {
holder.titleView.typeface = dialog.bodyFont
}
}
override fun positiveButtonClicked() {
val activatedIndex = dialog.config[KEY_ACTIVATED_INDEX] as? Int
if (activatedIndex != null) {
selection?.invoke(dialog, activatedIndex, items[activatedIndex])
dialog.config.remove(KEY_ACTIVATED_INDEX)
}
}
override fun replaceItems(
items: List<IT>,
listener: ListItemListener<IT>) {
this.items = items
if (listener != null) {
this.selection = listener
}
this.notifyDataSetChanged()
}
override fun disableItems(indices: IntArray) {
this.disabledIndices = indices
notifyDataSetChanged()
}
override fun checkItems(indices: IntArray) = Unit
override fun uncheckItems(indices: IntArray) = Unit
override fun toggleItems(indices: IntArray) = Unit
override fun checkAllItems() = Unit
override fun uncheckAllItems() = Unit
override fun toggleAllChecked() = Unit
override fun isItemChecked(index: Int) = false
}

View File

@ -0,0 +1,75 @@
/*
* Nextcloud Talk application
*
* @author Mario Danic
* Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
*
* This program 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.
*
* 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 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 <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.talk.controllers.bottomsheet.items
import androidx.annotation.CheckResult
import androidx.recyclerview.widget.LinearLayoutManager
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.internal.list.DialogAdapter
import com.afollestad.materialdialogs.list.customListAdapter
import com.afollestad.materialdialogs.list.getListAdapter
typealias ListItemListener<IT> =
((dialog: MaterialDialog, index: Int, item: IT) -> Unit)?
@CheckResult fun <IT : ListItemWithImage> MaterialDialog.listItemsWithImage(
items: List<IT>,
disabledIndices: IntArray? = null,
waitForPositiveButton: Boolean = true,
selection: ListItemListener<IT> = null): MaterialDialog {
if (getListAdapter() != null) {
return updateListItemsWithImage(
items = items,
disabledIndices = disabledIndices
)
}
val layoutManager = LinearLayoutManager(windowContext)
return customListAdapter(
adapter = ListIconDialogAdapter(
dialog = this,
items = items,
disabledItems = disabledIndices,
waitForPositiveButton = waitForPositiveButton,
selection = selection
),
layoutManager = layoutManager
)
}
fun MaterialDialog.updateListItemsWithImage(
items: List<ListItemWithImage>,
disabledIndices: IntArray? = null): MaterialDialog {
val adapter = getListAdapter()
check(adapter != null) {
"updateGridItems(...) can't be used before you've created a bottom sheet grid dialog."
}
if (adapter is DialogAdapter<*, *>) {
@Suppress("UNCHECKED_CAST")
(adapter as DialogAdapter<ListItemWithImage, *>).replaceItems(items)
if (disabledIndices != null) {
adapter.disableItems(disabledIndices)
}
}
return this
}

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Nextcloud Talk application
~
~ @author Mario Danic
~ Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
~
~ This program 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.
~
~ 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 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 <http://www.gnu.org/licenses/>.
-->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
style="@style/MD_ListItem">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="center"
android:layout_centerVertical="true"
tools:src="@drawable/ic_delete_grey600_24dp"
android:layout_marginStart="16dp"
tools:ignore="ContentDescription"
/>
<com.afollestad.materialdialogs.internal.rtl.RtlTextView
android:id="@+id/title"
tools:text="Item"
android:layout_toEndOf="@id/icon"
style="@style/MD_ListItemText" />
</RelativeLayout>
</FrameLayout>