1
0

Compare commits

...

20 Commits

Author SHA1 Message Date
dd3d62c10d Merge branch 'release/2.6.14' 2024-05-29 17:38:54 +02:00
2ae451ac4f Version 2.6.14 2024-05-29 17:38:34 +02:00
85d3a6e8a7 Bump sdk to 2.6.12-SNAPSHOT 2024-05-29 16:33:49 +02:00
47041c5fcb Bump com.android.tools.build:gradle from 8.4.0 to 8.4.1 (#2573) 2024-05-25 15:28:26 +00:00
eed0a3b6f1 Bump androidx.annotation:annotation from 1.7.1 to 1.8.0 (#2563) 2024-05-25 13:49:33 +00:00
c6eea8b84d Bump com.google.android.gms:play-services-ads from 22.6.0 to 23.1.0 (#2556) 2024-05-25 13:44:02 +00:00
b02865e963 Bump androidx.lifecycle:lifecycle-livedata-ktx from 2.7.0 to 2.8.0 (#2561) 2024-05-25 13:43:47 +00:00
20be52a60a Bump com.google.firebase:firebase-crashlytics-gradle from 2.9.9 to 3.0.1 (#2562) 2024-05-25 13:43:33 +00:00
0ffc661b4f Bump androidx.viewpager2:viewpager2 from 1.1.0-rc01 to 1.1.0 (#2564) 2024-05-25 13:43:04 +00:00
2a0e8497db Bump org.robolectric:robolectric from 4.12.1 to 4.12.2 (#2565) 2024-05-25 13:42:41 +00:00
e8643bc8ba Bump mockk from 1.13.10 to 1.13.11 (#2566) 2024-05-25 13:42:19 +00:00
b3b4603e89 Bump androidx.fragment:fragment-ktx from 1.7.0 to 1.7.1 (#2567) 2024-05-25 13:41:54 +00:00
528a947ffd Merge branch 'release/2.6.13' into develop 2024-05-23 23:26:24 +02:00
05c6c8bc96 Merge branch 'release/2.6.13' 2024-05-23 23:26:19 +02:00
ca9caeca66 Version 2.6.13 2024-05-23 23:26:06 +02:00
e971eb7821 Add full panic mode (#2569) 2024-05-23 23:15:47 +02:00
c7afa262d9 Merge branch 'release/2.6.12' into develop 2024-05-23 07:55:17 +02:00
1f0b400e5a Merge branch 'release/2.6.12' 2024-05-23 07:55:06 +02:00
b622c09e56 Version 2.6.12 2024-05-23 07:55:02 +02:00
87fb1916d8 Add panic button 2024-05-23 07:37:49 +02:00
22 changed files with 417 additions and 98 deletions

View File

@ -27,8 +27,8 @@ android {
testApplicationId "io.github.tests.wulkanowy" testApplicationId "io.github.tests.wulkanowy"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 34 targetSdkVersion 34
versionCode 171 versionCode 174
versionName "2.6.11" versionName "2.6.14"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
resValue "string", "app_name", "Wulkanowy" resValue "string", "app_name", "Wulkanowy"
@ -161,7 +161,7 @@ play {
track = 'production' track = 'production'
releaseStatus = ReleaseStatus.IN_PROGRESS releaseStatus = ReleaseStatus.IN_PROGRESS
userFraction = 0.99d userFraction = 0.99d
updatePriority = 2 updatePriority = 3
enabled.set(false) enabled.set(false)
} }
@ -186,12 +186,12 @@ ext {
android_hilt = "1.2.0" android_hilt = "1.2.0"
room = "2.6.1" room = "2.6.1"
chucker = "4.0.0" chucker = "4.0.0"
mockk = "1.13.10" mockk = "1.13.11"
coroutines = "1.8.1" coroutines = "1.8.1"
} }
dependencies { dependencies {
implementation 'io.github.wulkanowy:sdk:2.6.10' implementation 'io.github.wulkanowy:sdk:2.6.12'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
@ -203,13 +203,13 @@ dependencies {
implementation 'androidx.core:core-splashscreen:1.0.1' implementation 'androidx.core:core-splashscreen:1.0.1'
implementation "androidx.activity:activity-ktx:1.9.0" implementation "androidx.activity:activity-ktx:1.9.0"
implementation "androidx.appcompat:appcompat:1.6.1" implementation "androidx.appcompat:appcompat:1.6.1"
implementation "androidx.fragment:fragment-ktx:1.7.0" implementation "androidx.fragment:fragment-ktx:1.7.1"
implementation "androidx.annotation:annotation:1.7.1" implementation "androidx.annotation:annotation:1.8.0"
implementation "androidx.javascriptengine:javascriptengine:1.0.0-beta01" implementation "androidx.javascriptengine:javascriptengine:1.0.0-beta01"
implementation "androidx.preference:preference-ktx:1.2.1" implementation "androidx.preference:preference-ktx:1.2.1"
implementation "androidx.recyclerview:recyclerview:1.3.2" implementation "androidx.recyclerview:recyclerview:1.3.2"
implementation "androidx.viewpager2:viewpager2:1.1.0-rc01" implementation "androidx.viewpager2:viewpager2:1.1.0"
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
implementation "androidx.constraintlayout:constraintlayout:2.1.4" implementation "androidx.constraintlayout:constraintlayout:2.1.4"
implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0" implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0"
@ -221,7 +221,7 @@ dependencies {
implementation "androidx.work:work-runtime:$work_manager" implementation "androidx.work:work-runtime:$work_manager"
playImplementation "androidx.work:work-gcm:$work_manager" playImplementation "androidx.work:work-gcm:$work_manager"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.7.0" implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.8.0"
implementation "androidx.room:room-runtime:$room" implementation "androidx.room:room-runtime:$room"
implementation "androidx.room:room-ktx:$room" implementation "androidx.room:room-ktx:$room"
@ -256,7 +256,7 @@ dependencies {
playImplementation 'com.google.firebase:firebase-crashlytics:' playImplementation 'com.google.firebase:firebase-crashlytics:'
playImplementation 'com.google.firebase:firebase-config' playImplementation 'com.google.firebase:firebase-config'
playImplementation 'com.google.android.gms:play-services-ads:22.6.0' playImplementation 'com.google.android.gms:play-services-ads:23.1.0'
playImplementation "com.google.android.play:integrity:1.3.0" playImplementation "com.google.android.play:integrity:1.3.0"
playImplementation 'com.google.android.play:app-update-ktx:2.1.0' playImplementation 'com.google.android.play:app-update-ktx:2.1.0'
playImplementation 'com.google.android.play:review-ktx:2.0.1' playImplementation 'com.google.android.play:review-ktx:2.0.1'
@ -276,7 +276,7 @@ dependencies {
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines" testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines"
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version" testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
testImplementation 'org.robolectric:robolectric:4.12.1' testImplementation 'org.robolectric:robolectric:4.12.2'
testImplementation "androidx.test:runner:1.5.2" testImplementation "androidx.test:runner:1.5.2"
testImplementation "androidx.test.ext:junit:1.1.5" testImplementation "androidx.test.ext:junit:1.1.5"
testImplementation "androidx.test:core:1.5.0" testImplementation "androidx.test:core:1.5.0"

View File

@ -11,6 +11,6 @@ interface WulkanowyService {
@GET("/v1.json") @GET("/v1.json")
suspend fun getAdminMessages(): List<AdminMessage> suspend fun getAdminMessages(): List<AdminMessage>
@GET("/mapping2.json") @GET("/mapping3.json")
suspend fun getMapping(): Mapping suspend fun getMapping(): Mapping
} }

View File

@ -30,6 +30,7 @@ import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.main.MainView import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.ui.modules.message.MessageFragment import io.github.wulkanowy.ui.modules.message.MessageFragment
import io.github.wulkanowy.ui.modules.notificationscenter.NotificationsCenterFragment import io.github.wulkanowy.ui.modules.notificationscenter.NotificationsCenterFragment
import io.github.wulkanowy.ui.modules.panicmode.PanicModeFragment
import io.github.wulkanowy.ui.modules.schoolannouncement.SchoolAnnouncementFragment import io.github.wulkanowy.ui.modules.schoolannouncement.SchoolAnnouncementFragment
import io.github.wulkanowy.ui.modules.timetable.TimetableFragment import io.github.wulkanowy.ui.modules.timetable.TimetableFragment
import io.github.wulkanowy.utils.capitalise import io.github.wulkanowy.utils.capitalise
@ -125,6 +126,7 @@ class DashboardFragment : BaseFragment<FragmentDashboardBinding>(R.layout.fragme
mainActivity.pushView(ConferenceFragment.newInstance()) mainActivity.pushView(ConferenceFragment.newInstance())
} }
onAdminMessageClickListener = presenter::onAdminMessageSelected onAdminMessageClickListener = presenter::onAdminMessageSelected
onPanicButtonClickListener = presenter::onPanicButtonClicked
onAdminMessageDismissClickListener = presenter::onAdminMessageDismissed onAdminMessageDismissClickListener = presenter::onAdminMessageDismissed
registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
@ -208,7 +210,11 @@ class DashboardFragment : BaseFragment<FragmentDashboardBinding>(R.layout.fragme
binding = binding.dashboardErrorAdminMessage, binding = binding.dashboardErrorAdminMessage,
onAdminMessageDismissClickListener = presenter::onAdminMessageDismissed, onAdminMessageDismissClickListener = presenter::onAdminMessageDismissed,
onAdminMessageClickListener = presenter::onAdminMessageSelected, onAdminMessageClickListener = presenter::onAdminMessageSelected,
).bind(adminMessageItem.adminMessage) onPanicButtonClickListener = presenter::onPanicButtonClicked,
).bind(
item = adminMessageItem.adminMessage,
showPanicButton = true,
)
} }
} }
@ -236,6 +242,10 @@ class DashboardFragment : BaseFragment<FragmentDashboardBinding>(R.layout.fragme
requireContext().openInternetBrowser(url) requireContext().openInternetBrowser(url)
} }
override fun openPanicWebView(url: String) {
(requireActivity() as MainActivity).pushView(PanicModeFragment.newInstance(url))
}
override fun onDestroyView() { override fun onDestroyView() {
dashboardAdapter.clearTimers() dashboardAdapter.clearTimers()
presenter.onDetachView() presenter.onDetachView()

View File

@ -11,6 +11,7 @@ import io.github.wulkanowy.data.errorOrNull
import io.github.wulkanowy.data.flatResourceFlow import io.github.wulkanowy.data.flatResourceFlow
import io.github.wulkanowy.data.mapResourceData import io.github.wulkanowy.data.mapResourceData
import io.github.wulkanowy.data.onResourceError import io.github.wulkanowy.data.onResourceError
import io.github.wulkanowy.data.onResourceSuccess
import io.github.wulkanowy.data.repositories.AttendanceSummaryRepository import io.github.wulkanowy.data.repositories.AttendanceSummaryRepository
import io.github.wulkanowy.data.repositories.ConferenceRepository import io.github.wulkanowy.data.repositories.ConferenceRepository
import io.github.wulkanowy.data.repositories.ExamRepository import io.github.wulkanowy.data.repositories.ExamRepository
@ -23,6 +24,7 @@ import io.github.wulkanowy.data.repositories.SchoolAnnouncementRepository
import io.github.wulkanowy.data.repositories.SemesterRepository import io.github.wulkanowy.data.repositories.SemesterRepository
import io.github.wulkanowy.data.repositories.StudentRepository import io.github.wulkanowy.data.repositories.StudentRepository
import io.github.wulkanowy.data.repositories.TimetableRepository import io.github.wulkanowy.data.repositories.TimetableRepository
import io.github.wulkanowy.data.resourceFlow
import io.github.wulkanowy.domain.adminmessage.GetAppropriateAdminMessageUseCase import io.github.wulkanowy.domain.adminmessage.GetAppropriateAdminMessageUseCase
import io.github.wulkanowy.domain.timetable.IsStudentHasLessonsOnWeekendUseCase import io.github.wulkanowy.domain.timetable.IsStudentHasLessonsOnWeekendUseCase
import io.github.wulkanowy.ui.base.BasePresenter import io.github.wulkanowy.ui.base.BasePresenter
@ -44,6 +46,7 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import okhttp3.HttpUrl.Companion.toHttpUrl
import timber.log.Timber import timber.log.Timber
import java.time.Instant import java.time.Instant
import java.time.LocalDate import java.time.LocalDate
@ -282,6 +285,22 @@ class DashboardPresenter @Inject constructor(
url?.let { view?.openInternetBrowser(it) } url?.let { view?.openInternetBrowser(it) }
} }
fun onPanicButtonClicked() {
resourceFlow { studentRepository.getCurrentStudent() }
.onResourceError { errorHandler.dispatch(it) }
.onResourceSuccess {
val baseUrl = it.scrapperBaseUrl.toHttpUrl()
val urlToOpen = baseUrl.newBuilder()
.host("uonetplus${it.scrapperDomainSuffix}.${baseUrl.host}")
.addPathSegment(it.symbol)
.build()
.toString()
view?.openPanicWebView(urlToOpen)
}
.launch("panic_button")
}
private fun loadHorizontalGroup(student: Student, forceRefresh: Boolean) { private fun loadHorizontalGroup(student: Student, forceRefresh: Boolean) {
flow { flow {
val selectedTiles = selectedDashboardTiles val selectedTiles = selectedDashboardTiles

View File

@ -31,4 +31,6 @@ interface DashboardView : BaseView {
fun openNotificationsCenterView() fun openNotificationsCenterView()
fun openInternetBrowser(url: String) fun openInternetBrowser(url: String)
fun openPanicWebView(url: String)
} }

View File

@ -59,6 +59,8 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
var onAdminMessageClickListener: (String?) -> Unit = {} var onAdminMessageClickListener: (String?) -> Unit = {}
var onPanicButtonClickListener: () -> Unit = {}
var onAdminMessageDismissClickListener: (AdminMessage) -> Unit = {} var onAdminMessageDismissClickListener: (AdminMessage) -> Unit = {}
val items = mutableListOf<DashboardItem>() val items = mutableListOf<DashboardItem>()
@ -86,35 +88,46 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
DashboardItem.Type.ACCOUNT.ordinal -> AccountViewHolder( DashboardItem.Type.ACCOUNT.ordinal -> AccountViewHolder(
ItemDashboardAccountBinding.inflate(inflater, parent, false) ItemDashboardAccountBinding.inflate(inflater, parent, false)
) )
DashboardItem.Type.HORIZONTAL_GROUP.ordinal -> HorizontalGroupViewHolder( DashboardItem.Type.HORIZONTAL_GROUP.ordinal -> HorizontalGroupViewHolder(
ItemDashboardHorizontalGroupBinding.inflate(inflater, parent, false) ItemDashboardHorizontalGroupBinding.inflate(inflater, parent, false)
) )
DashboardItem.Type.GRADES.ordinal -> GradesViewHolder( DashboardItem.Type.GRADES.ordinal -> GradesViewHolder(
ItemDashboardGradesBinding.inflate(inflater, parent, false) ItemDashboardGradesBinding.inflate(inflater, parent, false)
) )
DashboardItem.Type.LESSONS.ordinal -> LessonsViewHolder( DashboardItem.Type.LESSONS.ordinal -> LessonsViewHolder(
ItemDashboardLessonsBinding.inflate(inflater, parent, false) ItemDashboardLessonsBinding.inflate(inflater, parent, false)
) )
DashboardItem.Type.HOMEWORK.ordinal -> HomeworkViewHolder( DashboardItem.Type.HOMEWORK.ordinal -> HomeworkViewHolder(
ItemDashboardHomeworkBinding.inflate(inflater, parent, false) ItemDashboardHomeworkBinding.inflate(inflater, parent, false)
) )
DashboardItem.Type.ANNOUNCEMENTS.ordinal -> AnnouncementsViewHolder( DashboardItem.Type.ANNOUNCEMENTS.ordinal -> AnnouncementsViewHolder(
ItemDashboardAnnouncementsBinding.inflate(inflater, parent, false) ItemDashboardAnnouncementsBinding.inflate(inflater, parent, false)
) )
DashboardItem.Type.EXAMS.ordinal -> ExamsViewHolder( DashboardItem.Type.EXAMS.ordinal -> ExamsViewHolder(
ItemDashboardExamsBinding.inflate(inflater, parent, false) ItemDashboardExamsBinding.inflate(inflater, parent, false)
) )
DashboardItem.Type.CONFERENCES.ordinal -> ConferencesViewHolder( DashboardItem.Type.CONFERENCES.ordinal -> ConferencesViewHolder(
ItemDashboardConferencesBinding.inflate(inflater, parent, false) ItemDashboardConferencesBinding.inflate(inflater, parent, false)
) )
DashboardItem.Type.ADMIN_MESSAGE.ordinal -> AdminMessageViewHolder( DashboardItem.Type.ADMIN_MESSAGE.ordinal -> AdminMessageViewHolder(
ItemDashboardAdminMessageBinding.inflate(inflater, parent, false), ItemDashboardAdminMessageBinding.inflate(inflater, parent, false),
onAdminMessageDismissClickListener = onAdminMessageDismissClickListener, onAdminMessageDismissClickListener = onAdminMessageDismissClickListener,
onAdminMessageClickListener = onAdminMessageClickListener, onAdminMessageClickListener = onAdminMessageClickListener,
onPanicButtonClickListener = onPanicButtonClickListener,
) )
DashboardItem.Type.ADS.ordinal -> AdsViewHolder( DashboardItem.Type.ADS.ordinal -> AdsViewHolder(
ItemDashboardAdsBinding.inflate(inflater, parent, false) ItemDashboardAdsBinding.inflate(inflater, parent, false)
) )
else -> throw IllegalArgumentException() else -> throw IllegalArgumentException()
} }
} }
@ -129,7 +142,11 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
is AnnouncementsViewHolder -> bindAnnouncementsViewHolder(holder, position) is AnnouncementsViewHolder -> bindAnnouncementsViewHolder(holder, position)
is ExamsViewHolder -> bindExamsViewHolder(holder, position) is ExamsViewHolder -> bindExamsViewHolder(holder, position)
is ConferencesViewHolder -> bindConferencesViewHolder(holder, position) is ConferencesViewHolder -> bindConferencesViewHolder(holder, position)
is AdminMessageViewHolder -> holder.bind((items[position] as DashboardItem.AdminMessages).adminMessage) is AdminMessageViewHolder -> holder.bind(
(items[position] as DashboardItem.AdminMessages).adminMessage,
showPanicButton = true
)
is AdsViewHolder -> bindAdsViewHolder(holder, position) is AdsViewHolder -> bindAdsViewHolder(holder, position)
} }
} }
@ -240,12 +257,15 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
attendancePercentage == null || attendancePercentage == .0 -> { attendancePercentage == null || attendancePercentage == .0 -> {
root.context.getThemeAttrColor(R.attr.colorOnSurface) root.context.getThemeAttrColor(R.attr.colorOnSurface)
} }
attendancePercentage <= ATTENDANCE_SECOND_WARNING_THRESHOLD -> { attendancePercentage <= ATTENDANCE_SECOND_WARNING_THRESHOLD -> {
root.context.getThemeAttrColor(R.attr.colorPrimary) root.context.getThemeAttrColor(R.attr.colorPrimary)
} }
attendancePercentage <= ATTENDANCE_FIRST_WARNING_THRESHOLD -> { attendancePercentage <= ATTENDANCE_FIRST_WARNING_THRESHOLD -> {
root.context.getThemeAttrColor(R.attr.colorTimetableChange) root.context.getThemeAttrColor(R.attr.colorTimetableChange)
} }
else -> root.context.getThemeAttrColor(R.attr.colorOnSurface) else -> root.context.getThemeAttrColor(R.attr.colorOnSurface)
} }
val attendanceString = if (attendancePercentage == null || attendancePercentage == .0) { val attendanceString = if (attendancePercentage == null || attendancePercentage == .0) {
@ -336,24 +356,28 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
binding.dashboardLessonsItemTitleTomorrow.isVisible = false binding.dashboardLessonsItemTitleTomorrow.isVisible = false
binding.dashboardLessonsItemTitleTodayAndTomorrow.isVisible = false binding.dashboardLessonsItemTitleTodayAndTomorrow.isVisible = false
} }
tomorrowTimetable.isNotEmpty() -> { tomorrowTimetable.isNotEmpty() -> {
dateToNavigate = tomorrowDate dateToNavigate = tomorrowDate
updateLessonView(item, tomorrowTimetable, binding) updateLessonView(item, tomorrowTimetable, binding)
binding.dashboardLessonsItemTitleTomorrow.isVisible = true binding.dashboardLessonsItemTitleTomorrow.isVisible = true
binding.dashboardLessonsItemTitleTodayAndTomorrow.isVisible = false binding.dashboardLessonsItemTitleTodayAndTomorrow.isVisible = false
} }
currentDayHeader != null && currentDayHeader.content.isNotBlank() -> { currentDayHeader != null && currentDayHeader.content.isNotBlank() -> {
dateToNavigate = currentDate dateToNavigate = currentDate
updateLessonView(item, emptyList(), binding, currentDayHeader) updateLessonView(item, emptyList(), binding, currentDayHeader)
binding.dashboardLessonsItemTitleTomorrow.isVisible = false binding.dashboardLessonsItemTitleTomorrow.isVisible = false
binding.dashboardLessonsItemTitleTodayAndTomorrow.isVisible = false binding.dashboardLessonsItemTitleTodayAndTomorrow.isVisible = false
} }
tomorrowDayHeader != null && tomorrowDayHeader.content.isNotBlank() -> { tomorrowDayHeader != null && tomorrowDayHeader.content.isNotBlank() -> {
dateToNavigate = tomorrowDate dateToNavigate = tomorrowDate
updateLessonView(item, emptyList(), binding, tomorrowDayHeader) updateLessonView(item, emptyList(), binding, tomorrowDayHeader)
binding.dashboardLessonsItemTitleTomorrow.isVisible = true binding.dashboardLessonsItemTitleTomorrow.isVisible = true
binding.dashboardLessonsItemTitleTodayAndTomorrow.isVisible = false binding.dashboardLessonsItemTitleTodayAndTomorrow.isVisible = false
} }
else -> { else -> {
dateToNavigate = currentDate dateToNavigate = currentDate
updateLessonView(item, emptyList(), binding) updateLessonView(item, emptyList(), binding)
@ -461,6 +485,7 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
firstTitleText = firstTitleText =
context.getString(R.string.dashboard_timetable_first_lesson_title_moment) context.getString(R.string.dashboard_timetable_first_lesson_title_moment)
} }
minutesToStartLesson < 240 -> { minutesToStartLesson < 240 -> {
firstTitleAndValueTextColor = firstTitleAndValueTextColor =
context.getThemeAttrColor(R.attr.colorOnSurface) context.getThemeAttrColor(R.attr.colorOnSurface)
@ -468,6 +493,7 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
firstTitleText = firstTitleText =
context.getString(R.string.dashboard_timetable_first_lesson_title_soon) context.getString(R.string.dashboard_timetable_first_lesson_title_soon)
} }
else -> { else -> {
firstTitleAndValueTextColor = firstTitleAndValueTextColor =
context.getThemeAttrColor(R.attr.colorOnSurface) context.getThemeAttrColor(R.attr.colorOnSurface)

View File

@ -13,9 +13,10 @@ class AdminMessageViewHolder(
private val binding: ItemDashboardAdminMessageBinding, private val binding: ItemDashboardAdminMessageBinding,
private val onAdminMessageDismissClickListener: (AdminMessage) -> Unit, private val onAdminMessageDismissClickListener: (AdminMessage) -> Unit,
private val onAdminMessageClickListener: (String?) -> Unit, private val onAdminMessageClickListener: (String?) -> Unit,
private val onPanicButtonClickListener: () -> Unit,
) : RecyclerView.ViewHolder(binding.root) { ) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: AdminMessage?) { fun bind(item: AdminMessage?, showPanicButton: Boolean = false) {
item ?: return item ?: return
val context = binding.root.context val context = binding.root.context
@ -48,10 +49,14 @@ class AdminMessageViewHolder(
dashboardAdminMessageItemClose.setOnClickListener { dashboardAdminMessageItemClose.setOnClickListener {
onAdminMessageDismissClickListener(item) onAdminMessageDismissClickListener(item)
} }
dashboardPanicSection.root.isVisible = showPanicButton
dashboardPanicSection.dashboardPanicButton.setOnClickListener {
onPanicButtonClickListener()
}
root.setCardBackgroundColor(backgroundColor?.let { ColorStateList.valueOf(it) }) dashboardAdminMessage.setCardBackgroundColor(backgroundColor?.let { ColorStateList.valueOf(it) })
item.destinationUrl?.let { url -> item.destinationUrl?.let { url ->
root.setOnClickListener { onAdminMessageClickListener(url) } dashboardAdminMessage.setOnClickListener { onAdminMessageClickListener(url) }
} }
} }
} }

View File

@ -238,6 +238,7 @@ class LoginFormFragment : BaseFragment<FragmentLoginFormBinding>(R.layout.fragme
binding = binding.loginFormMessage, binding = binding.loginFormMessage,
onAdminMessageDismissClickListener = presenter::onAdminMessageDismissed, onAdminMessageDismissClickListener = presenter::onAdminMessageDismissed,
onAdminMessageClickListener = presenter::onAdminMessageSelected, onAdminMessageClickListener = presenter::onAdminMessageSelected,
onPanicButtonClickListener = {},
).bind(message) ).bind(message)
binding.loginFormMessage.root.isVisible = message != null binding.loginFormMessage.root.isVisible = message != null
} }

