[APIv2] Implement getting timetable for one week. Support arguments in EdziennikTask. Create new DataRemoveModel.

This commit is contained in:
Kuba Szczodrzyński 2019-11-11 14:11:05 +01:00
parent 4eeaa54a47
commit d4e9e1730f
21 changed files with 626 additions and 67 deletions

View File

@ -391,4 +391,21 @@ fun List<CharSequence>.concat(delimiter: String? = null): CharSequence {
fun TextView.setText(@StringRes resid: Int, vararg formatArgs: Any) {
text = context.getString(resid, *formatArgs)
}
}
fun JsonObject(vararg properties: Pair<String, Any>): JsonObject {
return JsonObject().apply {
for (property in properties) {
when (property.second) {
is JsonElement -> add(property.first, property.second as JsonElement)
is String -> addProperty(property.first, property.second as String)
is Char -> addProperty(property.first, property.second as Char)
is Number -> addProperty(property.first, property.second as Number)
is Boolean -> addProperty(property.first, property.second as Boolean)
}
}
}
}
fun JsonArray?.isNullOrEmpty(): Boolean = (this?.size() ?: 0) == 0
fun JsonArray.isEmpty(): Boolean = this.size() == 0

View File

@ -1,5 +1,6 @@
package pl.szczodrzynski.edziennik.api.v2.events.task
import com.google.gson.JsonObject
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.api.v2.*
@ -18,7 +19,7 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
fun firstLogin(loginStore: LoginStore) = EdziennikTask(-1, FirstLoginRequest(loginStore))
fun sync() = EdziennikTask(-1, SyncRequest())
fun syncProfile(profileId: Int, viewIds: List<Pair<Int, Int>>? = null) = EdziennikTask(profileId, SyncProfileRequest(viewIds))
fun syncProfile(profileId: Int, viewIds: List<Pair<Int, Int>>? = null, arguments: JsonObject? = null) = EdziennikTask(profileId, SyncProfileRequest(viewIds, arguments))
fun syncProfileList(profileList: List<Int>) = EdziennikTask(-1, SyncProfileListRequest(profileList))
fun messageGet(profileId: Int, messageId: Int) = EdziennikTask(profileId, MessageGetRequest(messageId))
fun announcementsRead(profileId: Int) = EdziennikTask(profileId, AnnouncementsReadRequest())
@ -50,7 +51,7 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
private var edziennikInterface: EdziennikInterface? = null
fun run(app: App, taskCallback: EdziennikCallback) {
internal fun run(app: App, taskCallback: EdziennikCallback) {
edziennikInterface = when (loginStore.type) {
LOGIN_TYPE_LIBRUS -> Librus(app, profile, loginStore, taskCallback)
LOGIN_TYPE_MOBIDZIENNIK -> Mobidziennik(app, profile, loginStore, taskCallback)
@ -66,7 +67,8 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
when (request) {
is SyncProfileRequest -> edziennikInterface?.sync(
featureIds = request.viewIds?.flatMap { Features.getIdsByView(it.first, it.second) } ?: Features.getAllIds(),
viewId = request.viewIds?.get(0)?.first)
viewId = request.viewIds?.get(0)?.first,
arguments = request.arguments)
is MessageGetRequest -> edziennikInterface?.getMessage(request.messageId)
is FirstLoginRequest -> edziennikInterface?.firstLogin()
is AnnouncementsReadRequest -> edziennikInterface?.markAllAnnouncementsAsRead()
@ -83,7 +85,7 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
data class FirstLoginRequest(val loginStore: LoginStore)
class SyncRequest
data class SyncProfileRequest(val viewIds: List<Pair<Int, Int>>? = null)
data class SyncProfileRequest(val viewIds: List<Pair<Int, Int>>? = null, val arguments: JsonObject? = null)
data class SyncProfileListRequest(val profileList: List<Int>)
data class MessageGetRequest(val messageId: Int)
class AnnouncementsReadRequest

View File

@ -4,6 +4,7 @@
package pl.szczodrzynski.edziennik.api.v2.idziennik
import com.google.gson.JsonObject
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
import pl.szczodrzynski.edziennik.api.v2.idziennik.data.IdziennikData
@ -48,7 +49,8 @@ class Idziennik(val app: App, val profile: Profile?, val loginStore: LoginStore,
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
__/ |
|__*/
override fun sync(featureIds: List<Int>, viewId: Int?) {
override fun sync(featureIds: List<Int>, viewId: Int?, arguments: JsonObject?) {
data.arguments = arguments
data.prepare(idziennikLoginMethods, IdziennikFeatures, featureIds, viewId)
d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")

View File

@ -4,8 +4,10 @@
package pl.szczodrzynski.edziennik.api.v2.interfaces
import com.google.gson.JsonObject
interface EdziennikInterface {
fun sync(featureIds: List<Int>, viewId: Int? = null)
fun sync(featureIds: List<Int>, viewId: Int? = null, arguments: JsonObject? = null)
fun getMessage(messageId: Int)
fun markAllAnnouncementsAsRead()
fun firstLogin()

View File

@ -4,6 +4,7 @@
package pl.szczodrzynski.edziennik.api.v2.librus
import com.google.gson.JsonObject
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.api.v2.*
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
@ -49,7 +50,8 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
__/ |
|__*/
override fun sync(featureIds: List<Int>, viewId: Int?) {
override fun sync(featureIds: List<Int>, viewId: Int?, arguments: JsonObject?) {
data.arguments = arguments
data.prepare(librusLoginMethods, LibrusFeatures, featureIds, viewId)
login()
}
@ -173,7 +175,10 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
login()
}
// TODO PORTAL CAPTCHA
ERROR_LIBRUS_API_TIMETABLE_NOT_PUBLIC,
ERROR_LIBRUS_API_TIMETABLE_NOT_PUBLIC -> {
loginStore.putLoginData("timetableNotPublic", true)
data()
}
ERROR_LIBRUS_API_LUCKY_NUMBER_NOT_ACTIVE,
ERROR_LIBRUS_API_NOTES_NOT_ACTIVE -> {
data()

View File

@ -4,11 +4,13 @@
package pl.szczodrzynski.edziennik.api.v2.librus.data.api
import androidx.core.util.isEmpty
import com.google.gson.JsonObject
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.api.v2.librus.DataLibrus
import pl.szczodrzynski.edziennik.api.v2.librus.ENDPOINT_LIBRUS_API_TIMETABLES
import pl.szczodrzynski.edziennik.api.v2.librus.data.LibrusApi
import pl.szczodrzynski.edziennik.api.v2.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
@ -22,20 +24,42 @@ class LibrusApiTimetables(override val data: DataLibrus,
}
init {
apiGet(TAG, "Timetables") { json ->
if (data.classrooms.isEmpty()) {
data.db.classroomDao().getAllNow(profileId).toSparseArray(data.classrooms) { it.id }
}
val currentWeekStart = Date.getToday().let { it.stepForward(0, 0, -it.weekDay) }
val getDate = data.arguments?.getString("weekStart") ?: currentWeekStart.stringY_m_d
apiGet(TAG, "Timetables?weekStart=$getDate") { json ->
val days = json.getJsonObject("Timetable")
days?.entrySet()?.forEach { (dateString, dayEl) ->
val lessonDate = dateString?.let { Date.fromY_m_d(it) } ?: return@forEach
val day = dayEl?.asJsonArray
val lessonDate = dateString?.let { Date.fromY_m_d(it) } ?: return@forEach
var lessonsFound = false
day?.forEach { lessonRangeEl ->
val lessonRange = lessonRangeEl?.asJsonArray?.asJsonObjectList()
if (lessonRange?.isNullOrEmpty() == false)
lessonsFound = true
lessonRange?.forEachIndexed { index, lesson ->
parseLesson(lessonDate, lesson)
}
}
if (day.isNullOrEmpty() || !lessonsFound) {
data.lessonNewList += Lesson(profileId, lessonDate.inUnix).apply {
type = Lesson.TYPE_NO_LESSONS
date = lessonDate
}
}
}
val weekStart = Date.fromY_m_d(getDate)
val weekEnd = weekStart.clone().stepForward(0, 0, 6)
data.toRemove.add(DataRemoveModel.Timetable.between(weekStart, weekEnd))
data.setSyncNext(ENDPOINT_LIBRUS_API_TIMETABLES, SYNC_ALWAYS)
onSuccess()
}

View File

@ -4,6 +4,7 @@
package pl.szczodrzynski.edziennik.api.v2.mobidziennik
import com.google.gson.JsonObject
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
@ -48,7 +49,8 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
__/ |
|__*/
override fun sync(featureIds: List<Int>, viewId: Int?) {
override fun sync(featureIds: List<Int>, viewId: Int?, arguments: JsonObject?) {
data.arguments = arguments
data.prepare(mobidziennikLoginMethods, MobidziennikFeatures, featureIds, viewId)
d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")

View File

@ -57,6 +57,8 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
val profileId
get() = profile?.id ?: -1
var arguments: JsonObject? = null
/**
* A callback passed to all [Feature]s and [LoginMethod]s
*/
@ -130,24 +132,20 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
mTeamClass = value
}
var lessonsToRemove: DataRemoveModel? = null
var toRemove = mutableListOf<DataRemoveModel>()
val lessonList = mutableListOf<Lesson>()
val lessonChangeList = mutableListOf<LessonChange>()
val lessonNewList = mutableListOf<pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson>()
var gradesToRemove: DataRemoveModel? = null
val gradeList = mutableListOf<Grade>()
var eventsToRemove: DataRemoveModel? = null
val eventList = mutableListOf<Event>()
var noticesToRemove: DataRemoveModel? = null
val noticeList = mutableListOf<Notice>()
var attendancesToRemove: DataRemoveModel? = null
val attendanceList = mutableListOf<Attendance>()
var announcementsToRemove: DataRemoveModel? = null
val announcementList = mutableListOf<Announcement>()
val luckyNumberList = mutableListOf<LuckyNumber>()
@ -250,6 +248,7 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
app.profile.loginStoreData = loginStore.data
}
// always present and not empty, during every sync
db.endpointTimerDao().addAll(endpointTimers)
db.teacherDao().clear(profileId)
db.teacherDao().addAll(teacherList.values())
@ -262,6 +261,7 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
db.gradeCategoryDao().clear(profileId)
db.gradeCategoryDao().addAll(gradeCategories.values())
// may be empty - extracted from DB on demand, by an endpoint
if (classrooms.size > 0)
db.classroomDao().addAll(classrooms.values())
if (attendanceTypes.size > 0)
@ -273,11 +273,15 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
if (teacherAbsenceTypes.size > 0)
db.teacherAbsenceTypeDao().addAll(teacherAbsenceTypes.values())
gradesToRemove?.let { it ->
it.removeAll?.let { _ -> db.gradeDao().clear(profileId) }
it.removeSemester?.let { semester -> db.gradeDao().clearForSemester(profileId, semester) }
// clear DB with DataRemoveModels added by endpoints
for (model in toRemove) {
when (model) {
is DataRemoveModel.Timetable -> model.commit(profileId, db.timetableDao())
is DataRemoveModel.Grades -> model.commit(profileId, db.gradeDao())
}
}
// not extracted from DB - always new data
if (lessonList.isNotEmpty()) {
db.lessonDao().clear(profile.id)
db.lessonDao().addAll(lessonList)

View File

@ -4,28 +4,37 @@
package pl.szczodrzynski.edziennik.api.v2.models
import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeDao
import pl.szczodrzynski.edziennik.data.db.modules.timetable.TimetableDao
import pl.szczodrzynski.edziennik.utils.models.Date
class DataRemoveModel {
var removeAll: Boolean? = null
var removeSemester: Int? = null
var removeDateFrom: Date? = null
var removeDateTo: Date? = null
constructor() {
this.removeAll = true
open class DataRemoveModel {
class Timetable(private val dateFrom: Date?, private val dateTo: Date?) : DataRemoveModel() {
companion object {
fun from(dateFrom: Date) = Timetable(dateFrom, null)
fun to(dateTo: Date) = Timetable(null, dateTo)
fun between(dateFrom: Date, dateTo: Date) = Timetable(dateFrom, dateTo)
}
fun commit(profileId: Int, dao: TimetableDao) {
if (dateFrom != null && dateTo != null) {
dao.clearBetweenDates(profileId, dateFrom, dateTo)
}
else {
dateFrom?.let { dateFrom -> dao.clearFromDate(profileId, dateFrom) }
dateTo?.let { dateTo -> dao.clearToDate(profileId, dateTo) }
}
}
}
constructor(semester: Int) {
this.removeSemester = semester
}
constructor(dateFrom: Date?, dateTo: Date) {
this.removeDateFrom = dateFrom
this.removeDateTo = dateTo
}
constructor(dateFrom: Date) {
this.removeDateFrom = dateFrom
class Grades(val all: Boolean, val semester: Int?) : DataRemoveModel() {
companion object {
fun all() = Grades(true, null)
fun semester(semester: Int) = Grades(false, semester)
}
fun commit(profileId: Int, dao: GradeDao) {
if (all) {
dao.clear(profileId)
}
semester?.let { dao.clearForSemester(profileId, it) }
}
}
}

View File

@ -4,6 +4,7 @@
package pl.szczodrzynski.edziennik.api.v2.template
import com.google.gson.JsonObject
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
@ -48,7 +49,8 @@ class Template(val app: App, val profile: Profile?, val loginStore: LoginStore,
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
__/ |
|__*/
override fun sync(featureIds: List<Int>, viewId: Int?) {
override fun sync(featureIds: List<Int>, viewId: Int?, arguments: JsonObject?) {
data.arguments = arguments
data.prepare(templateLoginMethods, TemplateFeatures, featureIds, viewId)
d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")

View File

@ -4,6 +4,7 @@
package pl.szczodrzynski.edziennik.api.v2.vulcan
import com.google.gson.JsonObject
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.api.v2.CODE_INTERNAL_LIBRUS_ACCOUNT_410
import pl.szczodrzynski.edziennik.api.v2.interfaces.EdziennikCallback
@ -48,7 +49,8 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va
|_| |_| |_|\___| /_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|
__/ |
|__*/
override fun sync(featureIds: List<Int>, viewId: Int?) {
override fun sync(featureIds: List<Int>, viewId: Int?, arguments: JsonObject?) {
data.arguments = arguments
data.prepare(vulcanLoginMethods, VulcanFeatures, featureIds, viewId)
d(TAG, "LoginMethod IDs: ${data.targetLoginMethodIds}")
d(TAG, "Endpoint IDs: ${data.targetEndpointIds}")

View File

@ -17,6 +17,7 @@ import pl.szczodrzynski.edziennik.utils.models.Time
])
open class Lesson(val profileId: Int, @PrimaryKey val id: Long) {
companion object {
const val TYPE_NO_LESSONS = -1
const val TYPE_NORMAL = 0
const val TYPE_CANCELLED = 1
const val TYPE_CHANGE = 2

View File

@ -17,6 +17,13 @@ interface TimetableDao {
@Query("DELETE FROM timetable WHERE profileId = :profileId")
fun clear(profileId: Int)
@Query("DELETE FROM timetable WHERE profileId = :profileId AND (type != 3 AND date >= :dateFrom) OR ((type = 3 OR type = 1) AND oldDate >= :dateFrom)")
fun clearFromDate(profileId: Int, dateFrom: Date)
@Query("DELETE FROM timetable WHERE profileId = :profileId AND (type != 3 AND date <= :dateTo) OR ((type = 3 OR type = 1) AND oldDate <= :dateTo)")
fun clearToDate(profileId: Int, dateTo: Date)
@Query("DELETE FROM timetable WHERE profileId = :profileId AND (type != 3 AND date >= :dateFrom AND date <= :dateTo) OR ((type = 3 OR type = 1) AND oldDate >= :dateFrom AND oldDate <= :dateTo)")
fun clearBetweenDates(profileId: Int, dateFrom: Date, dateTo: Date)
@Query("""
SELECT
timetable.*,

View File

@ -112,7 +112,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
app.notifier.postAll(profile);
app.saveConfig("notifications");*/
d(TAG, "Syncing profile " + profile.getId());
EdziennikTask.Companion.syncProfile(profile.getId(), null).enqueue(app);
EdziennikTask.Companion.syncProfile(profile.getId(), null, null).enqueue(app);
} else {
/*app.notifier.add(new Notification(app.getContext(), remoteMessage.getData().get("message"))
.withProfileData(profile.id, profile.name)
@ -123,7 +123,7 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
app.notifier.postAll(profile);
app.saveConfig("notifications");*/
d(TAG, "Syncing profile " + profile.getId());
EdziennikTask.Companion.syncProfile(profile.getId(), null).enqueue(app);
EdziennikTask.Companion.syncProfile(profile.getId(), null, null).enqueue(app);
}
}
});

View File

@ -10,6 +10,7 @@ import com.mikepenz.iconics.typeface.library.community.material.CommunityMateria
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.MainActivity
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.api.v2.LOGIN_TYPE_LIBRUS
import pl.szczodrzynski.edziennik.databinding.FragmentTimetableV2Binding
import pl.szczodrzynski.edziennik.utils.Themes
import pl.szczodrzynski.edziennik.utils.models.Date
@ -42,6 +43,14 @@ class TimetableFragment : Fragment() {
if (app.profile == null || !isAdded)
return
if (app.profile.loginStoreType == LOGIN_TYPE_LIBRUS && app.profile.getLoginData("timetableNotPublic", false)) {
b.timetableLayout.visibility = View.GONE
b.timetableNotPublicLayout.visibility = View.VISIBLE
return
}
b.timetableLayout.visibility = View.VISIBLE
b.timetableNotPublicLayout.visibility = View.GONE
val items = mutableListOf<Date>()
val monthDayCount = listOf(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)

View File

@ -12,6 +12,7 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import com.linkedin.android.tachyon.DayView
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.api.v2.events.task.EdziennikTask
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
import pl.szczodrzynski.edziennik.data.db.modules.timetable.LessonFull
import pl.szczodrzynski.edziennik.databinding.FragmentTimetableV2DayBinding
@ -45,7 +46,6 @@ class TimetableDayFragment(val date: Date) : Fragment() {
return
Log.d(TAG, "onViewCreated, date=$date")
b.date.text = date.formattedString
// Inflate a label view for each hour the day view will display
val hourLabelViews = ArrayList<View>()
@ -62,6 +62,31 @@ class TimetableDayFragment(val date: Date) : Fragment() {
}
private fun buildLessonViews(lessons: List<LessonFull>) {
if (lessons.isEmpty()) {
b.dayScroll.visibility = View.GONE
b.noTimetableLayout.visibility = View.VISIBLE
b.noLessonsLayout.visibility = View.GONE
b.noTimetableSync.setOnClickListener {
EdziennikTask.syncProfile(
profileId = App.profileId,
arguments = JsonObject(
"weekStart" to date.clone().stepForward(0, 0, -date.weekDay).stringY_m_d
)
).enqueue(activity)
}
return
}
if (lessons.size == 1 && lessons[0].type == Lesson.TYPE_NO_LESSONS) {
b.dayScroll.visibility = View.GONE
b.noTimetableLayout.visibility = View.GONE
b.noLessonsLayout.visibility = View.VISIBLE
return
}
b.dayScroll.visibility = View.VISIBLE
b.noTimetableLayout.visibility = View.GONE
b.noLessonsLayout.visibility = View.GONE
val eventViews = mutableListOf<View>()
val eventTimeRanges = mutableListOf<DayView.EventTimeRange>()

View File

@ -0,0 +1,61 @@
<!--
~ Copyright (c) Kuba Szczodrzyński 2019-11-11.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="128dp"
android:height="128dp"
android:viewportWidth="128"
android:viewportHeight="128">
<path
android:pathData="m117,76h4c3.852,0 7,-3.148 7,-7 0,-3.852 -3.148,-7 -7,-7h-13c-2.199,0 -4,-1.801 -4,-4s1.801,-4 4,-4h11c3.852,0 7,-3.148 7,-7 0,-3.852 -3.148,-7 -7,-7h-1c-2.211,0 -4,-1.789 -4,-4 0,-2.211 1.789,-4 4,-4h4c3.695,0 6.637,-3.387 5.879,-7.211 -0.566,-2.844 -3.238,-4.789 -6.141,-4.789h-15.738c-1.656,0 -3,-1.344 -3,-3s1.344,-3 3,-3h6.824c2.277,0 4.402,-1.441 4.992,-3.641 0.895,-3.328 -1.625,-6.359 -4.816,-6.359h-96c-3.852,0 -7,3.148 -7,7 0,3.852 3.148,7 7,7h3c2.211,0 4,1.789 4,4 0,2.211 -1.789,4 -4,4h-10.77c-3.34,0 -6.391,2.242 -7.074,5.516 -0.941,4.488 2.508,8.484 6.844,8.484h15l-6,24h-10.77c-3.34,0 -6.391,2.242 -7.074,5.516 -0.941,4.488 2.508,8.484 6.844,8.484h1c2.211,0 4,1.789 4,4 0,2.211 -1.789,4 -4,4h-1c-4.336,0 -7.785,3.996 -6.844,8.484 0.684,3.273 3.734,5.516 7.074,5.516h10.77c2.211,0 4,1.789 4,4s-1.789,4 -4,4h-2.77c-3.34,0 -6.391,2.242 -7.074,5.516 -0.941,4.488 2.508,8.484 6.844,8.484h97c3.313,0 6,-2.688 6,-6s-2.688,-6 -6,-6h-1c-2.762,0 -5,-2.238 -5,-5s2.238,-5 5,-5h6c3.852,0 7,-3.148 7,-7 0,-3.852 -3.148,-7 -7,-7 -2.75,0 -5,-2.25 -5,-5s2.25,-5 5,-5z">
<aapt:attr name="android:fillColor">
<gradient
android:gradientRadius="100.522"
android:centerX="63.746"
android:centerY="71.138"
android:type="radial"
android:tileMode="mirror">
<item android:offset="0" android:color="#1F0FCCFF"/>
<item android:offset="0.1927" android:color="#1F0FCEFF"/>
<item android:offset="0.7025" android:color="#1F0FD5FF"/>
<item android:offset="1" android:color="#1F0FD7FF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="m103.24,15.168 l-7.883,7.871c-8.746,-7.063 -19.719,-11.039 -31.355,-11.039 -27.57,0 -50,22.43 -50,50 0,27.57 22.43,50 50,50 17.758,0 34.348,-9.367 43.301,-24.449 1.41,-2.375 0.625,-5.441 -1.75,-6.852 -2.367,-1.41 -5.438,-0.629 -6.852,1.746 -7.156,12.062 -20.453,19.555 -34.699,19.555 -22.055,0 -40,-17.945 -40,-40 0,-22.055 17.945,-40 40,-40 8.934,0 17.371,2.938 24.223,8.16l-9.063,9.047c-2.48,2.5 -0.719,6.762 2.801,6.762h24.039c2.199,0 4,-1.801 4,-4v-24c0,-3.52 -4.262,-5.301 -6.762,-2.801z">
<aapt:attr name="android:fillColor">
<gradient
android:startY="125.452"
android:startX="62"
android:endY="6.4762"
android:endX="62"
android:type="linear"
android:tileMode="mirror">
<item android:offset="0" android:color="#FFFEAA53"/>
<item android:offset="0.6124" android:color="#FFFFCD49"/>
<item android:offset="1" android:color="#FFFFDE44"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="m68,85c0,2.762 -2.238,5 -5,5s-5,-2.238 -5,-5 2.238,-5 5,-5 5,2.238 5,5zM70,41c0,-3.867 -3.133,-7 -7,-7 -3.867,0 -7,3.133 -7,7 0,0.047 0.016,0.094 0.016,0.141h-0.016l2.438,28.59c0.203,2.414 2.188,4.269 4.563,4.269s4.359,-1.855 4.563,-4.269l2.438,-28.59h-0.016c0,-0.047 0.016,-0.094 0.016,-0.141z">
<aapt:attr name="android:fillColor">
<gradient
android:startY="90"
android:startX="63"
android:endY="11.7176"
android:endX="63"
android:type="linear"
android:tileMode="mirror">
<item android:offset="0" android:color="#FFFF634D"/>
<item android:offset="0.2043" android:color="#FFFE6464"/>
<item android:offset="0.5209" android:color="#FFFC6581"/>
<item android:offset="0.7936" android:color="#FFFA6694"/>
<item android:offset="0.9892" android:color="#FFFA669A"/>
</gradient>
</aapt:attr>
</path>
</vector>

View File

@ -0,0 +1,45 @@
<!--
~ Copyright (c) Kuba Szczodrzyński 2019-11-11.
-->
<vector android:height="128dp" android:viewportHeight="64"
android:viewportWidth="64" android:width="128dp"
xmlns:aapt="http://schemas.android.com/aapt" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:pathData="m59,16h2c1.848,0 3.319,-1.693 2.94,-3.605 -0.283,-1.423 -1.62,-2.395 -3.071,-2.395h-10.369c-0.828,0 -1.5,-0.672 -1.5,-1.5s0.672,-1.5 1.5,-1.5h5.912c1.139,0 2.202,-0.721 2.497,-1.821 0.446,-1.663 -0.813,-3.179 -2.409,-3.179h-48c-1.925,0 -3.5,1.575 -3.5,3.5s1.575,3.5 3.5,3.5h1.5c1.105,0 2,0.895 2,2s-0.895,2 -2,2h-5.385c-1.67,0 -3.195,1.122 -3.537,2.757 -0.47,2.245 1.254,4.243 3.422,4.243h7.5l-3,12h-5.385c-1.67,0 -3.195,1.122 -3.537,2.757 -0.47,2.245 1.254,4.243 3.422,4.243h0.5c1.105,0 2,0.895 2,2s-0.895,2 -2,2h-0.5c-2.168,0 -3.892,1.998 -3.422,4.243 0.342,1.635 1.867,2.757 3.537,2.757h5.385c1.105,0 2,0.895 2,2s-0.895,2 -2,2h-1.385c-1.67,0 -3.195,1.122 -3.537,2.757 -0.47,2.245 1.254,4.243 3.422,4.243h48.5c1.657,0 3,-1.343 3,-3s-1.343,-3 -3,-3h-0.5c-1.381,0 -2.5,-1.119 -2.5,-2.5s1.119,-2.5 2.5,-2.5h4.5c1.657,0 3,-1.343 3,-3s-1.343,-3 -3,-3h-8.377c2.141,-3.494 3.377,-7.602 3.377,-12 0,-2.441 -0.384,-4.792 -1.088,-7h6.501c1.139,0 2.202,-0.721 2.497,-1.821 0.445,-1.663 -0.814,-3.179 -2.41,-3.179h-1.5c-1.105,0 -2,-0.895 -2,-2s0.895,-2 2,-2z">
<aapt:attr name="android:fillColor">
<gradient android:centerX="32" android:centerY="31.500021"
android:gradientRadius="32" android:tileMode="mirror" android:type="radial">
<item android:color="#1F0FCCFF" android:offset="0"/>
<item android:color="#1F0FCEFF" android:offset="0.193"/>
<item android:color="#1F0FD5FF" android:offset="0.703"/>
<item android:color="#1F0ECEFF" android:offset="1"/>
</gradient>
</aapt:attr>
</path>
<path android:pathData="M51.483,15.326l3.937,-3.93c1.24,-1.25 0.36,-3.38 -1.4,-3.38H42c-1.1,0 -2,0.9 -2,2v12c0,1.76 2.13,2.65 3.38,1.4l4.537,-4.529C50.532,22.313 52,26.533 52,31c0,11.215 -8.565,20 -19.5,20c-1.381,0 -2.5,1.119 -2.5,2.5s1.119,2.5 2.5,2.5C46.238,56 57,45.019 57,31C57,25.183 55.012,19.699 51.483,15.326z">
<aapt:attr name="android:fillColor">
<gradient android:endX="43.5" android:endY="-21.15"
android:startX="43.5" android:startY="59.034"
android:tileMode="mirror" android:type="linear">
<item android:color="#FFFF634D" android:offset="0"/>
<item android:color="#FFFE6464" android:offset="0.204"/>
<item android:color="#FFFC6581" android:offset="0.521"/>
<item android:color="#FFFA6694" android:offset="0.794"/>
<item android:color="#FFFA669A" android:offset="0.989"/>
</gradient>
</aapt:attr>
</path>
<path android:pathData="M20.604,38.58l-4.523,4.53C13.468,39.683 12,35.463 12,31c0,-11.215 8.565,-20 19.5,-20c1.381,0 2.5,-1.119 2.5,-2.5S32.881,6 31.5,6C17.762,6 7,16.981 7,31c0,5.815 1.989,11.303 5.52,15.677L8.584,50.62c-1.25,1.25 -0.36,3.38 1.4,3.38h12c1.1,0 2,-0.9 2,-2V39.98C23.984,38.22 21.854,37.34 20.604,38.58z">
<aapt:attr name="android:fillColor">
<gradient android:endX="20.5" android:endY="-24.844"
android:startX="20.5" android:startY="55.227"
android:tileMode="mirror" android:type="linear">
<item android:color="#FFFF634D" android:offset="0"/>
<item android:color="#FFFE6464" android:offset="0.204"/>
<item android:color="#FFFC6581" android:offset="0.521"/>
<item android:color="#FFFA6694" android:offset="0.794"/>
<item android:color="#FFFA669A" android:offset="0.989"/>
</gradient>
</aapt:attr>
</path>
</vector>

View File

@ -0,0 +1,202 @@
<!--
~ Copyright (c) Kuba Szczodrzyński 2019-11-11.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="128dp"
android:height="128dp"
android:viewportWidth="128"
android:viewportHeight="128">
<path
android:pathData="m118,62.129h2.605c3.789,0 7.188,-2.84 7.383,-6.625 0.211,-4.035 -3,-7.375 -6.988,-7.375h-4.805c-1.965,0 -3.785,-1.328 -4.129,-3.262 -0.043,-0.25 -0.066,-0.5 -0.066,-0.746 0.004,-2.168 1.734,-3.93 3.887,-3.988 3.023,-0.082 5.731,-2.293 6.07,-5.297 0.027,-0.242 0.039,-0.477 0.039,-0.711 0,-3.313 -2.688,-5.996 -6,-5.996h-4.602c-0.434,0 -4.863,-0.035 -5.281,-0.105 -0.035,-0.008 -0.074,-0.016 -0.113,-0.023v18h-42v-18h25.715c0.438,-1.688 0.539,-3.512 -0.945,-5.719 -1.836,-2.742 -5.023,-4.281 -8.324,-4.281h-9.445c-1.656,0 -3,-1.344 -3,-3s1.344,-3 3,-3h0.66c3.25,0 6.16,-2.434 6.332,-5.68 0.18,-3.461 -2.57,-6.32 -5.992,-6.32h-57.66c-3.25,0 -6.16,2.434 -6.332,5.68 -0.18,3.457 2.57,6.32 5.992,6.32h15c1.656,0 3,1.344 3,3s-1.344,3 -3,3h-17c-4.418,0 -8,3.582 -8,8s3.582,8 8,8h26v12h-14l2,21.109c-1.07,0.801 -1.836,1.98 -1.973,3.375 -0.184,1.84 0.633,3.5 1.973,4.504v5.047c-0.027,0.148 -0.043,0.297 -0.027,0.449 0.301,2.992 -2.039,5.516 -4.973,5.516h-14.66c-2.984,0 -5.762,2.023 -6.25,4.965 -0.246,1.465 0.043,2.848 0.684,4.012 1.074,1.938 3.234,3.023 5.449,3.023h3.164c2.375,0 4.207,1.328 4.551,3.27 0.039,0.246 0.063,0.488 0.063,0.723 0.004,2.215 -1.789,4.008 -3.996,4.008h-0.004c-2.27,0 -4.473,1.203 -5.398,3.277 -1.98,4.426 1.207,8.723 5.398,8.723h62c3.313,0 6,-2.688 6,-6s-2.688,-6 -6,-6h-10v-20l46,0.129h9.66c3.141,0 6.168,-2.539 6.328,-5.676 0.184,-3.461 -2.57,-6.324 -5.992,-6.324h-0.023,-0.035c-1.555,0 -3.078,-0.508 -4.156,-1.535 -0.34,-0.324 -0.637,-0.699 -0.875,-1.129 -2.574,-4.637 0.711,-9.336 5.094,-9.336z">
<aapt:attr name="android:fillColor">
<gradient
android:gradientRadius="80.322"
android:centerX="60.334"
android:centerY="65.146"
android:type="radial"
android:tileMode="mirror">
<item android:offset="0" android:color="#1F0FCCFF"/>
<item android:offset="0.1927" android:color="#1F0FCEFF"/>
<item android:offset="0.7025" android:color="#1F0FD5FF"/>
<item android:offset="1" android:color="#1F0FD7FF"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="m18,100v-60h92v60c0,5.523 -4.477,10 -10,10h-72c-5.523,0 -10,-4.477 -10,-10z">
<aapt:attr name="android:fillColor">
<gradient
android:startY="110"
android:startX="64"
android:endY="40"
android:endX="64"
android:type="linear"
android:tileMode="mirror">
<item android:offset="0" android:color="#FFFFC662"/>
<item android:offset="0.0036" android:color="#FFFFC662"/>
<item android:offset="0.6085" android:color="#FFFFC582"/>
<item android:offset="1" android:color="#FFFFC491"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="m110,29.602v16.398h-92v-16.398c0,-5.309 4.332,-9.602 9.684,-9.602h72.633c5.352,0 9.684,4.293 9.684,9.602">
<aapt:attr name="android:fillColor">
<gradient
android:startY="46"
android:startX="64"
android:endY="20"
android:endX="64"
android:type="linear"
android:tileMode="mirror">
<item android:offset="0" android:color="#FFFF634D"/>
<item android:offset="0.2083" android:color="#FFFD6464"/>
<item android:offset="0.5223" android:color="#FFFC6582"/>
<item android:offset="0.7935" android:color="#FFFA6694"/>
<item android:offset="0.9892" android:color="#FFFA669A"/>
<item android:offset="1" android:color="#FFFA669A"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="m49.309,20h-12.621c-2.832,1.988 -4.688,5.277 -4.688,9 0,6.07 4.93,11 11,11 6.07,0 11,-4.93 11,-11 0,-3.723 -1.855,-7.012 -4.691,-9z">
<aapt:attr name="android:fillColor">
<gradient
android:startY="40"
android:startX="43"
android:endY="20"
android:endX="43"
android:type="linear"
android:tileMode="mirror">
<item android:offset="0" android:color="#FFFF5840"/>
<item android:offset="0.0072" android:color="#FFFF5840"/>
<item android:offset="0.9892" android:color="#FFFA528C"/>
<item android:offset="1" android:color="#FFFA528C"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="m43,34c-2.75,0 -5,-2.25 -5,-5v-12c0,-2.75 2.25,-5 5,-5s5,2.25 5,5v12c0,2.75 -2.25,5 -5,5z">
<aapt:attr name="android:fillColor">
<gradient
android:startY="12"
android:startX="43"
android:endY="34"
android:endX="43"
android:type="linear"
android:tileMode="mirror">
<item android:offset="0" android:color="#FFA4A4A4"/>
<item android:offset="0.6301" android:color="#FF7F7F7F"/>
<item android:offset="1" android:color="#FF6F6F6F"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="m91.309,20h-12.621c-2.832,1.988 -4.688,5.277 -4.688,9 0,6.07 4.93,11 11,11 6.07,0 11,-4.93 11,-11 0,-3.723 -1.855,-7.012 -4.691,-9z">
<aapt:attr name="android:fillColor">
<gradient
android:startY="40"
android:startX="85"
android:endY="20"
android:endX="85"
android:type="linear"
android:tileMode="mirror">
<item android:offset="0" android:color="#FFFF5840"/>
<item android:offset="0.0072" android:color="#FFFF5840"/>
<item android:offset="0.9892" android:color="#FFFA528C"/>
<item android:offset="1" android:color="#FFFA528C"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="m85,34c-2.75,0 -5,-2.25 -5,-5v-12c0,-2.75 2.25,-5 5,-5s5,2.25 5,5v12c0,2.75 -2.25,5 -5,5z">
<aapt:attr name="android:fillColor">
<gradient
android:startY="12"
android:startX="85"
android:endY="34"
android:endX="85"
android:type="linear"
android:tileMode="mirror">
<item android:offset="0" android:color="#FFA4A4A4"/>
<item android:offset="0.6301" android:color="#FF7F7F7F"/>
<item android:offset="1" android:color="#FF6F6F6F"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="m78,81.008c0,2.762 2.238,5 5,4.996h2.992c3.316,-0.008 6.008,2.684 6.008,5.996s-2.688,6 -6,6h-8c-3.313,0 -6,2.688 -6,6s2.688,6 6,6h22c5.523,0 10,-4.477 10,-10v-24l-27.008,0.012c-2.758,-0 -4.992,2.234 -4.992,4.996z"
android:fillColor="#ffb86a"/>
<path
android:pathData="m18,68h17.785c1.992,0 3.84,-1.363 4.16,-3.328 0.406,-2.508 -1.516,-4.672 -3.945,-4.672h-3c-1.656,0 -3,-1.344 -3,-3s1.344,-3 3,-3h14.785c1.992,0 3.84,-1.363 4.16,-3.328 0.406,-2.508 -1.516,-4.672 -3.945,-4.672h-30z">
<aapt:attr name="android:fillColor">
<gradient
android:startY="108.25"
android:startX="35"
android:endY="43.742"
android:endX="35"
android:type="linear"
android:tileMode="mirror">
<item android:offset="0" android:color="#FFFFCE76"/>
<item android:offset="0.0036" android:color="#FFFFCE76"/>
<item android:offset="0.6054" android:color="#FFFFCD92"/>
<item android:offset="1" android:color="#FFFFCCA0"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="m98,62c0,3.313 -2.688,6 -6,6s-6,-2.688 -6,-6 2.688,-6 6,-6 6,2.688 6,6z"
android:fillColor="#ffb977"/>
<path
android:pathData="m48,74h-8c-2.211,0 -4,-1.789 -4,-4v-8c0,-2.211 1.789,-4 4,-4h8c2.211,0 4,1.789 4,4v8c0,2.211 -1.789,4 -4,4zM72,70v-8c0,-2.211 -1.789,-4 -4,-4h-8c-2.211,0 -4,1.789 -4,4v8c0,2.211 1.789,4 4,4h8c2.211,0 4,-1.789 4,-4zM92,70v-8c0,-2.211 -1.789,-4 -4,-4h-8c-2.211,0 -4,1.789 -4,4v8c0,2.211 1.789,4 4,4h8c2.211,0 4,-1.789 4,-4zM52,90v-8c0,-2.211 -1.789,-4 -4,-4h-8c-2.211,0 -4,1.789 -4,4v8c0,2.211 1.789,4 4,4h8c2.211,0 4,-1.789 4,-4zM72,90v-8c0,-2.211 -1.789,-4 -4,-4h-8c-2.211,0 -4,1.789 -4,4v8c0,2.211 1.789,4 4,4h8c2.211,0 4,-1.789 4,-4zM92,90v-8c0,-2.211 -1.789,-4 -4,-4h-8c-2.211,0 -4,1.789 -4,4v8c0,2.211 1.789,4 4,4h8c2.211,0 4,-1.789 4,-4z">
<aapt:attr name="android:fillColor">
<gradient
android:startY="94"
android:startX="64"
android:endY="58"
android:endX="64"
android:type="linear"
android:tileMode="mirror">
<item android:offset="0" android:color="#FFFFE79F"/>
<item android:offset="0.1186" android:color="#FFFFE9A6"/>
<item android:offset="1" android:color="#FFFFF5D5"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="m124,104c0,11.047 -8.953,20 -20,20 -11.047,0 -20,-8.953 -20,-20 0,-11.047 8.953,-20 20,-20 11.047,0 20,8.953 20,20z"
android:fillColor="#fff"/>
<path
android:pathData="m104,80c-13.254,0 -24,10.746 -24,24 0,13.254 10.746,24 24,24 13.254,0 24,-10.746 24,-24 0,-13.254 -10.746,-24 -24,-24zM104,120c-8.836,0 -16,-7.164 -16,-16 0,-8.836 7.164,-16 16,-16 8.836,0 16,7.164 16,16 0,8.836 -7.164,16 -16,16z">
<aapt:attr name="android:fillColor">
<gradient
android:startY="128"
android:startX="104"
android:endY="80"
android:endX="104"
android:type="linear"
android:tileMode="mirror">
<item android:offset="0" android:color="#FF155CDE"/>
<item android:offset="0.6248" android:color="#FF2289E7"/>
<item android:offset="1" android:color="#FF289FEC"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="m113.41,110.59 l-5.563,-5.563c0.086,-0.328 0.148,-0.668 0.148,-1.023 0,-1.477 -0.809,-2.754 -2,-3.445v-6.555c0,-1.105 -0.895,-2 -2,-2s-2,0.895 -2,2v6.555c-1.191,0.691 -2,1.969 -2,3.445 0,2.211 1.789,4 4,4 0.355,0 0.695,-0.063 1.023,-0.148l5.563,5.563c0.391,0.391 0.902,0.586 1.414,0.586s1.023,-0.195 1.414,-0.586c0.781,-0.781 0.781,-2.047 0,-2.828z">
<aapt:attr name="android:fillColor">
<gradient
android:startY="92"
android:startX="107"
android:endY="114"
android:endX="107"
android:type="linear"
android:tileMode="mirror">
<item android:offset="0" android:color="#FF919191"/>
<item android:offset="1" android:color="#FF6F6F6F"/>
</gradient>
</aapt:attr>
</path>
</vector>

View File

@ -1,15 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center">
android:layout_height="match_parent">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/timetableLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
tools:visibility="gone">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
@ -41,5 +42,36 @@
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/timetableNotPublicLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="gone"
android:gravity="center"
tools:visibility="visible">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_no_timetable" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:fontFamily="sans-serif-light"
android:text="Brak planu lekcji"
android:textSize="24sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Plan lekcji nie został opublikowany przez szkołę."
android:textSize="16sp" />
</LinearLayout>
</FrameLayout>
</layout>

View File

@ -1,24 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_blank_fragment"
android:textSize="24sp"
android:visibility="gone"/>
<ScrollView
android:id="@+id/dayScroll"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.linkedin.android.tachyon.DayView
android:id="@+id/day"
android:layout_width="match_parent"
@ -32,9 +24,123 @@
app:hourDividerColor="#b0b0b0"
app:hourLabelMarginEnd="10dp"
app:hourLabelWidth="40dp"
app:startHour="5" />
app:startHour="5"
tools:visibility="gone"/>
</ScrollView>
</LinearLayout>
<LinearLayout
android:id="@+id/noLessonsLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="gone"
android:gravity="center"
tools:visibility="gone">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_timetable" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:fontFamily="sans-serif-light"
android:text="Brak lekcji tego dnia"
android:textSize="24sp" />
</LinearLayout>
<LinearLayout
android:id="@+id/freeDayLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="gone"
android:gravity="center"
tools:visibility="gone">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_sunbed" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:fontFamily="sans-serif-light"
android:text="Dzień wolny"
android:textSize="24sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="W tym dniu nie ma lekcji:"
android:textSize="14sp" />
<TextView
android:id="@+id/freeDayText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Ferie zimowe"
android:textSize="16sp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/freeDayShowTimetable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Pokaż plan lekcji" />
</LinearLayout>
<LinearLayout
android:id="@+id/noTimetableLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="gone"
android:gravity="center"
tools:visibility="gone">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_sync" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:fontFamily="sans-serif-light"
android:text="Brak planu lekcji"
android:textSize="24sp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Nie pobrano planu lekcji na ten tydzień."
android:textSize="16sp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/noTimetableSync"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Pobierz plan lekcji" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="na tydzień 2019-11-11"
android:textSize="12sp"
android:textStyle="italic"/>
</LinearLayout>
</FrameLayout>
</layout>