mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-01-18 12:56:45 -06:00
[Messages/Compose] Add dropdown icon to show all recipient categories. Add before-send confirmation dialog.
This commit is contained in:
parent
c8c1fe5367
commit
82b232d0e5
@ -17,6 +17,7 @@ import android.text.style.StyleSpan
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.AutoCompleteTextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.text.HtmlCompat
|
import androidx.core.text.HtmlCompat
|
||||||
import androidx.core.widget.addTextChangedListener
|
import androidx.core.widget.addTextChangedListener
|
||||||
@ -72,8 +73,6 @@ class MessagesComposeFragment : Fragment(), CoroutineScope {
|
|||||||
context ?: return null
|
context ?: return null
|
||||||
app = activity.application as App
|
app = activity.application as App
|
||||||
context!!.theme.applyStyle(Themes.appTheme, true)
|
context!!.theme.applyStyle(Themes.appTheme, true)
|
||||||
if (app.profile == null)
|
|
||||||
return inflater.inflate(R.layout.fragment_loading, container, false)
|
|
||||||
// activity, context and profile is valid
|
// activity, context and profile is valid
|
||||||
b = MessagesComposeFragmentBinding.inflate(inflater)
|
b = MessagesComposeFragmentBinding.inflate(inflater)
|
||||||
return b.root
|
return b.root
|
||||||
@ -84,7 +83,7 @@ class MessagesComposeFragment : Fragment(), CoroutineScope {
|
|||||||
}
|
}
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
// TODO check if app, activity, b can be null
|
// TODO check if app, activity, b can be null
|
||||||
if (app.profile == null || !isAdded)
|
if (!isAdded)
|
||||||
return
|
return
|
||||||
|
|
||||||
EventBus.getDefault().register(this)
|
EventBus.getDefault().register(this)
|
||||||
@ -190,80 +189,94 @@ class MessagesComposeFragment : Fragment(), CoroutineScope {
|
|||||||
override fun createChip(context: Context, text: CharSequence, data: Any?): ChipSpan? {
|
override fun createChip(context: Context, text: CharSequence, data: Any?): ChipSpan? {
|
||||||
if (data == null || data !is Teacher)
|
if (data == null || data !is Teacher)
|
||||||
return null
|
return null
|
||||||
if (data.id in -24L..0L) {
|
if (data.id !in -24L..0L) {
|
||||||
val type = (data.id * -1).toInt()
|
b.recipients.allChips.forEach {
|
||||||
|
if (it.data == data) {
|
||||||
val textColorPrimary = android.R.attr.textColorPrimary.resolveAttr(activity)
|
Toast.makeText(activity, R.string.messages_compose_recipient_exists, Toast.LENGTH_SHORT).show()
|
||||||
val textColorSecondary = android.R.attr.textColorSecondary.resolveAttr(activity)
|
return null
|
||||||
|
|
||||||
val category = mutableListOf<Teacher>()
|
|
||||||
val categoryNames = mutableListOf<CharSequence>()
|
|
||||||
val categoryCheckedItems = mutableListOf<Boolean>()
|
|
||||||
teachers.forEach { teacher ->
|
|
||||||
if (teacher.isType(type)) {
|
|
||||||
category += teacher
|
|
||||||
val name = teacher.fullName
|
|
||||||
val description = when (type) {
|
|
||||||
Teacher.TYPE_TEACHER -> null
|
|
||||||
Teacher.TYPE_PARENTS_COUNCIL -> teacher.typeDescription
|
|
||||||
Teacher.TYPE_SCHOOL_PARENTS_COUNCIL -> null
|
|
||||||
Teacher.TYPE_PEDAGOGUE -> null
|
|
||||||
Teacher.TYPE_LIBRARIAN -> null
|
|
||||||
Teacher.TYPE_SCHOOL_ADMIN -> null
|
|
||||||
Teacher.TYPE_SUPER_ADMIN -> null
|
|
||||||
Teacher.TYPE_SECRETARIAT -> null
|
|
||||||
Teacher.TYPE_PRINCIPAL -> null
|
|
||||||
Teacher.TYPE_EDUCATOR -> teacher.typeDescription
|
|
||||||
Teacher.TYPE_PARENT -> teacher.typeDescription
|
|
||||||
Teacher.TYPE_STUDENT -> teacher.typeDescription
|
|
||||||
Teacher.TYPE_SPECIALIST -> null
|
|
||||||
else -> teacher.typeDescription
|
|
||||||
}
|
|
||||||
categoryNames += listOfNotNull(
|
|
||||||
name.asSpannable(
|
|
||||||
ForegroundColorSpan(textColorPrimary)
|
|
||||||
),
|
|
||||||
description?.asSpannable(
|
|
||||||
ForegroundColorSpan(textColorSecondary),
|
|
||||||
AbsoluteSizeSpan(14.dp)
|
|
||||||
)
|
|
||||||
).concat("\n")
|
|
||||||
categoryCheckedItems += b.recipients.allChips.firstOrNull { it.data == teacher } != null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val chipSpan = ChipSpan(context, data.fullName, BitmapDrawable(context.resources, data.image), data)
|
||||||
|
chipSpan.setIconBackgroundColor(Colors.stringToMaterialColor(data.fullName))
|
||||||
|
return chipSpan
|
||||||
|
}
|
||||||
|
|
||||||
MaterialAlertDialogBuilder(activity)
|
val type = (data.id * -1).toInt()
|
||||||
.setTitle("Dodaj odbiorców - "+ Teacher.typeName(activity, type))
|
|
||||||
//.setMessage(getString(R.string.messages_compose_recipients_text_format, Teacher.typeName(activity, type)))
|
val textColorPrimary = android.R.attr.textColorPrimary.resolveAttr(activity)
|
||||||
.setPositiveButton("OK", null)
|
val textColorSecondary = android.R.attr.textColorSecondary.resolveAttr(activity)
|
||||||
.setNeutralButton("Anuluj", null)
|
|
||||||
.setMultiChoiceItems(categoryNames.toTypedArray(), categoryCheckedItems.toBooleanArray()) { _, which, isChecked ->
|
val sortByCategory = type in listOf(
|
||||||
val teacher = category[which]
|
Teacher.TYPE_PARENTS_COUNCIL,
|
||||||
if (isChecked) {
|
Teacher.TYPE_EDUCATOR,
|
||||||
val chipInfoList = mutableListOf<ChipInfo>()
|
Teacher.TYPE_STUDENT
|
||||||
teacher.image = getProfileImage(48, 24, 16, 12, 1, teacher.fullName)
|
)
|
||||||
chipInfoList.add(ChipInfo(teacher.fullName, teacher))
|
val teachers = if (sortByCategory)
|
||||||
b.recipients.addTextWithChips(chipInfoList)
|
teachers.sortedBy { it.typeDescription }
|
||||||
}
|
else
|
||||||
else {
|
teachers
|
||||||
b.recipients.allChips.forEach {
|
|
||||||
if (it.data == teacher)
|
val category = mutableListOf<Teacher>()
|
||||||
b.recipients.chipTokenizer?.deleteChipAndPadding(it, b.recipients.text)
|
val categoryNames = mutableListOf<CharSequence>()
|
||||||
}
|
val categoryCheckedItems = mutableListOf<Boolean>()
|
||||||
|
teachers.forEach { teacher ->
|
||||||
|
if (!teacher.isType(type))
|
||||||
|
return@forEach
|
||||||
|
|
||||||
|
category += teacher
|
||||||
|
val name = teacher.fullName
|
||||||
|
val description = when (type) {
|
||||||
|
Teacher.TYPE_TEACHER -> null
|
||||||
|
Teacher.TYPE_PARENTS_COUNCIL -> teacher.typeDescription
|
||||||
|
Teacher.TYPE_SCHOOL_PARENTS_COUNCIL -> null
|
||||||
|
Teacher.TYPE_PEDAGOGUE -> null
|
||||||
|
Teacher.TYPE_LIBRARIAN -> null
|
||||||
|
Teacher.TYPE_SCHOOL_ADMIN -> null
|
||||||
|
Teacher.TYPE_SUPER_ADMIN -> null
|
||||||
|
Teacher.TYPE_SECRETARIAT -> null
|
||||||
|
Teacher.TYPE_PRINCIPAL -> null
|
||||||
|
Teacher.TYPE_EDUCATOR -> teacher.typeDescription
|
||||||
|
Teacher.TYPE_PARENT -> teacher.typeDescription
|
||||||
|
Teacher.TYPE_STUDENT -> teacher.typeDescription
|
||||||
|
Teacher.TYPE_SPECIALIST -> null
|
||||||
|
else -> teacher.typeDescription
|
||||||
|
}
|
||||||
|
categoryNames += listOfNotNull(
|
||||||
|
name.asSpannable(
|
||||||
|
ForegroundColorSpan(textColorPrimary)
|
||||||
|
),
|
||||||
|
description?.asSpannable(
|
||||||
|
ForegroundColorSpan(textColorSecondary),
|
||||||
|
AbsoluteSizeSpan(14.dp)
|
||||||
|
)
|
||||||
|
).concat("\n")
|
||||||
|
|
||||||
|
// check the teacher if already added as a recipient
|
||||||
|
categoryCheckedItems += b.recipients.allChips.firstOrNull { it.data == teacher } != null
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialAlertDialogBuilder(activity)
|
||||||
|
.setTitle("Dodaj odbiorców - "+ Teacher.typeName(activity, type))
|
||||||
|
//.setMessage(getString(R.string.messages_compose_recipients_text_format, Teacher.typeName(activity, type)))
|
||||||
|
.setPositiveButton("OK", null)
|
||||||
|
.setNeutralButton("Anuluj", null)
|
||||||
|
.setMultiChoiceItems(categoryNames.toTypedArray(), categoryCheckedItems.toBooleanArray()) { _, which, isChecked ->
|
||||||
|
val teacher = category[which]
|
||||||
|
if (isChecked) {
|
||||||
|
val chipInfoList = mutableListOf<ChipInfo>()
|
||||||
|
teacher.image = getProfileImage(48, 24, 16, 12, 1, teacher.fullName)
|
||||||
|
chipInfoList.add(ChipInfo(teacher.fullName, teacher))
|
||||||
|
b.recipients.addTextWithChips(chipInfoList)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
b.recipients.allChips.forEach {
|
||||||
|
if (it.data == teacher)
|
||||||
|
b.recipients.chipTokenizer?.deleteChipAndPadding(it, b.recipients.text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.show()
|
}
|
||||||
return null
|
.show()
|
||||||
}
|
return null
|
||||||
b.recipients.allChips.forEach {
|
|
||||||
if (it.data == data) {
|
|
||||||
Toast.makeText(activity, R.string.messages_compose_recipient_exists, Toast.LENGTH_SHORT).show()
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val chipSpan = ChipSpan(context, data.fullName, BitmapDrawable(context.resources, data.image), data)
|
|
||||||
chipSpan.setIconBackgroundColor(Colors.stringToMaterialColor(data.fullName))
|
|
||||||
return chipSpan
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun configureChip(chip: ChipSpan, chipConfiguration: ChipConfiguration) {
|
override fun configureChip(chip: ChipSpan, chipConfiguration: ChipConfiguration) {
|
||||||
@ -276,23 +289,33 @@ class MessagesComposeFragment : Fragment(), CoroutineScope {
|
|||||||
b.recipients.setIllegalCharacterIdentifier { c ->
|
b.recipients.setIllegalCharacterIdentifier { c ->
|
||||||
c.toString().matches("[\\n;:_ ]".toRegex())
|
c.toString().matches("[\\n;:_ ]".toRegex())
|
||||||
}
|
}
|
||||||
/*b.recipients.setOnChipClickListener { chip, _ ->
|
b.recipients.setOnChipRemoveListener { _ ->
|
||||||
Toast.makeText(app, "onChipClick: " + chip.text, Toast.LENGTH_SHORT).show()
|
|
||||||
}*/
|
|
||||||
b.recipients.setOnChipRemoveListener { chip ->
|
|
||||||
b.recipients.setSelection(b.recipients.text.length)
|
b.recipients.setSelection(b.recipients.text.length)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.recipients.addTextChangedListener( beforeTextChanged = { _, _, _, _ ->
|
||||||
|
b.recipients.ignoreThreshold = false
|
||||||
|
})
|
||||||
|
b.recipients.onDismissListener = AutoCompleteTextView.OnDismissListener {
|
||||||
|
b.recipients.ignoreThreshold = false
|
||||||
|
}
|
||||||
|
b.recipientsLayout.setEndIconOnClickListener {
|
||||||
|
b.recipients.error = null
|
||||||
|
b.recipients.ignoreThreshold = true
|
||||||
|
b.recipients.showDropDown()
|
||||||
|
val adapter = b.recipients.adapter ?: return@setEndIconOnClickListener
|
||||||
|
if (adapter is MessagesComposeSuggestionAdapter)
|
||||||
|
adapter.filter.filter(null)
|
||||||
|
}
|
||||||
|
|
||||||
b.recipientsLayout.isEnabled = false
|
b.recipientsLayout.isEnabled = false
|
||||||
b.subjectLayout.isEnabled = false
|
b.subjectLayout.isEnabled = false
|
||||||
b.textLayout.isEnabled = false
|
b.textLayout.isEnabled = false
|
||||||
|
|
||||||
activity.navView.apply {
|
activity.navView.bottomBar.apply {
|
||||||
bottomBar.apply {
|
fabEnable = true
|
||||||
fabEnable = true
|
fabExtendedText = getString(R.string.messages_compose_send)
|
||||||
fabExtendedText = getString(R.string.messages_compose_send)
|
fabIcon = CommunityMaterial.Icon2.cmd_send
|
||||||
fabIcon = CommunityMaterial.Icon2.cmd_send
|
|
||||||
}
|
|
||||||
|
|
||||||
setFabOnClickListener(View.OnClickListener {
|
setFabOnClickListener(View.OnClickListener {
|
||||||
sendMessage()
|
sendMessage()
|
||||||
@ -438,7 +461,14 @@ class MessagesComposeFragment : Fragment(), CoroutineScope {
|
|||||||
|
|
||||||
activity.bottomSheet.hideKeyboard()
|
activity.bottomSheet.hideKeyboard()
|
||||||
|
|
||||||
EdziennikTask.messageSend(App.profileId, recipients, subject.trim(), textHtml.trim()).enqueue(activity)
|
MaterialAlertDialogBuilder(activity)
|
||||||
|
.setTitle(R.string.messages_compose_confirm_title)
|
||||||
|
.setMessage(R.string.messages_compose_confirm_text)
|
||||||
|
.setPositiveButton(R.string.send) { _, _ ->
|
||||||
|
EdziennikTask.messageSend(App.profileId, recipients, subject.trim(), textHtml.trim()).enqueue(activity)
|
||||||
|
}
|
||||||
|
.setNegativeButton(R.string.cancel, null)
|
||||||
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
||||||
|
@ -71,7 +71,12 @@ class MessagesComposeSuggestionAdapter(
|
|||||||
override fun performFiltering(prefix: CharSequence?): FilterResults {
|
override fun performFiltering(prefix: CharSequence?): FilterResults {
|
||||||
val results = FilterResults()
|
val results = FilterResults()
|
||||||
|
|
||||||
if (prefix.isNullOrEmpty()) {
|
if (prefix == null) {
|
||||||
|
originalList.filter { it.id in -24L..0L }.let {
|
||||||
|
results.values = it
|
||||||
|
results.count = it.size
|
||||||
|
}
|
||||||
|
} else if (prefix.isEmpty()) {
|
||||||
results.values = originalList
|
results.values = originalList
|
||||||
results.count = originalList.size
|
results.count = originalList.size
|
||||||
} else {
|
} else {
|
||||||
|
@ -21,7 +21,9 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:boxBackgroundColor="@android:color/transparent"
|
app:boxBackgroundColor="@android:color/transparent"
|
||||||
app:boxBackgroundMode="filled">
|
app:boxBackgroundMode="filled"
|
||||||
|
app:endIconMode="custom"
|
||||||
|
app:endIconDrawable="@drawable/dropdown_arrow">
|
||||||
|
|
||||||
<com.hootsuite.nachos.NachoTextView
|
<com.hootsuite.nachos.NachoTextView
|
||||||
android:id="@+id/recipients"
|
android:id="@+id/recipients"
|
||||||
|
@ -1174,4 +1174,6 @@
|
|||||||
<string name="other">Inne</string>
|
<string name="other">Inne</string>
|
||||||
<string name="menu_grades_config">Ustawienia ocen</string>
|
<string name="menu_grades_config">Ustawienia ocen</string>
|
||||||
<string name="timetable_generate_show_teachers_names">Pokaż imiona i nazwiska nauczycieli</string>
|
<string name="timetable_generate_show_teachers_names">Pokaż imiona i nazwiska nauczycieli</string>
|
||||||
|
<string name="messages_compose_confirm_title">Potwierdź wysłanie wiadomości</string>
|
||||||
|
<string name="messages_compose_confirm_text">Czy na pewno chcesz wysłać wiadomość do wybranych odbiorców?</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1078,6 +1078,22 @@ public class NachoTextView extends MultiAutoCompleteTextView implements TextWatc
|
|||||||
return chipAndTokenValues;
|
return chipAndTokenValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean ignoreThreshold = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean enoughToFilter() {
|
||||||
|
return ignoreThreshold || super.enoughToFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
public OnDismissListener onDismissListener = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dismissDropDown() {
|
||||||
|
if (onDismissListener != null)
|
||||||
|
onDismissListener.onDismiss();
|
||||||
|
super.dismissDropDown();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
try {
|
try {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user