View File

@ -118,6 +118,7 @@ class LoginStudentSelectFragment :
binding = binding.loginStudentSelectAdminMessage, binding = binding.loginStudentSelectAdminMessage,
onAdminMessageDismissClickListener = presenter::onAdminMessageDismissed, onAdminMessageDismissClickListener = presenter::onAdminMessageDismissed,
onAdminMessageClickListener = presenter::onAdminMessageSelected, onAdminMessageClickListener = presenter::onAdminMessageSelected,
onPanicButtonClickListener = {},
).bind(adminMessage) ).bind(adminMessage)
binding.loginStudentSelectAdminMessage.root.isVisible = adminMessage != null binding.loginStudentSelectAdminMessage.root.isVisible = adminMessage != null
} }

View File

@ -188,6 +188,7 @@ class LoginSymbolFragment :
binding = binding.loginSymbolAdminMessage, binding = binding.loginSymbolAdminMessage,
onAdminMessageDismissClickListener = presenter::onAdminMessageDismissed, onAdminMessageDismissClickListener = presenter::onAdminMessageDismissed,
onAdminMessageClickListener = presenter::onAdminMessageSelected, onAdminMessageClickListener = presenter::onAdminMessageSelected,
onPanicButtonClickListener = {},
).bind(adminMessage) ).bind(adminMessage)
binding.loginSymbolAdminMessage.root.isVisible = adminMessage != null binding.loginSymbolAdminMessage.root.isVisible = adminMessage != null
} }

