forked from github/szkolny
[UI] Add teachers list feature. (#94)
* Add teachers list feature * Fix * some fixes * Auto stash before merge of "develop" and "origin/develop" * Add teachers list feature * Fix * some fixes * [UI] Fix updating badges crashing with expanded items. * Add support for fetching teachers from vulcan, fix some code * Update app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Teacher.kt Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl> * Update some code * Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl> * Update app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Teacher.kt Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl> * Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl> * Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl> * Update app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeTeachers.kt Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl> * Update app/src/main/java/pl/szczodrzynski/edziennik/data/db/entity/Teacher.kt Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl> * Update app/src/main/java/pl/szczodrzynski/edziennik/data/db/migration/Migration96.kt Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl> * Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl> * Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl> * Update app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/hebe/VulcanHebeTeachers.kt Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl> * Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl> * Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl> * Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl> * Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl> * Optimize code * Fix loadTarget algorithm * Apply suggestions from code review Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl> * Update app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl> Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
This commit is contained in:
parent
74b766f18a
commit
2807659da3
6
.idea/copyright/Antoni.xml
Normal file
6
.idea/copyright/Antoni.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<component name="CopyrightManager">
|
||||
<copyright>
|
||||
<option name="notice" value="Copyright (c) Antoni Czaplicki &#36;{today.year}-&#36;{today.month}-&#36;{today.day}. " />
|
||||
<option name="myName" value="Antoni" />
|
||||
</copyright>
|
||||
</component>
|
@ -44,6 +44,8 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.gson.*
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import com.mikepenz.iconics.typeface.IIcon
|
||||
import com.mikepenz.materialdrawer.holder.StringHolder
|
||||
import im.wangchao.mhttp.Response
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.delay
|
||||
@ -59,6 +61,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Profile
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Team
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import pl.szczodrzynski.navlib.ImageHolder
|
||||
import java.io.InterruptedIOException
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
@ -862,6 +865,8 @@ fun @receiver:DrawableRes Int.resolveDrawable(context: Context): Drawable {
|
||||
}
|
||||
}
|
||||
|
||||
fun @receiver:StringRes Int.resolveString(context: Context) = context.getString(this)
|
||||
|
||||
fun View.findParentById(targetId: Int): View? {
|
||||
if (id == targetId) {
|
||||
return this
|
||||
@ -1371,3 +1376,7 @@ fun CharSequence.getWordBounds(position: Int, onlyInWord: Boolean = false): Pair
|
||||
}
|
||||
|
||||
infix fun Int.hasSet(what: Int) = this and what == what
|
||||
|
||||
fun Int.toStringHolder() = StringHolder(this)
|
||||
fun CharSequence.toStringHolder() = StringHolder(this)
|
||||
fun IIcon.toImageHolder() = ImageHolder(this)
|
||||
|
@ -25,9 +25,7 @@ import com.mikepenz.iconics.IconicsDrawable
|
||||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
||||
import com.mikepenz.iconics.utils.colorInt
|
||||
import com.mikepenz.iconics.utils.sizeDp
|
||||
import com.mikepenz.materialdrawer.model.DividerDrawerItem
|
||||
import com.mikepenz.materialdrawer.model.ProfileDrawerItem
|
||||
import com.mikepenz.materialdrawer.model.ProfileSettingDrawerItem
|
||||
import com.mikepenz.materialdrawer.model.*
|
||||
import com.mikepenz.materialdrawer.model.interfaces.*
|
||||
import com.mikepenz.materialdrawer.model.utils.hiddenInMiniDrawer
|
||||
import eu.szkolny.font.SzkolnyFont
|
||||
@ -76,6 +74,7 @@ import pl.szczodrzynski.edziennik.ui.modules.messages.single.MessageFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.notifications.NotificationsListFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.settings.ProfileManagerFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.settings.SettingsFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.teachers.TeachersListFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.timetable.TimetableFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.webpush.WebPushFragment
|
||||
import pl.szczodrzynski.edziennik.utils.*
|
||||
@ -116,6 +115,8 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
const val DRAWER_ITEM_ATTENDANCE = 16
|
||||
const val DRAWER_ITEM_ANNOUNCEMENTS = 18
|
||||
const val DRAWER_ITEM_NOTIFICATIONS = 20
|
||||
const val DRAWER_ITEM_MORE = 21
|
||||
const val DRAWER_ITEM_TEACHERS = 22
|
||||
const val DRAWER_ITEM_SETTINGS = 101
|
||||
const val DRAWER_ITEM_DEBUG = 102
|
||||
|
||||
@ -130,6 +131,13 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
|
||||
val navTargetList: List<NavTarget> by lazy {
|
||||
val list: MutableList<NavTarget> = mutableListOf()
|
||||
val moreList: MutableList<NavTarget> = mutableListOf()
|
||||
|
||||
moreList += NavTarget(DRAWER_ITEM_TEACHERS,
|
||||
R.string.menu_teachers,
|
||||
TeachersListFragment::class)
|
||||
.withIcon(CommunityMaterial.Icon3.cmd_shield_account_outline)
|
||||
.isStatic(true)
|
||||
|
||||
// home item
|
||||
list += NavTarget(DRAWER_ITEM_HOME, R.string.menu_home_page, HomeFragment::class)
|
||||
@ -139,7 +147,9 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
.isStatic(true)
|
||||
.withPopToHome(false)
|
||||
|
||||
list += NavTarget(DRAWER_ITEM_TIMETABLE, R.string.menu_timetable, TimetableFragment::class)
|
||||
list += NavTarget(DRAWER_ITEM_TIMETABLE,
|
||||
R.string.menu_timetable,
|
||||
TimetableFragment::class)
|
||||
.withIcon(CommunityMaterial.Icon3.cmd_timetable)
|
||||
.withBadgeTypeId(TYPE_LESSON_CHANGE)
|
||||
.isInDrawer(true)
|
||||
@ -164,24 +174,38 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
.withBadgeTypeId(TYPE_HOMEWORK)
|
||||
.isInDrawer(true)
|
||||
|
||||
list += NavTarget(DRAWER_ITEM_BEHAVIOUR, R.string.menu_notices, BehaviourFragment::class)
|
||||
list += NavTarget(DRAWER_ITEM_BEHAVIOUR,
|
||||
R.string.menu_notices,
|
||||
BehaviourFragment::class)
|
||||
.withIcon(CommunityMaterial.Icon.cmd_emoticon_outline)
|
||||
.withBadgeTypeId(TYPE_NOTICE)
|
||||
.isInDrawer(true)
|
||||
|
||||
list += NavTarget(DRAWER_ITEM_ATTENDANCE, R.string.menu_attendance, AttendanceFragment::class)
|
||||
list += NavTarget(DRAWER_ITEM_ATTENDANCE,
|
||||
R.string.menu_attendance,
|
||||
AttendanceFragment::class)
|
||||
.withIcon(CommunityMaterial.Icon.cmd_calendar_remove_outline)
|
||||
.withBadgeTypeId(TYPE_ATTENDANCE)
|
||||
.isInDrawer(true)
|
||||
|
||||
list += NavTarget(DRAWER_ITEM_ANNOUNCEMENTS, R.string.menu_announcements, AnnouncementsFragment::class)
|
||||
list += NavTarget(DRAWER_ITEM_ANNOUNCEMENTS,
|
||||
R.string.menu_announcements,
|
||||
AnnouncementsFragment::class)
|
||||
.withIcon(CommunityMaterial.Icon.cmd_bullhorn_outline)
|
||||
.withBadgeTypeId(TYPE_ANNOUNCEMENT)
|
||||
.isInDrawer(true)
|
||||
|
||||
list += NavTarget(DRAWER_ITEM_MORE, R.string.menu_more, null)
|
||||
.withIcon(CommunityMaterial.Icon.cmd_dots_horizontal_circle_outline)
|
||||
.isInDrawer(true)
|
||||
.isStatic(true)
|
||||
.withSubItems(*moreList.toTypedArray())
|
||||
|
||||
|
||||
// static drawer items
|
||||
list += NavTarget(DRAWER_ITEM_NOTIFICATIONS, R.string.menu_notifications, NotificationsListFragment::class)
|
||||
list += NavTarget(DRAWER_ITEM_NOTIFICATIONS,
|
||||
R.string.menu_notifications,
|
||||
NotificationsListFragment::class)
|
||||
.withIcon(CommunityMaterial.Icon.cmd_bell_ring_outline)
|
||||
.isInDrawer(true)
|
||||
.isStatic(true)
|
||||
@ -200,13 +224,17 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
.withDescription(R.string.drawer_add_new_profile_desc)
|
||||
.isInProfileList(true)
|
||||
|
||||
list += NavTarget(DRAWER_PROFILE_MANAGE, R.string.menu_manage_profiles, ProfileManagerFragment::class)
|
||||
list += NavTarget(DRAWER_PROFILE_MANAGE,
|
||||
R.string.menu_manage_profiles,
|
||||
ProfileManagerFragment::class)
|
||||
.withTitle(R.string.title_profile_manager)
|
||||
.withIcon(CommunityMaterial.Icon.cmd_account_group)
|
||||
.withDescription(R.string.drawer_manage_profiles_desc)
|
||||
.isInProfileList(false)
|
||||
|
||||
list += NavTarget(DRAWER_PROFILE_MARK_ALL_AS_READ, R.string.menu_mark_everything_as_read, null)
|
||||
list += NavTarget(DRAWER_PROFILE_MARK_ALL_AS_READ,
|
||||
R.string.menu_mark_everything_as_read,
|
||||
null)
|
||||
.withIcon(CommunityMaterial.Icon.cmd_eye_check_outline)
|
||||
.isInProfileList(true)
|
||||
|
||||
@ -216,10 +244,16 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
|
||||
|
||||
// other target items, not directly navigated
|
||||
list += NavTarget(TARGET_GRADES_EDITOR, R.string.menu_grades_editor, GradesEditorFragment::class)
|
||||
list += NavTarget(TARGET_GRADES_EDITOR,
|
||||
R.string.menu_grades_editor,
|
||||
GradesEditorFragment::class)
|
||||
list += NavTarget(TARGET_FEEDBACK, R.string.menu_feedback, FeedbackFragment::class)
|
||||
list += NavTarget(TARGET_MESSAGES_DETAILS, R.string.menu_message, MessageFragment::class).withPopTo(DRAWER_ITEM_MESSAGES)
|
||||
list += NavTarget(TARGET_MESSAGES_COMPOSE, R.string.menu_message_compose, MessagesComposeFragment::class)
|
||||
list += NavTarget(TARGET_MESSAGES_DETAILS,
|
||||
R.string.menu_message,
|
||||
MessageFragment::class).withPopTo(DRAWER_ITEM_MESSAGES)
|
||||
list += NavTarget(TARGET_MESSAGES_COMPOSE,
|
||||
R.string.menu_message_compose,
|
||||
MessagesComposeFragment::class)
|
||||
list += NavTarget(TARGET_WEB_PUSH, R.string.menu_web_push, WebPushFragment::class)
|
||||
if (App.devMode) {
|
||||
list += NavTarget(DRAWER_ITEM_DEBUG, R.string.menu_debug, DebugFragment::class)
|
||||
@ -323,9 +357,12 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
window.statusBarColor = statusBarColor
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && ColorUtils.calculateLuminance(statusBarColor) > 0.6) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
||||
&& ColorUtils.calculateLuminance(statusBarColor) > 0.6
|
||||
) {
|
||||
@Suppress("deprecation")
|
||||
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
|
||||
window.decorView.systemUiVisibility =
|
||||
window.decorView.systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
|
||||
}
|
||||
|
||||
// TODO fix navlib navbar detection, orientation change issues, status bar color setting if not fullscreen
|
||||
@ -385,8 +422,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
ProfileConfigDialog(this@MainActivity, appProfile)
|
||||
}
|
||||
true
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
@ -407,7 +443,9 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
|
||||
app.db.profileDao().all.observe(this) { profiles ->
|
||||
val allArchived = profiles.all { it.archived }
|
||||
drawer.setProfileList(profiles.filter { it.id >= 0 && (!it.archived || allArchived) }.toMutableList())
|
||||
drawer.setProfileList(profiles.filter {
|
||||
it.id >= 0 && (!it.archived || allArchived)
|
||||
}.toMutableList())
|
||||
//prepend the archived profile if loaded
|
||||
if (app.profile.archived && !allArchived) {
|
||||
drawer.prependProfile(Profile(
|
||||
@ -469,9 +507,12 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
val today = Date.getToday()
|
||||
if ((today.month % 11 == 1) && app.config.ui.snowfall) {
|
||||
b.rootFrame.addView(layoutInflater.inflate(R.layout.snowfall, b.rootFrame, false))
|
||||
}
|
||||
else if (app.config.ui.eggfall && BigNightUtil().isDataWielkanocyNearDzisiaj()) {
|
||||
val eggfall = layoutInflater.inflate(R.layout.eggfall, b.rootFrame, false) as SnowfallView
|
||||
} else if (app.config.ui.eggfall && BigNightUtil().isDataWielkanocyNearDzisiaj()) {
|
||||
val eggfall = layoutInflater.inflate(
|
||||
R.layout.eggfall,
|
||||
b.rootFrame,
|
||||
false
|
||||
) as SnowfallView
|
||||
eggfall.setSnowflakeBitmaps(listOf(
|
||||
BitmapFactory.decodeResource(resources, R.drawable.egg1),
|
||||
BitmapFactory.decodeResource(resources, R.drawable.egg2),
|
||||
@ -518,14 +559,17 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
app.config.appRateSnackbarTime = 0
|
||||
}
|
||||
.onNegative { cafeBar ->
|
||||
Toast.makeText(this, R.string.rate_snackbar_negative_message, Toast.LENGTH_LONG).show()
|
||||
Toast.makeText(this,
|
||||
R.string.rate_snackbar_negative_message,
|
||||
Toast.LENGTH_LONG).show()
|
||||
cafeBar.dismiss()
|
||||
app.config.appRateSnackbarTime = 0
|
||||
}
|
||||
.onNeutral { cafeBar ->
|
||||
Toast.makeText(this, R.string.ok, Toast.LENGTH_LONG).show()
|
||||
cafeBar.dismiss()
|
||||
app.config.appRateSnackbarTime = System.currentTimeMillis() + 7 * 24 * 60 * 60 * 1000
|
||||
app.config.appRateSnackbarTime =
|
||||
System.currentTimeMillis() + 7 * 24 * 60 * 60 * 1000
|
||||
}
|
||||
.autoDismiss(false)
|
||||
.swipeToDismiss(true)
|
||||
@ -570,17 +614,22 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
DRAWER_PROFILE_SYNC_ALL -> {
|
||||
EdziennikTask.sync().enqueue(this)
|
||||
}
|
||||
DRAWER_PROFILE_MARK_ALL_AS_READ -> { launch {
|
||||
DRAWER_PROFILE_MARK_ALL_AS_READ -> {
|
||||
launch {
|
||||
withContext(Dispatchers.Default) {
|
||||
app.db.profileDao().allNow.forEach { profile ->
|
||||
if (profile.loginStoreType != LoginStore.LOGIN_TYPE_LIBRUS)
|
||||
app.db.metadataDao().setAllSeenExceptMessagesAndAnnouncements(profile.id, true)
|
||||
app.db.metadataDao()
|
||||
.setAllSeenExceptMessagesAndAnnouncements(profile.id, true)
|
||||
else
|
||||
app.db.metadataDao().setAllSeenExceptMessages(profile.id, true)
|
||||
}
|
||||
}
|
||||
Toast.makeText(this@MainActivity, R.string.main_menu_mark_as_read_success, Toast.LENGTH_SHORT).show()
|
||||
}}
|
||||
Toast.makeText(this@MainActivity,
|
||||
R.string.main_menu_mark_as_read_success,
|
||||
Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
loadTarget(id)
|
||||
}
|
||||
@ -668,11 +717,13 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
arguments = arguments
|
||||
).enqueue(this)
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
||||
fun onUpdateEvent(event: Update) {
|
||||
EventBus.getDefault().removeStickyEvent(event)
|
||||
UpdateAvailableDialog(this, event)
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
||||
fun onRegisterAvailabilityEvent(event: RegisterAvailabilityEvent) {
|
||||
EventBus.getDefault().removeStickyEvent(event)
|
||||
@ -681,6 +732,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
RegisterUnavailableDialog(this, error.status!!)
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onApiTaskStartedEvent(event: ApiTaskStartedEvent) {
|
||||
swipeRefreshLayout.isRefreshing = true
|
||||
@ -692,6 +744,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onProfileListEmptyEvent(event: ProfileListEmptyEvent) {
|
||||
d(TAG, "Profile list is empty. Launch LoginActivity.")
|
||||
@ -699,6 +752,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
startActivity(Intent(this, LoginActivity::class.java))
|
||||
finish()
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onApiTaskProgressEvent(event: ApiTaskProgressEvent) {
|
||||
if (event.profileId == App.profileId) {
|
||||
@ -708,11 +762,16 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
subtitle = if (event.progress < 0f)
|
||||
event.progressText ?: ""
|
||||
else
|
||||
getString(R.string.toolbar_subtitle_syncing_format, event.progress.roundToInt(), event.progressText ?: "")
|
||||
getString(
|
||||
R.string.toolbar_subtitle_syncing_format,
|
||||
event.progress.roundToInt(),
|
||||
event.progressText ?: "",
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
||||
fun onApiTaskFinishedEvent(event: ApiTaskFinishedEvent) {
|
||||
EventBus.getDefault().removeStickyEvent(event)
|
||||
@ -724,11 +783,13 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
||||
fun onApiTaskAllFinishedEvent(event: ApiTaskAllFinishedEvent) {
|
||||
EventBus.getDefault().removeStickyEvent(event)
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
||||
fun onApiTaskErrorEvent(event: ApiTaskErrorEvent) {
|
||||
EventBus.getDefault().removeStickyEvent(event)
|
||||
@ -745,6 +806,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
mainSnackbar.dismiss()
|
||||
errorSnackbar.addError(event.error).show()
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
|
||||
fun onAppManagerDetectedEvent(event: AppManagerDetectedEvent) {
|
||||
EventBus.getDefault().removeStickyEvent(event)
|
||||
@ -756,7 +818,9 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
.setPositiveButton(R.string.ok) { _, _ ->
|
||||
try {
|
||||
for (intent in appManagerIntentList) {
|
||||
if (packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
|
||||
if (packageManager.resolveActivity(intent,
|
||||
PackageManager.MATCH_DEFAULT_ONLY) != null
|
||||
) {
|
||||
startActivity(intent)
|
||||
}
|
||||
}
|
||||
@ -765,7 +829,8 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
startActivity(Intent(Settings.ACTION_SETTINGS))
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
Toast.makeText(this, R.string.app_manager_open_failed, Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(this, R.string.app_manager_open_failed, Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -775,6 +840,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
.setCancelable(false)
|
||||
.show()
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onUserActionRequiredEvent(event: UserActionRequiredEvent) {
|
||||
app.userActionManager.execute(this, event.profileId, event.type)
|
||||
@ -808,6 +874,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
handleIntent(intent?.extras)
|
||||
}
|
||||
}
|
||||
|
||||
fun handleIntent(extras: Bundle?) {
|
||||
|
||||
d(TAG, "handleIntent() {")
|
||||
@ -842,7 +909,9 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
true
|
||||
}
|
||||
"createManualEvent" -> {
|
||||
val date = extras.getString("eventDate")?.let { Date.fromY_m_d(it) } ?: Date.getToday()
|
||||
val date = extras.getString("eventDate")
|
||||
?.let { Date.fromY_m_d(it) }
|
||||
?: Date.getToday()
|
||||
EventManualDialog(
|
||||
this,
|
||||
App.profileId,
|
||||
@ -913,9 +982,11 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
override fun recreate() {
|
||||
recreate(navTargetId)
|
||||
}
|
||||
|
||||
fun recreate(targetId: Int) {
|
||||
recreate(targetId, null)
|
||||
}
|
||||
|
||||
fun recreate(targetId: Int? = null, arguments: Bundle? = null) {
|
||||
val intent = Intent(this, MainActivity::class.java)
|
||||
if (arguments != null)
|
||||
@ -932,10 +1003,12 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
d(TAG, "Activity started")
|
||||
super.onStart()
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
d(TAG, "Activity stopped")
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
d(TAG, "Activity resumed")
|
||||
val filter = IntentFilter()
|
||||
@ -944,12 +1017,14 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
EventBus.getDefault().register(this)
|
||||
super.onResume()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
d(TAG, "Activity paused")
|
||||
unregisterReceiver(intentReceiver)
|
||||
EventBus.getDefault().unregister(this)
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
d(TAG, "Activity destroyed")
|
||||
super.onDestroy()
|
||||
@ -1010,6 +1085,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
}
|
||||
|
||||
fun loadProfile(id: Int) = loadProfile(id, navTargetId)
|
||||
|
||||
// fun loadProfile(id: Int, arguments: Bundle?) = loadProfile(id, navTargetId, arguments)
|
||||
fun loadProfile(profile: Profile): Boolean {
|
||||
if (!canNavigate()) {
|
||||
@ -1024,6 +1100,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
loadProfile(profile, navTargetId, null)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun loadProfile(
|
||||
id: Int,
|
||||
drawerSelection: Int,
|
||||
@ -1055,6 +1132,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun loadProfile(profile: Profile, drawerSelection: Int, arguments: Bundle?) {
|
||||
App.profile = profile
|
||||
MessagesFragment.pageSelection = -1
|
||||
@ -1084,6 +1162,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
drawer.currentProfile = app.profileId
|
||||
loadTarget(drawerSelection, arguments, skipBeforeNavigate = true)
|
||||
}
|
||||
|
||||
fun loadTarget(
|
||||
id: Int,
|
||||
arguments: Bundle? = null,
|
||||
@ -1093,15 +1172,28 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
if (loadId == -1) {
|
||||
loadId = DRAWER_ITEM_HOME
|
||||
}
|
||||
val target = navTargetList
|
||||
.firstOrNull { it.id == loadId }
|
||||
return if (target == null) {
|
||||
Toast.makeText(this, getString(R.string.error_invalid_fragment, id), Toast.LENGTH_LONG).show()
|
||||
val targets = navTargetList
|
||||
.flatMap { it.subItems?.toList() ?: emptyList() }
|
||||
.plus(navTargetList)
|
||||
val target = targets.firstOrNull { it.id == loadId }
|
||||
return when {
|
||||
target == null -> {
|
||||
Toast.makeText(
|
||||
this,
|
||||
getString(R.string.error_invalid_fragment, id),
|
||||
Toast.LENGTH_LONG,
|
||||
).show()
|
||||
loadTarget(navTargetList.first(), arguments, skipBeforeNavigate)
|
||||
} else {
|
||||
}
|
||||
target.fragmentClass != null -> {
|
||||
loadTarget(target, arguments, skipBeforeNavigate)
|
||||
}
|
||||
else -> {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadTarget(
|
||||
target: NavTarget,
|
||||
args: Bundle? = null,
|
||||
@ -1120,7 +1212,9 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
}
|
||||
pausedNavigationData = null
|
||||
|
||||
val arguments = args ?: navBackStack.firstOrNull { it.first.id == target.id }?.second ?: Bundle()
|
||||
val arguments = args
|
||||
?: navBackStack.firstOrNull { it.first.id == target.id }?.second
|
||||
?: Bundle()
|
||||
bottomSheet.close()
|
||||
bottomSheet.removeAllContextual()
|
||||
bottomSheet.toggleGroupEnabled = false
|
||||
@ -1132,7 +1226,8 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
navView.bottomBar.fabExtended = false
|
||||
navView.bottomBar.setFabOnClickListener(null)
|
||||
|
||||
d("NavDebug", "Navigating from ${navTarget.fragmentClass?.java?.simpleName} to ${target.fragmentClass?.java?.simpleName}")
|
||||
d("NavDebug",
|
||||
"Navigating from ${navTarget.fragmentClass?.java?.simpleName} to ${target.fragmentClass?.java?.simpleName}")
|
||||
|
||||
val fragment = target.fragmentClass?.java?.newInstance() ?: return false
|
||||
fragment.arguments = arguments
|
||||
@ -1144,8 +1239,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
R.anim.fade_in,
|
||||
R.anim.fade_out
|
||||
)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
navBackStack.keys().lastIndexOf(target).let {
|
||||
if (it == -1)
|
||||
return@let target
|
||||
@ -1193,7 +1287,8 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
}
|
||||
}
|
||||
|
||||
d("NavDebug", "Current fragment ${navTarget.fragmentClass?.java?.simpleName}, pop to home ${navTarget.popToHome}, back stack:")
|
||||
d("NavDebug",
|
||||
"Current fragment ${navTarget.fragmentClass?.java?.simpleName}, pop to home ${navTarget.popToHome}, back stack:")
|
||||
navBackStack.forEachIndexed { index, target2 ->
|
||||
d("NavDebug", " - $index: ${target2.first.fragmentClass?.java?.simpleName}")
|
||||
}
|
||||
@ -1204,9 +1299,13 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
// TASK DESCRIPTION
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
val bm = BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher)
|
||||
|
||||
@Suppress("deprecation")
|
||||
val taskDesc = ActivityManager.TaskDescription(
|
||||
if (target.id == HOME_ID) getString(R.string.app_name) else getString(R.string.app_task_format, getString(target.name)),
|
||||
if (target.id == HOME_ID)
|
||||
getString(R.string.app_name)
|
||||
else
|
||||
getString(R.string.app_task_format, getString(target.name)),
|
||||
bm,
|
||||
getColorFromAttr(this, R.attr.colorSurface)
|
||||
)
|
||||
@ -1214,6 +1313,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun reloadTarget() = loadTarget(navTarget)
|
||||
|
||||
private fun popBackStack(skipBeforeNavigate: Boolean = false): Boolean {
|
||||
@ -1236,6 +1336,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun navigateUp(skipBeforeNavigate: Boolean = false) {
|
||||
if (!popBackStack(skipBeforeNavigate)) {
|
||||
super.onBackPressed()
|
||||
@ -1287,29 +1388,31 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
|_____/|_| \__,_| \_/\_/ \___|_| |_|\__\___|_| |_| |_|__*/
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
private fun createDrawerItem(target: NavTarget, level: Int = 1): IDrawerItem<*> {
|
||||
val item = DrawerPrimaryItem().apply {
|
||||
identifier = target.id.toLong()
|
||||
nameRes = target.name
|
||||
hiddenInMiniDrawer = !app.config.ui.miniMenuButtons.contains(target.id)
|
||||
if (target.description != null)
|
||||
descriptionRes = target.description!!
|
||||
if (target.icon != null)
|
||||
withIcon(target.icon!!)
|
||||
if (target.title != null)
|
||||
appTitle = getString(target.title!!)
|
||||
if (target.badgeTypeId != null)
|
||||
badgeStyle = drawer.badgeStyle
|
||||
isSelectedBackgroundAnimated = false
|
||||
val item = when {
|
||||
target.subItems != null -> ExpandableDrawerItem()
|
||||
level > 1 -> SecondaryDrawerItem()
|
||||
else -> DrawerPrimaryItem()
|
||||
}
|
||||
|
||||
item.also {
|
||||
it.identifier = target.id.toLong()
|
||||
it.nameRes = target.name
|
||||
it.hiddenInMiniDrawer = !app.config.ui.miniMenuButtons.contains(target.id)
|
||||
it.description = target.description?.toStringHolder()
|
||||
it.icon = target.icon?.toImageHolder()
|
||||
if (it is DrawerPrimaryItem)
|
||||
it.appTitle = target.title?.resolveString(this)
|
||||
if (it is ColorfulBadgeable && target.badgeTypeId != null)
|
||||
it.badgeStyle = drawer.badgeStyle
|
||||
it.isSelectedBackgroundAnimated = false
|
||||
it.level = level
|
||||
}
|
||||
if (target.badgeTypeId != null)
|
||||
drawer.addUnreadCounterType(target.badgeTypeId!!, target.id)
|
||||
// TODO sub items
|
||||
/*
|
||||
if (target.subItems != null) {
|
||||
for (subItem in target.subItems!!) {
|
||||
item.subItems += createDrawerItem(subItem, level+1)
|
||||
}
|
||||
}*/
|
||||
|
||||
item.subItems = target.subItems?.map {
|
||||
createDrawerItem(it, level + 1)
|
||||
}?.toMutableList() ?: mutableListOf()
|
||||
|
||||
return item
|
||||
}
|
||||
@ -1334,7 +1437,11 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
if (target.popToHome)
|
||||
targetPopToHomeList += target.id
|
||||
|
||||
if (target.isInDrawer && (target.isStatic || supportedFragments.isEmpty() || supportedFragments.contains(target.id))) {
|
||||
if (target.isInDrawer && (
|
||||
target.isStatic
|
||||
|| supportedFragments.isEmpty()
|
||||
|| supportedFragments.contains(target.id))
|
||||
) {
|
||||
drawerItems += createDrawerItem(target)
|
||||
if (target.id == 1) {
|
||||
targetHomeId = target.id
|
||||
@ -1367,7 +1474,8 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
override fun onBackPressed() {
|
||||
if (!b.navView.onBackPressed()) {
|
||||
if (App.config.ui.openDrawerOnBackPressed && ((navTarget.popTo == null && navTarget.popToHome)
|
||||
|| navTarget.id == DRAWER_ITEM_HOME)) {
|
||||
|| navTarget.id == DRAWER_ITEM_HOME)
|
||||
) {
|
||||
b.navView.drawer.toggle()
|
||||
} else {
|
||||
navigateUp()
|
||||
@ -1376,6 +1484,11 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
|
||||
}
|
||||
|
||||
fun error(error: ApiError) = errorSnackbar.addError(error).show()
|
||||
fun snackbar(text: String, actionText: String? = null, onClick: (() -> Unit)? = null) = mainSnackbar.snackbar(text, actionText, onClick)
|
||||
fun snackbar(
|
||||
text: String,
|
||||
actionText: String? = null,
|
||||
onClick: (() -> Unit)? = null,
|
||||
) = mainSnackbar.snackbar(text, actionText, onClick)
|
||||
|
||||
fun snackbarDismiss() = mainSnackbar.dismiss()
|
||||
}
|
||||
|
@ -109,6 +109,7 @@ const val VULCAN_HEBE_ENDPOINT_PUSH_ALL = "api/mobile/push/all"
|
||||
const val VULCAN_HEBE_ENDPOINT_TIMETABLE = "api/mobile/schedule"
|
||||
const val VULCAN_HEBE_ENDPOINT_TIMETABLE_CHANGES = "api/mobile/schedule/changes"
|
||||
const val VULCAN_HEBE_ENDPOINT_ADDRESSBOOK = "api/mobile/addressbook"
|
||||
const val VULCAN_HEBE_ENDPOINT_TEACHERS = "api/mobile/teacher"
|
||||
const val VULCAN_HEBE_ENDPOINT_EXAMS = "api/mobile/exam"
|
||||
const val VULCAN_HEBE_ENDPOINT_GRADES = "api/mobile/grade"
|
||||
const val VULCAN_HEBE_ENDPOINT_GRADE_SUMMARY = "api/mobile/grade/summary"
|
||||
|
@ -21,6 +21,7 @@ const val ENDPOINT_VULCAN_HEBE_NOTICES = 3070
|
||||
const val ENDPOINT_VULCAN_HEBE_ATTENDANCE = 3080
|
||||
const val ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX = 3090
|
||||
const val ENDPOINT_VULCAN_HEBE_MESSAGES_SENT = 3100
|
||||
const val ENDPOINT_VULCAN_HEBE_TEACHERS = 3110
|
||||
const val ENDPOINT_VULCAN_HEBE_LUCKY_NUMBER = 3200
|
||||
|
||||
val VulcanFeatures = listOf(
|
||||
@ -83,6 +84,7 @@ val VulcanFeatures = listOf(
|
||||
|
||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_ALWAYS_NEEDED, listOf(
|
||||
ENDPOINT_VULCAN_HEBE_MAIN to LOGIN_METHOD_VULCAN_HEBE,
|
||||
ENDPOINT_VULCAN_HEBE_ADDRESSBOOK to LOGIN_METHOD_VULCAN_HEBE
|
||||
ENDPOINT_VULCAN_HEBE_ADDRESSBOOK to LOGIN_METHOD_VULCAN_HEBE,
|
||||
ENDPOINT_VULCAN_HEBE_TEACHERS to LOGIN_METHOD_VULCAN_HEBE
|
||||
), listOf(LOGIN_METHOD_VULCAN_HEBE))
|
||||
)
|
||||
|
@ -27,6 +27,7 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) {
|
||||
ENDPOINT_VULCAN_HEBE_NOTICES,
|
||||
ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX,
|
||||
ENDPOINT_VULCAN_HEBE_MESSAGES_SENT,
|
||||
ENDPOINT_VULCAN_HEBE_TEACHERS,
|
||||
ENDPOINT_VULCAN_HEBE_LUCKY_NUMBER
|
||||
)
|
||||
|
||||
@ -103,9 +104,13 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) {
|
||||
VulcanHebePushConfig(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_VULCAN_HEBE_ADDRESSBOOK -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_teachers)
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_addressbook)
|
||||
VulcanHebeAddressbook(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_VULCAN_HEBE_TEACHERS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_teachers)
|
||||
VulcanHebeTeachers(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_VULCAN_HEBE_TIMETABLE -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_timetable)
|
||||
VulcanHebeTimetable(data, lastSync, onSuccess)
|
||||
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) Antoni Czaplicki 2021-10-15.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
||||
|
||||
import pl.szczodrzynski.edziennik.DAY
|
||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_TEACHERS
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_TEACHERS
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
|
||||
import pl.szczodrzynski.edziennik.getString
|
||||
|
||||
class VulcanHebeTeachers(
|
||||
override val data: DataVulcan,
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit,
|
||||
) : VulcanHebe(data, lastSync) {
|
||||
companion object {
|
||||
const val TAG = "VulcanHebeTeachers"
|
||||
}
|
||||
|
||||
init {
|
||||
apiGetList(
|
||||
TAG,
|
||||
VULCAN_HEBE_ENDPOINT_TEACHERS,
|
||||
HebeFilterType.BY_PERIOD,
|
||||
lastSync = lastSync,
|
||||
) { list, _ ->
|
||||
list.forEach { person ->
|
||||
val name = person.getString("Name")
|
||||
val surname = person.getString("Surname")
|
||||
val displayName = person.getString("DisplayName")
|
||||
val subjectName = person.getString("Description") ?: return@apiGetList
|
||||
|
||||
val teacher = data.getTeacherByFirstLast(
|
||||
name?.plus(" ")?.plus(surname) ?: displayName ?: return@forEach
|
||||
)
|
||||
|
||||
teacher.addSubject(data.getSubject(null, subjectName).id)
|
||||
}
|
||||
data.setSyncNext(ENDPOINT_VULCAN_HEBE_TEACHERS, 2 * DAY)
|
||||
onSuccess(ENDPOINT_VULCAN_HEBE_TEACHERS)
|
||||
}
|
||||
}
|
||||
}
|
@ -43,7 +43,7 @@ import pl.szczodrzynski.edziennik.data.db.migration.*
|
||||
LibrusLesson::class,
|
||||
TimetableManual::class,
|
||||
Metadata::class
|
||||
], version = 95)
|
||||
], version = 96)
|
||||
@TypeConverters(
|
||||
ConverterTime::class,
|
||||
ConverterDate::class,
|
||||
@ -181,6 +181,7 @@ abstract class AppDb : RoomDatabase() {
|
||||
Migration93(),
|
||||
Migration94(),
|
||||
Migration95(),
|
||||
Migration96(),
|
||||
).allowMainThreadQueries().build()
|
||||
}
|
||||
}
|
||||
|
@ -9,10 +9,7 @@ import android.graphics.Bitmap
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.Ignore
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.fixName
|
||||
import pl.szczodrzynski.edziennik.getNameInitials
|
||||
import pl.szczodrzynski.edziennik.join
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import java.util.*
|
||||
|
||||
@Entity(tableName = "teachers",
|
||||
@ -26,6 +23,7 @@ open class Teacher {
|
||||
const val TYPE_SECRETARIAT = 4 // 16
|
||||
const val TYPE_PRINCIPAL = 5 // 32
|
||||
const val TYPE_SCHOOL_ADMIN = 6 // 64
|
||||
|
||||
// not teachers
|
||||
const val TYPE_SPECIALIST = 7 // 128
|
||||
const val TYPE_SUPER_ADMIN = 10 // 1024
|
||||
@ -36,7 +34,8 @@ open class Teacher {
|
||||
const val TYPE_OTHER = 24 // 16777216
|
||||
const val IS_TEACHER_MASK = 127
|
||||
|
||||
val types: List<Int> by lazy { listOf(
|
||||
val types: List<Int> by lazy {
|
||||
listOf(
|
||||
TYPE_TEACHER,
|
||||
TYPE_EDUCATOR,
|
||||
TYPE_PEDAGOGUE,
|
||||
@ -51,7 +50,8 @@ open class Teacher {
|
||||
TYPE_PARENTS_COUNCIL,
|
||||
TYPE_SCHOOL_PARENTS_COUNCIL,
|
||||
TYPE_OTHER
|
||||
) }
|
||||
)
|
||||
}
|
||||
|
||||
fun typeName(c: Context, type: Int, typeDescription: String? = null): String {
|
||||
val suffix = typeDescription?.let { " ($typeDescription)" } ?: ""
|
||||
@ -94,6 +94,9 @@ open class Teacher {
|
||||
@ColumnInfo(name = "teacherTypeDescription")
|
||||
var typeDescription: String? = null
|
||||
|
||||
@ColumnInfo(name = "teacherSubjects")
|
||||
var subjects = mutableListOf<Long>()
|
||||
|
||||
fun isType(checkingType: Int): Boolean {
|
||||
return type and (1 shl checkingType) >= 1
|
||||
}
|
||||
@ -105,6 +108,8 @@ open class Teacher {
|
||||
type = type or (1 shl i)
|
||||
}
|
||||
|
||||
fun addSubject(subjectId: Long) = subjects.add(subjectId)
|
||||
|
||||
fun unsetTeacherType(i: Int) {
|
||||
type = type and (1 shl i).inv()
|
||||
}
|
||||
@ -128,6 +133,7 @@ open class Teacher {
|
||||
*/
|
||||
@Ignore
|
||||
var recipientDisplayName: CharSequence? = null
|
||||
|
||||
/**
|
||||
* Used in Message composing - determining the priority
|
||||
* of search result, based on the search phrase match
|
||||
@ -142,8 +148,6 @@ open class Teacher {
|
||||
this.id = id
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Ignore
|
||||
constructor(profileId: Int, id: Long, name: String, surname: String) {
|
||||
this.profileId = profileId
|
||||
@ -170,6 +174,7 @@ open class Teacher {
|
||||
this.surname = it.surname
|
||||
this.type = it.type
|
||||
this.typeDescription = it.typeDescription
|
||||
this.subjects = it.subjects
|
||||
this.image = it.image
|
||||
this.recipientDisplayName = it.recipientDisplayName
|
||||
}
|
||||
@ -195,6 +200,7 @@ open class Teacher {
|
||||
", name='" + name + '\'' +
|
||||
", surname='" + surname + '\'' +
|
||||
", type=" + dumpType() +
|
||||
", subjects=" + subjects.joinToString() +
|
||||
", typeDescription='" + typeDescription + '\'' +
|
||||
'}'
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) Antoni Czaplicki 2021-10-17.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.db.migration
|
||||
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
|
||||
class Migration96 : Migration(95, 96) {
|
||||
override fun migrate(database: SupportSQLiteDatabase) {
|
||||
// teachers - associated subjects list
|
||||
database.execSQL("ALTER TABLE teachers ADD COLUMN teacherSubjects TEXT NOT NULL;")
|
||||
}
|
||||
}
|
@ -30,7 +30,7 @@ class MessagesComposeSuggestionAdapter(
|
||||
private val comparator by lazy { Comparator { o1: Teacher, o2: Teacher -> o1.recipientWeight - o2.recipientWeight } }
|
||||
|
||||
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
|
||||
val listItem = convertView ?: LayoutInflater.from(context).inflate(R.layout.messages_compose_suggestion_item, parent, false)
|
||||
val listItem = convertView ?: LayoutInflater.from(context).inflate(R.layout.teacher_item, parent, false)
|
||||
|
||||
val teacher = teacherList[position]
|
||||
val name = listItem.findViewById<TextView>(R.id.name)
|
||||
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) Antoni Czaplicki 2021-10-15.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.teachers
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import pl.szczodrzynski.edziennik.databinding.TeacherItemBinding
|
||||
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
|
||||
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesUtils.getProfileImage
|
||||
import pl.szczodrzynski.edziennik.utils.BetterLink
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class TeachersAdapter(
|
||||
private val activity: AppCompatActivity,
|
||||
val onItemClick: ((item: Teacher) -> Unit)? = null,
|
||||
) : RecyclerView.Adapter<TeachersAdapter.ViewHolder>(), CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "TeachersAdapter"
|
||||
}
|
||||
|
||||
private val app = activity.applicationContext as App
|
||||
// optional: place the manager here
|
||||
|
||||
private val job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
var items = listOf<Teacher>()
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val inflater = LayoutInflater.from(activity)
|
||||
val view = TeacherItemBinding.inflate(inflater, parent, false)
|
||||
return ViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val item = items[position]
|
||||
val b = holder.b
|
||||
|
||||
b.name.text = item.fullName
|
||||
b.image.setImageBitmap(item.image?: getProfileImage(48, 24, 16, 12, 1, item.fullName))
|
||||
var role = item.getTypeText(activity)
|
||||
if (item.subjects.isNotNullNorEmpty()) {
|
||||
val subjects = item.subjects.map { App.db.subjectDao().getByIdNow(App.profileId, it).longName }
|
||||
role = role.plus(": ").plus(subjects.joinToString())
|
||||
}
|
||||
b.type.text = role
|
||||
|
||||
item.fullName.let { name ->
|
||||
BetterLink.attach(
|
||||
b.name,
|
||||
teachers = mapOf(item.id to name)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
|
||||
class ViewHolder(val b: TeacherItemBinding) : RecyclerView.ViewHolder(b.root)
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) Antoni Czaplicki 2021-10-15.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.teachers
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.AsyncTask
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.databinding.TeachersListFragmentBinding
|
||||
import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class TeachersListFragment : Fragment(), CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "TeachersListFragment"
|
||||
}
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var activity: MainActivity
|
||||
private lateinit var b: TeachersListFragmentBinding
|
||||
|
||||
private val job: Job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
activity = (getActivity() as MainActivity?) ?: return null
|
||||
context ?: return null
|
||||
app = activity.application as App
|
||||
b = TeachersListFragmentBinding.inflate(inflater)
|
||||
return b.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { startCoroutineTimer(100L) {
|
||||
if (!isAdded) return@startCoroutineTimer
|
||||
|
||||
val adapter = TeachersAdapter(activity)
|
||||
|
||||
app.db.teacherDao().getAllTeachers(App.profileId).observe(this@TeachersListFragment, Observer { items ->
|
||||
if (!isAdded) return@Observer
|
||||
|
||||
// load & configure the adapter
|
||||
adapter.items = items
|
||||
if (items.isNotNullNorEmpty() && b.list.adapter == null) {
|
||||
b.list.adapter = adapter
|
||||
b.list.apply {
|
||||
setHasFixedSize(true)
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
addItemDecoration(SimpleDividerItemDecoration(context))
|
||||
}
|
||||
}
|
||||
adapter.notifyDataSetChanged()
|
||||
|
||||
// show/hide relevant views
|
||||
b.progressBar.isVisible = false
|
||||
if (items.isNullOrEmpty()) {
|
||||
b.list.isVisible = false
|
||||
b.noData.isVisible = true
|
||||
} else {
|
||||
b.list.isVisible = true
|
||||
b.noData.isVisible = false
|
||||
}
|
||||
})
|
||||
}}
|
||||
}
|
43
app/src/main/res/layout/teachers_list_fragment.xml
Normal file
43
app/src/main/res/layout/teachers_list_fragment.xml
Normal file
@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) Antoni Czaplicki 2021-10-15.
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/noData"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:drawablePadding="16dp"
|
||||
android:fontFamily="sans-serif-light"
|
||||
android:gravity="center"
|
||||
android:padding="16dp"
|
||||
android:text="@string/teachers_no_data"
|
||||
android:textSize="24sp"
|
||||
android:visibility="gone"
|
||||
app:drawableTopCompat="@drawable/ic_archive"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
tools:listitem="@layout/teacher_item"
|
||||
tools:visibility="visible" />
|
||||
</FrameLayout>
|
||||
</layout>
|
@ -656,6 +656,7 @@
|
||||
<string name="menu_message">Nachricht</string>
|
||||
<string name="menu_message_compose">Schreiben Sie eine Nachricht</string>
|
||||
<string name="menu_messages">Nachrichten</string>
|
||||
<string name="menu_more">Mehr</string>
|
||||
<string name="menu_notices">Verhalten</string>
|
||||
<string name="menu_notifications">Benachrichtigungen</string>
|
||||
<string name="menu_remove_notifications">Löschen</string>
|
||||
@ -1108,6 +1109,7 @@
|
||||
<string name="teacher_super_admin">Administrator / Superadministrator</string>
|
||||
<string name="teacher_teacher">Lehrer</string>
|
||||
<string name="teachers_browse_category">Kategorie durchsuchen</string>
|
||||
<string name="teachers_no_data">Keine Lehrer.</string>
|
||||
<string name="the_day_after">Übermorgen</string>
|
||||
<string name="the_day_before">Vorgestern</string>
|
||||
<string name="theme_amber">Bernstein</string>
|
||||
@ -1236,4 +1238,6 @@
|
||||
<string name="login_summary_account_parent">(Elternteil)</string>
|
||||
<string name="settings_about_contributors_text">Anwendungsentwickler</string>
|
||||
<string name="settings_about_contributors_subtext">Liste der Szkolny-Entwickler</string>
|
||||
<string name="menu_teachers">Lehrer</string>
|
||||
<string name="edziennik_progress_endpoint_addressbook">Addressbuch herunterladen…</string>
|
||||
</resources>
|
||||
|
@ -658,6 +658,7 @@
|
||||
<string name="menu_message">Message</string>
|
||||
<string name="menu_message_compose">Compose</string>
|
||||
<string name="menu_messages">Messages</string>
|
||||
<string name="menu_more">More</string>
|
||||
<string name="menu_notices">Behaviour</string>
|
||||
<string name="menu_notifications">Notifications</string>
|
||||
<string name="menu_remove_notifications">Clear</string>
|
||||
@ -1110,6 +1111,7 @@
|
||||
<string name="teacher_super_admin">SuperAdmin</string>
|
||||
<string name="teacher_teacher">Teacher</string>
|
||||
<string name="teachers_browse_category">Browse category</string>
|
||||
<string name="teachers_no_data">No teachers.</string>
|
||||
<string name="the_day_after">overmorrow</string>
|
||||
<string name="the_day_before">the day before yesterday</string>
|
||||
<string name="theme_amber">Amber</string>
|
||||
@ -1372,4 +1374,6 @@
|
||||
<string name="permissions_generate_timetable">In order to be able to save the generated timetable, you must grant access rights to the device\'s memory.\n\nClick OK to grant permissions.</string>
|
||||
<string name="login_summary_account_child">(Child)</string>
|
||||
<string name="login_summary_account_parent">(Parent)</string>
|
||||
<string name="menu_teachers">Teachers</string>
|
||||
<string name="edziennik_progress_endpoint_addressbook">Syncing addressbook…</string>
|
||||
</resources>
|
||||
|
@ -301,6 +301,7 @@
|
||||
<string name="edziennik_notification_api_text">Dzięki niej, aplikacja Szkolny.eu może synchronizować dane z e-dziennikiem. Możesz ją zamknąć, ponieważ w tej chwili nic nie robi.</string>
|
||||
<string name="edziennik_notification_api_title">Usługa synchronizacji</string>
|
||||
<string name="edziennik_progress_endpoint_account_details">Pobieranie szczegółów konta…</string>
|
||||
<string name="edziennik_progress_endpoint_addressbook">Pobieranie listy odbiorców…</string>
|
||||
<string name="edziennik_progress_endpoint_announcements">Pobieranie ogłoszeń szkolnych…</string>
|
||||
<string name="edziennik_progress_endpoint_attendance">Pobieranie frekwencji ucznia…</string>
|
||||
<string name="edziennik_progress_endpoint_attendance_types">Pobieranie kategorii obecności…</string>
|
||||
@ -708,6 +709,7 @@
|
||||
<string name="menu_message">Wiadomość</string>
|
||||
<string name="menu_message_compose">Napisz wiadomość</string>
|
||||
<string name="menu_messages">Wiadomości</string>
|
||||
<string name="menu_more">Więcej</string>
|
||||
<string name="menu_notices">Zachowanie</string>
|
||||
<string name="menu_notifications">Powiadomienia</string>
|
||||
<string name="menu_remove_notifications">Usuń wszystkie</string>
|
||||
@ -716,6 +718,7 @@
|
||||
<string name="menu_settings">Ustawienia</string>
|
||||
<string name="menu_sync">Synchronizuj</string>
|
||||
<string name="menu_sync_all">Synchronizuj wszystkie</string>
|
||||
<string name="menu_teachers">Nauczyciele</string>
|
||||
<string name="menu_template">Szablon</string>
|
||||
<string name="menu_timetable">Plan lekcji</string>
|
||||
<string name="menu_timetable_manual">Edytor planu lekcji</string>
|
||||
@ -1180,6 +1183,7 @@
|
||||
<string name="teacher_super_admin">Administrator / SuperAdministrator</string>
|
||||
<string name="teacher_teacher">Nauczyciel</string>
|
||||
<string name="teachers_browse_category">Przeglądaj kategorię</string>
|
||||
<string name="teachers_no_data">Brak nauczycieli.</string>
|
||||
<string name="the_day_after">pojutrze</string>
|
||||
<string name="the_day_before">przedwczoraj</string>
|
||||
<string name="theme_amber">Bursztynowy</string>
|
||||
|
Loading…
Reference in New Issue
Block a user