diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fb824573..2c24b426 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -12,7 +12,7 @@ - + diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/config/ProfileConfigUI.kt b/app/src/main/java/pl/szczodrzynski/edziennik/config/ProfileConfigUI.kt index 187cb6bd..a3fb184e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/config/ProfileConfigUI.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/config/ProfileConfigUI.kt @@ -69,4 +69,24 @@ class ProfileConfigUI(private val config: ProfileConfig) { var messagesGreetingText: String? get() { mMessagesGreetingText = mMessagesGreetingText ?: config.values["messagesGreetingText"]; return mMessagesGreetingText } set(value) { config.set("messagesGreetingText", value); mMessagesGreetingText = value } + + private var mTimetableShowAttendance: Boolean? = null + var timetableShowAttendance: Boolean + get() { mTimetableShowAttendance = mTimetableShowAttendance ?: config.values.get("timetableShowAttendance", true); return mTimetableShowAttendance ?: true } + set(value) { config.set("timetableShowAttendance", value); mTimetableShowAttendance = value } + + private var mTimetableShowEvents: Boolean? = null + var timetableShowEvents: Boolean + get() { mTimetableShowEvents = mTimetableShowEvents ?: config.values.get("timetableShowEvents", true); return mTimetableShowEvents ?: true } + set(value) { config.set("timetableShowEvents", value); mTimetableShowEvents = value } + + private var mTimetableTrimHourRange: Boolean? = null + var timetableTrimHourRange: Boolean + get() { mTimetableTrimHourRange = mTimetableTrimHourRange ?: config.values.get("timetableTrimHourRange", false); return mTimetableTrimHourRange ?: false } + set(value) { config.set("timetableTrimHourRange", value); mTimetableTrimHourRange = value } + + private var mTimetableColorSubjectName: Boolean? = null + var timetableColorSubjectName: Boolean + get() { mTimetableColorSubjectName = mTimetableColorSubjectName ?: config.values.get("timetableColorSubjectName", false); return mTimetableColorSubjectName ?: false } + set(value) { config.set("timetableColorSubjectName", value); mTimetableColorSubjectName = value } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/settings/TimetableConfigDialog.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/settings/TimetableConfigDialog.kt new file mode 100644 index 00000000..b784165b --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/dialogs/settings/TimetableConfigDialog.kt @@ -0,0 +1,44 @@ +/* + * Copyright (c) Kuba Szczodrzyński 2022-10-7. + */ + +package pl.szczodrzynski.edziennik.ui.dialogs.settings + +import android.view.LayoutInflater +import androidx.appcompat.app.AppCompatActivity +import pl.szczodrzynski.edziennik.MainActivity +import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.databinding.TimetableConfigDialogBinding +import pl.szczodrzynski.edziennik.ext.Intent +import pl.szczodrzynski.edziennik.ext.onClick +import pl.szczodrzynski.edziennik.ui.dialogs.base.ConfigDialog +import pl.szczodrzynski.edziennik.ui.timetable.TimetableFragment + +class TimetableConfigDialog( + activity: AppCompatActivity, + reloadOnDismiss: Boolean = true, + onShowListener: ((tag: String) -> Unit)? = null, + onDismissListener: ((tag: String) -> Unit)? = null, +) : ConfigDialog( + activity, + reloadOnDismiss, + onShowListener, + onDismissListener, +) { + + override val TAG = "TimetableConfigDialog" + + override fun getTitleRes() = R.string.menu_timetable_config + override fun inflate(layoutInflater: LayoutInflater) = + TimetableConfigDialogBinding.inflate(layoutInflater) + + private val profileConfig by lazy { app.config.getFor(app.profileId).ui } + + override suspend fun loadConfig() { + b.config = profileConfig + } + + override suspend fun saveConfig() { + activity.sendBroadcast(Intent(TimetableFragment.ACTION_RELOAD_PAGES)) + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/home/HomeFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/home/HomeFragment.kt index 54f94433..635c7b56 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/home/HomeFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/home/HomeFragment.kt @@ -81,7 +81,8 @@ class HomeFragment : Fragment(), CoroutineScope { private val job: Job = Job() override val coroutineContext: CoroutineContext get() = job + Dispatchers.Main - + private val manager + get() = app.permissionManager override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { activity = (getActivity() as MainActivity?) ?: return null context ?: return null @@ -96,6 +97,10 @@ class HomeFragment : Fragment(), CoroutineScope { if (!isAdded) return + if (!manager.isNotificationPermissionGranted) { + manager.requestNotificationsPermission(activity, 0, false){} + } + activity.bottomSheet.prependItems( BottomSheetPrimaryItem(true) .withTitle(R.string.menu_add_remove_cards) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/login/LoginChooserFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/login/LoginChooserFragment.kt index 1bfe0abd..a4367dee 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/login/LoginChooserFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/login/LoginChooserFragment.kt @@ -23,8 +23,8 @@ import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager import com.google.android.material.dialog.MaterialAlertDialogBuilder import kotlinx.coroutines.* -import pl.szczodrzynski.edziennik.* -import pl.szczodrzynski.edziennik.data.api.* +import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.databinding.LoginChooserFragmentBinding import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ui.dialogs.sync.RegisterUnavailableDialog @@ -51,7 +51,8 @@ class LoginChooserFragment : Fragment(), CoroutineScope { private val job: Job = Job() override val coroutineContext: CoroutineContext get() = job + Dispatchers.Main - + private val manager + get() = app.permissionManager // local/private variables go here override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { @@ -67,6 +68,9 @@ class LoginChooserFragment : Fragment(), CoroutineScope { if (!isAdded) return val adapter = LoginChooserAdapter(activity, this::onLoginModeClicked) + if (!manager.isNotificationPermissionGranted) { + manager.requestNotificationsPermission(activity, 0, false){} + } b.versionText.setText( R.string.login_chooser_version_format, diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/timetable/TimetableDayFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/timetable/TimetableDayFragment.kt index 754bd4f5..37e82a27 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/timetable/TimetableDayFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/timetable/TimetableDayFragment.kt @@ -4,6 +4,7 @@ package pl.szczodrzynski.edziennik.ui.timetable +import android.graphics.drawable.ColorDrawable import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -12,6 +13,7 @@ import android.widget.FrameLayout import android.widget.LinearLayout import android.widget.TextView import androidx.asynclayoutinflater.view.AsyncLayoutInflater +import androidx.core.graphics.ColorUtils import androidx.core.view.* import com.linkedin.android.tachyon.DayView import com.linkedin.android.tachyon.DayViewConfig @@ -33,9 +35,11 @@ import pl.szczodrzynski.edziennik.ext.* import pl.szczodrzynski.edziennik.ui.base.lazypager.LazyFragment import pl.szczodrzynski.edziennik.ui.timetable.TimetableFragment.Companion.DEFAULT_END_HOUR import pl.szczodrzynski.edziennik.ui.timetable.TimetableFragment.Companion.DEFAULT_START_HOUR +import pl.szczodrzynski.edziennik.utils.Colors import pl.szczodrzynski.edziennik.utils.managers.NoteManager import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.edziennik.utils.models.Time +import pl.szczodrzynski.edziennik.utils.mutableLazy import java.util.* import kotlin.coroutines.CoroutineContext import kotlin.math.min @@ -71,8 +75,9 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope { // find SwipeRefreshLayout in the hierarchy private val refreshLayout by lazy { view?.findParentById(R.id.refreshLayout) } + private val profileConfig by lazy { app.config.forProfile().ui } - private val dayView by lazy { + private val dayViewDelegate = mutableLazy { val dayView = DayView(activity, DayViewConfig( startHour = startHour, endHour = endHour, @@ -85,8 +90,9 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope { eventMargin = 2.dp ), true) dayView.setPadding(10.dp) - return@lazy dayView + return@mutableLazy dayView } + private val dayView by dayViewDelegate override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { activity = (getActivity() as MainActivity?) ?: return null @@ -173,8 +179,19 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope { return } + if (dayViewDelegate.isInitialized()) + b.dayFrame.removeView(dayView) + + val lessonsActual = lessons.filter { it.type != Lesson.TYPE_NO_LESSONS } + + if (profileConfig.timetableTrimHourRange) { + dayViewDelegate.deinitialize() + // end/start defaults are swapped on purpose + startHour = lessonsActual.minOf { it.displayStartTime?.hour ?: DEFAULT_END_HOUR } + endHour = lessonsActual.maxOf { it.displayEndTime?.hour?.plus(1) ?: DEFAULT_START_HOUR } + } + b.scrollView.isVisible = true - b.dayFrame.removeView(dayView) b.dayFrame.addView(dayView, 0) // Inflate a label view for each hour the day view will display @@ -195,7 +212,7 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope { lessons.forEach { it.showAsUnseen = !it.seen } - buildLessonViews(lessons.filter { it.type != Lesson.TYPE_NO_LESSONS }, events, attendanceList) + buildLessonViews(lessonsActual, events, attendanceList) } private fun buildLessonViews(lessons: List, events: List, attendanceList: List) { @@ -215,7 +232,10 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope { val colorSecondary = android.R.attr.textColorSecondary.resolveAttr(activity) for (lesson in lessons) { - val attendance = attendanceList.find { it.startTime == lesson.startTime } + val attendance = if (profileConfig.timetableShowAttendance) + attendanceList.find { it.startTime == lesson.startTime } + else + null val startTime = lesson.displayStartTime ?: continue val endTime = lesson.displayEndTime ?: continue @@ -245,23 +265,20 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope { } } - val eventList = events.filter { it.time != null && it.time == lesson.displayStartTime }.take(3) - eventList.getOrNull(0).let { - lb.event1.visibility = if (it == null) View.GONE else View.VISIBLE - lb.event1.background = it?.let { - R.drawable.bg_circle.resolveDrawable(activity).setTintColor(it.eventColor) + val eventIcons = listOf(lb.event1, lb.event2, lb.event3) + if (profileConfig.timetableShowEvents) { + val eventList = events.filter { it.time != null && it.time == lesson.displayStartTime }.take(3) + for ((i, eventIcon) in eventIcons.withIndex()) { + eventList.getOrNull(i).let { + eventIcon.isVisible = it != null + eventIcon.background = it?.let { + R.drawable.bg_circle.resolveDrawable(activity).setTintColor(it.eventColor) + } + } } - } - eventList.getOrNull(1).let { - lb.event2.visibility = if (it == null) View.GONE else View.VISIBLE - lb.event2.background = it?.let { - R.drawable.bg_circle.resolveDrawable(activity).setTintColor(it.eventColor) - } - } - eventList.getOrNull(2).let { - lb.event3.visibility = if (it == null) View.GONE else View.VISIBLE - lb.event3.background = it?.let { - R.drawable.bg_circle.resolveDrawable(activity).setTintColor(it.eventColor) + } else { + for (eventIcon in eventIcons) { + eventIcon.visibility = View.GONE } } @@ -295,13 +312,36 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope { lesson.classroom?.let { add(it) } }.concat(arrowRight) + lb.annotationVisible = manager.getAnnotation(activity, lesson, lb.annotation) - lb.lessonNumber = lesson.displayLessonNumber val lessonText = lesson.getNoteSubstituteText(showNotes = true) ?: lesson.displaySubjectName + + val (subjectTextPrimary, subjectTextSecondary) = if (profileConfig.timetableColorSubjectName) { + val subjectColor = Colors.stringToMaterialColorCRC(lessonText?.toString() ?: "") + if (lb.annotationVisible) { + lb.subjectContainer.background = ColorDrawable(subjectColor) + } else { + lb.subjectContainer.setBackgroundResource(R.drawable.timetable_subject_color_rounded) + lb.subjectContainer.background.setTintColor(subjectColor) + } + when (ColorUtils.calculateLuminance(subjectColor) > 0.5) { + true -> /* light */ 0xFF000000 to 0xFF666666 + false -> /* dark */ 0xFFFFFFFF to 0xFFAAAAAA + } + } else { + lb.subjectContainer.background = null + null to colorSecondary + } + + lb.lessonNumber = lesson.displayLessonNumber + if (subjectTextPrimary != null) + lb.lessonNumberText.setTextColor(subjectTextPrimary.toInt()) lb.subjectName.text = lessonText?.let { if (lesson.type == Lesson.TYPE_CANCELLED || lesson.type == Lesson.TYPE_SHIFTED_SOURCE) - it.asStrikethroughSpannable().asColoredSpannable(colorSecondary) + it.asStrikethroughSpannable().asColoredSpannable(subjectTextSecondary.toInt()) + else if (subjectTextPrimary != null) + it.asColoredSpannable(subjectTextPrimary.toInt()) else it } @@ -328,7 +368,6 @@ class TimetableDayFragment : LazyFragment(), CoroutineScope { } //lb.subjectName.typeface = Typeface.create("sans-serif-light", Typeface.BOLD) - lb.annotationVisible = manager.getAnnotation(activity, lesson, lb.annotation) val lessonNumberMargin = if (lb.annotationVisible) (-8).dp else 0 diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/timetable/TimetableFragment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/timetable/TimetableFragment.kt index b046ff68..fc2221bc 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/timetable/TimetableFragment.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/timetable/TimetableFragment.kt @@ -26,6 +26,7 @@ import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.data.db.entity.Metadata import pl.szczodrzynski.edziennik.databinding.FragmentTimetableV2Binding import pl.szczodrzynski.edziennik.ext.getSchoolYearConstrains +import pl.szczodrzynski.edziennik.ui.dialogs.settings.TimetableConfigDialog import pl.szczodrzynski.edziennik.ui.event.EventManualDialog import pl.szczodrzynski.edziennik.utils.models.Date import pl.szczodrzynski.navlib.bottomsheet.items.BottomSheetPrimaryItem @@ -52,6 +53,7 @@ class TimetableFragment : Fragment(), CoroutineScope { private var fabShown = false private val items = mutableListOf() + private val profileConfig by lazy { app.config.forProfile().ui } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { activity = (getActivity() as MainActivity?) ?: return null @@ -128,8 +130,8 @@ class TimetableFragment : Fragment(), CoroutineScope { } val lessonRanges = app.db.lessonRangeDao().getAllNow(App.profileId) - startHour = lessonRanges.map { it.startTime.hour }.minOrNull() ?: DEFAULT_START_HOUR - endHour = lessonRanges.map { it.endTime.hour }.maxOrNull()?.plus(1) ?: DEFAULT_END_HOUR + startHour = lessonRanges.minOfOrNull { it.startTime.hour } ?: DEFAULT_START_HOUR + endHour = lessonRanges.maxOfOrNull { it.endTime.hour }?.plus(1) ?: DEFAULT_END_HOUR } deferred.await() if (!isAdded) @@ -208,6 +210,13 @@ class TimetableFragment : Fragment(), CoroutineScope { activity.bottomSheet.close() GenerateBlockTimetableDialog(activity) }), + BottomSheetPrimaryItem(true) + .withTitle(R.string.menu_timetable_config) + .withIcon(CommunityMaterial.Icon.cmd_cog_outline) + .withOnClickListener { + activity.bottomSheet.close() + TimetableConfigDialog(activity, false, null, null).show() + }, BottomSheetSeparatorItem(true), BottomSheetPrimaryItem(true) .withTitle(R.string.menu_mark_as_read) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/Colors.java b/app/src/main/java/pl/szczodrzynski/edziennik/utils/Colors.java index 1f6c7ad3..39371516 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/utils/Colors.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/Colors.java @@ -15,6 +15,7 @@ import androidx.core.graphics.ColorUtils; import java.security.MessageDigest; import java.util.Arrays; import java.util.Random; +import java.util.zip.CRC32; import pl.szczodrzynski.edziennik.data.db.entity.Grade; @@ -84,6 +85,28 @@ public class Colors { 0xFF6D4C41 }; + public static final int[] materialColorsBasic = { + 0xFFE53935, 0xFFD81B60, 0xFF8E24AA, 0xFF5E35B1, + 0xFF3949AB, 0xFF1E88E5, 0xFF039BE5, 0xFF00ACC1, + 0xFF00897B, 0xFF43A047, 0xFF7CB342, 0xFFC0CA33, + 0xFFFDD835, 0xFFFFB300, 0xFFFB8C00, 0xFFF4511E, + 0xFF6D4C41, 0xFF757575, 0xFF546E7A, 0xFF00E676, + + 0xFFEF9A9A, 0xFFF48FB1, 0xFFCE93D8, 0xFFB39DDB, + 0xFF9FA8DA, 0xFF90CAF9, 0xFF81D4FA, 0xFF80DEEA, + 0xFF80CBC4, 0xFFA5D6A7, 0xFFC5E1A5, 0xFFE6EE9C, + 0xFFFFF59D, 0xFFFFE082, 0xFFFFCC80, 0xFFFFAB91, + 0xFFBCAAA4, 0xFFEEEEEE, 0xFFB0BEC5, 0xFFCCFF90, + }; + + public static final int[] metroColors = { + 0xFF76FF03, 0xFF60A917, 0xFF00C853, 0xFF00ABA9, + 0xFF1BA1E2, 0xFF0050EF, 0xFF6A00FF, 0xFFAA00FF, + 0xFFF472D0, 0xFFD80073, 0xFFA20025, 0xFFE51400, + 0xFFFA6800, 0xFFF0A30A, 0xFFE3C800, 0xFF795548, + 0xFF6D8764, 0xFF647687, 0xFF76608A, 0xFFA0522D, + }; + /** * Used for teacher's images (e.g. in messages or announcements). * @param s teacher's fullName @@ -115,6 +138,18 @@ public class Colors { return materialColors[getRandomNumberInRange(0, materialColors.length-1, seed)]; } + public static int stringToMaterialColorCRC(String s) { + long seed; + try { + CRC32 crc = new CRC32(); + crc.update(s.getBytes()); + seed = crc.getValue(); + } catch (Exception e) { + seed = 1234; + } + return metroColors[(int) (seed % metroColors.length)]; + } + public static int gradeToColor(Grade grade) { if (grade.getType() == Grade.TYPE_POINT_SUM) { diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/MutableLazy.kt b/app/src/main/java/pl/szczodrzynski/edziennik/utils/MutableLazy.kt index cf000e1f..f742c185 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/utils/MutableLazy.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/MutableLazy.kt @@ -19,7 +19,6 @@ class MutableLazyImpl(initializer: () -> T, lock: Any? = null) { return synchronized(lock) { val typedValue = initializer!!() _value = typedValue - initializer = null typedValue } } @@ -29,7 +28,11 @@ class MutableLazyImpl(initializer: () -> T, lock: Any? = null) { fun isInitialized() = _value !== UNINITIALIZED_VALUE + fun deinitialize() { + _value = UNINITIALIZED_VALUE + } + override fun toString() = if (isInitialized()) _value.toString() else "ChangeableLazy value not initialized yet." } -fun mutableLazy(initializer: () -> T): MutableLazyImpl = MutableLazyImpl(initializer) \ No newline at end of file +fun mutableLazy(initializer: () -> T): MutableLazyImpl = MutableLazyImpl(initializer) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/PermissionManager.kt b/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/PermissionManager.kt index 65430f60..e99f9e3e 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/PermissionManager.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/managers/PermissionManager.kt @@ -36,7 +36,13 @@ class PermissionManager(val app: App) : CoroutineScope { app.checkSelfPermission(name) == PackageManager.PERMISSION_GRANTED else true - + val isNotificationPermissionGranted by lazy { + if (Build.VERSION.SDK_INT >= 33) { + app.checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED + } else { + true + } + } private fun openPermissionSettings(activity: AppCompatActivity) { val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) val uri = Uri.fromParts("package", app.packageName, null) @@ -80,6 +86,10 @@ class PermissionManager(val app: App) : CoroutineScope { .show() } result.hasPermanentDenied() -> { + if (!isRequired) { + onSuccess() + return@launch + } MaterialAlertDialogBuilder(activity) .setTitle(R.string.permissions_required) .setMessage(R.string.permissions_denied) @@ -92,6 +102,18 @@ class PermissionManager(val app: App) : CoroutineScope { } } } + fun requestNotificationsPermission( + activity: AppCompatActivity, + @StringRes permissionMessage: Int, + isRequired: Boolean = false, + onSuccess: suspend CoroutineScope.() -> Unit + ) = requestPermission( + activity, + permissionMessage, + isRequired, + Manifest.permission.POST_NOTIFICATIONS, + onSuccess + ) fun requestStoragePermission( activity: AppCompatActivity, diff --git a/app/src/main/res/layout/dialog_config_agenda.xml b/app/src/main/res/layout/dialog_config_agenda.xml index f17b5989..b51464e2 100644 --- a/app/src/main/res/layout/dialog_config_agenda.xml +++ b/app/src/main/res/layout/dialog_config_agenda.xml @@ -31,7 +31,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/timetable_lesson.xml b/app/src/main/res/layout/timetable_lesson.xml index 491788b5..d8d9609c 100644 --- a/app/src/main/res/layout/timetable_lesson.xml +++ b/app/src/main/res/layout/timetable_lesson.xml @@ -45,14 +45,15 @@ tools:visibility="gone" /> - + android:paddingVertical="4dp" + tools:background="@drawable/timetable_subject_color_rounded"> Grade read the Privacy Policy and accept its provisions.

The authors of the application are not responsible for the use of the Szkolny.eu application.]]>
Szkolny.eu v%s\n%s - Appearance + Appearance Online learning online lesson Messages settings diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7aae860c..3cc2451d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1424,7 +1424,7 @@ przeczytanie Polityki prywatności i akceptujesz jej postanowienia.

Autorzy aplikacji nie biorą odpowiedzialności za korzystanie z aplikacji Szkolny.eu.]]>
Szkolny.eu v%s\n%s Ustawienia terminarza - Wygląd + Wygląd Pokazuj zmiany planu lekcji Pokazuj nieobecności nauczycieli Tryb kompaktowy @@ -1537,6 +1537,11 @@ (rodzic) - nieznany przedmiot - {cmd-information-outline} Oceny, których przedmiot nie został podany w dzienniku. Może to być na przykład taki, który nie jest prowadzony w tym roku szkolnym. + Ustawienia planu lekcji + Pokazuj wydarzenia przy lekcjach + Pokazuj rodzaj obecności na lekcji + Koloruj nazwę przedmiotu + Nie pokazuj godzin bez lekcji Logowanie do USOS API... USOS Logowanie z użyciem przeglądarki