View File

@ -27,6 +27,7 @@ import io.github.wulkanowy.ui.modules.main.MainActivity
import io.github.wulkanowy.ui.modules.message.MessageFragment import io.github.wulkanowy.ui.modules.message.MessageFragment
import io.github.wulkanowy.ui.modules.message.mailboxchooser.MailboxChooserDialog import io.github.wulkanowy.ui.modules.message.mailboxchooser.MailboxChooserDialog
import io.github.wulkanowy.ui.modules.message.preview.MessagePreviewFragment import io.github.wulkanowy.ui.modules.message.preview.MessagePreviewFragment
import io.github.wulkanowy.ui.modules.panicmode.PanicModeFragment
import io.github.wulkanowy.ui.widgets.DividerItemDecoration import io.github.wulkanowy.ui.widgets.DividerItemDecoration
import io.github.wulkanowy.utils.dpToPx import io.github.wulkanowy.utils.dpToPx
import io.github.wulkanowy.utils.getThemeAttrColor import io.github.wulkanowy.utils.getThemeAttrColor
@ -132,6 +133,7 @@ class MessageTabFragment : BaseFragment<FragmentMessageTabBinding>(R.layout.frag
) )
messageTabErrorRetry.setOnClickListener { presenter.onRetry() } messageTabErrorRetry.setOnClickListener { presenter.onRetry() }
messageTabErrorDetails.setOnClickListener { presenter.onDetailsClick() } messageTabErrorDetails.setOnClickListener { presenter.onDetailsClick() }
messageTabPanicSection.dashboardPanicButton.setOnClickListener { presenter.onPanicButtonClicked() }
} }
setFragmentResultListener(requireArguments().getString(MESSAGE_TAB_FOLDER_ID)!!) { _, bundle -> setFragmentResultListener(requireArguments().getString(MESSAGE_TAB_FOLDER_ID)!!) { _, bundle ->
@ -283,6 +285,10 @@ class MessageTabFragment : BaseFragment<FragmentMessageTabBinding>(R.layout.frag
) )
} }
override fun openPanicWebView(url: String) {
(requireActivity() as MainActivity).pushView(PanicModeFragment.newInstance(url))
}
override fun hideKeyboard() { override fun hideKeyboard() {
activity?.hideSoftInput() activity?.hideSoftInput()
} }

