forked from github/szkolny
Compare commits
30 Commits
v3.9.16-de
...
v3.9.17-de
Author | SHA1 | Date | |
---|---|---|---|
d20102c3bd | |||
f165ee32e5 | |||
60ad2e81f3 | |||
5ca8b642da | |||
f40cd7f26c | |||
e04b519e9b | |||
658e59bed6 | |||
cb5eb19abc | |||
d336531ca8 | |||
30ee71f4e3 | |||
844d5b33bc | |||
e3741f1c75 | |||
21a6e4d8c6 | |||
ec14ba76c9 | |||
90e7b1e9c7 | |||
a09d943344 | |||
52ac40c826 | |||
8f8eb64364 | |||
fe40ab0ab4 | |||
5991ef820f | |||
d67c2a90b1 | |||
e85d6fbc3b | |||
62a9604bd2 | |||
0aae2174c1 | |||
b66bd6fec9 | |||
b399a3f5ad | |||
1f5927eec0 | |||
2d838e7003 | |||
f242c30476 | |||
2cf204ff79 |
@ -12,7 +12,7 @@
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/SplashTheme"
|
||||
android:theme="@style/AppTheme.Dark"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:ignore="UnusedAttribute">
|
||||
<activity
|
||||
@ -99,12 +99,6 @@
|
||||
__/ |
|
||||
|_
|
||||
-->
|
||||
<activity
|
||||
android:name=".widgets.timetable.LessonDetailsActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:excludeFromRecents="true"
|
||||
android:noHistory="true"
|
||||
android:theme="@style/AppTheme.NoDisplay" />
|
||||
<activity android:name=".widgets.timetable.LessonDialogActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:excludeFromRecents="true"
|
||||
@ -122,6 +116,9 @@
|
||||
android:name=".ui.modules.webpush.WebPushConfigActivity"
|
||||
android:configChanges="orientation|keyboardHidden"
|
||||
android:theme="@style/AppTheme.Dark" />
|
||||
<activity
|
||||
android:name=".ui.modules.home.CounterActivityOld"
|
||||
android:theme="@style/AppTheme.Black" />
|
||||
<activity
|
||||
android:name=".ui.modules.home.CounterActivity"
|
||||
android:theme="@style/AppTheme.Black" />
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
/*secret password - removed for source code publication*/
|
||||
static toys AES_IV[16] = {
|
||||
0x97, 0x0e, 0x93, 0xd3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
0xc4, 0x14, 0x3c, 0x14, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
||||
|
||||
unsigned char *agony(unsigned int laugh, unsigned char *box, unsigned char *heat);
|
||||
|
||||
|
@ -112,15 +112,13 @@ fun String.swapFirstLastName(): String {
|
||||
}
|
||||
}
|
||||
|
||||
fun String.getFirstLastName(): Pair<String, String>? {
|
||||
fun String.splitName(): Pair<String, String>? {
|
||||
return this.split(" ").let {
|
||||
if (it.size >= 2) Pair(it[0], it[1])
|
||||
else null
|
||||
}
|
||||
}
|
||||
|
||||
fun String.getLastFirstName() = this.getFirstLastName()
|
||||
|
||||
fun changeStringCase(s: String): String {
|
||||
val delimiters = " '-/"
|
||||
val sb = StringBuilder()
|
||||
@ -179,6 +177,20 @@ fun colorFromName(context: Context, name: String?): Int {
|
||||
return context.getColorFromRes(color)
|
||||
}
|
||||
|
||||
fun colorFromCssName(name: String): Int {
|
||||
return when (name) {
|
||||
"red" -> 0xffff0000
|
||||
"green" -> 0xff008000
|
||||
"blue" -> 0xff0000ff
|
||||
"violet" -> 0xffee82ee
|
||||
"brown" -> 0xffa52a2a
|
||||
"orange" -> 0xffffa500
|
||||
"black" -> 0xff000000
|
||||
"white" -> 0xffffffff
|
||||
else -> -1
|
||||
}.toInt()
|
||||
}
|
||||
|
||||
fun MutableList<Profile>.filterOutArchived(): MutableList<Profile> {
|
||||
this.removeAll { it.archived }
|
||||
return this
|
||||
@ -576,52 +588,65 @@ operator fun StringBuilder.plusAssign(str: String?) {
|
||||
this.append(str)
|
||||
}
|
||||
|
||||
fun Context.timeTill(time: Int, delimiter: String = " "): String {
|
||||
fun Context.timeTill(time: Int, delimiter: String = " ", countInSeconds: Boolean = false): String {
|
||||
val parts = mutableListOf<Pair<Int, Int>>()
|
||||
|
||||
val hours = time / 3600
|
||||
val minutes = (time - hours*3600) / 60
|
||||
val seconds = time - minutes*60 - hours*3600
|
||||
|
||||
var prefixAdded = false
|
||||
if (hours > 0) {
|
||||
if (!prefixAdded) parts += R.plurals.time_till_text to hours; prefixAdded = true
|
||||
parts += R.plurals.time_till_hours to hours
|
||||
}
|
||||
if (minutes > 0) {
|
||||
if (!prefixAdded) parts += R.plurals.time_till_text to minutes; prefixAdded = true
|
||||
parts += R.plurals.time_till_minutes to minutes
|
||||
}
|
||||
if (hours == 0 && minutes < 10) {
|
||||
if (!prefixAdded) parts += R.plurals.time_till_text to seconds; prefixAdded = true
|
||||
parts += R.plurals.time_till_seconds to seconds
|
||||
if (!countInSeconds) {
|
||||
var prefixAdded = false
|
||||
if (hours > 0) {
|
||||
if (!prefixAdded) parts += R.plurals.time_till_text to hours
|
||||
prefixAdded = true
|
||||
parts += R.plurals.time_till_hours to hours
|
||||
}
|
||||
if (minutes > 0) {
|
||||
if (!prefixAdded) parts += R.plurals.time_till_text to minutes
|
||||
prefixAdded = true
|
||||
parts += R.plurals.time_till_minutes to minutes
|
||||
}
|
||||
if (hours == 0 && minutes < 10) {
|
||||
if (!prefixAdded) parts += R.plurals.time_till_text to seconds
|
||||
prefixAdded = true
|
||||
parts += R.plurals.time_till_seconds to seconds
|
||||
}
|
||||
} else {
|
||||
parts += R.plurals.time_till_text to time
|
||||
parts += R.plurals.time_till_seconds to time
|
||||
}
|
||||
|
||||
return parts.joinToString(delimiter) { resources.getQuantityString(it.first, it.second, it.second) }
|
||||
}
|
||||
|
||||
fun Context.timeLeft(time: Int, delimiter: String = " "): String {
|
||||
fun Context.timeLeft(time: Int, delimiter: String = " ", countInSeconds: Boolean = false): String {
|
||||
val parts = mutableListOf<Pair<Int, Int>>()
|
||||
|
||||
val hours = time / 3600
|
||||
val minutes = (time - hours*3600) / 60
|
||||
val seconds = time - minutes*60 - hours*3600
|
||||
|
||||
var prefixAdded = false
|
||||
if (hours > 0) {
|
||||
if (!prefixAdded) parts += R.plurals.time_left_text to hours
|
||||
prefixAdded = true
|
||||
parts += R.plurals.time_left_hours to hours
|
||||
}
|
||||
if (minutes > 0) {
|
||||
if (!prefixAdded) parts += R.plurals.time_left_text to minutes
|
||||
prefixAdded = true
|
||||
parts += R.plurals.time_left_minutes to minutes
|
||||
}
|
||||
if (hours == 0 && minutes < 10) {
|
||||
if (!prefixAdded) parts += R.plurals.time_left_text to seconds
|
||||
prefixAdded = true
|
||||
parts += R.plurals.time_left_seconds to seconds
|
||||
if (!countInSeconds) {
|
||||
var prefixAdded = false
|
||||
if (hours > 0) {
|
||||
if (!prefixAdded) parts += R.plurals.time_left_text to hours
|
||||
prefixAdded = true
|
||||
parts += R.plurals.time_left_hours to hours
|
||||
}
|
||||
if (minutes > 0) {
|
||||
if (!prefixAdded) parts += R.plurals.time_left_text to minutes
|
||||
prefixAdded = true
|
||||
parts += R.plurals.time_left_minutes to minutes
|
||||
}
|
||||
if (hours == 0 && minutes < 10) {
|
||||
if (!prefixAdded) parts += R.plurals.time_left_text to seconds
|
||||
prefixAdded = true
|
||||
parts += R.plurals.time_left_seconds to seconds
|
||||
}
|
||||
} else {
|
||||
parts += R.plurals.time_left_text to time
|
||||
parts += R.plurals.time_left_seconds to time
|
||||
}
|
||||
|
||||
return parts.joinToString(delimiter) { resources.getQuantityString(it.first, it.second, it.second) }
|
||||
@ -641,3 +666,19 @@ fun Drawable.setTintColor(color: Int): Drawable {
|
||||
)
|
||||
return this
|
||||
}
|
||||
|
||||
inline fun <T> List<T>.ifNotEmpty(block: (List<T>) -> Unit) {
|
||||
if (!isEmpty())
|
||||
block(this)
|
||||
}
|
||||
|
||||
val String.firstLettersName: String
|
||||
get() {
|
||||
var nameShort = ""
|
||||
this.split(" ").forEach {
|
||||
if (it.isBlank())
|
||||
return@forEach
|
||||
nameShort += it[0].toLowerCase()
|
||||
}
|
||||
return nameShort
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ import pl.szczodrzynski.edziennik.ui.modules.feedback.FeedbackFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.feedback.HelpFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.grades.GradesFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.grades.editor.GradesEditorFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragmentV2
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.homework.HomeworkFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.login.LoginActivity
|
||||
import pl.szczodrzynski.edziennik.ui.modules.messages.MessageFragment
|
||||
@ -127,7 +127,7 @@ class MainActivity : AppCompatActivity() {
|
||||
val list: MutableList<NavTarget> = mutableListOf()
|
||||
|
||||
// home item
|
||||
list += NavTarget(DRAWER_ITEM_HOME, R.string.menu_home_page, HomeFragmentV2::class)
|
||||
list += NavTarget(DRAWER_ITEM_HOME, R.string.menu_home_page, HomeFragment::class)
|
||||
.withTitle(R.string.app_name)
|
||||
.withIcon(CommunityMaterial.Icon2.cmd_home_outline)
|
||||
.isInDrawer(true)
|
||||
|
@ -43,6 +43,8 @@ class WidgetTimetable : AppWidgetProvider() {
|
||||
super.onReceive(context, intent)
|
||||
}
|
||||
|
||||
private val ignoreCancelled = true
|
||||
|
||||
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) {
|
||||
val thisWidget = ComponentName(context, WidgetTimetable::class.java)
|
||||
|
||||
@ -122,7 +124,7 @@ class WidgetTimetable : AppWidgetProvider() {
|
||||
val method = declaredMethods[m]
|
||||
if (method.name == "setDrawableParameters") {
|
||||
method.isAccessible = true
|
||||
method.invoke(views, R.id.widgetTimetableListView, true, -1, colorFilter.toInt(), mode, -1)
|
||||
method.invoke(views, R.id.widgetTimetableBackground, true, -1, colorFilter.toInt(), mode, -1)
|
||||
method.invoke(views, R.id.widgetTimetableHeader, true, -1, colorFilter.toInt(), mode, -1)
|
||||
break
|
||||
}
|
||||
@ -185,12 +187,30 @@ class WidgetTimetable : AppWidgetProvider() {
|
||||
// search for lessons to display
|
||||
val timetableDate = Date.getToday()
|
||||
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
|
||||
&& it.displayEndTime > now
|
||||
&& !(it.isCancelled && ignoreCancelled)
|
||||
}
|
||||
while ((lessons.isEmpty() || lessons.none {
|
||||
it.displayDate != today || (it.displayDate == today && it.displayEndTime != null && it.displayEndTime!! >= now)
|
||||
it.type != Lesson.TYPE_NO_LESSONS
|
||||
&& (it.displayDate != today
|
||||
|| (it.displayDate == today
|
||||
&& it.displayEndTime != null
|
||||
&& it.displayEndTime!! >= now))
|
||||
}) && checkedDays < 7) {
|
||||
|
||||
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
|
||||
&& !(it.isCancelled && ignoreCancelled)
|
||||
}
|
||||
|
||||
if (lessons.isEmpty() && timetableDate.weekDay <= 5)
|
||||
break
|
||||
|
||||
checkedDays++
|
||||
}
|
||||
|
||||
@ -199,6 +219,32 @@ class WidgetTimetable : AppWidgetProvider() {
|
||||
if (lessons.isNotEmpty())
|
||||
displayingDate = timetableDate
|
||||
profileId = profile.id
|
||||
if (lessons.isEmpty()) {
|
||||
views.setViewVisibility(R.id.widgetTimetableListView, View.GONE)
|
||||
views.setViewVisibility(R.id.widgetTimetableNoTimetable, View.VISIBLE)
|
||||
}
|
||||
if (lessons.size == 1 && lessons[0].type == Lesson.TYPE_NO_LESSONS) {
|
||||
views.setViewVisibility(R.id.widgetTimetableListView, View.GONE)
|
||||
views.setViewVisibility(R.id.widgetTimetableNoLessons, View.VISIBLE)
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (lessons.isEmpty()) {
|
||||
val separator = ItemWidgetTimetableModel()
|
||||
separator.profileId = profile.id
|
||||
separator.bigStyle = widgetConfig.bigStyle
|
||||
separator.darkTheme = widgetConfig.darkTheme
|
||||
separator.isNoTimetableItem = true;
|
||||
models.add(separator)
|
||||
}
|
||||
if (lessons.size == 1 && lessons[0].type == Lesson.TYPE_NO_LESSONS) {
|
||||
val separator = ItemWidgetTimetableModel()
|
||||
separator.profileId = profile.id
|
||||
separator.bigStyle = widgetConfig.bigStyle
|
||||
separator.darkTheme = widgetConfig.darkTheme
|
||||
separator.isNoLessonsItem = true;
|
||||
models.add(separator)
|
||||
}
|
||||
}
|
||||
|
||||
// get all events for the current date
|
||||
@ -298,13 +344,6 @@ class WidgetTimetable : AppWidgetProvider() {
|
||||
val pendingOpenIntent = PendingIntent.getActivity(app, appWidgetId, openIntent, 0)
|
||||
views.setOnClickPendingIntent(R.id.widgetTimetableHeader, pendingOpenIntent)
|
||||
|
||||
if (lessonList.isEmpty()) {
|
||||
views.setViewVisibility(R.id.widgetTimetableLoading, View.VISIBLE)
|
||||
views.setRemoteAdapter(R.id.widgetTimetableListView, Intent())
|
||||
views.setTextViewText(R.id.widgetTimetableLoading, app.getString(R.string.widget_timetable_no_lessons))
|
||||
return
|
||||
}
|
||||
|
||||
timetables!!.put(appWidgetId, models)
|
||||
|
||||
// apply the list service to the list view
|
||||
@ -315,7 +354,7 @@ class WidgetTimetable : AppWidgetProvider() {
|
||||
|
||||
// create an intent used to display the lesson details dialog
|
||||
val intentTemplate = Intent(app, LessonDialogActivity::class.java)
|
||||
intentTemplate.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||
intentTemplate.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK /*or Intent.FLAG_ACTIVITY_CLEAR_TASK*/)
|
||||
val pendingIntentTimetable = PendingIntent.getActivity(app, appWidgetId, intentTemplate, 0)
|
||||
views.setPendingIntentTemplate(R.id.widgetTimetableListView, pendingIntentTimetable)
|
||||
|
||||
@ -336,11 +375,8 @@ class WidgetTimetable : AppWidgetProvider() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
|
||||
val ACTION_SYNC_DATA = "ACTION_SYNC_DATA"
|
||||
private val TAG = "WidgetTimetable"
|
||||
private val modeInt = 0
|
||||
const val ACTION_SYNC_DATA = "ACTION_SYNC_DATA"
|
||||
private const val TAG = "WidgetTimetable"
|
||||
|
||||
var timetables: SparseArray<List<ItemWidgetTimetableModel>>? = null
|
||||
|
||||
|
@ -101,3 +101,5 @@ const val VULCAN_API_ENDPOINT_MESSAGES_RECEIVED = "mobile-api/Uczen.v3.Uczen/Wia
|
||||
const val VULCAN_API_ENDPOINT_MESSAGES_SENT = "mobile-api/Uczen.v3.Uczen/WiadomosciWyslane"
|
||||
const val VULCAN_API_ENDPOINT_MESSAGES_CHANGE_STATUS = "mobile-api/Uczen.v3.Uczen/ZmienStatusWiadomosci"
|
||||
const val VULCAN_API_ENDPOINT_PUSH = "mobile-api/Uczen.v3.Uczen/UstawPushToken"
|
||||
|
||||
const val EDUDZIENNIK_USER_AGENT = "Szkolny.eu/${BuildConfig.VERSION_NAME}"
|
||||
|
@ -158,6 +158,12 @@ const val ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA = 441
|
||||
const val ERROR_IDZIENNIK_API_ACCESS_DENIED = 450
|
||||
const val ERROR_IDZIENNIK_API_OTHER = 451
|
||||
|
||||
const val ERROR_LOGIN_EDUDZIENNIK_WEB_INVALID_LOGIN = 501
|
||||
const val ERROR_LOGIN_EDUDZIENNIK_WEB_OTHER = 510
|
||||
const val ERROR_LOGIN_EDUDZIENNIK_WEB_NO_SESSION_ID = 511
|
||||
const val ERROR_EDUDZIENNIK_WEB_TIMETABLE_NOT_PUBLIC = 520
|
||||
const val ERROR_EDUDZIENNIK_WEB_TEAM_MISSING = 530
|
||||
|
||||
const val ERROR_TEMPLATE_WEB_OTHER = 801
|
||||
|
||||
const val EXCEPTION_API_TASK = 900
|
||||
@ -175,5 +181,6 @@ const val EXCEPTION_LIBRUS_MESSAGES_REQUEST = 911
|
||||
const val EXCEPTION_IDZIENNIK_WEB_REQUEST = 912
|
||||
const val EXCEPTION_IDZIENNIK_WEB_API_REQUEST = 913
|
||||
const val EXCEPTION_IDZIENNIK_API_REQUEST = 914
|
||||
const val EXCEPTION_EDUDZIENNIK_WEB_REQUEST = 920
|
||||
|
||||
const val LOGIN_NO_ARGUMENTS = 1201
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api
|
||||
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.login.EdudziennikLoginWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.login.IdziennikLoginApi
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.login.IdziennikLoginWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginApi
|
||||
@ -130,6 +131,14 @@ val idziennikLoginMethods = listOf(
|
||||
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_IDZIENNIK_WEB }
|
||||
)
|
||||
|
||||
const val LOGIN_TYPE_EDUDZIENNIK = 5
|
||||
const val LOGIN_METHOD_EDUDZIENNIK_WEB = 100
|
||||
val edudziennikLoginMethods = listOf(
|
||||
LoginMethod(LOGIN_TYPE_EDUDZIENNIK, LOGIN_METHOD_EDUDZIENNIK_WEB, EdudziennikLoginWeb::class.java)
|
||||
.withIsPossible { _, _ -> true }
|
||||
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED }
|
||||
)
|
||||
|
||||
val templateLoginMethods = listOf(
|
||||
LoginMethod(LOGIN_TYPE_TEMPLATE, LOGIN_METHOD_TEMPLATE_WEB, TemplateLoginWeb::class.java)
|
||||
.withIsPossible { _, _ -> true }
|
||||
|
@ -4,76 +4,84 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api
|
||||
|
||||
import kotlin.text.RegexOption.DOT_MATCHES_ALL
|
||||
|
||||
object Regexes {
|
||||
val STYLE_CSS_COLOR by lazy {
|
||||
"""color: \w+?;?"?""".toRegex()
|
||||
}
|
||||
|
||||
|
||||
|
||||
val MOBIDZIENNIK_GRADES_SUBJECT_NAME by lazy {
|
||||
"""<div.*?>\n*\s*(.+?)\s*\n*(?:<.*?)??</div>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||
"""<div.*?>\n*\s*(.+?)\s*\n*(?:<.*?)??</div>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val MOBIDZIENNIK_GRADES_COLOR by lazy {
|
||||
"""background-color:([#A-Fa-f0-9]+);""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||
"""background-color:([#A-Fa-f0-9]+);""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val MOBIDZIENNIK_GRADES_CATEGORY by lazy {
|
||||
"""> (.+?):</span>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||
"""> (.+?):</span>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val MOBIDZIENNIK_GRADES_CLASS_AVERAGE by lazy {
|
||||
"""Średnia ocen:.*<strong>([0-9]*\.?[0-9]*)</strong>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||
"""Średnia ocen:.*<strong>([0-9]*\.?[0-9]*)</strong>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val MOBIDZIENNIK_GRADES_ADDED_DATE by lazy {
|
||||
"""Wpisano:.*<strong>.+?,\s([0-9]+)\s(.+?)\s([0-9]{4}),\sgodzina\s([0-9:]+)</strong>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||
"""Wpisano:.*<strong>.+?,\s([0-9]+)\s(.+?)\s([0-9]{4}),\sgodzina\s([0-9:]+)</strong>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val MOBIDZIENNIK_GRADES_COUNT_TO_AVG by lazy {
|
||||
"""Liczona do średniej:.*?<strong>nie<br/?></strong>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||
"""Liczona do średniej:.*?<strong>nie<br/?></strong>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val MOBIDZIENNIK_GRADES_DETAILS by lazy {
|
||||
"""<strong.*?>(.+?)</strong>.*?<sup>.+?</sup>.*?(?:<small>\((.+?)\)</small>.*?)?<span>.*?Wartość oceny:.*?<strong>([0-9.]+)</strong>.*?Wpisał\(a\):.*?<strong>(.+?)</strong>.*?(?:Komentarz:.*?<strong>(.+?)</strong>)?</span>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||
"""<strong.*?>(.+?)</strong>.*?<sup>.+?</sup>.*?(?:<small>\((.+?)\)</small>.*?)?<span>.*?Wartość oceny:.*?<strong>([0-9.]+)</strong>.*?Wpisał\(a\):.*?<strong>(.+?)</strong>.*?(?:Komentarz:.*?<strong>(.+?)</strong>)?</span>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
|
||||
val MOBIDZIENNIK_EVENT_TYPE by lazy {
|
||||
"""\(([0-9A-ząęóżźńśłć]*?)\)$""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||
"""\(([0-9A-ząęóżźńśłć]*?)\)$""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val MOBIDZIENNIK_LUCKY_NUMBER by lazy {
|
||||
"""class="szczesliwy_numerek".*>0*([0-9]+)(?:/0*[0-9]+)*</a>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||
"""class="szczesliwy_numerek".*>0*([0-9]+)(?:/0*[0-9]+)*</a>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val MOBIDZIENNIK_CLASS_CALENDAR by lazy {
|
||||
"""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)
|
||||
"""czas przeczytania:.+?,\s([0-9]+)\s(.+?)\s([0-9]{4}),\sgodzina\s([0-9:]+)""".toRegex(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)
|
||||
""".+?,\s([0-9]+)\s(.+?)\s([0-9]{4}),\sgodzina\s([0-9:]+)""".toRegex(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)
|
||||
"""href="https://.+?\.mobidziennik.pl/.+?&(?:amp;)?zalacznik=([0-9]+)"(?:.+?<small.+?\(([0-9.]+)\s(M|K|G|)B\))*""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
|
||||
|
||||
|
||||
val IDZIENNIK_LOGIN_HIDDEN_FIELDS by lazy {
|
||||
"""<input type="hidden".+?name="([A-z0-9_]+)?".+?value="([A-z0-9_+-/=]+)?".+?>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||
"""<input type="hidden".+?name="([A-z0-9_]+)?".+?value="([A-z0-9_+-/=]+)?".+?>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val IDZIENNIK_LOGIN_ERROR by lazy {
|
||||
"""id="spanErrorMessage">(.*?)</""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||
"""id="spanErrorMessage">(.*?)</""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val IDZIENNIK_LOGIN_FIRST_ACCOUNT_NAME by lazy {
|
||||
"""Imię i nazwisko:.+?">(.+?)</div>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||
"""Imię i nazwisko:.+?">(.+?)</div>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val IDZIENNIK_LOGIN_FIRST_IS_PARENT by lazy {
|
||||
"""id="ctl00_CzyRodzic" value="([01])" />""".toRegex()
|
||||
}
|
||||
val IDZIENNIK_LOGIN_FIRST_SCHOOL_YEAR by lazy {
|
||||
"""name="ctl00\${"$"}dxComboRokSzkolny".+?selected="selected".*?value="([0-9]+)">([0-9/]+)<""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||
"""name="ctl00\${"$"}dxComboRokSzkolny".+?selected="selected".*?value="([0-9]+)">([0-9/]+)<""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val IDZIENNIK_LOGIN_FIRST_STUDENT_SELECT by lazy {
|
||||
"""<select.*?name="ctl00\${"$"}dxComboUczniowie".*?</select>""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||
"""<select.*?name="ctl00\${"$"}dxComboUczniowie".*?</select>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val IDZIENNIK_LOGIN_FIRST_STUDENT by lazy {
|
||||
"""<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(DOT_MATCHES_ALL)
|
||||
}
|
||||
|
||||
|
||||
|
||||
val VULCAN_SHITFT_ANNOTATION by lazy {
|
||||
val VULCAN_SHIFT_ANNOTATION by lazy {
|
||||
"""\(przeniesiona (z|na) lekcj[ię] ([0-9]+), (.+)\)""".toRegex()
|
||||
}
|
||||
|
||||
@ -82,4 +90,49 @@ object Regexes {
|
||||
val LIBRUS_ATTACHMENT_KEY by lazy {
|
||||
"""singleUseKey=([0-9A-f_]+)""".toRegex()
|
||||
}
|
||||
|
||||
|
||||
|
||||
val EDUDZIENNIK_STUDENTS_START by lazy {
|
||||
"""<li><a href="/Students/([\w-_]+?)/start/">(.*?)</a>""".toRegex()
|
||||
}
|
||||
val EDUDZIENNIK_ACCOUNT_NAME_START by lazy {
|
||||
"""<span id='user_dn'>(.*?)</span>""".toRegex()
|
||||
}
|
||||
|
||||
val EDUDZIENNIK_ATTENDANCE_ENTRIES by lazy {
|
||||
"""<td id="([\d-]+?):(\d+?)".*?>(.+?)</td>""".toRegex()
|
||||
}
|
||||
val EDUDZIENNIK_ATTENDANCE_TYPES by lazy {
|
||||
"""<div class="info">.*?<p>(.*?)</p>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val EDUDZIENNIK_ATTENDANCE_TYPE by lazy {
|
||||
"""\((.+?)\) (.+)""".toRegex()
|
||||
}
|
||||
|
||||
val EDUDZIENNIK_SUBJECT_ID by lazy {
|
||||
"""/Courses/([\w-_]+?)/""".toRegex()
|
||||
}
|
||||
val EDUDZIENNIK_GRADE_ID by lazy {
|
||||
"""/Grades/([\w-_]+?)/""".toRegex()
|
||||
}
|
||||
val EDUDZIENNIK_EXAM_ID by lazy {
|
||||
"""/Evaluations/([\w-_]+?)/""".toRegex()
|
||||
}
|
||||
val EDUDZIENNIK_EVENT_TYPE_ID by lazy {
|
||||
"""/GradeLabels/([\w-_]+?)/""".toRegex()
|
||||
}
|
||||
|
||||
val EDUDZIENNIK_SCHOOL_DETAIL_ID by lazy {
|
||||
"""<a id="School_detail".*?/School/([\w-_]+?)/""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val EDUDZIENNIK_SCHOOL_DETAIL_NAME by lazy {
|
||||
"""</li>.*?<p>(.*?)</p>.*?<li>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val EDUDZIENNIK_CLASS_DETAIL_ID by lazy {
|
||||
"""<a id="Klass_detail".*?/Klass/([\w-_]+?)/""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
val EDUDZIENNIK_CLASS_DETAIL_NAME by lazy {
|
||||
"""<a id="Klass_detail".*?>(.*?)</a>""".toRegex(DOT_MATCHES_ALL)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-22
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik
|
||||
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_EDUDZIENNIK_WEB
|
||||
import pl.szczodrzynski.edziennik.data.api.models.Data
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.events.EventType
|
||||
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.subjects.Subject
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
|
||||
|
||||
/**
|
||||
* Use http://patorjk.com/software/taag/#p=display&f=Big for the ascii art
|
||||
*
|
||||
* Use https://codepen.io/kubasz/pen/RwwwbGN to easily generate the student data getters/setters
|
||||
*/
|
||||
class DataEdudziennik(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) {
|
||||
|
||||
fun isWebLoginValid() = webSessionIdExpiryTime-30 > currentTimeUnix() && webSessionId.isNotNullNorEmpty()
|
||||
|
||||
override fun satisfyLoginMethods() {
|
||||
loginMethods.clear()
|
||||
if (isWebLoginValid()) {
|
||||
loginMethods += LOGIN_METHOD_EDUDZIENNIK_WEB
|
||||
}
|
||||
}
|
||||
|
||||
private var mLoginEmail: String? = null
|
||||
var loginEmail: String?
|
||||
get() { mLoginEmail = mLoginEmail ?: loginStore.getLoginData("email", null); return mLoginEmail }
|
||||
set(value) { loginStore.putLoginData("email", value); mLoginEmail = value }
|
||||
|
||||
private var mLoginPassword: String? = null
|
||||
var loginPassword: String?
|
||||
get() { mLoginPassword = mLoginPassword ?: loginStore.getLoginData("password", null); return mLoginPassword }
|
||||
set(value) { loginStore.putLoginData("password", value); mLoginPassword = value }
|
||||
|
||||
private var mStudentId: String? = null
|
||||
var studentId: String?
|
||||
get() { mStudentId = mStudentId ?: profile?.getStudentData("studentId", null); return mStudentId }
|
||||
set(value) { profile?.putStudentData("studentId", value) ?: return; mStudentId = value }
|
||||
|
||||
private var mSchoolId: String? = null
|
||||
var schoolId: String?
|
||||
get() { mSchoolId = mSchoolId ?: profile?.getStudentData("schoolId", null); return mSchoolId }
|
||||
set(value) { profile?.putStudentData("schoolId", value) ?: return; mSchoolId = value }
|
||||
|
||||
private var mClassId: String? = null
|
||||
var classId: String?
|
||||
get() { mClassId = mClassId ?: profile?.getStudentData("classId", null); return mClassId }
|
||||
set(value) { profile?.putStudentData("classId", value) ?: return; mClassId = value }
|
||||
|
||||
/* __ __ _
|
||||
\ \ / / | |
|
||||
\ \ /\ / /__| |__
|
||||
\ \/ \/ / _ \ '_ \
|
||||
\ /\ / __/ |_) |
|
||||
\/ \/ \___|_._*/
|
||||
private var mWebSessionId: String? = null
|
||||
var webSessionId: String?
|
||||
get() { mWebSessionId = mWebSessionId ?: loginStore.getLoginData("webSessionId", null); return mWebSessionId }
|
||||
set(value) { loginStore.putLoginData("webSessionId", value); mWebSessionId = value }
|
||||
|
||||
private var mWebSessionIdExpiryTime: Long? = null
|
||||
var webSessionIdExpiryTime: Long
|
||||
get() { mWebSessionIdExpiryTime = mWebSessionIdExpiryTime ?: loginStore.getLoginData("webSessionIdExpiryTime", 0L); return mWebSessionIdExpiryTime ?: 0L }
|
||||
set(value) { loginStore.putLoginData("webSessionIdExpiryTime", value); mWebSessionIdExpiryTime = value }
|
||||
|
||||
/* ____ _ _
|
||||
/ __ \| | | |
|
||||
| | | | |_| |__ ___ _ __
|
||||
| | | | __| '_ \ / _ \ '__|
|
||||
| |__| | |_| | | | __/ |
|
||||
\____/ \__|_| |_|\___|*/
|
||||
private var mSchoolName: String? = null
|
||||
var schoolName: String?
|
||||
get() { mSchoolName = mSchoolName ?: profile?.getStudentData("schoolName", null); return mSchoolName }
|
||||
set(value) { profile?.putStudentData("schoolName", value) ?: return; mSchoolName = value }
|
||||
|
||||
private var mTimetableNotPublic: Boolean? = null
|
||||
var timetableNotPublic: Boolean
|
||||
get() { mTimetableNotPublic = mTimetableNotPublic ?: profile?.getStudentData("timetableNotPublic", false); return mTimetableNotPublic ?: false }
|
||||
set(value) { profile?.putStudentData("timetableNotPublic", value) ?: return; mTimetableNotPublic = value }
|
||||
|
||||
val studentEndpoint: String
|
||||
get() = "Students/$studentId/"
|
||||
|
||||
val schoolEndpoint: String
|
||||
get() = "Schools/$schoolId/"
|
||||
|
||||
val schoolClassEndpoint: String
|
||||
get() = "Schools/$classId/"
|
||||
|
||||
val studentAndClassEndpoint: String
|
||||
get() = "Students/$studentId/Klass/$classId/"
|
||||
|
||||
val courseEndpoint: String
|
||||
get() = "Course/$studentId/"
|
||||
|
||||
val timetableEndpoint: String
|
||||
get() = "Plan/$studentId/"
|
||||
|
||||
fun getSubject(longId: String, name: String): Subject {
|
||||
val id = longId.crc32()
|
||||
return subjectList.singleOrNull { it.id == id } ?: run {
|
||||
val subject = Subject(profileId, id, name, name)
|
||||
subjectList.put(id, subject)
|
||||
subject
|
||||
}
|
||||
}
|
||||
|
||||
fun getTeacher(firstName: String, lastName: String): Teacher {
|
||||
val name = "$firstName $lastName".fixName()
|
||||
val id = name.crc32()
|
||||
return teacherList.singleOrNull { it.id == id } ?: run {
|
||||
val teacher = Teacher(profileId, id, firstName, lastName)
|
||||
teacherList.put(id, teacher)
|
||||
teacher
|
||||
}
|
||||
}
|
||||
|
||||
fun getEventType(longId: String, name: String): EventType {
|
||||
val id = longId.crc16().toLong()
|
||||
return eventTypes.singleOrNull { it.id == id } ?: run {
|
||||
val eventType = EventType(profileId, id, name, colorFromName(app, name))
|
||||
eventTypes.put(id, eventType)
|
||||
eventType
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-22
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_EDUDZIENNIK_WEB_TIMETABLE_NOT_PUBLIC
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_EDUDZIENNIK_WEB_NO_SESSION_ID
|
||||
import pl.szczodrzynski.edziennik.data.api.edudziennikLoginMethods
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikData
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.firstlogin.EdudziennikFirstLogin
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.login.EdudziennikLogin
|
||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
|
||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.api.prepare
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageFull
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
|
||||
class Edudziennik(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
|
||||
companion object {
|
||||
private const val TAG = "Edudziennik"
|
||||
}
|
||||
|
||||
val internalErrorList = mutableListOf<Int>()
|
||||
val data: DataEdudziennik
|
||||
|
||||
init {
|
||||
data = DataEdudziennik(app, profile, loginStore).apply {
|
||||
callback = wrapCallback(this@Edudziennik.callback)
|
||||
satisfyLoginMethods()
|
||||
}
|
||||
}
|
||||
|
||||
private fun completed() {
|
||||
data.saveData()
|
||||
data.notify {
|
||||
callback.onCompleted()
|
||||
}
|
||||
}
|
||||
|
||||
/* _______ _ _ _ _ _
|
||||
|__ __| | /\ | | (_) | | |
|
||||
| | | |__ ___ / \ | | __ _ ___ _ __ _| |_| |__ _ __ ___
|
||||
| | | '_ \ / _ \ / /\ \ | |/ _` |/ _ \| '__| | __| '_ \| '_ ` _ \
|
||||
| | | | | | __/ / ____ \| | (_| | (_) | | | | |_| | | | | | | | |
|
||||
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
|
||||
__/ |
|
||||
|__*/
|
||||
override fun sync(featureIds: List<Int>, viewId: Int?, arguments: JsonObject?) {
|
||||
data.arguments = arguments
|
||||
data.prepare(edudziennikLoginMethods, EdudziennikFeatures, featureIds, viewId)
|
||||
d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
|
||||
d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
||||
EdudziennikLogin(data) {
|
||||
EdudziennikData(data) {
|
||||
completed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun login() {
|
||||
d(TAG, "Trying to login with ${data.targetLoginMethodIds}")
|
||||
if (internalErrorList.isNotEmpty()) {
|
||||
d(TAG, " - Internal errors:")
|
||||
internalErrorList.forEach { d(TAG, " - code $it") }
|
||||
}
|
||||
EdudziennikLogin(data) {
|
||||
data()
|
||||
}
|
||||
}
|
||||
|
||||
private fun data() {
|
||||
d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")
|
||||
if (internalErrorList.isNotEmpty()) {
|
||||
d(TAG, " - Internal errors:")
|
||||
internalErrorList.forEach { d(TAG, " - code $it") }
|
||||
}
|
||||
EdudziennikData(data) {
|
||||
completed()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getMessage(message: MessageFull) {
|
||||
|
||||
}
|
||||
|
||||
override fun markAllAnnouncementsAsRead() {
|
||||
|
||||
}
|
||||
|
||||
override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
|
||||
|
||||
}
|
||||
|
||||
override fun firstLogin() {
|
||||
EdudziennikFirstLogin(data) {
|
||||
completed()
|
||||
}
|
||||
}
|
||||
|
||||
override fun cancel() {
|
||||
d(TAG, "Cancelled")
|
||||
data.cancel()
|
||||
}
|
||||
|
||||
private fun wrapCallback(callback: EdziennikCallback): EdziennikCallback {
|
||||
return object : EdziennikCallback {
|
||||
override fun onCompleted() {
|
||||
callback.onCompleted()
|
||||
}
|
||||
|
||||
override fun onProgress(step: Float) {
|
||||
callback.onProgress(step)
|
||||
}
|
||||
|
||||
override fun onStartProgress(stringRes: Int) {
|
||||
callback.onStartProgress(stringRes)
|
||||
}
|
||||
|
||||
override fun onError(apiError: ApiError) {
|
||||
if (apiError.errorCode in internalErrorList) {
|
||||
// finish immediately if the same error occurs twice during the same sync
|
||||
callback.onError(apiError)
|
||||
return
|
||||
}
|
||||
internalErrorList.add(apiError.errorCode)
|
||||
when (apiError.errorCode) {
|
||||
ERROR_LOGIN_EDUDZIENNIK_WEB_NO_SESSION_ID -> {
|
||||
login()
|
||||
}
|
||||
ERROR_EDUDZIENNIK_WEB_TIMETABLE_NOT_PUBLIC -> {
|
||||
data.timetableNotPublic = true
|
||||
data()
|
||||
}
|
||||
else -> callback.onError(apiError)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-23
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik
|
||||
|
||||
import pl.szczodrzynski.edziennik.data.api.*
|
||||
import pl.szczodrzynski.edziennik.data.api.models.Feature
|
||||
|
||||
const val ENDPOINT_EDUDZIENNIK_WEB_START = 1000
|
||||
const val ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE = 1001
|
||||
const val ENDPOINT_EDUDZIENNIK_WEB_EXAMS = 1002
|
||||
const val ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE = 1003
|
||||
const val ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER = 1010
|
||||
|
||||
val EdudziennikFeatures = listOf(
|
||||
Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_STUDENT_INFO, listOf(
|
||||
ENDPOINT_EDUDZIENNIK_WEB_START to LOGIN_METHOD_EDUDZIENNIK_WEB
|
||||
), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB)),
|
||||
|
||||
Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_TIMETABLE, listOf(
|
||||
ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE to LOGIN_METHOD_EDUDZIENNIK_WEB
|
||||
), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB)),
|
||||
|
||||
Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_GRADES, listOf(
|
||||
ENDPOINT_EDUDZIENNIK_WEB_START to LOGIN_METHOD_EDUDZIENNIK_WEB
|
||||
), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB)),
|
||||
|
||||
Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_AGENDA, listOf(
|
||||
ENDPOINT_EDUDZIENNIK_WEB_EXAMS to LOGIN_METHOD_EDUDZIENNIK_WEB
|
||||
), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB)),
|
||||
|
||||
Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_ATTENDANCE, listOf(
|
||||
ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE to LOGIN_METHOD_EDUDZIENNIK_WEB
|
||||
), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB)),
|
||||
|
||||
Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_LUCKY_NUMBER, listOf(
|
||||
ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER to LOGIN_METHOD_EDUDZIENNIK_WEB
|
||||
), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB))
|
||||
)
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-22
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data
|
||||
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web.*
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
|
||||
class EdudziennikData(val data: DataEdudziennik, val onSuccess: () -> Unit) {
|
||||
companion object {
|
||||
private const val TAG = "TemplateData"
|
||||
}
|
||||
|
||||
init {
|
||||
nextEndpoint(onSuccess)
|
||||
}
|
||||
|
||||
private fun nextEndpoint(onSuccess: () -> Unit) {
|
||||
if (data.targetEndpointIds.isEmpty()) {
|
||||
onSuccess()
|
||||
return
|
||||
}
|
||||
if (data.cancelled) {
|
||||
onSuccess()
|
||||
return
|
||||
}
|
||||
useEndpoint(data.targetEndpointIds.removeAt(0)) {
|
||||
data.progress(data.progressStep)
|
||||
nextEndpoint(onSuccess)
|
||||
}
|
||||
}
|
||||
|
||||
private fun useEndpoint(endpointId: Int, onSuccess: () -> Unit) {
|
||||
Utils.d(TAG, "Using endpoint $endpointId")
|
||||
when (endpointId) {
|
||||
ENDPOINT_EDUDZIENNIK_WEB_START -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_data)
|
||||
EdudziennikWebStart(data, onSuccess)
|
||||
}
|
||||
ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_timetable)
|
||||
EdudziennikWebTimetable(data, onSuccess)
|
||||
}
|
||||
ENDPOINT_EDUDZIENNIK_WEB_EXAMS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_exams)
|
||||
EdudziennikWebExams(data, onSuccess)
|
||||
}
|
||||
ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_attendance)
|
||||
EdudziennikWebAttendance(data, onSuccess)
|
||||
}
|
||||
ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_lucky_number)
|
||||
EdudziennikWebLuckyNumber(data, onSuccess)
|
||||
}
|
||||
else -> onSuccess()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-22
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data
|
||||
|
||||
import im.wangchao.mhttp.Request
|
||||
import im.wangchao.mhttp.Response
|
||||
import im.wangchao.mhttp.callback.TextCallbackHandler
|
||||
import okhttp3.Cookie
|
||||
import pl.szczodrzynski.edziennik.data.api.EDUDZIENNIK_USER_AGENT
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_REQUEST_FAILURE
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_RESPONSE_EMPTY
|
||||
import pl.szczodrzynski.edziennik.data.api.EXCEPTION_EDUDZIENNIK_WEB_REQUEST
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
|
||||
open class EdudziennikWeb(open val data: DataEdudziennik) {
|
||||
companion object {
|
||||
private const val TAG = "EdudziennikWeb"
|
||||
}
|
||||
|
||||
val profileId
|
||||
get() = data.profile?.id ?: -1
|
||||
|
||||
val profile
|
||||
get() = data.profile
|
||||
|
||||
fun webGet(tag: String, endpoint: String, xhr: Boolean = false, onSuccess: (text: String) -> Unit) {
|
||||
val url = "https://dziennikel.appspot.com/" + when (endpoint.endsWith('/') || endpoint.contains('?') || endpoint.isEmpty()) {
|
||||
true -> endpoint
|
||||
else -> "$endpoint/"
|
||||
}
|
||||
|
||||
d(tag, "Request: Edudziennik/Web - $url")
|
||||
|
||||
val callback = object : TextCallbackHandler() {
|
||||
override fun onSuccess(text: String?, response: Response?) {
|
||||
if (text == null || response == null) {
|
||||
data.error(ApiError(tag, ERROR_RESPONSE_EMPTY)
|
||||
.withResponse(response))
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
onSuccess(text)
|
||||
} catch (e: Exception) {
|
||||
data.error(ApiError(tag, EXCEPTION_EDUDZIENNIK_WEB_REQUEST)
|
||||
.withThrowable(e)
|
||||
.withResponse(response)
|
||||
.withApiResponse(text))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFailure(response: Response?, throwable: Throwable?) {
|
||||
data.error(ApiError(tag, ERROR_REQUEST_FAILURE)
|
||||
.withResponse(response)
|
||||
.withThrowable(throwable))
|
||||
}
|
||||
}
|
||||
|
||||
data.app.cookieJar.saveFromResponse(null, listOf(
|
||||
Cookie.Builder()
|
||||
.name("sessionid")
|
||||
.value(data.webSessionId!!)
|
||||
.domain("dziennikel.appspot.com")
|
||||
.secure().httpOnly().build(),
|
||||
Cookie.Builder()
|
||||
.name("semester")
|
||||
.value((profile?.currentSemester ?: 1).toString())
|
||||
.domain("dziennikel.appspot.com")
|
||||
.secure().httpOnly().build()
|
||||
))
|
||||
|
||||
Request.builder()
|
||||
.url(url)
|
||||
.userAgent(EDUDZIENNIK_USER_AGENT)
|
||||
.apply {
|
||||
if (xhr) header("X-Requested-With", "XMLHttpRequest")
|
||||
}
|
||||
.get()
|
||||
.callback(callback)
|
||||
.build()
|
||||
.enqueue()
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-24
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
|
||||
|
||||
import pl.szczodrzynski.edziennik.crc32
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_ATTENDANCE_ENTRIES
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_ATTENDANCE_TYPE
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_ATTENDANCE_TYPES
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
import pl.szczodrzynski.edziennik.singleOrNull
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import java.util.*
|
||||
|
||||
class EdudziennikWebAttendance(override val data: DataEdudziennik,
|
||||
val onSuccess: () -> Unit) : EdudziennikWeb(data) {
|
||||
companion object {
|
||||
private const val TAG = "EdudziennikWebAttendance"
|
||||
}
|
||||
|
||||
init { data.profile?.also { profile ->
|
||||
webGet(TAG, data.studentEndpoint + "Presence") { text ->
|
||||
|
||||
val attendanceTypes = EDUDZIENNIK_ATTENDANCE_TYPES.find(text)?.get(1)?.split(',')?.map {
|
||||
val type = EDUDZIENNIK_ATTENDANCE_TYPE.find(it.trim())
|
||||
val symbol = type?.get(1)?.trim()
|
||||
val name = type?.get(2)?.trim()
|
||||
return@map Triple(
|
||||
symbol,
|
||||
name,
|
||||
when (name?.toLowerCase(Locale.ROOT)) {
|
||||
"obecność" -> Attendance.TYPE_PRESENT
|
||||
"nieobecność" -> Attendance.TYPE_ABSENT
|
||||
"spóźnienie" -> Attendance.TYPE_BELATED
|
||||
"nieobecność usprawiedliwiona" -> Attendance.TYPE_ABSENT_EXCUSED
|
||||
"dzień wolny" -> Attendance.TYPE_RELEASED
|
||||
"brak zajęć" -> Attendance.TYPE_RELEASED
|
||||
"oddelegowany" -> Attendance.TYPE_RELEASED
|
||||
else -> Attendance.TYPE_CUSTOM
|
||||
}
|
||||
)
|
||||
} ?: emptyList()
|
||||
|
||||
EDUDZIENNIK_ATTENDANCE_ENTRIES.findAll(text).forEach { attendanceElement ->
|
||||
val date = Date.fromY_m_d(attendanceElement[1])
|
||||
val lessonNumber = attendanceElement[2].toInt()
|
||||
val attendanceSymbol = attendanceElement[3]
|
||||
|
||||
val lessons = data.app.db.timetableDao().getForDateNow(profileId, date)
|
||||
val lesson = lessons.firstOrNull { it.lessonNumber == lessonNumber }
|
||||
|
||||
val id = "${date.stringY_m_d}:$lessonNumber:$attendanceSymbol".crc32()
|
||||
|
||||
val (_, name, type) = attendanceTypes.firstOrNull { (symbol, _, _) -> symbol == attendanceSymbol }
|
||||
?: return@forEach
|
||||
|
||||
val startTime = data.lessonRanges.singleOrNull { it.lessonNumber == lessonNumber }?.startTime
|
||||
?: return@forEach
|
||||
|
||||
val attendanceObject = Attendance(
|
||||
profileId,
|
||||
id,
|
||||
lesson?.displayTeacherId ?: -1,
|
||||
lesson?.displaySubjectId ?: -1,
|
||||
profile.currentSemester,
|
||||
name,
|
||||
date,
|
||||
lesson?.displayStartTime ?: startTime,
|
||||
type
|
||||
)
|
||||
|
||||
data.attendanceList.add(attendanceObject)
|
||||
data.metadataList.add(Metadata(
|
||||
profileId,
|
||||
Metadata.TYPE_ATTENDANCE,
|
||||
id,
|
||||
profile.empty,
|
||||
profile.empty,
|
||||
System.currentTimeMillis()
|
||||
))
|
||||
}
|
||||
|
||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
}
|
||||
} ?: onSuccess() }
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-24
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
|
||||
|
||||
import org.jsoup.Jsoup
|
||||
import pl.szczodrzynski.edziennik.crc32
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_EVENT_TYPE_ID
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_EXAM_ID
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_SUBJECT_ID
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_EXAMS
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class EdudziennikWebExams(override val data: DataEdudziennik,
|
||||
val onSuccess: () -> Unit) : EdudziennikWeb(data) {
|
||||
companion object {
|
||||
const val TAG = "EdudziennikWebExams"
|
||||
}
|
||||
|
||||
init { profile?.also { profile ->
|
||||
webGet(TAG, data.studentAndClassEndpoint + "Evaluations", xhr = true) { text ->
|
||||
val doc = Jsoup.parseBodyFragment("<table>" + text.trim() + "</table>")
|
||||
|
||||
doc.select("tr").forEach { examElement ->
|
||||
val id = EDUDZIENNIK_EXAM_ID.find(examElement.child(0).child(0).attr("href"))
|
||||
?.get(1)?.crc32() ?: return@forEach
|
||||
val topic = examElement.child(0).text().trim()
|
||||
|
||||
val subjectElement = examElement.child(1).child(0)
|
||||
val subjectId = EDUDZIENNIK_SUBJECT_ID.find(subjectElement.attr("href"))?.get(1)
|
||||
?: return@forEach
|
||||
val subjectName = subjectElement.text().trim()
|
||||
val subject = data.getSubject(subjectId, subjectName)
|
||||
|
||||
val dateString = examElement.child(2).text().trim()
|
||||
if (dateString.isBlank()) return@forEach
|
||||
val date = Date.fromY_m_d(dateString)
|
||||
|
||||
val lessons = data.app.db.timetableDao().getForDateNow(profileId, date)
|
||||
val startTime = lessons.firstOrNull { it.subjectId == subject.id }?.startTime
|
||||
|
||||
val eventTypeElement = examElement.child(3).child(0)
|
||||
val eventTypeId = EDUDZIENNIK_EVENT_TYPE_ID.find(eventTypeElement.attr("href"))?.get(1)
|
||||
?: return@forEach
|
||||
val eventTypeName = eventTypeElement.text()
|
||||
val eventType = data.getEventType(eventTypeId, eventTypeName)
|
||||
|
||||
val eventObject = Event(
|
||||
profileId,
|
||||
id,
|
||||
date,
|
||||
startTime,
|
||||
topic,
|
||||
-1,
|
||||
eventType.id.toInt(),
|
||||
false,
|
||||
-1,
|
||||
subject.id,
|
||||
data.teamClass?.id ?: -1
|
||||
)
|
||||
|
||||
data.eventList.add(eventObject)
|
||||
data.metadataList.add(Metadata(
|
||||
profileId,
|
||||
Metadata.TYPE_EVENT,
|
||||
id,
|
||||
profile.empty,
|
||||
profile.empty,
|
||||
System.currentTimeMillis()
|
||||
))
|
||||
}
|
||||
|
||||
data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_DEFAULT))
|
||||
|
||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_EXAMS, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
}
|
||||
}}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-23
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
|
||||
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.luckynumber.LuckyNumber
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class EdudziennikWebLuckyNumber(override val data: DataEdudziennik,
|
||||
val onSuccess: () -> Unit) : EdudziennikWeb(data) {
|
||||
companion object {
|
||||
private const val TAG = "EdudziennikWebLuckyNumber"
|
||||
}
|
||||
|
||||
init { data.profile?.also { profile ->
|
||||
webGet(TAG, data.schoolEndpoint + "Lucky", xhr = true) { text ->
|
||||
text.toIntOrNull()?.let { luckyNumber ->
|
||||
val luckyNumberObject = LuckyNumber(
|
||||
profileId,
|
||||
Date.getToday(),
|
||||
luckyNumber
|
||||
)
|
||||
|
||||
data.luckyNumberList.add(luckyNumberObject)
|
||||
data.metadataList.add(Metadata(
|
||||
profileId,
|
||||
Metadata.TYPE_LUCKY_NUMBER,
|
||||
luckyNumberObject.date.value.toLong(),
|
||||
profile.empty,
|
||||
profile.empty,
|
||||
System.currentTimeMillis()
|
||||
))
|
||||
}
|
||||
|
||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
}
|
||||
} ?: onSuccess() }
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-23
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
|
||||
|
||||
import org.jsoup.Jsoup
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_START
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||
|
||||
class EdudziennikWebStart(override val data: DataEdudziennik,
|
||||
val onSuccess: () -> Unit) : EdudziennikWeb(data) {
|
||||
companion object {
|
||||
private const val TAG = "EdudziennikWebStart"
|
||||
}
|
||||
|
||||
init {
|
||||
webGet(TAG, data.studentEndpoint + "start") { text ->
|
||||
val doc = Jsoup.parse(text)
|
||||
|
||||
EdudziennikWebStartInfo(data, text)
|
||||
EdudziennikWebStartGrades(data, doc)
|
||||
|
||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_START, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-24
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
|
||||
|
||||
import android.graphics.Color
|
||||
import org.jsoup.nodes.Document
|
||||
import pl.szczodrzynski.edziennik.colorFromCssName
|
||||
import pl.szczodrzynski.edziennik.crc32
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
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.metadata.Metadata
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
|
||||
class EdudziennikWebStartGrades(val data: DataEdudziennik, val doc: Document) {
|
||||
companion object {
|
||||
const val TAG = "EdudziennikWebStartGrades"
|
||||
}
|
||||
|
||||
init {data.profile?.also { profile ->
|
||||
val subjects = doc.select("#student_grades tbody").firstOrNull()?.children()
|
||||
|
||||
if (subjects.isNullOrEmpty()) return@also
|
||||
|
||||
subjects.forEach { subjectElement ->
|
||||
if (subjectElement.id().isBlank()) return@forEach
|
||||
|
||||
val subjectId = subjectElement.id().trim()
|
||||
val subjectName = subjectElement.child(0).text().trim()
|
||||
val subject = data.getSubject(subjectId, subjectName)
|
||||
|
||||
val grades = subjectElement.select(".grade")
|
||||
val gradesInfo = subjectElement.select(".grade-tip")
|
||||
|
||||
val gradeValues = subjects.select(".avg-$subjectId .grade-tip > p").first()
|
||||
.text().split('+').map {
|
||||
val split = it.split('*')
|
||||
val weight = split[0].trim().toFloat()
|
||||
val value = split[1].trim().toFloat()
|
||||
|
||||
Pair(value, weight)
|
||||
}
|
||||
|
||||
grades.forEachIndexed { index, gradeElement ->
|
||||
val id = Regexes.EDUDZIENNIK_GRADE_ID.find(gradeElement.attr("href"))?.get(1)?.crc32()
|
||||
?: return@forEachIndexed
|
||||
val (value, weight) = gradeValues[index]
|
||||
val name = gradeElement.text().trim().let {
|
||||
if (it.contains(',') || it.contains('.')) {
|
||||
val replaced = it.replace(',', '.')
|
||||
val float = replaced.toFloatOrNull()
|
||||
|
||||
if (float != null && float % 1 == 0f) float.toInt().toString()
|
||||
else it
|
||||
} else it
|
||||
}
|
||||
|
||||
val info = gradesInfo[index]
|
||||
val category = info.child(4).text().trim()
|
||||
|
||||
val (teacherLastName, teacherFirstName) = info.child(1).text().split(' ')
|
||||
val teacher = data.getTeacher(teacherFirstName, teacherLastName)
|
||||
|
||||
val addedDate = info.child(2).text().split(' ').let {
|
||||
val day = it[0].toInt()
|
||||
val month = Utils.monthFromName(it[1])
|
||||
val year = it[2].toInt()
|
||||
|
||||
Date(year, month, day).inMillis
|
||||
}
|
||||
|
||||
val color = Regexes.STYLE_CSS_COLOR.find(gradeElement.attr("style"))?.get(1)?.let {
|
||||
if (it.startsWith('#')) Color.parseColor(it)
|
||||
else colorFromCssName(it)
|
||||
} ?: -1
|
||||
|
||||
val gradeObject = Grade(
|
||||
data.profileId,
|
||||
id,
|
||||
category,
|
||||
color,
|
||||
"",
|
||||
name,
|
||||
value,
|
||||
weight,
|
||||
profile.currentSemester,
|
||||
teacher.id,
|
||||
subject.id
|
||||
)
|
||||
|
||||
data.gradeList.add(gradeObject)
|
||||
data.metadataList.add(Metadata(
|
||||
data.profileId,
|
||||
Metadata.TYPE_GRADE,
|
||||
id,
|
||||
profile.empty,
|
||||
profile.empty,
|
||||
addedDate
|
||||
))
|
||||
}
|
||||
|
||||
val proposed = subjectElement.select(".proposal").firstOrNull()?.text()?.trim()
|
||||
|
||||
if (proposed != null && proposed.isNotBlank()) {
|
||||
val proposedGradeObject = Grade(
|
||||
data.profileId,
|
||||
(-1 * subject.id) - 1,
|
||||
"",
|
||||
-1,
|
||||
"",
|
||||
proposed,
|
||||
proposed.toFloatOrNull() ?: 0f,
|
||||
0f,
|
||||
profile.currentSemester,
|
||||
-1,
|
||||
subject.id
|
||||
).apply {
|
||||
type = when (semester) {
|
||||
1 -> TYPE_SEMESTER1_PROPOSED
|
||||
else -> TYPE_SEMESTER2_PROPOSED
|
||||
}
|
||||
}
|
||||
|
||||
data.gradeList.add(proposedGradeObject)
|
||||
data.metadataList.add(Metadata(
|
||||
data.profileId,
|
||||
Metadata.TYPE_GRADE,
|
||||
proposedGradeObject.id,
|
||||
profile.empty,
|
||||
profile.empty,
|
||||
System.currentTimeMillis()
|
||||
))
|
||||
}
|
||||
|
||||
val final = subjectElement.select(".final").firstOrNull()?.text()?.trim()
|
||||
|
||||
if (final != null && final.isNotBlank()) {
|
||||
val finalGradeObject = Grade(
|
||||
data.profileId,
|
||||
(-1 * subject.id) - 2,
|
||||
"",
|
||||
-1,
|
||||
"",
|
||||
final,
|
||||
final.toFloatOrNull() ?: 0f,
|
||||
0f,
|
||||
profile.currentSemester,
|
||||
-1,
|
||||
subject.id
|
||||
).apply {
|
||||
type = when (semester) {
|
||||
1 -> TYPE_SEMESTER1_FINAL
|
||||
else -> TYPE_SEMESTER2_FINAL
|
||||
}
|
||||
}
|
||||
|
||||
data.gradeList.add(finalGradeObject)
|
||||
data.metadataList.add(Metadata(
|
||||
data.profileId,
|
||||
Metadata.TYPE_GRADE,
|
||||
finalGradeObject.id,
|
||||
profile.empty,
|
||||
profile.empty,
|
||||
System.currentTimeMillis()
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
data.toRemove.addAll(listOf(
|
||||
TYPE_NORMAL,
|
||||
TYPE_SEMESTER1_PROPOSED,
|
||||
TYPE_SEMESTER2_PROPOSED,
|
||||
TYPE_SEMESTER1_FINAL,
|
||||
TYPE_SEMESTER2_FINAL
|
||||
).map {
|
||||
DataRemoveModel.Grades.semesterWithType(profile.currentSemester, it)
|
||||
})
|
||||
}}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-24
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
|
||||
|
||||
import pl.szczodrzynski.edziennik.crc32
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_EDUDZIENNIK_WEB_TEAM_MISSING
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
|
||||
import pl.szczodrzynski.edziennik.firstLettersName
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
|
||||
class EdudziennikWebStartInfo(val data: DataEdudziennik, val text: String) {
|
||||
companion object {
|
||||
const val TAG = "EdudziennikWebStartInfo"
|
||||
}
|
||||
|
||||
init { run {
|
||||
val schoolId = Regexes.EDUDZIENNIK_SCHOOL_DETAIL_ID.find(text)?.get(1)?.trim()
|
||||
val schoolLongName = Regexes.EDUDZIENNIK_SCHOOL_DETAIL_NAME.find(text)?.get(1)?.trim()
|
||||
data.schoolId = schoolId
|
||||
|
||||
val classId = Regexes.EDUDZIENNIK_CLASS_DETAIL_ID.find(text)?.get(1)?.trim()
|
||||
val className = Regexes.EDUDZIENNIK_CLASS_DETAIL_NAME.find(text)?.get(1)?.trim()
|
||||
data.classId = classId
|
||||
|
||||
if (classId == null || className == null || schoolId == null || schoolLongName == null) {
|
||||
data.error(ApiError(TAG, ERROR_EDUDZIENNIK_WEB_TEAM_MISSING)
|
||||
.withApiResponse(text))
|
||||
return@run
|
||||
}
|
||||
|
||||
val schoolName = schoolId.crc32().toString() + schoolLongName.firstLettersName + "_edu"
|
||||
data.schoolName = schoolName
|
||||
|
||||
val teamId = classId.crc32()
|
||||
val teamCode = "$schoolName:$className"
|
||||
|
||||
val teamObject = Team(
|
||||
data.profileId,
|
||||
teamId,
|
||||
className,
|
||||
Team.TYPE_CLASS,
|
||||
teamCode,
|
||||
-1
|
||||
)
|
||||
|
||||
data.teamClass = teamObject
|
||||
data.teamList.put(teamObject.id, teamObject)
|
||||
}}
|
||||
}
|
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-23
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
|
||||
|
||||
import org.jsoup.Jsoup
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_EDUDZIENNIK_WEB_TIMETABLE_NOT_PUBLIC
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_SUBJECT_ID
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonRange
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
import pl.szczodrzynski.edziennik.getString
|
||||
import pl.szczodrzynski.edziennik.singleOrNull
|
||||
import pl.szczodrzynski.edziennik.splitName
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import pl.szczodrzynski.edziennik.utils.models.Week
|
||||
|
||||
class EdudziennikWebTimetable(override val data: DataEdudziennik,
|
||||
val onSuccess: () -> Unit) : EdudziennikWeb(data) {
|
||||
companion object {
|
||||
private const val TAG = "EdudziennikWebTimetable"
|
||||
}
|
||||
|
||||
init { data.profile?.also { profile ->
|
||||
|
||||
val currentWeekStart = Week.getWeekStart()
|
||||
|
||||
if (Date.getToday().weekDay > 4) {
|
||||
currentWeekStart.stepForward(0, 0, 7)
|
||||
}
|
||||
|
||||
val getDate = data.arguments?.getString("weekStart") ?: currentWeekStart.stringY_m_d
|
||||
|
||||
val weekStart = Date.fromY_m_d(getDate)
|
||||
val weekEnd = weekStart.clone().stepForward(0, 0, 6)
|
||||
|
||||
webGet(TAG, data.timetableEndpoint + "print?date=$getDate") { text ->
|
||||
val doc = Jsoup.parse(text)
|
||||
|
||||
val dataDays = mutableListOf<Int>()
|
||||
val dataStart = weekStart.clone()
|
||||
while (dataStart <= weekEnd) {
|
||||
dataDays += dataStart.value
|
||||
dataStart.stepForward(0, 0, 1)
|
||||
}
|
||||
|
||||
val table = doc.select("#Schedule tbody").first()
|
||||
|
||||
if (table.text().trim() == "Brak planu lekcji.") {
|
||||
data.error(ApiError(TAG, ERROR_EDUDZIENNIK_WEB_TIMETABLE_NOT_PUBLIC)
|
||||
.withApiResponse(text))
|
||||
onSuccess()
|
||||
return@webGet
|
||||
}
|
||||
|
||||
table.children().forEach { row ->
|
||||
val rowElements = row.children()
|
||||
|
||||
val lessonNumber = rowElements[0].text().toInt()
|
||||
|
||||
val times = rowElements[1].text().split('-')
|
||||
val startTime = Time.fromH_m(times[0].trim())
|
||||
val endTime = Time.fromH_m(times[1].trim())
|
||||
|
||||
data.lessonRanges.singleOrNull {
|
||||
it.lessonNumber == lessonNumber && it.startTime == startTime && it.endTime == endTime
|
||||
} ?: run {
|
||||
data.lessonRanges.put(lessonNumber, LessonRange(profileId, lessonNumber, startTime, endTime))
|
||||
}
|
||||
|
||||
rowElements.subList(2, rowElements.size).forEachIndexed { index, lesson ->
|
||||
val course = lesson.select(".course").firstOrNull() ?: return@forEachIndexed
|
||||
val info = course.select("span > span")
|
||||
|
||||
if (info.isEmpty()) return@forEachIndexed
|
||||
|
||||
val type = when (course.hasClass("substitute")) {
|
||||
true -> Lesson.TYPE_CHANGE
|
||||
else -> Lesson.TYPE_NORMAL
|
||||
}
|
||||
|
||||
/* Getting subject */
|
||||
|
||||
val subjectElement = info[0].child(0)
|
||||
val subjectId = EDUDZIENNIK_SUBJECT_ID.find(subjectElement.attr("href"))?.get(1)
|
||||
?: return@forEachIndexed
|
||||
val subjectName = subjectElement.text().trim()
|
||||
val subject = data.getSubject(subjectId, subjectName)
|
||||
|
||||
/* Getting teacher */
|
||||
|
||||
val teacherId = if (info.size >= 2) {
|
||||
val teacherElement = info[1].child(0)
|
||||
val teacherName = teacherElement.text().trim()
|
||||
teacherName.splitName()?.let { (teacherLastName, teacherFirstName) ->
|
||||
data.getTeacher(teacherFirstName, teacherLastName)
|
||||
}?.id ?: -1
|
||||
} else -1
|
||||
|
||||
val lessonObject = Lesson(profileId, -1).also {
|
||||
it.type = type
|
||||
it.date = weekStart.clone().stepForward(0, 0, index)
|
||||
it.lessonNumber = lessonNumber
|
||||
it.startTime = startTime
|
||||
it.endTime = endTime
|
||||
it.subjectId = subject.id
|
||||
it.teacherId = teacherId
|
||||
|
||||
it.id = it.buildId()
|
||||
}
|
||||
|
||||
data.lessonNewList.add(lessonObject)
|
||||
dataDays.remove(lessonObject.date!!.value)
|
||||
|
||||
if (type != Lesson.TYPE_NORMAL) {
|
||||
val seen = profile.empty || lessonObject.date!! < Date.getToday()
|
||||
|
||||
data.metadataList.add(Metadata(
|
||||
profileId,
|
||||
Metadata.TYPE_LESSON_CHANGE,
|
||||
lessonObject.id,
|
||||
seen,
|
||||
seen,
|
||||
System.currentTimeMillis()
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (day in dataDays) {
|
||||
val lessonDate = Date.fromValue(day)
|
||||
data.lessonNewList += Lesson(profileId, lessonDate.value.toLong()).apply {
|
||||
type = Lesson.TYPE_NO_LESSONS
|
||||
date = lessonDate
|
||||
}
|
||||
}
|
||||
|
||||
d(TAG, "Clearing lessons between ${weekStart.stringY_m_d} and ${weekEnd.stringY_m_d} - timetable downloaded for $getDate")
|
||||
|
||||
if (data.timetableNotPublic) data.timetableNotPublic = false
|
||||
|
||||
data.toRemove.add(DataRemoveModel.Timetable.between(weekStart, weekEnd))
|
||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
}
|
||||
} ?: onSuccess() }
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-22
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.firstlogin
|
||||
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_ACCOUNT_NAME_START
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_STUDENTS_START
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.login.EdudziennikLoginWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||
import pl.szczodrzynski.edziennik.fixName
|
||||
import pl.szczodrzynski.edziennik.get
|
||||
import pl.szczodrzynski.edziennik.getShortName
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
|
||||
class EdudziennikFirstLogin(val data: DataEdudziennik, val onSuccess: () -> Unit) {
|
||||
companion object {
|
||||
private const val TAG = "EdudziennikFirstLogin"
|
||||
}
|
||||
|
||||
private val web = EdudziennikWeb(data)
|
||||
private val profileList = mutableListOf<Profile>()
|
||||
|
||||
init {
|
||||
EdudziennikLoginWeb(data) {
|
||||
web.webGet(TAG, "") { text ->
|
||||
val accountName = EDUDZIENNIK_ACCOUNT_NAME_START.find(text)?.get(1)?.fixName()
|
||||
|
||||
EDUDZIENNIK_STUDENTS_START.findAll(text).forEach {
|
||||
val studentId = it[1]
|
||||
val studentName = it[2].fixName()
|
||||
|
||||
if (studentId.isBlank() || studentName.isBlank()) return@forEach
|
||||
|
||||
val profile = Profile()
|
||||
profile.studentNameLong = studentName
|
||||
profile.studentNameShort = studentName.getShortName()
|
||||
profile.accountNameLong = if (studentName == accountName) null else accountName
|
||||
profile.studentSchoolYear = Utils.getCurrentSchoolYear()
|
||||
profile.name = studentName
|
||||
profile.subname = data.loginEmail
|
||||
profile.empty = true
|
||||
profile.putStudentData("studentId", studentId)
|
||||
profileList.add(profile)
|
||||
}
|
||||
|
||||
EventBus.getDefault().post(FirstLoginFinishedEvent(profileList, data.loginStore))
|
||||
onSuccess()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-22
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.login
|
||||
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_EDUDZIENNIK_WEB
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
|
||||
class EdudziennikLogin(val data: DataEdudziennik, val onSuccess: () -> Unit) {
|
||||
companion object {
|
||||
private const val TAG = "EdudziennikLogin"
|
||||
}
|
||||
|
||||
private var cancelled = false
|
||||
|
||||
init {
|
||||
nextLoginMethod(onSuccess)
|
||||
}
|
||||
|
||||
private fun nextLoginMethod(onSuccess: () -> Unit) {
|
||||
if (data.targetLoginMethodIds.isEmpty()) {
|
||||
onSuccess()
|
||||
return
|
||||
}
|
||||
if (cancelled) {
|
||||
onSuccess()
|
||||
return
|
||||
}
|
||||
useLoginMethod(data.targetLoginMethodIds.removeAt(0)) { usedMethodId ->
|
||||
data.progress(data.progressStep)
|
||||
if (usedMethodId != -1)
|
||||
data.loginMethods.add(usedMethodId)
|
||||
nextLoginMethod(onSuccess)
|
||||
}
|
||||
}
|
||||
|
||||
private fun useLoginMethod(loginMethodId: Int, onSuccess: (usedMethodId: Int) -> Unit) {
|
||||
// this should never be true
|
||||
if (data.loginMethods.contains(loginMethodId)) {
|
||||
onSuccess(-1)
|
||||
return
|
||||
}
|
||||
Utils.d(TAG, "Using login method $loginMethodId")
|
||||
when (loginMethodId) {
|
||||
LOGIN_METHOD_EDUDZIENNIK_WEB -> {
|
||||
data.startProgress(R.string.edziennik_progress_login_edudziennik_web)
|
||||
EdudziennikLoginWeb(data) { onSuccess(loginMethodId) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-22
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.login
|
||||
|
||||
import im.wangchao.mhttp.Request
|
||||
import im.wangchao.mhttp.Response
|
||||
import im.wangchao.mhttp.callback.TextCallbackHandler
|
||||
import pl.szczodrzynski.edziennik.data.api.*
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.getUnixDate
|
||||
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
|
||||
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||
|
||||
class EdudziennikLoginWeb(val data: DataEdudziennik, val onSuccess: () -> Unit) {
|
||||
companion object {
|
||||
private const val TAG = "EdudziennikLoginWeb"
|
||||
}
|
||||
|
||||
init { run {
|
||||
if (data.isWebLoginValid()) {
|
||||
onSuccess()
|
||||
}
|
||||
else {
|
||||
data.app.cookieJar.clearForDomain("dziennikel.appspot.com")
|
||||
if (data.loginEmail.isNotNullNorEmpty() && data.loginPassword.isNotNullNorEmpty()) {
|
||||
loginWithCredentials()
|
||||
}
|
||||
else {
|
||||
data.error(ApiError(TAG, ERROR_LOGIN_DATA_MISSING))
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
private fun loginWithCredentials() {
|
||||
d(TAG, "Request: Edudziennik/Login/Web - https://dziennikel.appspot.com/login/?next=/")
|
||||
|
||||
val callback = object : TextCallbackHandler() {
|
||||
override fun onSuccess(text: String?, response: Response?) {
|
||||
if (text == null || response == null) {
|
||||
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
|
||||
.withResponse(response))
|
||||
return
|
||||
}
|
||||
|
||||
val url = response.raw().request().url().toString()
|
||||
|
||||
if (!url.contains("Student")) {
|
||||
when {
|
||||
text.contains("Wprowadzono nieprawidłową nazwę użytkownika lub hasło.") -> ERROR_LOGIN_EDUDZIENNIK_WEB_INVALID_LOGIN
|
||||
else -> ERROR_LOGIN_EDUDZIENNIK_WEB_OTHER
|
||||
}.let { errorCode ->
|
||||
data.error(ApiError(TAG, errorCode)
|
||||
.withApiResponse(text)
|
||||
.withResponse(response))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
val cookies = data.app.cookieJar.getForDomain("dziennikel.appspot.com")
|
||||
val sessionId = cookies.firstOrNull { it.name() == "sessionid" }?.value()
|
||||
|
||||
if (sessionId == null) {
|
||||
data.error(ApiError(TAG, ERROR_LOGIN_EDUDZIENNIK_WEB_NO_SESSION_ID)
|
||||
.withResponse(response)
|
||||
.withApiResponse(text))
|
||||
return
|
||||
}
|
||||
|
||||
data.webSessionId = sessionId
|
||||
data.webSessionIdExpiryTime = response.getUnixDate() + 45 * 60 /* 45 min */
|
||||
onSuccess()
|
||||
}
|
||||
|
||||
override fun onFailure(response: Response?, throwable: Throwable?) {
|
||||
data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
|
||||
.withResponse(response)
|
||||
.withThrowable(throwable))
|
||||
}
|
||||
}
|
||||
|
||||
Request.builder()
|
||||
.url("https://dziennikel.appspot.com/login/?next=/")
|
||||
.userAgent(EDUDZIENNIK_USER_AGENT)
|
||||
.contentType("application/x-www-form-urlencoded")
|
||||
.addParameter("email", data.loginEmail)
|
||||
.addParameter("password", data.loginPassword)
|
||||
.addParameter("auth_method", "password")
|
||||
.addParameter("next", "/")
|
||||
.post()
|
||||
.callback(callback)
|
||||
.build()
|
||||
.enqueue()
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_WEB_GRADES
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
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.metadata.Metadata
|
||||
@ -23,7 +24,7 @@ class IdziennikWebGrades(override val data: DataIdziennik,
|
||||
private const val TAG = "IdziennikWebGrades"
|
||||
}
|
||||
|
||||
init {
|
||||
init { data.profile?.also { profile ->
|
||||
webApiGet(TAG, IDZIENNIK_WEB_GRADES, mapOf(
|
||||
"idPozDziennika" to data.registerId
|
||||
)) { result ->
|
||||
@ -123,12 +124,12 @@ class IdziennikWebGrades(override val data: DataIdziennik,
|
||||
}
|
||||
1 -> {
|
||||
gradeObject.type = Grade.TYPE_SEMESTER1_FINAL
|
||||
gradeObject.name = name
|
||||
gradeObject.name = value.toInt().toString()
|
||||
gradeObject.weight = 0f
|
||||
}
|
||||
2 -> {
|
||||
gradeObject.type = Grade.TYPE_YEAR_FINAL
|
||||
gradeObject.name = name
|
||||
gradeObject.name = value.toInt().toString()
|
||||
gradeObject.weight = 0f
|
||||
}
|
||||
}
|
||||
@ -141,15 +142,22 @@ class IdziennikWebGrades(override val data: DataIdziennik,
|
||||
profileId,
|
||||
Metadata.TYPE_GRADE,
|
||||
id,
|
||||
data.profile?.empty ?: false,
|
||||
data.profile?.empty ?: false,
|
||||
data.profile.empty,
|
||||
data.profile.empty,
|
||||
addedDate
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
data.toRemove.addAll(listOf(
|
||||
Grade.TYPE_NORMAL,
|
||||
Grade.TYPE_SEMESTER1_FINAL,
|
||||
Grade.TYPE_YEAR_FINAL
|
||||
).map {
|
||||
DataRemoveModel.Grades.semesterWithType(profile.currentSemester, it)
|
||||
})
|
||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_GRADES, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
}
|
||||
}
|
||||
} ?: onSuccess() }
|
||||
}
|
||||
|
@ -4,13 +4,14 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web
|
||||
|
||||
import pl.szczodrzynski.edziennik.asJsonObjectList
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA
|
||||
import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_MISSING_GRADES
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.models.ApiError
|
||||
import pl.szczodrzynski.edziennik.asJsonObjectList
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
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.TYPE_SEMESTER1_PROPOSED
|
||||
@ -106,8 +107,11 @@ class IdziennikWebProposedGrades(override val data: DataIdziennik,
|
||||
}
|
||||
}
|
||||
|
||||
data.toRemove.addAll(listOf(TYPE_SEMESTER1_PROPOSED, TYPE_YEAR_PROPOSED).map {
|
||||
DataRemoveModel.Grades.semesterWithType(profile.currentSemester, it)
|
||||
})
|
||||
data.setSyncNext(ENDPOINT_IDZIENNIK_WEB_PROPOSED_GRADES, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
}
|
||||
}}
|
||||
} ?: onSuccess() }
|
||||
}
|
||||
|
@ -6,12 +6,12 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.librus
|
||||
|
||||
import okhttp3.Cookie
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.currentTimeUnix
|
||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_API
|
||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_MESSAGES
|
||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_PORTAL
|
||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_LIBRUS_SYNERGIA
|
||||
import pl.szczodrzynski.edziennik.data.api.models.Data
|
||||
import pl.szczodrzynski.edziennik.currentTimeUnix
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||
import pl.szczodrzynski.edziennik.isNotNullNorEmpty
|
||||
@ -149,7 +149,8 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
|
||||
private var mApiCode: String? = null
|
||||
var apiCode: String?
|
||||
get() { mApiCode = mApiCode ?: loginStore.getLoginData("accountCode", null); return mApiCode }
|
||||
set(value) { loginStore.putLoginData("accountCode", value) ?: return; mApiCode = value }
|
||||
set(value) {
|
||||
loginStore.putLoginData("accountCode", value); mApiCode = value }
|
||||
/**
|
||||
* A JST login PIN.
|
||||
* Used only during first login in JST mode.
|
||||
@ -157,7 +158,8 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
|
||||
private var mApiPin: String? = null
|
||||
var apiPin: String?
|
||||
get() { mApiPin = mApiPin ?: loginStore.getLoginData("accountPin", null); return mApiPin }
|
||||
set(value) { loginStore.putLoginData("accountPin", value) ?: return; mApiPin = value }
|
||||
set(value) {
|
||||
loginStore.putLoginData("accountPin", value); mApiPin = value }
|
||||
|
||||
/**
|
||||
* A Synergia API access token.
|
||||
@ -256,6 +258,7 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
|
||||
var startPointsSemester1: Int
|
||||
get() { mStartPointsSemester1 = mStartPointsSemester1 ?: profile?.getStudentData("startPointsSemester1", 0); return mStartPointsSemester1 ?: 0 }
|
||||
set(value) { profile?.putStudentData("startPointsSemester1", value) ?: return; mStartPointsSemester1 = value }
|
||||
|
||||
private var mStartPointsSemester2: Int? = null
|
||||
var startPointsSemester2: Int
|
||||
get() { mStartPointsSemester2 = mStartPointsSemester2 ?: profile?.getStudentData("startPointsSemester2", 0); return mStartPointsSemester2 ?: 0 }
|
||||
@ -265,8 +268,14 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
|
||||
var enablePointGrades: Boolean
|
||||
get() { mEnablePointGrades = mEnablePointGrades ?: profile?.getStudentData("enablePointGrades", true); return mEnablePointGrades ?: true }
|
||||
set(value) { profile?.putStudentData("enablePointGrades", value) ?: return; mEnablePointGrades = value }
|
||||
|
||||
private var mEnableDescriptiveGrades: Boolean? = null
|
||||
var enableDescriptiveGrades: Boolean
|
||||
get() { mEnableDescriptiveGrades = mEnableDescriptiveGrades ?: profile?.getStudentData("enableDescriptiveGrades", true); return mEnableDescriptiveGrades ?: true }
|
||||
set(value) { profile?.putStudentData("enableDescriptiveGrades", value) ?: return; mEnableDescriptiveGrades = value }
|
||||
|
||||
private var mTimetableNotPublic: Boolean? = null
|
||||
var timetableNotPublic: Boolean
|
||||
get() { mTimetableNotPublic = mTimetableNotPublic ?: profile?.getStudentData("timetableNotPublic", false); return mTimetableNotPublic ?: false }
|
||||
set(value) { profile?.putStudentData("timetableNotPublic", value) ?: return; mTimetableNotPublic = value }
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|
||||
}
|
||||
// TODO PORTAL CAPTCHA
|
||||
ERROR_LIBRUS_API_TIMETABLE_NOT_PUBLIC -> {
|
||||
loginStore.putLoginData("timetableNotPublic", true)
|
||||
data.timetableNotPublic = true
|
||||
data()
|
||||
}
|
||||
ERROR_LIBRUS_API_LUCKY_NUMBER_NOT_ACTIVE,
|
||||
|
@ -8,6 +8,7 @@ import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADES
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
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.GradeCategory
|
||||
@ -23,56 +24,60 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
|
||||
|
||||
private val nameFormat by lazy { DecimalFormat("#.##") }
|
||||
|
||||
init { data.profile?.let { profile ->
|
||||
init { data.profile?.also { profile ->
|
||||
apiGet(TAG, "BehaviourGrades/Points") { json ->
|
||||
|
||||
val semester1StartGradeObject = Grade(
|
||||
profileId,
|
||||
-101,
|
||||
data.app.getString(R.string.grade_start_points),
|
||||
0xffbdbdbd.toInt(),
|
||||
data.app.getString(R.string.grade_start_points_format, 1),
|
||||
nameFormat.format(data.startPointsSemester1),
|
||||
data.startPointsSemester1.toFloat(),
|
||||
-1f,
|
||||
1,
|
||||
-1,
|
||||
1
|
||||
).apply { type = Grade.TYPE_BEHAVIOUR }
|
||||
if (data.startPointsSemester1 > 0) {
|
||||
val semester1StartGradeObject = Grade(
|
||||
profileId,
|
||||
-101,
|
||||
data.app.getString(R.string.grade_start_points),
|
||||
0xffbdbdbd.toInt(),
|
||||
data.app.getString(R.string.grade_start_points_format, 1),
|
||||
nameFormat.format(data.startPointsSemester1),
|
||||
data.startPointsSemester1.toFloat(),
|
||||
-1f,
|
||||
1,
|
||||
-1,
|
||||
1
|
||||
).apply { type = Grade.TYPE_BEHAVIOUR }
|
||||
|
||||
data.gradeList.add(semester1StartGradeObject)
|
||||
data.metadataList.add(Metadata(
|
||||
profileId,
|
||||
Metadata.TYPE_GRADE,
|
||||
semester1StartGradeObject.id,
|
||||
true,
|
||||
true,
|
||||
profile.getSemesterStart(1).inMillis
|
||||
))
|
||||
data.gradeList.add(semester1StartGradeObject)
|
||||
data.metadataList.add(Metadata(
|
||||
profileId,
|
||||
Metadata.TYPE_GRADE,
|
||||
semester1StartGradeObject.id,
|
||||
true,
|
||||
true,
|
||||
profile.getSemesterStart(1).inMillis
|
||||
))
|
||||
}
|
||||
|
||||
val semester2StartGradeObject = Grade(
|
||||
profileId,
|
||||
-102,
|
||||
data.app.getString(R.string.grade_start_points),
|
||||
0xffbdbdbd.toInt(),
|
||||
data.app.getString(R.string.grade_start_points_format, 2),
|
||||
nameFormat.format(data.startPointsSemester2),
|
||||
data.startPointsSemester2.toFloat(),
|
||||
-1f,
|
||||
2,
|
||||
-1,
|
||||
1
|
||||
).apply { type = Grade.TYPE_BEHAVIOUR }
|
||||
if (data.startPointsSemester2 > 0) {
|
||||
val semester2StartGradeObject = Grade(
|
||||
profileId,
|
||||
-102,
|
||||
data.app.getString(R.string.grade_start_points),
|
||||
0xffbdbdbd.toInt(),
|
||||
data.app.getString(R.string.grade_start_points_format, 2),
|
||||
nameFormat.format(data.startPointsSemester2),
|
||||
data.startPointsSemester2.toFloat(),
|
||||
-1f,
|
||||
2,
|
||||
-1,
|
||||
1
|
||||
).apply { type = Grade.TYPE_BEHAVIOUR }
|
||||
|
||||
data.gradeList.add(semester2StartGradeObject)
|
||||
data.metadataList.add(Metadata(
|
||||
profileId,
|
||||
Metadata.TYPE_GRADE,
|
||||
semester2StartGradeObject.id,
|
||||
true,
|
||||
true,
|
||||
profile.getSemesterStart(2).inMillis
|
||||
))
|
||||
data.gradeList.add(semester2StartGradeObject)
|
||||
data.metadataList.add(Metadata(
|
||||
profileId,
|
||||
Metadata.TYPE_GRADE,
|
||||
semester2StartGradeObject.id,
|
||||
true,
|
||||
true,
|
||||
profile.getSemesterStart(2).inMillis
|
||||
))
|
||||
}
|
||||
|
||||
json.getJsonArray("Grades")?.asJsonObjectList()?.forEach { grade ->
|
||||
val id = grade.getLong("Id") ?: return@forEach
|
||||
@ -143,8 +148,9 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
|
||||
))
|
||||
}
|
||||
|
||||
data.toRemove.add(DataRemoveModel.Grades.semesterWithType(profile.currentSemester, Grade.TYPE_BEHAVIOUR))
|
||||
data.setSyncNext(ENDPOINT_LIBRUS_API_BEHAVIOUR_GRADES, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
}
|
||||
}}
|
||||
} ?: onSuccess() }
|
||||
}
|
||||
|
@ -4,8 +4,10 @@ import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.DataLibrus
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_API_NORMAL_GRADES
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.LibrusApi
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
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.utils.Utils
|
||||
@ -17,7 +19,7 @@ class LibrusApiGrades(override val data: DataLibrus,
|
||||
const val TAG = "LibrusApiGrades"
|
||||
}
|
||||
|
||||
init {
|
||||
init { data.profile?.also { profile ->
|
||||
apiGet(TAG, "Grades") { json ->
|
||||
val grades = json.getJsonArray("Grades").asJsonObjectList()
|
||||
|
||||
@ -68,15 +70,15 @@ class LibrusApiGrades(override val data: DataLibrus,
|
||||
|
||||
when {
|
||||
grade.getBoolean("IsConstituent") ?: false ->
|
||||
gradeObject.type = Grade.TYPE_NORMAL
|
||||
gradeObject.type = TYPE_NORMAL
|
||||
grade.getBoolean("IsSemester") ?: false -> // semester final
|
||||
gradeObject.type = if (gradeObject.semester == 1) Grade.TYPE_SEMESTER1_FINAL else Grade.TYPE_SEMESTER2_FINAL
|
||||
gradeObject.type = if (gradeObject.semester == 1) TYPE_SEMESTER1_FINAL else TYPE_SEMESTER2_FINAL
|
||||
grade.getBoolean("IsSemesterProposition") ?: false -> // semester proposed
|
||||
gradeObject.type = if (gradeObject.semester == 1) Grade.TYPE_SEMESTER1_PROPOSED else Grade.TYPE_SEMESTER2_PROPOSED
|
||||
gradeObject.type = if (gradeObject.semester == 1) TYPE_SEMESTER1_PROPOSED else TYPE_SEMESTER2_PROPOSED
|
||||
grade.getBoolean("IsFinal") ?: false -> // year final
|
||||
gradeObject.type = Grade.TYPE_YEAR_FINAL
|
||||
gradeObject.type = TYPE_YEAR_FINAL
|
||||
grade.getBoolean("IsFinalProposition") ?: false -> // year final
|
||||
gradeObject.type = Grade.TYPE_YEAR_PROPOSED
|
||||
gradeObject.type = TYPE_YEAR_PROPOSED
|
||||
}
|
||||
|
||||
grade.getJsonObject("Improvement")?.also {
|
||||
@ -94,14 +96,25 @@ class LibrusApiGrades(override val data: DataLibrus,
|
||||
profileId,
|
||||
Metadata.TYPE_GRADE,
|
||||
id,
|
||||
profile?.empty ?: false,
|
||||
profile?.empty ?: false,
|
||||
profile.empty,
|
||||
profile.empty,
|
||||
addedDate
|
||||
))
|
||||
}
|
||||
|
||||
data.toRemove.addAll(listOf(
|
||||
TYPE_NORMAL,
|
||||
TYPE_SEMESTER1_FINAL,
|
||||
TYPE_SEMESTER2_FINAL,
|
||||
TYPE_SEMESTER1_PROPOSED,
|
||||
TYPE_SEMESTER2_PROPOSED,
|
||||
TYPE_YEAR_FINAL,
|
||||
TYPE_YEAR_PROPOSED
|
||||
).map {
|
||||
DataRemoveModel.Grades.semesterWithType(profile.currentSemester, it)
|
||||
})
|
||||
data.setSyncNext(ENDPOINT_LIBRUS_API_NORMAL_GRADES, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
}
|
||||
}
|
||||
} ?: onSuccess() }
|
||||
}
|
||||
|
@ -26,12 +26,7 @@ class LibrusApiSchools(override val data: DataLibrus,
|
||||
|
||||
// create the school's short name using first letters of each long name's word
|
||||
// append the town name and save to student data
|
||||
var schoolNameShort = ""
|
||||
schoolNameLong?.split(" ")?.forEach {
|
||||
if (it.isBlank())
|
||||
return@forEach
|
||||
schoolNameShort += it[0].toLowerCase()
|
||||
}
|
||||
val schoolNameShort = schoolNameLong?.firstLettersName
|
||||
val schoolTown = school?.getString("Town")?.toLowerCase(Locale.getDefault())
|
||||
data.schoolName = schoolId.toString() + schoolNameShort + "_" + schoolTown
|
||||
|
||||
|
@ -69,6 +69,8 @@ class LibrusApiTimetables(override val data: DataLibrus,
|
||||
|
||||
d(TAG, "Clearing lessons between ${weekStart.stringY_m_d} and ${weekEnd.stringY_m_d} - timetable downloaded for $getDate")
|
||||
|
||||
if (data.timetableNotPublic) data.timetableNotPublic = false
|
||||
|
||||
data.toRemove.add(DataRemoveModel.Timetable.between(weekStart, weekEnd))
|
||||
data.setSyncNext(ENDPOINT_LIBRUS_API_TIMETABLES, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
|
@ -5,12 +5,13 @@
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api
|
||||
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
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.metadata.Metadata
|
||||
|
||||
class MobidziennikApiGrades(val data: DataMobidziennik, rows: List<String>) {
|
||||
init { run {
|
||||
init { data.profile?.also { profile -> run {
|
||||
data.db.gradeDao().getDetails(
|
||||
data.profileId,
|
||||
data.gradeAddedDates,
|
||||
@ -73,6 +74,17 @@ class MobidziennikApiGrades(val data: DataMobidziennik, rows: List<String>) {
|
||||
subjectId)
|
||||
gradeObject.type = type
|
||||
|
||||
data.toRemove.addAll(listOf(
|
||||
TYPE_NORMAL,
|
||||
TYPE_SEMESTER1_FINAL,
|
||||
TYPE_SEMESTER2_FINAL,
|
||||
TYPE_SEMESTER1_PROPOSED,
|
||||
TYPE_SEMESTER2_PROPOSED,
|
||||
TYPE_YEAR_FINAL,
|
||||
TYPE_YEAR_PROPOSED
|
||||
).map {
|
||||
DataRemoveModel.Grades.semesterWithType(profile.currentSemester, it)
|
||||
})
|
||||
data.gradeList.add(gradeObject)
|
||||
data.metadataList.add(
|
||||
Metadata(
|
||||
@ -85,5 +97,5 @@ class MobidziennikApiGrades(val data: DataMobidziennik, rows: List<String>) {
|
||||
))
|
||||
addedDate++
|
||||
}
|
||||
}}
|
||||
}}}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import pl.szczodrzynski.edziennik.data.api.Regexes
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_GRADES
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
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.metadata.Metadata
|
||||
@ -25,8 +26,10 @@ class MobidziennikWebGrades(override val data: DataMobidziennik,
|
||||
private const val TAG = "MobidziennikWebGrades"
|
||||
}
|
||||
|
||||
init {
|
||||
webGet(TAG, "/dziennik/oceny?semestr=${profile?.currentSemester ?: 1}") { text ->
|
||||
init { data.profile?.also { profile ->
|
||||
val currentSemester = profile.currentSemester
|
||||
|
||||
webGet(TAG, "/dziennik/oceny?semestr=$currentSemester") { text ->
|
||||
MobidziennikLuckyNumberExtractor(data, text)
|
||||
|
||||
val doc = Jsoup.parse(text)
|
||||
@ -90,7 +93,7 @@ class MobidziennikWebGrades(override val data: DataMobidziennik,
|
||||
)
|
||||
val time = Time.fromH_m_s(it[4])
|
||||
gradeAddedDateMillis = gradeAddedDate.combineWith(time)
|
||||
gradeSemester = profile?.dateToSemester(gradeAddedDate) ?: 1
|
||||
gradeSemester = profile.dateToSemester(gradeAddedDate)
|
||||
}
|
||||
|
||||
if (Regexes.MOBIDZIENNIK_GRADES_COUNT_TO_AVG.containsMatchIn(html)) {
|
||||
@ -129,8 +132,8 @@ class MobidziennikWebGrades(override val data: DataMobidziennik,
|
||||
profileId,
|
||||
Metadata.TYPE_GRADE,
|
||||
gradeObject.id,
|
||||
profile?.empty ?: false,
|
||||
profile?.empty ?: false,
|
||||
profile.empty,
|
||||
profile.empty,
|
||||
gradeAddedDateMillis
|
||||
))
|
||||
}
|
||||
@ -143,8 +146,9 @@ class MobidziennikWebGrades(override val data: DataMobidziennik,
|
||||
}
|
||||
}
|
||||
|
||||
data.toRemove.add(DataRemoveModel.Grades.semesterWithType(currentSemester, Grade.TYPE_NORMAL))
|
||||
data.setSyncNext(ENDPOINT_MOBIDZIENNIK_WEB_GRADES, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
}
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.Mobidzie
|
||||
import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||
import pl.szczodrzynski.edziennik.fixName
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
|
||||
class MobidziennikFirstLogin(val data: DataMobidziennik, val onSuccess: () -> Unit) {
|
||||
companion object {
|
||||
@ -39,12 +39,11 @@ class MobidziennikFirstLogin(val data: DataMobidziennik, val onSuccess: () -> Un
|
||||
if (student1.size == 2)
|
||||
return@forEach
|
||||
|
||||
val today = Date.getToday()
|
||||
val profile = Profile()
|
||||
profile.studentNameLong = "${student1[2]} ${student1[4]}".fixName()
|
||||
profile.studentNameShort = "${student1[2]} ${student1[4][0]}.".fixName()
|
||||
profile.accountNameLong = if (accountNameLong == profile.studentNameLong) null else accountNameLong
|
||||
profile.studentSchoolYear = "${today.year}/${today.year+1}"
|
||||
profile.studentSchoolYear = Utils.getCurrentSchoolYear()
|
||||
profile.name = profile.studentNameLong
|
||||
profile.subname = data.loginUsername
|
||||
profile.empty = true
|
||||
|
@ -9,6 +9,7 @@ import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_GRADES
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_GRADES
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
|
||||
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||
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.metadata.Metadata
|
||||
@ -109,6 +110,7 @@ class VulcanApiGrades(override val data: DataVulcan, val onSuccess: () -> Unit)
|
||||
))
|
||||
}
|
||||
|
||||
data.toRemove.add(DataRemoveModel.Grades.semesterWithType(data.studentSemesterNumber, Grade.TYPE_NORMAL))
|
||||
data.setSyncNext(ENDPOINT_VULCAN_API_GRADES, SYNC_ALWAYS)
|
||||
onSuccess()
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ class VulcanApiMessagesInbox(override val data: DataVulcan, val onSuccess: () ->
|
||||
|
||||
val senderName = message.getString("Nadawca") ?: ""
|
||||
|
||||
senderName.getLastFirstName()?.let { (senderLastName, senderFirstName) ->
|
||||
senderName.splitName()?.let { (senderLastName, senderFirstName) ->
|
||||
val teacherObject = Teacher(
|
||||
profileId,
|
||||
-1 * Utils.crc16(senderName.toByteArray()).toLong(),
|
||||
|
@ -54,7 +54,7 @@ class VulcanApiMessagesSent(override val data: DataVulcan, val onSuccess: () ->
|
||||
?: {
|
||||
val receiverName = receiver.getString("Nazwa") ?: ""
|
||||
|
||||
receiverName.getLastFirstName()?.let { (receiverLastName, receiverFirstName) ->
|
||||
receiverName.splitName()?.let { (receiverLastName, receiverFirstName) ->
|
||||
val teacherObject = Teacher(
|
||||
profileId,
|
||||
-1 * Utils.crc16(receiverName.toByteArray()).toLong(),
|
||||
|
@ -6,7 +6,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api
|
||||
|
||||
import androidx.core.util.set
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes.VULCAN_SHIFT_ANNOTATION
|
||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_TIMETABLE
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_TIMETABLE
|
||||
@ -144,7 +144,7 @@ class VulcanApiTimetable(override val data: DataVulcan, val onSuccess: () -> Uni
|
||||
}
|
||||
|
||||
if (type == Lesson.TYPE_SHIFTED_SOURCE || type == Lesson.TYPE_SHIFTED_TARGET) {
|
||||
val shift = Regexes.VULCAN_SHITFT_ANNOTATION.find(changeAnnotation)
|
||||
val shift = VULCAN_SHIFT_ANNOTATION.find(changeAnnotation)
|
||||
val oldLessonNumber = shift?.get(2)?.toInt()
|
||||
val oldLessonDate = shift?.get(3)?.let { Date.fromd_m_Y(it) }
|
||||
|
||||
|
@ -27,17 +27,23 @@ open class DataRemoveModel {
|
||||
}
|
||||
}
|
||||
|
||||
class Grades(private val all: Boolean, private val semester: Int?) : DataRemoveModel() {
|
||||
class Grades(private val all: Boolean, private val semester: Int?, private val type: Int?) : DataRemoveModel() {
|
||||
companion object {
|
||||
fun all() = Grades(true, null)
|
||||
fun semester(semester: Int) = Grades(false, semester)
|
||||
fun all() = Grades(true, null, null)
|
||||
fun allWithType(type: Int) = Grades(true, null, type)
|
||||
fun semester(semester: Int) = Grades(false, semester, null)
|
||||
fun semesterWithType(semester: Int, type: Int) = Grades(false, semester, type)
|
||||
}
|
||||
|
||||
fun commit(profileId: Int, dao: GradeDao) {
|
||||
if (all) {
|
||||
dao.clear(profileId)
|
||||
if (type != null) dao.clearWithType(profileId, type)
|
||||
else dao.clear(profileId)
|
||||
}
|
||||
semester?.let {
|
||||
if (type != null) dao.clearForSemesterWithType(profileId, it, type)
|
||||
else dao.clearForSemester(profileId, it)
|
||||
}
|
||||
semester?.let { dao.clearForSemester(profileId, it) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ class Szkolny(val app: App, val callback: EdziennikCallback) {
|
||||
completed()
|
||||
}
|
||||
|
||||
fun shareEvent(event: EventFull) {
|
||||
/*fun shareEvent(event: EventFull) {
|
||||
api.shareEvent(event)
|
||||
completed()
|
||||
}
|
||||
@ -44,7 +44,7 @@ class Szkolny(val app: App, val callback: EdziennikCallback) {
|
||||
fun unshareEvent(event: EventFull) {
|
||||
api.unshareEvent(event)
|
||||
completed()
|
||||
}
|
||||
}*/
|
||||
|
||||
private fun completed() {
|
||||
callback.onCompleted()
|
||||
|
@ -15,7 +15,9 @@ import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.SignatureIntercep
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.request.EventShareRequest
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.request.ServerSyncRequest
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.request.WebPushRequest
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.response.ApiResponse
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.response.WebPushResponse
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.ProfileFull
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
@ -102,29 +104,33 @@ class SzkolnyApi(val app: App) {
|
||||
return events
|
||||
}
|
||||
|
||||
fun shareEvent(event: EventFull) {
|
||||
fun shareEvent(event: EventFull): ApiResponse<Nothing>? {
|
||||
val team = app.db.teamDao().getByIdNow(event.profileId, event.teamId)
|
||||
|
||||
api.shareEvent(EventShareRequest(
|
||||
return api.shareEvent(EventShareRequest(
|
||||
deviceId = app.deviceId,
|
||||
sharedByName = event.sharedByName,
|
||||
shareTeamCode = team.code,
|
||||
event = event
|
||||
)).execute()
|
||||
)).execute().body()
|
||||
}
|
||||
|
||||
fun unshareEvent(event: EventFull) {
|
||||
fun unshareEvent(event: Event): ApiResponse<Nothing>? {
|
||||
val team = app.db.teamDao().getByIdNow(event.profileId, event.teamId)
|
||||
|
||||
api.shareEvent(EventShareRequest(
|
||||
return api.shareEvent(EventShareRequest(
|
||||
deviceId = app.deviceId,
|
||||
sharedByName = event.sharedByName,
|
||||
unshareTeamCode = team.code,
|
||||
eventId = event.id
|
||||
)).execute()
|
||||
)).execute().body()
|
||||
}
|
||||
|
||||
fun pairBrowser(browserId: String?, pairToken: String?): List<WebPushResponse.Browser> {
|
||||
/*fun eventEditRequest(requesterName: String, event: Event): ApiResponse<Nothing>? {
|
||||
|
||||
}*/
|
||||
|
||||
fun pairBrowser(browserId: String?, pairToken: String?, onError: ((List<ApiResponse.Error>) -> Unit)? = null): List<WebPushResponse.Browser> {
|
||||
val response = api.webPush(WebPushRequest(
|
||||
action = "pairBrowser",
|
||||
deviceId = app.deviceId,
|
||||
@ -132,10 +138,15 @@ class SzkolnyApi(val app: App) {
|
||||
pairToken = pairToken
|
||||
)).execute().body()
|
||||
|
||||
response?.errors?.let {
|
||||
onError?.invoke(it)
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
return response?.data?.browsers ?: emptyList()
|
||||
}
|
||||
|
||||
fun listBrowsers(): List<WebPushResponse.Browser> {
|
||||
fun listBrowsers(onError: ((List<ApiResponse.Error>) -> Unit)? = null): List<WebPushResponse.Browser> {
|
||||
val response = api.webPush(WebPushRequest(
|
||||
action = "listBrowsers",
|
||||
deviceId = app.deviceId
|
||||
|
@ -46,6 +46,6 @@ object Signing {
|
||||
|
||||
/*fun provideKey(param1: String, param2: Long): ByteArray {*/
|
||||
fun pleaseStopRightNow(param1: String, param2: Long): ByteArray {
|
||||
return "$param1.MTIzNDU2Nzg5MDnJqFBfu7===.$param2".sha256()
|
||||
return "$param1.MTIzNDU2Nzg5MDpOm94zKC===.$param2".sha256()
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ data class EventShareRequest (
|
||||
val sharedByName: String,
|
||||
val shareTeamCode: String? = null,
|
||||
val unshareTeamCode: String? = null,
|
||||
val requesterName: String? = null,
|
||||
|
||||
val eventId: Long? = null,
|
||||
val event: EventFull? = null
|
||||
|
@ -4,6 +4,7 @@ import com.google.gson.JsonObject
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.api.*
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.Edudziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.Idziennik
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.Librus
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.Mobidziennik
|
||||
@ -59,6 +60,7 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
|
||||
LOGIN_TYPE_MOBIDZIENNIK -> Mobidziennik(app, profile, loginStore, taskCallback)
|
||||
LOGIN_TYPE_VULCAN -> Vulcan(app, profile, loginStore, taskCallback)
|
||||
LOGIN_TYPE_IDZIENNIK -> Idziennik(app, profile, loginStore, taskCallback)
|
||||
LOGIN_TYPE_EDUDZIENNIK -> Edudziennik(app, profile, loginStore, taskCallback)
|
||||
LOGIN_TYPE_TEMPLATE -> Template(app, profile, loginStore, taskCallback)
|
||||
else -> null
|
||||
}
|
||||
|
@ -16,8 +16,8 @@ class SzkolnyTask(val request: Any) : IApiTask(-1) {
|
||||
private const val TAG = "SzkolnyTask"
|
||||
|
||||
fun sync(profiles: List<ProfileFull>) = SzkolnyTask(SyncRequest(profiles))
|
||||
fun shareEvent(event: EventFull) = SzkolnyTask(ShareEventRequest(event))
|
||||
fun unshareEvent(event: EventFull) = SzkolnyTask(UnshareEventRequest(event))
|
||||
/*fun shareEvent(event: EventFull) = SzkolnyTask(ShareEventRequest(event))
|
||||
fun unshareEvent(event: EventFull) = SzkolnyTask(UnshareEventRequest(event))*/
|
||||
}
|
||||
|
||||
private lateinit var szkolny: Szkolny
|
||||
@ -35,12 +35,12 @@ class SzkolnyTask(val request: Any) : IApiTask(-1) {
|
||||
|
||||
when (request) {
|
||||
is SyncRequest -> szkolny.sync(request.profiles)
|
||||
is ShareEventRequest -> szkolny.shareEvent(request.event)
|
||||
is UnshareEventRequest -> szkolny.unshareEvent(request.event)
|
||||
/*is ShareEventRequest -> szkolny.shareEvent(request.event)
|
||||
is UnshareEventRequest -> szkolny.unshareEvent(request.event)*/
|
||||
}
|
||||
}
|
||||
|
||||
data class SyncRequest(val profiles: List<ProfileFull>)
|
||||
data class ShareEventRequest(val event: EventFull)
|
||||
data class UnshareEventRequest(val event: EventFull)
|
||||
/*data class ShareEventRequest(val event: EventFull)
|
||||
data class UnshareEventRequest(val event: EventFull)*/
|
||||
}
|
||||
|
@ -27,9 +27,15 @@ public abstract class GradeDao {
|
||||
@Query("DELETE FROM grades WHERE profileId = :profileId")
|
||||
public abstract void clear(int profileId);
|
||||
|
||||
@Query("DELETE FROM grades WHERE profileId = :profileId AND gradeType = :type")
|
||||
public abstract void clearWithType(int profileId, int type);
|
||||
|
||||
@Query("DELETE FROM grades WHERE profileId = :profileId AND gradeSemester = :semester")
|
||||
public abstract void clearForSemester(int profileId, int semester);
|
||||
|
||||
@Query("DELETE FROM grades WHERE profileId = :profileId AND gradeSemester = :semester AND gradeType = :type")
|
||||
public abstract void clearForSemesterWithType(int profileId, int semester, int type);
|
||||
|
||||
@RawQuery(observedEntities = {Grade.class})
|
||||
abstract LiveData<List<GradeFull>> getAll(SupportSQLiteQuery query);
|
||||
public LiveData<List<GradeFull>> getAll(int profileId, String filter, String orderBy) {
|
||||
|
@ -12,6 +12,8 @@ import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_GRADES
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_HOMEWORK
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_TIMETABLE
|
||||
import pl.szczodrzynski.edziennik.crc32
|
||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_EDUDZIENNIK
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.*
|
||||
import java.util.*
|
||||
@ -35,6 +37,7 @@ class ProfileFull : Profile {
|
||||
LOGIN_TYPE_LIBRUS -> getStudentData("schoolName", "LIBRUS_UN") + ":" + getStudentData("accountLogin", "LIBRUS_LOGIN_UN")
|
||||
LOGIN_TYPE_IUCZNIOWIE -> getLoginData("schoolName", "IUCZNIOWIE_UN") + ":" + getLoginData("username", "IUCZNIOWIE_UN") + ":" + getStudentData("registerId", -1)
|
||||
LOGIN_TYPE_VULCAN -> getStudentData("schoolName", "VULCAN_UN") + ":" + getStudentData("studentId", -1)
|
||||
LOGIN_TYPE_EDUDZIENNIK -> getStudentData("schoolName", "EDU_UN") + ":" + getLoginData("email", "EDU_UN") + ":" + getStudentData("studentId", null)?.crc32()
|
||||
LOGIN_TYPE_DEMO -> getLoginData("serverName", "DEMO_UN") + ":" + getLoginData("username", "DEMO_UN") + ":" + getStudentData("studentId", -1)
|
||||
else -> "TYPE_UNKNOWN"
|
||||
}
|
||||
@ -57,19 +60,7 @@ class ProfileFull : Profile {
|
||||
fragmentIds.add(DRAWER_ITEM_ATTENDANCE)
|
||||
return fragmentIds
|
||||
}
|
||||
LOGIN_TYPE_LIBRUS -> {
|
||||
fragmentIds = ArrayList()
|
||||
fragmentIds.add(DRAWER_ITEM_TIMETABLE)
|
||||
fragmentIds.add(DRAWER_ITEM_AGENDA)
|
||||
fragmentIds.add(DRAWER_ITEM_GRADES)
|
||||
fragmentIds.add(DRAWER_ITEM_MESSAGES)
|
||||
fragmentIds.add(DRAWER_ITEM_HOMEWORK)
|
||||
fragmentIds.add(DRAWER_ITEM_BEHAVIOUR)
|
||||
fragmentIds.add(DRAWER_ITEM_ATTENDANCE)
|
||||
fragmentIds.add(DRAWER_ITEM_ANNOUNCEMENTS)
|
||||
return fragmentIds
|
||||
}
|
||||
LOGIN_TYPE_IUCZNIOWIE -> {
|
||||
LOGIN_TYPE_LIBRUS, LOGIN_TYPE_IUCZNIOWIE, LOGIN_TYPE_EDUDZIENNIK -> {
|
||||
fragmentIds = ArrayList()
|
||||
fragmentIds.add(DRAWER_ITEM_TIMETABLE)
|
||||
fragmentIds.add(DRAWER_ITEM_AGENDA)
|
||||
|
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-20
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.bell
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogBellSyncBinding
|
||||
import pl.szczodrzynski.edziennik.startCoroutineTimer
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class BellSyncDialog(
|
||||
val activity: AppCompatActivity,
|
||||
private val bellTime: Time,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
|
||||
companion object {
|
||||
const val TAG = "BellSyncDialog"
|
||||
}
|
||||
|
||||
private lateinit var job: Job
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
private lateinit var dialog: AlertDialog
|
||||
private lateinit var b: DialogBellSyncBinding
|
||||
|
||||
private val app by lazy { activity.application as App }
|
||||
|
||||
private var counterJob: Job? = null
|
||||
|
||||
private val actualBellDiff: Pair<Time, Int>
|
||||
get() {
|
||||
val now = Time.getNow()
|
||||
val bellDiff = Time.diff(now, bellTime)
|
||||
val multiplier = if (bellTime > now) -1 else 1
|
||||
return Pair(bellDiff, multiplier)
|
||||
}
|
||||
|
||||
init { apply {
|
||||
if (activity.isFinishing)
|
||||
return@apply
|
||||
job = Job()
|
||||
b = DialogBellSyncBinding.inflate(activity.layoutInflater)
|
||||
onShowListener?.invoke(TAG)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.bell_sync_title)
|
||||
.setView(b.root)
|
||||
.setNeutralButton(R.string.cancel) { dialog, _ -> dialog.dismiss() }
|
||||
.setOnDismissListener {
|
||||
counterJob?.cancel()
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.show()
|
||||
initView()
|
||||
}}
|
||||
|
||||
private fun initView() {
|
||||
b.bellSyncButton.setOnClickListener {
|
||||
val (bellDiff, multiplier) = actualBellDiff
|
||||
val bellDiffText = (if (multiplier == -1) '-' else '+') + bellDiff.stringHMS
|
||||
app.config.timetable.bellSyncDiff = bellDiff
|
||||
app.config.timetable.bellSyncMultiplier = multiplier
|
||||
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.bell_sync_title)
|
||||
.setMessage(app.getString(R.string.bell_sync_results, bellDiffText))
|
||||
.setPositiveButton(R.string.ok) { resultsDialog, _ ->
|
||||
resultsDialog.dismiss()
|
||||
dialog.dismiss()
|
||||
if (activity is MainActivity) activity.reloadTarget()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
if (Time.diff(Time.getNow(), bellTime) > Time(2, 0, 0)) { // Easter egg ^^
|
||||
b.bellSyncButton.setImageDrawable(app.resources.getDrawable(R.drawable.ic_bell_wtf)) // wtf
|
||||
}
|
||||
|
||||
launch {
|
||||
counterJob = startCoroutineTimer(repeatMillis = 1000) {
|
||||
val (bellDiff, multiplier) = actualBellDiff
|
||||
val bellDiffText = (if (multiplier == -1) '-' else '+') + bellDiff.stringHMS
|
||||
b.bellSyncHowto.text = app.getString(R.string.bell_sync_howto, bellTime.stringHM, bellDiffText)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-20
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.dialogs.bell
|
||||
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.*
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogBellSyncTimeChooseBinding
|
||||
import pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class BellSyncTimeChooseDialog(
|
||||
val activity: AppCompatActivity,
|
||||
val onShowListener: ((tag: String) -> Unit)? = null,
|
||||
val onDismissListener: ((tag: String) -> Unit)? = null
|
||||
) : CoroutineScope {
|
||||
|
||||
companion object {
|
||||
const val TAG = "BellSyncTimeChooseDialog"
|
||||
|
||||
private const val MAX_DIFF_MINUTES = 10
|
||||
}
|
||||
|
||||
private lateinit var job: Job
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
private lateinit var dialog: AlertDialog
|
||||
private lateinit var b: DialogBellSyncTimeChooseBinding
|
||||
|
||||
private val app by lazy { activity.application as App }
|
||||
|
||||
private val today = Date.getToday()
|
||||
private val selectedTime: Time?
|
||||
get() = b.timeDropdown.selected?.tag as Time?
|
||||
|
||||
init { apply {
|
||||
if (activity.isFinishing)
|
||||
return@apply
|
||||
job = Job()
|
||||
b = DialogBellSyncTimeChooseBinding.inflate(activity.layoutInflater)
|
||||
onShowListener?.invoke(TAG)
|
||||
dialog = MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.bell_sync_title)
|
||||
.setView(b.root)
|
||||
.setPositiveButton(R.string.ok) { dialog, _ ->
|
||||
dialog.dismiss()
|
||||
selectedTime?.let {
|
||||
BellSyncDialog(activity, it)
|
||||
}
|
||||
}
|
||||
.setNegativeButton(R.string.cancel) { dialog, _ -> dialog.dismiss() }
|
||||
.setOnDismissListener {
|
||||
onDismissListener?.invoke(TAG)
|
||||
}
|
||||
.create()
|
||||
.apply {
|
||||
setButton(AlertDialog.BUTTON_NEUTRAL, app.getString(R.string.reset)) { _, _ ->
|
||||
showResetDialog()
|
||||
}
|
||||
}
|
||||
|
||||
initView()
|
||||
}}
|
||||
|
||||
private fun initView() {
|
||||
b.bellSyncHowto.text = app.getString(R.string.bell_sync_choose_howto)
|
||||
|
||||
app.config.timetable.bellSyncDiff?.let { bellDiff ->
|
||||
val multiplier = app.config.timetable.bellSyncMultiplier
|
||||
val bellDiffText = (if (multiplier == -1) '-' else '+') + bellDiff.stringHMS
|
||||
b.bellSyncHowto.text = app.getString(R.string.concat_2_strings,
|
||||
app.getString(R.string.bell_sync_choose_howto),
|
||||
app.getString(R.string.bell_sync_current_dialog, bellDiffText)
|
||||
)
|
||||
}
|
||||
|
||||
loadTimeList()
|
||||
}
|
||||
|
||||
private fun checkForLessons(timeList: List<Time>): Boolean {
|
||||
return if (timeList.isNotEmpty()) {
|
||||
val now = Time.getNow()
|
||||
val first = timeList.first()
|
||||
val last = timeList.last()
|
||||
|
||||
now.stepForward(0, MAX_DIFF_MINUTES, 0) >= first &&
|
||||
now.stepForward(0, -1 * MAX_DIFF_MINUTES, 0) <= last
|
||||
} else false
|
||||
}
|
||||
|
||||
private fun loadTimeList() { launch {
|
||||
val timeItems = withContext(Dispatchers.Default) {
|
||||
val lessons = app.db.timetableDao().getForDateNow(App.profileId, today)
|
||||
val items = mutableListOf<TextInputDropDown.Item>()
|
||||
|
||||
lessons.forEach {
|
||||
if (it.type != Lesson.TYPE_NO_LESSONS &&
|
||||
it.type != Lesson.TYPE_CANCELLED &&
|
||||
it.type != Lesson.TYPE_SHIFTED_SOURCE) {
|
||||
|
||||
items += TextInputDropDown.Item(
|
||||
it.displayStartTime?.value?.toLong() ?: return@forEach,
|
||||
app.getString(R.string.bell_sync_lesson_item, it.displaySubjectName, it.displayStartTime?.stringHM),
|
||||
tag = it.displayStartTime
|
||||
)
|
||||
|
||||
items += TextInputDropDown.Item(
|
||||
it.displayEndTime?.value?.toLong() ?: return@forEach,
|
||||
app.getString(R.string.bell_sync_break_item, it.displayEndTime?.stringHM),
|
||||
tag = it.displayEndTime
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
items
|
||||
}
|
||||
|
||||
if (!checkForLessons(timeItems.map { it.tag as Time })) {
|
||||
/* Synchronization not possible */
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.bell_sync_title)
|
||||
.setMessage(R.string.bell_sync_cannot_now)
|
||||
.setPositiveButton(R.string.ok) { dialog, _ -> dialog.dismiss() }
|
||||
.show()
|
||||
} else {
|
||||
b.timeDropdown.clear()
|
||||
b.timeDropdown.append(timeItems)
|
||||
timeItems.forEachIndexed { index, item ->
|
||||
val time = item.tag as Time
|
||||
if (time < Time.getNow()) {
|
||||
b.timeDropdown.select(if (timeItems.size > index + 1) timeItems[index + 1] else item)
|
||||
}
|
||||
}
|
||||
|
||||
b.timeDropdown.isEnabled = true
|
||||
// TODO Fix popup cutting off
|
||||
|
||||
dialog.show()
|
||||
}
|
||||
}}
|
||||
|
||||
private fun showResetDialog() {
|
||||
MaterialAlertDialogBuilder(activity)
|
||||
.setTitle(R.string.bell_sync_title)
|
||||
.setMessage(R.string.bell_sync_reset_confirm)
|
||||
.setPositiveButton(R.string.yes) { confirmDialog, _ ->
|
||||
app.config.timetable.bellSyncDiff = null
|
||||
app.config.timetable.bellSyncMultiplier = 0
|
||||
|
||||
confirmDialog.dismiss()
|
||||
initView()
|
||||
if (activity is MainActivity) activity.reloadTarget()
|
||||
}
|
||||
.setNegativeButton(R.string.no) { dialog, _ -> dialog.dismiss() }
|
||||
.show()
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@ import androidx.appcompat.app.AppCompatActivity
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import kotlinx.coroutines.*
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
|
||||
import pl.szczodrzynski.edziennik.data.api.task.SzkolnyTask
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull
|
||||
import pl.szczodrzynski.edziennik.databinding.DialogEventDetailsBinding
|
||||
@ -39,6 +40,10 @@ class EventDetailsDialog(
|
||||
|
||||
private lateinit var adapter: EventListAdapter
|
||||
|
||||
private val api by lazy {
|
||||
SzkolnyApi(app)
|
||||
}
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
return@run
|
||||
@ -126,19 +131,27 @@ class EventDetailsDialog(
|
||||
}
|
||||
|
||||
private fun removeEvent() {
|
||||
if (eventShared && eventOwn) {
|
||||
Toast.makeText(activity, "Unshare + remove own event", Toast.LENGTH_SHORT).show()
|
||||
launch {
|
||||
if (eventShared && eventOwn) {
|
||||
Toast.makeText(activity, "Unshare + remove own event", Toast.LENGTH_SHORT).show()
|
||||
|
||||
SzkolnyTask.unshareEvent(event).enqueue(activity)
|
||||
finishRemoving()
|
||||
}
|
||||
else if (eventShared && !eventOwn) {
|
||||
Toast.makeText(activity, "Remove + blacklist somebody's event", Toast.LENGTH_SHORT).show()
|
||||
// TODO
|
||||
}
|
||||
else {
|
||||
Toast.makeText(activity, "Remove event", Toast.LENGTH_SHORT).show()
|
||||
finishRemoving()
|
||||
val response = withContext(Dispatchers.Default) {
|
||||
api.unshareEvent(event!!)
|
||||
}
|
||||
|
||||
response?.errors?.ifNotEmpty {
|
||||
Toast.makeText(activity, "Error: "+it[0].reason, Toast.LENGTH_SHORT).show()
|
||||
return@launch
|
||||
}
|
||||
|
||||
finishRemoving()
|
||||
} else if (eventShared && !eventOwn) {
|
||||
Toast.makeText(activity, "Remove + blacklist somebody's event", Toast.LENGTH_SHORT).show()
|
||||
// TODO
|
||||
} else {
|
||||
Toast.makeText(activity, "Remove event", Toast.LENGTH_SHORT).show()
|
||||
finishRemoving()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ import com.jaredrummler.android.colorpicker.ColorPickerDialogListener
|
||||
import kotlinx.coroutines.*
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_AGENDA
|
||||
import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
|
||||
import pl.szczodrzynski.edziennik.data.api.task.SzkolnyTask
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull
|
||||
@ -60,13 +61,17 @@ class EventManualDialog(
|
||||
private val app by lazy { activity.application as App }
|
||||
private lateinit var b: DialogEventManualV2Binding
|
||||
private lateinit var dialog: AlertDialog
|
||||
private var removeEventDialog: AlertDialog? = null
|
||||
private var defaultLoaded = false
|
||||
|
||||
private lateinit var event: Event
|
||||
private var customColor: Int? = null
|
||||
private val editingShared = editingEvent?.sharedBy != null
|
||||
private val editingOwn = editingEvent?.sharedBy == "self"
|
||||
private var removeEventDialog: AlertDialog? = null
|
||||
private var defaultLoaded = false
|
||||
|
||||
private val api by lazy {
|
||||
SzkolnyApi(app)
|
||||
}
|
||||
|
||||
init { run {
|
||||
if (activity.isFinishing)
|
||||
@ -617,7 +622,21 @@ class EventManualDialog(
|
||||
else if (!share && editingShared) {
|
||||
Toast.makeText(activity, "Unshare own event", Toast.LENGTH_SHORT).show()
|
||||
|
||||
SzkolnyTask.unshareEvent(eventObject.withMetadata(metadataObject)).enqueue(activity)
|
||||
eventObject.apply {
|
||||
sharedBy = null
|
||||
sharedByName = profile?.studentNameLong
|
||||
}
|
||||
|
||||
val response = withContext(Dispatchers.Default) {
|
||||
api.unshareEvent(eventObject)
|
||||
}
|
||||
|
||||
response?.errors?.ifNotEmpty {
|
||||
Toast.makeText(activity, "Error: "+it[0].reason, Toast.LENGTH_SHORT).show()
|
||||
return@launch
|
||||
}
|
||||
|
||||
eventObject.sharedByName = null
|
||||
finishAdding(eventObject, metadataObject)
|
||||
}
|
||||
else if (share) {
|
||||
@ -630,7 +649,14 @@ class EventManualDialog(
|
||||
|
||||
metadataObject.addedDate = System.currentTimeMillis()
|
||||
|
||||
SzkolnyTask.shareEvent(eventObject.withMetadata(metadataObject)).enqueue(activity)
|
||||
val response = withContext(Dispatchers.Default) {
|
||||
api.shareEvent(eventObject.withMetadata(metadataObject))
|
||||
}
|
||||
|
||||
response?.errors?.ifNotEmpty {
|
||||
Toast.makeText(activity, "Error: "+it[0].reason, Toast.LENGTH_SHORT).show()
|
||||
return@launch
|
||||
}
|
||||
|
||||
eventObject.sharedBy = "self"
|
||||
finishAdding(eventObject, metadataObject)
|
||||
@ -642,19 +668,27 @@ class EventManualDialog(
|
||||
}
|
||||
|
||||
private fun removeEvent() {
|
||||
if (editingShared && editingOwn) {
|
||||
Toast.makeText(activity, "Unshare + remove own event", Toast.LENGTH_SHORT).show()
|
||||
launch {
|
||||
if (editingShared && editingOwn) {
|
||||
Toast.makeText(activity, "Unshare + remove own event", Toast.LENGTH_SHORT).show()
|
||||
|
||||
editingEvent?.let { SzkolnyTask.unshareEvent(it).enqueue(activity) }
|
||||
finishRemoving()
|
||||
}
|
||||
else if (editingShared && !editingOwn) {
|
||||
Toast.makeText(activity, "Remove + blacklist somebody's event", Toast.LENGTH_SHORT).show()
|
||||
// TODO
|
||||
}
|
||||
else {
|
||||
Toast.makeText(activity, "Remove event", Toast.LENGTH_SHORT).show()
|
||||
finishRemoving()
|
||||
val response = withContext(Dispatchers.Default) {
|
||||
api.unshareEvent(editingEvent!!)
|
||||
}
|
||||
|
||||
response?.errors?.ifNotEmpty {
|
||||
Toast.makeText(activity, "Error: "+it[0].reason, Toast.LENGTH_SHORT).show()
|
||||
return@launch
|
||||
}
|
||||
|
||||
finishRemoving()
|
||||
} else if (editingShared && !editingOwn) {
|
||||
Toast.makeText(activity, "Remove + blacklist somebody's event", Toast.LENGTH_SHORT).show()
|
||||
// TODO
|
||||
} else {
|
||||
Toast.makeText(activity, "Remove event", Toast.LENGTH_SHORT).show()
|
||||
finishRemoving()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ package pl.szczodrzynski.edziennik.ui.modules.home
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.card.MaterialCardView
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragmentV2.Companion.swapCards
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment.Companion.swapCards
|
||||
import pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator
|
||||
|
||||
class CardItemTouchHelperCallback(private val cardAdapter: HomeCardAdapter, private val refreshLayout: SwipeRefreshLayoutNoIndicator?) : ItemTouchHelper.Callback() {
|
||||
@ -46,4 +46,4 @@ class CardItemTouchHelperCallback(private val cardAdapter: HomeCardAdapter, priv
|
||||
dragCardView = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-21
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.home
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import kotlinx.coroutines.*
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.LessonFull
|
||||
import pl.szczodrzynski.edziennik.databinding.ActivityCounterBinding
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class CounterActivity : AppCompatActivity(), CoroutineScope {
|
||||
|
||||
private var job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
private var counterJob: Job? = null
|
||||
|
||||
private val app by lazy { application as App }
|
||||
private lateinit var b: ActivityCounterBinding
|
||||
|
||||
private val lessonList = mutableListOf<LessonFull>()
|
||||
|
||||
private var bellSyncDiffMillis = 0L
|
||||
private val syncedNow: Time
|
||||
get() = Time.fromMillis(Time.getNow().inMillis - bellSyncDiffMillis)
|
||||
|
||||
private val countInSeconts: Boolean
|
||||
get() = app.config.timetable.countInSeconds
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
b = ActivityCounterBinding.inflate(layoutInflater)
|
||||
setContentView(b.root)
|
||||
initView()
|
||||
}
|
||||
|
||||
private fun initView() { launch {
|
||||
withContext(Dispatchers.Default) {
|
||||
lessonList.apply {
|
||||
clear()
|
||||
addAll(app.db.timetableDao().getForDateNow(App.profileId, Date.getToday())
|
||||
.filter {
|
||||
it.type != Lesson.TYPE_NO_LESSONS && it.type != Lesson.TYPE_CANCELLED &&
|
||||
it.type != Lesson.TYPE_SHIFTED_SOURCE
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
app.config.timetable.bellSyncDiff?.let {
|
||||
bellSyncDiffMillis = (it.hour * 60 * 60 * 1000 + it.minute * 60 * 1000 + it.second * 1000).toLong()
|
||||
bellSyncDiffMillis *= app.config.timetable.bellSyncMultiplier.toLong()
|
||||
}
|
||||
|
||||
counterJob = startCoroutineTimer(repeatMillis = 1000) {
|
||||
update()
|
||||
}
|
||||
}}
|
||||
|
||||
private fun update() {
|
||||
if (lessonList.isEmpty()) {
|
||||
b.lessonName.text = app.getString(R.string.no_lessons_today)
|
||||
b.timeLeft.text = ""
|
||||
} else {
|
||||
val now = syncedNow
|
||||
|
||||
val next = lessonList.firstOrNull {
|
||||
it.displayStartTime != null && it.displayStartTime!! > now
|
||||
}
|
||||
|
||||
val actual = lessonList.firstOrNull {
|
||||
it.displayStartTime != null && it.displayEndTime != null &&
|
||||
it.displayStartTime!! <= now && now <= it.displayEndTime!!
|
||||
}
|
||||
|
||||
when {
|
||||
actual != null -> {
|
||||
b.lessonName.text = actual.displaySubjectName
|
||||
|
||||
val left = actual.displayEndTime!! - now
|
||||
b.timeLeft.text = timeLeft(left.toInt(), "\n", countInSeconts)
|
||||
}
|
||||
next != null -> {
|
||||
b.lessonName.text = next.displaySubjectName
|
||||
|
||||
val till = next.displayStartTime!! - now
|
||||
b.timeLeft.text = timeTill(till.toInt(), "\n", countInSeconts)
|
||||
}
|
||||
else -> {
|
||||
b.lessonName.text = app.getString(R.string.lessons_finished)
|
||||
b.timeLeft.text = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
counterJob?.cancel()
|
||||
}
|
||||
}
|
@ -20,11 +20,11 @@ import pl.szczodrzynski.edziennik.databinding.ActivityCounterBinding;
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date;
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time;
|
||||
|
||||
import static pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment.updateInterval;
|
||||
import static pl.szczodrzynski.edziennik.ui.modules.home.HomeFragmentOld.updateInterval;
|
||||
|
||||
public class CounterActivity extends AppCompatActivity {
|
||||
public class CounterActivityOld extends AppCompatActivity {
|
||||
|
||||
private static final String TAG = "CounterActivity";
|
||||
private static final String TAG = "CounterActivityOld";
|
||||
private App app;
|
||||
private ActivityCounterBinding b;
|
||||
|
||||
@ -153,7 +153,7 @@ public class CounterActivity extends AppCompatActivity {
|
||||
private short counterType = TIME_LEFT;
|
||||
private long updateCounter(Time syncedNow) {
|
||||
Time diff = Time.diff(counterTarget, syncedNow);
|
||||
b.timeLeft.setText(counterType == TIME_TILL ? HomeFragment.timeTill(app, diff, app.config.getTimetable().getCountInSeconds(), "\n") : HomeFragment.timeLeft(app, diff, app.config.getTimetable().getCountInSeconds(), "\n"));
|
||||
b.timeLeft.setText(counterType == TIME_TILL ? HomeFragmentOld.timeTill(app, diff, app.config.getTimetable().getCountInSeconds(), "\n") : HomeFragmentOld.timeLeft(app, diff, app.config.getTimetable().getCountInSeconds(), "\n"));
|
||||
return updateInterval(app, diff);
|
||||
}
|
||||
|
@ -26,8 +26,9 @@ import kotlinx.coroutines.Job
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.databinding.FragmentHomeV2Binding
|
||||
import pl.szczodrzynski.edziennik.databinding.FragmentHomeBinding
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.home.StudentNumberDialog
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.cards.HomeDebugCard
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.cards.HomeGradesCard
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.cards.HomeLuckyNumberCard
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.cards.HomeTimetableCard
|
||||
@ -36,7 +37,7 @@ import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem
|
||||
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class HomeFragmentV2 : Fragment(), CoroutineScope {
|
||||
class HomeFragment : Fragment(), CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "HomeFragment"
|
||||
|
||||
@ -56,7 +57,7 @@ class HomeFragmentV2 : Fragment(), CoroutineScope {
|
||||
|
||||
private lateinit var app: App
|
||||
private lateinit var activity: MainActivity
|
||||
private lateinit var b: FragmentHomeV2Binding
|
||||
private lateinit var b: FragmentHomeBinding
|
||||
|
||||
private lateinit var job: Job
|
||||
override val coroutineContext: CoroutineContext
|
||||
@ -67,7 +68,7 @@ class HomeFragmentV2 : Fragment(), CoroutineScope {
|
||||
context ?: return null
|
||||
app = activity.application as App
|
||||
context!!.theme.applyStyle(Themes.appTheme, true)
|
||||
b = FragmentHomeV2Binding.inflate(inflater)
|
||||
b = FragmentHomeBinding.inflate(inflater)
|
||||
b.refreshLayout.setParent(activity.swipeRefreshLayout)
|
||||
job = Job()
|
||||
return b.root
|
||||
@ -121,6 +122,8 @@ class HomeFragmentV2 : Fragment(), CoroutineScope {
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
if (App.devMode)
|
||||
items += HomeDebugCard(100, app, activity, this, app.profile)
|
||||
|
||||
val adapter = HomeCardAdapter(items)
|
||||
val itemTouchHelper = ItemTouchHelper(CardItemTouchHelperCallback(adapter, b.refreshLayout))
|
@ -53,7 +53,7 @@ import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile;
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.subjects.Subject;
|
||||
import pl.szczodrzynski.edziennik.databinding.CardLuckyNumberBinding;
|
||||
import pl.szczodrzynski.edziennik.databinding.CardUpdateBinding;
|
||||
import pl.szczodrzynski.edziennik.databinding.FragmentHomeBinding;
|
||||
import pl.szczodrzynski.edziennik.databinding.FragmentHomeOldBinding;
|
||||
import pl.szczodrzynski.edziennik.receivers.BootReceiver;
|
||||
import pl.szczodrzynski.edziennik.ui.modules.login.LoginLibrusCaptchaActivity;
|
||||
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesComposeActivity;
|
||||
@ -67,7 +67,6 @@ import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem;
|
||||
import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetSeparatorItem;
|
||||
|
||||
import static pl.szczodrzynski.edziennik.App.UPDATES_ON_PLAY_STORE;
|
||||
import static pl.szczodrzynski.edziennik.MainActivity.DRAWER_ITEM_GRADES;
|
||||
import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_SEMESTER1_FINAL;
|
||||
import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_SEMESTER1_PROPOSED;
|
||||
import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_SEMESTER2_FINAL;
|
||||
@ -76,11 +75,11 @@ import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_YEAR_
|
||||
import static pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.TYPE_YEAR_PROPOSED;
|
||||
import static pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore.LOGIN_TYPE_MOBIDZIENNIK;
|
||||
|
||||
public class HomeFragment extends Fragment {
|
||||
private static final String TAG = "HomeFragment";
|
||||
public class HomeFragmentOld extends Fragment {
|
||||
private static final String TAG = "HomeFragmentOld";
|
||||
private App app = null;
|
||||
private MainActivity activity = null;
|
||||
private FragmentHomeBinding b = null;
|
||||
private FragmentHomeOldBinding b = null;
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
@ -92,7 +91,7 @@ public class HomeFragment extends Fragment {
|
||||
if (app.profile == null)
|
||||
return inflater.inflate(R.layout.fragment_loading, container, false);
|
||||
// activity, context and profile is valid
|
||||
b = DataBindingUtil.inflate(inflater, R.layout.fragment_home, container, false);
|
||||
b = DataBindingUtil.inflate(inflater, R.layout.fragment_home_old, container, false);
|
||||
b.refreshLayout.setParent(activity.getSwipeRefreshLayout());
|
||||
return b.getRoot();
|
||||
}
|
||||
@ -261,7 +260,7 @@ public class HomeFragment extends Fragment {
|
||||
b.cardLuckyNumber.setOnClickListener(v1 -> setNumberDialog());
|
||||
}
|
||||
|
||||
timetableCard = new HomeTimetableCard(app, activity, this, layoutInflater, insertPoint);
|
||||
timetableCard = new HomeTimetableCardOld(app, activity, this, layoutInflater, insertPoint);
|
||||
timetableCard.run();
|
||||
|
||||
configCardGrades(activity, layoutInflater, activity, insertPoint);
|
||||
@ -571,7 +570,7 @@ public class HomeFragment extends Fragment {
|
||||
Button cardGradesButton = root.findViewById(R.id.cardGradesButton);
|
||||
buttonAddDrawable(c, cardGradesButton, CommunityMaterial.Icon.cmd_arrow_right);
|
||||
cardGradesButton.setOnClickListener((v1 -> new Handler().postDelayed(() -> a.runOnUiThread(() -> {
|
||||
activity.loadTarget(DRAWER_ITEM_GRADES, null);
|
||||
activity.loadTarget(MainActivity.DRAWER_ITEM_GRADES, null);
|
||||
}), 100)));
|
||||
|
||||
//new Handler().postDelayed(() -> a.runOnUiThread(() -> updateCardGrades(c, a, root)), newRefreshInterval);
|
||||
@ -591,5 +590,5 @@ public class HomeFragment extends Fragment {
|
||||
insertPoint.addView(root, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
}
|
||||
|
||||
private HomeTimetableCard timetableCard;
|
||||
private HomeTimetableCardOld timetableCard;
|
||||
}
|
@ -1,177 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-11-22
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.home
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.AsyncTask
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import com.afollestad.materialdialogs.DialogAction
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||
import pl.szczodrzynski.edziennik.databinding.CardTimetableBinding
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment.updateInterval
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import java.util.*
|
||||
|
||||
class HomeTimetableCard(
|
||||
private val app: App,
|
||||
private val activity: MainActivity,
|
||||
private val homeFragment: HomeFragment,
|
||||
private val layoutInflater: LayoutInflater,
|
||||
private val insertPoint: ViewGroup
|
||||
) {
|
||||
companion object {
|
||||
private const val TAG = "HomeTimetableCard"
|
||||
const val TIME_TILL = 0
|
||||
const val TIME_LEFT = 1
|
||||
}
|
||||
|
||||
private lateinit var timetableTimer: Timer
|
||||
private lateinit var b: CardTimetableBinding
|
||||
|
||||
private var bellSyncTime: Time? = null
|
||||
|
||||
private var counterType = TIME_TILL
|
||||
private val counterTarget = Time(0, 0, 0)
|
||||
|
||||
private val lessons = mutableListOf<Lesson>()
|
||||
private val events = mutableListOf<Event>()
|
||||
|
||||
fun run() {
|
||||
timetableTimer = Timer()
|
||||
b = DataBindingUtil.inflate(layoutInflater, R.layout.card_timetable, null, false)
|
||||
|
||||
update()
|
||||
|
||||
insertPoint.addView(b.root, ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT))
|
||||
|
||||
b.cardTimetableFullscreenCounter.setOnClickListener {
|
||||
activity.startActivity(Intent(activity, CounterActivity::class.java))
|
||||
}
|
||||
|
||||
b.cardTimetableBellSync.setOnClickListener {
|
||||
if (bellSyncTime == null) {
|
||||
MaterialDialog.Builder(activity)
|
||||
.title(R.string.bell_sync_title)
|
||||
.content(R.string.bell_sync_cannot_now)
|
||||
.positiveText(R.string.ok)
|
||||
.show()
|
||||
} else {
|
||||
MaterialDialog.Builder(activity)
|
||||
.title(R.string.bell_sync_title)
|
||||
.content(app.getString(R.string.bell_sync_howto, bellSyncTime!!.stringHM).toString() +
|
||||
when {
|
||||
app.config.timetable.bellSyncDiff != null -> app.getString(R.string.bell_sync_current_dialog,
|
||||
(if (app.config.timetable.bellSyncMultiplier == -1) "-" else "+") + app.config.timetable.bellSyncDiff?.stringHMS)
|
||||
else -> ""
|
||||
})
|
||||
.positiveText(R.string.ok)
|
||||
.negativeText(R.string.cancel)
|
||||
.neutralText(R.string.reset)
|
||||
.onPositive { _, _: DialogAction? ->
|
||||
val bellDiff = Time.diff(Time.getNow(), bellSyncTime)
|
||||
app.config.timetable.bellSyncDiff = bellDiff
|
||||
app.config.timetable.bellSyncMultiplier = if (bellSyncTime!!.value > Time.getNow().value) -1 else 1
|
||||
|
||||
MaterialDialog.Builder(activity)
|
||||
.title(R.string.bell_sync_title)
|
||||
.content(app.getString(R.string.bell_sync_results, if (bellSyncTime!!.value > Time.getNow().value) "-" else "+", bellDiff.stringHMS))
|
||||
.positiveText(R.string.ok)
|
||||
.show()
|
||||
}
|
||||
.onNeutral { _, _ ->
|
||||
MaterialDialog.Builder(activity)
|
||||
.title(R.string.bell_sync_title)
|
||||
.content(R.string.bell_sync_reset_confirm)
|
||||
.positiveText(R.string.yes)
|
||||
.negativeText(R.string.no)
|
||||
.onPositive { _, _ ->
|
||||
app.config.timetable.bellSyncDiff = null
|
||||
app.config.timetable.bellSyncMultiplier = 0
|
||||
app.saveConfig("bellSyncDiff", "bellSyncMultiplier")
|
||||
}
|
||||
.show()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
HomeFragment.buttonAddDrawable(activity, b.cardTimetableButton, CommunityMaterial.Icon.cmd_arrow_right)
|
||||
}
|
||||
|
||||
fun destroy() {
|
||||
try {
|
||||
timetableTimer.apply {
|
||||
cancel()
|
||||
purge()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
private fun update() {
|
||||
if (!homeFragment.isAdded) return
|
||||
|
||||
val now = Time.getNow()
|
||||
|
||||
val syncedNow: Time = when (app.config.timetable.bellSyncDiff != null) {
|
||||
true -> when {
|
||||
app.config.timetable.bellSyncMultiplier < 0 -> Time.sum(now, app.config.timetable.bellSyncDiff)
|
||||
app.config.timetable.bellSyncMultiplier > 0 -> Time.diff(now, app.config.timetable.bellSyncDiff)
|
||||
else -> now
|
||||
}
|
||||
else -> now
|
||||
}
|
||||
|
||||
if (lessons.size == 0 || syncedNow.value > counterTarget.value) {
|
||||
findLessons(syncedNow)
|
||||
} else {
|
||||
scheduleUpdate(updateCounter(syncedNow))
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateCounter(syncedNow: Time): Long {
|
||||
val diff = Time.diff(counterTarget, syncedNow)
|
||||
b.cardTimetableTimeLeft.text = when (counterType) {
|
||||
TIME_TILL -> HomeFragment.timeTill(app, diff, app.config.timetable.countInSeconds)
|
||||
else -> HomeFragment.timeLeft(app, diff, app.config.timetable.countInSeconds)
|
||||
}
|
||||
bellSyncTime = counterTarget.clone()
|
||||
b.cardTimetableFullscreenCounter.visibility = View.VISIBLE
|
||||
return updateInterval(app, diff)
|
||||
}
|
||||
|
||||
private fun scheduleUpdate(newRefreshInterval: Long) {
|
||||
timetableTimer.schedule(object : TimerTask() {
|
||||
override fun run() {
|
||||
activity.runOnUiThread { update() }
|
||||
}
|
||||
}, newRefreshInterval)
|
||||
}
|
||||
|
||||
private fun findLessons(syncedNow: Time) {
|
||||
AsyncTask.execute {
|
||||
val today = Date.getToday()
|
||||
val searchEnd = Date.getToday().stepForward(0, 0, -today.weekDay)
|
||||
|
||||
lessons.apply {
|
||||
clear()
|
||||
addAll(app.db.timetableDao().getBetweenDatesNow(today, searchEnd))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -32,21 +32,21 @@ import pl.szczodrzynski.edziennik.utils.models.Week;
|
||||
|
||||
import static pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange.TYPE_CANCELLED;
|
||||
import static pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange.TYPE_CHANGE;
|
||||
import static pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment.updateInterval;
|
||||
import static pl.szczodrzynski.edziennik.ui.modules.home.HomeFragmentOld.updateInterval;
|
||||
import static pl.szczodrzynski.edziennik.utils.Utils.bs;
|
||||
|
||||
public class HomeTimetableCardOld {
|
||||
private static final String TAG = "HomeTimetableCardOld";
|
||||
private App app;
|
||||
private MainActivity a;
|
||||
private HomeFragment f;
|
||||
private HomeFragmentOld f;
|
||||
private LayoutInflater layoutInflater;
|
||||
private ViewGroup insertPoint;
|
||||
private CardTimetableBinding b;
|
||||
private Timer timetableTimer;
|
||||
private Time bellSyncTime = null;
|
||||
|
||||
public HomeTimetableCardOld(App app, MainActivity a, HomeFragment f, LayoutInflater layoutInflater, ViewGroup insertPoint) {
|
||||
public HomeTimetableCardOld(App app, MainActivity a, HomeFragmentOld f, LayoutInflater layoutInflater, ViewGroup insertPoint) {
|
||||
this.app = app;
|
||||
this.a = a;
|
||||
this.f = f;
|
||||
@ -61,7 +61,7 @@ public class HomeTimetableCardOld {
|
||||
insertPoint.addView(b.getRoot(), new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
|
||||
|
||||
b.cardTimetableFullscreenCounter.setOnClickListener((v -> {
|
||||
Intent intent = new Intent(a, CounterActivity.class);
|
||||
Intent intent = new Intent(a, CounterActivityOld.class);
|
||||
a.startActivity(intent);
|
||||
}));
|
||||
|
||||
@ -109,7 +109,7 @@ public class HomeTimetableCardOld {
|
||||
}
|
||||
});
|
||||
|
||||
HomeFragment.buttonAddDrawable(a, b.cardTimetableButton, CommunityMaterial.Icon.cmd_arrow_right);
|
||||
HomeFragmentOld.buttonAddDrawable(a, b.cardTimetableButton, CommunityMaterial.Icon.cmd_arrow_right);
|
||||
}
|
||||
|
||||
private List<LessonFull> lessons = new ArrayList<>();
|
||||
@ -228,7 +228,7 @@ public class HomeTimetableCardOld {
|
||||
private short counterType = TIME_TILL;
|
||||
private long updateCounter(Time syncedNow) {
|
||||
Time diff = Time.diff(counterTarget, syncedNow);
|
||||
b.cardTimetableTimeLeft.setText(counterType == TIME_TILL ? HomeFragment.timeTill(app, diff, app.config.getTimetable().getCountInSeconds()) : HomeFragment.timeLeft(app, diff, app.config.getTimetable().getCountInSeconds()));
|
||||
b.cardTimetableTimeLeft.setText(counterType == TIME_TILL ? HomeFragmentOld.timeTill(app, diff, app.config.getTimetable().getCountInSeconds()) : HomeFragmentOld.timeLeft(app, diff, app.config.getTimetable().getCountInSeconds()));
|
||||
bellSyncTime = counterTarget;
|
||||
b.cardTimetableFullscreenCounter.setVisibility(View.VISIBLE);
|
||||
return updateInterval(app, diff);
|
||||
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-12-22.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.home.cards
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.view.plusAssign
|
||||
import androidx.core.view.setMargins
|
||||
import androidx.work.WorkManager
|
||||
import com.chuckerteam.chucker.api.Chucker
|
||||
import com.hypertrack.hyperlog.HyperLog
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||
import pl.szczodrzynski.edziennik.databinding.CardHomeDebugBinding
|
||||
import pl.szczodrzynski.edziennik.dp
|
||||
import pl.szczodrzynski.edziennik.onClick
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeCard
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeCardAdapter
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment
|
||||
import pl.szczodrzynski.edziennik.ui.modules.login.LoginLibrusCaptchaActivity
|
||||
import pl.szczodrzynski.edziennik.ui.modules.messages.MessagesComposeActivity
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class HomeDebugCard(
|
||||
override val id: Int,
|
||||
val app: App,
|
||||
val activity: MainActivity,
|
||||
val fragment: HomeFragment,
|
||||
val profile: Profile
|
||||
) : HomeCard, CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "HomeDebugCard"
|
||||
}
|
||||
|
||||
private var job: Job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
override fun bind(position: Int, holder: HomeCardAdapter.ViewHolder) { launch {
|
||||
holder.root.removeAllViews()
|
||||
val b = CardHomeDebugBinding.inflate(LayoutInflater.from(holder.root.context))
|
||||
b.root.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply {
|
||||
setMargins(8.dp)
|
||||
}
|
||||
holder.root += b.root
|
||||
|
||||
b.composeButton.onClick {
|
||||
app.startActivity(Intent(activity, MessagesComposeActivity::class.java));
|
||||
}
|
||||
|
||||
b.pruneWorkButton.onClick {
|
||||
WorkManager.getInstance(app).pruneWork()
|
||||
}
|
||||
|
||||
b.runChucker.onClick {
|
||||
app.startActivity(Chucker.getLaunchIntent(activity, 1));
|
||||
}
|
||||
|
||||
b.librusCaptchaButton.onClick {
|
||||
app.startActivity(Intent(activity, LoginLibrusCaptchaActivity::class.java))
|
||||
}
|
||||
|
||||
b.getLogs.onClick {
|
||||
val logs = HyperLog.getDeviceLogsInFile(activity, true)
|
||||
val intent = Intent(Intent.ACTION_SEND)
|
||||
|
||||
if (logs.exists()) {
|
||||
intent.type = "text/plain"
|
||||
intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + logs.absolutePath))
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, "Share debug logs")
|
||||
intent.putExtra(Intent.EXTRA_TEXT, "Share debug logs")
|
||||
app.startActivity(Intent.createChooser(intent, "Share debug logs"))
|
||||
}
|
||||
}
|
||||
|
||||
holder.root.onClick {
|
||||
// do stuff
|
||||
}
|
||||
}}
|
||||
|
||||
override fun unbind(position: Int, holder: HomeCardAdapter.ViewHolder) = Unit
|
||||
}
|
@ -36,7 +36,7 @@ import pl.szczodrzynski.edziennik.databinding.CardHomeGradesBinding
|
||||
import pl.szczodrzynski.edziennik.dp
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeCard
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeCardAdapter
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragmentV2
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment
|
||||
import pl.szczodrzynski.edziennik.utils.Colors
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
import pl.szczodrzynski.edziennik.utils.models.ItemGradesSubjectModel
|
||||
@ -46,7 +46,7 @@ class HomeGradesCard(
|
||||
override val id: Int,
|
||||
val app: App,
|
||||
val activity: MainActivity,
|
||||
val fragment: HomeFragmentV2,
|
||||
val fragment: HomeFragment,
|
||||
val profile: Profile
|
||||
) : HomeCard, CoroutineScope {
|
||||
|
||||
|
@ -21,7 +21,7 @@ import pl.szczodrzynski.edziennik.databinding.CardHomeLuckyNumberBinding
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.home.StudentNumberDialog
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeCard
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeCardAdapter
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragmentV2
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
@ -29,7 +29,7 @@ class HomeLuckyNumberCard(
|
||||
override val id: Int,
|
||||
val app: App,
|
||||
val activity: MainActivity,
|
||||
val fragment: HomeFragmentV2,
|
||||
val fragment: HomeFragment,
|
||||
val profile: Profile
|
||||
) : HomeCard, CoroutineScope {
|
||||
companion object {
|
||||
@ -51,6 +51,9 @@ class HomeLuckyNumberCard(
|
||||
val today = Date.getToday()
|
||||
val todayValue = today.value
|
||||
|
||||
val tomorrow = Date.getToday().stepForward(0, 0, 1)
|
||||
val tomorrowValue = tomorrow.value
|
||||
|
||||
val subTextRes = if (profile.studentNumber == -1)
|
||||
R.string.home_lucky_number_details_click_to_set
|
||||
else
|
||||
@ -59,28 +62,26 @@ class HomeLuckyNumberCard(
|
||||
|
||||
app.db.luckyNumberDao().getNearestFuture(App.profileId, todayValue).observe(fragment, Observer { luckyNumber ->
|
||||
val isYours = luckyNumber?.number == profile.studentNumber
|
||||
val titleRes = when {
|
||||
luckyNumber == null -> R.string.home_lucky_number_no_info
|
||||
luckyNumber.number == -1 -> R.string.home_lucky_number_no_number
|
||||
val res: Pair<Int, Array<out Any>> = when {
|
||||
luckyNumber == null -> R.string.home_lucky_number_no_info to emptyArray()
|
||||
luckyNumber.number == -1 -> R.string.home_lucky_number_no_number to emptyArray()
|
||||
else -> when (isYours) {
|
||||
true -> when (luckyNumber.date.value) {
|
||||
todayValue -> R.string.home_lucky_number_yours_today
|
||||
todayValue + 1 -> R.string.home_lucky_number_yours_tomorrow
|
||||
else -> R.string.home_lucky_number_yours_later
|
||||
todayValue -> R.string.home_lucky_number_yours_today to emptyArray()
|
||||
tomorrowValue -> R.string.home_lucky_number_yours_tomorrow to emptyArray()
|
||||
else -> R.string.home_lucky_number_yours_later to arrayOf(luckyNumber.date.formattedString)
|
||||
}
|
||||
false -> when (luckyNumber.date.value) {
|
||||
todayValue -> R.string.home_lucky_number_today
|
||||
todayValue + 1 -> R.string.home_lucky_number_tomorrow
|
||||
else -> R.string.home_lucky_number_later
|
||||
todayValue -> R.string.home_lucky_number_today to arrayOf(luckyNumber.number)
|
||||
tomorrowValue -> R.string.home_lucky_number_tomorrow to arrayOf(luckyNumber.number)
|
||||
else -> R.string.home_lucky_number_later to arrayOf(luckyNumber.date.formattedString, luckyNumber.number)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b.title.setText(
|
||||
titleRes,
|
||||
luckyNumber?.number ?: 0,
|
||||
luckyNumber?.date?.formattedString ?: ""
|
||||
)
|
||||
val (titleRes, resArguments) = res
|
||||
|
||||
b.title.setText(titleRes, *resArguments)
|
||||
|
||||
val drawableRes = when {
|
||||
luckyNumber == null || luckyNumber.number == -1 -> R.drawable.emoji_sad
|
||||
@ -104,4 +105,4 @@ class HomeLuckyNumberCard(
|
||||
}}
|
||||
|
||||
override fun unbind(position: Int, holder: HomeCardAdapter.ViewHolder) = Unit
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2019-12-22.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.home.cards
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.view.plusAssign
|
||||
import androidx.core.view.setMargins
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||
import pl.szczodrzynski.edziennik.databinding.CardHomeTemplateBinding
|
||||
import pl.szczodrzynski.edziennik.dp
|
||||
import pl.szczodrzynski.edziennik.onClick
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeCard
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeCardAdapter
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class HomeTemplateCard(
|
||||
override val id: Int,
|
||||
val app: App,
|
||||
val activity: MainActivity,
|
||||
val fragment: HomeFragment,
|
||||
val profile: Profile
|
||||
) : HomeCard, CoroutineScope {
|
||||
companion object {
|
||||
private const val TAG = "HomeTemplateCard"
|
||||
}
|
||||
|
||||
private var job: Job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
override fun bind(position: Int, holder: HomeCardAdapter.ViewHolder) { launch {
|
||||
holder.root.removeAllViews()
|
||||
val b = CardHomeTemplateBinding.inflate(LayoutInflater.from(holder.root.context))
|
||||
b.root.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply {
|
||||
setMargins(8.dp)
|
||||
}
|
||||
holder.root += b.root
|
||||
|
||||
// do stuff
|
||||
|
||||
holder.root.onClick {
|
||||
// do stuff
|
||||
}
|
||||
}}
|
||||
|
||||
override fun unbind(position: Int, holder: HomeCardAdapter.ViewHolder) = Unit
|
||||
}
|
@ -4,6 +4,7 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.home.cards
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@ -14,17 +15,25 @@ import androidx.core.view.setMargins
|
||||
import androidx.lifecycle.Observer
|
||||
import com.mikepenz.iconics.IconicsDrawable
|
||||
import com.mikepenz.iconics.typeface.library.community.material.CommunityMaterial
|
||||
import com.mikepenz.iconics.typeface.library.szkolny.font.SzkolnyFont
|
||||
import com.mikepenz.iconics.utils.sizeDp
|
||||
import kotlinx.coroutines.*
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.api.events.ApiTaskAllFinishedEvent
|
||||
import pl.szczodrzynski.edziennik.data.api.task.EdziennikTask
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.LessonFull
|
||||
import pl.szczodrzynski.edziennik.databinding.CardHomeTimetableBinding
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.bell.BellSyncTimeChooseDialog
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.CounterActivity
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeCard
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeCardAdapter
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragmentV2
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||
import pl.szczodrzynski.edziennik.utils.models.Week
|
||||
@ -35,7 +44,7 @@ class HomeTimetableCard(
|
||||
override val id: Int,
|
||||
val app: App,
|
||||
val activity: MainActivity,
|
||||
val fragment: HomeFragmentV2,
|
||||
val fragment: HomeFragment,
|
||||
val profile: Profile
|
||||
) : HomeCard, CoroutineScope {
|
||||
companion object {
|
||||
@ -58,7 +67,7 @@ class HomeTimetableCard(
|
||||
|
||||
private var bellSyncDiffMillis = 0L
|
||||
private val syncedNow: Time
|
||||
get() = Time.fromMillis(Time.getNow().inMillis + bellSyncDiffMillis)
|
||||
get() = Time.fromMillis(Time.getNow().inMillis - bellSyncDiffMillis)
|
||||
|
||||
private var counterJob: Job? = null
|
||||
private var counterStart: Time? = null
|
||||
@ -67,6 +76,9 @@ class HomeTimetableCard(
|
||||
|
||||
private val ignoreCancelled = true
|
||||
|
||||
private val countInSeconds: Boolean
|
||||
get() = app.config.timetable.countInSeconds
|
||||
|
||||
override fun bind(position: Int, holder: HomeCardAdapter.ViewHolder) {
|
||||
holder.root.removeAllViews()
|
||||
b = CardHomeTimetableBinding.inflate(LayoutInflater.from(holder.root.context))
|
||||
@ -79,11 +91,40 @@ class HomeTimetableCard(
|
||||
.colorAttr(activity, R.attr.colorIcon)
|
||||
.sizeDp(20))
|
||||
|
||||
b.bellSync.setImageDrawable(IconicsDrawable(activity, SzkolnyFont.Icon.szf_alarm_bell_outline)
|
||||
.colorAttr(activity, R.attr.colorIcon)
|
||||
.sizeDp(20))
|
||||
|
||||
b.showCounter.setImageDrawable(IconicsDrawable(activity, CommunityMaterial.Icon.cmd_fullscreen)
|
||||
.colorAttr(activity, R.attr.colorIcon)
|
||||
.sizeDp(20))
|
||||
|
||||
b.bellSync.setOnClickListener {
|
||||
BellSyncTimeChooseDialog(
|
||||
activity
|
||||
)
|
||||
}
|
||||
|
||||
b.showCounter.setOnClickListener {
|
||||
activity.startActivity(Intent(activity, CounterActivity::class.java))
|
||||
}
|
||||
|
||||
b.root.onClick {
|
||||
activity.loadTarget(MainActivity.DRAWER_ITEM_TIMETABLE, Bundle().apply {
|
||||
putString("timetableDate", timetableDate.stringY_m_d)
|
||||
})
|
||||
}
|
||||
|
||||
if (app.profile.getStudentData("timetableNotPublic", false)) {
|
||||
b.timetableLayout.visibility = View.GONE
|
||||
b.notPublicLayout.visibility = View.VISIBLE
|
||||
return
|
||||
}
|
||||
|
||||
// get current bell-sync params
|
||||
app.config.timetable.bellSyncDiff?.let {
|
||||
bellSyncDiffMillis = (it.hour * 60 * 60 * 1000 + it.minute * 60 * 1000 + it.second * 1000).toLong()
|
||||
bellSyncDiffMillis *= app.config.timetable.bellSyncMultiplier.toLong()
|
||||
bellSyncDiffMillis *= -1
|
||||
}
|
||||
|
||||
// get all lessons within the search bounds
|
||||
@ -92,11 +133,7 @@ class HomeTimetableCard(
|
||||
update()
|
||||
})
|
||||
|
||||
b.root.setOnClickListener {
|
||||
activity.loadTarget(MainActivity.DRAWER_ITEM_TIMETABLE, Bundle().apply {
|
||||
putString("timetableDate", timetableDate.stringY_m_d)
|
||||
})
|
||||
}
|
||||
EventBus.getDefault().register(this)
|
||||
}
|
||||
|
||||
private fun update() { launch {
|
||||
@ -111,21 +148,26 @@ class HomeTimetableCard(
|
||||
it.profileId == profile.id
|
||||
&& it.displayDate == timetableDate
|
||||
&& it.displayEndTime > now
|
||||
&& it.type != Lesson.TYPE_NO_LESSONS
|
||||
&& !(it.isCancelled && ignoreCancelled)
|
||||
}
|
||||
while ((lessons.isEmpty() || lessons.none {
|
||||
it.displayDate != today || (it.displayDate == today && it.displayEndTime != null && it.displayEndTime!! >= now)
|
||||
it.type != Lesson.TYPE_NO_LESSONS
|
||||
&& (it.displayDate != today
|
||||
|| (it.displayDate == today
|
||||
&& it.displayEndTime != null
|
||||
&& it.displayEndTime!! >= now))
|
||||
}) && checkedDays < 7) {
|
||||
|
||||
timetableDate.stepForward(0, 0, 1)
|
||||
lessons = allLessons.filter {
|
||||
it.profileId == profile.id
|
||||
&& it.displayDate == timetableDate
|
||||
&& it.type != Lesson.TYPE_NO_LESSONS
|
||||
&& !(it.isCancelled && ignoreCancelled)
|
||||
}
|
||||
|
||||
if (lessons.isEmpty() && timetableDate.weekDay <= 5)
|
||||
break
|
||||
|
||||
checkedDays++
|
||||
}
|
||||
timetableDate
|
||||
@ -133,6 +175,43 @@ class HomeTimetableCard(
|
||||
|
||||
timetableDate = deferred.await()
|
||||
|
||||
if (lessons.isEmpty()) {
|
||||
// timetable is not downloaded yet
|
||||
b.timetableLayout.visibility = View.GONE
|
||||
b.noTimetableLayout.visibility = View.VISIBLE
|
||||
b.noLessonsLayout.visibility = View.GONE
|
||||
val weekStart = timetableDate.weekStart
|
||||
b.noTimetableText.setText(
|
||||
R.string.home_timetable_no_timetable_text,
|
||||
weekStart.stringY_m_d
|
||||
)
|
||||
b.noTimetableSync.onClick {
|
||||
it.isEnabled = false
|
||||
EdziennikTask.syncProfile(
|
||||
profileId = App.profileId,
|
||||
viewIds = listOf(
|
||||
MainActivity.DRAWER_ITEM_TIMETABLE to 0
|
||||
),
|
||||
arguments = JsonObject(
|
||||
"weekStart" to weekStart
|
||||
)
|
||||
).enqueue(activity)
|
||||
}
|
||||
return@launch
|
||||
}
|
||||
if (lessons.size == 1 && lessons[0].type == Lesson.TYPE_NO_LESSONS) {
|
||||
// in next 7 days only NO_LESSONS is found
|
||||
b.timetableLayout.visibility = View.GONE
|
||||
b.noTimetableLayout.visibility = View.GONE
|
||||
b.noLessonsLayout.visibility = View.VISIBLE
|
||||
timetableDate = timetableDate.weekStart
|
||||
return@launch
|
||||
}
|
||||
|
||||
b.timetableLayout.visibility = View.VISIBLE
|
||||
b.noTimetableLayout.visibility = View.GONE
|
||||
b.noLessonsLayout.visibility = View.GONE
|
||||
|
||||
val isToday = today == timetableDate
|
||||
|
||||
b.progress.visibility = View.GONE
|
||||
@ -264,7 +343,7 @@ class HomeTimetableCard(
|
||||
b.progress.visibility = View.GONE
|
||||
b.counter.visibility = View.VISIBLE
|
||||
val diff = counterStart - now
|
||||
b.counter.text = activity.timeTill(diff.toInt(), "\n")
|
||||
b.counter.text = activity.timeTill(diff.toInt(), "\n", countInSeconds)
|
||||
}
|
||||
else {
|
||||
// the lesson is right now
|
||||
@ -273,11 +352,16 @@ class HomeTimetableCard(
|
||||
val lessonLength = counterEnd - counterStart
|
||||
val timePassed = now - counterStart
|
||||
val timeLeft = counterEnd - now
|
||||
b.counter.text = activity.timeLeft(timeLeft.toInt(), "\n")
|
||||
b.counter.text = activity.timeLeft(timeLeft.toInt(), "\n", countInSeconds)
|
||||
b.progress.max = lessonLength.toInt()
|
||||
b.progress.progress = timePassed.toInt()
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
fun onSyncFinishedEvent(event: ApiTaskAllFinishedEvent) {
|
||||
b.noTimetableSync.isEnabled = true
|
||||
}
|
||||
|
||||
override fun unbind(position: Int, holder: HomeCardAdapter.ViewHolder) = Unit
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import pl.szczodrzynski.edziennik.MainActivity;
|
||||
import pl.szczodrzynski.edziennik.R;
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull;
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.event.EventManualDialog;
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment;
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragmentOld;
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date;
|
||||
|
||||
import static pl.szczodrzynski.edziennik.utils.Utils.bs;
|
||||
@ -53,7 +53,7 @@ public class HomeworkAdapter extends RecyclerView.Adapter<HomeworkAdapter.ViewHo
|
||||
else if (dayDiff == 2) {
|
||||
return context.getString(R.string.the_day_after);
|
||||
}
|
||||
return HomeFragment.plural(context, R.plurals.time_till_days, Math.abs(dayDiff));
|
||||
return HomeFragmentOld.plural(context, R.plurals.time_till_days, Math.abs(dayDiff));
|
||||
}
|
||||
else if (dayDiff < 0) {
|
||||
if (dayDiff == -1) {
|
||||
@ -62,7 +62,7 @@ public class HomeworkAdapter extends RecyclerView.Adapter<HomeworkAdapter.ViewHo
|
||||
else if (dayDiff == -2) {
|
||||
return context.getString(R.string.the_day_before);
|
||||
}
|
||||
return context.getString(R.string.ago_format, HomeFragment.plural(context, R.plurals.time_till_days, Math.abs(dayDiff)));
|
||||
return context.getString(R.string.ago_format, HomeFragmentOld.plural(context, R.plurals.time_till_days, Math.abs(dayDiff)));
|
||||
}
|
||||
return context.getString(R.string.today);
|
||||
}
|
||||
|
@ -54,6 +54,7 @@ public class LoginChooserFragment extends Fragment {
|
||||
b.loginLibrusJstLogo.setOnClickListener((v) -> nav.navigate(R.id.loginLibrusJstFragment, null, LoginActivity.navOptions));
|
||||
b.loginVulcanLogo.setOnClickListener((v) -> nav.navigate(R.id.loginVulcanFragment, null, LoginActivity.navOptions));
|
||||
b.loginIuczniowieLogo.setOnClickListener((v) -> nav.navigate(R.id.loginIuczniowieFragment, null, LoginActivity.navOptions));
|
||||
b.loginEdudziennikLogo.setOnClickListener((v) -> nav.navigate(R.id.loginEdudziennikFragment, null, LoginActivity.navOptions));
|
||||
|
||||
if (LoginActivity.firstCompleted) {
|
||||
// we are navigated here from LoginSummary
|
||||
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) Kacper Ziubryniewicz 2019-12-23
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.ui.modules.login
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.Navigation
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_EDUDZIENNIK_WEB_INVALID_LOGIN
|
||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_EDUDZIENNIK
|
||||
import pl.szczodrzynski.edziennik.databinding.FragmentLoginEdudziennikBinding
|
||||
import pl.szczodrzynski.edziennik.startCoroutineTimer
|
||||
import pl.szczodrzynski.edziennik.ui.modules.error.ErrorSnackbar
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class LoginEdudziennikFragment : Fragment(), CoroutineScope {
|
||||
|
||||
private val app by lazy { activity?.application as App? }
|
||||
|
||||
private var job = Job()
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
private lateinit var b: FragmentLoginEdudziennikBinding
|
||||
|
||||
private lateinit var nav: NavController
|
||||
private lateinit var errorSnackbar: ErrorSnackbar
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
activity?.also { activity ->
|
||||
nav = Navigation.findNavController(activity, R.id.nav_host_fragment)
|
||||
errorSnackbar = (activity as LoginActivity).errorSnackbar
|
||||
}
|
||||
|
||||
b = FragmentLoginEdudziennikBinding.inflate(inflater, container, false)
|
||||
return b.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { launch {
|
||||
startCoroutineTimer(delayMillis = 100) {
|
||||
val error = LoginActivity.error
|
||||
|
||||
if (error != null) {
|
||||
when (error.errorCode) {
|
||||
ERROR_LOGIN_EDUDZIENNIK_WEB_INVALID_LOGIN ->
|
||||
b.loginPasswordLayout.error = getString(R.string.login_error_incorrect_login_or_password)
|
||||
}
|
||||
|
||||
errorSnackbar.addError(error)
|
||||
LoginActivity.error = null
|
||||
}
|
||||
}
|
||||
|
||||
b.backButton.setOnClickListener { nav.navigateUp() }
|
||||
b.loginButton.setOnClickListener { login() }
|
||||
}}
|
||||
|
||||
private fun login() {
|
||||
var errors = false
|
||||
|
||||
b.loginEmailLayout.error = null
|
||||
b.loginPasswordLayout.error = null
|
||||
|
||||
val emailEditable = b.loginEmail.text
|
||||
val passwordEditable = b.loginPassword.text
|
||||
|
||||
if (emailEditable.isNullOrBlank()) {
|
||||
b.loginEmailLayout.error = getString(R.string.login_error_no_email)
|
||||
errors = true
|
||||
}
|
||||
|
||||
if (passwordEditable.isNullOrBlank()) {
|
||||
b.loginPasswordLayout.error = getString(R.string.login_error_no_password)
|
||||
errors = true
|
||||
}
|
||||
|
||||
if (errors)
|
||||
return
|
||||
|
||||
nav.navigate(R.id.loginProgressFragment, Bundle().apply {
|
||||
putInt("loginType", LOGIN_TYPE_EDUDZIENNIK)
|
||||
putString("email", emailEditable.toString())
|
||||
putString("password", passwordEditable.toString())
|
||||
}, LoginActivity.navOptions)
|
||||
}
|
||||
}
|
@ -31,6 +31,7 @@ import pl.szczodrzynski.edziennik.databinding.RowLoginProfileListItemBinding;
|
||||
import static pl.szczodrzynski.edziennik.data.api.LoginMethodsKt.LOGIN_MODE_LIBRUS_EMAIL;
|
||||
import static pl.szczodrzynski.edziennik.data.api.LoginMethodsKt.LOGIN_MODE_VULCAN_API;
|
||||
import static pl.szczodrzynski.edziennik.data.api.LoginMethodsKt.LOGIN_MODE_VULCAN_WEB;
|
||||
import static pl.szczodrzynski.edziennik.data.api.LoginMethodsKt.LOGIN_TYPE_EDUDZIENNIK;
|
||||
import static pl.szczodrzynski.edziennik.data.api.LoginMethodsKt.LOGIN_TYPE_IDZIENNIK;
|
||||
import static pl.szczodrzynski.edziennik.data.api.LoginMethodsKt.LOGIN_TYPE_LIBRUS;
|
||||
import static pl.szczodrzynski.edziennik.data.api.LoginMethodsKt.LOGIN_TYPE_MOBIDZIENNIK;
|
||||
@ -225,6 +226,9 @@ public class LoginSummaryFragment extends Fragment {
|
||||
imageRes = R.drawable.logo_dzienniczek;
|
||||
}
|
||||
}
|
||||
else if (m.loginType == LOGIN_TYPE_EDUDZIENNIK) {
|
||||
imageRes = R.drawable.logo_edudziennik;
|
||||
}
|
||||
if (imageRes != 0) {
|
||||
b.registerIcon.setImageResource(imageRes);
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ import pl.szczodrzynski.edziennik.receivers.BootReceiver;
|
||||
import pl.szczodrzynski.edziennik.sync.SyncWorker;
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.changelog.ChangelogDialog;
|
||||
import pl.szczodrzynski.edziennik.ui.dialogs.settings.ProfileRemoveDialog;
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment;
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragmentOld;
|
||||
import pl.szczodrzynski.edziennik.utils.Themes;
|
||||
import pl.szczodrzynski.edziennik.utils.Utils;
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date;
|
||||
@ -513,14 +513,14 @@ public class SettingsNewFragment extends MaterialAboutFragment {
|
||||
if (app.config.getSync().getInterval() < 60 * 60)
|
||||
return getString(
|
||||
R.string.settings_sync_sync_interval_subtext_format,
|
||||
HomeFragment.plural(activity, R.plurals.time_till_minutes, app.config.getSync().getInterval() / 60)
|
||||
HomeFragmentOld.plural(activity, R.plurals.time_till_minutes, app.config.getSync().getInterval() / 60)
|
||||
);
|
||||
return getString(
|
||||
R.string.settings_sync_sync_interval_subtext_format,
|
||||
HomeFragment.plural(activity, R.plurals.time_till_hours, app.config.getSync().getInterval() / 60 / 60) +
|
||||
HomeFragmentOld.plural(activity, R.plurals.time_till_hours, app.config.getSync().getInterval() / 60 / 60) +
|
||||
(app.config.getSync().getInterval() / 60 % 60 == 0 ?
|
||||
"" :
|
||||
" " + HomeFragment.plural(activity, R.plurals.time_till_minutes, app.config.getSync().getInterval() / 60 % 60)
|
||||
" " + HomeFragmentOld.plural(activity, R.plurals.time_till_minutes, app.config.getSync().getInterval() / 60 % 60)
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -566,16 +566,16 @@ public class SettingsNewFragment extends MaterialAboutFragment {
|
||||
syncCardIntervalItem.setOnClickAction(() -> {
|
||||
List<CharSequence> intervalNames = new ArrayList<>();
|
||||
if (App.devMode && false) {
|
||||
intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_seconds, 30));
|
||||
intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_minutes, 2));
|
||||
intervalNames.add(HomeFragmentOld.plural(activity, R.plurals.time_till_seconds, 30));
|
||||
intervalNames.add(HomeFragmentOld.plural(activity, R.plurals.time_till_minutes, 2));
|
||||
}
|
||||
intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_minutes, 30));
|
||||
intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_minutes, 45));
|
||||
intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_hours, 1));
|
||||
intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_hours, 1)+" "+HomeFragment.plural(activity, R.plurals.time_till_minutes, 30));
|
||||
intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_hours, 2));
|
||||
intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_hours, 3));
|
||||
intervalNames.add(HomeFragment.plural(activity, R.plurals.time_till_hours, 4));
|
||||
intervalNames.add(HomeFragmentOld.plural(activity, R.plurals.time_till_minutes, 30));
|
||||
intervalNames.add(HomeFragmentOld.plural(activity, R.plurals.time_till_minutes, 45));
|
||||
intervalNames.add(HomeFragmentOld.plural(activity, R.plurals.time_till_hours, 1));
|
||||
intervalNames.add(HomeFragmentOld.plural(activity, R.plurals.time_till_hours, 1)+" "+ HomeFragmentOld.plural(activity, R.plurals.time_till_minutes, 30));
|
||||
intervalNames.add(HomeFragmentOld.plural(activity, R.plurals.time_till_hours, 2));
|
||||
intervalNames.add(HomeFragmentOld.plural(activity, R.plurals.time_till_hours, 3));
|
||||
intervalNames.add(HomeFragmentOld.plural(activity, R.plurals.time_till_hours, 4));
|
||||
List<Integer> intervals = new ArrayList<>();
|
||||
if (App.devMode && false) {
|
||||
intervals.add(30);
|
||||
|
@ -52,7 +52,7 @@ import pl.szczodrzynski.edziennik.R;
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonFull;
|
||||
import pl.szczodrzynski.edziennik.databinding.FragmentTimetableBinding;
|
||||
import pl.szczodrzynski.edziennik.ui.modules.error.ErrorDialog;
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragment;
|
||||
import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragmentOld;
|
||||
import pl.szczodrzynski.edziennik.utils.SpannableHtmlTagHandler;
|
||||
import pl.szczodrzynski.edziennik.utils.Themes;
|
||||
import pl.szczodrzynski.edziennik.utils.Utils;
|
||||
@ -184,7 +184,7 @@ public class TimetableFragment extends Fragment {
|
||||
return;
|
||||
|
||||
List<LessonFull> lessons = app.db.lessonDao().getAllWeekNow(App.profileId, today.getWeekStart(), today);
|
||||
displayingDate = HomeFragment.findDateWithLessons(App.profileId, lessons);
|
||||
displayingDate = HomeFragmentOld.findDateWithLessons(App.profileId, lessons);
|
||||
pageSelection = 2 + Date.diffDays(displayingDate, today); // DEFAULT HERE
|
||||
|
||||
activity.runOnUiThread(() -> {
|
||||
|
@ -20,7 +20,6 @@ import kotlinx.coroutines.*
|
||||
import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.MainActivity
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_LIBRUS
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||
import pl.szczodrzynski.edziennik.databinding.FragmentTimetableV2Binding
|
||||
@ -88,7 +87,7 @@ class TimetableFragment : Fragment(), CoroutineScope {
|
||||
if (app.profile == null || !isAdded)
|
||||
return@launch
|
||||
|
||||
if (app.profile.loginStoreType == LOGIN_TYPE_LIBRUS && app.profile.getLoginData("timetableNotPublic", false)) {
|
||||
if (app.profile.getStudentData("timetableNotPublic", false)) {
|
||||
b.timetableLayout.visibility = View.GONE
|
||||
b.timetableNotPublicLayout.visibility = View.VISIBLE
|
||||
return@launch
|
||||
|
@ -18,7 +18,6 @@ import com.linkedin.android.tachyon.DayViewConfig
|
||||
import kotlinx.coroutines.*
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_TIMETABLE
|
||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_LIBRUS
|
||||
import pl.szczodrzynski.edziennik.data.api.task.EdziennikTask
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.events.EventFull
|
||||
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||
@ -151,15 +150,15 @@ class TimetableDayFragment : Fragment(), CoroutineScope {
|
||||
}
|
||||
|
||||
// reload the fragment when: no lessons, user wants to sync the week, the timetable is not public, pager gets removed
|
||||
if (app.profile.loginStoreType == LOGIN_TYPE_LIBRUS && app.profile.getLoginData("timetableNotPublic", false)) {
|
||||
if (app.profile.getStudentData("timetableNotPublic", false)) {
|
||||
activity.reloadTarget()
|
||||
// TODO fix for (not really)possible infinite loops
|
||||
return
|
||||
}
|
||||
|
||||
// clear the root view and add the ScrollView
|
||||
(view as FrameLayout).removeAllViews()
|
||||
(view as FrameLayout).addView(dayScroll)
|
||||
(view as FrameLayout?)?.removeAllViews()
|
||||
(view as FrameLayout?)?.addView(dayScroll)
|
||||
|
||||
// Inflate a label view for each hour the day view will display
|
||||
val hourLabelViews = ArrayList<View>()
|
||||
|
@ -39,6 +39,7 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
@ -418,7 +419,7 @@ public class Utils {
|
||||
byte[] iv = new byte[16];
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, keyObj, ivSpec);
|
||||
byte [] encryptedByteValue = cipher.doFinal(value.getBytes("utf-8"));
|
||||
byte [] encryptedByteValue = cipher.doFinal(value.getBytes(StandardCharsets.UTF_8));
|
||||
String encryptedValue64 = Base64.encodeToString(encryptedByteValue, Base64.DEFAULT);
|
||||
return encryptedValue64;
|
||||
|
||||
@ -433,7 +434,7 @@ public class Utils {
|
||||
cipher.init(Cipher.DECRYPT_MODE, keyObj, ivSpec);
|
||||
byte[] decryptedValue64 = Base64.decode(value, Base64.DEFAULT);
|
||||
byte [] decryptedByteValue = cipher.doFinal(decryptedValue64);
|
||||
String decryptedValue = new String(decryptedByteValue,"utf-8");
|
||||
String decryptedValue = new String(decryptedByteValue, StandardCharsets.UTF_8);
|
||||
return decryptedValue;
|
||||
|
||||
}
|
||||
@ -612,7 +613,7 @@ public class Utils {
|
||||
if (sourceFile.isDirectory()) {
|
||||
zipSubFolder(out, sourceFile, sourceFile.getParent().length());
|
||||
} else {
|
||||
byte data[] = new byte[BUFFER];
|
||||
byte[] data = new byte[BUFFER];
|
||||
FileInputStream fi = new FileInputStream(sourcePath);
|
||||
origin = new BufferedInputStream(fi, BUFFER);
|
||||
ZipEntry entry = new ZipEntry(getLastPathComponent(sourcePath));
|
||||
@ -648,7 +649,7 @@ public class Utils {
|
||||
if (file.isDirectory()) {
|
||||
zipSubFolder(out, file, basePathLength);
|
||||
} else {
|
||||
byte data[] = new byte[BUFFER];
|
||||
byte[] data = new byte[BUFFER];
|
||||
String unmodifiedFilePath = file.getPath();
|
||||
String relativePath = unmodifiedFilePath
|
||||
.substring(basePathLength);
|
||||
@ -797,4 +798,10 @@ public class Utils {
|
||||
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
|
||||
return dateFormat.format(date);
|
||||
}
|
||||
|
||||
public static String getCurrentSchoolYear() {
|
||||
pl.szczodrzynski.edziennik.utils.models.Date today = pl.szczodrzynski.edziennik.utils.models.Date.getToday();
|
||||
if (today.month >= 9) return today.year + "/" + (today.year + 1);
|
||||
else return (today.year - 1) + "/" + today.year;
|
||||
}
|
||||
}
|
||||
|
@ -25,4 +25,8 @@ public class ItemWidgetTimetableModel {
|
||||
public List<Integer> eventColors = new ArrayList<>();
|
||||
public boolean bigStyle = false;
|
||||
public boolean darkTheme = false;
|
||||
|
||||
public boolean isNoTimetableItem = false;
|
||||
public boolean isNoLessonsItem = false;
|
||||
public boolean isNotPublicItem = false;
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ public class Time implements Comparable<Time> {
|
||||
long t2millis = t2.getInMillis();
|
||||
int multiplier = (t1millis > t2millis ? 1 : -1);
|
||||
Time diff = Time.fromMillis((t1millis - t2millis)*multiplier);
|
||||
diff.hour -= 1;
|
||||
// diff.hour -= 1;
|
||||
return diff;
|
||||
}
|
||||
|
||||
@ -175,7 +175,7 @@ public class Time implements Comparable<Time> {
|
||||
long t1millis = t1.getInMillis();
|
||||
long t2millis = t2.getInMillis();
|
||||
Time sum = Time.fromMillis((t1millis + t2millis));
|
||||
sum.hour += 1;
|
||||
// sum.hour += 1;
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
@ -1,67 +0,0 @@
|
||||
package pl.szczodrzynski.edziennik.widgets.timetable;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import pl.szczodrzynski.edziennik.App;
|
||||
import pl.szczodrzynski.edziennik.MainActivity;
|
||||
import pl.szczodrzynski.edziennik.R;
|
||||
import pl.szczodrzynski.edziennik.utils.Themes;
|
||||
import pl.szczodrzynski.edziennik.utils.models.Date;
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time;
|
||||
|
||||
import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
|
||||
|
||||
public class LessonDetailsActivity extends AppCompatActivity {
|
||||
public LessonDetailsActivity() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
getWindow().setBackgroundDrawable(new ColorDrawable(0));
|
||||
|
||||
setTheme(Themes.INSTANCE.getAppThemeNoDisplay());
|
||||
|
||||
App app = (App)getApplication();
|
||||
Bundle extras = getIntent().getExtras();
|
||||
if (app != null && extras != null) {
|
||||
int profileId = extras.getInt("profileId", -1);
|
||||
|
||||
if (extras.getBoolean("separatorItem", false)) {
|
||||
Intent i = new Intent(this, MainActivity.class)
|
||||
.putExtra("fragmentId", MainActivity.DRAWER_ITEM_TIMETABLE)
|
||||
.putExtra("profileId", profileId)
|
||||
.addFlags(FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||
app.getContext().startActivity(i);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
Date date = Date.fromYmd(extras.getString("date", "20181109"));
|
||||
Time startTime = Time.fromHms(extras.getString("startTime", "20181109"));
|
||||
//Time endTime = Time.fromHms(extras.getString("endTime", "20181109"));
|
||||
|
||||
/* new EventListDialogOld(this, profileId)
|
||||
.withDismissListener((dialog -> {
|
||||
finish();
|
||||
Intent intent = new Intent(app.getContext(), WidgetTimetable.class);
|
||||
intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
|
||||
int[] ids = AppWidgetManager.getInstance(app)
|
||||
.getAppWidgetIds(new ComponentName(app, WidgetTimetable.class));
|
||||
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
|
||||
app.sendBroadcast(intent);
|
||||
}))
|
||||
.show(app, date, startTime); */
|
||||
return;
|
||||
}
|
||||
Toast.makeText(app, R.string.error_reading_lesson_details, Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
}
|
||||
}
|
@ -33,6 +33,8 @@ import pl.szczodrzynski.edziennik.utils.models.Date;
|
||||
import pl.szczodrzynski.edziennik.utils.models.ItemWidgetTimetableModel;
|
||||
import pl.szczodrzynski.edziennik.utils.models.Time;
|
||||
|
||||
import static android.util.TypedValue.COMPLEX_UNIT_SP;
|
||||
|
||||
public class WidgetTimetableListProvider implements RemoteViewsService.RemoteViewsFactory {
|
||||
|
||||
private static final String TAG = "WidgetTimetableProvider";
|
||||
@ -149,6 +151,8 @@ public class WidgetTimetableListProvider implements RemoteViewsService.RemoteVie
|
||||
views.setViewVisibility(R.id.widgetTimetableProfileName, View.VISIBLE);
|
||||
views.setViewVisibility(R.id.widgetTimetableContent, View.GONE);
|
||||
views.setTextViewText(R.id.widgetTimetableProfileName, lesson.separatorProfileName);
|
||||
views.setTextViewTextSize(R.id.widgetTimetableProfileName, COMPLEX_UNIT_SP, lesson.bigStyle ? 30 : 20);
|
||||
views.setTextColor(R.id.widgetTimetableProfileName, lesson.darkTheme ? 0xff000000 : 0xffffffff);
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("profileId", lesson.profileId);
|
||||
@ -158,6 +162,37 @@ public class WidgetTimetableListProvider implements RemoteViewsService.RemoteVie
|
||||
return views;
|
||||
}
|
||||
|
||||
if (lesson.isNoTimetableItem) {
|
||||
views.setImageViewBitmap(R.id.widgetTimetableBackground, null);
|
||||
views.setViewVisibility(R.id.widgetTimetableProfileName, View.VISIBLE);
|
||||
views.setViewVisibility(R.id.widgetTimetableContent, View.GONE);
|
||||
views.setTextViewText(R.id.widgetTimetableProfileName, context.getString(R.string.widget_timetable_short_no_timetable));
|
||||
views.setTextViewTextSize(R.id.widgetTimetableProfileName, COMPLEX_UNIT_SP, lesson.bigStyle ? 26 : 18);
|
||||
views.setTextColor(R.id.widgetTimetableProfileName, lesson.darkTheme ? 0xffffffff : 0xff000000);
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("profileId", lesson.profileId);
|
||||
intent.putExtra("separatorItem", true);
|
||||
intent.putExtra("isNoTimetableItem", true);
|
||||
views.setOnClickFillInIntent(R.id.widgetTimetableRoot, intent);
|
||||
return views;
|
||||
}
|
||||
if (lesson.isNoLessonsItem) {
|
||||
views.setImageViewBitmap(R.id.widgetTimetableBackground, null);
|
||||
views.setViewVisibility(R.id.widgetTimetableProfileName, View.VISIBLE);
|
||||
views.setViewVisibility(R.id.widgetTimetableContent, View.GONE);
|
||||
views.setTextViewText(R.id.widgetTimetableProfileName, context.getString(R.string.widget_timetable_short_no_lessons));
|
||||
views.setTextViewTextSize(R.id.widgetTimetableProfileName, COMPLEX_UNIT_SP, lesson.bigStyle ? 26 : 18);
|
||||
views.setTextColor(R.id.widgetTimetableProfileName, lesson.darkTheme ? 0xffffffff : 0xff000000);
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("profileId", lesson.profileId);
|
||||
intent.putExtra("separatorItem", true);
|
||||
intent.putExtra("isNoLessonsItem", true);
|
||||
views.setOnClickFillInIntent(R.id.widgetTimetableRoot, intent);
|
||||
return views;
|
||||
}
|
||||
|
||||
views.setViewVisibility(R.id.widgetTimetableBackground, View.VISIBLE);
|
||||
views.setViewVisibility(R.id.widgetTimetableProfileName, View.GONE);
|
||||
views.setViewVisibility(R.id.widgetTimetableContent, View.VISIBLE);
|
||||
|
54
app/src/main/res/drawable/ic_bell.xml
Normal file
54
app/src/main/res/drawable/ic_bell.xml
Normal file
@ -0,0 +1,54 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="64dp"
|
||||
android:height="64dp"
|
||||
android:viewportWidth="64"
|
||||
android:viewportHeight="64">
|
||||
<path
|
||||
android:pathData="M48.3984,50.668L34.668,50.668L34.668,48L48.3984,48C50.3984,48 52,46.3984 52,44.3984L52,26.668L54.668,26.668L54.668,44.3984C54.668,47.8672 51.8672,50.668 48.3984,50.668Z"
|
||||
android:fillColor="#C5CAE9"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
<path
|
||||
android:pathData="M34.668,56L18.668,56C16.5352,56 14.668,54.2656 14.668,52L14.668,42.668C14.668,40.5352 16.5352,38.668 18.668,38.668L34.668,38.668C36.8008,38.668 38.668,40.5352 38.668,42.668L38.668,52C38.668,54.2656 36.8008,56 34.668,56Z"
|
||||
android:fillColor="#546E7A"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
<path
|
||||
android:pathData="M46.668,28C46.668,39.0664 37.7344,48 26.668,48C15.6016,48 6.668,39.0664 6.668,28C6.668,16.9336 15.6016,8 26.668,8C37.7344,8 46.668,16.9336 46.668,28Z"
|
||||
android:fillColor="#FF3D00"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
<path
|
||||
android:pathData="M26.668,42.668C16,42.668 7.332,34.9336 6.668,26.9336C6.668,27.332 6.668,27.7344 6.668,28C6.668,39.0664 15.6016,48 26.668,48C37.7344,48 46.668,39.0664 46.668,28C46.668,27.6016 46.668,27.1992 46.668,26.9336C46,34.9336 37.332,42.668 26.668,42.668Z"
|
||||
android:fillColor="#DD2C00"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
<path
|
||||
android:pathData="M14.668,44L14.668,47.1992C18.1328,49.332 22.2656,50.668 26.668,50.668C31.0664,50.668 35.1992,49.332 38.668,47.1992L38.668,44C35.332,46.5352 31.1992,48 26.668,48C22.1328,48 18,46.5352 14.668,44Z"
|
||||
android:fillColor="#37474F"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
<path
|
||||
android:pathData="M34.668,28C34.668,32.3984 31.0664,36 26.668,36C22.2656,36 18.668,32.3984 18.668,28C18.668,23.6016 22.2656,20 26.668,20C31.0664,20 34.668,23.6016 34.668,28Z"
|
||||
android:fillColor="#C5CAE9"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
<path
|
||||
android:pathData="M29.332,28C29.332,29.4648 28.1328,30.668 26.668,30.668C25.1992,30.668 24,29.4648 24,28C24,26.5352 25.1992,25.332 26.668,25.332C28.1328,25.332 29.332,26.5352 29.332,28Z"
|
||||
android:fillColor="#7986CB"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
<path
|
||||
android:pathData="M57.332,26.668C57.332,28.9336 55.6016,30.668 53.332,30.668C51.0664,30.668 49.332,28.9336 49.332,26.668C49.332,24.3984 51.0664,22.668 53.332,22.668C55.6016,22.668 57.332,24.3984 57.332,26.668Z"
|
||||
android:fillColor="#9FA8DA"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
</vector>
|
78
app/src/main/res/drawable/ic_bell_wtf.xml
Normal file
78
app/src/main/res/drawable/ic_bell_wtf.xml
Normal file
@ -0,0 +1,78 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="64dp"
|
||||
android:height="64dp"
|
||||
android:viewportWidth="64"
|
||||
android:viewportHeight="64">
|
||||
<path
|
||||
android:pathData="M45.5508,36.1758C44.8242,32.8359 43.625,29.5391 43.3516,26.125C43.1641,23.7617 43.0859,21.375 42.6016,19.0508C42.1758,16.9883 41.3516,14.6016 39.4258,13.4883C38.0391,12.6875 36.4375,12.6641 34.8633,12.7109C33.0117,12.7734 31.1875,12.8008 29.3359,12.75C26.1367,12.6758 22.7617,12.7617 20.6484,15.5234C19.0234,17.6484 18.4883,20.4258 18.1758,23.0234C17.8242,25.9141 17.6992,28.8125 17.1484,31.6758C16.4766,35.1875 15.5625,38.7734 15.9375,42.375C17.7617,41.6641 19.8984,41.5234 21.8008,41.4609C25.4141,41.3359 29.0234,41.1875 32.6484,41.2734C34.6641,41.3242 36.6992,41.3359 38.6992,41.5859C39.6875,41.7109 40.6875,41.8984 41.6875,41.9766C42.5859,42.0391 43.4883,41.9766 44.3867,41.9883C44.9766,42 45.5742,42.0234 46.1641,42.125C46.2383,40.1367 45.9766,38.1367 45.5508,36.1758ZM27.3984,36.5859C27.3984,36.8867 27.25,37.1992 26.9375,37.2891C24.3633,38.0508 21.6758,37.8984 19.0742,37.3125C18.2383,37.125 18.4609,35.8359 19.2734,35.9492C19.2891,34.875 19.3359,33.8008 19.7109,32.7617C19.7891,32.5742 19.8984,32.4609 20.0391,32.3984C20.1367,32.2891 20.2734,32.2109 20.4609,32.1875C21.7383,32.0234 23.0234,31.8359 24.3125,31.8125C25.125,31.8008 26.1875,31.8516 26.8125,32.4883C27.875,33.5859 27.4141,35.2383 27.3984,36.5859ZM27.5742,27.8359C27.5117,29 27.0508,29.9141 25.8867,30.2891C24.2383,30.8125 22.4609,30.6875 20.7734,30.9492C20.4375,31 20.2109,30.8359 20.125,30.6016C20.0742,30.5625 20.0117,30.5234 19.9766,30.4609C19.5234,29.9492 19.6133,29.0508 19.6758,28.4258C19.7617,27.5117 19.9609,26.625 20.1641,25.7383C20.4883,24.3008 20.6875,22.8867 20.8867,21.4375C21.1016,19.8633 21.375,18.1133 22.25,16.7383C23.1875,15.2734 24.5742,14.5859 26.3125,14.7891C26.5859,14.8125 26.875,15.125 26.8633,15.4141C26.6484,19.5742 27.7891,23.6758 27.5742,27.8359Z"
|
||||
android:fillColor="#EF4823"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
<path
|
||||
android:pathData="M25.8242,33.4766C25.2266,33.0234 24.1992,33.1992 23.5117,33.25C22.6367,33.3125 21.7734,33.4258 20.8984,33.5391C20.625,34.3867 20.6484,35.3359 20.6484,36.2109C20.6484,36.2109 20.6484,36.2109 20.6484,36.2266C22.4492,36.5117 24.2734,36.5625 26.0508,36.1133C26.0742,35.625 26.125,35.1484 26.125,34.6641C26.1367,34.2891 26.1758,33.7383 25.8242,33.4766Z"
|
||||
android:fillColor="#D6E5E5"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
<path
|
||||
android:pathData="M18.1758,11.0234C18.1758,11.0391 18.1875,11.0508 18.1992,11.0625C18.3633,11.2266 18.5234,11.25 18.6367,11.2266C18.4609,11.2109 18.3008,11.1484 18.1758,11.0234Z"
|
||||
android:fillColor="#D6E5E5"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
<path
|
||||
android:pathData="M26.2266,27.0234C26.2109,23.375 25.3867,19.7617 25.4492,16.125C22.8242,16.3125 22.3984,20.1016 22.1484,22.1992C22,23.5 21.7734,24.7383 21.4883,26.0117C21.3125,26.8125 21.125,27.625 21.0391,28.4375C21,28.7266 20.9766,29.0234 21,29.3125C21.0117,29.4258 21.0117,29.4883 21.0234,29.5391C22.4883,29.3633 24.0625,29.4766 25.4375,28.9883C26.3242,28.6758 26.2266,27.8867 26.2266,27.0234Z"
|
||||
android:fillColor="#D6E5E5"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
<path
|
||||
android:pathData="M49.6641,45.9883C49.0625,45.0859 48.25,44.1484 47.1875,43.8008C46.8984,43.9766 46.4492,43.8633 46.2383,43.5625C44.7891,43.3008 43.3242,43.4375 41.8359,43.3633C39.875,43.2617 37.9375,42.8633 35.9609,42.7617C33.9141,42.6641 31.8633,42.6133 29.8125,42.625C27.8242,42.625 25.8516,42.6992 23.875,42.7734C22.5859,42.8242 21.2891,42.8359 20,42.9492C18.6992,43.0625 17.375,43.25 16.1758,43.7891C15.0234,44.3008 14.1992,45.1133 13.5742,46.1992C12.8867,47.3867 12.4258,48.7109 12.1133,50.0508C11.8359,51.2109 11.5859,52.5117 11.7617,53.7266C12.2734,53.5625 12.875,53.5234 13.3008,53.4883C14.8984,53.3125 16.5117,53.2383 18.125,53.1758C29.3633,52.7109 40.6133,52.6641 51.8633,52.6484C51.5508,50.3516 50.9492,47.9258 49.6641,45.9883Z"
|
||||
android:fillColor="#EF4823"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
<path
|
||||
android:pathData="M53.25,52.875C52.9609,50.3984 52.3359,47.9258 51.125,45.7383C50.5234,44.6641 49.7109,43.6758 48.6641,43.0117C48.3008,42.7891 47.9141,42.6016 47.5117,42.4609C47.6758,38.9492 46.8516,35.5391 45.9883,32.1484C45.5391,30.4258 44.9883,28.6484 44.8008,26.875C44.6875,25.7891 44.625,24.6875 44.5508,23.6016C44.2383,19.2617 43.625,13.2734 38.75,11.6875C37.0625,11.1367 35.125,11.3242 33.3867,11.3984C31.6016,11.4766 29.8242,11.3867 28.0391,11.3633C26.3125,11.3359 24.5859,11.4766 22.9766,12.1016C21.6484,12.6133 20.5117,13.5234 19.6367,14.6367C17.9609,16.75 17.3125,19.5117 16.9375,22.125C16.5391,24.9375 16.4766,27.7734 15.9883,30.5742C15.2891,34.5742 14.1367,38.6133 14.6133,42.7109C14.625,42.8359 14.6641,42.9375 14.7266,43.0117C14.0234,43.4492 13.3867,44.0117 12.8867,44.75C11.9375,46.125 11.3359,47.6641 10.8984,49.2734C10.4375,50.9492 10.1641,52.7891 10.5234,54.5117C10.5742,54.7617 10.7266,54.8984 10.8867,54.9492C11.0508,55.3242 11.6367,55.4375 11.9883,55.1484C12.0234,55.1367 12.1133,55.1016 12.1367,55.0859C12.3984,55.0117 12.4141,55.0117 12.7617,54.9609C13.5234,54.8516 14.2891,54.7891 15.0508,54.7266C17.1641,54.5742 19.2891,54.5117 21.3984,54.4492C25.6992,54.3242 30.0117,54.1758 34.3125,54.1016C40.4883,54 46.6484,54.0391 52.8242,54.0391C53.4883,54.0117 53.6016,53.2617 53.25,52.875ZM17.1484,31.6875C17.6992,28.8125 17.8242,25.9258 18.1758,23.0391C18.4883,20.4375 19.0234,17.6641 20.6484,15.5391C22.7617,12.7617 26.1367,12.6875 29.3359,12.7617C31.1875,12.8008 33.0117,12.7734 34.8633,12.7266C36.4258,12.6758 38.0234,12.6992 39.4258,13.5C41.3516,14.6133 42.1758,17.0117 42.6016,19.0625C43.0742,21.3867 43.1484,23.7734 43.3516,26.1367C43.625,29.5508 44.8359,32.8516 45.5508,36.1875C45.9766,38.1367 46.2383,40.1484 46.1641,42.1484C45.5742,42.0625 44.9766,42.0234 44.3867,42.0117C43.4883,42 42.5859,42.0508 41.6875,42C40.6875,41.9375 39.6992,41.7383 38.6992,41.6133C36.6992,41.3516 34.6641,41.3359 32.6484,41.3008C29.0234,41.2109 25.4141,41.3633 21.8008,41.4883C19.9141,41.5508 17.7734,41.6875 15.9375,42.3984C15.5742,38.7891 16.4883,35.1992 17.1484,31.6875ZM18.1016,53.1641C16.4883,53.2266 14.875,53.3008 13.2734,53.4766C12.8516,53.5234 12.25,53.5508 11.7383,53.7109C11.5625,52.5 11.8125,51.1992 12.0859,50.0391C12.3984,48.6992 12.8633,47.375 13.5508,46.1875C14.1758,45.1016 15,44.2891 16.1484,43.7734C17.3516,43.2383 18.6758,43.0508 19.9766,42.9375C21.2617,42.8242 22.5625,42.8242 23.8516,42.7617C25.8242,42.6758 27.8125,42.6133 29.7891,42.6133C31.8359,42.6133 33.8867,42.6641 35.9375,42.75C37.9141,42.8359 39.8516,43.25 41.8125,43.3516C43.3008,43.4258 44.7617,43.2891 46.2109,43.5508C46.4375,43.8516 46.875,43.9492 47.1641,43.7891C48.2266,44.1367 49.0508,45.0742 49.6367,45.9766C50.9258,47.9141 51.5234,50.3359 51.8125,52.6367C40.5859,52.6484 29.3359,52.7109 18.1016,53.1641Z"
|
||||
android:fillColor="#010101"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
<path
|
||||
android:pathData="M26.8359,15.4141C26.8516,15.125 26.5625,14.8242 26.2891,14.7891C24.5508,14.5859 23.1641,15.2734 22.2266,16.7383C21.3516,18.1016 21.0742,19.8516 20.8633,21.4375C20.6641,22.8984 20.4609,24.3008 20.1367,25.7383C19.9375,26.625 19.75,27.5234 19.6484,28.4258C19.5859,29.0508 19.5,29.9492 19.9492,30.4609C20,30.5117 20.0508,30.5625 20.1016,30.6016C20.1992,30.8359 20.4141,31 20.75,30.9492C22.4492,30.6875 24.2109,30.8008 25.8633,30.2891C27.0234,29.9258 27.4883,29 27.5508,27.8359C27.7891,23.6758 26.6484,19.5742 26.8359,15.4141ZM25.4375,28.9883C24.0508,29.4766 22.4766,29.3633 21.0234,29.5391C21.0117,29.4883 21.0117,29.4141 21,29.3125C20.9766,29.0234 21.0117,28.7266 21.0391,28.4375C21.1367,27.625 21.3125,26.8125 21.4883,26.0117C21.7734,24.7383 21.9883,23.5 22.1484,22.1992C22.3984,20.1016 22.8242,16.3125 25.4492,16.125C25.3867,19.7734 26.1992,23.375 26.2266,27.0234C26.2266,27.8867 26.3242,28.6758 25.4375,28.9883Z"
|
||||
android:fillColor="#010101"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
<path
|
||||
android:pathData="M26.8125,32.5117C26.1875,31.8867 25.1367,31.8242 24.3125,31.8359C23.0234,31.8633 21.75,32.0508 20.4609,32.2109C20.2734,32.2383 20.1367,32.3125 20.0391,32.4258C19.8984,32.4766 19.7734,32.5859 19.7109,32.7891C19.3359,33.8125 19.2734,34.8867 19.2734,35.9766C18.4609,35.8633 18.2383,37.1484 19.0742,37.3359C21.6758,37.9258 24.3633,38.0742 26.9375,37.3125C27.25,37.2266 27.3867,36.9141 27.3984,36.6133C27.4141,35.2383 27.875,33.5859 26.8125,32.5117ZM26.125,34.6758C26.1133,35.1641 26.0742,35.6367 26.0508,36.125C24.2734,36.5625 22.4492,36.5234 20.6484,36.2383C20.6484,36.2383 20.6484,36.2383 20.6484,36.2266C20.6484,35.3359 20.625,34.3984 20.8984,33.5508C21.7734,33.4375 22.6367,33.3359 23.5117,33.2617C24.1992,33.2109 25.2266,33.0391 25.8242,33.4883C26.1758,33.7383 26.1367,34.2891 26.125,34.6758Z"
|
||||
android:fillColor="#010101"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
<path
|
||||
android:pathData="M50.9883,18.2383C50.125,16.3359 49.875,14.1875 49.0859,12.25C48.2383,10.1875 46.75,8.2266 44.2891,8.3984C43.3984,8.4609 43.5117,9.8359 44.3867,9.7734C46.3867,9.6367 47.3633,11.5859 47.9766,13.1992C48.6484,14.9883 48.8984,16.9492 49.6875,18.6992C50.0508,19.4883 51.3516,19.0391 50.9883,18.2383Z"
|
||||
android:fillColor="#010101"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
<path
|
||||
android:pathData="M56.875,15.8125C56.5508,14.0625 56.1641,12.2734 55.6641,10.5742C55.3359,9.4609 54.875,8.3984 54.3125,7.3984C53.9609,6.7891 53.3984,6.3359 52.8633,5.8867C52.1133,5.2617 50.25,3.7734 49.5234,5.2266C49.1758,5.9375 50.1367,6.5117 50.625,6.0234C50.8633,6.125 51.0859,6.2617 51.3008,6.4141C51.7617,6.7383 52.1875,7.1133 52.6133,7.4883C53.125,7.9492 53.3984,8.5391 53.6875,9.1758C54.1133,10.1016 54.3984,11.0859 54.6484,12.0742C54.9766,13.3984 55.2891,14.7383 55.5391,16.0742C55.75,17.1992 56.0859,18.75 55.5391,19.8359C55.125,20.625 56.3633,21.2383 56.7734,20.4492C57.4883,19.0742 57.1484,17.2617 56.875,15.8125Z"
|
||||
android:fillColor="#010101"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
<path
|
||||
android:pathData="M19.3359,10.5391C19.1758,9.6758 18.3867,9.7734 17.8242,10.1758C17.5117,10.4141 17.2109,10.6758 16.9141,10.9375C16.6484,11.1641 16.2891,11.375 16.0625,11.6367C15.3125,12.5117 14.6992,13.5 14.3008,14.5742C14.0859,15.1484 13.9375,15.7383 13.8633,16.3516C13.8008,16.8516 13.7109,17.5391 13.8984,18.0117C14.0234,18.3359 14.4258,18.5859 14.7734,18.4375C15.125,18.2734 15.3008,18.0391 15.375,17.6484C15.4375,17.3633 15.3359,17.1484 15.1641,17.0117C15.1758,16.8633 15.1992,16.7266 15.2109,16.6133C15.25,16.1992 15.3516,15.8008 15.4609,15.4141C15.6875,14.6133 16.1133,13.8516 16.6016,13.1758C16.9375,12.6992 17.3516,12.375 17.7891,11.9883C17.9883,11.8125 18.1992,11.6367 18.4141,11.4609C18.5,11.3867 18.5859,11.3242 18.6758,11.2617C18.6875,11.25 18.6875,11.25 18.6992,11.25C19.0742,11.2383 19.4258,11 19.3359,10.5391ZM18.1875,11.0625C18.1758,11.0508 18.1758,11.0391 18.1641,11.0234C18.2891,11.1484 18.4492,11.2109 18.625,11.2266C18.5117,11.25 18.3516,11.2266 18.1875,11.0625Z"
|
||||
android:fillColor="#010101"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
<path
|
||||
android:pathData="M15.9883,5.8125C9.875,8.7266 7.8984,16.4609 7.2891,22.6367C7.1992,23.5117 8.4375,23.7734 8.6367,22.8984C8.6992,22.8125 8.7734,22.7383 8.8516,22.6641C9.1758,22.3359 9.0508,21.9258 8.7617,21.7109C9.1016,19.0625 9.6875,16.4375 10.6992,13.9609C11.8359,11.1758 13.6367,8.4492 16.4375,7.1133C17.2383,6.7383 16.7891,5.4258 15.9883,5.8125Z"
|
||||
android:fillColor="#010101"
|
||||
android:fillAlpha="1"
|
||||
android:fillType="nonZero"
|
||||
android:strokeColor="#00000000"/>
|
||||
</vector>
|
BIN
app/src/main/res/drawable/login_logo_edudziennik.png
Normal file
BIN
app/src/main/res/drawable/login_logo_edudziennik.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.8 KiB |
BIN
app/src/main/res/drawable/logo_edudziennik.png
Normal file
BIN
app/src/main/res/drawable/logo_edudziennik.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
76
app/src/main/res/layout/card_home_debug.xml
Normal file
76
app/src/main/res/layout/card_home_debug.xml
Normal file
@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) Kuba Szczodrzyński 2019-12-22.
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
tools:layout_margin="8dp"
|
||||
tools:ignore="HardcodedText">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Warning! Do not move this debug card, or you will probably confuse the internal card ID list, thus resulting in a weird and (maybe)non-undoable card order."/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/getLogs"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Save Debug Logs" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/librusCaptchaButton"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Librus Captcha" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/runChucker"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Launch Chucker" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/composeButton"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:text="Compose" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/composeNewButton"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:text="Compose 2" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/pruneWorkButton"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Prune finished work" />
|
||||
|
||||
</LinearLayout>
|
||||
</layout>
|
21
app/src/main/res/layout/card_home_template.xml
Normal file
21
app/src/main/res/layout/card_home_template.xml
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) Kuba Szczodrzyński 2019-12-22.
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
tools:layout_margin="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello world"/>
|
||||
|
||||
</LinearLayout>
|
||||
</layout>
|
@ -6,118 +6,264 @@
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<LinearLayout
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
tools:layout_margin="8dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/noTimetableLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<View
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:background="@drawable/ic_sync"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dayInfo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/NavView.TextView.Title"
|
||||
tools:text="Jutro" />
|
||||
android:text="@string/home_timetable_no_timetable" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/lessonInfo"
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/noTimetableText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/NavView.TextView.Helper"
|
||||
tools:text="7 lekcji - 8:10 do 14:45" />
|
||||
android:textSize="16sp"
|
||||
android:text="@string/home_timetable_no_timetable_text"/>
|
||||
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/noTimetableSync"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:text="@string/home_timetable_no_timetable_sync" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/settings"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:padding="10dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:visibility="gone"
|
||||
tools:src="@sample/settings" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:background="@color/dividerColor" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/noLessonsLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:visibility="gone"
|
||||
tools:layout_marginTop="150dp"
|
||||
tools:visibility="visible">
|
||||
|
||||
<View
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:background="@drawable/ic_timetable"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/lessonBig"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/NavView.TextView.Subtitle"
|
||||
tools:text="Pierwsza: informatyka" />
|
||||
android:textAppearance="@style/NavView.TextView.Title"
|
||||
android:text="@string/home_timetable_no_lessons" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/classroom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/NavView.TextView.Small"
|
||||
tools:text="09a komputerowa" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:max="2700"
|
||||
android:progress="780" />
|
||||
android:textSize="16sp"
|
||||
android:text="@string/home_timetable_no_lessons_text"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/counter"
|
||||
android:layout_width="wrap_content"
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/notPublicLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="gone"
|
||||
tools:layout_marginTop="220dp"
|
||||
tools:visibility="visible">
|
||||
|
||||
<View
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:background="@drawable/ic_no_timetable"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:gravity="center"
|
||||
tools:text="zostały\n2 minuty\n35 sekund" />
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/NavView.TextView.Title"
|
||||
android:text="@string/home_timetable_not_public" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="16sp"
|
||||
android:text="@string/home_timetable_not_public_text"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:background="@color/dividerColor" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/nextLessons"
|
||||
<LinearLayout
|
||||
android:id="@+id/timetableLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/NavView.TextView.Helper"
|
||||
tools:text="Póżniej:\n9:05 informatyka\n10:00 urządzenia techniki komputerowej\n11:00 projektowanie lokalnych sieci komputerowych\n11:55 zajęcia z wychowawcą\n13:00 język polski\n14:05 język niemiecki" />
|
||||
android:orientation="vertical"
|
||||
tools:layout_marginTop="350dp">
|
||||
|
||||
</LinearLayout>
|
||||
</layout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/dayInfo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/NavView.TextView.Title"
|
||||
tools:text="Jutro" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/lessonInfo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/NavView.TextView.Helper"
|
||||
tools:text="7 lekcji - 8:10 do 14:45" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/settings"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:padding="10dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
android:visibility="gone"
|
||||
tools:src="@sample/settings" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bellSync"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:padding="10dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
tools:src="@sample/settings" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/showCounter"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:padding="10dp"
|
||||
android:background="?selectableItemBackgroundBorderless"
|
||||
tools:src="@sample/settings" />
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:background="@color/dividerColor" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/lessonBig"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/NavView.TextView.Subtitle"
|
||||
tools:text="Pierwsza: informatyka" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/classroom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/NavView.TextView.Small"
|
||||
tools:text="09a komputerowa" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
tools:max="2700"
|
||||
tools:progress="780" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/counter"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:gravity="center"
|
||||
tools:text="zostały\n2 minuty\n35 sekund" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:background="@color/dividerColor" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/nextLessons"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/NavView.TextView.Helper"
|
||||
tools:text="Póżniej:\n9:05 informatyka\n10:00 urządzenia techniki komputerowej\n11:00 projektowanie lokalnych sieci komputerowych\n11:55 zajęcia z wychowawcą\n13:00 język polski\n14:05 język niemiecki" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
</layout>
|
||||
|
31
app/src/main/res/layout/dialog_bell_sync.xml
Normal file
31
app/src/main/res/layout/dialog_bell_sync.xml
Normal file
@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) Kacper Ziubryniewicz 2019-12-20
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bellSyncHowto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="@string/bell_sync_howto" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bellSyncButton"
|
||||
android:layout_width="128dp"
|
||||
android:layout_height="128dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="32dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
app:srcCompat="@drawable/ic_bell" />
|
||||
</LinearLayout>
|
||||
</layout>
|
43
app/src/main/res/layout/dialog_bell_sync_time_choose.xml
Normal file
43
app/src/main/res/layout/dialog_bell_sync_time_choose.xml
Normal file
@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) Kacper Ziubryniewicz 2019-12-20
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:padding="24dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bellSyncHowto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
tools:text="@string/bell_sync_choose_howto" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.FilledBox.Dense"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/bell_sync_time_title">
|
||||
|
||||
<pl.szczodrzynski.edziennik.utils.TextInputDropDown
|
||||
android:id="@+id/timeDropdown"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="false"
|
||||
tools:text="lekcja matematyka (8:00)"/>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</layout>
|
@ -1,101 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".HomeFragment">
|
||||
<!--
|
||||
~ Copyright (c) Kuba Szczodrzyński 2019-11-23.
|
||||
-->
|
||||
|
||||
<layout xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator
|
||||
android:id="@+id/refreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.modules.home.HomeFragment">
|
||||
android:layout_height="match_parent"
|
||||
tools:listitem="@layout/card_home" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/cardInsertPoint"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/nextSync"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
tools:text="TextView" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/devMode"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:orientation="vertical"
|
||||
tools:visibility="visible"
|
||||
tools:ignore="HardcodedText">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/getLogs"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:text="Save Debug Logs" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/librusCaptchaButton"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:text="Librus Captcha" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/runChucker"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:text="Launch Chucker" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/mobidziennikMessagesSwitch"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="Zmień moduł wiadomości" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/composeButton"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="Compose" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/pruneWorkButton"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:text="Prune finished work" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator>
|
||||
</layout>
|
||||
</layout>
|
101
app/src/main/res/layout/fragment_home_old.xml
Normal file
101
app/src/main/res/layout/fragment_home_old.xml
Normal file
@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".HomeFragment">
|
||||
|
||||
<pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator
|
||||
android:id="@+id/refreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.modules.home.HomeFragmentOld">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/cardInsertPoint"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/nextSync"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
tools:text="TextView" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/devMode"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:orientation="vertical"
|
||||
tools:visibility="visible"
|
||||
tools:ignore="HardcodedText">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/getLogs"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:text="Save Debug Logs" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/librusCaptchaButton"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:text="Librus Captcha" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/runChucker"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:text="Launch Chucker" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/mobidziennikMessagesSwitch"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="Zmień moduł wiadomości" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/composeButton"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:layout_weight="1"
|
||||
android:text="Compose" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/pruneWorkButton"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:text="Prune finished work" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator>
|
||||
</layout>
|
@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) Kuba Szczodrzyński 2019-11-23.
|
||||
-->
|
||||
|
||||
<layout xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator
|
||||
android:id="@+id/refreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:listitem="@layout/card_home" />
|
||||
|
||||
</pl.szczodrzynski.edziennik.utils.SwipeRefreshLayoutNoIndicator>
|
||||
</layout>
|
@ -184,18 +184,17 @@
|
||||
android:layout_height="100dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_weight="1"
|
||||
android:visibility="invisible">
|
||||
android:layout_weight="1">
|
||||
|
||||
<!--<ImageView
|
||||
android:id="@+id/loginIuczniowieLogo"
|
||||
<ImageView
|
||||
android:id="@+id/loginEdudziennikLogo"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="@drawable/bg_rounded_ripple"
|
||||
android:padding="16dp"
|
||||
android:scaleType="fitCenter"
|
||||
app:srcCompat="@drawable/login_logo_iuczniowie" />-->
|
||||
app:srcCompat="@drawable/login_logo_edudziennik" />
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@ -247,4 +246,4 @@
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</layout>
|
||||
</layout>
|
||||
|
173
app/src/main/res/layout/fragment_login_edudziennik.xml
Normal file
173
app/src/main/res/layout/fragment_login_edudziennik.xml
Normal file
@ -0,0 +1,173 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) Kacper Ziubryniewicz 2019-12-23
|
||||
-->
|
||||
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.mikepenz.iconics.view.IconicsImageView
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginLeft="24dp"
|
||||
android:layout_marginTop="48dp"
|
||||
app:iiv_color="@color/colorPrimary"
|
||||
app:iiv_icon="cmd-account-circle"
|
||||
app:iiv_size="32dp"
|
||||
tools:srcCompat="@tools:sample/avatars" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="24dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginRight="24dp"
|
||||
android:text="@string/login_edudziennik_title"
|
||||
android:textSize="24sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="24dp"
|
||||
android:layout_marginTop="2dp"
|
||||
android:layout_marginRight="24dp"
|
||||
android:text="@string/login_edudziennik_subtitle" />
|
||||
|
||||
<Space
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="16dp" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/loginEmailLayout"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:hint="@string/login_hint_email"
|
||||
app:errorEnabled="true"
|
||||
app:hintAnimationEnabled="true"
|
||||
app:hintEnabled="true">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/loginEmail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textNoSuggestions|textEmailAddress" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/loginPasswordLayout"
|
||||
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:hint="@string/login_hint_password"
|
||||
app:errorEnabled="true"
|
||||
app:hintAnimationEnabled="true"
|
||||
app:hintEnabled="true"
|
||||
app:passwordToggleEnabled="true">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/loginPassword"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="textPassword" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<!--<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/helpButton"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:text="@string/login_help_button"
|
||||
android:textAllCaps="false" />-->
|
||||
|
||||
<Space
|
||||
android:layout_width="0.0dip"
|
||||
android:layout_height="0.0dip"
|
||||
android:layout_weight="1.0" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/loginButton"
|
||||
style="@style/Widget.MaterialComponents.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:text="@string/login_button"
|
||||
android:textAllCaps="false" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/backButton"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:text="@string/back"
|
||||
android:textAllCaps="false"
|
||||
android:layout_marginStart="8dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
</layout>
|
@ -1,5 +1,4 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/root"
|
||||
android:layout_width="match_parent"
|
||||
@ -65,17 +64,18 @@
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/widgetTimetableBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/widget_background_bottom">
|
||||
|
||||
<ListView
|
||||
android:id="@+id/widgetTimetableListView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:divider="@color/secondaryTextLight"
|
||||
android:background="@drawable/widget_background_bottom"
|
||||
android:dividerHeight="1.0dip" ><!--#b5ffffff-->
|
||||
</ListView>
|
||||
android:dividerHeight="1.0dip"
|
||||
tools:listitem="@layout/row_widget_timetable_item"/><!--#b5ffffff-->
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widgetTimetableLoading"
|
||||
@ -84,7 +84,34 @@
|
||||
android:textColor="@color/primaryTextLight"
|
||||
android:layout_gravity="center"
|
||||
android:textStyle="italic"
|
||||
android:text="@string/widget_loading" />
|
||||
android:text="@string/widget_loading"
|
||||
tools:visibility="gone"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widgetTimetableNoTimetable"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="8dp"
|
||||
android:textColor="@color/primaryTextLight"
|
||||
android:gravity="center"
|
||||
android:textSize="16sp"
|
||||
android:text="@string/widget_timetable_no_timetable"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widgetTimetableNoLessons"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="8dp"
|
||||
android:textColor="@color/primaryTextLight"
|
||||
android:gravity="center"
|
||||
android:textSize="16sp"
|
||||
android:text="@string/widget_timetable_no_lessons_found"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/root"
|
||||
android:layout_width="match_parent"
|
||||
@ -65,17 +64,18 @@
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/widgetTimetableBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/widget_background_bottom">
|
||||
|
||||
<ListView
|
||||
android:id="@+id/widgetTimetableListView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:divider="@color/secondaryTextLight"
|
||||
android:background="@drawable/widget_background_bottom"
|
||||
android:dividerHeight="1.0dip" ><!--#b5ffffff-->
|
||||
</ListView>
|
||||
android:dividerHeight="1.0dip"
|
||||
tools:listitem="@layout/row_widget_timetable_big_item"/><!--#b5ffffff-->
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widgetTimetableLoading"
|
||||
@ -85,7 +85,34 @@
|
||||
android:text="@string/widget_loading"
|
||||
android:textColor="@color/primaryTextLight"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="italic" />
|
||||
android:textStyle="italic"
|
||||
tools:visibility="gone"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widgetTimetableNoTimetable"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="8dp"
|
||||
android:textColor="@color/primaryTextLight"
|
||||
android:gravity="center"
|
||||
android:textSize="24sp"
|
||||
android:text="@string/widget_timetable_no_timetable"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widgetTimetableNoLessons"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="8dp"
|
||||
android:textColor="@color/primaryTextLight"
|
||||
android:gravity="center"
|
||||
android:textSize="24sp"
|
||||
android:text="@string/widget_timetable_no_lessons_found"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/root"
|
||||
android:layout_width="match_parent"
|
||||
@ -65,17 +64,18 @@
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/widgetTimetableBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/widget_background_dark_bottom">
|
||||
|
||||
<ListView
|
||||
android:id="@+id/widgetTimetableListView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:divider="@color/secondaryTextDark"
|
||||
android:background="@drawable/widget_background_dark_bottom"
|
||||
android:dividerHeight="1.0dip" ><!--#b5ffffff-->
|
||||
</ListView>
|
||||
android:dividerHeight="1.0dip"
|
||||
tools:listitem="@layout/row_widget_timetable_dark_item"/><!--#b5ffffff-->
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widgetTimetableLoading"
|
||||
@ -84,7 +84,34 @@
|
||||
android:textColor="@color/primaryTextDark"
|
||||
android:layout_gravity="center"
|
||||
android:textStyle="italic"
|
||||
android:text="@string/widget_loading" />
|
||||
android:text="@string/widget_loading"
|
||||
tools:visibility="gone"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widgetTimetableNoTimetable"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="8dp"
|
||||
android:textColor="@color/primaryTextLight"
|
||||
android:gravity="center"
|
||||
android:textSize="16sp"
|
||||
android:text="@string/widget_timetable_no_timetable"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widgetTimetableNoLessons"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="8dp"
|
||||
android:textColor="@color/primaryTextLight"
|
||||
android:gravity="center"
|
||||
android:textSize="16sp"
|
||||
android:text="@string/widget_timetable_no_lessons_found"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/root"
|
||||
android:layout_width="match_parent"
|
||||
@ -65,17 +64,18 @@
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/widgetTimetableBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/widget_background_dark_bottom">
|
||||
|
||||
<ListView
|
||||
android:id="@+id/widgetTimetableListView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:divider="@color/secondaryTextDark"
|
||||
android:background="@drawable/widget_background_dark_bottom"
|
||||
android:dividerHeight="1.0dip" ><!--#b5ffffff-->
|
||||
</ListView>
|
||||
android:dividerHeight="1.0dip"
|
||||
tools:listitem="@layout/row_widget_timetable_dark_big_item"/><!--#b5ffffff-->
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widgetTimetableLoading"
|
||||
@ -85,7 +85,34 @@
|
||||
android:text="@string/widget_loading"
|
||||
android:textColor="@color/primaryTextDark"
|
||||
android:textSize="22sp"
|
||||
android:textStyle="italic" />
|
||||
android:textStyle="italic"
|
||||
tools:visibility="gone"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widgetTimetableNoTimetable"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="8dp"
|
||||
android:textColor="@color/primaryTextDark"
|
||||
android:gravity="center"
|
||||
android:textSize="24sp"
|
||||
android:text="@string/widget_timetable_no_timetable"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widgetTimetableNoLessons"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="8dp"
|
||||
android:textColor="@color/primaryTextDark"
|
||||
android:gravity="center"
|
||||
android:textSize="24sp"
|
||||
android:text="@string/widget_timetable_no_lessons_found"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
|
@ -125,6 +125,18 @@
|
||||
android:id="@+id/action_loginVulcanFragment_to_loginProgressFragment"
|
||||
app:destination="@id/loginProgressFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/loginEdudziennikFragment"
|
||||
android:name="pl.szczodrzynski.edziennik.ui.modules.login.LoginEdudziennikFragment"
|
||||
android:label="fragment_login_edudziennik"
|
||||
tools:layout="@layout/fragment_login_edudziennik" >
|
||||
<!--<action
|
||||
android:id="@+id/action_loginLibrusFragment_to_loginLibrusHelpFragment"
|
||||
app:destination="@id/loginLibrusHelpFragment" />-->
|
||||
<action
|
||||
android:id="@+id/action_loginEdudziennikFragment_to_loginProgressFragment"
|
||||
app:destination="@id/loginProgressFragment" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/loginVulcanHelpFragment"
|
||||
android:name="pl.szczodrzynski.edziennik.ui.modules.login.LoginVulcanHelpFragment"
|
||||
|
@ -76,10 +76,13 @@
|
||||
<string name="bell_sync_adjust_error">Incorrect format</string>
|
||||
<string name="bell_sync_cannot_now">Calibration is impossible, because there are no lessons now. Try again, i.e. in the end of the lesson or break. Remember that you should run this even before planned bell time.</string>
|
||||
<string name="bell_sync_current_dialog">\n\nCurrent calibration: %s</string>
|
||||
<string name="bell_sync_howto">Click OK, when the lesson ends. The counter\'s time will be calibrated to the bell time.\n\nPlanned bell time is %s</string>
|
||||
<string name="bell_sync_howto">Click the bell icon, when the bell rings. The counter\'s time will be calibrated to the bell time.\n\nPlanned bell time is %s\n\nThe bell time difference at the moment is %s</string>
|
||||
<string name="bell_sync_reset_confirm">Do you want to reset the calibration?</string>
|
||||
<string name="bell_sync_results">The bell is inexact by %s%s</string>
|
||||
<string name="bell_sync_results">The bell is inexact by %s</string>
|
||||
<string name="bell_sync_title">Calibrate with the school bell</string>
|
||||
<string name="bell_sync_time_title">Time of the bell to synchronize</string>
|
||||
<string name="bell_sync_lesson_item">lesson %s (%s)</string>
|
||||
<string name="bell_sync_break_item">break (%s)</string>
|
||||
<string name="cancel">Cancel</string>
|
||||
<string name="card_grades_button">Go to grades</string>
|
||||
<string name="card_grades_header_title">Grades - last 7 days</string>
|
||||
@ -870,4 +873,5 @@
|
||||
<string name="login_summary_account_child">(child)</string>
|
||||
<string name="login_summary_account_parent">(parent)</string>
|
||||
<string name="toolbar_subtitle_syncing">Syncing...</string>
|
||||
<string name="bell_sync_choose_howto">Choose the nearest bell to synchronize.</string>
|
||||
</resources>
|
||||
|
@ -98,10 +98,14 @@
|
||||
<string name="bell_sync_adjust_error">Nieprawidłowy format</string>
|
||||
<string name="bell_sync_cannot_now">Synchronizacja jest niemożliwa, ponieważ teraz nie ma żadnych lekcji. Spróbuj jeszcze raz np. pod koniec lekcji albo przerwy. Pamiętaj, że powinieneś to uruchomić jeszcze przed planowanym czasem dzwonka.</string>
|
||||
<string name="bell_sync_current_dialog">"\n\nAktualna kalibracja to %s"</string>
|
||||
<string name="bell_sync_howto">Kliknij OK, kiedy lekcja się skończy. Licznik czasu zostanie zsynchronizowany z czasem dzwonka.\n\nCzas według planu to %s</string>
|
||||
<string name="bell_sync_howto">Kliknij w ikonę dzwonka, kiedy dzwonek zadzwoni. Licznik czasu zostanie zsynchronizowany z czasem dzwonka.\n\nCzas według planu to %s\n\nAktualna różnica wynosi %s</string>
|
||||
<string name="bell_sync_choose_howto">Wybierz najbliższy dzwonek, abyś mógł go zsynchronizować z aplikacją.</string>
|
||||
<string name="bell_sync_reset_confirm">Czy na pewno zresetować synchronizację?</string>
|
||||
<string name="bell_sync_results">Dzwonek jest niedokładny o %s%s</string>
|
||||
<string name="bell_sync_results">Dzwonek jest niedokładny o %s</string>
|
||||
<string name="bell_sync_title">Synchronizacja z dzwonkiem</string>
|
||||
<string name="bell_sync_time_title">Godzina dzwonka do synchronizacji</string>
|
||||
<string name="bell_sync_lesson_item">lekcja %s (%s)</string>
|
||||
<string name="bell_sync_break_item">przerwa (%s)</string>
|
||||
<string name="cancel">Anuluj</string>
|
||||
<string name="card_grades_button">Przejdź do ocen</string>
|
||||
<string name="card_grades_header_title">Oceny - ostatnie 7 dni</string>
|
||||
@ -1109,4 +1113,20 @@
|
||||
<string name="qr_scanner_dialog_title">Skanuj kod QR</string>
|
||||
<string name="web_push_unpair_button">Odłącz</string>
|
||||
<string name="web_push_date_paired_format">Połączono %s</string>
|
||||
<string name="home_timetable_no_timetable">Nie pobrano planu lekcji</string>
|
||||
<string name="home_timetable_no_timetable_text">Plan lekcji na tydzień %s nie został jeszcze pobrany.</string>
|
||||
<string name="home_timetable_no_timetable_sync">Pobierz</string>
|
||||
<string name="home_timetable_no_lessons">Nie ma żadnych lekcji</string>
|
||||
<string name="home_timetable_no_lessons_text">Przez następne 7 dni nie ma żadnych lekcji.</string>
|
||||
<string name="home_timetable_not_public">Brak planu lekcji</string>
|
||||
<string name="home_timetable_not_public_text">Plan lekcji nie został opublikowany przez szkołę.\n\nSkontaktuj się z wychowawcą.</string>
|
||||
<string name="widget_timetable_no_timetable">Plan lekcji nie został pobrany.\n\nOtwórz aplikację i wykonaj synchronizację, aby pobrać plan lekcji.</string>
|
||||
<string name="widget_timetable_no_lessons_found">Brak lekcji przez następne 7 dni.</string>
|
||||
<string name="widget_timetable_short_no_timetable">Nie pobrano planu lekcji.</string>
|
||||
<string name="widget_timetable_short_no_lessons">Brak lekcji przez nast. 7 dni.</string>
|
||||
<string name="no_lessons_today">Nie ma dzisiaj żadnych lekcji!</string>
|
||||
<string name="lessons_finished">Nie ma dzisiaj więcej lekcji!</string>
|
||||
<string name="login_edudziennik_title">Zaloguj się - Edudziennik</string>
|
||||
<string name="login_edudziennik_subtitle">Użyj danych, którymi logujesz się do wersji komputerowej Edudziennika.</string>
|
||||
<string name="edziennik_progress_login_edudziennik_web">Logowanie do Edudziennika</string>
|
||||
</resources>
|
||||
|
@ -5,8 +5,8 @@ buildscript {
|
||||
kotlin_version = '1.3.50'
|
||||
|
||||
release = [
|
||||
versionName: "3.9.16-dev",
|
||||
versionCode: 3091600
|
||||
versionName: "3.9.17-dev",
|
||||
versionCode: 3091700
|
||||
]
|
||||
|
||||
setup = [
|
||||
|
Reference in New Issue
Block a user