mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-06-13 14:10:46 +02:00
Compare commits
15 Commits
v4.0-beta.
...
v4.0-beta.
Author | SHA1 | Date | |
---|---|---|---|
c8c1fe5367 | |||
71128e0244 | |||
453bcaa1f6 | |||
48898ab1d4 | |||
a095520d0d | |||
2e0c6fa6a5 | |||
bfbc0861df | |||
3a500f3f28 | |||
df8094c39c | |||
448fd0e884 | |||
4717b4549e | |||
57a8d72f1c | |||
7e57617e04 | |||
37ddd643ac | |||
bcf3fef303 |
@ -24,6 +24,7 @@
|
||||
-keep class pl.szczodrzynski.edziennik.utils.models.** { *; }
|
||||
-keep class pl.szczodrzynski.edziennik.data.db.entity.Event { *; }
|
||||
-keep class pl.szczodrzynski.edziennik.data.db.full.EventFull { *; }
|
||||
-keep class pl.szczodrzynski.edziennik.data.db.entity.FeedbackMessage { *; }
|
||||
-keep class pl.szczodrzynski.edziennik.ui.modules.home.HomeCardModel { *; }
|
||||
-keepclassmembers class pl.szczodrzynski.edziennik.ui.widgets.WidgetConfig { public *; }
|
||||
-keepnames class pl.szczodrzynski.edziennik.ui.widgets.timetable.WidgetTimetableProvider
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
/*secret password - removed for source code publication*/
|
||||
static toys AES_IV[16] = {
|
||||
0x21, 0xd7, 0x64, 0x86, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
0x89, 0x62, 0x5d, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat);
|
||||
|
||||
|
@ -116,6 +116,7 @@ const val ERROR_LOGIN_LIBRUS_MESSAGES_INVALID_LOGIN = 179
|
||||
const val ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN = 180
|
||||
const val ERROR_LIBRUS_API_MAINTENANCE = 181
|
||||
const val ERROR_LIBRUS_PORTAL_MAINTENANCE = 182
|
||||
const val ERROR_LIBRUS_API_NOTICEBOARD_PROBLEM = 183
|
||||
|
||||
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN = 201
|
||||
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD = 202
|
||||
|
@ -63,6 +63,7 @@ open class LibrusApi(open val data: DataLibrus) {
|
||||
"NotesIsNotActive" -> ERROR_LIBRUS_API_NOTES_NOT_ACTIVE
|
||||
"InvalidRequest" -> ERROR_LIBRUS_API_INVALID_REQUEST_PARAMS
|
||||
"Nieprawidłowy węzeł." -> ERROR_LIBRUS_API_INCORRECT_ENDPOINT
|
||||
"NoticeboardProblem" -> ERROR_LIBRUS_API_NOTICEBOARD_PROBLEM
|
||||
else -> ERROR_LIBRUS_API_OTHER
|
||||
}.let { errorCode ->
|
||||
if (errorCode !in ignoreErrors) {
|
||||
|
@ -6,12 +6,13 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.api
|
||||
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_LIBRUS_API_INVALID_REQUEST_PARAMS
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_LIBRUS_API_NOTICEBOARD_PROBLEM
|
||||
import pl.szczodrzynski.edziennik.data.api.POST
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
||||
import pl.szczodrzynski.edziennik.data.api.events.AnnouncementGetEvent
|
||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
|
||||
|
||||
class LibrusApiAnnouncementMarkAsRead(
|
||||
override val data: DataLibrus,
|
||||
@ -24,7 +25,10 @@ class LibrusApiAnnouncementMarkAsRead(
|
||||
|
||||
init {
|
||||
apiGet(TAG, "SchoolNotices/MarkAsRead/${announcement.idString}", method = POST,
|
||||
ignoreErrors = listOf(ERROR_LIBRUS_API_INVALID_REQUEST_PARAMS)) {
|
||||
ignoreErrors = listOf(
|
||||
ERROR_LIBRUS_API_INVALID_REQUEST_PARAMS,
|
||||
ERROR_LIBRUS_API_NOTICEBOARD_PROBLEM
|
||||
)) {
|
||||
announcement.seen = true
|
||||
|
||||
EventBus.getDefault().postSticky(AnnouncementGetEvent(announcement))
|
||||
|
@ -58,11 +58,6 @@ class SynergiaTokenExtractor(override val data: DataLibrus, val onSuccess: () ->
|
||||
data.apiAccessToken = accountToken
|
||||
data.apiTokenExpiryTime = response.getUnixDate() + 6 * 60 * 60
|
||||
|
||||
// TODO remove this
|
||||
data.profile?.studentNameLong = json.getString("studentName") ?: ""
|
||||
val nameParts = json.getString("studentName")?.split(" ")
|
||||
data.profile?.studentNameShort = nameParts?.get(0) + " " + nameParts?.get(1)?.get(0)
|
||||
|
||||
onSuccess()
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ class ApiError(val tag: String, var errorCode: Int) {
|
||||
|
||||
fun toReportableError(context: Context): ErrorReportRequest.Error {
|
||||
val requestString = request?.let {
|
||||
it.method() + " " + it.url() + "\n" + it.headers()
|
||||
it.method() + " " + it.url() + "\n" + it.headers() + "\n\n" + (it.jsonBody()?.toString() ?: "") + (it.textBody() ?: "")
|
||||
}
|
||||
val responseString = response?.let {
|
||||
if (it.parserErrorBody == null) {
|
||||
|
@ -46,6 +46,6 @@ object Signing {
|
||||
|
||||
/*fun provideKey(param1: String, param2: Long): ByteArray {*/
|
||||
fun pleaseStopRightNow(param1: String, param2: Long): ByteArray {
|
||||
return "$param1.MTIzNDU2Nzg5MDdK88yzVk===.$param2".sha256()
|
||||
return "$param1.MTIzNDU2Nzg5MD4iBdQfyv===.$param2".sha256()
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
|
||||
}
|
||||
|
||||
private fun timetableNotifications() {
|
||||
for (lesson in app.db.timetableDao().getNotNotifiedNow()) {
|
||||
for (lesson in app.db.timetableDao().getNotNotifiedNow().filter { it.displayDate == null || it.displayDate!! >= today }) {
|
||||
val text = app.getString(
|
||||
R.string.notification_lesson_change_format,
|
||||
lesson.getDisplayChangeType(app),
|
||||
@ -58,7 +58,7 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
|
||||
}
|
||||
|
||||
private fun eventNotifications() {
|
||||
for (event in app.db.eventDao().notNotifiedNow) {
|
||||
for (event in app.db.eventDao().notNotifiedNow.filter { it.eventDate >= today }) {
|
||||
val text = if (event.type == Event.TYPE_HOMEWORK)
|
||||
app.getString(
|
||||
if (event.subjectLongName.isNullOrEmpty())
|
||||
@ -93,7 +93,7 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
|
||||
}
|
||||
|
||||
fun sharedEventNotifications() {
|
||||
for (event in app.db.eventDao().notNotifiedNow.filter { it.sharedBy != null }) {
|
||||
for (event in app.db.eventDao().notNotifiedNow.filter { it.eventDate >= today && it.sharedBy != null }) {
|
||||
val text = app.getString(
|
||||
R.string.notification_shared_event_format,
|
||||
event.sharedByName,
|
||||
@ -274,4 +274,4 @@ class Notifications(val app: App, val notifications: MutableList<Notification>,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,14 @@ interface TeacherAbsenceDao {
|
||||
"AND :date BETWEEN teacherAbsenceDateFrom AND teacherAbsenceDateTo")
|
||||
fun getAllByDateFull(profileId: Int, date: Date): LiveData<List<TeacherAbsenceFull>>
|
||||
|
||||
@Query("SELECT *, teachers.teacherName || ' ' || teachers.teacherSurname as teacherFullName, " +
|
||||
"metadata.seen, metadata.notified, metadata.addedDate FROM teacherAbsence " +
|
||||
"LEFT JOIN teachers USING (profileId, teacherId) " +
|
||||
"LEFT JOIN metadata ON teacherAbsenceId = thingId AND metadata.thingType = " + Metadata.TYPE_TEACHER_ABSENCE +
|
||||
" AND metadata.profileId = :profileId WHERE teachers.profileId = :profileId " +
|
||||
"AND :date BETWEEN teacherAbsenceDateFrom AND teacherAbsenceDateTo")
|
||||
fun getAllByDateNow(profileId: Int, date: Date): List<TeacherAbsenceFull>
|
||||
|
||||
@Query("DELETE FROM teacherAbsence WHERE profileId = :profileId")
|
||||
fun clear(profileId: Int)
|
||||
}
|
||||
|
@ -58,7 +58,14 @@ interface TimetableDao {
|
||||
WHERE timetable.profileId = :profileId AND type != -1 AND type != 0
|
||||
ORDER BY id, type
|
||||
""")
|
||||
fun getAllChangesNow(profileId: Int): List<Lesson>
|
||||
fun getAllChangesNow(profileId: Int): List<LessonFull>
|
||||
|
||||
@Query("""
|
||||
$QUERY
|
||||
WHERE timetable.profileId = :profileId AND type != -1 AND type != 0 AND ((type != 3 AND date = :date) OR ((type = 3 OR type = 1) AND oldDate = :date))
|
||||
ORDER BY id, type
|
||||
""")
|
||||
fun getChangesForDateNow(profileId: Int, date: Date): List<LessonFull>
|
||||
|
||||
@Query("""
|
||||
$QUERY
|
||||
|
@ -47,7 +47,7 @@ class SzkolnyAppFirebase(val app: App, val profiles: List<Profile>, val message:
|
||||
)
|
||||
"appUpdate" -> launch { UpdateWorker.runNow(app, app.gson.fromJson(message.data.getString("update"), Update::class.java)) }
|
||||
"feedbackMessage" -> launch {
|
||||
val message = app.gson.fromJson(message.data.getString("message"), FeedbackMessage::class.java)
|
||||
val message = app.gson.fromJson(message.data.getString("message"), FeedbackMessage::class.java) ?: return@launch
|
||||
feedbackMessage(message)
|
||||
}
|
||||
}
|
||||
@ -74,18 +74,20 @@ class SzkolnyAppFirebase(val app: App, val profiles: List<Profile>, val message:
|
||||
}
|
||||
withContext(Dispatchers.Default) {
|
||||
app.db.feedbackMessageDao().add(message)
|
||||
val notification = Notification(
|
||||
id = System.currentTimeMillis(),
|
||||
title = "Wiadomość od ${message.senderName}",
|
||||
text = message.text,
|
||||
type = Notification.TYPE_FEEDBACK_MESSAGE,
|
||||
profileId = null,
|
||||
profileName = "Wiadomość od ${message.senderName}"
|
||||
).addExtra("action", "feedbackMessage").addExtra("feedbackMessageDeviceId", message.deviceId)
|
||||
app.db.notificationDao().add(notification)
|
||||
PostNotifications(app, listOf(notification))
|
||||
if (!EventBus.getDefault().hasSubscriberForEvent(FeedbackMessageEvent::class.java)) {
|
||||
val notification = Notification(
|
||||
id = System.currentTimeMillis(),
|
||||
title = "Wiadomość od ${message.senderName}",
|
||||
text = message.text,
|
||||
type = Notification.TYPE_FEEDBACK_MESSAGE,
|
||||
profileId = null,
|
||||
profileName = "Wiadomość od ${message.senderName}"
|
||||
).addExtra("action", "feedbackMessage").addExtra("feedbackMessageDeviceId", message.deviceId)
|
||||
app.db.notificationDao().add(notification)
|
||||
PostNotifications(app, listOf(notification))
|
||||
}
|
||||
EventBus.getDefault().postSticky(FeedbackMessageEvent(message))
|
||||
}
|
||||
EventBus.getDefault().postSticky(FeedbackMessageEvent(message))
|
||||
}
|
||||
|
||||
private fun sharedEvent(teamCode: String, jsonStr: String, message: String) {
|
||||
|
@ -10,17 +10,16 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import kotlinx.android.synthetic.main.row_lesson_change_item.view.*
|
||||
import kotlinx.android.synthetic.main.row_teacher_absence_item.view.*
|
||||
import kotlinx.coroutines.*
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogDayBinding
|
||||
import pl.szczodrzynski.edziennik.onClick
|
||||
import pl.szczodrzynski.edziennik.setText
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.event.EventDetailsDialog
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.event.EventListAdapter
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.event.EventManualDialog
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.lessonchange.LessonChangeDialog
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.teacherabsence.TeacherAbsenceDialog
|
||||
import pl.szczodrzynski.edziennik.utils.SimpleDividerItemDecoration
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Week
|
||||
@ -77,13 +76,51 @@ class DayDialog(
|
||||
update()
|
||||
}}
|
||||
|
||||
private fun update() {
|
||||
private fun update() { launch {
|
||||
b.dayDate.setText(
|
||||
R.string.dialog_day_date_format,
|
||||
Week.getFullDayName(date.weekDay),
|
||||
date.formattedString
|
||||
)
|
||||
|
||||
val lessonChanges = withContext(Dispatchers.Default) {
|
||||
app.db.timetableDao().getChangesForDateNow(profileId, date)
|
||||
}
|
||||
|
||||
lessonChanges.ifNotEmpty {
|
||||
b.lessonChangeContainer.visibility = View.VISIBLE
|
||||
b.lessonChangeContainer.lessonChangeCount.text = it.size.toString()
|
||||
|
||||
b.lessonChangeLayout.onClick {
|
||||
LessonChangeDialog(
|
||||
activity,
|
||||
profileId,
|
||||
date,
|
||||
onShowListener = onShowListener,
|
||||
onDismissListener = onDismissListener
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val teacherAbsences = withContext(Dispatchers.Default) {
|
||||
app.db.teacherAbsenceDao().getAllByDateNow(profileId, date)
|
||||
}
|
||||
|
||||
teacherAbsences.ifNotEmpty {
|
||||
b.teacherAbsenceContainer.visibility = View.VISIBLE
|
||||
b.teacherAbsenceContainer.teacherAbsenceCount.text = it.size.toString()
|
||||
|
||||
b.teacherAbsenceLayout.onClick {
|
||||
TeacherAbsenceDialog(
|
||||
activity,
|
||||
profileId,
|
||||
date,
|
||||
onShowListener = onShowListener,
|
||||
onDismissListener = onDismissListener
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
adapter = EventListAdapter(
|
||||
activity,
|
||||
onItemClick = {
|
||||
@ -126,5 +163,5 @@ class DayDialog(
|
||||
b.eventsNoData.visibility = View.VISIBLE
|
||||
}
|
||||
})
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-12-19.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.lessonchange
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.PorterDuff
|
||||
import android.graphics.PorterDuffColorFilter
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Lesson
|
||||
import pl.szczodrzynski.edziennik.data.db.full.LessonFull
|
||||
import pl.szczodrzynski.edziennik.databinding.TimetableLessonBinding
|
||||
import pl.szczodrzynski.navlib.getColorFromAttr
|
||||
|
||||
class LessonChangeAdapter(
|
||||
val context: Context,
|
||||
private val onItemClick: ((lesson: LessonFull) -> Unit)? = null
|
||||
) : RecyclerView.Adapter<LessonChangeAdapter.ViewHolder>() {
|
||||
|
||||
var items = listOf<LessonFull>()
|
||||
|
||||
private val arrowRight = " → "
|
||||
private val bullet = " • "
|
||||
private val colorSecondary = android.R.attr.textColorSecondary.resolveAttr(context)
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
val view = TimetableLessonBinding.inflate(inflater, parent, false)
|
||||
return ViewHolder(view)
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
val lesson = items[position]
|
||||
val b = holder.b
|
||||
|
||||
b.root.onClick {
|
||||
onItemClick?.invoke(lesson)
|
||||
}
|
||||
|
||||
val startTime = lesson.displayStartTime ?: return
|
||||
val endTime = lesson.displayEndTime ?: return
|
||||
|
||||
val timeRange = "${startTime.stringHM} - ${endTime.stringHM}".asColoredSpannable(colorSecondary)
|
||||
|
||||
b.unread = false
|
||||
b.root.background = null
|
||||
|
||||
b.root.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||
topMargin = 16.dp
|
||||
}
|
||||
|
||||
// teacher
|
||||
val teacherInfo = if (lesson.teacherId != null && lesson.teacherId == lesson.oldTeacherId)
|
||||
lesson.teacherName ?: "?"
|
||||
else
|
||||
mutableListOf<CharSequence>().apply {
|
||||
lesson.oldTeacherName?.let { add(it.asStrikethroughSpannable()) }
|
||||
lesson.teacherName?.let { add(it) }
|
||||
}.concat(arrowRight)
|
||||
|
||||
// team
|
||||
val teamInfo = if (lesson.teamId != null && lesson.teamId == lesson.oldTeamId)
|
||||
lesson.teamName ?: "?"
|
||||
else
|
||||
mutableListOf<CharSequence>().apply {
|
||||
lesson.oldTeamName?.let { add(it.asStrikethroughSpannable()) }
|
||||
lesson.teamName?.let { add(it) }
|
||||
}.concat(arrowRight)
|
||||
|
||||
// classroom
|
||||
val classroomInfo = if (lesson.classroom != null && lesson.classroom == lesson.oldClassroom)
|
||||
lesson.classroom ?: "?"
|
||||
else
|
||||
mutableListOf<CharSequence>().apply {
|
||||
lesson.oldClassroom?.let { add(it.asStrikethroughSpannable()) }
|
||||
lesson.classroom?.let { add(it) }
|
||||
}.concat(arrowRight)
|
||||
|
||||
|
||||
b.lessonNumber = lesson.displayLessonNumber
|
||||
b.subjectName.text = lesson.displaySubjectName?.let {
|
||||
if (lesson.type == Lesson.TYPE_CANCELLED || lesson.type == Lesson.TYPE_SHIFTED_SOURCE)
|
||||
it.asStrikethroughSpannable().asColoredSpannable(colorSecondary)
|
||||
else
|
||||
it
|
||||
}
|
||||
b.detailsFirst.text = listOfNotEmpty(timeRange, classroomInfo).concat(bullet)
|
||||
b.detailsSecond.text = listOfNotEmpty(teacherInfo, teamInfo).concat(bullet)
|
||||
|
||||
//lb.subjectName.typeface = Typeface.create("sans-serif-light", Typeface.BOLD)
|
||||
when (lesson.type) {
|
||||
Lesson.TYPE_NORMAL -> {
|
||||
b.annotationVisible = false
|
||||
}
|
||||
Lesson.TYPE_CANCELLED -> {
|
||||
b.annotationVisible = true
|
||||
b.annotation.setText(R.string.timetable_lesson_cancelled)
|
||||
b.annotation.background.colorFilter = PorterDuffColorFilter(
|
||||
getColorFromAttr(context, R.attr.timetable_lesson_cancelled_color),
|
||||
PorterDuff.Mode.SRC_ATOP
|
||||
)
|
||||
//lb.subjectName.typeface = Typeface.DEFAULT
|
||||
}
|
||||
Lesson.TYPE_CHANGE -> {
|
||||
b.annotationVisible = true
|
||||
when {
|
||||
lesson.subjectId != lesson.oldSubjectId && lesson.teacherId != lesson.oldTeacherId
|
||||
&& lesson.oldSubjectName != null && lesson.oldTeacherName != null ->
|
||||
b.annotation.setText(
|
||||
R.string.timetable_lesson_change_format,
|
||||
"${lesson.oldSubjectName ?: "?"}, ${lesson.oldTeacherName ?: "?"}"
|
||||
)
|
||||
|
||||
lesson.subjectId != lesson.oldSubjectId && lesson.oldSubjectName != null ->
|
||||
b.annotation.setText(
|
||||
R.string.timetable_lesson_change_format,
|
||||
lesson.oldSubjectName ?: "?"
|
||||
)
|
||||
|
||||
lesson.teacherId != lesson.oldTeacherId && lesson.oldTeacherName != null ->
|
||||
b.annotation.setText(
|
||||
R.string.timetable_lesson_change_format,
|
||||
lesson.oldTeacherName ?: "?"
|
||||
)
|
||||
else -> b.annotation.setText(R.string.timetable_lesson_change)
|
||||
}
|
||||
|
||||
b.annotation.background.colorFilter = PorterDuffColorFilter(
|
||||
getColorFromAttr(context, R.attr.timetable_lesson_change_color),
|
||||
PorterDuff.Mode.SRC_ATOP
|
||||
)
|
||||
}
|
||||
Lesson.TYPE_SHIFTED_SOURCE -> {
|
||||
b.annotationVisible = true
|
||||
when {
|
||||
lesson.date != lesson.oldDate && lesson.date != null ->
|
||||
b.annotation.setText(
|
||||
R.string.timetable_lesson_shifted_other_day,
|
||||
lesson.date?.stringY_m_d ?: "?",
|
||||
lesson.startTime?.stringHM ?: ""
|
||||
)
|
||||
|
||||
lesson.startTime != lesson.oldStartTime && lesson.startTime != null ->
|
||||
b.annotation.setText(
|
||||
R.string.timetable_lesson_shifted_same_day,
|
||||
lesson.startTime?.stringHM ?: "?"
|
||||
)
|
||||
|
||||
else -> b.annotation.setText(R.string.timetable_lesson_shifted)
|
||||
}
|
||||
|
||||
b.annotation.background.setTintColor(R.attr.timetable_lesson_shifted_source_color.resolveAttr(context))
|
||||
}
|
||||
Lesson.TYPE_SHIFTED_TARGET -> {
|
||||
b.annotationVisible = true
|
||||
when {
|
||||
lesson.date != lesson.oldDate && lesson.oldDate != null ->
|
||||
b.annotation.setText(
|
||||
R.string.timetable_lesson_shifted_from_other_day,
|
||||
lesson.oldDate?.stringY_m_d ?: "?",
|
||||
lesson.oldStartTime?.stringHM ?: ""
|
||||
)
|
||||
|
||||
lesson.startTime != lesson.oldStartTime && lesson.oldStartTime != null ->
|
||||
b.annotation.setText(
|
||||
R.string.timetable_lesson_shifted_from_same_day,
|
||||
lesson.oldStartTime?.stringHM ?: "?"
|
||||
)
|
||||
|
||||
else -> b.annotation.setText(R.string.timetable_lesson_shifted_from)
|
||||
}
|
||||
|
||||
b.annotation.background.colorFilter = PorterDuffColorFilter(
|
||||
getColorFromAttr(context, R.attr.timetable_lesson_shifted_target_color),
|
||||
PorterDuff.Mode.SRC_ATOP
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = items.size
|
||||
|
||||
class ViewHolder(val b: TimetableLessonBinding) : RecyclerView.ViewHolder(b.root)
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.lessonchange;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
|
||||
import pl.szczodrzynski.edziennik.App;
|
||||
import pl.szczodrzynski.edziennik.R;
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogLessonChangeListBinding;
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date;
|
||||
|
||||
public class LessonChangeDialog {
|
||||
private App app;
|
||||
private Context context;
|
||||
private int profileId;
|
||||
|
||||
public LessonChangeDialog(Context context) {
|
||||
this.context = context;
|
||||
this.profileId = App.Companion.getProfileId();
|
||||
}
|
||||
public LessonChangeDialog(Context context, int profileId) {
|
||||
this.context = context;
|
||||
this.profileId = profileId;
|
||||
}
|
||||
|
||||
private MaterialDialog dialog;
|
||||
private DialogLessonChangeListBinding b;
|
||||
|
||||
public void show(App _app, Date date)
|
||||
{
|
||||
this.app = _app;
|
||||
dialog = new MaterialDialog.Builder(context)
|
||||
.title(date.getFormattedString())
|
||||
.customView(R.layout.dialog_lesson_change_list, false)
|
||||
.positiveText(R.string.close)
|
||||
.autoDismiss(false)
|
||||
.onPositive((dialog, which) -> dialog.dismiss())
|
||||
.show();
|
||||
if (dialog.getCustomView() == null)
|
||||
return;
|
||||
b = DataBindingUtil.bind(dialog.getCustomView());
|
||||
if (b == null)
|
||||
return;
|
||||
|
||||
b.lessonChangeView.setHasFixedSize(true);
|
||||
b.lessonChangeView.setLayoutManager(new LinearLayoutManager(context));
|
||||
|
||||
/*app.db.lessonDao().getAllByDate(profileId, date, Time.getNow()).observe((LifecycleOwner) context, lessons -> {
|
||||
if (app == null || app.profile == null || b == null)
|
||||
return;
|
||||
|
||||
List<LessonFull> changedLessons = new ArrayList<>();
|
||||
for (LessonFull lesson: lessons) {
|
||||
if (lesson.changeId != 0) {
|
||||
changedLessons.add(lesson);
|
||||
}
|
||||
}
|
||||
|
||||
app.db.eventDao().getAllByDate(profileId, date).observe((LifecycleOwner) context, events -> {
|
||||
TimetableAdapter adapter = new TimetableAdapter(context, date, changedLessons, events == null ? new ArrayList<>() : events);
|
||||
b.lessonChangeView.setAdapter(adapter);
|
||||
b.lessonChangeView.setVisibility(View.VISIBLE);
|
||||
});
|
||||
});*/
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.lessonchange
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.*
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogLessonChangeListBinding
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.timetable.LessonDetailsDialog
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class LessonChangeDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val profileId: Int,
|
||||
private val defaultDate: Date,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
companion object {
|
||||
const val TAG = "LessonChangeDialog"
|
||||
}
|
||||
|
||||
private val app by lazy { activity.application as App }
|
||||
|
||||
private lateinit var job: Job
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
private lateinit var b: DialogLessonChangeListBinding
|
||||
private lateinit var dialog: AlertDialog
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
job = Job()
|
||||
onShowListener?.invoke(TAG)
|
||||
b = DialogLessonChangeListBinding.inflate(activity.layoutInflater)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(defaultDate.formattedString)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.close) { dialog, _ -> dialog.dismiss() }
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.create()
|
||||
loadLessonChanges()
|
||||
}}
|
||||
|
||||
private fun loadLessonChanges() { launch {
|
||||
val lessonChanges = withContext(Dispatchers.Default) {
|
||||
app.db.timetableDao().getChangesForDateNow(profileId, defaultDate)
|
||||
}
|
||||
|
||||
val adapter = LessonChangeAdapter(
|
||||
activity,
|
||||
onItemClick = {
|
||||
LessonDetailsDialog(
|
||||
activity,
|
||||
it,
|
||||
onShowListener = onShowListener,
|
||||
onDismissListener = onDismissListener
|
||||
)
|
||||
}
|
||||
).apply {
|
||||
items = lessonChanges
|
||||
}
|
||||
|
||||
b.lessonChangeView.adapter = adapter
|
||||
b.lessonChangeView.layoutManager = LinearLayoutManager(activity)
|
||||
|
||||
dialog.show()
|
||||
}}
|
||||
}
|
@ -32,6 +32,7 @@ import pl.szczodrzynski.edziennik.databinding.FragmentAgendaCalendarBinding
|
||||
import pl.szczodrzynski.edziennik.databinding.FragmentAgendaDefaultBinding
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.day.DayDialog
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.event.EventManualDialog
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.lessonchange.LessonChangeDialog
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.teacherabsence.TeacherAbsenceDialog
|
||||
import pl.szczodrzynski.edziennik.ui.modules.agenda.lessonchange.LessonChangeCounter
|
||||
import pl.szczodrzynski.edziennik.ui.modules.agenda.lessonchange.LessonChangeEvent
|
||||
@ -215,7 +216,7 @@ class AgendaFragment : Fragment(), CoroutineScope {
|
||||
eventList.add(BaseCalendarEvent(
|
||||
"${event.typeName} - ${event.topic}",
|
||||
"",
|
||||
if (event.startTime == null) getString(R.string.agenda_event_all_day) else event.startTime!!.stringHM +
|
||||
(if (event.startTime == null) getString(R.string.agenda_event_all_day) else event.startTime!!.stringHM) +
|
||||
(event.subjectLongName?.let { ", $it" } ?: "") +
|
||||
(event.teacherFullName?.let { ", $it" } ?: "") +
|
||||
(event.teamName?.let { ", $it" } ?: ""),
|
||||
@ -250,7 +251,7 @@ class AgendaFragment : Fragment(), CoroutineScope {
|
||||
|
||||
when (event) {
|
||||
is BaseCalendarEvent -> DayDialog(activity, app.profileId, date)
|
||||
// is LessonChangeEvent -> todo
|
||||
is LessonChangeEvent -> LessonChangeDialog(activity, app.profileId, date)
|
||||
is TeacherAbsenceEvent -> TeacherAbsenceDialog(activity, app.profileId, date)
|
||||
}
|
||||
}
|
||||
|
@ -70,9 +70,14 @@ class FeedbackFragment : Fragment(), CoroutineScope {
|
||||
fun onFeedbackMessageEvent(event: FeedbackMessageEvent) {
|
||||
EventBus.getDefault().removeStickyEvent(event)
|
||||
val message = event.message
|
||||
val chatMessage = getChatMessage(message)
|
||||
if (message.received) chatView.receive(chatMessage)
|
||||
else chatView.send(chatMessage)
|
||||
if (currentDeviceId == null || message.deviceId == currentDeviceId) {
|
||||
val chatMessage = getChatMessage(message)
|
||||
if (message.received) chatView.receive(chatMessage)
|
||||
else chatView.send(chatMessage)
|
||||
}
|
||||
else {
|
||||
Toast.makeText(context, "${message.senderName}: Nowa wiadomość w innym wątku.", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
|
||||
private val users = mutableMapOf(
|
||||
|
@ -155,7 +155,7 @@ public class WidgetTimetableFactory implements RemoteViewsService.RemoteViewsFac
|
||||
views.setViewVisibility(R.id.widgetTimetableContent, View.GONE);
|
||||
views.setTextViewText(R.id.widgetTimetableProfileName, lesson.separatorProfileName);
|
||||
views.setTextViewTextSize(R.id.widgetTimetableProfileName, COMPLEX_UNIT_SP, lesson.bigStyle ? 30 : 20);
|
||||
views.setTextColor(R.id.widgetTimetableProfileName, lesson.darkTheme ? 0xff000000 : 0xffffffff);
|
||||
views.setTextColor(R.id.widgetTimetableProfileName, lesson.darkTheme ? 0xffffffff : 0xff000000);
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("profileId", lesson.profileId);
|
||||
|
@ -30,29 +30,43 @@
|
||||
android:textIsSelectable="true"
|
||||
tools:text="wtorek, 17 grudnia" />
|
||||
|
||||
<include
|
||||
android:id="@+id/lessonChangeContainer"
|
||||
layout="@layout/row_lesson_change_item"
|
||||
<LinearLayout
|
||||
android:id="@+id/lessonChangeLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
android:background="?selectableItemBackground">
|
||||
|
||||
<include
|
||||
android:id="@+id/teacherAbsenceContainer"
|
||||
layout="@layout/row_teacher_absence_item"
|
||||
<include
|
||||
android:id="@+id/lessonChangeContainer"
|
||||
layout="@layout/row_lesson_change_item"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/teacherAbsenceLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
android:background="?selectableItemBackground">
|
||||
|
||||
<include
|
||||
android:id="@+id/teacherAbsenceContainer"
|
||||
layout="@layout/row_teacher_absence_item"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/eventsNoData"
|
||||
|
@ -11,5 +11,5 @@
|
||||
android:paddingLeft="24dp"
|
||||
android:paddingRight="24dp"
|
||||
android:clipToPadding="false"
|
||||
tools:listitem="@layout/row_timetable_item" />
|
||||
</layout>
|
||||
tools:listitem="@layout/timetable_lesson" />
|
||||
</layout>
|
||||
|
@ -54,7 +54,8 @@
|
||||
android:focusableInTouchMode="true"
|
||||
android:hint="@string/messages_compose_subject_hint"
|
||||
android:singleLine="true"
|
||||
tools:text="kachoomba"/>
|
||||
tools:text="kachoomba"
|
||||
android:inputType="textCapSentences|textAutoCorrect|textShortMessage|textAutoComplete|textEmailSubject"/>
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
@ -66,7 +67,7 @@
|
||||
app:boxBackgroundMode="filled"
|
||||
app:counterEnabled="true"
|
||||
tools:counterMaxLength="1983">
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
<androidx.appcompat.widget.AppCompatEditText
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@ -77,7 +78,7 @@
|
||||
android:ems="10"
|
||||
android:gravity="start|top"
|
||||
tools:text="Witam,\n\nchciałem przekazać bardzo ważną wiadomość.\nJest to cytat znanej osoby.\n\n"To jest tak, ale nie. Pamiętaj żeby oczywiście"\n\nCytat ma bardzo duże przesłanie i ogromny wpływ na dzisiejszą kulturę i rozwój współczesnej cywilizacji.\n\nJako zadanie domowe, należy wypisać 5 pierwszych liczb pierwszych. Uzasadnij decyzję, odwołując się do cytatu i 3 innych przykładów z literatury lub filmu.\n\nPozdrawiam,\nJa."
|
||||
android:inputType="textMultiLine" />
|
||||
android:inputType="textMultiLine|textAutoCorrect|textLongMessage|textAutoComplete|textCapSentences" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<!--<com.google.android.material.button.MaterialButtonToggleGroup
|
||||
@ -130,4 +131,4 @@
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</layout>
|
||||
</layout>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<androidx.cardview.widget.CardView android:id="@+id/lesson_change_card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:cardBackgroundColor="#78909c"
|
||||
app:cardBackgroundColor="#78909c"
|
||||
app:cardCornerRadius="5dp"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
|
@ -1,7 +1,7 @@
|
||||
<androidx.cardview.widget.CardView android:id="@+id/teacherAbsenceCard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:cardBackgroundColor="#ff1744"
|
||||
app:cardBackgroundColor="#ff1744"
|
||||
app:cardCornerRadius="5dp"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
|
@ -17,7 +17,7 @@
|
||||
</data>
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:colorBackground"
|
||||
android:foreground="@drawable/bg_rounded_ripple_4dp"
|
||||
tools:padding="32dp">
|
||||
|
@ -93,7 +93,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="8dp"
|
||||
android:textColor="@color/primaryTextLight"
|
||||
android:textColor="@color/primaryTextDark"
|
||||
android:gravity="center"
|
||||
android:textSize="16sp"
|
||||
android:text="@string/widget_timetable_no_timetable"
|
||||
@ -106,7 +106,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="8dp"
|
||||
android:textColor="@color/primaryTextLight"
|
||||
android:textColor="@color/primaryTextDark"
|
||||
android:gravity="center"
|
||||
android:textSize="16sp"
|
||||
android:text="@string/widget_timetable_no_lessons_found"
|
||||
@ -115,4 +115,4 @@
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
@ -90,6 +90,7 @@
|
||||
<string name="error_180" translatable="false">ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN</string>
|
||||
<string name="error_181" translatable="false">ERROR_LIBRUS_API_MAINTENANCE</string>
|
||||
<string name="error_182" translatable="false">ERROR_LIBRUS_PORTAL_MAINTENANCE</string>
|
||||
<string name="error_183" translatable="false">ERROR_LIBRUS_API_NOTICEBOARD_PROBLEM</string>
|
||||
|
||||
<string name="error_201" translatable="false">ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN</string>
|
||||
<string name="error_202" translatable="false">ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD</string>
|
||||
@ -256,6 +257,7 @@
|
||||
<string name="error_180_reason">Librus Portal: nieprawidłowe dane logowania</string>
|
||||
<string name="error_181_reason">Librus API: przerwa techniczna</string>
|
||||
<string name="error_182_reason">Librus Portal: przerwa techniczna</string>
|
||||
<string name="error_183_reason">Wystąpił problem z tablicą ogłoszeń</string>
|
||||
|
||||
<string name="error_201_reason">Nieprawidłowy login lub hasło</string>
|
||||
<string name="error_202_reason">Podano stare hasło</string>
|
||||
|
@ -5,8 +5,8 @@ buildscript {
|
||||
kotlin_version = '1.3.61'
|
||||
|
||||
release = [
|
||||
versionName: "4.0-beta.7",
|
||||
versionCode: 4000007
|
||||
versionName: "4.0-beta.8",
|
||||
versionCode: 4000008
|
||||
]
|
||||
|
||||
setup = [
|
||||
|
Reference in New Issue
Block a user