forked from github/szkolny
Compare commits
No commits in common. "v3.9.9-dev" and "v3.9.6-dev" have entirely different histories.
v3.9.9-dev
...
v3.9.6-dev
50 changed files with 738 additions and 1494 deletions
|
@ -169,7 +169,7 @@ dependencies {
|
||||||
|
|
||||||
implementation 'com.github.kuba2k2:RecyclerTabLayout:700f980584'
|
implementation 'com.github.kuba2k2:RecyclerTabLayout:700f980584'
|
||||||
|
|
||||||
implementation 'com.github.kuba2k2:Tachyon:551943a6b5'
|
implementation 'com.linkedin.android.tachyon:tachyon:1.0.2'
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
|
|
@ -4,9 +4,7 @@ import android.Manifest
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.Resources
|
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.*
|
import android.text.*
|
||||||
|
@ -15,10 +13,9 @@ import android.text.style.StrikethroughSpan
|
||||||
import android.text.style.StyleSpan
|
import android.text.style.StyleSpan
|
||||||
import android.util.LongSparseArray
|
import android.util.LongSparseArray
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
import android.util.TypedValue
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.annotation.*
|
import androidx.annotation.StringRes
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.util.forEach
|
import androidx.core.util.forEach
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
@ -449,49 +446,3 @@ fun <T> LiveData<T>.observeOnce(lifecycleOwner: LifecycleOwner, observer: Observ
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a value in dp to pixels.
|
|
||||||
*/
|
|
||||||
val Int.dp: Int
|
|
||||||
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
|
|
||||||
/**
|
|
||||||
* Convert a value in pixels to dp.
|
|
||||||
*/
|
|
||||||
val Int.px: Int
|
|
||||||
get() = (this / Resources.getSystem().displayMetrics.density).toInt()
|
|
||||||
|
|
||||||
@ColorInt
|
|
||||||
fun @receiver:AttrRes Int.resolveAttr(context: Context?): Int {
|
|
||||||
val typedValue = TypedValue()
|
|
||||||
context?.theme?.resolveAttribute(this, typedValue, true)
|
|
||||||
return typedValue.data
|
|
||||||
}
|
|
||||||
@ColorInt
|
|
||||||
fun @receiver:ColorRes Int.resolveColor(context: Context): Int {
|
|
||||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
context.resources.getColor(this, context.theme)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
context.resources.getColor(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fun @receiver:DrawableRes Int.resolveDrawable(context: Context): Drawable {
|
|
||||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
context.resources.getDrawable(this, context.theme)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
context.resources.getDrawable(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun View.findParentById(targetId: Int): View? {
|
|
||||||
if (id == targetId) {
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
val viewParent = this.parent ?: return null
|
|
||||||
if (viewParent is View) {
|
|
||||||
return viewParent.findParentById(targetId)
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
|
@ -376,11 +376,6 @@ class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
b.swipeRefreshLayout.isEnabled = true
|
b.swipeRefreshLayout.isEnabled = true
|
||||||
b.swipeRefreshLayout.setOnRefreshListener { this.syncCurrentFeature() }
|
b.swipeRefreshLayout.setOnRefreshListener { this.syncCurrentFeature() }
|
||||||
b.swipeRefreshLayout.setColorSchemeResources(
|
|
||||||
R.color.md_blue_500,
|
|
||||||
R.color.md_amber_500,
|
|
||||||
R.color.md_green_500
|
|
||||||
)
|
|
||||||
|
|
||||||
isStoragePermissionGranted()
|
isStoragePermissionGranted()
|
||||||
|
|
||||||
|
|
|
@ -311,14 +311,13 @@ public class Notifier {
|
||||||
\____/| .__/ \__,_|\__,_|\__\___||___/
|
\____/| .__/ \__,_|\__,_|\__\___||___/
|
||||||
| |
|
| |
|
||||||
|*/
|
|*/
|
||||||
public void notificationUpdatesShow(String updateVersion, String updateUrl, String updateFilename, boolean updateDirect) {
|
public void notificationUpdatesShow(String updateVersion, String updateUrl, String updateFilename) {
|
||||||
if (!app.appConfig.notifyAboutUpdates)
|
if (!app.appConfig.notifyAboutUpdates)
|
||||||
return;
|
return;
|
||||||
Intent notificationIntent = new Intent(app.getContext(), BootReceiver.NotificationActionService.class)
|
Intent notificationIntent = new Intent(app.getContext(), BootReceiver.NotificationActionService.class)
|
||||||
.putExtra("update_version", updateVersion)
|
.putExtra("update_version", updateVersion)
|
||||||
.putExtra("update_url", updateUrl)
|
.putExtra("update_url", updateUrl)
|
||||||
.putExtra("update_filename", updateFilename)
|
.putExtra("update_filename", updateFilename);
|
||||||
.putExtra("update_direct", updateDirect);
|
|
||||||
|
|
||||||
PendingIntent pendingIntent = PendingIntent.getService(app.getContext(), 0,
|
PendingIntent pendingIntent = PendingIntent.getService(app.getContext(), 0,
|
||||||
notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
|
notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT);
|
||||||
|
|
|
@ -185,12 +185,12 @@ class WidgetTimetable : AppWidgetProvider() {
|
||||||
// search for lessons to display
|
// search for lessons to display
|
||||||
val timetableDate = Date.getToday()
|
val timetableDate = Date.getToday()
|
||||||
var checkedDays = 0
|
var checkedDays = 0
|
||||||
var lessons = lessonList.filter { it.profileId == profile.id && it.displayDate == timetableDate && it.type != Lesson.TYPE_NO_LESSONS }
|
var lessons = lessonList.filter { it.profileId == profile.id && it.displayDate == timetableDate }
|
||||||
while ((lessons.isEmpty() || lessons.none {
|
while ((lessons.isEmpty() || lessons.none {
|
||||||
it.displayDate != today || (it.displayDate == today && it.displayEndTime != null && it.displayEndTime!! >= now)
|
it.displayDate != today || (it.displayDate == today && it.displayEndTime != null && it.displayEndTime!! >= now)
|
||||||
}) && checkedDays < 7) {
|
}) && checkedDays < 7) {
|
||||||
timetableDate.stepForward(0, 0, 1)
|
timetableDate.stepForward(0, 0, 1)
|
||||||
lessons = lessonList.filter { it.profileId == profile.id && it.displayDate == timetableDate && it.type != Lesson.TYPE_NO_LESSONS }
|
lessons = lessonList.filter { it.profileId == profile.id && it.displayDate == timetableDate }
|
||||||
checkedDays++
|
checkedDays++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,8 +214,8 @@ class WidgetTimetable : AppWidgetProvider() {
|
||||||
|
|
||||||
model.lessonId = lesson.id
|
model.lessonId = lesson.id
|
||||||
model.lessonDate = timetableDate
|
model.lessonDate = timetableDate
|
||||||
model.startTime = lesson.displayStartTime
|
model.startTime = lesson.startTime
|
||||||
model.endTime = lesson.displayEndTime
|
model.endTime = lesson.endTime
|
||||||
|
|
||||||
// check if the lesson has already passed or it's currently in progress
|
// check if the lesson has already passed or it's currently in progress
|
||||||
if (lesson.displayDate == today) {
|
if (lesson.displayDate == today) {
|
||||||
|
|
|
@ -39,11 +39,9 @@ const val ERROR_REQUEST_HTTP_404 = 54
|
||||||
const val ERROR_REQUEST_HTTP_405 = 55
|
const val ERROR_REQUEST_HTTP_405 = 55
|
||||||
const val ERROR_REQUEST_HTTP_410 = 56
|
const val ERROR_REQUEST_HTTP_410 = 56
|
||||||
const val ERROR_REQUEST_HTTP_500 = 57
|
const val ERROR_REQUEST_HTTP_500 = 57
|
||||||
const val ERROR_REQUEST_FAILURE_HOSTNAME_NOT_FOUND = 60
|
|
||||||
const val ERROR_REQUEST_FAILURE_TIMEOUT = 61
|
|
||||||
const val ERROR_REQUEST_FAILURE_NO_INTERNET = 62
|
|
||||||
const val ERROR_RESPONSE_EMPTY = 100
|
const val ERROR_RESPONSE_EMPTY = 100
|
||||||
const val ERROR_LOGIN_DATA_MISSING = 101
|
const val ERROR_LOGIN_DATA_MISSING = 101
|
||||||
|
const val ERROR_LOGIN_DATA_INVALID = 102
|
||||||
const val ERROR_PROFILE_MISSING = 105
|
const val ERROR_PROFILE_MISSING = 105
|
||||||
const val ERROR_INVALID_LOGIN_MODE = 110
|
const val ERROR_INVALID_LOGIN_MODE = 110
|
||||||
const val ERROR_LOGIN_METHOD_NOT_SATISFIED = 111
|
const val ERROR_LOGIN_METHOD_NOT_SATISFIED = 111
|
||||||
|
@ -101,13 +99,6 @@ const val ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_INVALID = 172
|
||||||
const val ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_REVOKED = 173
|
const val ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_REVOKED = 173
|
||||||
const val ERROR_LIBRUS_SYNERGIA_OTHER = 174
|
const val ERROR_LIBRUS_SYNERGIA_OTHER = 174
|
||||||
const val ERROR_LIBRUS_SYNERGIA_MAINTENANCE = 175
|
const val ERROR_LIBRUS_SYNERGIA_MAINTENANCE = 175
|
||||||
const val ERROR_LIBRUS_MESSAGES_MAINTENANCE = 176
|
|
||||||
const val ERROR_LIBRUS_MESSAGES_ERROR = 177
|
|
||||||
const val ERROR_LIBRUS_MESSAGES_OTHER = 178
|
|
||||||
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_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN = 201
|
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN = 201
|
||||||
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD = 202
|
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD = 202
|
||||||
|
|
|
@ -37,16 +37,6 @@ object Regexes {
|
||||||
"""events: (.+),$""".toRegex(RegexOption.MULTILINE)
|
"""events: (.+),$""".toRegex(RegexOption.MULTILINE)
|
||||||
}
|
}
|
||||||
|
|
||||||
val MOBIDZIENNIK_MESSAGE_READ_DATE by lazy {
|
|
||||||
"""czas przeczytania:.+?,\s([0-9]+)\s(.+?)\s([0-9]{4}),\sgodzina\s([0-9:]+)""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
val MOBIDZIENNIK_MESSAGE_SENT_READ_DATE by lazy {
|
|
||||||
""".+?,\s([0-9]+)\s(.+?)\s([0-9]{4}),\sgodzina\s([0-9:]+)""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
val MOBIDZIENNIK_MESSAGE_ATTACHMENT by lazy {
|
|
||||||
"""href="https://.+?\.mobidziennik.pl/.+?&(?:amp;)?zalacznik=([0-9]+)"(?:.+?<small.+?\(([0-9.]+)\s(M|K|G|)B\))*""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
val IDZIENNIK_LOGIN_HIDDEN_FIELDS by lazy {
|
val IDZIENNIK_LOGIN_HIDDEN_FIELDS by lazy {
|
||||||
|
@ -71,8 +61,6 @@ object Regexes {
|
||||||
"""<option.*?value="([0-9]+)"\sdata-id-ucznia="([A-z0-9]+?)".*?>(.+?)\s(.+?)\s*\((.+?),\s*(.+?)\)</option>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
"""<option.*?value="([0-9]+)"\sdata-id-ucznia="([A-z0-9]+?)".*?>(.+?)\s(.+?)\s*\((.+?),\s*(.+?)\)</option>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
val VULCAN_SHITFT_ANNOTATION by lazy {
|
val VULCAN_SHITFT_ANNOTATION by lazy {
|
||||||
"""\(przeniesiona (z|na) lekcj[ię] ([0-9]+), (.+)\)""".toRegex()
|
"""\(przeniesiona (z|na) lekcj[ię] ([0-9]+), (.+)\)""".toRegex()
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ const val ENDPOINT_LIBRUS_API_DESCRIPTIVE_GC = 1023
|
||||||
const val ENDPOINT_LIBRUS_API_TEXT_GC = 1024
|
const val ENDPOINT_LIBRUS_API_TEXT_GC = 1024
|
||||||
const val ENDPOINT_LIBRUS_API_DESCRIPTIVE_TEXT_GC = 1025
|
const val ENDPOINT_LIBRUS_API_DESCRIPTIVE_TEXT_GC = 1025
|
||||||
const val ENDPOINT_LIBRUS_API_BEHAVIOUR_GC = 1026
|
const val ENDPOINT_LIBRUS_API_BEHAVIOUR_GC = 1026
|
||||||
const val ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS = 1030
|
|
||||||
const val ENDPOINT_LIBRUS_API_NORMAL_GRADES = 1031
|
const val ENDPOINT_LIBRUS_API_NORMAL_GRADES = 1031
|
||||||
const val ENDPOINT_LIBRUS_API_POINT_GRADES = 1032
|
const val ENDPOINT_LIBRUS_API_POINT_GRADES = 1032
|
||||||
const val ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES = 1033
|
const val ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES = 1033
|
||||||
|
@ -98,7 +97,6 @@ val LibrusFeatures = listOf(
|
||||||
ENDPOINT_LIBRUS_API_TEXT_GC to LOGIN_METHOD_LIBRUS_API,
|
ENDPOINT_LIBRUS_API_TEXT_GC to LOGIN_METHOD_LIBRUS_API,
|
||||||
ENDPOINT_LIBRUS_API_DESCRIPTIVE_TEXT_GC to LOGIN_METHOD_LIBRUS_API,
|
ENDPOINT_LIBRUS_API_DESCRIPTIVE_TEXT_GC to LOGIN_METHOD_LIBRUS_API,
|
||||||
ENDPOINT_LIBRUS_API_BEHAVIOUR_GC to LOGIN_METHOD_LIBRUS_API,
|
ENDPOINT_LIBRUS_API_BEHAVIOUR_GC to LOGIN_METHOD_LIBRUS_API,
|
||||||
ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS to LOGIN_METHOD_LIBRUS_API,
|
|
||||||
ENDPOINT_LIBRUS_API_NORMAL_GRADES to LOGIN_METHOD_LIBRUS_API,
|
ENDPOINT_LIBRUS_API_NORMAL_GRADES to LOGIN_METHOD_LIBRUS_API,
|
||||||
ENDPOINT_LIBRUS_API_POINT_GRADES to LOGIN_METHOD_LIBRUS_API,
|
ENDPOINT_LIBRUS_API_POINT_GRADES to LOGIN_METHOD_LIBRUS_API,
|
||||||
ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES to LOGIN_METHOD_LIBRUS_API,
|
ENDPOINT_LIBRUS_API_DESCRIPTIVE_GRADES to LOGIN_METHOD_LIBRUS_API,
|
||||||
|
|
|
@ -32,13 +32,6 @@ open class LibrusApi(open val data: DataLibrus) {
|
||||||
|
|
||||||
val callback = object : JsonCallbackHandler() {
|
val callback = object : JsonCallbackHandler() {
|
||||||
override fun onSuccess(json: JsonObject?, response: Response?) {
|
override fun onSuccess(json: JsonObject?, response: Response?) {
|
||||||
if (response?.code() == HTTP_UNAVAILABLE) {
|
|
||||||
data.error(ApiError(tag, ERROR_LIBRUS_API_MAINTENANCE)
|
|
||||||
.withApiResponse(json)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json == null && response?.parserErrorBody == null) {
|
if (json == null && response?.parserErrorBody == null) {
|
||||||
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
||||||
.withResponse(response))
|
.withResponse(response))
|
||||||
|
@ -111,7 +104,6 @@ open class LibrusApi(open val data: DataLibrus) {
|
||||||
.allowErrorCode(HTTP_BAD_REQUEST)
|
.allowErrorCode(HTTP_BAD_REQUEST)
|
||||||
.allowErrorCode(HTTP_FORBIDDEN)
|
.allowErrorCode(HTTP_FORBIDDEN)
|
||||||
.allowErrorCode(HTTP_UNAUTHORIZED)
|
.allowErrorCode(HTTP_UNAUTHORIZED)
|
||||||
.allowErrorCode(HTTP_UNAVAILABLE)
|
|
||||||
.callback(callback)
|
.callback(callback)
|
||||||
.build()
|
.build()
|
||||||
.enqueue()
|
.enqueue()
|
||||||
|
|
|
@ -85,10 +85,6 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_grades)
|
data.startProgress(R.string.edziennik_progress_endpoint_grades)
|
||||||
LibrusApiGrades(data, onSuccess)
|
LibrusApiGrades(data, onSuccess)
|
||||||
}
|
}
|
||||||
ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS -> {
|
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_grade_comments)
|
|
||||||
LibrusApiGradeComments(data, onSuccess)
|
|
||||||
}
|
|
||||||
ENDPOINT_LIBRUS_API_NORMAL_GC -> {
|
ENDPOINT_LIBRUS_API_NORMAL_GC -> {
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_grade_categories)
|
data.startProgress(R.string.edziennik_progress_endpoint_grade_categories)
|
||||||
LibrusApiGradeCategories(data, onSuccess)
|
LibrusApiGradeCategories(data, onSuccess)
|
||||||
|
|
|
@ -15,6 +15,7 @@ import org.jsoup.parser.Parser
|
||||||
import pl.szczodrzynski.edziennik.api.v2.*
|
import pl.szczodrzynski.edziennik.api.v2.*
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
|
import pl.szczodrzynski.edziennik.get
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
import java.io.StringWriter
|
import java.io.StringWriter
|
||||||
import javax.xml.parsers.DocumentBuilderFactory
|
import javax.xml.parsers.DocumentBuilderFactory
|
||||||
|
@ -42,19 +43,19 @@ open class LibrusMessages(open val data: DataLibrus) {
|
||||||
val callback = object : TextCallbackHandler() {
|
val callback = object : TextCallbackHandler() {
|
||||||
override fun onSuccess(text: String?, response: Response?) {
|
override fun onSuccess(text: String?, response: Response?) {
|
||||||
if (text.isNullOrEmpty()) {
|
if (text.isNullOrEmpty()) {
|
||||||
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
data.error(ApiError(LibrusSynergia.TAG, ERROR_RESPONSE_EMPTY)
|
||||||
.withResponse(response))
|
.withResponse(response))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
when {
|
// TODO: Finish error handling
|
||||||
text.contains("<message>Niepoprawny login i/lub hasło.</message>") -> data.error(TAG, ERROR_LOGIN_LIBRUS_MESSAGES_INVALID_LOGIN, response, text)
|
|
||||||
text.contains("stop.png") -> data.error(TAG, ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED, response, text)
|
if ("error" in text) {
|
||||||
text.contains("eAccessDeny") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
|
when ("<type>(.*)</type>".toRegex().find(text)?.get(1)) {
|
||||||
text.contains("OffLine") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_MAINTENANCE, response, text)
|
"eAccessDeny" -> data.error(ApiError(tag, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED)
|
||||||
text.contains("<status>error</status>") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ERROR, response, text)
|
.withResponse(response)
|
||||||
text.contains("<type>eVarWhitThisNameNotExists</type>") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
|
.withApiResponse(text))
|
||||||
text.contains("<error>") -> data.error(TAG, ERROR_LIBRUS_MESSAGES_OTHER, response, text)
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -14,7 +14,7 @@ import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
|
||||||
open class LibrusSynergia(open val data: DataLibrus) {
|
open class LibrusSynergia(open val data: DataLibrus) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "LibrusSynergia"
|
const val TAG = "LibrusSynergia"
|
||||||
}
|
}
|
||||||
|
|
||||||
val profileId
|
val profileId
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) Kacper Ziubryniewicz 2019-11-20
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.api.v2.librus.data.api
|
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusApi
|
|
||||||
import pl.szczodrzynski.edziennik.asJsonObjectList
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory
|
|
||||||
import pl.szczodrzynski.edziennik.getJsonArray
|
|
||||||
import pl.szczodrzynski.edziennik.getLong
|
|
||||||
import pl.szczodrzynski.edziennik.getString
|
|
||||||
|
|
||||||
class LibrusApiGradeComments(override val data: DataLibrus,
|
|
||||||
val onSuccess: () -> Unit) : LibrusApi(data) {
|
|
||||||
companion object {
|
|
||||||
const val TAG = "LibrusApiGradeComments"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
apiGet(TAG, "Grades/Comments") { json ->
|
|
||||||
|
|
||||||
json.getJsonArray("Comments")?.asJsonObjectList()?.forEach { comment ->
|
|
||||||
val id = comment.getLong("Id") ?: return@forEach
|
|
||||||
val text = comment.getString("Text")
|
|
||||||
|
|
||||||
val gradeCategoryObject = GradeCategory(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
-1f,
|
|
||||||
-1,
|
|
||||||
text
|
|
||||||
).apply {
|
|
||||||
type = GradeCategory.TYPE_COMMENT
|
|
||||||
}
|
|
||||||
|
|
||||||
data.gradeCategories.put(id, gradeCategoryObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_LIBRUS_API_NORMAL_GRADE_COMMENTS, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,7 +6,6 @@ import pl.szczodrzynski.edziennik.api.v2.librus.ENDPOINT_LIBRUS_API_NORMAL_GRADE
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusApi
|
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusApi
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade
|
import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeCategory
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
@ -43,21 +42,12 @@ class LibrusApiGrades(override val data: DataLibrus,
|
||||||
weight = 0f
|
weight = 0f
|
||||||
}
|
}
|
||||||
|
|
||||||
val description = grade.getJsonArray("Comments")?.asJsonObjectList()?.let { comments ->
|
|
||||||
if (comments.isNotEmpty()) {
|
|
||||||
data.gradeCategories.singleOrNull {
|
|
||||||
it.type == GradeCategory.TYPE_COMMENT
|
|
||||||
&& it.categoryId == comments[0].asJsonObject.getLong("Id")
|
|
||||||
}?.text
|
|
||||||
} else null
|
|
||||||
} ?: ""
|
|
||||||
|
|
||||||
val gradeObject = Grade(
|
val gradeObject = Grade(
|
||||||
profileId,
|
profileId,
|
||||||
id,
|
id,
|
||||||
categoryName,
|
categoryName,
|
||||||
color,
|
color,
|
||||||
description,
|
"",
|
||||||
name,
|
name,
|
||||||
value,
|
value,
|
||||||
weight,
|
weight,
|
||||||
|
|
|
@ -16,7 +16,8 @@ import pl.szczodrzynski.edziennik.getInt
|
||||||
import pl.szczodrzynski.edziennik.getString
|
import pl.szczodrzynski.edziennik.getString
|
||||||
import pl.szczodrzynski.edziennik.getUnixDate
|
import pl.szczodrzynski.edziennik.getUnixDate
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
import java.net.HttpURLConnection.*
|
import java.net.HttpURLConnection.HTTP_BAD_REQUEST
|
||||||
|
import java.net.HttpURLConnection.HTTP_UNAUTHORIZED
|
||||||
|
|
||||||
class LibrusLoginApi {
|
class LibrusLoginApi {
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -116,13 +117,6 @@ class LibrusLoginApi {
|
||||||
|
|
||||||
private val tokenCallback = object : JsonCallbackHandler() {
|
private val tokenCallback = object : JsonCallbackHandler() {
|
||||||
override fun onSuccess(json: JsonObject?, response: Response?) {
|
override fun onSuccess(json: JsonObject?, response: Response?) {
|
||||||
if (response?.code() == HTTP_UNAVAILABLE) {
|
|
||||||
data.error(ApiError(TAG, ERROR_LIBRUS_API_MAINTENANCE)
|
|
||||||
.withApiResponse(json)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json == null) {
|
if (json == null) {
|
||||||
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
||||||
.withResponse(response))
|
.withResponse(response))
|
||||||
|
@ -182,7 +176,6 @@ class LibrusLoginApi {
|
||||||
.post()
|
.post()
|
||||||
.allowErrorCode(HTTP_BAD_REQUEST)
|
.allowErrorCode(HTTP_BAD_REQUEST)
|
||||||
.allowErrorCode(HTTP_UNAUTHORIZED)
|
.allowErrorCode(HTTP_UNAUTHORIZED)
|
||||||
.allowErrorCode(HTTP_UNAVAILABLE)
|
|
||||||
.callback(tokenCallback)
|
.callback(tokenCallback)
|
||||||
.build()
|
.build()
|
||||||
.enqueue()
|
.enqueue()
|
||||||
|
|
|
@ -6,57 +6,20 @@ package pl.szczodrzynski.edziennik.api.v2.librus.login
|
||||||
|
|
||||||
import im.wangchao.mhttp.Request
|
import im.wangchao.mhttp.Request
|
||||||
import im.wangchao.mhttp.Response
|
import im.wangchao.mhttp.Response
|
||||||
import im.wangchao.mhttp.body.MediaTypeUtils
|
|
||||||
import im.wangchao.mhttp.callback.TextCallbackHandler
|
import im.wangchao.mhttp.callback.TextCallbackHandler
|
||||||
import okhttp3.Cookie
|
import okhttp3.Cookie
|
||||||
import pl.szczodrzynski.edziennik.api.v2.*
|
import pl.szczodrzynski.edziennik.api.v2.*
|
||||||
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.getUnixDate
|
import pl.szczodrzynski.edziennik.getUnixDate
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
import java.io.StringWriter
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory
|
|
||||||
import javax.xml.transform.OutputKeys
|
|
||||||
import javax.xml.transform.TransformerFactory
|
|
||||||
import javax.xml.transform.dom.DOMSource
|
|
||||||
import javax.xml.transform.stream.StreamResult
|
|
||||||
|
|
||||||
class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
|
class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "LoginLibrusMessages"
|
private const val TAG = "LoginLibrusMessages"
|
||||||
}
|
}
|
||||||
|
|
||||||
private val callback by lazy { object : TextCallbackHandler() {
|
|
||||||
override fun onSuccess(text: String?, response: Response?) {
|
|
||||||
val location = response?.headers()?.get("Location")
|
|
||||||
when {
|
|
||||||
location?.contains("MultiDomainLogon") == true -> loginWithSynergia(location)
|
|
||||||
location?.contains("AutoLogon") == true -> {
|
|
||||||
saveSessionId(response, text)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
|
|
||||||
text?.contains("<status>ok</status>") == true -> {
|
|
||||||
saveSessionId(response, text)
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
text?.contains("<message>Niepoprawny login i/lub hasło.</message>") == true -> data.error(TAG, ERROR_LOGIN_LIBRUS_MESSAGES_INVALID_LOGIN, response, text)
|
|
||||||
text?.contains("stop.png") == true -> data.error(TAG, ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED, response, text)
|
|
||||||
text?.contains("eAccessDeny") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
|
|
||||||
text?.contains("OffLine") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_MAINTENANCE, response, text)
|
|
||||||
text?.contains("<status>error</status>") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ERROR, response, text)
|
|
||||||
text?.contains("<type>eVarWhitThisNameNotExists</type>") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
|
|
||||||
text?.contains("<error>") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_OTHER, response, text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(response: Response?, throwable: Throwable?) {
|
|
||||||
data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
|
|
||||||
.withResponse(response)
|
|
||||||
.withThrowable(throwable))
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
|
|
||||||
init { run {
|
init { run {
|
||||||
if (data.profile == null) {
|
if (data.profile == null) {
|
||||||
data.error(ApiError(TAG, ERROR_PROFILE_MISSING))
|
data.error(ApiError(TAG, ERROR_PROFILE_MISSING))
|
||||||
|
@ -78,7 +41,7 @@ class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
|
||||||
if (data.loginMethods.contains(LOGIN_METHOD_LIBRUS_SYNERGIA)) {
|
if (data.loginMethods.contains(LOGIN_METHOD_LIBRUS_SYNERGIA)) {
|
||||||
loginWithSynergia()
|
loginWithSynergia()
|
||||||
}
|
}
|
||||||
else if (data.apiLogin != null && data.apiPassword != null) {
|
else if (data.apiLogin != null && data.apiPassword != null && false) {
|
||||||
loginWithCredentials()
|
loginWithCredentials()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -91,44 +54,7 @@ class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
|
||||||
* XML (Flash messages website) login method. Uses a Synergia login and password.
|
* XML (Flash messages website) login method. Uses a Synergia login and password.
|
||||||
*/
|
*/
|
||||||
private fun loginWithCredentials() {
|
private fun loginWithCredentials() {
|
||||||
d(TAG, "Request: Librus/Login/Messages - $LIBRUS_MESSAGES_URL/Login")
|
|
||||||
|
|
||||||
val docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
|
|
||||||
val doc = docBuilder.newDocument()
|
|
||||||
val serviceElement = doc.createElement("service")
|
|
||||||
val headerElement = doc.createElement("header")
|
|
||||||
val dataElement = doc.createElement("data")
|
|
||||||
val loginElement = doc.createElement("login")
|
|
||||||
loginElement.appendChild(doc.createTextNode(data.apiLogin))
|
|
||||||
dataElement.appendChild(loginElement)
|
|
||||||
val passwordElement = doc.createElement("login")
|
|
||||||
passwordElement.appendChild(doc.createTextNode(data.apiPassword))
|
|
||||||
dataElement.appendChild(passwordElement)
|
|
||||||
val keyStrokeElement = doc.createElement("KeyStroke")
|
|
||||||
val keysElement = doc.createElement("Keys")
|
|
||||||
val upElement = doc.createElement("Up")
|
|
||||||
keysElement.appendChild(upElement)
|
|
||||||
val downElement = doc.createElement("Down")
|
|
||||||
keysElement.appendChild(downElement)
|
|
||||||
keyStrokeElement.appendChild(keysElement)
|
|
||||||
dataElement.appendChild(keyStrokeElement)
|
|
||||||
serviceElement.appendChild(headerElement)
|
|
||||||
serviceElement.appendChild(dataElement)
|
|
||||||
doc.appendChild(serviceElement)
|
|
||||||
val transformer = TransformerFactory.newInstance().newTransformer()
|
|
||||||
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes")
|
|
||||||
val stringWriter = StringWriter()
|
|
||||||
transformer.transform(DOMSource(doc), StreamResult(stringWriter))
|
|
||||||
val requestXml = stringWriter.toString()
|
|
||||||
|
|
||||||
Request.builder()
|
|
||||||
.url("$LIBRUS_MESSAGES_URL/Login")
|
|
||||||
.userAgent(SYNERGIA_USER_AGENT)
|
|
||||||
.setTextBody(requestXml, MediaTypeUtils.APPLICATION_XML)
|
|
||||||
.post()
|
|
||||||
.callback(callback)
|
|
||||||
.build()
|
|
||||||
.enqueue()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -137,6 +63,37 @@ class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
|
||||||
private fun loginWithSynergia(url: String = "https://synergia.librus.pl/wiadomosci2") {
|
private fun loginWithSynergia(url: String = "https://synergia.librus.pl/wiadomosci2") {
|
||||||
d(TAG, "Request: Librus/Login/Messages - $url")
|
d(TAG, "Request: Librus/Login/Messages - $url")
|
||||||
|
|
||||||
|
val callback = object : TextCallbackHandler() {
|
||||||
|
override fun onSuccess(text: String?, response: Response?) {
|
||||||
|
val location = response?.headers()?.get("Location")
|
||||||
|
when {
|
||||||
|
location?.contains("MultiDomainLogon") == true -> loginWithSynergia(location)
|
||||||
|
location?.contains("AutoLogon") == true -> {
|
||||||
|
var sessionId = data.app.cookieJar.getCookie("wiadomosci.librus.pl", "DZIENNIKSID")
|
||||||
|
sessionId = sessionId?.replace("-MAINT", "")
|
||||||
|
if (sessionId == null) {
|
||||||
|
data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_MESSAGES_NO_SESSION_ID)
|
||||||
|
.withResponse(response)
|
||||||
|
.withApiResponse(text))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data.messagesSessionId = sessionId
|
||||||
|
data.messagesSessionIdExpiryTime = response.getUnixDate() + 45 * 60 /* 45min */
|
||||||
|
onSuccess()
|
||||||
|
}
|
||||||
|
|
||||||
|
text?.contains("eAccessDeny") == true -> data.error(TAG, ERROR_LIBRUS_MESSAGES_ACCESS_DENIED, response, text)
|
||||||
|
text?.contains("stop.png") == true -> data.error(TAG, ERROR_LIBRUS_SYNERGIA_ACCESS_DENIED, response, text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(response: Response?, throwable: Throwable?) {
|
||||||
|
data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
|
||||||
|
.withResponse(response)
|
||||||
|
.withThrowable(throwable))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Request.builder()
|
Request.builder()
|
||||||
.url(url)
|
.url(url)
|
||||||
.userAgent(SYNERGIA_USER_AGENT)
|
.userAgent(SYNERGIA_USER_AGENT)
|
||||||
|
@ -146,17 +103,4 @@ class LibrusLoginMessages(val data: DataLibrus, val onSuccess: () -> Unit) {
|
||||||
.build()
|
.build()
|
||||||
.enqueue()
|
.enqueue()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveSessionId(response: Response?, text: String?) {
|
|
||||||
var sessionId = data.app.cookieJar.getCookie("wiadomosci.librus.pl", "DZIENNIKSID")
|
|
||||||
sessionId = sessionId?.replace("-MAINT", "") // dunno what's this
|
|
||||||
if (sessionId == null) {
|
|
||||||
data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_MESSAGES_NO_SESSION_ID)
|
|
||||||
.withResponse(response)
|
|
||||||
.withApiResponse(text))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
data.messagesSessionId = sessionId
|
|
||||||
data.messagesSessionIdExpiryTime = response.getUnixDate() + 45 * 60 /* 45min */
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -99,14 +99,6 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
|
||||||
.post()
|
.post()
|
||||||
.callback(object : JsonCallbackHandler() {
|
.callback(object : JsonCallbackHandler() {
|
||||||
override fun onSuccess(json: JsonObject?, response: Response) {
|
override fun onSuccess(json: JsonObject?, response: Response) {
|
||||||
val location = response.headers()?.get("Location")
|
|
||||||
if (location == "http://localhost/bar?command=close") {
|
|
||||||
data.error(ApiError(TAG, ERROR_LIBRUS_PORTAL_MAINTENANCE)
|
|
||||||
.withApiResponse(json)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json == null) {
|
if (json == null) {
|
||||||
if (response.parserErrorBody?.contains("wciąż nieaktywne") == true) {
|
if (response.parserErrorBody?.contains("wciąż nieaktywne") == true) {
|
||||||
data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED)
|
data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED)
|
||||||
|
@ -128,7 +120,7 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
|
||||||
|
|
||||||
override fun onFailure(response: Response, throwable: Throwable) {
|
override fun onFailure(response: Response, throwable: Throwable) {
|
||||||
if (response.code() == 403 || response.code() == 401) {
|
if (response.code() == 403 || response.code() == 401) {
|
||||||
data.error(ApiError(TAG, ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN)
|
data.error(ApiError(TAG, ERROR_LOGIN_DATA_INVALID)
|
||||||
.withResponse(response)
|
.withResponse(response)
|
||||||
.withThrowable(throwable))
|
.withThrowable(throwable))
|
||||||
return
|
return
|
||||||
|
|
|
@ -7,6 +7,7 @@ package pl.szczodrzynski.edziennik.api.v2.librus.login
|
||||||
import com.google.gson.JsonObject
|
import com.google.gson.JsonObject
|
||||||
import im.wangchao.mhttp.Request
|
import im.wangchao.mhttp.Request
|
||||||
import im.wangchao.mhttp.Response
|
import im.wangchao.mhttp.Response
|
||||||
|
import im.wangchao.mhttp.callback.JsonCallbackHandler
|
||||||
import im.wangchao.mhttp.callback.TextCallbackHandler
|
import im.wangchao.mhttp.callback.TextCallbackHandler
|
||||||
import okhttp3.Cookie
|
import okhttp3.Cookie
|
||||||
import pl.szczodrzynski.edziennik.api.v2.*
|
import pl.szczodrzynski.edziennik.api.v2.*
|
||||||
|
@ -15,6 +16,7 @@ import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusApi
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.getString
|
import pl.szczodrzynski.edziennik.getString
|
||||||
import pl.szczodrzynski.edziennik.getUnixDate
|
import pl.szczodrzynski.edziennik.getUnixDate
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
import java.net.HttpURLConnection
|
import java.net.HttpURLConnection
|
||||||
|
|
||||||
|
@ -84,13 +86,6 @@ class LibrusLoginSynergia(override val data: DataLibrus, val onSuccess: () -> Un
|
||||||
val callback = object : TextCallbackHandler() {
|
val callback = object : TextCallbackHandler() {
|
||||||
override fun onSuccess(json: String?, response: Response?) {
|
override fun onSuccess(json: String?, response: Response?) {
|
||||||
val location = response?.headers()?.get("Location")
|
val location = response?.headers()?.get("Location")
|
||||||
if (location?.endsWith("przerwa_techniczna") == true) {
|
|
||||||
data.error(ApiError(TAG, ERROR_LIBRUS_SYNERGIA_MAINTENANCE)
|
|
||||||
.withApiResponse(json)
|
|
||||||
.withResponse(response))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (location?.endsWith("centrum_powiadomien") == true) {
|
if (location?.endsWith("centrum_powiadomien") == true) {
|
||||||
val sessionId = data.app.cookieJar.getCookie("synergia.librus.pl", "DZIENNIKSID")
|
val sessionId = data.app.cookieJar.getCookie("synergia.librus.pl", "DZIENNIKSID")
|
||||||
if (sessionId == null) {
|
if (sessionId == null) {
|
||||||
|
|
|
@ -10,10 +10,8 @@ import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
|
||||||
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
|
||||||
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikInterface
|
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikInterface
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.MobidziennikData
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.MobidziennikData
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web.MobidziennikWebGetMessage
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.firstlogin.MobidziennikFirstLogin
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.firstlogin.MobidziennikFirstLogin
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.login.MobidziennikLogin
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.login.MobidziennikLogin
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.login.MobidziennikLoginWeb
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennikLoginMethods
|
import pl.szczodrzynski.edziennik.api.v2.mobidziennikLoginMethods
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
|
||||||
import pl.szczodrzynski.edziennik.api.v2.prepare
|
import pl.szczodrzynski.edziennik.api.v2.prepare
|
||||||
|
@ -65,11 +63,7 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMessage(message: MessageFull) {
|
override fun getMessage(message: MessageFull) {
|
||||||
MobidziennikLoginWeb(data) {
|
|
||||||
MobidziennikWebGetMessage(data, message) {
|
|
||||||
completed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun markAllAnnouncementsAsRead() {
|
override fun markAllAnnouncementsAsRead() {
|
||||||
|
|
|
@ -1,157 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-11-18.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web
|
|
||||||
|
|
||||||
import org.greenrobot.eventbus.EventBus
|
|
||||||
import org.jsoup.Jsoup
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.Regexes
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.events.MessageGetEvent
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
|
|
||||||
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.MobidziennikWeb
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message.TYPE_RECEIVED
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipientFull
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.get
|
|
||||||
import pl.szczodrzynski.edziennik.singleOrNull
|
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.monthFromName
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
|
||||||
|
|
||||||
class MobidziennikWebGetMessage(
|
|
||||||
override val data: DataMobidziennik,
|
|
||||||
private val message: MessageFull,
|
|
||||||
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "MobidziennikWebGetMessage"
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
|
||||||
val typeUrl = if (message.type == Message.TYPE_SENT)
|
|
||||||
"wiadwyslana"
|
|
||||||
else
|
|
||||||
"wiadodebrana"
|
|
||||||
webGet(TAG, "/dziennik/$typeUrl/?id=${message.id}") { text ->
|
|
||||||
MobidziennikLuckyNumberExtractor(data, text)
|
|
||||||
|
|
||||||
val messageRecipientList = mutableListOf<MessageRecipientFull>()
|
|
||||||
|
|
||||||
val doc = Jsoup.parse(text)
|
|
||||||
|
|
||||||
val content = doc.select("#content").first()
|
|
||||||
|
|
||||||
val body = content.select(".wiadomosc_tresc").first()
|
|
||||||
|
|
||||||
if (message.type == TYPE_RECEIVED) {
|
|
||||||
var readDate = System.currentTimeMillis()
|
|
||||||
Regexes.MOBIDZIENNIK_MESSAGE_READ_DATE.find(body.html())?.let {
|
|
||||||
val date = Date(
|
|
||||||
it[3].toIntOrNull() ?: 2019,
|
|
||||||
monthFromName(it[2]),
|
|
||||||
it[1].toIntOrNull() ?: 1
|
|
||||||
)
|
|
||||||
val time = Time.fromH_m_s(
|
|
||||||
it[4] // TODO blank string safety
|
|
||||||
)
|
|
||||||
readDate = date.combineWith(time)
|
|
||||||
}
|
|
||||||
|
|
||||||
val recipient = MessageRecipientFull(
|
|
||||||
profileId,
|
|
||||||
-1,
|
|
||||||
-1,
|
|
||||||
readDate,
|
|
||||||
message.id
|
|
||||||
)
|
|
||||||
|
|
||||||
recipient.fullName = profile?.accountNameLong ?: profile?.studentNameLong
|
|
||||||
|
|
||||||
messageRecipientList.add(recipient)
|
|
||||||
} else {
|
|
||||||
message.senderId = -1
|
|
||||||
message.senderReplyId = -1
|
|
||||||
|
|
||||||
content.select("table.spis tr:has(td)")?.forEach { recipientEl ->
|
|
||||||
val senderEl = recipientEl.select("td:eq(0)").first()
|
|
||||||
val senderName = senderEl.text()
|
|
||||||
|
|
||||||
val teacher = data.teacherList.singleOrNull { it.fullNameLastFirst == senderName }
|
|
||||||
val receiverId = teacher?.id ?: -1
|
|
||||||
|
|
||||||
var readDate = 0L
|
|
||||||
val isReadEl = recipientEl.select("td:eq(2)").first()
|
|
||||||
if (isReadEl.ownText() != "NIE") {
|
|
||||||
val readDateEl = recipientEl.select("td:eq(3) small").first()
|
|
||||||
Regexes.MOBIDZIENNIK_MESSAGE_SENT_READ_DATE.find(readDateEl.ownText())?.let {
|
|
||||||
val date = Date(
|
|
||||||
it[3].toIntOrNull() ?: 2019,
|
|
||||||
monthFromName(it[2]),
|
|
||||||
it[1].toIntOrNull() ?: 1
|
|
||||||
)
|
|
||||||
val time = Time.fromH_m_s(
|
|
||||||
it[4] // TODO blank string safety
|
|
||||||
)
|
|
||||||
readDate = date.combineWith(time)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val recipient = MessageRecipientFull(
|
|
||||||
profileId,
|
|
||||||
receiverId,
|
|
||||||
-1,
|
|
||||||
readDate,
|
|
||||||
message.id
|
|
||||||
)
|
|
||||||
|
|
||||||
recipient.fullName = teacher?.fullName ?: "?"
|
|
||||||
|
|
||||||
messageRecipientList.add(recipient)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// this line removes the sender and read date details
|
|
||||||
body.select("div").remove()
|
|
||||||
|
|
||||||
// this needs to be at the end
|
|
||||||
message.apply {
|
|
||||||
this.body = body.html()
|
|
||||||
|
|
||||||
clearAttachments()
|
|
||||||
content.select("ul li").map { it.select("a").first() }.forEach {
|
|
||||||
val attachmentName = it.ownText()
|
|
||||||
Regexes.MOBIDZIENNIK_MESSAGE_ATTACHMENT.find(it.outerHtml())?.let { match ->
|
|
||||||
val attachmentId = match[1].toLong()
|
|
||||||
var size = match[2].toFloatOrNull() ?: 0f
|
|
||||||
when (match[3]) {
|
|
||||||
"K" -> size *= 1024f
|
|
||||||
"M" -> size *= 1024f * 1024f
|
|
||||||
"G" -> size *= 1024f * 1024f * 1024f
|
|
||||||
}
|
|
||||||
message.addAttachment(attachmentId, attachmentName, size.toLong())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!message.seen) { // TODO discover why this monstrosity instead of MetadataDao.setSeen
|
|
||||||
data.messageMetadataList.add(Metadata(
|
|
||||||
message.profileId,
|
|
||||||
Metadata.TYPE_MESSAGE,
|
|
||||||
message.id,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
message.addedDate
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
message.recipients = messageRecipientList
|
|
||||||
data.messageRecipientList.addAll(messageRecipientList)
|
|
||||||
data.messageList.add(message)
|
|
||||||
|
|
||||||
EventBus.getDefault().postSticky(MessageGetEvent(message))
|
|
||||||
onSuccess()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,14 +7,15 @@ package pl.szczodrzynski.edziennik.api.v2.vulcan
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.api.v2.LOGIN_METHOD_VULCAN_API
|
import pl.szczodrzynski.edziennik.api.v2.LOGIN_METHOD_VULCAN_API
|
||||||
import pl.szczodrzynski.edziennik.api.v2.models.Data
|
import pl.szczodrzynski.edziennik.api.v2.models.Data
|
||||||
|
import pl.szczodrzynski.edziennik.currentTimeUnix
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||||
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
|
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
|
||||||
|
|
||||||
class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) {
|
class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) {
|
||||||
|
|
||||||
fun isApiLoginValid() = /*apiCertificateExpiryTime-30 > currentTimeUnix()
|
fun isApiLoginValid() = apiCertificateExpiryTime-30 > currentTimeUnix()
|
||||||
&&*/ apiCertificateKey.isNotNullNorEmpty()
|
&& apiCertificateKey.isNotNullNorEmpty()
|
||||||
&& apiCertificatePrivate.isNotNullNorEmpty()
|
&& apiCertificatePrivate.isNotNullNorEmpty()
|
||||||
&& symbol.isNotNullNorEmpty()
|
&& symbol.isNotNullNorEmpty()
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.api.v2.vulcan.data.api
|
package pl.szczodrzynski.edziennik.api.v2.vulcan.data.api
|
||||||
|
|
||||||
import androidx.core.util.set
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
import pl.szczodrzynski.edziennik.*
|
||||||
import pl.szczodrzynski.edziennik.api.v2.Regexes
|
import pl.szczodrzynski.edziennik.api.v2.Regexes
|
||||||
import pl.szczodrzynski.edziennik.api.v2.VULCAN_API_ENDPOINT_TIMETABLE
|
import pl.szczodrzynski.edziennik.api.v2.VULCAN_API_ENDPOINT_TIMETABLE
|
||||||
|
@ -15,7 +14,6 @@ import pl.szczodrzynski.edziennik.api.v2.vulcan.data.VulcanApi
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.subjects.Subject
|
import pl.szczodrzynski.edziennik.data.db.modules.subjects.Subject
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.crc16
|
import pl.szczodrzynski.edziennik.utils.Utils.crc16
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
@ -26,180 +24,163 @@ class VulcanApiTimetable(override val data: DataVulcan, val onSuccess: () -> Uni
|
||||||
const val TAG = "VulcanApiTimetable"
|
const val TAG = "VulcanApiTimetable"
|
||||||
}
|
}
|
||||||
|
|
||||||
init { data.profile?.also { profile ->
|
init {
|
||||||
val currentWeekStart = Date.getToday().let { it.stepForward(0, 0, -it.weekDay) }
|
data.profile?.also { profile ->
|
||||||
val getDate = data.arguments?.getString("weekStart") ?: currentWeekStart.stringY_m_d
|
val currentWeekStart = Date.getToday().let { it.stepForward(0, 0, -it.weekDay) }
|
||||||
|
val getDate = data.arguments?.getString("weekStart") ?: currentWeekStart.stringY_m_d
|
||||||
|
|
||||||
val weekStart = Date.fromY_m_d(getDate)
|
val weekStart = Date.fromY_m_d(getDate)
|
||||||
val weekEnd = weekStart.clone().stepForward(0, 0, 6)
|
val weekEnd = weekStart.clone().stepForward(0, 0, 6)
|
||||||
|
|
||||||
apiGet(TAG, VULCAN_API_ENDPOINT_TIMETABLE, parameters = mapOf(
|
apiGet(TAG, VULCAN_API_ENDPOINT_TIMETABLE, parameters = mapOf(
|
||||||
"DataPoczatkowa" to weekStart.stringY_m_d,
|
"DataPoczatkowa" to weekStart.stringY_m_d,
|
||||||
"DataKoncowa" to weekEnd.stringY_m_d,
|
"DataKoncowa" to weekEnd.stringY_m_d,
|
||||||
"IdUczen" to data.studentId,
|
"IdUczen" to data.studentId,
|
||||||
"IdOddzial" to data.studentClassId,
|
"IdOddzial" to data.studentClassId,
|
||||||
"IdOkresKlasyfikacyjny" to data.studentSemesterId
|
"IdOkresKlasyfikacyjny" to data.studentSemesterId
|
||||||
)) { json, _ ->
|
)) { json, _ ->
|
||||||
val dates: MutableSet<Int> = mutableSetOf()
|
val dates: MutableSet<Int> = mutableSetOf()
|
||||||
val lessons: MutableList<Lesson> = mutableListOf()
|
val lessons: MutableList<Lesson> = mutableListOf()
|
||||||
|
|
||||||
json.getJsonArray("Data")?.asJsonObjectList()?.forEach { lesson ->
|
json.getJsonArray("Data")?.asJsonObjectList()?.forEach { lesson ->
|
||||||
if (lesson.getBoolean("PlanUcznia") != true)
|
val lessonDate = Date.fromY_m_d(lesson.getString("DzienTekst"))
|
||||||
return@forEach
|
val lessonNumber = lesson.getInt("NumerLekcji")
|
||||||
val lessonDate = Date.fromY_m_d(lesson.getString("DzienTekst"))
|
val lessonRange = data.lessonRanges.singleOrNull { it.lessonNumber == lessonNumber }
|
||||||
val lessonNumber = lesson.getInt("NumerLekcji")
|
val startTime = lessonRange?.startTime
|
||||||
val lessonRange = data.lessonRanges.singleOrNull { it.lessonNumber == lessonNumber }
|
val endTime = lessonRange?.endTime
|
||||||
val startTime = lessonRange?.startTime
|
val teacherId = lesson.getLong("IdPracownik")
|
||||||
val endTime = lessonRange?.endTime
|
val teamId = data.studentClassId.toLong()
|
||||||
val teacherId = lesson.getLong("IdPracownik")
|
val classroom = lesson.getString("Classroom")
|
||||||
val classroom = lesson.getString("Sala")
|
|
||||||
|
|
||||||
val oldTeacherId = lesson.getLong("IdPracownikOld")
|
val oldTeacherId = lesson.getLong("IdPracownikOld")
|
||||||
|
|
||||||
val changeAnnotation = lesson.getString("AdnotacjaOZmianie") ?: ""
|
val changeAnnotation = lesson.getString("AdnotacjaOZmianie") ?: ""
|
||||||
val type = when {
|
val type = when {
|
||||||
changeAnnotation.startsWith("(przeniesiona z") -> Lesson.TYPE_SHIFTED_TARGET
|
changeAnnotation.startsWith("(przeniesiona z") -> Lesson.TYPE_SHIFTED_TARGET
|
||||||
changeAnnotation.startsWith("(przeniesiona na") -> Lesson.TYPE_SHIFTED_SOURCE
|
changeAnnotation.startsWith("(przeniesiona na") -> Lesson.TYPE_SHIFTED_SOURCE
|
||||||
changeAnnotation.startsWith("(zastępstwo") -> Lesson.TYPE_CHANGE
|
changeAnnotation.startsWith("(zastępstwo") -> Lesson.TYPE_CHANGE
|
||||||
lesson.getBoolean("PrzekreslonaNazwa") == true -> Lesson.TYPE_CANCELLED
|
lesson.getBoolean("PrzekreslonaNazwa") == true -> Lesson.TYPE_CANCELLED
|
||||||
else -> Lesson.TYPE_NORMAL
|
else -> Lesson.TYPE_NORMAL
|
||||||
}
|
|
||||||
|
|
||||||
val teamId = lesson.getString("PodzialSkrot")?.let { teamName ->
|
|
||||||
val name = "${data.teamClass?.name} $teamName"
|
|
||||||
val id = name.crc16().toLong()
|
|
||||||
var team = data.teamList.singleOrNull { it.name == name }
|
|
||||||
if (team == null) {
|
|
||||||
team = Team(
|
|
||||||
profileId,
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
Team.TYPE_VIRTUAL,
|
|
||||||
"${data.schoolName}:$name",
|
|
||||||
teacherId ?: oldTeacherId ?: -1
|
|
||||||
)
|
|
||||||
data.teamList[id] = team
|
|
||||||
}
|
}
|
||||||
team.id
|
|
||||||
} ?: data.studentClassId.toLong()
|
|
||||||
|
|
||||||
val subjectId = lesson.getLong("IdPrzedmiot")?.let {
|
val subjectId = lesson.getLong("IdPrzedmiot")?.let {
|
||||||
when (it) {
|
when (it) {
|
||||||
0L -> {
|
0L -> {
|
||||||
val subjectName = lesson.getString("PrzedmiotNazwa") ?: ""
|
val subjectName = lesson.getString("PrzedmiotNazwa") ?: ""
|
||||||
|
|
||||||
data.subjectList.singleOrNull { subject -> subject.longName == subjectName }?.id
|
data.subjectList.singleOrNull { subject -> subject.longName == subjectName }?.id
|
||||||
?: {
|
?: {
|
||||||
/**
|
/**
|
||||||
* CREATE A NEW SUBJECT IF IT DOESN'T EXIST
|
* CREATE A NEW SUBJECT IF IT DOESN'T EXIST
|
||||||
*/
|
*/
|
||||||
|
|
||||||
val subjectObject = Subject(
|
val subjectObject = Subject(
|
||||||
profileId,
|
profileId,
|
||||||
-1 * crc16(subjectName.toByteArray()).toLong(),
|
-1 * crc16(subjectName.toByteArray()).toLong(),
|
||||||
subjectName,
|
subjectName,
|
||||||
subjectName
|
subjectName
|
||||||
)
|
)
|
||||||
data.subjectList.put(subjectObject.id, subjectObject)
|
data.subjectList.put(subjectObject.id, subjectObject)
|
||||||
subjectObject.id
|
subjectObject.id
|
||||||
}.invoke()
|
}.invoke()
|
||||||
}
|
}
|
||||||
else -> it
|
else -> it
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val id = lessonDate.combineWith(startTime) / 6L * 10L + (lesson.hashCode() and 0xFFFF)
|
|
||||||
|
|
||||||
val lessonObject = Lesson(profileId, id).apply {
|
|
||||||
this.type = type
|
|
||||||
|
|
||||||
when (type) {
|
|
||||||
Lesson.TYPE_NORMAL, Lesson.TYPE_CHANGE, Lesson.TYPE_SHIFTED_TARGET -> {
|
|
||||||
this.date = lessonDate
|
|
||||||
this.lessonNumber = lessonNumber
|
|
||||||
this.startTime = startTime
|
|
||||||
this.endTime = endTime
|
|
||||||
this.subjectId = subjectId
|
|
||||||
this.teacherId = teacherId
|
|
||||||
this.teamId = teamId
|
|
||||||
this.classroom = classroom
|
|
||||||
|
|
||||||
this.oldTeacherId = oldTeacherId
|
|
||||||
}
|
|
||||||
|
|
||||||
Lesson.TYPE_CANCELLED, Lesson.TYPE_SHIFTED_SOURCE -> {
|
|
||||||
this.oldDate = lessonDate
|
|
||||||
this.oldLessonNumber = lessonNumber
|
|
||||||
this.oldStartTime = startTime
|
|
||||||
this.oldEndTime = endTime
|
|
||||||
this.oldSubjectId = subjectId
|
|
||||||
this.oldTeacherId = teacherId
|
|
||||||
this.oldTeamId = teamId
|
|
||||||
this.oldClassroom = classroom
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == Lesson.TYPE_SHIFTED_SOURCE || type == Lesson.TYPE_SHIFTED_TARGET) {
|
val id = lessonDate.combineWith(startTime) / 6L * 10L + (lesson.hashCode() and 0xFFFF)
|
||||||
val shift = Regexes.VULCAN_SHITFT_ANNOTATION.find(changeAnnotation)
|
|
||||||
val oldLessonNumber = shift?.get(2)?.toInt()
|
|
||||||
val oldLessonDate = shift?.get(3)?.let { Date.fromd_m_Y(it) }
|
|
||||||
|
|
||||||
val oldLessonRange = data.lessonRanges.singleOrNull { it.lessonNumber == oldLessonNumber }
|
val lessonObject = Lesson(profileId, id).apply {
|
||||||
val oldStartTime = oldLessonRange?.startTime
|
this.type = type
|
||||||
val oldEndTime = oldLessonRange?.endTime
|
|
||||||
|
|
||||||
when (type) {
|
when (type) {
|
||||||
Lesson.TYPE_SHIFTED_SOURCE -> {
|
Lesson.TYPE_NORMAL, Lesson.TYPE_CHANGE, Lesson.TYPE_SHIFTED_TARGET -> {
|
||||||
this.lessonNumber = oldLessonNumber
|
this.date = lessonDate
|
||||||
this.date = oldLessonDate
|
this.lessonNumber = lessonNumber
|
||||||
this.startTime = oldStartTime
|
this.startTime = startTime
|
||||||
this.endTime = oldEndTime
|
this.endTime = endTime
|
||||||
|
this.subjectId = subjectId
|
||||||
|
this.teacherId = teacherId
|
||||||
|
this.teamId = teamId
|
||||||
|
this.classroom = classroom
|
||||||
|
|
||||||
|
this.oldTeacherId = oldTeacherId
|
||||||
}
|
}
|
||||||
|
|
||||||
Lesson.TYPE_SHIFTED_TARGET -> {
|
Lesson.TYPE_CANCELLED, Lesson.TYPE_SHIFTED_SOURCE -> {
|
||||||
this.oldLessonNumber = oldLessonNumber
|
this.oldDate = lessonDate
|
||||||
this.oldDate = oldLessonDate
|
this.oldLessonNumber = lessonNumber
|
||||||
this.oldStartTime = oldStartTime
|
this.oldStartTime = startTime
|
||||||
this.oldEndTime = oldEndTime
|
this.oldEndTime = endTime
|
||||||
|
this.oldSubjectId = subjectId
|
||||||
|
this.oldTeacherId = teacherId
|
||||||
|
this.oldTeamId = teamId
|
||||||
|
this.oldClassroom = classroom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == Lesson.TYPE_SHIFTED_SOURCE || type == Lesson.TYPE_SHIFTED_TARGET) {
|
||||||
|
val shift = Regexes.VULCAN_SHITFT_ANNOTATION.find(changeAnnotation)
|
||||||
|
val oldLessonNumber = shift?.get(2)?.toInt()
|
||||||
|
val oldLessonDate = shift?.get(3)?.let { Date.fromd_m_Y(it) }
|
||||||
|
|
||||||
|
val oldLessonRange = data.lessonRanges.singleOrNull { it.lessonNumber == oldLessonNumber }
|
||||||
|
val oldStartTime = oldLessonRange?.startTime
|
||||||
|
val oldEndTime = oldLessonRange?.endTime
|
||||||
|
|
||||||
|
when (type) {
|
||||||
|
Lesson.TYPE_SHIFTED_SOURCE -> {
|
||||||
|
this.lessonNumber = oldLessonNumber
|
||||||
|
this.date = oldLessonDate
|
||||||
|
this.startTime = oldStartTime
|
||||||
|
this.endTime = oldEndTime
|
||||||
|
}
|
||||||
|
|
||||||
|
Lesson.TYPE_SHIFTED_TARGET -> {
|
||||||
|
this.oldLessonNumber = oldLessonNumber
|
||||||
|
this.oldDate = oldLessonDate
|
||||||
|
this.oldStartTime = oldStartTime
|
||||||
|
this.oldEndTime = oldEndTime
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type != Lesson.TYPE_NORMAL) {
|
||||||
|
data.metadataList.add(Metadata(
|
||||||
|
profileId,
|
||||||
|
Metadata.TYPE_LESSON_CHANGE,
|
||||||
|
id,
|
||||||
|
profile.empty,
|
||||||
|
profile.empty,
|
||||||
|
System.currentTimeMillis()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
dates.add(lessonDate.value)
|
||||||
|
lessons.add(lessonObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type != Lesson.TYPE_NORMAL) {
|
val date: Date = weekStart.clone()
|
||||||
data.metadataList.add(Metadata(
|
while (date <= weekEnd) {
|
||||||
profileId,
|
if (!dates.contains(date.value)) {
|
||||||
Metadata.TYPE_LESSON_CHANGE,
|
lessons.add(Lesson(profileId, date.value.toLong()).apply {
|
||||||
id,
|
this.type = Lesson.TYPE_NO_LESSONS
|
||||||
profile.empty,
|
this.date = date.clone()
|
||||||
profile.empty,
|
})
|
||||||
System.currentTimeMillis()
|
}
|
||||||
))
|
|
||||||
|
date.stepForward(0, 0, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
dates.add(lessonDate.value)
|
d(TAG, "Clearing lessons between ${weekStart.stringY_m_d} and ${weekEnd.stringY_m_d} - timetable downloaded for $getDate")
|
||||||
lessons.add(lessonObject)
|
|
||||||
|
data.lessonNewList.addAll(lessons)
|
||||||
|
data.toRemove.add(DataRemoveModel.Timetable.between(weekStart, weekEnd))
|
||||||
|
|
||||||
|
data.setSyncNext(ENDPOINT_VULCAN_API_TIMETABLE, SYNC_ALWAYS)
|
||||||
|
onSuccess()
|
||||||
}
|
}
|
||||||
|
|
||||||
val date: Date = weekStart.clone()
|
|
||||||
while (date <= weekEnd) {
|
|
||||||
if (!dates.contains(date.value)) {
|
|
||||||
lessons.add(Lesson(profileId, date.value.toLong()).apply {
|
|
||||||
this.type = Lesson.TYPE_NO_LESSONS
|
|
||||||
this.date = date.clone()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
date.stepForward(0, 0, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
d(TAG, "Clearing lessons between ${weekStart.stringY_m_d} and ${weekEnd.stringY_m_d} - timetable downloaded for $getDate")
|
|
||||||
|
|
||||||
data.lessonNewList.addAll(lessons)
|
|
||||||
data.toRemove.add(DataRemoveModel.Timetable.between(weekStart, weekEnd))
|
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_VULCAN_API_TIMETABLE, SYNC_ALWAYS)
|
|
||||||
onSuccess()
|
|
||||||
}
|
}
|
||||||
}}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package pl.szczodrzynski.edziennik.data.db.modules.grades;
|
package pl.szczodrzynski.edziennik.data.db.modules.grades;
|
||||||
|
|
||||||
import androidx.room.Entity;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import androidx.room.Entity;
|
||||||
|
|
||||||
@Entity(tableName = "gradeCategories",
|
@Entity(tableName = "gradeCategories",
|
||||||
primaryKeys = {"profileId", "categoryId"})
|
primaryKeys = {"profileId", "categoryId"})
|
||||||
public class GradeCategory {
|
public class GradeCategory {
|
||||||
|
@ -25,9 +25,6 @@ public class GradeCategory {
|
||||||
*/
|
*/
|
||||||
public int type = 0;
|
public int type = 0;
|
||||||
|
|
||||||
public static final int TYPE_NORMAL = 0;
|
|
||||||
public static final int TYPE_COMMENT = 1;
|
|
||||||
|
|
||||||
public GradeCategory(int profileId, long categoryId, float weight, int color, String text) {
|
public GradeCategory(int profileId, long categoryId, float weight, int color, String text) {
|
||||||
this.profileId = profileId;
|
this.profileId = profileId;
|
||||||
this.categoryId = categoryId;
|
this.categoryId = categoryId;
|
||||||
|
|
|
@ -38,16 +38,16 @@ interface TimetableDao {
|
||||||
@Query("DELETE FROM timetable WHERE profileId = :profileId")
|
@Query("DELETE FROM timetable WHERE profileId = :profileId")
|
||||||
fun clear(profileId: Int)
|
fun clear(profileId: Int)
|
||||||
|
|
||||||
@Query("DELETE FROM timetable WHERE profileId = :profileId AND ((type != 3 AND date >= :dateFrom) OR ((type = 3 OR type = 1) AND oldDate >= :dateFrom))")
|
@Query("DELETE FROM timetable WHERE profileId = :profileId AND (type != 3 AND date >= :dateFrom) OR ((type = 3 OR type = 1) AND oldDate >= :dateFrom)")
|
||||||
fun clearFromDate(profileId: Int, dateFrom: Date)
|
fun clearFromDate(profileId: Int, dateFrom: Date)
|
||||||
@Query("DELETE FROM timetable WHERE profileId = :profileId AND ((type != 3 AND date <= :dateTo) OR ((type = 3 OR type = 1) AND oldDate <= :dateTo))")
|
@Query("DELETE FROM timetable WHERE profileId = :profileId AND (type != 3 AND date <= :dateTo) OR ((type = 3 OR type = 1) AND oldDate <= :dateTo)")
|
||||||
fun clearToDate(profileId: Int, dateTo: Date)
|
fun clearToDate(profileId: Int, dateTo: Date)
|
||||||
@Query("DELETE FROM timetable WHERE profileId = :profileId AND ((type != 3 AND date >= :dateFrom AND date <= :dateTo) OR ((type = 3 OR type = 1) AND oldDate >= :dateFrom AND oldDate <= :dateTo))")
|
@Query("DELETE FROM timetable WHERE profileId = :profileId AND (type != 3 AND date >= :dateFrom AND date <= :dateTo) OR ((type = 3 OR type = 1) AND oldDate >= :dateFrom AND oldDate <= :dateTo)")
|
||||||
fun clearBetweenDates(profileId: Int, dateFrom: Date, dateTo: Date)
|
fun clearBetweenDates(profileId: Int, dateFrom: Date, dateTo: Date)
|
||||||
|
|
||||||
@Query("""
|
@Query("""
|
||||||
$QUERY
|
$QUERY
|
||||||
WHERE timetable.profileId = :profileId AND ((type != 3 AND date = :date) OR ((type = 3 OR type = 1) AND oldDate = :date))
|
WHERE timetable.profileId = :profileId AND (type != 3 AND date = :date) OR ((type = 3 OR type = 1) AND oldDate = :date)
|
||||||
ORDER BY id, type
|
ORDER BY id, type
|
||||||
""")
|
""")
|
||||||
fun getForDate(profileId: Int, date: Date) : LiveData<List<LessonFull>>
|
fun getForDate(profileId: Int, date: Date) : LiveData<List<LessonFull>>
|
||||||
|
@ -58,15 +58,7 @@ interface TimetableDao {
|
||||||
ORDER BY id, type
|
ORDER BY id, type
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
""")
|
""")
|
||||||
fun getNextWithSubject(profileId: Int, today: Date, subjectId: Long) : LiveData<LessonFull?>
|
fun getNextWithSubject(profileId: Int, today: Date, subjectId: Long) : LiveData<LessonFull>
|
||||||
|
|
||||||
@Query("""
|
|
||||||
$QUERY
|
|
||||||
WHERE timetable.profileId = :profileId AND ((type != 3 AND date > :today) OR ((type = 3 OR type = 1) AND oldDate > :today)) AND timetable.subjectId = :subjectId AND timetable.teamId = :teamId
|
|
||||||
ORDER BY id, type
|
|
||||||
LIMIT 1
|
|
||||||
""")
|
|
||||||
fun getNextWithSubjectAndTeam(profileId: Int, today: Date, subjectId: Long, teamId: Long): LiveData<LessonFull?>
|
|
||||||
|
|
||||||
@Query("""
|
@Query("""
|
||||||
$QUERY
|
$QUERY
|
||||||
|
|
|
@ -125,22 +125,19 @@ public class BootReceiver extends BroadcastReceiver {
|
||||||
String updateUrl = result.get("update_url").getAsString();
|
String updateUrl = result.get("update_url").getAsString();
|
||||||
String updateFilename = result.get("update_filename").getAsString();
|
String updateFilename = result.get("update_filename").getAsString();
|
||||||
boolean updateMandatory = result.get("update_mandatory").getAsBoolean();
|
boolean updateMandatory = result.get("update_mandatory").getAsBoolean();
|
||||||
boolean updateDirect = result.get("update_direct").getAsBoolean();
|
|
||||||
|
|
||||||
if (app.appConfig.updateVersion == null || !app.appConfig.updateVersion.equals(updateVersion)) {
|
if (app.appConfig.updateVersion == null || !app.appConfig.updateVersion.equals(updateVersion)) {
|
||||||
app.appConfig.updateVersion = updateVersion;
|
app.appConfig.updateVersion = updateVersion;
|
||||||
app.appConfig.updateUrl = updateUrl;
|
app.appConfig.updateUrl = updateUrl;
|
||||||
app.appConfig.updateFilename = updateFilename;
|
app.appConfig.updateFilename = updateFilename;
|
||||||
app.appConfig.updateMandatory = updateMandatory;
|
app.appConfig.updateMandatory = updateMandatory;
|
||||||
app.appConfig.updateDirect = updateDirect;
|
|
||||||
app.saveConfig();
|
app.saveConfig();
|
||||||
}
|
}
|
||||||
if (!UPDATES_ON_PLAY_STORE || intent.getBooleanExtra("UserChecked", false)) {
|
if (!UPDATES_ON_PLAY_STORE || intent.getBooleanExtra("UserChecked", false)) {
|
||||||
app.notifier.notificationUpdatesShow(
|
app.notifier.notificationUpdatesShow(
|
||||||
updateVersion,
|
updateVersion,
|
||||||
updateUrl,
|
updateUrl,
|
||||||
updateFilename,
|
updateFilename);
|
||||||
updateDirect);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (app.appConfig.updateVersion == null || !app.appConfig.updateVersion.equals("")) {
|
if (app.appConfig.updateVersion == null || !app.appConfig.updateVersion.equals("")) {
|
||||||
|
@ -262,7 +259,7 @@ public class BootReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onHandleIntent(Intent intent) {
|
protected void onHandleIntent(Intent intent) {
|
||||||
if (UPDATES_ON_PLAY_STORE && !intent.getBooleanExtra("update_direct", false)) {
|
if (UPDATES_ON_PLAY_STORE) {
|
||||||
Utils.openGooglePlay(this, "pl.szczodrzynski.edziennik");
|
Utils.openGooglePlay(this, "pl.szczodrzynski.edziennik");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -273,8 +270,7 @@ public class BootReceiver extends BroadcastReceiver {
|
||||||
app.notifier.notificationUpdatesShow(
|
app.notifier.notificationUpdatesShow(
|
||||||
intent.getStringExtra("update_version"),
|
intent.getStringExtra("update_version"),
|
||||||
intent.getStringExtra("update_url"),
|
intent.getStringExtra("update_url"),
|
||||||
intent.getStringExtra("update_filename"),
|
intent.getStringExtra("update_filename"));
|
||||||
intent.getBooleanExtra("update_direct", false));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,22 +154,19 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
|
||||||
String updateUrl = remoteMessage.getData().get("update_url");
|
String updateUrl = remoteMessage.getData().get("update_url");
|
||||||
String updateFilename = remoteMessage.getData().get("update_filename");
|
String updateFilename = remoteMessage.getData().get("update_filename");
|
||||||
boolean updateMandatory = Boolean.parseBoolean(remoteMessage.getData().get("update_mandatory"));
|
boolean updateMandatory = Boolean.parseBoolean(remoteMessage.getData().get("update_mandatory"));
|
||||||
boolean updateDirect = Boolean.parseBoolean(remoteMessage.getData().get("update_direct"));
|
|
||||||
|
|
||||||
if (app.appConfig.updateVersion == null || !app.appConfig.updateVersion.equals(updateVersion)) {
|
if (app.appConfig.updateVersion == null || !app.appConfig.updateVersion.equals(updateVersion)) {
|
||||||
app.appConfig.updateVersion = updateVersion;
|
app.appConfig.updateVersion = updateVersion;
|
||||||
app.appConfig.updateUrl = updateUrl;
|
app.appConfig.updateUrl = updateUrl;
|
||||||
app.appConfig.updateFilename = updateFilename;
|
app.appConfig.updateFilename = updateFilename;
|
||||||
app.appConfig.updateMandatory = updateMandatory;
|
app.appConfig.updateMandatory = updateMandatory;
|
||||||
app.appConfig.updateDirect = updateDirect;
|
|
||||||
app.saveConfig("updateVersion", "updateUrl", "updateFilename", "updateMandatory");
|
app.saveConfig("updateVersion", "updateUrl", "updateFilename", "updateMandatory");
|
||||||
}
|
}
|
||||||
if (!remoteMessage.getData().containsKey("update_silent")) {
|
if (!remoteMessage.getData().containsKey("update_silent")) {
|
||||||
app.notifier.notificationUpdatesShow(
|
app.notifier.notificationUpdatesShow(
|
||||||
updateVersion,
|
updateVersion,
|
||||||
updateUrl,
|
updateUrl,
|
||||||
updateFilename,
|
updateFilename);
|
||||||
updateDirect);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (app.appConfig.updateVersion == null || !app.appConfig.updateVersion.equals("")) {
|
if (app.appConfig.updateVersion == null || !app.appConfig.updateVersion.equals("")) {
|
||||||
|
|
|
@ -4,25 +4,19 @@
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.ui.dialogs.event
|
package pl.szczodrzynski.edziennik.ui.dialogs.event
|
||||||
|
|
||||||
import android.graphics.PorterDuff
|
|
||||||
import android.graphics.PorterDuffColorFilter
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import com.google.android.material.datepicker.MaterialDatePicker
|
import com.google.android.material.datepicker.MaterialDatePicker
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.jaredrummler.android.colorpicker.ColorPickerDialog
|
|
||||||
import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import pl.szczodrzynski.edziennik.*
|
import pl.szczodrzynski.edziennik.*
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.events.EventType
|
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.subjects.Subject
|
import pl.szczodrzynski.edziennik.data.db.modules.subjects.Subject
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
|
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.LessonFull
|
import pl.szczodrzynski.edziennik.data.db.modules.timetable.LessonFull
|
||||||
import pl.szczodrzynski.edziennik.databinding.DialogEventManualV2Binding
|
import pl.szczodrzynski.edziennik.databinding.DialogEventManualV2Binding
|
||||||
import pl.szczodrzynski.edziennik.utils.Anim
|
|
||||||
import pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
import pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||||
|
@ -52,14 +46,10 @@ class EventManualV2Dialog(
|
||||||
private val app by lazy { activity.application as App }
|
private val app by lazy { activity.application as App }
|
||||||
private lateinit var b: DialogEventManualV2Binding
|
private lateinit var b: DialogEventManualV2Binding
|
||||||
private lateinit var dialog: AlertDialog
|
private lateinit var dialog: AlertDialog
|
||||||
|
private lateinit var event: Event
|
||||||
private var defaultLoaded = false
|
private var defaultLoaded = false
|
||||||
|
|
||||||
private lateinit var event: Event
|
|
||||||
private var customColor: Int? = null
|
|
||||||
|
|
||||||
init { run {
|
init { run {
|
||||||
if (activity.isFinishing)
|
|
||||||
return@run
|
|
||||||
job = Job()
|
job = Job()
|
||||||
onShowListener?.invoke(TAG)
|
onShowListener?.invoke(TAG)
|
||||||
b = DialogEventManualV2Binding.inflate(activity.layoutInflater)
|
b = DialogEventManualV2Binding.inflate(activity.layoutInflater)
|
||||||
|
@ -88,17 +78,6 @@ class EventManualV2Dialog(
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
b.showMore.onClick { // TODO iconics is broken
|
|
||||||
it.apply {
|
|
||||||
refreshDrawableState()
|
|
||||||
|
|
||||||
if (isChecked)
|
|
||||||
Anim.expand(b.moreLayout, 200, null)
|
|
||||||
else
|
|
||||||
Anim.collapse(b.moreLayout, 200, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
loadLists()
|
loadLists()
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
@ -133,33 +112,18 @@ class EventManualV2Dialog(
|
||||||
""
|
""
|
||||||
)
|
)
|
||||||
b.teacherDropdown += teachers.map { TextInputDropDown.Item(it.id, it.fullName, tag = it) }
|
b.teacherDropdown += teachers.map { TextInputDropDown.Item(it.id, it.fullName, tag = it) }
|
||||||
|
|
||||||
// get the event type list
|
|
||||||
val eventTypes = app.db.eventTypeDao().getAllNow(profileId)
|
|
||||||
b.typeDropdown.clear()
|
|
||||||
b.typeDropdown += eventTypes.map { TextInputDropDown.Item(it.id, it.name, tag = it) }
|
|
||||||
}
|
}
|
||||||
deferred.await()
|
deferred.await()
|
||||||
|
|
||||||
b.teamDropdown.isEnabled = true
|
b.teamDropdown.isEnabled = true
|
||||||
b.subjectDropdown.isEnabled = true
|
b.subjectDropdown.isEnabled = true
|
||||||
b.teacherDropdown.isEnabled = true
|
b.teacherDropdown.isEnabled = true
|
||||||
b.typeDropdown.isEnabled = true
|
|
||||||
|
|
||||||
b.typeDropdown.selected?.let { item ->
|
|
||||||
customColor = (item.tag as EventType).color
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy IDs from event being edited
|
// copy IDs from event being edited
|
||||||
editingEvent?.let {
|
editingEvent?.let {
|
||||||
b.teamDropdown.select(it.teamId)
|
b.teamDropdown.select(it.teamId)
|
||||||
b.subjectDropdown.select(it.subjectId)
|
b.subjectDropdown.select(it.subjectId)
|
||||||
b.teacherDropdown.select(it.teacherId)
|
b.teacherDropdown.select(it.teacherId)
|
||||||
b.typeDropdown.select(it.type)?.let { item ->
|
|
||||||
customColor = (item.tag as EventType).color
|
|
||||||
}
|
|
||||||
if (it.color != -1)
|
|
||||||
customColor = it.color
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy IDs from the LessonFull
|
// copy IDs from the LessonFull
|
||||||
|
@ -169,30 +133,6 @@ class EventManualV2Dialog(
|
||||||
b.teacherDropdown.select(it.displayTeacherId)
|
b.teacherDropdown.select(it.displayTeacherId)
|
||||||
}
|
}
|
||||||
|
|
||||||
b.typeDropdown.setOnChangeListener {
|
|
||||||
b.typeColor.background.colorFilter = PorterDuffColorFilter((it.tag as EventType).color, PorterDuff.Mode.SRC_ATOP)
|
|
||||||
customColor = null
|
|
||||||
return@setOnChangeListener true
|
|
||||||
}
|
|
||||||
(customColor ?: Event.COLOR_DEFAULT).let {
|
|
||||||
b.typeColor.background.colorFilter = PorterDuffColorFilter(it, PorterDuff.Mode.SRC_ATOP)
|
|
||||||
}
|
|
||||||
b.typeColor.onClick {
|
|
||||||
val currentColor = (b.typeDropdown?.selected?.tag as EventType?)?.color ?: Event.COLOR_DEFAULT
|
|
||||||
val colorPickerDialog = ColorPickerDialog.newBuilder()
|
|
||||||
.setColor(currentColor)
|
|
||||||
.create()
|
|
||||||
colorPickerDialog.setColorPickerDialogListener(
|
|
||||||
object : ColorPickerDialogListener {
|
|
||||||
override fun onDialogDismissed(dialogId: Int) {}
|
|
||||||
override fun onColorSelected(dialogId: Int, color: Int) {
|
|
||||||
b.typeColor.background.colorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP)
|
|
||||||
customColor = color
|
|
||||||
}
|
|
||||||
})
|
|
||||||
colorPickerDialog.show(activity.fragmentManager, "color-picker-dialog")
|
|
||||||
}
|
|
||||||
|
|
||||||
loadDates()
|
loadDates()
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
@ -263,20 +203,12 @@ class EventManualV2Dialog(
|
||||||
val dates = deferred.await()
|
val dates = deferred.await()
|
||||||
b.dateDropdown.clear().append(dates)
|
b.dateDropdown.clear().append(dates)
|
||||||
|
|
||||||
editingEvent?.eventDate?.let {
|
editingEvent?.let {
|
||||||
b.dateDropdown.select(TextInputDropDown.Item(
|
b.dateDropdown.select(it.eventDate.value.toLong())
|
||||||
it.value.toLong(),
|
|
||||||
it.formattedString,
|
|
||||||
tag = it
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultLesson?.displayDate?.let {
|
defaultLesson?.let {
|
||||||
b.dateDropdown.select(TextInputDropDown.Item(
|
b.dateDropdown.select(it.displayDate?.value?.toLong())
|
||||||
it.value.toLong(),
|
|
||||||
it.formattedString,
|
|
||||||
tag = it
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b.dateDropdown.selected == null) {
|
if (b.dateDropdown.selected == null) {
|
||||||
|
@ -289,24 +221,22 @@ class EventManualV2Dialog(
|
||||||
when {
|
when {
|
||||||
// next lesson with specified subject
|
// next lesson with specified subject
|
||||||
item.id < -1 -> {
|
item.id < -1 -> {
|
||||||
val teamId = defaultLesson?.teamId ?: -1
|
app.db.timetableDao().getNextWithSubject(profileId, Date.getToday(), -item.id).observeOnce(activity, Observer {
|
||||||
val selectedLessonDate = defaultLesson?.date ?: Date.getToday()
|
|
||||||
|
|
||||||
when (teamId) {
|
|
||||||
-1L -> app.db.timetableDao().getNextWithSubject(profileId, selectedLessonDate, -item.id)
|
|
||||||
else -> app.db.timetableDao().getNextWithSubjectAndTeam(profileId, selectedLessonDate, -item.id, teamId)
|
|
||||||
}.observeOnce(activity, Observer {
|
|
||||||
val lessonDate = it?.displayDate ?: return@Observer
|
val lessonDate = it?.displayDate ?: return@Observer
|
||||||
b.dateDropdown.select(TextInputDropDown.Item(
|
b.dateDropdown.selected = TextInputDropDown.Item(
|
||||||
lessonDate.value.toLong(),
|
lessonDate.value.toLong(),
|
||||||
lessonDate.formattedString,
|
lessonDate.formattedString,
|
||||||
tag = lessonDate
|
tag = lessonDate
|
||||||
))
|
)
|
||||||
b.teamDropdown.select(it.displayTeamId)
|
// TODO load correct hour when selecting next lesson
|
||||||
b.subjectDropdown.select(it.displaySubjectId)
|
b.dateDropdown.updateText()
|
||||||
b.teacherDropdown.select(it.displayTeacherId)
|
it.let {
|
||||||
|
b.teamDropdown.select(it.displayTeamId)
|
||||||
|
b.subjectDropdown.select(it.displaySubjectId)
|
||||||
|
b.teacherDropdown.select(it.displayTeacherId)
|
||||||
|
}
|
||||||
defaultLoaded = false
|
defaultLoaded = false
|
||||||
loadHours(it.displayStartTime)
|
loadHours()
|
||||||
})
|
})
|
||||||
return@setOnChangeListener false
|
return@setOnChangeListener false
|
||||||
}
|
}
|
||||||
|
@ -314,17 +244,17 @@ class EventManualV2Dialog(
|
||||||
item.id == -1L -> {
|
item.id == -1L -> {
|
||||||
MaterialDatePicker.Builder
|
MaterialDatePicker.Builder
|
||||||
.datePicker()
|
.datePicker()
|
||||||
.setSelection((b.dateDropdown.selectedId?.let { Date.fromValue(it.toInt()) }
|
.setSelection((b.dateDropdown.selectedId?.let { Date.fromValue(it.toInt()) } ?: Date.getToday()).inMillis)
|
||||||
?: Date.getToday()).inMillis)
|
|
||||||
.build()
|
.build()
|
||||||
.apply {
|
.apply {
|
||||||
addOnPositiveButtonClickListener {
|
addOnPositiveButtonClickListener {
|
||||||
val dateSelected = Date.fromMillis(it)
|
val dateSelected = Date.fromMillis(it)
|
||||||
b.dateDropdown.select(TextInputDropDown.Item(
|
b.dateDropdown.selected = TextInputDropDown.Item(
|
||||||
dateSelected.value.toLong(),
|
dateSelected.value.toLong(),
|
||||||
dateSelected.formattedString,
|
dateSelected.formattedString,
|
||||||
tag = dateSelected
|
tag = dateSelected
|
||||||
))
|
)
|
||||||
|
b.dateDropdown.updateText()
|
||||||
loadHours()
|
loadHours()
|
||||||
}
|
}
|
||||||
show(this@EventManualV2Dialog.activity.supportFragmentManager, "MaterialDatePicker")
|
show(this@EventManualV2Dialog.activity.supportFragmentManager, "MaterialDatePicker")
|
||||||
|
@ -344,7 +274,7 @@ class EventManualV2Dialog(
|
||||||
loadHours()
|
loadHours()
|
||||||
}}
|
}}
|
||||||
|
|
||||||
private fun loadHours(defaultHour: Time? = null) {
|
private fun loadHours() {
|
||||||
b.timeDropdown.isEnabled = false
|
b.timeDropdown.isEnabled = false
|
||||||
// get the selected date
|
// get the selected date
|
||||||
val date = b.dateDropdown.selectedId?.let { Date.fromValue(it.toInt()) } ?: return
|
val date = b.dateDropdown.selectedId?.let { Date.fromValue(it.toInt()) } ?: return
|
||||||
|
@ -370,8 +300,7 @@ class EventManualV2Dialog(
|
||||||
lesson.displayStartTime?.stringHM ?: "",
|
lesson.displayStartTime?.stringHM ?: "",
|
||||||
lesson.displaySubjectName?.let {
|
lesson.displaySubjectName?.let {
|
||||||
when {
|
when {
|
||||||
lesson.type == Lesson.TYPE_CANCELLED
|
lesson.type == Lesson.TYPE_CANCELLED -> it.asStrikethroughSpannable()
|
||||||
|| lesson.type == Lesson.TYPE_SHIFTED_SOURCE -> it.asStrikethroughSpannable()
|
|
||||||
lesson.type != Lesson.TYPE_NORMAL -> it.asItalicSpannable()
|
lesson.type != Lesson.TYPE_NORMAL -> it.asItalicSpannable()
|
||||||
else -> it
|
else -> it
|
||||||
}
|
}
|
||||||
|
@ -407,10 +336,6 @@ class EventManualV2Dialog(
|
||||||
defaultLesson?.let {
|
defaultLesson?.let {
|
||||||
b.timeDropdown.select(it.displayStartTime?.value?.toLong())
|
b.timeDropdown.select(it.displayStartTime?.value?.toLong())
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultHour?.let {
|
|
||||||
b.timeDropdown.select(it.value.toLong())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
defaultLoaded = true
|
defaultLoaded = true
|
||||||
b.timeDropdown.isEnabled = true
|
b.timeDropdown.isEnabled = true
|
||||||
|
@ -418,16 +343,16 @@ class EventManualV2Dialog(
|
||||||
// attach a listener to time dropdown
|
// attach a listener to time dropdown
|
||||||
b.timeDropdown.setOnChangeListener { item ->
|
b.timeDropdown.setOnChangeListener { item ->
|
||||||
when {
|
when {
|
||||||
// no lessons this day
|
|
||||||
item.id == -2L -> {
|
|
||||||
b.timeDropdown.deselect()
|
|
||||||
return@setOnChangeListener false
|
|
||||||
}
|
|
||||||
// custom start hour
|
// custom start hour
|
||||||
item.id == -1L -> {
|
item.id == -1L -> {
|
||||||
|
|
||||||
return@setOnChangeListener false
|
return@setOnChangeListener false
|
||||||
}
|
}
|
||||||
|
// no lessons this day
|
||||||
|
item.id == -2L -> {
|
||||||
|
b.timeDropdown.deselect()
|
||||||
|
return@setOnChangeListener false
|
||||||
|
}
|
||||||
// selected a specific lesson
|
// selected a specific lesson
|
||||||
else -> {
|
else -> {
|
||||||
if (item.tag is LessonFull) {
|
if (item.tag is LessonFull) {
|
||||||
|
@ -456,4 +381,4 @@ class EventManualV2Dialog(
|
||||||
private fun saveEvent() {
|
private fun saveEvent() {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -33,8 +33,6 @@ class LessonDetailsDialog(
|
||||||
private lateinit var dialog: AlertDialog
|
private lateinit var dialog: AlertDialog
|
||||||
|
|
||||||
init { run {
|
init { run {
|
||||||
if (activity.isFinishing)
|
|
||||||
return@run
|
|
||||||
onShowListener?.invoke(TAG)
|
onShowListener?.invoke(TAG)
|
||||||
b = DialogLessonDetailsBinding.inflate(activity.layoutInflater)
|
b = DialogLessonDetailsBinding.inflate(activity.layoutInflater)
|
||||||
dialog = MaterialAlertDialogBuilder(activity)
|
dialog = MaterialAlertDialogBuilder(activity)
|
||||||
|
@ -132,28 +130,28 @@ class LessonDetailsDialog(
|
||||||
if (lesson.type < Lesson.TYPE_SHIFTED_SOURCE && lesson.oldSubjectId != null && lesson.subjectId != lesson.oldSubjectId) {
|
if (lesson.type < Lesson.TYPE_SHIFTED_SOURCE && lesson.oldSubjectId != null && lesson.subjectId != lesson.oldSubjectId) {
|
||||||
b.oldSubjectName = lesson.oldSubjectName
|
b.oldSubjectName = lesson.oldSubjectName
|
||||||
}
|
}
|
||||||
if (lesson.type != Lesson.TYPE_CANCELLED && lesson.displaySubjectId != null) {
|
if (lesson.type != Lesson.TYPE_CANCELLED && lesson.subjectId != null) {
|
||||||
b.subjectName = lesson.subjectName
|
b.subjectName = lesson.subjectName
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lesson.type < Lesson.TYPE_SHIFTED_SOURCE && lesson.oldTeacherId != null && lesson.teacherId != lesson.oldTeacherId) {
|
if (lesson.type < Lesson.TYPE_SHIFTED_SOURCE && lesson.oldTeacherId != null && lesson.teacherId != lesson.oldTeacherId) {
|
||||||
b.oldTeacherName = lesson.oldTeacherName
|
b.oldTeacherName = lesson.oldTeacherName
|
||||||
}
|
}
|
||||||
if (lesson.type != Lesson.TYPE_CANCELLED && lesson.displayTeacherId != null) {
|
if (lesson.type != Lesson.TYPE_CANCELLED && lesson.teacherId != null) {
|
||||||
b.teacherName = lesson.teacherName
|
b.teacherName = lesson.teacherName
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lesson.oldClassroom != null && lesson.classroom != lesson.oldClassroom) {
|
if (lesson.oldClassroom != null && lesson.classroom != lesson.oldClassroom) {
|
||||||
b.oldClassroom = lesson.oldClassroom
|
b.oldClassroom = lesson.oldClassroom
|
||||||
}
|
}
|
||||||
if (lesson.type != Lesson.TYPE_CANCELLED && lesson.displayClassroom != null) {
|
if (lesson.type != Lesson.TYPE_CANCELLED && lesson.classroom != null) {
|
||||||
b.classroom = lesson.classroom
|
b.classroom = lesson.classroom
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lesson.type < Lesson.TYPE_SHIFTED_SOURCE && lesson.oldTeamId != null && lesson.teamId != lesson.oldTeamId) {
|
if (lesson.type < Lesson.TYPE_SHIFTED_SOURCE && lesson.oldTeamId != null && lesson.teamId != lesson.oldTeamId) {
|
||||||
b.oldTeamName = lesson.oldTeamName
|
b.oldTeamName = lesson.oldTeamName
|
||||||
}
|
}
|
||||||
if (lesson.type != Lesson.TYPE_CANCELLED && lesson.displayTeamId != null) {
|
if (lesson.type != Lesson.TYPE_CANCELLED && lesson.teamId != null) {
|
||||||
b.teamName = lesson.teamName
|
b.teamName = lesson.teamName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,8 @@ import com.mikepenz.iconics.typeface.library.community.material.CommunityMateria
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.MainActivity
|
import pl.szczodrzynski.edziennik.MainActivity
|
||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
|
||||||
import pl.szczodrzynski.edziennik.databinding.FragmentHomeworkBinding
|
import pl.szczodrzynski.edziennik.databinding.FragmentHomeworkBinding
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
import pl.szczodrzynski.edziennik.ui.dialogs.event.EventManualDialog
|
import pl.szczodrzynski.edziennik.ui.dialogs.event.EventManualDialog
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesFragment
|
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesFragment
|
||||||
import pl.szczodrzynski.edziennik.utils.Themes
|
import pl.szczodrzynski.edziennik.utils.Themes
|
||||||
|
@ -84,11 +84,7 @@ class HomeworkFragment : Fragment() {
|
||||||
b.viewPager.currentItem = pageSelection
|
b.viewPager.currentItem = pageSelection
|
||||||
b.viewPager.clearOnPageChangeListeners()
|
b.viewPager.clearOnPageChangeListeners()
|
||||||
b.viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
b.viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
||||||
override fun onPageScrollStateChanged(state: Int) {
|
override fun onPageScrollStateChanged(state: Int) {}
|
||||||
if (b.refreshLayout != null) {
|
|
||||||
b.refreshLayout.isEnabled = state == ViewPager.SCROLL_STATE_IDLE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
|
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
|
||||||
override fun onPageSelected(position: Int) {
|
override fun onPageSelected(position: Int) {
|
||||||
pageSelection = position
|
pageSelection = position
|
||||||
|
|
|
@ -19,7 +19,7 @@ import pl.szczodrzynski.edziennik.api.v2.models.ApiError;
|
||||||
import pl.szczodrzynski.edziennik.databinding.FragmentLoginLibrusBinding;
|
import pl.szczodrzynski.edziennik.databinding.FragmentLoginLibrusBinding;
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.error.ErrorSnackbar;
|
import pl.szczodrzynski.edziennik.ui.modules.error.ErrorSnackbar;
|
||||||
|
|
||||||
import static pl.szczodrzynski.edziennik.api.v2.ErrorsKt.ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN;
|
import static pl.szczodrzynski.edziennik.api.v2.ErrorsKt.ERROR_LOGIN_DATA_INVALID;
|
||||||
import static pl.szczodrzynski.edziennik.api.v2.ErrorsKt.ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED;
|
import static pl.szczodrzynski.edziennik.api.v2.ErrorsKt.ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED;
|
||||||
import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_LIBRUS;
|
import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_LIBRUS;
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ public class LoginLibrusFragment extends Fragment {
|
||||||
ApiError error = LoginActivity.error;
|
ApiError error = LoginActivity.error;
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
switch (error.getErrorCode()) {
|
switch (error.getErrorCode()) {
|
||||||
case ERROR_LOGIN_LIBRUS_PORTAL_INVALID_LOGIN:
|
case ERROR_LOGIN_DATA_INVALID:
|
||||||
b.loginPasswordLayout.setError(getString(R.string.login_error_incorrect_login_or_password));
|
b.loginPasswordLayout.setError(getString(R.string.login_error_incorrect_login_or_password));
|
||||||
break;
|
break;
|
||||||
case ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED:
|
case ERROR_LOGIN_LIBRUS_PORTAL_NOT_ACTIVATED:
|
||||||
|
|
|
@ -77,11 +77,7 @@ class MessagesFragment : Fragment() {
|
||||||
b.viewPager.currentItem = pageSelection
|
b.viewPager.currentItem = pageSelection
|
||||||
b.viewPager.clearOnPageChangeListeners()
|
b.viewPager.clearOnPageChangeListeners()
|
||||||
b.viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
b.viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
||||||
override fun onPageScrollStateChanged(state: Int) {
|
override fun onPageScrollStateChanged(state: Int) {}
|
||||||
if (b.refreshLayout != null) {
|
|
||||||
b.refreshLayout.isEnabled = state == ViewPager.SCROLL_STATE_IDLE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
|
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
|
||||||
override fun onPageSelected(position: Int) {
|
override fun onPageSelected(position: Int) {
|
||||||
pageSelection = position
|
pageSelection = position
|
||||||
|
|
|
@ -11,7 +11,6 @@ import android.view.ViewGroup
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.viewpager.widget.ViewPager
|
import androidx.viewpager.widget.ViewPager
|
||||||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
||||||
import kotlinx.coroutines.*
|
|
||||||
import pl.szczodrzynski.edziennik.App
|
import pl.szczodrzynski.edziennik.App
|
||||||
import pl.szczodrzynski.edziennik.MainActivity
|
import pl.szczodrzynski.edziennik.MainActivity
|
||||||
import pl.szczodrzynski.edziennik.R
|
import pl.szczodrzynski.edziennik.R
|
||||||
|
@ -19,25 +18,16 @@ import pl.szczodrzynski.edziennik.api.v2.LOGIN_TYPE_LIBRUS
|
||||||
import pl.szczodrzynski.edziennik.databinding.FragmentTimetableV2Binding
|
import pl.szczodrzynski.edziennik.databinding.FragmentTimetableV2Binding
|
||||||
import pl.szczodrzynski.edziennik.utils.Themes
|
import pl.szczodrzynski.edziennik.utils.Themes
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
|
|
||||||
class TimetableFragment : Fragment(), CoroutineScope {
|
class TimetableFragment : Fragment() {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "TimetableFragment"
|
private const val TAG = "TimetableFragment"
|
||||||
const val ACTION_SCROLL_TO_DATE = "pl.szczodrzynski.edziennik.timetable.SCROLL_TO_DATE"
|
const val ACTION_SCROLL_TO_DATE = "pl.szczodrzynski.edziennik.timetable.SCROLL_TO_DATE"
|
||||||
const val DEFAULT_START_HOUR = 6
|
|
||||||
const val DEFAULT_END_HOUR = 19
|
|
||||||
var pageSelection: Date? = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var app: App
|
private lateinit var app: App
|
||||||
private lateinit var activity: MainActivity
|
private lateinit var activity: MainActivity
|
||||||
private lateinit var b: FragmentTimetableV2Binding
|
private lateinit var b: FragmentTimetableV2Binding
|
||||||
|
|
||||||
private lateinit var job: Job
|
|
||||||
override val coroutineContext: CoroutineContext
|
|
||||||
get() = job + Dispatchers.Main
|
|
||||||
|
|
||||||
private var fabShown = false
|
private var fabShown = false
|
||||||
private val items = mutableListOf<Date>()
|
private val items = mutableListOf<Date>()
|
||||||
|
|
||||||
|
@ -46,13 +36,11 @@ class TimetableFragment : Fragment(), CoroutineScope {
|
||||||
if (context == null)
|
if (context == null)
|
||||||
return null
|
return null
|
||||||
app = activity.application as App
|
app = activity.application as App
|
||||||
job = Job()
|
|
||||||
context!!.theme.applyStyle(Themes.appTheme, true)
|
context!!.theme.applyStyle(Themes.appTheme, true)
|
||||||
if (app.profile == null)
|
if (app.profile == null)
|
||||||
return inflater.inflate(R.layout.fragment_loading, container, false)
|
return inflater.inflate(R.layout.fragment_loading, container, false)
|
||||||
// activity, context and profile is valid
|
// activity, context and profile is valid
|
||||||
b = FragmentTimetableV2Binding.inflate(inflater)
|
b = FragmentTimetableV2Binding.inflate(inflater)
|
||||||
b.refreshLayout.setParent(activity.swipeRefreshLayout)
|
|
||||||
return b.root
|
return b.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,64 +62,48 @@ class TimetableFragment : Fragment(), CoroutineScope {
|
||||||
activity.unregisterReceiver(broadcastReceiver)
|
activity.unregisterReceiver(broadcastReceiver)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { launch {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
// TODO check if app, activity, b can be null
|
// TODO check if app, activity, b can be null
|
||||||
if (app.profile == null || !isAdded)
|
if (app.profile == null || !isAdded)
|
||||||
return@launch
|
return
|
||||||
|
|
||||||
if (app.profile.loginStoreType == LOGIN_TYPE_LIBRUS && app.profile.getLoginData("timetableNotPublic", false)) {
|
if (app.profile.loginStoreType == LOGIN_TYPE_LIBRUS && app.profile.getLoginData("timetableNotPublic", false)) {
|
||||||
b.timetableLayout.visibility = View.GONE
|
b.timetableLayout.visibility = View.GONE
|
||||||
b.timetableNotPublicLayout.visibility = View.VISIBLE
|
b.timetableNotPublicLayout.visibility = View.VISIBLE
|
||||||
return@launch
|
return
|
||||||
}
|
}
|
||||||
b.timetableLayout.visibility = View.VISIBLE
|
b.timetableLayout.visibility = View.VISIBLE
|
||||||
b.timetableNotPublicLayout.visibility = View.GONE
|
b.timetableNotPublicLayout.visibility = View.GONE
|
||||||
|
|
||||||
|
items.clear()
|
||||||
|
|
||||||
|
val monthDayCount = listOf(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
|
||||||
|
|
||||||
val today = Date.getToday().value
|
val today = Date.getToday().value
|
||||||
var startHour = DEFAULT_START_HOUR
|
val yearStart = app.profile.dateSemester1Start?.clone() ?: return
|
||||||
var endHour = DEFAULT_END_HOUR
|
val yearEnd = app.profile.dateYearEnd ?: return
|
||||||
val deferred = async(Dispatchers.Default) {
|
while (yearStart.value <= yearEnd.value) {
|
||||||
items.clear()
|
items += yearStart.clone()
|
||||||
|
var maxDays = monthDayCount[yearStart.month-1]
|
||||||
val monthDayCount = listOf(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
|
if (yearStart.month == 2 && yearStart.isLeap)
|
||||||
|
maxDays++
|
||||||
val yearStart = app.profile.dateSemester1Start?.clone() ?: return@async
|
yearStart.day++
|
||||||
val yearEnd = app.profile.dateYearEnd ?: return@async
|
if (yearStart.day > maxDays) {
|
||||||
while (yearStart.value <= yearEnd.value) {
|
yearStart.day = 1
|
||||||
items += yearStart.clone()
|
yearStart.month++
|
||||||
var maxDays = monthDayCount[yearStart.month-1]
|
}
|
||||||
if (yearStart.month == 2 && yearStart.isLeap)
|
if (yearStart.month > 12) {
|
||||||
maxDays++
|
yearStart.month = 1
|
||||||
yearStart.day++
|
yearStart.year++
|
||||||
if (yearStart.day > maxDays) {
|
|
||||||
yearStart.day = 1
|
|
||||||
yearStart.month++
|
|
||||||
}
|
|
||||||
if (yearStart.month > 12) {
|
|
||||||
yearStart.month = 1
|
|
||||||
yearStart.year++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val lessonRanges = app.db.lessonRangeDao().getAllNow(App.profileId)
|
|
||||||
startHour = lessonRanges.map { it.startTime.hour }.min() ?: DEFAULT_START_HOUR
|
|
||||||
endHour = lessonRanges.map { it.endTime.hour }.max()?.plus(1) ?: DEFAULT_END_HOUR
|
|
||||||
}
|
}
|
||||||
deferred.await()
|
|
||||||
|
|
||||||
val pagerAdapter = TimetablePagerAdapter(
|
val pagerAdapter = TimetablePagerAdapter(fragmentManager ?: return, items)
|
||||||
fragmentManager ?: return@launch,
|
|
||||||
items,
|
|
||||||
startHour,
|
|
||||||
endHour
|
|
||||||
)
|
|
||||||
b.viewPager.offscreenPageLimit = 2
|
b.viewPager.offscreenPageLimit = 2
|
||||||
b.viewPager.adapter = pagerAdapter
|
b.viewPager.adapter = pagerAdapter
|
||||||
b.viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
b.viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
|
||||||
override fun onPageScrollStateChanged(state: Int) {
|
override fun onPageScrollStateChanged(state: Int) {
|
||||||
if (b.refreshLayout != null) {
|
|
||||||
b.refreshLayout.isEnabled = state == ViewPager.SCROLL_STATE_IDLE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||||
|
@ -139,7 +111,6 @@ class TimetableFragment : Fragment(), CoroutineScope {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPageSelected(position: Int) {
|
override fun onPageSelected(position: Int) {
|
||||||
pageSelection = items[position]
|
|
||||||
activity.navView.bottomBar.fabEnable = items[position].value != today
|
activity.navView.bottomBar.fabEnable = items[position].value != today
|
||||||
if (activity.navView.bottomBar.fabEnable && !fabShown) {
|
if (activity.navView.bottomBar.fabEnable && !fabShown) {
|
||||||
activity.gainAttentionFAB()
|
activity.gainAttentionFAB()
|
||||||
|
@ -152,10 +123,10 @@ class TimetableFragment : Fragment(), CoroutineScope {
|
||||||
b.tabLayout.setCurrentItem(items.indexOfFirst { it.value == today }, false)
|
b.tabLayout.setCurrentItem(items.indexOfFirst { it.value == today }, false)
|
||||||
|
|
||||||
//activity.navView.bottomBar.fabEnable = true
|
//activity.navView.bottomBar.fabEnable = true
|
||||||
activity.navView.bottomBar.fabExtendedText = getString(R.string.timetable_today)
|
activity.navView.bottomBar.fabExtendedText = getString(pl.szczodrzynski.edziennik.R.string.timetable_today)
|
||||||
activity.navView.bottomBar.fabIcon = CommunityMaterial.Icon.cmd_calendar_today
|
activity.navView.bottomBar.fabIcon = CommunityMaterial.Icon.cmd_calendar_today
|
||||||
activity.navView.setFabOnClickListener(View.OnClickListener {
|
activity.navView.setFabOnClickListener(View.OnClickListener {
|
||||||
b.tabLayout.setCurrentItem(items.indexOfFirst { it.value == today }, true)
|
b.tabLayout.setCurrentItem(items.indexOfFirst { it.value == today }, true)
|
||||||
})
|
})
|
||||||
}}
|
}
|
||||||
}
|
}
|
|
@ -8,12 +8,7 @@ import pl.szczodrzynski.edziennik.ui.modules.timetable.v2.day.TimetableDayFragme
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Week
|
import pl.szczodrzynski.edziennik.utils.models.Week
|
||||||
|
|
||||||
class TimetablePagerAdapter(
|
class TimetablePagerAdapter(val fragmentManager: FragmentManager, val items: List<Date>) : FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
|
||||||
fragmentManager: FragmentManager,
|
|
||||||
private val items: List<Date>,
|
|
||||||
private val startHour: Int,
|
|
||||||
private val endHour: Int
|
|
||||||
) : FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "TimetablePagerAdapter"
|
private const val TAG = "TimetablePagerAdapter"
|
||||||
}
|
}
|
||||||
|
@ -26,8 +21,6 @@ class TimetablePagerAdapter(
|
||||||
return TimetableDayFragment().apply {
|
return TimetableDayFragment().apply {
|
||||||
arguments = Bundle().apply {
|
arguments = Bundle().apply {
|
||||||
putInt("date", items[position].value)
|
putInt("date", items[position].value)
|
||||||
putInt("startHour", startHour)
|
|
||||||
putInt("endHour", endHour)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*return TimetableDayFragment().apply {
|
/*return TimetableDayFragment().apply {
|
||||||
|
|
|
@ -7,97 +7,42 @@ import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.FrameLayout
|
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.asynclayoutinflater.view.AsyncLayoutInflater
|
|
||||||
import androidx.core.view.setPadding
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import com.linkedin.android.tachyon.DayView
|
import com.linkedin.android.tachyon.DayView
|
||||||
import com.linkedin.android.tachyon.DayViewConfig
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import pl.szczodrzynski.edziennik.*
|
import pl.szczodrzynski.edziennik.*
|
||||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_TIMETABLE
|
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_TIMETABLE
|
||||||
import pl.szczodrzynski.edziennik.api.v2.LOGIN_TYPE_LIBRUS
|
import pl.szczodrzynski.edziennik.api.v2.LOGIN_TYPE_LIBRUS
|
||||||
import pl.szczodrzynski.edziennik.api.v2.events.task.EdziennikTask
|
import pl.szczodrzynski.edziennik.api.v2.events.task.EdziennikTask
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.LessonFull
|
import pl.szczodrzynski.edziennik.data.db.modules.timetable.LessonFull
|
||||||
|
import pl.szczodrzynski.edziennik.databinding.FragmentTimetableV2DayBinding
|
||||||
import pl.szczodrzynski.edziennik.databinding.TimetableLessonBinding
|
import pl.szczodrzynski.edziennik.databinding.TimetableLessonBinding
|
||||||
import pl.szczodrzynski.edziennik.databinding.TimetableNoTimetableBinding
|
|
||||||
import pl.szczodrzynski.edziennik.ui.dialogs.timetable.LessonDetailsDialog
|
import pl.szczodrzynski.edziennik.ui.dialogs.timetable.LessonDetailsDialog
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.timetable.v2.TimetableFragment.Companion.DEFAULT_END_HOUR
|
|
||||||
import pl.szczodrzynski.edziennik.ui.modules.timetable.v2.TimetableFragment.Companion.DEFAULT_START_HOUR
|
|
||||||
import pl.szczodrzynski.edziennik.utils.ListenerScrollView
|
|
||||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
import pl.szczodrzynski.navlib.getColorFromAttr
|
import pl.szczodrzynski.navlib.getColorFromAttr
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.coroutines.CoroutineContext
|
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
class TimetableDayFragment : Fragment(), CoroutineScope {
|
class TimetableDayFragment() : Fragment() {
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "TimetableDayFragment"
|
private const val TAG = "TimetableDayFragment"
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var app: App
|
private lateinit var app: App
|
||||||
private lateinit var activity: MainActivity
|
private lateinit var activity: MainActivity
|
||||||
private lateinit var inflater: AsyncLayoutInflater
|
private lateinit var b: FragmentTimetableV2DayBinding
|
||||||
|
|
||||||
private lateinit var job: Job
|
|
||||||
override val coroutineContext: CoroutineContext
|
|
||||||
get() = job + Dispatchers.Main
|
|
||||||
|
|
||||||
private lateinit var date: Date
|
private lateinit var date: Date
|
||||||
private var startHour = DEFAULT_START_HOUR
|
|
||||||
private var endHour = DEFAULT_END_HOUR
|
|
||||||
private var firstEventMinute = 24*60
|
|
||||||
|
|
||||||
// find SwipeRefreshLayout in the hierarchy
|
|
||||||
private val refreshLayout by lazy { view?.findParentById(R.id.refreshLayout) }
|
|
||||||
// the day ScrollView
|
|
||||||
private val dayScrollDelegate = lazy {
|
|
||||||
val dayScroll = ListenerScrollView(context!!)
|
|
||||||
dayScroll.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
|
|
||||||
dayScroll.setOnRefreshLayoutEnabledListener { enabled ->
|
|
||||||
refreshLayout?.isEnabled = enabled
|
|
||||||
}
|
|
||||||
dayScroll
|
|
||||||
}
|
|
||||||
private val dayScroll by dayScrollDelegate
|
|
||||||
// the lesson DayView
|
|
||||||
private val dayView by lazy {
|
|
||||||
val dayView = DayView(context!!, DayViewConfig(
|
|
||||||
startHour = startHour,
|
|
||||||
endHour = endHour,
|
|
||||||
dividerHeight = 1.dp,
|
|
||||||
halfHourHeight = 60.dp,
|
|
||||||
hourDividerColor = R.attr.hourDividerColor.resolveAttr(context),
|
|
||||||
halfHourDividerColor = R.attr.halfHourDividerColor.resolveAttr(context),
|
|
||||||
hourLabelWidth = 40.dp,
|
|
||||||
hourLabelMarginEnd = 10.dp,
|
|
||||||
eventMargin = 2.dp
|
|
||||||
), true)
|
|
||||||
dayView.setPadding(10.dp)
|
|
||||||
dayScroll.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
|
||||||
dayScroll.addView(dayView)
|
|
||||||
dayView
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
activity = (getActivity() as MainActivity?) ?: return null
|
activity = (getActivity() as MainActivity?) ?: return null
|
||||||
if (context == null)
|
if (context == null)
|
||||||
return null
|
return null
|
||||||
app = activity.application as App
|
app = activity.application as App
|
||||||
job = Job()
|
b = FragmentTimetableV2DayBinding.inflate(inflater)
|
||||||
this.inflater = AsyncLayoutInflater(context!!)
|
|
||||||
date = arguments?.getInt("date")?.let { Date.fromValue(it) } ?: Date.getToday()
|
date = arguments?.getInt("date")?.let { Date.fromValue(it) } ?: Date.getToday()
|
||||||
startHour = arguments?.getInt("startHour") ?: DEFAULT_START_HOUR
|
return b.root
|
||||||
endHour = arguments?.getInt("endHour") ?: DEFAULT_END_HOUR
|
|
||||||
return FrameLayout(activity).apply {
|
|
||||||
layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
@ -107,42 +52,45 @@ class TimetableDayFragment : Fragment(), CoroutineScope {
|
||||||
|
|
||||||
Log.d(TAG, "onViewCreated, date=$date")
|
Log.d(TAG, "onViewCreated, date=$date")
|
||||||
|
|
||||||
// observe lesson database
|
// Inflate a label view for each hour the day view will display
|
||||||
|
val hourLabelViews = ArrayList<View>()
|
||||||
|
for (i in b.day.startHour..b.day.endHour) {
|
||||||
|
val hourLabelView = layoutInflater.inflate(R.layout.timetable_hour_label, b.day, false) as TextView
|
||||||
|
hourLabelView.text = "$i:00"
|
||||||
|
hourLabelViews.add(hourLabelView)
|
||||||
|
}
|
||||||
|
b.day.setHourLabelViews(hourLabelViews)
|
||||||
|
|
||||||
app.db.timetableDao().getForDate(App.profileId, date).observe(this, Observer<List<LessonFull>> { lessons ->
|
app.db.timetableDao().getForDate(App.profileId, date).observe(this, Observer<List<LessonFull>> { lessons ->
|
||||||
processLessonList(lessons)
|
buildLessonViews(lessons)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processLessonList(lessons: List<LessonFull>) {
|
private fun buildLessonViews(lessons: List<LessonFull>) {
|
||||||
// no lessons - timetable not downloaded yet
|
|
||||||
if (lessons.isEmpty()) {
|
if (lessons.isEmpty()) {
|
||||||
inflater.inflate(R.layout.timetable_no_timetable, view as FrameLayout) { view, _, parent ->
|
b.dayScroll.visibility = View.GONE
|
||||||
parent?.removeAllViews()
|
b.noTimetableLayout.visibility = View.VISIBLE
|
||||||
parent?.addView(view)
|
b.noLessonsLayout.visibility = View.GONE
|
||||||
val b = TimetableNoTimetableBinding.bind(view)
|
val weekStart = date.clone().stepForward(0, 0, -date.weekDay).stringY_m_d
|
||||||
val weekStart = date.clone().stepForward(0, 0, -date.weekDay).stringY_m_d
|
b.noTimetableSync.onClick {
|
||||||
b.noTimetableSync.onClick {
|
it.isEnabled = false
|
||||||
it.isEnabled = false
|
EdziennikTask.syncProfile(
|
||||||
EdziennikTask.syncProfile(
|
profileId = App.profileId,
|
||||||
profileId = App.profileId,
|
viewIds = listOf(
|
||||||
viewIds = listOf(
|
DRAWER_ITEM_TIMETABLE to 0
|
||||||
DRAWER_ITEM_TIMETABLE to 0
|
),
|
||||||
),
|
arguments = JsonObject(
|
||||||
arguments = JsonObject(
|
"weekStart" to weekStart
|
||||||
"weekStart" to weekStart
|
)
|
||||||
)
|
).enqueue(activity)
|
||||||
).enqueue(activity)
|
|
||||||
}
|
|
||||||
b.noTimetableWeek.setText(R.string.timetable_no_timetable_week, weekStart)
|
|
||||||
}
|
}
|
||||||
|
b.noTimetableWeek.setText(R.string.timetable_no_timetable_week, weekStart)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// one lesson indicating a day without lessons
|
|
||||||
if (lessons.size == 1 && lessons[0].type == Lesson.TYPE_NO_LESSONS) {
|
if (lessons.size == 1 && lessons[0].type == Lesson.TYPE_NO_LESSONS) {
|
||||||
inflater.inflate(R.layout.timetable_no_lessons, view as FrameLayout) { view, _, parent ->
|
b.dayScroll.visibility = View.GONE
|
||||||
parent?.removeAllViews()
|
b.noTimetableLayout.visibility = View.GONE
|
||||||
parent?.addView(view)
|
b.noLessonsLayout.visibility = View.VISIBLE
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,37 +101,23 @@ class TimetableDayFragment : Fragment(), CoroutineScope {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear the root view and add the ScrollView
|
b.dayScroll.visibility = View.VISIBLE
|
||||||
(view as FrameLayout).removeAllViews()
|
b.noTimetableLayout.visibility = View.GONE
|
||||||
(view as FrameLayout).addView(dayScroll)
|
b.noLessonsLayout.visibility = View.GONE
|
||||||
|
|
||||||
// Inflate a label view for each hour the day view will display
|
var firstEventMinute = 24*60
|
||||||
val hourLabelViews = ArrayList<View>()
|
|
||||||
for (i in dayView.startHour..dayView.endHour) {
|
|
||||||
val hourLabelView = layoutInflater.inflate(R.layout.timetable_hour_label, dayView, false) as TextView
|
|
||||||
hourLabelView.text = "$i:00"
|
|
||||||
hourLabelViews.add(hourLabelView)
|
|
||||||
}
|
|
||||||
dayView.setHourLabelViews(hourLabelViews)
|
|
||||||
|
|
||||||
buildLessonViews(lessons)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildLessonViews(lessons: List<LessonFull>) {
|
|
||||||
if (!isAdded)
|
|
||||||
return
|
|
||||||
|
|
||||||
val eventViews = mutableListOf<View>()
|
val eventViews = mutableListOf<View>()
|
||||||
val eventTimeRanges = mutableListOf<DayView.EventTimeRange>()
|
val eventTimeRanges = mutableListOf<DayView.EventTimeRange>()
|
||||||
|
|
||||||
// Reclaim all of the existing event views so we can reuse them if needed, this process
|
// Reclaim all of the existing event views so we can reuse them if needed, this process
|
||||||
// can be useful if your day view is hosted in a recycler view for example
|
// can be useful if your day view is hosted in a recycler view for example
|
||||||
val recycled = dayView.removeEventViews()
|
val recycled = b.day.removeEventViews()
|
||||||
var remaining = recycled?.size ?: 0
|
var remaining = recycled?.size ?: 0
|
||||||
|
|
||||||
val arrowRight = " → "
|
val arrowRight = " → "
|
||||||
val bullet = " • "
|
val bullet = " • "
|
||||||
val colorSecondary = android.R.attr.textColorSecondary.resolveAttr(activity)
|
val colorSecondary = getColorFromAttr(activity, android.R.attr.textColorSecondary)
|
||||||
|
|
||||||
for (lesson in lessons) {
|
for (lesson in lessons) {
|
||||||
val startTime = lesson.displayStartTime ?: continue
|
val startTime = lesson.displayStartTime ?: continue
|
||||||
|
@ -193,7 +127,7 @@ class TimetableDayFragment : Fragment(), CoroutineScope {
|
||||||
|
|
||||||
// Try to recycle an existing event view if there are enough left, otherwise inflate
|
// Try to recycle an existing event view if there are enough left, otherwise inflate
|
||||||
// a new one
|
// a new one
|
||||||
val eventView = (if (remaining > 0) recycled?.get(--remaining) else layoutInflater.inflate(R.layout.timetable_lesson, dayView, false))
|
val eventView = (if (remaining > 0) recycled?.get(--remaining) else layoutInflater.inflate(R.layout.timetable_lesson, b.day, false))
|
||||||
?: continue
|
?: continue
|
||||||
val lb = TimetableLessonBinding.bind(eventView)
|
val lb = TimetableLessonBinding.bind(eventView)
|
||||||
eventViews += eventView
|
eventViews += eventView
|
||||||
|
@ -340,16 +274,9 @@ class TimetableDayFragment : Fragment(), CoroutineScope {
|
||||||
eventTimeRanges.add(DayView.EventTimeRange(startMinute, endMinute))
|
eventTimeRanges.add(DayView.EventTimeRange(startMinute, endMinute))
|
||||||
}
|
}
|
||||||
|
|
||||||
dayView.setEventViews(eventViews, eventTimeRanges)
|
val minuteHeight = (b.day.getHourTop(1) - b.day.getHourTop(0)).toFloat() / 60f
|
||||||
val firstEventTop = (firstEventMinute - dayView.startHour * 60) * dayView.minuteHeight
|
val firstEventTop = (firstEventMinute - b.day.startHour * 60) * minuteHeight
|
||||||
dayScroll.scrollTo(0, firstEventTop.toInt())
|
b.day.setEventViews(eventViews, eventTimeRanges)
|
||||||
}
|
b.dayScroll.scrollTo(0, firstEventTop.toInt())
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
if (dayScrollDelegate.isInitialized()) {
|
|
||||||
val firstEventTop = (firstEventMinute - dayView.startHour * 60) * dayView.minuteHeight
|
|
||||||
dayScroll.scrollTo(0, firstEventTop.toInt())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) Kuba Szczodrzyński 2019-11-16.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package pl.szczodrzynski.edziennik.utils
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.MotionEvent
|
|
||||||
import android.widget.ScrollView
|
|
||||||
|
|
||||||
class ListenerScrollView(
|
|
||||||
context: Context,
|
|
||||||
attrs: AttributeSet? = null
|
|
||||||
) : ScrollView(context, attrs) {
|
|
||||||
|
|
||||||
private var onScrollChangedListener: ((v: ListenerScrollView, scrollX: Int, scrollY: Int, oldScrollX: Int, oldScrollY: Int) -> Unit)? = null
|
|
||||||
private var onRefreshLayoutEnabledListener: ((enabled: Boolean) -> Unit)? = null
|
|
||||||
private var refreshLayoutEnabled = true
|
|
||||||
|
|
||||||
init {
|
|
||||||
setOnTouchListener { _, event ->
|
|
||||||
if (event.action == MotionEvent.ACTION_UP) {
|
|
||||||
refreshLayoutEnabled = scrollY < 10
|
|
||||||
onRefreshLayoutEnabledListener?.invoke(refreshLayoutEnabled)
|
|
||||||
}
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) {
|
|
||||||
onScrollChangedListener?.invoke(this, l, t, oldl, oldt)
|
|
||||||
if (t > 10 && refreshLayoutEnabled) {
|
|
||||||
refreshLayoutEnabled = false
|
|
||||||
onRefreshLayoutEnabledListener?.invoke(refreshLayoutEnabled)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setOnScrollChangedListener(l: ((v: ListenerScrollView, scrollX: Int, scrollY: Int, oldScrollX: Int, oldScrollY: Int) -> Unit)?) {
|
|
||||||
onScrollChangedListener = l
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setOnRefreshLayoutEnabledListener(l: ((enabled: Boolean) -> Unit)?) {
|
|
||||||
onRefreshLayoutEnabledListener = l
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -75,22 +75,21 @@ class TextInputDropDown : TextInputEditText {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun select(item: Item): Item? {
|
fun select(item: Item) {
|
||||||
selected = item
|
selected = item
|
||||||
updateText()
|
updateText()
|
||||||
return item
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun select(id: Long?): Item? {
|
fun select(id: Long?) {
|
||||||
return items.singleOrNull { it.id == id }?.let { select(it) }
|
items.singleOrNull { it.id == id }?.let { select(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun select(tag: Any?): Item? {
|
fun select(tag: Any?) {
|
||||||
return items.singleOrNull { it.tag == tag }?.let { select(it) }
|
items.singleOrNull { it.tag == tag }?.let { select(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun select(index: Int): Item? {
|
fun select(index: Int) {
|
||||||
return items.getOrNull(index)?.let { select(it) }
|
items.getOrNull(index)?.let { select(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deselect(): TextInputDropDown {
|
fun deselect(): TextInputDropDown {
|
||||||
|
|
|
@ -95,7 +95,6 @@ public class AppConfig {
|
||||||
public String updateUrl = "";
|
public String updateUrl = "";
|
||||||
public String updateFilename = "";
|
public String updateFilename = "";
|
||||||
public boolean updateMandatory = false;
|
public boolean updateMandatory = false;
|
||||||
public boolean updateDirect = false;
|
|
||||||
|
|
||||||
public boolean webPushEnabled = false;
|
public boolean webPushEnabled = false;
|
||||||
|
|
||||||
|
|
|
@ -173,8 +173,7 @@ public class WidgetTimetableListProvider implements RemoteViewsService.RemoteVie
|
||||||
intent.putExtra("endTime", lesson.endTime.getStringValue());
|
intent.putExtra("endTime", lesson.endTime.getStringValue());
|
||||||
views.setOnClickFillInIntent(R.id.widgetTimetableRoot, intent);
|
views.setOnClickFillInIntent(R.id.widgetTimetableRoot, intent);
|
||||||
|
|
||||||
if (lesson.startTime != null && lesson.endTime != null)
|
views.setTextViewText(R.id.widgetTimetableTime, lesson.startTime.getStringHM() + " - " + lesson.endTime.getStringHM());
|
||||||
views.setTextViewText(R.id.widgetTimetableTime, lesson.startTime.getStringHM() + " - " + lesson.endTime.getStringHM());
|
|
||||||
|
|
||||||
views.setViewVisibility(R.id.widgetTimetableEvent1, View.GONE);
|
views.setViewVisibility(R.id.widgetTimetableEvent1, View.GONE);
|
||||||
views.setViewVisibility(R.id.widgetTimetableEvent2, View.GONE);
|
views.setViewVisibility(R.id.widgetTimetableEvent2, View.GONE);
|
||||||
|
|
|
@ -4,17 +4,11 @@
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
|
||||||
|
|
||||||
<ScrollView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:focusableInTouchMode="true"
|
android:focusableInTouchMode="true"
|
||||||
android:padding="24dp">
|
android:padding="24dp">
|
||||||
|
@ -52,63 +46,41 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:hint="@string/dialog_event_manual_team">
|
android:hint="@string/dialog_event_manual_team">
|
||||||
|
|
||||||
<pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
<pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||||
android:id="@+id/teamDropdown"
|
android:id="@+id/teamDropdown"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:enabled="false"
|
android:enabled="false"
|
||||||
tools:text="2b3T" />
|
tools:text="2b3T"/>
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/shareSwitch"
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/dialog_event_manual_share_enabled" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/shareDetails"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/dialog_event_manual_share_first_notice"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:baselineAligned="false"
|
android:hint="@string/dialog_event_manual_subject">
|
||||||
android:orientation="horizontal">
|
<pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||||
|
android:id="@+id/subjectDropdown"
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
android:layout_width="match_parent"
|
||||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:enabled="false"
|
||||||
android:hint="@string/dialog_event_manual_type">
|
tools:text="2b3T"/>
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/typeDropdown"
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:enabled="false"
|
android:layout_marginTop="8dp"
|
||||||
tools:text="2b3T" />
|
android:hint="@string/dialog_event_manual_teacher">
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
<pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||||
|
android:id="@+id/teacherDropdown"
|
||||||
<FrameLayout
|
android:layout_width="match_parent"
|
||||||
android:id="@+id/typeColor"
|
android:layout_height="wrap_content"
|
||||||
android:layout_width="40dp"
|
android:enabled="false"
|
||||||
android:layout_height="40dp"
|
tools:text="2b3T"/>
|
||||||
android:layout_gravity="center_vertical"
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
android:layout_marginTop="2dp"
|
|
||||||
android:layout_marginStart="8dp"
|
|
||||||
android:layout_marginLeft="8dp"
|
|
||||||
android:background="@drawable/bg_circle"
|
|
||||||
android:foreground="?selectableItemBackgroundBorderless" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
|
||||||
|
@ -126,64 +98,5 @@
|
||||||
tools:text="2b3T" />
|
tools:text="2b3T" />
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<com.mikepenz.iconics.view.IconicsCheckableTextView
|
|
||||||
android:id="@+id/showMore"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingTop="16dp"
|
|
||||||
android:paddingBottom="16dp"
|
|
||||||
android:text="@string/dialog_event_manual_more_options"
|
|
||||||
android:background="?selectableItemBackground"
|
|
||||||
|
|
||||||
app:iiv_end_icon="cmd-chevron-down"
|
|
||||||
app:iiv_end_color="?android:textColorSecondary"
|
|
||||||
app:iiv_end_size="16dp"
|
|
||||||
|
|
||||||
app:iiv_end_checked_icon="cmd-chevron-up"
|
|
||||||
app:iiv_end_checked_color="?android:textColorSecondary"
|
|
||||||
app:iiv_end_checked_size="16dp"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/moreLayout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:visibility="gone"
|
|
||||||
tools:visibility="visible">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:hint="@string/dialog_event_manual_subject">
|
|
||||||
|
|
||||||
<pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
|
||||||
android:id="@+id/subjectDropdown"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:enabled="false"
|
|
||||||
tools:text="2b3T" />
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:hint="@string/dialog_event_manual_teacher">
|
|
||||||
|
|
||||||
<pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
|
||||||
android:id="@+id/teacherDropdown"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:enabled="false"
|
|
||||||
tools:text="2b3T" />
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
@ -21,207 +21,217 @@
|
||||||
<variable name="oldTeamName" type="String" />
|
<variable name="oldTeamName" type="String" />
|
||||||
<variable name="teamName" type="String" />
|
<variable name="teamName" type="String" />
|
||||||
</data>
|
</data>
|
||||||
<ScrollView
|
<LinearLayout
|
||||||
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:padding="24dp">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="24dp">
|
android:orientation="horizontal"
|
||||||
|
android:baselineAligned="false">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:orientation="vertical"
|
||||||
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:layout_gravity="center_vertical"
|
||||||
android:baselineAligned="false">
|
android:layout_weight="1">
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:layout_weight="1">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@{oldSubjectName}"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:textAppearance="@style/NavView.TextView.Medium"
|
|
||||||
android:textColor="?android:textColorTertiary"
|
|
||||||
android:visibility="@{oldSubjectName == null ? View.GONE : View.VISIBLE}"
|
|
||||||
app:strikeThrough="@{true}"
|
|
||||||
tools:text="pracownia urządzeń techniki komputerowej" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@{subjectName}"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:textAppearance="@style/NavView.TextView.Title"
|
|
||||||
android:visibility="@{subjectName == null ? View.GONE : View.VISIBLE}"
|
|
||||||
tools:text="pracownia urządzeń techniki komputerowej" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/lessonDate"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:textAppearance="@style/NavView.TextView.Subtitle"
|
|
||||||
tools:text="czwartek, 14 listopada 2019"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:gravity="center">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAppearance="@style/NavView.TextView.Helper"
|
|
||||||
android:text="@string/dialog_lesson_details_number"
|
|
||||||
android:visibility="@{lesson.displayLessonNumber == null ? View.GONE : View.VISIBLE}"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:fontFamily="sans-serif-light"
|
|
||||||
android:text="@{lesson.displayLessonNumber.toString()}"
|
|
||||||
android:textSize="36sp"
|
|
||||||
android:visibility="@{lesson.displayLessonNumber == null ? View.GONE : View.VISIBLE}"
|
|
||||||
tools:text="4" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@{lesson.displayStartTime.stringHM + ` - ` + lesson.displayEndTime.stringHM}"
|
|
||||||
tools:text="14:55 - 15:40" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/shiftedLayout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:baselineAligned="false"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/shiftedText"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="italic"
|
|
||||||
tools:text="Lekcja przeniesiona na czwartek, 17 października" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/shiftedGoTo"
|
|
||||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Przejdź" />
|
android:text="@{oldSubjectName}"
|
||||||
|
android:textIsSelectable="true"
|
||||||
|
android:textAppearance="@style/NavView.TextView.Medium"
|
||||||
|
android:textColor="?android:textColorTertiary"
|
||||||
|
android:visibility="@{oldSubjectName == null ? View.GONE : View.VISIBLE}"
|
||||||
|
app:strikeThrough="@{true}"
|
||||||
|
tools:text="pracownia urządzeń techniki komputerowej" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@{subjectName}"
|
||||||
|
android:textIsSelectable="true"
|
||||||
|
android:textAppearance="@style/NavView.TextView.Title"
|
||||||
|
android:visibility="@{subjectName == null ? View.GONE : View.VISIBLE}"
|
||||||
|
tools:text="pracownia urządzeń techniki komputerowej" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/lessonDate"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textIsSelectable="true"
|
||||||
|
android:textAppearance="@style/NavView.TextView.Subtitle"
|
||||||
|
tools:text="czwartek, 14 listopada 2019"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:orientation="vertical"
|
||||||
android:textAppearance="@style/NavView.TextView.Helper"
|
android:gravity="center">
|
||||||
android:text="@string/dialog_lesson_details_teacher"
|
|
||||||
android:visibility="@{teacherName != null || oldTeacherName != null ? View.VISIBLE : View.GONE}"/>
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAppearance="@style/NavView.TextView.Helper"
|
|
||||||
android:text="@{oldTeacherName}"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:visibility="@{oldTeacherName != null ? View.VISIBLE : View.GONE}"
|
|
||||||
app:strikeThrough="@{true}"
|
|
||||||
tools:text="Janósz Kowalski" />
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@{teacherName}"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:visibility="@{teacherName != null ? View.VISIBLE : View.GONE}"
|
|
||||||
tools:text="Janósz Kowalski" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:textAppearance="@style/NavView.TextView.Helper"
|
||||||
android:textAppearance="@style/NavView.TextView.Helper"
|
android:text="@string/dialog_lesson_details_number"
|
||||||
android:text="@string/dialog_lesson_details_classroom"
|
android:visibility="@{lesson.displayLessonNumber == null ? View.GONE : View.VISIBLE}"/>
|
||||||
android:visibility="@{classroom != null || oldClassroom != null ? View.VISIBLE : View.GONE}"/>
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAppearance="@style/NavView.TextView.Helper"
|
|
||||||
android:text="@{oldClassroom}"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:visibility="@{oldClassroom != null ? View.VISIBLE : View.GONE}"
|
|
||||||
app:strikeThrough="@{true}"
|
|
||||||
tools:text="013 informatyczna" />
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@{classroom}"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:visibility="@{classroom != null ? View.VISIBLE : View.GONE}"
|
|
||||||
tools:text="013 informatyczna" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:fontFamily="sans-serif-light"
|
||||||
android:textAppearance="@style/NavView.TextView.Helper"
|
android:text="@{lesson.displayLessonNumber.toString()}"
|
||||||
android:text="@string/dialog_lesson_details_team"
|
android:textSize="36sp"
|
||||||
android:visibility="@{teamName != null || oldTeamName != null ? View.VISIBLE : View.GONE}"/>
|
android:visibility="@{lesson.displayLessonNumber == null ? View.GONE : View.VISIBLE}"
|
||||||
<TextView
|
tools:text="4" />
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAppearance="@style/NavView.TextView.Helper"
|
|
||||||
android:text="@{oldTeamName}"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:visibility="@{oldTeamName != null ? View.VISIBLE : View.GONE}"
|
|
||||||
app:strikeThrough="@{true}"
|
|
||||||
tools:text="013 informatyczna" />
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@{teamName}"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:visibility="@{teamName != null ? View.VISIBLE : View.GONE}"
|
|
||||||
tools:text="013 informatyczna" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:text="@{lesson.displayStartTime.stringHM + ` - ` + lesson.displayEndTime.stringHM}"
|
||||||
android:textAppearance="@style/NavView.TextView.Helper"
|
tools:text="14:55 - 15:40" />
|
||||||
android:visibility="@{App.devMode ? View.VISIBLE : View.GONE}"
|
|
||||||
android:text="@string/dialog_lesson_details_id" />
|
|
||||||
|
|
||||||
<TextView
|
</LinearLayout>
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="0dp"
|
|
||||||
android:text="@{Long.toString(lesson.id)}"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:visibility="@{App.devMode ? View.VISIBLE : View.GONE}"
|
|
||||||
tools:text="12345" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</ScrollView>
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/shiftedLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:baselineAligned="false"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/shiftedText"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="italic"
|
||||||
|
tools:text="Lekcja przeniesiona na czwartek, 17 października" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/shiftedGoTo"
|
||||||
|
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Przejdź" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:textAppearance="@style/NavView.TextView.Helper"
|
||||||
|
android:text="@string/dialog_lesson_details_teacher"
|
||||||
|
android:visibility="@{teacherName != null || oldTeacherName != null ? View.VISIBLE : View.GONE}"/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@style/NavView.TextView.Helper"
|
||||||
|
android:text="@{oldTeacherName}"
|
||||||
|
android:textIsSelectable="true"
|
||||||
|
android:visibility="@{oldTeacherName != null ? View.VISIBLE : View.GONE}"
|
||||||
|
app:strikeThrough="@{true}"
|
||||||
|
tools:text="Janósz Kowalski" />
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@{teacherName}"
|
||||||
|
android:textIsSelectable="true"
|
||||||
|
android:visibility="@{teacherName != null ? View.VISIBLE : View.GONE}"
|
||||||
|
tools:text="Janósz Kowalski" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:textAppearance="@style/NavView.TextView.Helper"
|
||||||
|
android:text="@string/dialog_lesson_details_classroom"
|
||||||
|
android:visibility="@{classroom != null || oldClassroom != null ? View.VISIBLE : View.GONE}"/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@style/NavView.TextView.Helper"
|
||||||
|
android:text="@{oldClassroom}"
|
||||||
|
android:textIsSelectable="true"
|
||||||
|
android:visibility="@{oldClassroom != null ? View.VISIBLE : View.GONE}"
|
||||||
|
app:strikeThrough="@{true}"
|
||||||
|
tools:text="013 informatyczna" />
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@{classroom}"
|
||||||
|
android:textIsSelectable="true"
|
||||||
|
android:visibility="@{classroom != null ? View.VISIBLE : View.GONE}"
|
||||||
|
tools:text="013 informatyczna" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:textAppearance="@style/NavView.TextView.Helper"
|
||||||
|
android:text="@string/dialog_lesson_details_team"
|
||||||
|
android:visibility="@{teamName != null || oldTeamName != null ? View.VISIBLE : View.GONE}"/>
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="@style/NavView.TextView.Helper"
|
||||||
|
android:text="@{oldTeamName}"
|
||||||
|
android:textIsSelectable="true"
|
||||||
|
android:visibility="@{oldTeamName != null ? View.VISIBLE : View.GONE}"
|
||||||
|
app:strikeThrough="@{true}"
|
||||||
|
tools:text="013 informatyczna" />
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@{teamName}"
|
||||||
|
android:textIsSelectable="true"
|
||||||
|
android:visibility="@{teamName != null ? View.VISIBLE : View.GONE}"
|
||||||
|
tools:text="013 informatyczna" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:textAppearance="@style/NavView.TextView.Helper"
|
||||||
|
android:visibility="@{App.devMode ? View.VISIBLE : View.GONE}"
|
||||||
|
android:text="@string/dialog_lesson_details_id" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="0dp"
|
||||||
|
android:text="@{Long.toString(lesson.id)}"
|
||||||
|
android:textIsSelectable="true"
|
||||||
|
android:visibility="@{App.devMode ? View.VISIBLE : View.GONE}"
|
||||||
|
tools:text="12345" />
|
||||||
|
|
||||||
|
<!--<androidx.core.widget.NestedScrollView
|
||||||
|
android:id="@+id/gradeHistoryNest"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="@{historyVisible ? View.VISIBLE : View.GONE}">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/gradeHistoryList"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:listitem="@layout/row_grades_list_item" />
|
||||||
|
|
||||||
|
</androidx.core.widget.NestedScrollView>-->
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
@ -2,96 +2,89 @@
|
||||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
<FrameLayout
|
||||||
<pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator
|
|
||||||
android:id="@+id/refreshLayout"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<FrameLayout
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
android:id="@+id/timetableLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
tools:visibility="gone">
|
||||||
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:id="@+id/timetableLayout"
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?colorSurface"
|
||||||
|
style="@style/Widget.MaterialComponents.AppBarLayout.Surface">
|
||||||
|
|
||||||
|
<com.nshmura.recyclertablayout.RecyclerTabLayout
|
||||||
|
android:id="@+id/tabLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:background="@color/colorSurface_6dp"
|
||||||
|
app:rtl_tabTextAppearance="@style/rtl_RecyclerTabLayout.Tab"
|
||||||
|
app:rtl_tabIndicatorColor="?colorPrimary"
|
||||||
|
app:rtl_tabMinWidth="90dp"
|
||||||
|
app:rtl_tabMaxWidth="300dp"
|
||||||
|
app:rtl_tabSelectedTextColor="?colorPrimary"
|
||||||
|
app:rtl_tabPaddingStart="16dp"
|
||||||
|
app:rtl_tabPaddingEnd="16dp"
|
||||||
|
app:rtl_tabPaddingTop="12dp"
|
||||||
|
app:rtl_tabPaddingBottom="12dp"/>
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<androidx.viewpager.widget.ViewPager
|
||||||
|
android:id="@+id/viewPager"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:visibility="gone">
|
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
style="@style/Widget.MaterialComponents.AppBarLayout.Surface"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="?colorSurface">
|
|
||||||
|
|
||||||
<com.nshmura.recyclertablayout.RecyclerTabLayout
|
<LinearLayout
|
||||||
android:id="@+id/tabLayout"
|
android:id="@+id/timetableNotPublicLayout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="48dp"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/colorSurface_6dp"
|
android:orientation="vertical"
|
||||||
app:rtl_tabIndicatorColor="?colorPrimary"
|
android:visibility="gone"
|
||||||
app:rtl_tabMaxWidth="300dp"
|
android:gravity="center"
|
||||||
app:rtl_tabMinWidth="90dp"
|
tools:visibility="visible">
|
||||||
app:rtl_tabPaddingBottom="12dp"
|
|
||||||
app:rtl_tabPaddingEnd="16dp"
|
|
||||||
app:rtl_tabPaddingStart="16dp"
|
|
||||||
app:rtl_tabPaddingTop="12dp"
|
|
||||||
app:rtl_tabSelectedTextColor="?colorPrimary"
|
|
||||||
app:rtl_tabTextAppearance="@style/rtl_RecyclerTabLayout.Tab" />
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
|
||||||
|
|
||||||
<androidx.viewpager.widget.ViewPager
|
<ImageView
|
||||||
android:id="@+id/viewPager"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="match_parent"
|
app:srcCompat="@drawable/ic_no_timetable" />
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
android:text="@string/timetable_not_public_title"
|
||||||
|
android:textSize="24sp" />
|
||||||
|
|
||||||
<LinearLayout
|
<TextView
|
||||||
android:id="@+id/timetableNotPublicLayout"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginStart="32dp"
|
||||||
|
android:layout_marginEnd="32dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical"
|
android:text="@string/timetable_not_public_text"
|
||||||
android:visibility="gone"
|
android:textSize="16sp" />
|
||||||
tools:visibility="visible">
|
|
||||||
|
|
||||||
<ImageView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:srcCompat="@drawable/ic_no_timetable" />
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginStart="32dp"
|
||||||
|
android:layout_marginEnd="32dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/timetable_not_public_hint"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
<TextView
|
</LinearLayout>
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:fontFamily="sans-serif-light"
|
|
||||||
android:text="@string/timetable_not_public_title"
|
|
||||||
android:textSize="24sp" />
|
|
||||||
|
|
||||||
<TextView
|
</FrameLayout>
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="32dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginEnd="32dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/timetable_not_public_text"
|
|
||||||
android:textSize="16sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="32dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginEnd="32dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/timetable_not_public_hint"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
</pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator>
|
|
||||||
</layout>
|
</layout>
|
|
@ -28,5 +28,126 @@
|
||||||
tools:visibility="gone"/>
|
tools:visibility="gone"/>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/noLessonsLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:gravity="center"
|
||||||
|
tools:visibility="gone">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:srcCompat="@drawable/ic_timetable" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
android:text="@string/timetable_no_lessons_title"
|
||||||
|
android:textSize="24sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/freeDayLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:gravity="center"
|
||||||
|
tools:visibility="gone">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:srcCompat="@drawable/ic_sunbed" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
android:text="@string/timetable_free_day_title"
|
||||||
|
android:textSize="24sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="@string/timetable_free_day_text"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/freeDayText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="32dp"
|
||||||
|
android:layout_marginEnd="32dp"
|
||||||
|
android:gravity="center"
|
||||||
|
tools:text="Dzień wolny dla szkoły z puli dyrektorskiej z okazji obchodów Światowego Dnia Wtorku w mieście Poznań i na przedmieśiach"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/freeDayShowTimetable"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="@string/timetable_free_day_show" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/noTimetableLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:gravity="center"
|
||||||
|
tools:visibility="visible">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:srcCompat="@drawable/ic_sync" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
android:text="@string/timetable_no_timetable_title"
|
||||||
|
android:textSize="24sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:layout_marginStart="32dp"
|
||||||
|
android:layout_marginEnd="32dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/timetable_no_timetable_text"
|
||||||
|
android:textSize="16sp" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/noTimetableSync"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:text="@string/timetable_no_timetable_sync" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/noTimetableWeek"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:text="@string/timetable_no_timetable_week"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textStyle="italic"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
</layout>
|
</layout>
|
|
@ -1,47 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
~ Copyright (c) Kuba Szczodrzyński 2019-11-15.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/freeDayLayout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:gravity="center"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:drawableTop="@drawable/ic_sunbed"
|
|
||||||
android:drawablePadding="16dp"
|
|
||||||
android:fontFamily="sans-serif-light"
|
|
||||||
android:text="@string/timetable_free_day_title"
|
|
||||||
android:textSize="24sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:text="@string/timetable_free_day_text"
|
|
||||||
android:textSize="14sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/freeDayText"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="32dp"
|
|
||||||
android:layout_marginEnd="32dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textSize="16sp"
|
|
||||||
tools:text="Dzień wolny dla szkoły z puli dyrektorskiej z okazji obchodów Światowego Dnia Wtorku w mieście Poznań i na przedmieśiach" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/freeDayShowTimetable"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:text="@string/timetable_free_day_show" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
|
@ -1,14 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
~ Copyright (c) Kuba Szczodrzyński 2019-11-15.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:drawableTop="@drawable/ic_timetable"
|
|
||||||
android:drawablePadding="16dp"
|
|
||||||
android:fontFamily="sans-serif-light"
|
|
||||||
android:text="@string/timetable_no_lessons_title"
|
|
||||||
android:textSize="24sp" />
|
|
|
@ -1,50 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
~ Copyright (c) Kuba Szczodrzyński 2019-11-15.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/noTimetableLayout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:gravity="center"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:drawableTop="@drawable/ic_sync"
|
|
||||||
android:drawablePadding="16dp"
|
|
||||||
android:fontFamily="sans-serif-light"
|
|
||||||
android:text="@string/timetable_no_timetable_title"
|
|
||||||
android:textSize="24sp" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="32dp"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:layout_marginEnd="32dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/timetable_no_timetable_text"
|
|
||||||
android:textSize="16sp" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/noTimetableSync"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:text="@string/timetable_no_timetable_sync" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/noTimetableWeek"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:textStyle="italic"
|
|
||||||
tools:text="@string/timetable_no_timetable_week" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
</layout>
|
|
|
@ -72,12 +72,6 @@
|
||||||
<string name="error_173" translatable="false">ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_REVOKED</string>
|
<string name="error_173" translatable="false">ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_REVOKED</string>
|
||||||
<string name="error_174" translatable="false">ERROR_LIBRUS_SYNERGIA_OTHER</string>
|
<string name="error_174" translatable="false">ERROR_LIBRUS_SYNERGIA_OTHER</string>
|
||||||
<string name="error_175" translatable="false">ERROR_LIBRUS_SYNERGIA_MAINTENANCE</string>
|
<string name="error_175" translatable="false">ERROR_LIBRUS_SYNERGIA_MAINTENANCE</string>
|
||||||
<string name="error_176" translatable="false">ERROR_LIBRUS_MESSAGES_MAINTENANCE</string>
|
|
||||||
<string name="error_177" translatable="false">ERROR_LIBRUS_MESSAGES_ERROR</string>
|
|
||||||
<string name="error_178" translatable="false">ERROR_LIBRUS_MESSAGES_OTHER</string>
|
|
||||||
<string name="error_179" translatable="false">ERROR_LOGIN_LIBRUS_MESSAGES_INVALID_LOGIN</string>
|
|
||||||
<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_201" translatable="false">ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN</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>
|
<string name="error_202" translatable="false">ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD</string>
|
||||||
|
@ -171,7 +165,7 @@
|
||||||
<string name="error_127_reason">Wymagana akceptacja regulaminu</string>
|
<string name="error_127_reason">Wymagana akceptacja regulaminu</string>
|
||||||
<string name="error_128_reason">Błąd zmiany hasła</string>
|
<string name="error_128_reason">Błąd zmiany hasła</string>
|
||||||
<string name="error_129_reason">Wymagana zmiana hasła</string>
|
<string name="error_129_reason">Wymagana zmiana hasła</string>
|
||||||
<string name="error_130_reason">Librus API: nieprawidłowe dane logowania</string>
|
<string name="error_130_reason">Nieprawidłowe dane logowania</string>
|
||||||
<string name="error_131_reason">Inny błąd logowania do API</string>
|
<string name="error_131_reason">Inny błąd logowania do API</string>
|
||||||
<string name="error_132_reason">Brak tokenu CSRF</string>
|
<string name="error_132_reason">Brak tokenu CSRF</string>
|
||||||
<string name="error_133_reason">Konto LIBRUS nie zostało aktywowane</string>
|
<string name="error_133_reason">Konto LIBRUS nie zostało aktywowane</string>
|
||||||
|
@ -212,13 +206,7 @@
|
||||||
<string name="error_172_reason">ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_INVALID</string>
|
<string name="error_172_reason">ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_INVALID</string>
|
||||||
<string name="error_173_reason">ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_REVOKED</string>
|
<string name="error_173_reason">ERROR_LOGIN_LIBRUS_PORTAL_REFRESH_REVOKED</string>
|
||||||
<string name="error_174_reason">ERROR_LIBRUS_SYNERGIA_OTHER</string>
|
<string name="error_174_reason">ERROR_LIBRUS_SYNERGIA_OTHER</string>
|
||||||
<string name="error_175_reason">Librus Synergia: przerwa techniczna</string>
|
<string name="error_175_reason">ERROR_LIBRUS_SYNERGIA_MAINTENANCE</string>
|
||||||
<string name="error_176_reason">Librus Wiadomości: przerwa techniczna</string>
|
|
||||||
<string name="error_177_reason">ERROR_LIBRUS_MESSAGES_ERROR</string>
|
|
||||||
<string name="error_178_reason">ERROR_LIBRUS_MESSAGES_OTHER</string>
|
|
||||||
<string name="error_179_reason">Librus Wiadomości: nieprawidłowe dane logowania</string>
|
|
||||||
<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_201_reason">ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN</string>
|
<string name="error_201_reason">ERROR_LOGIN_MOBIDZIENNIK_WEB_INVALID_LOGIN</string>
|
||||||
<string name="error_202_reason">ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD</string>
|
<string name="error_202_reason">ERROR_LOGIN_MOBIDZIENNIK_WEB_OLD_PASSWORD</string>
|
||||||
|
|
|
@ -1026,6 +1026,4 @@
|
||||||
<string name="snackbar_error_text">Wystąpił błąd</string>
|
<string name="snackbar_error_text">Wystąpił błąd</string>
|
||||||
<string name="dialog_sync_view_list_title">Synchronizacja ręczna</string>
|
<string name="dialog_sync_view_list_title">Synchronizacja ręczna</string>
|
||||||
<string name="timetable_no_subject_name">(brak nazwy)</string>
|
<string name="timetable_no_subject_name">(brak nazwy)</string>
|
||||||
<string name="dialog_event_manual_more_options">Więcej opcji</string>
|
|
||||||
<string name="edziennik_progress_endpoint_grade_comments">Pobieranie komentarzy ocen...</string>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -101,8 +101,6 @@
|
||||||
<item name="timetable_lesson_change_color">#ffb300</item>
|
<item name="timetable_lesson_change_color">#ffb300</item>
|
||||||
<item name="timetable_lesson_shifted_source_color">#A1887F</item>
|
<item name="timetable_lesson_shifted_source_color">#A1887F</item>
|
||||||
<item name="timetable_lesson_shifted_target_color">#4caf50</item>
|
<item name="timetable_lesson_shifted_target_color">#4caf50</item>
|
||||||
<item name="hourDividerColor">#b0b0b0</item>
|
|
||||||
<item name="halfHourDividerColor">#e0e0e0</item>
|
|
||||||
</style>
|
</style>
|
||||||
<style name="AppTheme.Dark" parent="NavView.Dark">
|
<style name="AppTheme.Dark" parent="NavView.Dark">
|
||||||
<item name="colorPrimary">#64b5f6</item>
|
<item name="colorPrimary">#64b5f6</item>
|
||||||
|
@ -133,8 +131,6 @@
|
||||||
<item name="timetable_lesson_change_color">#ffb300</item>
|
<item name="timetable_lesson_change_color">#ffb300</item>
|
||||||
<item name="timetable_lesson_shifted_source_color">#A1887F</item>
|
<item name="timetable_lesson_shifted_source_color">#A1887F</item>
|
||||||
<item name="timetable_lesson_shifted_target_color">#4caf50</item>
|
<item name="timetable_lesson_shifted_target_color">#4caf50</item>
|
||||||
<item name="hourDividerColor">#7fffffff</item>
|
|
||||||
<item name="halfHourDividerColor">#40ffffff</item>
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@ buildscript {
|
||||||
kotlin_version = '1.3.50'
|
kotlin_version = '1.3.50'
|
||||||
|
|
||||||
release = [
|
release = [
|
||||||
versionName: "3.9.9-dev",
|
versionName: "3.9.6-dev",
|
||||||
versionCode: 3090900
|
versionCode: 3090600
|
||||||
]
|
]
|
||||||
|
|
||||||
setup = [
|
setup = [
|
||||||
|
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
|
Loading…
Add table
Add a link
Reference in a new issue