View File

@ -20,6 +20,7 @@ import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import me.xdrop.fuzzywuzzy.FuzzySearch import me.xdrop.fuzzywuzzy.FuzzySearch
import okhttp3.HttpUrl.Companion.toHttpUrl
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.pow import kotlin.math.pow
@ -429,4 +430,20 @@ class MessageTabPresenter @Inject constructor(
+ dateRatio.toDouble().pow(2) * 2 + dateRatio.toDouble().pow(2) * 2
).toInt() ).toInt()
} }
fun onPanicButtonClicked() {
resourceFlow { studentRepository.getCurrentStudent() }
.onResourceError { errorHandler.dispatch(it) }
.onResourceSuccess {
val baseUrl = it.scrapperBaseUrl.toHttpUrl()
val urlToOpen = baseUrl.newBuilder()
.host("uonetplus${it.scrapperDomainSuffix}-wiadomosciplus.${baseUrl.host}")
.addPathSegment(it.symbol)
.build()
.toString()
view?.openPanicWebView(urlToOpen)
}
.launch("panic_button")
}
} }

View File

@ -50,4 +50,6 @@ interface MessageTabView : BaseView {
fun showRecyclerBottomPadding(show: Boolean) fun showRecyclerBottomPadding(show: Boolean)
fun showMailboxChooser(mailboxes: List<Mailbox>) fun showMailboxChooser(mailboxes: List<Mailbox>)
fun openPanicWebView(url: String)
} }

