Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
775b5122ef | |||
fed00122d7 | |||
426bee882c | |||
d37de197fc | |||
447ece3696 | |||
a73f39e59c | |||
f912aac140 | |||
3caabd3e0e | |||
88576271e2 | |||
b088551005 | |||
130e11a629 | |||
d5e0ae7b37 | |||
e6f56a74a4 | |||
1bc59cfa7f | |||
41bae262a5 | |||
ae65228805 | |||
391ee6e621 | |||
0a87df3d82 | |||
cb4ae21903 | |||
679cf2554d | |||
d473d53879 | |||
6531061b48 | |||
3347e8fba8 | |||
84067126a1 | |||
da9bebe923 |
@ -22,8 +22,8 @@ android {
|
||||
testApplicationId "io.github.tests.wulkanowy"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 31
|
||||
versionCode 104
|
||||
versionName "1.6.0"
|
||||
versionCode 107
|
||||
versionName "1.6.3"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
resValue "string", "app_name", "Wulkanowy"
|
||||
@ -153,7 +153,7 @@ play {
|
||||
defaultToAppBundles = false
|
||||
track = 'production'
|
||||
releaseStatus = com.github.triplet.gradle.androidpublisher.ReleaseStatus.IN_PROGRESS
|
||||
userFraction = 0.25d
|
||||
userFraction = 0.50d
|
||||
updatePriority = 1
|
||||
enabled.set(false)
|
||||
}
|
||||
@ -174,7 +174,7 @@ ext {
|
||||
room = "2.4.2"
|
||||
chucker = "3.5.2"
|
||||
mockk = "1.12.2"
|
||||
coroutines = "1.6.0"
|
||||
coroutines = "1.6.1"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@ -233,7 +233,7 @@ dependencies {
|
||||
implementation 'me.xdrop:fuzzywuzzy:1.4.0'
|
||||
implementation 'com.fredporciuncula:flow-preferences:1.6.0'
|
||||
|
||||
playImplementation platform('com.google.firebase:firebase-bom:29.3.0')
|
||||
playImplementation platform('com.google.firebase:firebase-bom:29.3.1')
|
||||
playImplementation 'com.google.firebase:firebase-analytics-ktx'
|
||||
playImplementation 'com.google.firebase:firebase-messaging:'
|
||||
playImplementation 'com.google.firebase:firebase-crashlytics:'
|
||||
@ -241,8 +241,8 @@ dependencies {
|
||||
playImplementation 'com.google.android.play:core-ktx:1.8.1'
|
||||
playImplementation 'com.google.android.gms:play-services-ads:20.6.0'
|
||||
|
||||
hmsImplementation 'com.huawei.hms:hianalytics:6.4.1.300'
|
||||
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.6.5.200'
|
||||
hmsImplementation 'com.huawei.hms:hianalytics:6.4.1.302'
|
||||
hmsImplementation 'com.huawei.agconnect:agconnect-crash:1.6.5.300'
|
||||
|
||||
releaseImplementation "com.github.ChuckerTeam.Chucker:library-no-op:$chucker"
|
||||
|
||||
|
@ -15,79 +15,41 @@ import javax.inject.Singleton
|
||||
@Singleton
|
||||
class ShortcutsHelper @Inject constructor(@ApplicationContext private val context: Context) {
|
||||
|
||||
// Destination cannot be used here as shortcuts
|
||||
// require their intents to only use primitive types (see PersistableBundle.isValidType).
|
||||
|
||||
private val destinations = mapOf(
|
||||
"grade" to Destination.Grade,
|
||||
"attendance" to Destination.Attendance,
|
||||
"exam" to Destination.Exam,
|
||||
"timetable" to Destination.Timetable()
|
||||
)
|
||||
|
||||
init {
|
||||
initializeShortcuts()
|
||||
}
|
||||
|
||||
fun getDestination(intent: Intent) =
|
||||
destinations[intent.getStringExtra(EXTRA_SHORTCUT_DESTINATION_ID)]
|
||||
|
||||
private fun initializeShortcuts() {
|
||||
fun initializeShortcuts() {
|
||||
val shortcutsInfo = listOf(
|
||||
ShortcutInfoCompat.Builder(context, "grade_shortcut")
|
||||
.setShortLabel(context.getString(R.string.grade_title))
|
||||
.setLongLabel(context.getString(R.string.grade_title))
|
||||
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_shortcut_grade))
|
||||
.setIntent(SplashActivity.getStartIntent(context)
|
||||
.apply {
|
||||
action = Intent.ACTION_VIEW
|
||||
putExtra(EXTRA_SHORTCUT_DESTINATION_ID, "grade")
|
||||
}
|
||||
)
|
||||
.setIntent(SplashActivity.getStartIntent(context, Destination.Grade)
|
||||
.apply { action = Intent.ACTION_VIEW })
|
||||
.build(),
|
||||
|
||||
ShortcutInfoCompat.Builder(context, "attendance_shortcut")
|
||||
.setShortLabel(context.getString(R.string.attendance_title))
|
||||
.setLongLabel(context.getString(R.string.attendance_title))
|
||||
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_shortcut_attendance))
|
||||
.setIntent(SplashActivity.getStartIntent(context)
|
||||
.apply {
|
||||
action = Intent.ACTION_VIEW
|
||||
putExtra(EXTRA_SHORTCUT_DESTINATION_ID, "attendance")
|
||||
}
|
||||
)
|
||||
.setIntent(SplashActivity.getStartIntent(context, Destination.Attendance)
|
||||
.apply { action = Intent.ACTION_VIEW })
|
||||
.build(),
|
||||
|
||||
ShortcutInfoCompat.Builder(context, "exam_shortcut")
|
||||
.setShortLabel(context.getString(R.string.exam_title))
|
||||
.setLongLabel(context.getString(R.string.exam_title))
|
||||
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_shortcut_exam))
|
||||
.setIntent(SplashActivity.getStartIntent(context)
|
||||
.apply {
|
||||
action = Intent.ACTION_VIEW
|
||||
putExtra(EXTRA_SHORTCUT_DESTINATION_ID, "exam")
|
||||
}
|
||||
)
|
||||
.setIntent(SplashActivity.getStartIntent(context, Destination.Exam)
|
||||
.apply { action = Intent.ACTION_VIEW })
|
||||
.build(),
|
||||
|
||||
ShortcutInfoCompat.Builder(context, "timetable_shortcut")
|
||||
.setShortLabel(context.getString(R.string.timetable_title))
|
||||
.setLongLabel(context.getString(R.string.timetable_title))
|
||||
.setIcon(IconCompat.createWithResource(context, R.drawable.ic_shortcut_timetable))
|
||||
.setIntent(SplashActivity.getStartIntent(context)
|
||||
.apply {
|
||||
action = Intent.ACTION_VIEW
|
||||
putExtra(EXTRA_SHORTCUT_DESTINATION_ID, "timetable")
|
||||
}
|
||||
)
|
||||
.setIntent(SplashActivity.getStartIntent(context, Destination.Timetable())
|
||||
.apply { action = Intent.ACTION_VIEW })
|
||||
.build()
|
||||
)
|
||||
|
||||
shortcutsInfo.forEach { ShortcutManagerCompat.pushDynamicShortcut(context, it) }
|
||||
}
|
||||
|
||||
private companion object {
|
||||
|
||||
private const val EXTRA_SHORTCUT_DESTINATION_ID = "shortcut_destination_id"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,15 +19,15 @@ import kotlinx.serialization.Serializable
|
||||
import java.time.LocalDate
|
||||
|
||||
@Serializable
|
||||
sealed class Destination private constructor() : java.io.Serializable {
|
||||
sealed class Destination {
|
||||
|
||||
/*
|
||||
Type in children classes have to be as getter to avoid null in enums
|
||||
https://stackoverflow.com/questions/68866453/kotlin-enum-val-is-returning-null-despite-being-set-at-compile-time
|
||||
*/
|
||||
abstract val type: Type
|
||||
abstract val destinationType: Type
|
||||
|
||||
abstract val fragment: Fragment
|
||||
abstract val destinationFragment: Fragment
|
||||
|
||||
enum class Type(val defaultDestination: Destination) {
|
||||
DASHBOARD(Dashboard),
|
||||
@ -47,26 +47,26 @@ sealed class Destination private constructor() : java.io.Serializable {
|
||||
|
||||
@Serializable
|
||||
object Dashboard : Destination() {
|
||||
override val type get() = Type.DASHBOARD
|
||||
override val fragment get() = DashboardFragment.newInstance()
|
||||
override val destinationType get() = Type.DASHBOARD
|
||||
override val destinationFragment get() = DashboardFragment.newInstance()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
object Grade : Destination() {
|
||||
override val type get() = Type.GRADE
|
||||
override val fragment get() = GradeFragment.newInstance()
|
||||
override val destinationType get() = Type.GRADE
|
||||
override val destinationFragment get() = GradeFragment.newInstance()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
object Attendance : Destination() {
|
||||
override val type get() = Type.ATTENDANCE
|
||||
override val fragment get() = AttendanceFragment.newInstance()
|
||||
override val destinationType get() = Type.ATTENDANCE
|
||||
override val destinationFragment get() = AttendanceFragment.newInstance()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
object Exam : Destination() {
|
||||
override val type get() = Type.EXAM
|
||||
override val fragment get() = ExamFragment.newInstance()
|
||||
override val destinationType get() = Type.EXAM
|
||||
override val destinationFragment get() = ExamFragment.newInstance()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
@ -74,55 +74,55 @@ sealed class Destination private constructor() : java.io.Serializable {
|
||||
@Serializable(with = LocalDateSerializer::class)
|
||||
private val date: LocalDate? = null
|
||||
) : Destination() {
|
||||
override val type get() = Type.TIMETABLE
|
||||
override val fragment get() = TimetableFragment.newInstance(date)
|
||||
override val destinationType get() = Type.TIMETABLE
|
||||
override val destinationFragment get() = TimetableFragment.newInstance(date)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
object Homework : Destination() {
|
||||
override val type get() = Type.HOMEWORK
|
||||
override val fragment get() = HomeworkFragment.newInstance()
|
||||
override val destinationType get() = Type.HOMEWORK
|
||||
override val destinationFragment get() = HomeworkFragment.newInstance()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
object Note : Destination() {
|
||||
override val type get() = Type.NOTE
|
||||
override val fragment get() = NoteFragment.newInstance()
|
||||
override val destinationType get() = Type.NOTE
|
||||
override val destinationFragment get() = NoteFragment.newInstance()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
object Conference : Destination() {
|
||||
override val type get() = Type.CONFERENCE
|
||||
override val fragment get() = ConferenceFragment.newInstance()
|
||||
override val destinationType get() = Type.CONFERENCE
|
||||
override val destinationFragment get() = ConferenceFragment.newInstance()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
object SchoolAnnouncement : Destination() {
|
||||
override val type get() = Type.SCHOOL_ANNOUNCEMENT
|
||||
override val fragment get() = SchoolAnnouncementFragment.newInstance()
|
||||
override val destinationType get() = Type.SCHOOL_ANNOUNCEMENT
|
||||
override val destinationFragment get() = SchoolAnnouncementFragment.newInstance()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
object School : Destination() {
|
||||
override val type get() = Type.SCHOOL
|
||||
override val fragment get() = SchoolFragment.newInstance()
|
||||
override val destinationType get() = Type.SCHOOL
|
||||
override val destinationFragment get() = SchoolFragment.newInstance()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
object LuckyNumber : Destination() {
|
||||
override val type get() = Type.LUCKY_NUMBER
|
||||
override val fragment get() = LuckyNumberFragment.newInstance()
|
||||
override val destinationType get() = Type.LUCKY_NUMBER
|
||||
override val destinationFragment get() = LuckyNumberFragment.newInstance()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
object More : Destination() {
|
||||
override val type get() = Type.MORE
|
||||
override val fragment get() = MoreFragment.newInstance()
|
||||
override val destinationType get() = Type.MORE
|
||||
override val destinationFragment get() = MoreFragment.newInstance()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
object Message : Destination() {
|
||||
override val type get() = Type.MESSAGE
|
||||
override val fragment get() = MessageFragment.newInstance()
|
||||
override val destinationType get() = Type.MESSAGE
|
||||
override val destinationFragment get() = MessageFragment.newInstance()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import android.os.Looper
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.text.parseAsHtml
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.core.view.updateMarginsRelative
|
||||
@ -563,7 +564,7 @@ class DashboardAdapter @Inject constructor() : RecyclerView.Adapter<RecyclerView
|
||||
) {
|
||||
with(binding.dashboardLessonsItemDayHeader) {
|
||||
isVisible = header != null
|
||||
text = header?.content
|
||||
text = header?.content?.parseAsHtml()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ class LuckyNumberWidgetProvider : AppWidgetProvider() {
|
||||
.apply {
|
||||
setTextViewText(
|
||||
R.id.luckyNumberWidgetNumber,
|
||||
luckyNumber.dataOrNull?.toString() ?: "#"
|
||||
luckyNumber.dataOrNull?.luckyNumber?.toString() ?: "#"
|
||||
)
|
||||
setOnClickPendingIntent(R.id.luckyNumberWidgetContainer, appIntent)
|
||||
}
|
||||
|
@ -24,6 +24,8 @@ import io.github.wulkanowy.ui.base.BaseActivity
|
||||
import io.github.wulkanowy.ui.modules.Destination
|
||||
import io.github.wulkanowy.ui.modules.account.accountquick.AccountQuickDialog
|
||||
import io.github.wulkanowy.utils.*
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -55,13 +57,13 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
|
||||
|
||||
companion object {
|
||||
|
||||
private const val EXTRA_START_DESTINATION = "start_destination"
|
||||
private const val EXTRA_START_DESTINATION = "start_destination_json"
|
||||
|
||||
fun getStartIntent(
|
||||
context: Context,
|
||||
destination: Destination? = null,
|
||||
) = Intent(context, MainActivity::class.java).apply {
|
||||
putExtra(EXTRA_START_DESTINATION, destination)
|
||||
destination?.let { putExtra(EXTRA_START_DESTINATION, Json.encodeToString(it)) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,9 +72,8 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
|
||||
override val currentStackSize get() = navController.currentStack?.size
|
||||
|
||||
override val currentViewTitle
|
||||
get() = (navController.currentFrag as? MainView.TitledView)?.titleStringId?.let {
|
||||
getString(it)
|
||||
}
|
||||
get() = (navController.currentFrag as? MainView.TitledView)?.titleStringId
|
||||
?.let { getString(it) }
|
||||
|
||||
override val currentViewSubtitle get() = (navController.currentFrag as? MainView.TitledView)?.subtitleString
|
||||
|
||||
@ -86,7 +87,7 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
|
||||
messageContainer = binding.mainMessageContainer
|
||||
updateHelper.messageContainer = binding.mainFragmentContainer
|
||||
|
||||
val destination = (intent.getSerializableExtra(EXTRA_START_DESTINATION) as Destination?)
|
||||
val destination = intent.getStringExtra(EXTRA_START_DESTINATION)
|
||||
?.takeIf { savedInstanceState == null }
|
||||
|
||||
presenter.onAttachView(this, destination)
|
||||
@ -129,7 +130,7 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
|
||||
)
|
||||
}
|
||||
fragmentHideStrategy = HIDE
|
||||
rootFragments = rootDestinations.map { it.fragment }
|
||||
rootFragments = rootDestinations.map { it.destinationFragment }
|
||||
|
||||
initialize(startMenuIndex, savedInstanceState)
|
||||
}
|
||||
@ -230,7 +231,7 @@ class MainActivity : BaseActivity<MainPresenter, ActivityMainBinding>(), MainVie
|
||||
}
|
||||
|
||||
override fun openMoreDestination(destination: Destination) {
|
||||
pushView(destination.fragment)
|
||||
pushView(destination.destinationFragment)
|
||||
}
|
||||
|
||||
override fun notifyMenuViewReselected() {
|
||||
|
@ -19,6 +19,8 @@ import io.github.wulkanowy.ui.modules.message.MessageView
|
||||
import io.github.wulkanowy.ui.modules.schoolandteachers.SchoolAndTeachersView
|
||||
import io.github.wulkanowy.ui.modules.studentinfo.StudentInfoView
|
||||
import io.github.wulkanowy.utils.AnalyticsHelper
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import timber.log.Timber
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
@ -30,6 +32,7 @@ class MainPresenter @Inject constructor(
|
||||
private val prefRepository: PreferencesRepository,
|
||||
private val syncManager: SyncManager,
|
||||
private val analytics: AnalyticsHelper,
|
||||
private val json: Json
|
||||
) : BasePresenter<MainView>(errorHandler, studentRepository) {
|
||||
|
||||
private var studentsWitSemesters: List<StudentWithSemesters>? = null
|
||||
@ -45,18 +48,20 @@ class MainPresenter @Inject constructor(
|
||||
private val Destination?.startMenuIndex
|
||||
get() = when {
|
||||
this == null -> prefRepository.startMenuIndex
|
||||
type in rootDestinationTypeList -> {
|
||||
rootDestinationTypeList.indexOf(type)
|
||||
destinationType in rootDestinationTypeList -> {
|
||||
rootDestinationTypeList.indexOf(destinationType)
|
||||
}
|
||||
else -> 4
|
||||
}
|
||||
|
||||
fun onAttachView(view: MainView, initDestination: Destination?) {
|
||||
fun onAttachView(view: MainView, initDestinationJson: String?) {
|
||||
super.onAttachView(view)
|
||||
|
||||
val initDestination: Destination? = initDestinationJson?.let { json.decodeFromString(it) }
|
||||
|
||||
val startMenuIndex = initDestination.startMenuIndex
|
||||
val destinations = rootDestinationTypeList.map {
|
||||
if (it == initDestination?.type) initDestination else it.defaultDestination
|
||||
if (it == initDestination?.destinationType) initDestination else it.defaultDestination
|
||||
}
|
||||
|
||||
view.initView(startMenuIndex, destinations)
|
||||
|
@ -43,7 +43,7 @@ class NotificationsCenterFragment :
|
||||
|
||||
override fun initView() {
|
||||
notificationsCenterAdapter.onItemClickListener = { notification ->
|
||||
(requireActivity() as MainActivity).pushView(notification.destination.fragment)
|
||||
(requireActivity() as MainActivity).pushView(notification.destination.destinationFragment)
|
||||
}
|
||||
|
||||
with(binding.notificationsCenterRecycler) {
|
||||
|
@ -15,6 +15,8 @@ import io.github.wulkanowy.ui.modules.Destination
|
||||
import io.github.wulkanowy.ui.modules.login.LoginActivity
|
||||
import io.github.wulkanowy.ui.modules.main.MainActivity
|
||||
import io.github.wulkanowy.utils.openInternetBrowser
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import javax.inject.Inject
|
||||
|
||||
@SuppressLint("CustomSplashScreen")
|
||||
@ -29,13 +31,13 @@ class SplashActivity : BaseActivity<SplashPresenter, ViewBinding>(), SplashView
|
||||
|
||||
companion object {
|
||||
|
||||
private const val EXTRA_START_DESTINATION = "start_destination"
|
||||
private const val EXTRA_START_DESTINATION = "start_destination_json"
|
||||
|
||||
private const val EXTRA_EXTERNAL_URL = "external_url"
|
||||
|
||||
fun getStartIntent(context: Context, destination: Destination? = null) =
|
||||
Intent(context, SplashActivity::class.java).apply {
|
||||
putExtra(EXTRA_START_DESTINATION, destination)
|
||||
destination?.let { putExtra(EXTRA_START_DESTINATION, Json.encodeToString(it)) }
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
}
|
||||
}
|
||||
@ -43,12 +45,12 @@ class SplashActivity : BaseActivity<SplashPresenter, ViewBinding>(), SplashView
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
installSplashScreen().setKeepOnScreenCondition { true }
|
||||
shortcutsHelper.initializeShortcuts()
|
||||
|
||||
val externalLink = intent?.getStringExtra(EXTRA_EXTERNAL_URL)
|
||||
val startDestination = intent?.getSerializableExtra(EXTRA_START_DESTINATION) as Destination?
|
||||
?: shortcutsHelper.getDestination(intent)
|
||||
val startDestinationJson = intent?.getStringExtra(EXTRA_START_DESTINATION)
|
||||
|
||||
presenter.onAttachView(this, externalLink, startDestination)
|
||||
presenter.onAttachView(this, externalLink, startDestinationJson)
|
||||
}
|
||||
|
||||
override fun openLoginView() {
|
||||
|
@ -5,16 +5,21 @@ import io.github.wulkanowy.ui.base.BasePresenter
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.ui.modules.Destination
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import javax.inject.Inject
|
||||
|
||||
class SplashPresenter @Inject constructor(
|
||||
errorHandler: ErrorHandler,
|
||||
studentRepository: StudentRepository,
|
||||
private val json: Json
|
||||
) : BasePresenter<SplashView>(errorHandler, studentRepository) {
|
||||
|
||||
fun onAttachView(view: SplashView, externalUrl: String?, startDestination: Destination?) {
|
||||
fun onAttachView(view: SplashView, externalUrl: String?, startDestinationJson: String?) {
|
||||
super.onAttachView(view)
|
||||
|
||||
val startDestination: Destination? = startDestinationJson?.let { json.decodeFromString(it) }
|
||||
|
||||
if (!externalUrl.isNullOrBlank()) {
|
||||
view.openExternalUrlAndFinish(externalUrl)
|
||||
return
|
||||
|
@ -1,4 +1,4 @@
|
||||
Wersja 1.6.0
|
||||
Wersja 1.6.3
|
||||
|
||||
- dodaliśmy możliwość usuwania wielu wiadomości jednocześnie
|
||||
- dodaliśmy opcję szybkiego dodawania sprawdzianów do kalendarza
|
||||
|
@ -146,7 +146,7 @@
|
||||
android:id="@+id/examDialogDeadlineDateValue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="0dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:paddingStart="0dp"
|
||||
android:paddingEnd="16dp"
|
||||
@ -162,7 +162,7 @@
|
||||
android:id="@+id/examDialogEntryDateTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="0dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:text="@string/exam_entry_date"
|
||||
|
@ -71,6 +71,7 @@
|
||||
<string name="login_recover_title">Obnovte svůj účet</string>
|
||||
<string name="login_recover">Obnovit</string>
|
||||
<string name="login_signed_in">Žák je už přihlášen</string>
|
||||
<string name="login_host_standard">Standardní</string>
|
||||
<!--Main-->
|
||||
<string name="main_account_picker">Manažer účtů</string>
|
||||
<string name="main_log_in">Přihlásit se</string>
|
||||
@ -93,9 +94,9 @@
|
||||
<string name="grade_summary_predicted_grade">Předpokládaná známka</string>
|
||||
<string name="grade_summary_calculated_average">Vypočítaný průměr</string>
|
||||
<string name="grade_summary_calculated_average_help_dialog_title">Jak funguje vypočítaný průměr?</string>
|
||||
<string name="grade_summary_calculated_average_help_dialog_message">Vypočítaný průměr je aritmetický průměr vypočítaný z průměrů předmětů. Umožňuje vám to znát přibližný konečný průměr. Vypočítává se způsobem zvoleným uživatelem v nastavení aplikaci. Doporučuje se vybrat příslušnou možnost. Důvodem je rozdílný výpočet školních průměrů. Pokud vaše škola navíc uvádí průměr předmětů na stránce deníku Vulcan, aplikace si je stáhne a tyto průměry nepočítá. To lze změnit vynucením výpočtu průměru v nastavení aplikaci.\n\n<b>Průměr známek pouze z vybraného semestru</b>:\n1. Výpočet váženého průměru pro každý předmět v daném semestru\n2. Sčítání vypočítaných průměrů\n3. Výpočet aritmetického průměru součtených průměrů\n\n<b>Průměr průměrů z obou semestrů</b>:\n1. Výpočet váženého průměru pro každý předmět v semestru 1 a 2\n2. Výpočet aritmetického průměru vypočítaných průměrů za semestry 1 a 2 pro každý předmět.\n3. Sčítání vypočítaných průměrů\n4. Výpočet aritmetického průměru součtených průměrů\n\n<b>Průměr známek z celého roku:</b>\n1. Výpočet váženého průměru za rok pro každý předmět. Konečný průměr v 1. semestru je nepodstatný.\n3. Sčítání vypočítaných průměrů\n4. Výpočet aritmetického průměru součtených průměrů</string>
|
||||
<string name="grade_summary_calculated_average_help_dialog_message">Vypočítaný průměr je aritmetický průměr vypočítaný z průměrů předmětů. Umožňuje vám to znát přibližný konečný průměr. Vypočítává se způsobem zvoleným uživatelem v nastavení aplikaci. Doporučuje se vybrat příslušnou možnost. Důvodem je rozdílný výpočet školních průměrů. Pokud vaše škola navíc uvádí průměr předmětů na stránce deníku Vulcan, aplikace si je stáhne a tyto průměry nepočítá. To lze změnit vynucením výpočtu průměru v nastavení aplikaci.\n\n<b>Průměr známek pouze z vybraného semestru</b>:\n1. Výpočet váženého průměru pro každý předmět v daném semestru\n2. Sčítání vypočítaných průměrů\n3. Výpočet aritmetického průměru součtených průměrů\n\n<b>Průměr průměrů z obou semestrů</b>:\n1. Výpočet váženého průměru pro každý předmět v semestru 1 a 2\n2. Výpočet aritmetického průměru vypočítaných průměrů za semestry 1 a 2 pro každý předmět.\n3. Sčítání vypočítaných průměrů\n4. Výpočet aritmetického průměru sečtených průměrů\n\n<b>Průměr známek z celého roku:</b>\n1. Výpočet váženého průměru za rok pro každý předmět. Konečný průměr v 1. semestru je nepodstatný.\n3. Sčítání vypočítaných průměrů\n4. Výpočet aritmetického průměru součtených průměrů</string>
|
||||
<string name="grade_summary_final_average_help_dialog_title">Jak funguje konečný průměr?</string>
|
||||
<string name="grade_summary_final_average_help_dialog_message">Konečný průměr je aritmetický průměr vypočítaný ze všech aktuálně dostupných konečných známek v daném semestru.\n\nSchéma výpočtu se skládá z následujících kroků:\n1. Sčítání konečných známek zadaných učiteli\n2. Děleno počtem předmětů, pro které už byly vydány známky</string>
|
||||
<string name="grade_summary_final_average_help_dialog_message">Konečný průměr je aritmetický průměr vypočítaný ze všech aktuálně dostupných konečných známek v daném semestru.\n\nSchéma výpočtu se skládá z následujících kroků:\n1. Sčítání konečných známek zadaných učiteli\n2. Děleno počtem předmětů, pro které už byly uděleny známky</string>
|
||||
<string name="grade_summary_final_average">Konečný průměr</string>
|
||||
<string name="grade_summary_from_subjects">z %1$d z %2$d předmětů</string>
|
||||
<string name="grade_menu_summary">Shrnutí</string>
|
||||
@ -219,7 +220,7 @@
|
||||
<string name="additional_lessons_end_time_error">Čas ukončení musí být pozdější než čas zahájení</string>
|
||||
<!--Attendance-->
|
||||
<string name="attendance_summary_button">Shrnutí frekvencí</string>
|
||||
<string name="attendance_absence_school">Neprítomnosť zo školských dôvodov</string>
|
||||
<string name="attendance_absence_school">Nepřítomnost ze školních důvodů</string>
|
||||
<string name="attendance_absence_excused">Omluvená nepřítomnost</string>
|
||||
<string name="attendance_absence_unexcused">Neomluvená nepřítomnost</string>
|
||||
<string name="attendance_exemption">Osvobození</string>
|
||||
|
@ -71,6 +71,7 @@
|
||||
<string name="login_recover_title">Ihr Konto wiederherstellen</string>
|
||||
<string name="login_recover">Wiederherstellen</string>
|
||||
<string name="login_signed_in">Student ist bereits angemeldet</string>
|
||||
<string name="login_host_standard">Standard</string>
|
||||
<!--Main-->
|
||||
<string name="main_account_picker">Kundenbetreuer</string>
|
||||
<string name="main_log_in">Anmelden</string>
|
||||
|
@ -71,6 +71,7 @@
|
||||
<string name="login_recover_title">Przywróć swoje konto</string>
|
||||
<string name="login_recover">Przywróć</string>
|
||||
<string name="login_signed_in">Uczeń jest już zalogowany</string>
|
||||
<string name="login_host_standard">Standardowa</string>
|
||||
<!--Main-->
|
||||
<string name="main_account_picker">Menadżer kont</string>
|
||||
<string name="main_log_in">Zaloguj się</string>
|
||||
|
@ -71,6 +71,7 @@
|
||||
<string name="login_recover_title">Восстановите свой аккаунт</string>
|
||||
<string name="login_recover">Восстановить</string>
|
||||
<string name="login_signed_in">Студент уже вошел в систему</string>
|
||||
<string name="login_host_standard">Стандартный</string>
|
||||
<!--Main-->
|
||||
<string name="main_account_picker">Менеджер аккаунтов</string>
|
||||
<string name="main_log_in">Войти</string>
|
||||
|
@ -71,6 +71,7 @@
|
||||
<string name="login_recover_title">Obnovte svoj účet</string>
|
||||
<string name="login_recover">Obnoviť</string>
|
||||
<string name="login_signed_in">Žiak je už prihlásený</string>
|
||||
<string name="login_host_standard">Štandardná</string>
|
||||
<!--Main-->
|
||||
<string name="main_account_picker">Manažér účtov</string>
|
||||
<string name="main_log_in">Prihlásiť sa</string>
|
||||
|
@ -71,6 +71,7 @@
|
||||
<string name="login_recover_title">Відновіть свій обліковий запис</string>
|
||||
<string name="login_recover">Відновити</string>
|
||||
<string name="login_signed_in">Учень вже увійшов до системи</string>
|
||||
<string name="login_host_standard">Стандартний</string>
|
||||
<!--Main-->
|
||||
<string name="main_account_picker">Менеджер аккаунтів</string>
|
||||
<string name="main_log_in">Увійти</string>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
|
||||
<string-array name="hosts_keys">
|
||||
<item>Standardowa</item>
|
||||
<item>@string/login_host_standard</item>
|
||||
<item>Opolska eSzkoła</item>
|
||||
<item>Gdańska Platforma Edukacyjna</item>
|
||||
<item>Lubelski Portal Oświatowy</item>
|
||||
|
@ -77,6 +77,7 @@
|
||||
<string name="login_recover_title">Recover your account</string>
|
||||
<string name="login_recover">Recover</string>
|
||||
<string name="login_signed_in">Student is already signed in</string>
|
||||
<string name="login_host_standard">Standard</string>
|
||||
|
||||
|
||||
<!--Main-->
|
||||
|
@ -5,13 +5,9 @@ import io.github.wulkanowy.data.repositories.StudentRepository
|
||||
import io.github.wulkanowy.services.sync.SyncManager
|
||||
import io.github.wulkanowy.ui.base.ErrorHandler
|
||||
import io.github.wulkanowy.utils.AnalyticsHelper
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.Runs
|
||||
import io.mockk.clearMocks
|
||||
import io.mockk.every
|
||||
import io.mockk.*
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.mockk.just
|
||||
import io.mockk.verify
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
|
||||
@ -43,8 +39,14 @@ class MainPresenterTest {
|
||||
clearMocks(mainView)
|
||||
|
||||
every { mainView.initView(any(), any()) } just Runs
|
||||
presenter =
|
||||
MainPresenter(errorHandler, studentRepository, prefRepository, syncManager, analytics)
|
||||
presenter = MainPresenter(
|
||||
errorHandler = errorHandler,
|
||||
studentRepository = studentRepository,
|
||||
prefRepository = prefRepository,
|
||||
syncManager = syncManager,
|
||||
analytics = analytics,
|
||||
json = Json
|
||||
)
|
||||
presenter.onAttachView(mainView, null)
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@ import io.mockk.MockKAnnotations
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.impl.annotations.MockK
|
||||
import io.mockk.verify
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
@ -30,7 +31,7 @@ class SplashPresenterTest {
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockKAnnotations.init(this)
|
||||
presenter = SplashPresenter(errorHandler, studentRepository)
|
||||
presenter = SplashPresenter(errorHandler, studentRepository, Json)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1,6 +1,6 @@
|
||||
buildscript {
|
||||
ext {
|
||||
kotlin_version = '1.6.10'
|
||||
kotlin_version = '1.6.20'
|
||||
about_libraries = '8.9.4'
|
||||
hilt_version = "2.41"
|
||||
}
|
||||
@ -13,10 +13,10 @@ buildscript {
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||
classpath 'com.android.tools.build:gradle:7.1.2'
|
||||
classpath 'com.android.tools.build:gradle:7.1.3'
|
||||
classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version"
|
||||
classpath 'com.google.gms:google-services:4.3.10'
|
||||
classpath 'com.huawei.agconnect:agcp:1.6.5.200'
|
||||
classpath 'com.huawei.agconnect:agcp:1.6.5.300'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1'
|
||||
classpath "com.github.triplet.gradle:play-publisher:3.6.0"
|
||||
classpath "ru.cian:huawei-publish-gradle-plugin:1.3.3"
|
||||
|
Reference in New Issue
Block a user