[UI] Add teacher list action buttons. (#105)

* Update code

TODO: Change icons color

* Change "More" icon, update teachers list

* Update code

* Update code

* Reformat code

* Apply suggestions from code review

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* Update code

* Update app/src/main/java/pl/szczodrzynski/edziennik/ui/teachers/TeachersListFragment.kt

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>

* Update code

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
This commit is contained in:
Antoni Czaplicki 2021-10-24 18:29:04 +02:00 committed by GitHub
parent e629e03b33
commit e02246f97d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 95 additions and 28 deletions

View File

@ -197,7 +197,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
.isInDrawer(true) .isInDrawer(true)
list += NavTarget(DRAWER_ITEM_MORE, R.string.menu_more, null) list += NavTarget(DRAWER_ITEM_MORE, R.string.menu_more, null)
.withIcon(CommunityMaterial.Icon.cmd_dots_horizontal_circle_outline) .withIcon(CommunityMaterial.Icon.cmd_dots_horizontal)
.isInDrawer(true) .isInDrawer(true)
.isStatic(true) .isStatic(true)
.withSubItems(*moreList.toTypedArray()) .withSubItems(*moreList.toTypedArray())

View File

@ -442,7 +442,7 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
fun getTeacherByLastFirst(nameLastFirst: String, loginId: String? = null): Teacher { fun getTeacherByLastFirst(nameLastFirst: String, loginId: String? = null): Teacher {
// comparing full name is safer than splitting and swapping // comparing full name is safer than splitting and swapping
val teacher = teacherList.singleOrNull { it.fullNameLastFirst == nameLastFirst } val teacher = teacherList.singleOrNull { it.fullNameLastFirst == nameLastFirst }
val nameParts = nameLastFirst.split(" ") val nameParts = nameLastFirst.split(" ", limit = 2)
return if (nameParts.size == 1) return if (nameParts.size == 1)
validateTeacher(teacher, nameParts[0], "", loginId) validateTeacher(teacher, nameParts[0], "", loginId)
else else
@ -450,11 +450,13 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
} }
fun getTeacherByFirstLast(nameFirstLast: String, loginId: String? = null): Teacher { fun getTeacherByFirstLast(nameFirstLast: String, loginId: String? = null): Teacher {
val nameParts = nameFirstLast.split(" ") // comparing full name is safer than splitting and swapping
val teacher = teacherList.singleOrNull { it.fullName == nameFirstLast }
val nameParts = nameFirstLast.split(" ", limit = 2)
return if (nameParts.size == 1) return if (nameParts.size == 1)
getTeacher(nameParts[0], "", loginId) validateTeacher(teacher, nameParts[0], "", loginId)
else else
getTeacher(nameParts[0], nameParts[1], loginId) validateTeacher(teacher, nameParts[0], nameParts[1], loginId)
} }
fun getTeacherByFDotLast(nameFDotLast: String, loginId: String? = null): Teacher { fun getTeacherByFDotLast(nameFDotLast: String, loginId: String? = null): Teacher {

View File

@ -12,6 +12,7 @@ import androidx.room.Ignore
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.ext.fixName import pl.szczodrzynski.edziennik.ext.fixName
import pl.szczodrzynski.edziennik.ext.getNameInitials import pl.szczodrzynski.edziennik.ext.getNameInitials
import pl.szczodrzynski.edziennik.ext.isNotNullNorEmpty
import pl.szczodrzynski.edziennik.ext.join import pl.szczodrzynski.edziennik.ext.join
import java.util.* import java.util.*
@ -117,15 +118,23 @@ open class Teacher {
type = type and (1 shl i).inv() type = type and (1 shl i).inv()
} }
fun getTypeText(c: Context): String { fun getTypeText(c: Context, subjectList: List<Subject>? = null): String {
val list = mutableListOf<String>() val roles = mutableListOf<String>()
types.forEach { types.forEach {
if (isType(it)) if (isType(it))
list += typeName(c, it, typeDescription) roles += typeName(c, it, typeDescription)
}
return list.join(", ")
} }
if (subjectList != null && subjects.isNotEmpty()) {
return subjects.joinToString(
prefix = if (roles.isNotEmpty()) roles.joinToString(postfix = ": ") else "",
transform = { subjectId ->
subjectList.firstOrNull { it.id == subjectId }?.longName ?: ""
},
)
}
return roles.joinToString()
}
@Ignore @Ignore
var image: Bitmap? = null var image: Bitmap? = null

View File

@ -4,19 +4,23 @@
package pl.szczodrzynski.edziennik.ui.teachers package pl.szczodrzynski.edziennik.ui.teachers
import android.content.Intent
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isVisible
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import pl.szczodrzynski.edziennik.App import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.db.entity.Subject
import pl.szczodrzynski.edziennik.data.db.entity.Teacher import pl.szczodrzynski.edziennik.data.db.entity.Teacher
import pl.szczodrzynski.edziennik.databinding.TeacherItemBinding import pl.szczodrzynski.edziennik.databinding.TeacherItemBinding
import pl.szczodrzynski.edziennik.ext.isNotNullNorEmpty import pl.szczodrzynski.edziennik.ext.*
import pl.szczodrzynski.edziennik.ui.messages.MessagesUtils.getProfileImage
import pl.szczodrzynski.edziennik.utils.BetterLink
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
class TeachersAdapter( class TeachersAdapter(
@ -36,6 +40,8 @@ class TeachersAdapter(
var items = listOf<Teacher>() var items = listOf<Teacher>()
var subjectList = listOf<Subject>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(activity) val inflater = LayoutInflater.from(activity)
val view = TeacherItemBinding.inflate(inflater, parent, false) val view = TeacherItemBinding.inflate(inflater, parent, false)
@ -47,19 +53,28 @@ class TeachersAdapter(
val b = holder.b val b = holder.b
b.name.text = item.fullName b.name.text = item.fullName
b.image.setImageBitmap(item.image?: getProfileImage(48, 24, 16, 12, 1, item.fullName)) b.image.setImageBitmap(item.image)
var role = item.getTypeText(activity) b.type.text = item.getTypeText(activity, subjectList)
if (item.subjects.isNotNullNorEmpty()) { b.copy.isVisible = true
val subjects = item.subjects.map { App.db.subjectDao().getByIdNow(App.profileId, it).longName } b.copy.onClick {
role = role.plus(": ").plus(subjects.joinToString()) item.fullName.copyToClipboard(activity)
Toast.makeText(activity, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show()
} }
b.type.text = role b.copy.attachToastHint(R.string.copy_to_clipboard)
if (item.loginId.isNotNullNorBlank()) {
b.sendMessage.isVisible = true
item.fullName.let { name -> b.sendMessage.onClick {
BetterLink.attach( val intent = Intent(
b.name, Intent.ACTION_MAIN,
teachers = mapOf(item.id to name) "fragmentId" to MainActivity.TARGET_MESSAGES_COMPOSE,
"messageRecipientId" to item.id
) )
activity.sendBroadcast(intent)
}
b.sendMessage.attachToastHint(R.string.send_message)
} else {
b.sendMessage.isVisible = false
} }
} }

View File

@ -15,10 +15,12 @@ import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.withContext
import pl.szczodrzynski.edziennik.* import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.databinding.TeachersListFragmentBinding import pl.szczodrzynski.edziennik.databinding.TeachersListFragmentBinding
import pl.szczodrzynski.edziennik.ext.isNotNullNorEmpty import pl.szczodrzynski.edziennik.ext.isNotNullNorEmpty
import pl.szczodrzynski.edziennik.ext.startCoroutineTimer import pl.szczodrzynski.edziennik.ext.startCoroutineTimer
import pl.szczodrzynski.edziennik.ui.messages.MessagesUtils
import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
@ -48,11 +50,21 @@ class TeachersListFragment : Fragment(), CoroutineScope {
val adapter = TeachersAdapter(activity) val adapter = TeachersAdapter(activity)
adapter.subjectList = withContext(Dispatchers.IO) {
App.db.subjectDao().getAllNow(App.profileId)
}
app.db.teacherDao().getAllTeachers(App.profileId).observe(viewLifecycleOwner, Observer { items -> app.db.teacherDao().getAllTeachers(App.profileId).observe(viewLifecycleOwner, Observer { items ->
if (!isAdded) return@Observer if (!isAdded) return@Observer
// load & configure the adapter // load & configure the adapter
adapter.items = items adapter.items = items.sortedWith(compareBy(
{ it.subjects.isEmpty() },
{ it.type == 0 },
))
adapter.items.forEach {
it.image = it.image ?: MessagesUtils.getProfileImage(48, 24, 16, 12, 1, it.fullName)
}
if (items.isNotNullNorEmpty() && b.list.adapter == null) { if (items.isNotNullNorEmpty() && b.list.adapter == null) {
b.list.adapter = adapter b.list.adapter = adapter
b.list.apply { b.list.apply {

View File

@ -8,12 +8,12 @@
<ImageView <ImageView
android:id="@+id/image" android:id="@+id/image"
android:layout_marginLeft="8dp"
android:layout_width="48dp" android:layout_width="48dp"
android:layout_height="48dp" android:layout_height="48dp"
android:layout_gravity="center" android:layout_gravity="center"
tools:srcCompat="@drawable/bg_circle" android:layout_marginStart="8dp"
android:layout_marginStart="8dp" /> android:layout_marginLeft="8dp"
tools:srcCompat="@drawable/bg_circle" />
<LinearLayout <LinearLayout
android:layout_width="0dp" android:layout_width="0dp"
@ -43,4 +43,31 @@
tools:text="Jan Kowalski" /> tools:text="Jan Kowalski" />
</LinearLayout> </LinearLayout>
<com.mikepenz.iconics.view.IconicsImageButton
android:id="@+id/sendMessage"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:background="?selectableItemBackground"
android:visibility="gone"
app:iiv_color="?android:textColorSecondary"
app:iiv_icon="cmd-email-plus-outline"
app:iiv_size="24dp"
tools:visibility="visible" />
<com.mikepenz.iconics.view.IconicsImageButton
android:id="@+id/copy"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp"
android:background="?selectableItemBackground"
android:visibility="gone"
app:iiv_color="?android:textColorSecondary"
app:iiv_icon="cmd-clipboard-text-multiple-outline"
app:iiv_size="24dp"
tools:visibility="visible" />
</LinearLayout> </LinearLayout>

View File

@ -1376,4 +1376,5 @@
<string name="login_summary_account_parent">(Parent)</string> <string name="login_summary_account_parent">(Parent)</string>
<string name="menu_teachers">Teachers</string> <string name="menu_teachers">Teachers</string>
<string name="edziennik_progress_endpoint_addressbook">Syncing addressbook…</string> <string name="edziennik_progress_endpoint_addressbook">Syncing addressbook…</string>
<string name="send_message">Send message</string>
</resources> </resources>

View File

@ -1496,5 +1496,6 @@
<string name="login_mobidziennik_server_prefix">https://</string> <string name="login_mobidziennik_server_prefix">https://</string>
<string name="login_mobidziennik_server_suffix">.mobidziennik.pl/</string> <string name="login_mobidziennik_server_suffix">.mobidziennik.pl/</string>
<string name="styled_text_dialog_title">Edytuj tekst</string> <string name="styled_text_dialog_title">Edytuj tekst</string>
<string name="send_message">Wyślij wiadomość</string>
<string name="login_qr_decoding_error">Kod QR nie wygląda na prawidłowy</string> <string name="login_qr_decoding_error">Kod QR nie wygląda na prawidłowy</string>
</resources> </resources>