Added notifications for upcoming exams; updated app logo

This commit is contained in:
Deniz Düzgören
2020-03-09 20:17:34 +01:00
parent 31b1bc5d4e
commit 80f737a96c
41 changed files with 646 additions and 226 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
+328
View File
@@ -0,0 +1,328 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="WizardSettings">
<option name="children">
<map>
<entry key="imageWizard">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="imageAssetPanel">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="actionbar">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="clipArt">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="color" value="000000" />
<entry key="imagePath" value="C:\Users\kduez\AppData\Local\Temp\ic_android_black_24dp.xml" />
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="text">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="color" value="000000" />
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="textAsset">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="color" value="000000" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="launcher">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="foregroundClipArt">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="imagePath" value="C:\Users\kduez\AppData\Local\Temp\ic_android_black_24dp.xml" />
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="foregroundImage">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="color" value="000000" />
<entry key="imagePath" value="C:\Users\kduez\git\qwark_media\qwark_logo_2.png" />
<entry key="scalingPercent" value="140" />
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="foregroundText">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="color" value="000000" />
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="foregroundTextAsset">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="color" value="000000" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
<option name="values">
<map>
<entry key="legacyIconShape" value="CIRCLE" />
<entry key="previewDensity" value="XXXHIGH" />
<entry key="showGrid" value="true" />
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="launcherLegacy">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="clipArt">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="color" value="000000" />
<entry key="imagePath" value="C:\Users\kduez\AppData\Local\Temp\ic_android_black_24dp.xml" />
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="text">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="color" value="000000" />
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="textAsset">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="color" value="000000" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="notification">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="clipArt">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="color" value="000000" />
<entry key="imagePath" value="C:\Users\kduez\AppData\Local\Temp\ic_android_black_24dp.xml" />
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="text">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="color" value="000000" />
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="textAsset">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="color" value="000000" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="tvBanner">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="foregroundText">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="color" value="000000" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="tvChannel">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="foregroundClipArt">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="imagePath" value="C:\Users\kduez\AppData\Local\Temp\ic_android_black_24dp.xml" />
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="foregroundImage">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="color" value="000000" />
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="foregroundText">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="color" value="000000" />
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="foregroundTextAsset">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="color" value="000000" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
<option name="values">
<map>
<entry key="previewDensity" value="XXXHIGH" />
<entry key="showGrid" value="true" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</PersistentState>
</value>
</entry>
<entry key="vectorWizard">
<value>
<PersistentState>
<option name="children">
<map>
<entry key="vectorAssetStep">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="assetSourceType" value="FILE" />
<entry key="outputName" value="bolt" />
<entry key="sourceFile" value="C:\Users\kduez\Downloads\flash.svg" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
</component>
</project>
+25 -13
View File
File diff suppressed because one or more lines are too long
+4 -2
View File
@@ -38,11 +38,11 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.2.0' implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4' implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
implementation "androidx.fragment:fragment-ktx:1.2.1" implementation "androidx.fragment:fragment-ktx:1.2.2"
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
implementation 'androidx.recyclerview:recyclerview:1.1.0' implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'com.google.android.material:material:1.2.0-alpha04' implementation 'com.google.android.material:material:1.2.0-alpha05'
implementation 'androidx.preference:preference-ktx:1.1.0' implementation 'androidx.preference:preference-ktx:1.1.0'
@@ -54,6 +54,8 @@ dependencies {
implementation "androidx.room:room-runtime:2.2.3" implementation "androidx.room:room-runtime:2.2.3"
kapt "androidx.room:room-compiler:$room_version" kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.work:work-runtime-ktx:2.3.3"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0'
Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 23 KiB

@@ -1,27 +1,22 @@
package com.denizd.qwark.activity package com.denizd.qwark.activity
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.os.Bundle import android.os.Bundle
import android.os.Handler
import android.util.Log
import android.view.View import android.view.View
import android.view.ViewAnimationUtils
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatDelegate
import androidx.fragment.app.FragmentActivity import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentTransaction import androidx.fragment.app.FragmentTransaction
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.work.*
import com.denizd.lawrence.util.viewBinding import com.denizd.lawrence.util.viewBinding
import com.denizd.qwark.R import com.denizd.qwark.R
import com.denizd.qwark.database.QwarkRepository import com.denizd.qwark.database.QwarkRepository
import com.denizd.qwark.databinding.ActivityMainBinding import com.denizd.qwark.databinding.ActivityMainBinding
import com.denizd.qwark.fragment.* import com.denizd.qwark.fragment.*
import com.denizd.qwark.util.Dependencies import com.denizd.qwark.util.Dependencies
import com.denizd.qwark.util.QwarkPreferences import com.denizd.qwark.util.ExamNotificationWorker
import com.denizd.qwark.viewmodel.MainViewModel import com.denizd.qwark.viewmodel.MainViewModel
import kotlin.math.hypot import java.util.concurrent.TimeUnit
import kotlin.random.Random import kotlin.random.Random
class MainActivity : FragmentActivity() { class MainActivity : FragmentActivity() {
@@ -68,25 +63,44 @@ class MainActivity : FragmentActivity() {
// TODO reselected listener for scrolling up // TODO reselected listener for scrolling up
resources.getStringArray(R.array.greetings).also { array -> resources.getStringArray(R.array.greetings).also { array ->
binding.greetingTextView.text = String.format(array[Random.nextInt(array.size)], "TODO") binding.greetingTextView.text = String.format(
array[Random.nextInt(array.size)],
Dependencies.repo.prefs.getScoreProfileName()
)
} }
Handler().postDelayed({ // splash screen
binding.splashScreen.apply { // Handler().postDelayed({
val cx = width / 2 // binding.splashScreen.apply {
val cy = height / 2 // val cx = width / 2
val initialRadius = hypot(cx.toDouble(), cy.toDouble()).toFloat() // val cy = height / 2
// val initialRadius = hypot(cx.toDouble(), cy.toDouble()).toFloat()
//
// ViewAnimationUtils.createCircularReveal(this, cx, cy, initialRadius, 0f).also { anim ->
// anim.addListener(object : AnimatorListenerAdapter() {
// override fun onAnimationEnd(animation: Animator) {
// super.onAnimationEnd(animation)
// visibility = View.GONE
// }
// })
// anim.start()
// }
// }
// }, 1200)
ViewAnimationUtils.createCircularReveal(this, cx, cy, initialRadius, 0f).also { anim -> Dependencies.repo.allCoursesWithExams.observe(this, Observer { courses ->
anim.addListener(object : AnimatorListenerAdapter() { with (WorkManager.getInstance(this)) {
override fun onAnimationEnd(animation: Animator) { for (course in courses) {
super.onAnimationEnd(animation) beginUniqueWork(
visibility = View.GONE "${course.name}-${course.courseId}",
ExistingWorkPolicy.REPLACE,
OneTimeWorkRequestBuilder<ExamNotificationWorker>()
.setInitialDelay(getTimeUntil(course.examTime), TimeUnit.MILLISECONDS)
.setInputData(Data.Builder().putString("course", course.name).build())
.build()
).enqueue()
}
} }
}) })
anim.start()
}
}
}, 1200)
} }
override fun onResume() { override fun onResume() {
@@ -139,4 +153,7 @@ class MainActivity : FragmentActivity() {
} }
} }
} }
// TODO add option to set time of notification (currently: 7 AM)
private fun getTimeUntil(examTime: Long): Long = examTime + viewModel.getExamNotificationTime() - System.currentTimeMillis()
} }
@@ -20,6 +20,9 @@ interface QwarkDao {
@Query("SELECT course.*, (SELECT MIN(exam_time) FROM grade WHERE grade.course_id = course.course_id AND exam_time >= :time) AS exam_time FROM course GROUP BY course.course_id ORDER BY time") @Query("SELECT course.*, (SELECT MIN(exam_time) FROM grade WHERE grade.course_id = course.course_id AND exam_time >= :time) AS exam_time FROM course GROUP BY course.course_id ORDER BY time")
fun getAllCourseExams(time: Long = QwarkUtil.timeAtMidnight): List<CourseExam> fun getAllCourseExams(time: Long = QwarkUtil.timeAtMidnight): List<CourseExam>
@Query("SELECT course.*, (SELECT MIN(exam_time) FROM grade WHERE grade.course_id = course.course_id AND exam_time >= :time) AS exam_time FROM course WHERE exam_time > :time GROUP BY course.course_id ORDER BY time")
fun getAllCoursesWithExams(time: Long = QwarkUtil.timeAtMidnight + 25200000L): LiveData<List<CourseExam>>
@Query("SELECT *, -1 AS exam_time FROM course WHERE course_id != :u ORDER BY time") @Query("SELECT *, -1 AS exam_time FROM course WHERE course_id != :u ORDER BY time")
fun getAllCourses(u: Int = -1): List<CourseExam> // the u variable is an unnecessary workaround to return a list instead of LiveData fun getAllCourses(u: Int = -1): List<CourseExam> // the u variable is an unnecessary workaround to return a list instead of LiveData
@@ -83,7 +83,6 @@ class QwarkRepository(app: Application) {
prefs.setInt(PreferenceKey.SCORE_PROFILE_ID, scoreProfile.scoreProfileId) prefs.setInt(PreferenceKey.SCORE_PROFILE_ID, scoreProfile.scoreProfileId)
.setString(PreferenceKey.SCORE_PROFILE_NAME, scoreProfile.name) .setString(PreferenceKey.SCORE_PROFILE_NAME, scoreProfile.name)
} }
fun setCurrentSchoolYear(schoolYear: SchoolYear) { fun setCurrentSchoolYear(schoolYear: SchoolYear) {
prefs.setInt(PreferenceKey.SCHOOL_YEAR_ID, schoolYear.yearId) prefs.setInt(PreferenceKey.SCHOOL_YEAR_ID, schoolYear.yearId)
.setString(PreferenceKey.SCHOOL_YEAR_NAME, schoolYear.year) .setString(PreferenceKey.SCHOOL_YEAR_NAME, schoolYear.year)
@@ -122,7 +121,6 @@ class QwarkRepository(app: Application) {
dao.update(SchoolYear(name, prefs.getCurrentSchoolYearId())) dao.update(SchoolYear(name, prefs.getCurrentSchoolYearId()))
setCurrentSchoolYear(SchoolYear(name, prefs.getCurrentSchoolYearId())) setCurrentSchoolYear(SchoolYear(name, prefs.getCurrentSchoolYearId()))
} }
fun updateScoreProfile(name: String) { fun updateScoreProfile(name: String) {
dao.update(ScoreProfile(name, prefs.getScoreProfileId())) dao.update(ScoreProfile(name, prefs.getScoreProfileId()))
setCurrentScoreProfile(ScoreProfile(name, prefs.getScoreProfileId())) setCurrentScoreProfile(ScoreProfile(name, prefs.getScoreProfileId()))
@@ -137,7 +135,6 @@ class QwarkRepository(app: Application) {
dao.deleteSchoolYear(prefs.getCurrentSchoolYearId()) dao.deleteSchoolYear(prefs.getCurrentSchoolYearId())
setCurrentSchoolYear(SchoolYear("", 0)) setCurrentSchoolYear(SchoolYear("", 0))
} }
fun deleteScoreProfile() { fun deleteScoreProfile() {
dao.deleteScoreProfile(prefs.getScoreProfileId()) dao.deleteScoreProfile(prefs.getScoreProfileId())
setCurrentScoreProfile(ScoreProfile("", 0)) setCurrentScoreProfile(ScoreProfile("", 0))
@@ -148,6 +145,7 @@ class QwarkRepository(app: Application) {
val allCoursesForToday: LiveData<List<Course>> = dao.getCoursesByDayType(getDayType(), prefs.getSchoolYear()) val allCoursesForToday: LiveData<List<Course>> = dao.getCoursesByDayType(getDayType(), prefs.getSchoolYear())
val allYears: LiveData<List<SchoolYear>> = dao.allYears val allYears: LiveData<List<SchoolYear>> = dao.allYears
val allScoreProfiles: LiveData<List<ScoreProfile>> = dao.allScoreProfiles val allScoreProfiles: LiveData<List<ScoreProfile>> = dao.allScoreProfiles
val allCoursesWithExams: LiveData<List<CourseExam>> = dao.getAllCoursesWithExams()
// get // get
fun getCourse(courseId: Int): CourseExam = dao.getCourse(courseId) fun getCourse(courseId: Int): CourseExam = dao.getCourse(courseId)
@@ -166,7 +164,7 @@ class QwarkRepository(app: Application) {
(participations.map { it.timesSpoken }.sum()) (participations.map { it.timesSpoken }.sum())
) )
} }
fun getDayType(): String = if (dayId in 1..5) days[dayId - 1] else days[1] private fun getDayType(): String = if (dayId in 1..5) days[dayId - 1] else days[1]
private fun getMaxFinalScoreId(increment: Boolean): Int { private fun getMaxFinalScoreId(increment: Boolean): Int {
if (increment) { if (increment) {
prefs.setInt(PreferenceKey.MAX_SCORE_PROFILE_ID, getMaxFinalScoreId(false) + 1) prefs.setInt(PreferenceKey.MAX_SCORE_PROFILE_ID, getMaxFinalScoreId(false) + 1)
@@ -1,8 +1,10 @@
package com.denizd.qwark.fragment package com.denizd.qwark.fragment
import android.app.TimePickerDialog
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.TimePicker
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import com.denizd.lawrence.util.viewBinding import com.denizd.lawrence.util.viewBinding
@@ -13,10 +15,12 @@ import com.denizd.qwark.sheet.ScoreProfileCreateSheet
import com.denizd.qwark.sheet.YearCreateSheet import com.denizd.qwark.sheet.YearCreateSheet
import com.denizd.qwark.databinding.SettingsFragmentBinding import com.denizd.qwark.databinding.SettingsFragmentBinding
import com.denizd.qwark.model.SchoolYear import com.denizd.qwark.model.SchoolYear
import com.denizd.qwark.util.toHourAndSecond
import com.denizd.qwark.util.toMillis
import com.denizd.qwark.viewmodel.SettingsViewModel import com.denizd.qwark.viewmodel.SettingsViewModel
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
class SettingsFragment : QwarkFragment(R.layout.settings_fragment) { class SettingsFragment : QwarkFragment(R.layout.settings_fragment), TimePickerDialog.OnTimeSetListener {
private val binding: SettingsFragmentBinding by viewBinding(SettingsFragmentBinding::bind) private val binding: SettingsFragmentBinding by viewBinding(SettingsFragmentBinding::bind)
private val viewModel: SettingsViewModel by viewModels() private val viewModel: SettingsViewModel by viewModels()
@@ -166,7 +170,7 @@ class SettingsFragment : QwarkFragment(R.layout.settings_fragment) {
viewModel.allScoreProfiles.observe(viewLifecycleOwner, Observer { scoreProfiles -> viewModel.allScoreProfiles.observe(viewLifecycleOwner, Observer { scoreProfiles ->
binding.scoreProfileDropdown.apply { binding.scoreProfileDropdown.apply {
setAdapter( setAdapter(
ArrayAdapter<String>( ArrayAdapter(
context, context,
R.layout.dropdown_item, R.layout.dropdown_item,
scoreProfiles.map { s -> s.name } scoreProfiles.map { s -> s.name }
@@ -203,6 +207,24 @@ class SettingsFragment : QwarkFragment(R.layout.settings_fragment) {
openBottomSheet(deleteScoreProfileSheet) openBottomSheet(deleteScoreProfileSheet)
} }
} }
setExamNotificationTimeText()
binding.setExamNotificationTimeButton.setOnClickListener {
val time = viewModel.getExamNotificationTime().toHourAndSecond()
TimePickerDialog(context, this, time.first, time.second, true).show()
}
}
override fun onTimeSet(view: TimePicker?, hourOfDay: Int, minute: Int) {
viewModel.setExamNotificationTime(Pair(hourOfDay, minute).toMillis())
setExamNotificationTimeText()
}
private fun setExamNotificationTimeText() {
val time = viewModel.getExamNotificationTime().toHourAndSecond()
val examNotificationTime = with (time) {
"${first.toString().padStart(2, '0')}:${second.toString().padStart(2, '0')}"
}
binding.examNotificationTimeTextView.text = getString(R.string.exam_notification_time_placeholder, examNotificationTime)
} }
fun copyCourses(yearId: Int) { fun copyCourses(yearId: Int) {
@@ -0,0 +1,7 @@
package com.denizd.qwark.util
fun Pair<Int, Int>.toMillis(): Long = (first.toLong() * 60 * 60 * 1000) + (second.toLong() * 60 * 1000)
fun Long.toHourAndSecond(): Pair<Int, Int> {
val minutes = (this / (1000 * 60)).toInt()
return Pair(minutes / 60, minutes % 60)
}
@@ -0,0 +1,66 @@
package com.denizd.qwark.util
import android.annotation.TargetApi
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.os.Build
import androidx.core.app.NotificationCompat
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.denizd.qwark.R
import com.denizd.qwark.activity.MainActivity
private const val notificationChannelId = "qwark_exam_notification"
class ExamNotificationWorker(private val context: Context, workerParams: WorkerParameters) : Worker(context.applicationContext, workerParams) {
override fun doWork(): Result {
sendNotification(course = inputData.getString("course") ?: "error")
return Result.success()
}
// TODO launch fragment from intent and launch the fragment for the course
private fun sendNotification(course: String) {
val openAppPending = PendingIntent.getActivity(
context, 0,
Intent(context, MainActivity::class.java).also { intent ->
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK + Intent.FLAG_ACTIVITY_CLEAR_TASK
}, 0
)
val notificationService = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotificationChannel(context, notificationService)
}
val notification = NotificationCompat.Builder(context, notificationChannelId)
// .setStyle(NotificationCompat.BigTextStyle())
.setContentTitle(context.getString(R.string.exam_reminder, course))
.setContentText(context.getString(R.string.writing_an_exam_today, course))
.setContentIntent(openAppPending)
.setAutoCancel(true)
.setColor(context.getColor(R.color.colorAccent))
.setSmallIcon(R.drawable.bolt)
.build()
notificationService.notify(42, notification)
}
@TargetApi(26)
private fun createNotificationChannel(context: Context, notificationManager: NotificationManager) {
if (!Dependencies.repo.prefs.getIsNotificationChannelCreated()) {
notificationManager.createNotificationChannel(NotificationChannel(
notificationChannelId, context.getString(R.string.exams), NotificationManager.IMPORTANCE_DEFAULT
).also { channel ->
channel.enableLights(true)
channel.lightColor = Color.GREEN
})
Dependencies.repo.prefs.setIsNotificationChannelCreated(true)
}
}
}
@@ -18,5 +18,9 @@ enum class PreferenceKey(val value: String) {
// Bools // Bools
SHOW_GRADE_AVERAGE("show_grade_average"), SHOW_GRADE_AVERAGE("show_grade_average"),
FIRST_LAUNCH("first_launch") FIRST_LAUNCH("first_launch"),
IS_NOTIFICATION_CHANNEL_CREATED("is_notification_channel_created"),
// Longs
EXAM_NOTIFICATION_TIME("exam_notification_time")
} }
@@ -12,6 +12,7 @@ class QwarkPreferences(context: Context) {
fun getString(key: PreferenceKey, default: String = ""): String = prefs.getString(key.value, default) ?: default fun getString(key: PreferenceKey, default: String = ""): String = prefs.getString(key.value, default) ?: default
fun getInt(key: PreferenceKey, default: Int = 0): Int = prefs.getInt(key.value, default) fun getInt(key: PreferenceKey, default: Int = 0): Int = prefs.getInt(key.value, default)
fun getBool(key: PreferenceKey, default: Boolean = false): Boolean = prefs.getBoolean(key.value, default) fun getBool(key: PreferenceKey, default: Boolean = false): Boolean = prefs.getBoolean(key.value, default)
fun getLong(key: PreferenceKey, default: Long = 0L): Long = prefs.getLong(key.value, default)
fun setString(key: PreferenceKey, value: String): QwarkPreferences { fun setString(key: PreferenceKey, value: String): QwarkPreferences {
edit.putString(key.value, value).apply() edit.putString(key.value, value).apply()
@@ -25,6 +26,10 @@ class QwarkPreferences(context: Context) {
edit.putBoolean(key.value, value).apply() edit.putBoolean(key.value, value).apply()
return this return this
} }
fun setLong(key: PreferenceKey, value: Long): QwarkPreferences {
edit.putLong(key.value, value).apply()
return this
}
// TODO remove all of these // TODO remove all of these
fun getShowGradeAverage(): Boolean = getBool(PreferenceKey.SHOW_GRADE_AVERAGE) fun getShowGradeAverage(): Boolean = getBool(PreferenceKey.SHOW_GRADE_AVERAGE)
@@ -40,6 +45,8 @@ class QwarkPreferences(context: Context) {
fun getFinalScoreId(): Int = getInt(PreferenceKey.SCORE_PROFILE_ID) fun getFinalScoreId(): Int = getInt(PreferenceKey.SCORE_PROFILE_ID)
fun getFirstLaunch(): Boolean = getBool(PreferenceKey.FIRST_LAUNCH) fun getFirstLaunch(): Boolean = getBool(PreferenceKey.FIRST_LAUNCH)
fun getCurrentSchoolYearId(): Int = getInt(PreferenceKey.SCHOOL_YEAR_ID) fun getCurrentSchoolYearId(): Int = getInt(PreferenceKey.SCHOOL_YEAR_ID)
fun getIsNotificationChannelCreated(): Boolean = getBool(PreferenceKey.IS_NOTIFICATION_CHANNEL_CREATED)
fun getExamNotificationTime(): Long = getLong(PreferenceKey.EXAM_NOTIFICATION_TIME, 25200000L)
fun setCourseSortType(value: Int) { setInt(PreferenceKey.COURSE_SORT_TYPE, value) } fun setCourseSortType(value: Int) { setInt(PreferenceKey.COURSE_SORT_TYPE, value) }
fun setParticipationDisplay(value: Int) { setInt(PreferenceKey.PARTICIPATION_DISPLAY, value) } fun setParticipationDisplay(value: Int) { setInt(PreferenceKey.PARTICIPATION_DISPLAY, value) }
@@ -48,4 +55,6 @@ class QwarkPreferences(context: Context) {
fun setFirstLaunch(value: Boolean) { setBool(PreferenceKey.FIRST_LAUNCH, value) } fun setFirstLaunch(value: Boolean) { setBool(PreferenceKey.FIRST_LAUNCH, value) }
fun setShowGradeAverage(value: Boolean) { setBool(PreferenceKey.SHOW_GRADE_AVERAGE, value) } fun setShowGradeAverage(value: Boolean) { setBool(PreferenceKey.SHOW_GRADE_AVERAGE, value) }
fun setGradeType(value: Int) { setInt(PreferenceKey.GRADE_TYPE, value) } fun setGradeType(value: Int) { setInt(PreferenceKey.GRADE_TYPE, value) }
fun setIsNotificationChannelCreated(value: Boolean) { setBool(PreferenceKey.IS_NOTIFICATION_CHANNEL_CREATED, value) }
fun setExamNotificationTime(value: Long) { setLong(PreferenceKey.EXAM_NOTIFICATION_TIME, value) }
} }
@@ -59,4 +59,6 @@ class MainViewModel(val app: Application) : QwarkViewModel(app) {
repo.prefs.setFirstLaunch(false) repo.prefs.setFirstLaunch(false)
} }
} }
fun getExamNotificationTime(): Long = repo.prefs.getExamNotificationTime()
} }
@@ -5,6 +5,7 @@ import androidx.lifecycle.LiveData
import com.denizd.qwark.database.QwarkClient import com.denizd.qwark.database.QwarkClient
import com.denizd.qwark.model.ScoreProfile import com.denizd.qwark.model.ScoreProfile
import com.denizd.qwark.model.SchoolYear import com.denizd.qwark.model.SchoolYear
import com.denizd.qwark.util.PreferenceKey
class SettingsViewModel(private val app: Application) : QwarkViewModel(app) { class SettingsViewModel(private val app: Application) : QwarkViewModel(app) {
@@ -21,6 +22,7 @@ class SettingsViewModel(private val app: Application) : QwarkViewModel(app) {
fun getCurrentSchoolYearId(): Int = repo.prefs.getCurrentSchoolYearId() fun getCurrentSchoolYearId(): Int = repo.prefs.getCurrentSchoolYearId()
fun getParticipationDisplay(): Int = repo.prefs.getParticipationDisplay() fun getParticipationDisplay(): Int = repo.prefs.getParticipationDisplay()
fun getParticipationDay(): Int = repo.prefs.getParticipationDay() fun getParticipationDay(): Int = repo.prefs.getParticipationDay()
fun getExamNotificationTime(): Long = repo.prefs.getExamNotificationTime()
// Preference setters // Preference setters
fun setAppTheme(value: Int) { repo.prefs.setAppTheme(value) } fun setAppTheme(value: Int) { repo.prefs.setAppTheme(value) }
@@ -31,6 +33,7 @@ class SettingsViewModel(private val app: Application) : QwarkViewModel(app) {
fun updateSchoolYear(schoolYear: SchoolYear) { repo.setCurrentSchoolYear(schoolYear) } fun updateSchoolYear(schoolYear: SchoolYear) { repo.setCurrentSchoolYear(schoolYear) }
fun setParticipationDisplay(value: Int) { repo.prefs.setParticipationDisplay(value) } fun setParticipationDisplay(value: Int) { repo.prefs.setParticipationDisplay(value) }
fun setParticipationDay(value: Int) { repo.prefs.setParticipationDay(value) } fun setParticipationDay(value: Int) { repo.prefs.setParticipationDay(value) }
fun setExamNotificationTime(value: Long) = repo.prefs.setExamNotificationTime(value)
// Database functions // Database functions
fun insert(schoolYear: SchoolYear) = doAsync { repo.insert(schoolYear) } fun insert(schoolYear: SchoolYear) = doAsync { repo.insert(schoolYear) }
+8 -4
View File
@@ -1,5 +1,9 @@
<vector android:height="250dp" android:viewportHeight="80.79835" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:viewportWidth="53.145966" android:width="165dp" xmlns:android="http://schemas.android.com/apk/res/android"> android:width="512dp"
<path android:fillColor="@color/colorSplashLogo" android:height="512dp"
android:pathData="m13.1664,80.416c-0.3983,-0.2161 -0.8014,-0.7006 -0.8958,-1.0765 -0.1244,-0.4955 1.4236,-5.6423 5.6281,-18.7126C23.6983,42.5979 23.6983,42.5979 12.4059,42.4656 1.7759,42.3411 1.0807,42.3038 0.5567,41.8293 0.2087,41.5142 0,41.0033 0,40.4664c0,-1.3788 12.2864,-39.2443 12.9487,-39.9066 0.5548,-0.5548 0.6746,-0.5598 13.6215,-0.5598 12.2693,0 13.0941,0.0293 13.5949,0.4825 1.1973,1.0835 1.1729,1.1538 -4.7012,13.5387 -3.0613,6.4544 -5.5659,11.8038 -5.5659,11.8877 0,0.0839 4.9799,0.1525 11.0664,0.1525 11.0664,0 11.0664,0 11.6606,0.6325 0.411,0.4375 0.568,0.8836 0.5091,1.4469 -0.0614,0.5874 -5.2732,7.9334 -18.7031,26.3618 -10.2399,14.0511 -18.8687,25.7229 -19.175,25.9375 -0.6914,0.4843 -1.1627,0.4788 -2.0895,-0.024zM36.4322,30.0933C25.9694,30.0251 25.8162,30.0163 25.2154,29.4519 24.8587,29.1168 24.6063,28.5702 24.6063,28.133c0,-0.4239 2.39,-5.7794 5.529,-12.3893 5.529,-11.6426 5.529,-11.6426 -4.4337,-11.6426 -9.9627,0 -9.9627,0 -15.3537,16.7349 -2.965,9.2042 -5.4434,16.88 -5.5075,17.0574 -0.0902,0.2497 2.4609,0.3393 11.3035,0.3969 11.42,0.0743 11.42,0.0743 11.9256,0.699 0.2781,0.3435 0.5056,0.9045 0.5056,1.2466 0,0.3421 -1.8455,6.3614 -4.101,13.3763 -2.2556,7.0149 -4.101,12.8701 -4.101,13.0115 0,0.1414 6.0001,-8.0045 13.3335,-18.102C47.0398,30.1625 47.0398,30.1625 36.4322,30.0933Z" android:strokeWidth="0.26458335"/> android:viewportWidth="512"
android:viewportHeight="512.0014">
<path
android:fillColor="@color/colorText"
android:pathData="m406,211h-124.145l107.168,-188.559c2.652,-4.645 2.637,-10.344 -0.043,-14.973 -2.695,-4.625 -7.633,-7.469 -12.98,-7.469h-180c-6.457,0 -12.188,4.133 -14.223,10.254l-90,271c-1.539,4.57 -0.762,9.609 2.051,13.52 2.828,3.914 7.355,6.227 12.172,6.227h127.254l-81.035,190.098c-2.902,6.754 -0.469,14.621 5.742,18.559 6.109,3.906 14.316,2.879 19.246,-2.691l240,-271c3.926,-4.41 4.895,-10.727 2.477,-16.102 -2.418,-5.391 -7.777,-8.863 -13.684,-8.863zM406,211"/>
</vector> </vector>
@@ -1,170 +1,74 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector
android:width="108dp"
android:height="108dp" android:height="108dp"
android:width="108dp"
android:viewportHeight="108"
android:viewportWidth="108" android:viewportWidth="108"
android:viewportHeight="108"> xmlns:android="http://schemas.android.com/apk/res/android">
<path <path android:fillColor="#3DDC84"
android:fillColor="#008577"
android:pathData="M0,0h108v108h-108z"/> android:pathData="M0,0h108v108h-108z"/>
<path <path android:fillColor="#00000000" android:pathData="M9,0L9,108"
android:fillColor="#00000000" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:pathData="M9,0L9,108" <path android:fillColor="#00000000" android:pathData="M19,0L19,108"
android:strokeWidth="0.8" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeColor="#33FFFFFF" /> <path android:fillColor="#00000000" android:pathData="M29,0L29,108"
<path android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:fillColor="#00000000" <path android:fillColor="#00000000" android:pathData="M39,0L39,108"
android:pathData="M19,0L19,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeWidth="0.8" <path android:fillColor="#00000000" android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF" /> android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path <path android:fillColor="#00000000" android:pathData="M59,0L59,108"
android:fillColor="#00000000" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:pathData="M29,0L29,108" <path android:fillColor="#00000000" android:pathData="M69,0L69,108"
android:strokeWidth="0.8" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeColor="#33FFFFFF" /> <path android:fillColor="#00000000" android:pathData="M79,0L79,108"
<path android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:fillColor="#00000000" <path android:fillColor="#00000000" android:pathData="M89,0L89,108"
android:pathData="M39,0L39,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeWidth="0.8" <path android:fillColor="#00000000" android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF" /> android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path <path android:fillColor="#00000000" android:pathData="M0,9L108,9"
android:fillColor="#00000000" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:pathData="M49,0L49,108" <path android:fillColor="#00000000" android:pathData="M0,19L108,19"
android:strokeWidth="0.8" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeColor="#33FFFFFF" /> <path android:fillColor="#00000000" android:pathData="M0,29L108,29"
<path android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:fillColor="#00000000" <path android:fillColor="#00000000" android:pathData="M0,39L108,39"
android:pathData="M59,0L59,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeWidth="0.8" <path android:fillColor="#00000000" android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF" /> android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path <path android:fillColor="#00000000" android:pathData="M0,59L108,59"
android:fillColor="#00000000" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:pathData="M69,0L69,108" <path android:fillColor="#00000000" android:pathData="M0,69L108,69"
android:strokeWidth="0.8" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeColor="#33FFFFFF" /> <path android:fillColor="#00000000" android:pathData="M0,79L108,79"
<path android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:fillColor="#00000000" <path android:fillColor="#00000000" android:pathData="M0,89L108,89"
android:pathData="M79,0L79,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeWidth="0.8" <path android:fillColor="#00000000" android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF" /> android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path <path android:fillColor="#00000000" android:pathData="M19,29L89,29"
android:fillColor="#00000000" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:pathData="M89,0L89,108" <path android:fillColor="#00000000" android:pathData="M19,39L89,39"
android:strokeWidth="0.8" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeColor="#33FFFFFF" /> <path android:fillColor="#00000000" android:pathData="M19,49L89,49"
<path android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:fillColor="#00000000" <path android:fillColor="#00000000" android:pathData="M19,59L89,59"
android:pathData="M99,0L99,108" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeWidth="0.8" <path android:fillColor="#00000000" android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF" /> android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path <path android:fillColor="#00000000" android:pathData="M19,79L89,79"
android:fillColor="#00000000" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:pathData="M0,9L108,9" <path android:fillColor="#00000000" android:pathData="M29,19L29,89"
android:strokeWidth="0.8" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeColor="#33FFFFFF" /> <path android:fillColor="#00000000" android:pathData="M39,19L39,89"
<path android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:fillColor="#00000000" <path android:fillColor="#00000000" android:pathData="M49,19L49,89"
android:pathData="M0,19L108,19" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeWidth="0.8" <path android:fillColor="#00000000" android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF" /> android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path <path android:fillColor="#00000000" android:pathData="M69,19L69,89"
android:fillColor="#00000000" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:pathData="M0,29L108,29" <path android:fillColor="#00000000" android:pathData="M79,19L79,89"
android:strokeWidth="0.8" android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector> </vector>
+1 -1
View File
@@ -8,7 +8,7 @@
<item <item
android:drawable="@drawable/bolt" android:drawable="@drawable/bolt"
android:gravity="center" android:gravity="center"
android:width="120dp" android:width="184dp"
android:height="184dp" android:height="184dp"
android:scaleType="centerInside"> android:scaleType="centerInside">
</item> </item>
+2 -1
View File
@@ -128,7 +128,8 @@
<FrameLayout <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:animateLayoutChanges="false"> android:animateLayoutChanges="false"
android:visibility="gone">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/splash_screen" android:id="@+id/splash_screen"
+31 -3
View File
@@ -97,7 +97,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:text="@string/grades" android:text="@string/courses"
android:textColor="@color/colorAccent" android:textColor="@color/colorAccent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
@@ -106,6 +106,34 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<LinearLayout
style="@style/SelectableItemBackground"
android:id="@+id/set_exam_notification_time_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:paddingVertical="8dp"
android:paddingHorizontal="16dp"
android:focusable="true"
android:clickable="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/set_exam_notification_time"/>
<TextView
android:id="@+id/exam_notification_time_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/colorHint"
android:textSize="12sp"/>
</LinearLayout>
<TextView <TextView
android:id="@+id/show_grade_average_textview" android:id="@+id/show_grade_average_textview"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@@ -114,7 +142,7 @@
android:text="@string/show_grade_average_title" android:text="@string/show_grade_average_title"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toBottomOf="@+id/set_exam_notification_time_button"
app:layout_constraintStart_toStartOf="parent"/> app:layout_constraintStart_toStartOf="parent"/>
<TextView <TextView
@@ -133,7 +161,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toBottomOf="@+id/set_exam_notification_time_button"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/> app:layout_constraintEnd_toEndOf="parent"/>
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/> <background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/> <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon> </adaptive-icon>
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/> <background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@mipmap/ic_launcher_foreground"/> <foreground android:drawable="@mipmap/ic_launcher_foreground"/>
</adaptive-icon> </adaptive-icon>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 954 B

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 13 KiB

+5
View File
@@ -16,6 +16,9 @@
<string name="alert_create_school_year_title">Erstelle ein Schuljahr</string> <string name="alert_create_school_year_title">Erstelle ein Schuljahr</string>
<string name="alert_create_school_year_desc">Bevor du Kurse und Abschlussnoten hinzufügst, gehe in die Einstellungen und erstelle ein Schuljahr und ein Abschlussprofil!</string> <string name="alert_create_school_year_desc">Bevor du Kurse und Abschlussnoten hinzufügst, gehe in die Einstellungen und erstelle ein Schuljahr und ein Abschlussprofil!</string>
<string name="to_be_implemented">Wird noch hinzugefügt</string> <string name="to_be_implemented">Wird noch hinzugefügt</string>
<string name="exams">Klausuren</string>
<string name="exam_reminder">Klausurerinnerung: %s</string>
<string name="writing_an_exam_today">Heute schreibst du eine Klausur in %s!</string>
<!-- CourseFragment.kt --> <!-- CourseFragment.kt -->
<string name="course">Kurs</string> <string name="course">Kurs</string>
@@ -145,6 +148,8 @@
<!-- SettingsFragment.kt --> <!-- SettingsFragment.kt -->
<string name="settings">Einstellungen</string> <string name="settings">Einstellungen</string>
<string name="set_exam_notification_time">Stelle Zeit für Klausurbenachrichtigung</string>
<string name="exam_notification_time_placeholder">Derzeit eingestellt auf %s</string>
<string name="course_sort_type">Sortiere Kurse nach</string> <string name="course_sort_type">Sortiere Kurse nach</string>
<string-array name="course_sort_type_options"> <string-array name="course_sort_type_options">
<item>Zeit hinzugefügt (aufsteigend)</item> <item>Zeit hinzugefügt (aufsteigend)</item>
+5
View File
@@ -18,6 +18,9 @@
<string name="to_be_implemented">To be implemented</string> <string name="to_be_implemented">To be implemented</string>
<string name="powered_by_qwark" translatable="false">Powered by Qwark</string> <string name="powered_by_qwark" translatable="false">Powered by Qwark</string>
<string name="made_by_deniz" translatable="false">Made by Deniz</string> <string name="made_by_deniz" translatable="false">Made by Deniz</string>
<string name="exams">Exams</string>
<string name="exam_reminder">Exam reminder: %s</string>
<string name="writing_an_exam_today">You\'re writing an exam in %s today!</string>
<string-array name="greetings"> <string-array name="greetings">
<item>Hello %s!</item> <item>Hello %s!</item>
@@ -211,6 +214,8 @@
<!-- SettingsFragment.kt --> <!-- SettingsFragment.kt -->
<string name="settings">Settings</string> <string name="settings">Settings</string>
<string name="set_exam_notification_time">Set exam notification time</string>
<string name="exam_notification_time_placeholder">Currently set to %s</string>
<string name="course_sort_type">Sort courses by</string> <string name="course_sort_type">Sort courses by</string>
<string-array name="course_sort_type_options"> <string-array name="course_sort_type_options">
<item>Time added (ascending)</item> <item>Time added (ascending)</item>