View File

@ -0,0 +1,99 @@
package io.github.wulkanowy.ui.modules.panicmode
import android.annotation.SuppressLint
import android.os.Bundle
import android.view.View
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.activity.addCallback
import androidx.core.os.bundleOf
import dagger.hilt.android.AndroidEntryPoint
import io.github.wulkanowy.R
import io.github.wulkanowy.data.WulkanowySdkFactory
import io.github.wulkanowy.databinding.FragmentPanicModeBinding
import io.github.wulkanowy.ui.base.BaseFragment
import io.github.wulkanowy.ui.modules.main.MainView
import io.github.wulkanowy.utils.WebkitCookieManagerProxy
import io.github.wulkanowy.utils.openInternetBrowser
import javax.inject.Inject
@AndroidEntryPoint
class PanicModeFragment : BaseFragment<FragmentPanicModeBinding>(R.layout.fragment_panic_mode),
MainView.TitledView {
@Inject
lateinit var wulkanowySdkFactory: WulkanowySdkFactory
@Inject
lateinit var webkitCookieManagerProxy: WebkitCookieManagerProxy
private var webView: WebView? = null
override val titleStringId: Int get() = R.string.panic_mode_title
companion object {
private const val PANIC_URL = "panic_mode_url"
fun newInstance(url: String?): PanicModeFragment {
return PanicModeFragment().apply {
arguments = bundleOf(PANIC_URL to url)
}
}
}
@SuppressLint("SetJavaScriptEnabled")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding = FragmentPanicModeBinding.bind(view)
binding.panicModeRefresh.setOnClickListener {
binding.panicModeWebview.loadUrl(
binding.panicModeWebview.url ?: arguments?.getString(PANIC_URL).orEmpty()
)
}
binding.panicModeBack.setOnClickListener { binding.panicModeWebview.goBack() }
binding.panicModeHome.setOnClickListener {
binding.panicModeWebview.loadUrl(
arguments?.getString(PANIC_URL).orEmpty()
)
}
binding.panicModeForward.setOnClickListener { binding.panicModeWebview.goForward() }
binding.panicModeShare.setOnClickListener {
requireContext().openInternetBrowser(
binding.panicModeWebview.url.toString(),
)
}
val onBackPressedCallback = requireActivity().onBackPressedDispatcher
.addCallback(viewLifecycleOwner) {
binding.panicModeWebview.goBack()
}
with(binding.panicModeWebview) {
webView = this
with(settings) {
javaScriptEnabled = true
userAgentString = wulkanowySdkFactory.createBase().userAgent
}
webViewClient = object : WebViewClient() {
override fun doUpdateVisitedHistory(
view: WebView?,
url: String?,
isReload: Boolean
) {
binding.panicModeBack.isEnabled = binding.panicModeWebview.canGoBack()
binding.panicModeForward.isEnabled = binding.panicModeWebview.canGoForward()
onBackPressedCallback.isEnabled = binding.panicModeWebview.canGoBack()
}
}
loadUrl(arguments?.getString(PANIC_URL).orEmpty())
}
}
override fun onDestroy() {
webkitCookieManagerProxy.webkitCookieManager?.flush()
webView?.destroy()
super.onDestroy()
}
}

View File

@ -1,5 +1,5 @@
Wersja 2.6.11 Wersja 2.6.14
— naprawiliśmy obsługę wiadomości i ucznia plus u osób, u których działało na wcześniejszej wersji — naprawiliśmy moduł "Uczeń", czyli bez wiadomości i "Uczeń Plus" (na razie)
Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases Pełna lista zmian: https://github.com/wulkanowy/wulkanowy/releases

View File

@ -60,6 +60,16 @@
tools:ignore="UseCompoundDrawables" tools:ignore="UseCompoundDrawables"
tools:visibility="invisible"> tools:visibility="invisible">
<include
android:id="@+id/message_tab_panic_section"
layout="@layout/item_dashboard_panic_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="16dp"
android:visibility="visible"
app:layout_constraintTop_toBottomOf="@id/dashboard_error_admin_message" />
<ImageView <ImageView
android:layout_width="100dp" android:layout_width="100dp"
android:layout_height="100dp" android:layout_height="100dp"

View File

@ -0,0 +1,69 @@
<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:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.modules.panicmode.PanicModeFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?colorControlHighlight">
<com.google.android.material.button.MaterialButton
android:id="@+id/panic_mode_share"
style="@style/Widget.Material3.Button.IconButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
app:icon="@drawable/ic_share"
app:iconTint="?colorOnSurface" />
<com.google.android.material.button.MaterialButton
android:id="@+id/panic_mode_home"
style="@style/Widget.Material3.Button.IconButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
app:icon="@drawable/ic_all_home"
app:iconTint="?colorOnSurface" />
<com.google.android.material.button.MaterialButton
android:id="@+id/panic_mode_refresh"
style="@style/Widget.Material3.Button.IconButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:contentDescription="@string/logviewer_refresh"
app:icon="@drawable/ic_refresh"
app:iconTint="?colorOnSurface" />
<com.google.android.material.button.MaterialButton
android:id="@+id/panic_mode_back"
style="@style/Widget.Material3.Button.IconButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
app:icon="@drawable/ic_chevron_left"
app:iconTint="?colorOnSurface" />
<com.google.android.material.button.MaterialButton
android:id="@+id/panic_mode_forward"
style="@style/Widget.Material3.Button.IconButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
app:icon="@drawable/ic_chevron_right"
app:iconTint="?colorOnSurface" />
</LinearLayout>
<WebView
android:id="@+id/panic_mode_webview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>

View File

@ -1,87 +1,105 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="12dp" android:orientation="vertical">
android:layout_marginVertical="6dp">
<androidx.constraintlayout.widget.ConstraintLayout <com.google.android.material.card.MaterialCardView
android:id="@+id/dashboard_admin_message_item_content" android:id="@+id/dashboard_admin_message"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="wrap_content"
android:layout_marginHorizontal="12dp"
android:layout_marginVertical="6dp">
<ImageView
android:id="@+id/dashboard_admin_message_item_icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:src="@drawable/ic_error"
app:layout_constraintBottom_toBottomOf="@id/dashboard_admin_message_item_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/dashboard_admin_message_item_title"
tools:ignore="ContentDescription"
tools:tint="@android:color/black" />
<TextView <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/dashboard_admin_message_item_title" android:id="@+id/dashboard_admin_message_item_content"
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent">
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@id/dashboard_admin_message_item_close"
app:layout_constraintStart_toEndOf="@id/dashboard_admin_message_item_icon"
app:layout_constraintTop_toTopOf="parent"
tools:text="@tools:sample/lorem" />
<ImageView <ImageView
android:id="@+id/dashboard_admin_message_item_close" android:id="@+id/dashboard_admin_message_item_icon"
android:layout_width="48dp" android:layout_width="24dp"
android:layout_height="48dp" android:layout_height="24dp"
android:layout_marginTop="4dp" android:layout_marginStart="16dp"
android:layout_marginEnd="4dp" android:layout_marginEnd="16dp"
android:padding="12dp" android:src="@drawable/ic_error"
android:background="?selectableItemBackgroundBorderless" app:layout_constraintBottom_toBottomOf="@id/dashboard_admin_message_item_title"
android:src="@drawable/ic_close" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="@id/dashboard_admin_message_item_title"
app:layout_constraintTop_toTopOf="parent" tools:ignore="ContentDescription"
tools:ignore="ContentDescription" /> tools:tint="@android:color/black" />
<TextView <TextView
android:id="@+id/dashboard_admin_message_item_description" android:id="@+id/dashboard_admin_message_item_title"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="8dp"
android:layout_marginTop="8dp" android:layout_marginTop="16dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp" android:textSize="18sp"
android:textSize="14sp" android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@id/dashboard_admin_message_item_close"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/dashboard_admin_message_item_icon"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintTop_toBottomOf="@id/dashboard_admin_message_item_title" tools:text="@tools:sample/lorem" />
app:layout_constraintVertical_bias="0"
app:lineHeight="20dp"
tools:maxLines="5"
tools:text="@tools:sample/lorem/random" />
<com.google.android.material.button.MaterialButton <ImageView
android:id="@+id/dashboard_admin_message_item_dismiss" android:id="@+id/dashboard_admin_message_item_close"
style="@style/Widget.Material3.Button.TextButton.Dialog" android:layout_width="48dp"
android:layout_width="wrap_content" android:layout_height="48dp"
android:layout_height="wrap_content" android:layout_marginTop="4dp"
android:layout_marginTop="8dp" android:layout_marginEnd="4dp"
android:layout_marginEnd="16dp" android:background="?selectableItemBackgroundBorderless"
android:layout_marginBottom="8dp" android:padding="12dp"
android:text="@android:string/ok" android:src="@drawable/ic_close"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintTop_toBottomOf="@id/dashboard_admin_message_item_description" tools:ignore="ContentDescription" />
app:layout_constraintVertical_bias="0" />
</androidx.constraintlayout.widget.ConstraintLayout> <TextView
</com.google.android.material.card.MaterialCardView> android:id="@+id/dashboard_admin_message_item_description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/dashboard_admin_message_item_title"
app:layout_constraintVertical_bias="0"
app:lineHeight="20dp"
tools:maxLines="5"
tools:text="@tools:sample/lorem/random" />
<com.google.android.material.button.MaterialButton
android:id="@+id/dashboard_admin_message_item_dismiss"
style="@style/Widget.Material3.Button.TextButton.Dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:text="@android:string/ok"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/dashboard_admin_message_item_description"
app:layout_constraintVertical_bias="0" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.card.MaterialCardView>
<include
android:id="@+id/dashboard_panic_section"
layout="@layout/item_dashboard_panic_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginVertical="16dp"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/dashboard_error_admin_message" />
</LinearLayout>

View File

@ -0,0 +1,28 @@
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="12dp"
android:layout_marginVertical="6dp">
<LinearLayout
android:layout_margin="16dp"
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:text="Aplikacja nie działa?"
android:textSize="18sp"
android:textStyle="bold" />
<com.google.android.material.button.MaterialButton
android:id="@+id/dashboard_panic_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="Otwórz stronę dziennika" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>

View File

@ -872,6 +872,8 @@
<string name="captcha_dialog_title">Strona dziennika VULCAN wymaga weryfikacji</string> <string name="captcha_dialog_title">Strona dziennika VULCAN wymaga weryfikacji</string>
<string name="captcha_dialog_description"><b>Dlaczego to widzę?</b>\nStrona internetowa dziennika, z której Wulkanowy pobiera dane, wyświetla ten sam ekran jak powyżej, więc Wulkanowy musi również ją pokazać, aby móc pobrać dane z tej witryny. Nie da się tego obejść</string> <string name="captcha_dialog_description"><b>Dlaczego to widzę?</b>\nStrona internetowa dziennika, z której Wulkanowy pobiera dane, wyświetla ten sam ekran jak powyżej, więc Wulkanowy musi również ją pokazać, aby móc pobrać dane z tej witryny. Nie da się tego obejść</string>
<string name="captcha_verified_message">Pomyślnie zweryfikowano</string> <string name="captcha_verified_message">Pomyślnie zweryfikowano</string>
<!--Panic mode-->
<string name="panic_mode_title">Awaryjny dostęp</string>
<!--Errors--> <!--Errors-->
<string name="error_no_internet">Brak połączenia z internetem</string> <string name="error_no_internet">Brak połączenia z internetem</string>
<string name="error_invalid_device_datetime">Wystąpił błąd. Sprawdź poprawność daty w urządzeniu</string> <string name="error_invalid_device_datetime">Wystąpił błąd. Sprawdź poprawność daty w urządzeniu</string>

View File

@ -869,6 +869,9 @@
<string name="captcha_dialog_description"><b>Why am I seeing this?</b>\nThe register website from which Wulkanowy downloads data displays the same screen as above, so Wulkanowy must also show it to be able to download data from this website. There\'s no way around it</string> <string name="captcha_dialog_description"><b>Why am I seeing this?</b>\nThe register website from which Wulkanowy downloads data displays the same screen as above, so Wulkanowy must also show it to be able to download data from this website. There\'s no way around it</string>
<string name="captcha_verified_message">Verified successfully</string> <string name="captcha_verified_message">Verified successfully</string>
<!--Panic mode-->
<string name="panic_mode_title">Emergency access</string>
<!--Errors--> <!--Errors-->
<string name="error_no_internet">No internet connection</string> <string name="error_no_internet">No internet connection</string>

View File

@ -1,6 +1,6 @@
buildscript { buildscript {
ext { ext {
kotlin_version = '1.9.23' kotlin_version = '1.9.24'
about_libraries = '11.1.4' about_libraries = '11.1.4'
hilt_version = '2.51.1' hilt_version = '2.51.1'
} }
@ -13,12 +13,12 @@ buildscript {
dependencies { dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
classpath "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:$kotlin_version-1.0.19" classpath "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:$kotlin_version-1.0.20"
classpath 'com.android.tools.build:gradle:8.4.0' classpath 'com.android.tools.build:gradle:8.4.1'
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
classpath 'com.google.gms:google-services:4.4.1' classpath 'com.google.gms:google-services:4.4.1'
classpath 'com.huawei.agconnect:agcp:1.9.1.303' classpath 'com.huawei.agconnect:agcp:1.9.1.303'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.9' classpath 'com.google.firebase:firebase-crashlytics-gradle:3.0.1'
classpath "com.github.triplet.gradle:play-publisher:3.8.4" classpath "com.github.triplet.gradle:play-publisher:3.8.4"
classpath "ru.cian:huawei-publish-gradle-plugin:1.4.2" classpath "ru.cian:huawei-publish-gradle-plugin:1.4.2"
classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:5.0.0.4638" classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:5.0.0.4638"