Fragments now get data class instances from Room instead of having them passed through a Bundle object; ClassSessionSheet.kt now keeps screen turned on; renamed *BottomSheet.kt to *Sheet.kt

This commit is contained in:
Deniz Düzgören
2020-02-22 08:02:01 +01:00
parent bbec19e79c
commit 9ed5d7bb5f
64 changed files with 436 additions and 471 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+7 -7
View File
@@ -70,21 +70,21 @@
<output-test url="file://$MODULE_DIR$/../../../app/build/intermediates/javac/debugUnitTest/classes" />
<exclude-output />
<content url="file://$MODULE_DIR$/../../../app">
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/ap_generated_sources/debug/out" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/source/kapt/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/ap_generated_sources/debug/out" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/aidl_source_output_dir/debug/out" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/source/kaptKotlin/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/renderscript_source_output_dir/debug/out" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/source/kaptKotlin/debug" isTestSource="false" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/res/rs/debug" type="java-resource" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/source/kapt/debugAndroidTest" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/ap_generated_sources/debugAndroidTest/out" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/aidl_source_output_dir/debugAndroidTest/out" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/source/kapt/debugAndroidTest" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/renderscript_source_output_dir/debugAndroidTest/out" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/res/rs/androidTest/debug" type="java-test-resource" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/ap_generated_sources/debugUnitTest/out" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/source/kapt/debugUnitTest" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/build/generated/ap_generated_sources/debugUnitTest/out" isTestSource="true" generated="true" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/src/debug/res" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/src/debug/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/../../../app/src/debug/assets" type="java-resource" />
@@ -134,11 +134,11 @@
<orderEntry type="module-library">
<library name="Gradle: kaptGeneratedClasses">
<CLASSES>
<root url="file://$MODULE_DIR$/../../../app/build/tmp/kapt3/classes/releaseUnitTest" />
<root url="file://$MODULE_DIR$/../../../app/build/tmp/kapt3/classes/release" />
<root url="file://$MODULE_DIR$/../../../app/build/tmp/kapt3/classes/debugAndroidTest" />
<root url="file://$MODULE_DIR$/../../../app/build/tmp/kapt3/classes/debug" />
<root url="file://$MODULE_DIR$/../../../app/build/tmp/kapt3/classes/debugUnitTest" />
<root url="file://$MODULE_DIR$/../../../app/build/tmp/kapt3/classes/release" />
<root url="file://$MODULE_DIR$/../../../app/build/tmp/kapt3/classes/releaseUnitTest" />
</CLASSES>
<JAVADOC />
<SOURCES />
Generated
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
+1
View File
@@ -56,6 +56,7 @@ dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
implementation 'com.shawnlin:number-picker:2.4.8'
@@ -1,46 +1,39 @@
package com.denizd.qwark.activity
import android.Manifest
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.TextView
import androidx.core.app.ActivityCompat
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentTransaction
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ViewModelProvider
import com.denizd.qwark.R
import com.denizd.qwark.databinding.ActivityMainBinding
import com.denizd.qwark.fragment.*
import com.denizd.qwark.fragment.CourseFragment
import com.denizd.qwark.fragment.ParticipationFragment
import com.denizd.qwark.viewmodel.MainViewModel
import com.google.android.material.appbar.AppBarLayout
import com.google.android.material.bottomnavigation.BottomNavigationView
internal class MainActivity : AppCompatActivity(R.layout.activity_main) {
class MainActivity : FragmentActivity() {
private lateinit var toolbarTitle: TextView
private lateinit var bottomNavigationView: BottomNavigationView
private lateinit var viewModel: MainViewModel
private var _binding: ActivityMainBinding? = null
private val binding: ActivityMainBinding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setTheme(R.style.AppTheme)
_binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 42)
// ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 42)
viewModel = ViewModelProvider(this)[MainViewModel::class.java]
viewModel.applyTheme(window, this)
viewModel.checkForFirstTimeYearNotice(this)
val actionBar = findViewById<AppBarLayout>(R.id.app_bar_layout)
toolbarTitle = findViewById(R.id.toolbarTxt)
bottomNavigationView = findViewById(R.id.bottom_nav)
findViewById<AppBarLayout>(R.id.app_bar_layout).also { appBarLayout ->
binding.appBarLayout.also { appBarLayout ->
appBarLayout.setOnApplyWindowInsetsListener { _, insets ->
(appBarLayout.layoutParams as ViewGroup.MarginLayoutParams)
.topMargin = insets.systemWindowInsetTop
@@ -48,6 +41,7 @@ internal class MainActivity : AppCompatActivity(R.layout.activity_main) {
}
}
// TODO remove this translucent app bar layout stuff, it's hard to maintain
window.decorView.systemUiVisibility = if (resources.getBoolean(R.bool.isLight)) {
View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
} else {
@@ -59,8 +53,8 @@ internal class MainActivity : AppCompatActivity(R.layout.activity_main) {
}
window.statusBarColor = Color.TRANSPARENT
bottomNavigationView.setOnNavigationItemSelectedListener { item ->
actionBar.setExpanded(true)
binding.bottomNav.setOnNavigationItemSelectedListener { item ->
binding.appBarLayout.setExpanded(true)
loadFragment(viewModel.getFragmentType(item.itemId))
}
@@ -89,11 +83,16 @@ internal class MainActivity : AppCompatActivity(R.layout.activity_main) {
override fun onResume() {
super.onResume()
if (supportFragmentManager.fragments.size == 0) {
bottomNavigationView.selectedItemId = R.id.courses
binding.bottomNav.selectedItemId = R.id.courses
loadFragment(viewModel.getFragmentType(R.id.courses))
}
}
override fun onDestroy() {
super.onDestroy()
_binding = null
}
private fun loadFragment(type: String): Boolean {
val fragment = supportFragmentManager.findFragmentByTag(type) ?: viewModel.getFragment(type)
@@ -101,8 +100,10 @@ internal class MainActivity : AppCompatActivity(R.layout.activity_main) {
return false
}
supportFragmentManager.beginTransaction().replace(R.id.fragment_container, fragment, type)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN).commit()
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, fragment, type)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit()
// with (supportFragmentManager) {
// beginTransaction()
@@ -118,8 +119,8 @@ internal class MainActivity : AppCompatActivity(R.layout.activity_main) {
// Log.d("TAG2", "${supportFragmentManager.}") // supportFragmentManager.fragments[0].tag} ${supportFragmentManager.fragments[0].javaClass.simpleName
when (supportFragmentManager.fragments[0].tag) {
"GradeFragment", "ParticipationCourseFragment" -> {
bottomNavigationView.visibility = View.INVISIBLE
findViewById<View>(R.id.view).visibility = View.INVISIBLE
binding.bottomNav.visibility = View.INVISIBLE
binding.view.visibility = View.INVISIBLE
super.onBackPressed()
}
"NoteFragment" -> {
@@ -128,8 +129,8 @@ internal class MainActivity : AppCompatActivity(R.layout.activity_main) {
}
}
else -> {
bottomNavigationView.visibility = View.VISIBLE
findViewById<View>(R.id.view).visibility = View.VISIBLE
binding.bottomNav.visibility = View.VISIBLE
binding.view.visibility = View.VISIBLE
super.onBackPressed()
}
}
@@ -12,6 +12,7 @@ import com.denizd.qwark.util.QwarkUtil
import com.denizd.qwark.model.Course
import com.denizd.qwark.model.CourseExam
import com.denizd.qwark.util.getUserDefinedAverage
import com.denizd.qwark.util.round
import com.denizd.qwark.util.roundToInt
class CourseAdapter(private var courses: List<CourseExam>,
@@ -69,14 +70,16 @@ class CourseAdapter(private var courses: List<CourseExam>,
else -> context.getString(R.string.average_grade_placeholder, currentItem.average.getUserDefinedAverage(gradeType))
}
}
var timeLeft = ((currentItem.examTime.toDouble() - QwarkUtil.timeAtMidnight.toDouble()) / (1000.0 * 60.0 * 60.0 * 24.0)).roundToInt()
val examText = when (timeLeft) {
val examText = when (val timeLeft = ((currentItem.examTime.toDouble() - QwarkUtil.timeAtMidnight.toDouble()) / (1000.0 * 60.0 * 60.0 * 24.0)).roundToInt()) {
0 -> context.getString(R.string.exam_today_placeholder)
else -> {
when {
timeLeft > 7 -> {
timeLeft /= 7
context.resources.getQuantityString(R.plurals.exam_weeks_placeholder, timeLeft, timeLeft.toString())
context.resources.getQuantityString(
R.plurals.exam_weeks_placeholder,
2,
(timeLeft.toDouble() / 7.0).round(1).toString()
)
}
timeLeft in 1..7 -> context.resources.getQuantityString(R.plurals.exam_days_placeholder, timeLeft, timeLeft.toString())
else -> ""
@@ -53,7 +53,16 @@ class ParticipationAdapter(private var participations: List<Participation>, priv
}
}
))
holder.time.text = QwarkUtil.getSimpleDateTimeFormat().format(Date(currentItem.time))
holder.time.text = buildString {
append(QwarkUtil.getSimpleDateTimeFormat().format(Date(currentItem.time)))
// TODO this checks the time on fragment launch, but it doesn't change, even if the time has passed
append(if (currentItem.time > System.currentTimeMillis() - 1000 * 60 * 90) {
holder.time.context.getString(R.string.participation_resumable)
} else {
""
})
}
holder.participationText.text = holder.participationText.context.getString(
R.string.participation_placeholder,
currentItem.timesHandRaised.toString(),
@@ -21,4 +21,6 @@ internal class CourseRepository(app: Application) {
fun getCoursesByYearId(yearId: Int): LiveData<List<CourseExam>> = dao.getCoursesByYearId(yearId)
fun getAveragesForCourses(courseId: Int): List<HistoricalAvg> = dao.getAveragesForCourses(courseId)
fun getCourse(courseId: Int): CourseExam = dao.getCourse(courseId)[0]
}
@@ -42,6 +42,6 @@ class FinalsRepository(app: Application) {
fun getAllCourses() = dao.getAllCourseExams()
fun getCourse(courseId: Int) = dao.getCourse(courseId)[0]
fun getFinalGrade(finalGradeId: Int) = dao.getFinalGrade(finalGradeId)[0]
fun update(finalGrade: FinalGrade) { dao.update(finalGrade) }
}
@@ -27,4 +27,5 @@ class GradeRepository(app: Application) {
}
fun getGradesByForeignKey(courseId: Int): LiveData<List<Grade>> = dao.getGradesByForeignKey(courseId)
fun getGrade(gradeId: Int) = dao.getGrade(gradeId)[0]
}
@@ -16,4 +16,5 @@ class NoteRepository(app: Application) {
fun update(note: Note) { dao.update(note) }
fun updateDismissed(newDismissedStatus: Boolean, noteId: Int) { dao.updateDismissed(newDismissedStatus, noteId) }
fun delete(noteId: Int) { dao.deleteNote(noteId) }
fun getNote(noteId: Int) = dao.getNote(noteId)[0]
}
@@ -3,14 +3,12 @@ package com.denizd.qwark.database
import android.app.Application
import android.util.Log
import androidx.lifecycle.LiveData
import com.denizd.qwark.util.QwarkPreferences
import com.denizd.qwark.model.Course
import com.denizd.qwark.model.CourseExam
import com.denizd.qwark.model.Participation
import com.denizd.qwark.model.SchoolDay
import com.denizd.qwark.util.QwarkUtil
import com.denizd.qwark.util.round
import com.denizd.qwark.util.roundToInt
import com.denizd.qwark.util.*
import com.denizd.qwark.util.QwarkPreferences
import java.util.*
class ParticipationRepository(app: Application) {
@@ -46,8 +44,7 @@ class ParticipationRepository(app: Application) {
fun getDayType(): String = if (dayId in 1..5) days[dayId - 1] else days[1]
fun getDays(): List<SchoolDay> = dao.getDays(prefs.getSchoolYear())
fun getCourses(): List<CourseExam> = QwarkUtil.getCoursesSorted(
dao.getCoursesByYearIdAsList(prefs.getSchoolYear()),
fun getCourses(): List<CourseExam> = dao.getCoursesByYearIdAsList(prefs.getSchoolYear()).getSorted(
prefs.getCourseSortType()
)
fun link(courseId: Int) { dao.link(courseId, getDayType(), prefs.getSchoolYear()) }
@@ -67,6 +64,11 @@ class ParticipationRepository(app: Application) {
)
}
fun delete(participation: Participation) { dao.delete(participation) }
fun updateParticipation(participation: String, courseId: Int) { dao.updateParticipation(participation, courseId) }
fun updateParticipation(participation: String, courseId: Int) {
dao.updateParticipation(participation, courseId)
}
fun updateParticipation(timesHandRaised: Int, timesSpoken: Int, participationId: Int) {
dao.updateParticipation(timesHandRaised, timesSpoken, participationId)
}
fun getSchoolYearName() = prefs.getSchoolYearName()
}
@@ -47,6 +47,9 @@ interface QwarkDao {
@Query("UPDATE course SET participation = :participation WHERE course_id = :courseId")
fun updateParticipation(participation: String, courseId: Int)
@Query("UPDATE participation SET times_hand_raised = :timesHandRaised, times_spoken = :timesSpoken WHERE participation_id = :participationId")
fun updateParticipation(timesHandRaised: Int, timesSpoken: Int, participationId: Int)
// grades
@get:Query("SELECT * FROM grade ORDER BY time")
@@ -64,6 +67,9 @@ interface QwarkDao {
@Query("DELETE FROM grade WHERE grade_id = :gradeId")
fun deleteGrade(gradeId: Int)
@Query("SELECT * FROM grade WHERE grade_id = :gradeId")
fun getGrade(gradeId: Int): List<Grade>
// notes
@get:Query("SELECT * FROM note ORDER BY time DESC")
@@ -90,6 +96,9 @@ interface QwarkDao {
@Query("SELECT DISTINCT category FROM note")
fun getAllCategories(): List<String>
@Query("SELECT * FROM note WHERE note_id = :noteId")
fun getNote(noteId: Int): List<Note>
// historical averages
@get:Query("SELECT * FROM historical_avg ORDER BY course_id DESC")
@@ -155,6 +164,9 @@ interface QwarkDao {
@Insert
fun insertAll(finalGrades: Array<FinalGrade>)
@Query("SELECT * FROM final_grade WHERE final_grade_id = :finalGradeId")
fun getFinalGrade(finalGradeId: Int): List<FinalGrade>
// school days
@Insert
@@ -174,7 +186,7 @@ interface QwarkDao {
@Query("DELETE FROM course_schoolday_relation WHERE relation_id = :relationId")
fun removeLink(relationId: Int)
@Query("SELECT * FROM participation WHERE course_id = :courseId")
@Query("SELECT * FROM participation WHERE course_id = :courseId ORDER BY time DESC")
fun getAllParticipationsForCourse(courseId: Int): LiveData<List<Participation>>
@Insert
@@ -8,44 +8,44 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentTransaction
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.denizd.qwark.R
import com.denizd.qwark.adapter.CourseAdapter
import com.denizd.qwark.sheet.ConfirmDeletionBottomSheet
import com.denizd.qwark.sheet.CourseCreateBottomSheet
import com.denizd.qwark.sheet.CourseOptionsBottomSheet
import com.denizd.qwark.util.QwarkUtil
import com.denizd.qwark.sheet.ConfirmDeletionSheet
import com.denizd.qwark.sheet.CourseCreateSheet
import com.denizd.qwark.sheet.CourseOptionsSheet
import com.denizd.qwark.databinding.*
import com.denizd.qwark.sheet.HistoricalAverageBottomSheet
import com.denizd.qwark.sheet.HistoricalAverageSheet
import com.denizd.qwark.model.Course
import com.denizd.qwark.model.CourseExam
import com.denizd.qwark.util.calculateTotalAverage
import com.denizd.qwark.util.getSorted
import com.denizd.qwark.viewmodel.CourseViewModel
import com.google.android.material.snackbar.Snackbar
import java.lang.NumberFormatException
internal class CourseFragment : QwarkFragment(), CourseAdapter.CourseClickListener {
class CourseFragment : QwarkFragment(), CourseAdapter.CourseClickListener {
private var _binding: PaddedRecyclerViewBinding? = null
private val binding: PaddedRecyclerViewBinding get() = _binding!!
private lateinit var viewModel: CourseViewModel
private val viewModel: CourseViewModel by viewModels()
private lateinit var recyclerViewAdapter: CourseAdapter
private var scrollPosition: Parcelable? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this)[CourseViewModel::class.java]
recyclerViewAdapter = CourseAdapter(ArrayList(), this, viewModel.getGradeType())
viewModel.allCourses.observe(this, Observer { courses ->
val c = QwarkUtil.getCoursesSorted(courses, viewModel.getCourseSortType())
recyclerViewAdapter.setCourses(c)
recyclerViewAdapter.setCourses(courses.getSorted(viewModel.getCourseSortType()))
if (scrollPosition == null) {
binding.recyclerView.scrollToPosition(0)
binding.recyclerView.scheduleLayoutAnimation()
binding.recyclerView.apply {
scrollToPosition(0)
scheduleLayoutAnimation()
}
} else {
binding.recyclerView.layoutManager?.onRestoreInstanceState(scrollPosition)
}
@@ -105,16 +105,7 @@ internal class CourseFragment : QwarkFragment(), CourseAdapter.CourseClickListen
override fun onResume() {
super.onResume()
binding.recyclerView.apply {
applyPadding(verticalPadding = 4)
/**
* On first app launch, setting the padding will not scroll the recycler view items
* down. This is a workaround to scroll the recycler view down programmatically.
*/
// TODO this actually doesn't do anything
// if (!QwarkUtil.hasAppLaunched) {
// scrollToPosition(0)
// QwarkUtil.hasAppLaunched = true
// }
applyPadding(horizontalPadding = 4)
}
}
@@ -142,8 +133,8 @@ internal class CourseFragment : QwarkFragment(), CourseAdapter.CourseClickListen
}
private fun createOptionsDialog(course: CourseExam) {
openBottomSheet(CourseOptionsBottomSheet().also { sheet ->
QwarkUtil.putCourseInBundle(sheet, course)
openBottomSheet(CourseOptionsSheet().also { sheet ->
sheet.arguments = Bundle().apply { putInt("courseId", course.courseId) }
})
}
@@ -162,7 +153,7 @@ internal class CourseFragment : QwarkFragment(), CourseAdapter.CourseClickListen
fun getAveragesForCourse(courseId: Int) = viewModel.getAveragesForCourses(courseId)
fun createHistoryDialog(courseId: Int, course: String) {
openBottomSheet(HistoricalAverageBottomSheet().also { sheet ->
openBottomSheet(HistoricalAverageSheet().also { sheet ->
sheet.arguments = Bundle(2).apply {
putString("courseName", course)
putInt("courseId", courseId)
@@ -171,18 +162,20 @@ internal class CourseFragment : QwarkFragment(), CourseAdapter.CourseClickListen
}
fun createCourseDialog(course: CourseExam? = null) {
openBottomSheet(CourseCreateBottomSheet().also { sheet ->
if (course != null) QwarkUtil.putCourseInBundle(sheet, course)
openBottomSheet(CourseCreateSheet().also { sheet ->
if (course != null) sheet.arguments = Bundle().apply { putInt("courseId", course.courseId) }
})
}
fun deleteCourse(course: Course) {
openBottomSheet(
ConfirmDeletionBottomSheet(
ConfirmDeletionSheet(
getString(R.string.delete_course_and_data_confirmation, course.name)
) {
viewModel.delete(course)
}
)
}
fun getCourse(courseId: Int): CourseExam = viewModel.getCourse(courseId)
}
@@ -3,27 +3,26 @@ package com.denizd.qwark.fragment
import android.content.res.Configuration
import android.os.Bundle
import android.os.Parcelable
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentTransaction
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import com.denizd.qwark.R
import com.denizd.qwark.adapter.FinalGradeAdapter
import com.denizd.qwark.sheet.ConfirmDeletionBottomSheet
import com.denizd.qwark.sheet.FinalsCreateBottomSheet
import com.denizd.qwark.sheet.FinalsOptionsBottomSheet
import com.denizd.qwark.sheet.ConfirmDeletionSheet
import com.denizd.qwark.sheet.FinalsCreateSheet
import com.denizd.qwark.sheet.FinalsOptionsSheet
import com.denizd.qwark.databinding.FinalsFragmentBinding
import com.denizd.qwark.sheet.FinalsLinkBottomSheet
import com.denizd.qwark.util.QwarkUtil
import com.denizd.qwark.sheet.FinalsLinkSheet
import com.denizd.qwark.model.FinalGrade
import com.denizd.qwark.viewmodel.FinalsViewModel
import com.google.android.material.snackbar.Snackbar
internal class FinalsFragment : QwarkFragment(), FinalGradeAdapter.FinalGradeClickListener {
class FinalsFragment : QwarkFragment(), FinalGradeAdapter.FinalGradeClickListener {
private lateinit var viewModel: FinalsViewModel
private var _binding: FinalsFragmentBinding? = null
@@ -44,7 +43,7 @@ internal class FinalsFragment : QwarkFragment(), FinalGradeAdapter.FinalGradeCli
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this)[FinalsViewModel::class.java]
viewModel.updateLinkedGrades {
viewModel.allFinalGrades?.observe(this, Observer { finalGrades ->
viewModel.allFinalGrades.observe(this, Observer { finalGrades ->
// createOverview(finalGrades, view.rootView) // TODO export to bitmap
if (basicScrollPosition == null) {
binding.basicCoursesRecyclerview.scheduleLayoutAnimation()
@@ -67,7 +66,7 @@ internal class FinalsFragment : QwarkFragment(), FinalGradeAdapter.FinalGradeCli
binding.gradeTextview.text = "---"
} else {
pointsText = "$finalScore"
gradeText = getString(R.string.approximate_placeholder, viewModel.getFinalGrade(finalScore).toString())
gradeText = getString(R.string.approximate_placeholder, viewModel.getFinalGradeScore(finalScore).toString())
setTextForGradeTextViews()
}
@@ -126,41 +125,42 @@ internal class FinalsFragment : QwarkFragment(), FinalGradeAdapter.FinalGradeCli
}
override fun onFinalGradeClick(finalGrade: FinalGrade) {
openBottomSheet(FinalsOptionsBottomSheet().also { sheet ->
QwarkUtil.putFinalGradeInBundle(sheet, finalGrade)
openBottomSheet(FinalsOptionsSheet().also { sheet ->
sheet.arguments = Bundle().apply { putInt("finalGradeId", finalGrade.finalGradeId) }
})
}
internal fun createEditGradeSheet(finalGrade: FinalGrade) {
openBottomSheet(FinalsCreateBottomSheet().also { sheet ->
QwarkUtil.putFinalGradeInBundle(sheet, finalGrade)
fun createEditGradeSheet(finalGrade: FinalGrade) {
openBottomSheet(FinalsCreateSheet().also { sheet ->
sheet.arguments = Bundle().apply { putInt("finalGradeId", finalGrade.finalGradeId) }
})
}
internal fun createLinkGradeSheet(finalGrade: FinalGrade) {
openBottomSheet(FinalsLinkBottomSheet().also { sheet ->
QwarkUtil.putFinalGradeInBundle(sheet, finalGrade)
fun createLinkGradeSheet(finalGrade: FinalGrade) {
openBottomSheet(FinalsLinkSheet().also { sheet ->
sheet.arguments = Bundle().apply { putInt("finalGradeId", finalGrade.finalGradeId) }
})
}
internal fun getAllYears() = viewModel.getAllYears()
internal fun getAllCourses() = viewModel.getAllCourses()
fun getAllYears() = viewModel.getAllYears()
fun getAllCourses() = viewModel.getAllCourses()
internal fun viewLinkedCourse(courseId: Int) {
val f = GradeFragment()
QwarkUtil.putCourseInBundle(f, viewModel.getCourse(courseId))
val d = viewModel.getSchoolYearName(courseId)
Log.d("TAG", d)
f.arguments?.putString("schoolYear", d)
activity?.supportFragmentManager?.beginTransaction()
?.replace(R.id.fragment_container, f)
?.addToBackStack("GradeFragment")
?.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
?.commit()
fun viewLinkedCourse(courseId: Int) {
val f = GradeFragment().also { fragment ->
fragment.arguments = Bundle().apply {
putInt("courseId", courseId)
putString("schoolYear", viewModel.getSchoolYearName(courseId))
}
}
(context as FragmentActivity).supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, f)
.addToBackStack(f.name)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit()
}
internal fun clearFinalGrade(finalGrade: FinalGrade) {
val deletionSheet = ConfirmDeletionBottomSheet(getString(R.string.clear_final_grade_desc, finalGrade.name)) {
fun clearFinalGrade(finalGrade: FinalGrade) {
val deletionSheet = ConfirmDeletionSheet(getString(R.string.clear_final_grade_desc, finalGrade.name)) {
val newFinalGrade = FinalGrade(
name = "",
grade = "-1",
@@ -175,14 +175,14 @@ internal class FinalsFragment : QwarkFragment(), FinalGradeAdapter.FinalGradeCli
openBottomSheet(deletionSheet)
}
internal fun clearFinalGradeError() {
fun clearFinalGradeError() {
Snackbar
.make(snackBarContainer, getString(R.string.clear_final_grade_error), Snackbar.LENGTH_LONG)
.setBackgroundTint(context.getColor(R.color.colorWarning))
.show()
}
internal fun update(finalGrade: FinalGrade) { viewModel.update(finalGrade) }
fun update(finalGrade: FinalGrade) { viewModel.update(finalGrade) }
// TODO perhaps replace with a bottom sheet
// private fun createOverview(finalGrades: List<FinalGrade>, view: View) {
@@ -284,6 +284,7 @@ internal class FinalsFragment : QwarkFragment(), FinalGradeAdapter.FinalGradeCli
binding.finalExamsRecyclerview.layoutManager?.onRestoreInstanceState(examScrollPosition)
}
internal fun getCourseSortType() = viewModel.getCourseSortType()
fun getCourseSortType() = viewModel.getCourseSortType()
fun getGradeType() = viewModel.getGradeType()
fun getFinalGrade(finalGradeId: Int) = viewModel.getFinalGrade(finalGradeId)
}
@@ -2,24 +2,22 @@ package com.denizd.qwark.fragment
import android.os.Bundle
import android.os.Parcelable
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentTransaction
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.GridLayoutManager
import com.denizd.qwark.R
import com.denizd.qwark.adapter.GradeAdapter
import com.denizd.qwark.sheet.ConfirmDeletionBottomSheet
import com.denizd.qwark.sheet.GradeCreateBottomSheet
import com.denizd.qwark.sheet.ConfirmDeletionSheet
import com.denizd.qwark.sheet.GradeCreateSheet
import com.denizd.qwark.databinding.GradeFragmentBinding
import com.denizd.qwark.model.CourseExam
import com.denizd.qwark.model.Grade
import com.denizd.qwark.model.HistoricalAvg
import com.denizd.qwark.util.QwarkUtil
import com.denizd.qwark.util.calculateAverage
import com.denizd.qwark.util.getUserDefinedAverage
import com.denizd.qwark.viewmodel.GradeViewModel
@@ -34,7 +32,7 @@ class GradeFragment : QwarkFragment(), GradeAdapter.GradeClickListener {
private lateinit var weightingString: String
private lateinit var adapter: GradeAdapter
private lateinit var viewModel: GradeViewModel
private val viewModel: GradeViewModel by viewModels()
private lateinit var inflater: LayoutInflater
private var _binding: GradeFragmentBinding? = null
@@ -45,12 +43,9 @@ class GradeFragment : QwarkFragment(), GradeAdapter.GradeClickListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this)[GradeViewModel::class.java]
// currentCourse = QwarkUtil.getCourseFromBundle(arguments)
schoolYear = arguments?.getString("schoolYear") ?: ""
currentCourse = viewModel.getCourse(arguments?.getInt("courseId") ?: -1)
average = currentCourse.average
average = currentCourse.average.getUserDefinedAverage(getGradeType())
weightingString = "${currentCourse.oralWeighting} / ${100 - currentCourse.oralWeighting}"
viewModel.getGradesByForeignKey(currentCourse.courseId).observe(this, Observer { grades ->
@@ -67,7 +62,7 @@ class GradeFragment : QwarkFragment(), GradeAdapter.GradeClickListener {
average = filteredGrades.calculateAverage(
currentCourse.oralWeighting
)
binding.average.text = if (filteredGrades.isEmpty()) "X" else average.getUserDefinedAverage(getGradeType())
binding.average.text = if (filteredGrades.isEmpty()) "??" else average.getUserDefinedAverage(getGradeType())
viewModel.updateAverage(average, filteredGrades.size, currentCourse.courseId)
}
@@ -94,7 +89,7 @@ class GradeFragment : QwarkFragment(), GradeAdapter.GradeClickListener {
currentCourse.name
)
fab.hide()
with(view.rootView) {
with (view.rootView) {
findViewById<BottomNavigationView>(R.id.bottom_nav).visibility = View.GONE
findViewById<View>(R.id.view).visibility = View.GONE
}
@@ -103,7 +98,7 @@ class GradeFragment : QwarkFragment(), GradeAdapter.GradeClickListener {
presentGradeDialog()
}
binding.average.text = currentCourse.average
binding.average.text = currentCourse.average.getUserDefinedAverage(getGradeType())
binding.weighting.text = weightingString
binding.recyclerView.adapter = adapter
@@ -135,12 +130,12 @@ class GradeFragment : QwarkFragment(), GradeAdapter.GradeClickListener {
}
private fun presentGradeDialog(grade: Grade? = null) {
openBottomSheet(GradeCreateBottomSheet().also { sheet ->
if (grade == null) {
sheet.arguments = Bundle(1).apply { putInt("courseId", currentCourse.courseId) }
openBottomSheet(GradeCreateSheet().also { sheet ->
sheet.arguments = Bundle(1).apply { if (grade == null) {
putInt("courseId", currentCourse.courseId)
} else {
QwarkUtil.putGradeInBundle(sheet, grade)
}
putInt("gradeId", grade.gradeId)
}}
})
}
@@ -149,7 +144,7 @@ class GradeFragment : QwarkFragment(), GradeAdapter.GradeClickListener {
}
override fun onGradeLongClick(gradeId: Int) {
val deletionSheet = ConfirmDeletionBottomSheet(getString(R.string.confirm_grade_deletion)) {
val deletionSheet = ConfirmDeletionSheet(getString(R.string.confirm_grade_deletion)) {
viewModel.delete(gradeId)
}
openBottomSheet(deletionSheet)
@@ -157,23 +152,27 @@ class GradeFragment : QwarkFragment(), GradeAdapter.GradeClickListener {
private fun openParticipationCourseFragment() {
appBar.setExpanded(true)
val f = ParticipationCourseFragment()
f.arguments = Bundle().apply {
putString("course", currentCourse.name)
putInt("courseId", currentCourse.courseId)
putBoolean("advanced", currentCourse.advanced)
(context as FragmentActivity).supportFragmentManager.also { fm ->
if (fm.getBackStackEntryAt(0).name == "ParticipationCourseFragment") {
fm.popBackStack()
} else {
val f = ParticipationCourseFragment()
f.arguments = Bundle().apply {
putString("course", currentCourse.name)
putInt("courseId", currentCourse.courseId)
putBoolean("advanced", currentCourse.advanced)
}
fm.beginTransaction()
.replace(R.id.fragment_container, f)
.addToBackStack(f.name)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit()
}
}
// for targetFragment to work, ParticipationFragment needs to be active
// TODO fix the dependency on targetFragment (maybe introduce a ParticipationCourseViewModel)
// f.setTargetFragment((context as FragmentActivity).supportFragmentManager.findFragmentByTag("ParticipationFragment"), 42)
(context as FragmentActivity).supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, f)
.addToBackStack(f.name)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit()
}
fun insert(grade: Grade) { viewModel.insert(grade) }
fun update(grade: Grade) { viewModel.update(grade) }
fun getGradeType(): Int = viewModel.getGradeType()
fun getGrade(gradeId: Int) = viewModel.getGrade(gradeId)
}
@@ -11,14 +11,13 @@ import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.denizd.qwark.R
import com.denizd.qwark.adapter.NoteAdapter
import com.denizd.qwark.sheet.ConfirmDeletionBottomSheet
import com.denizd.qwark.sheet.NoteCreateBottomSheet
import com.denizd.qwark.sheet.NoteDisplayBottomSheet
import com.denizd.qwark.sheet.NoteOptionsBottomSheet
import com.denizd.qwark.sheet.ConfirmDeletionSheet
import com.denizd.qwark.sheet.NoteCreateSheet
import com.denizd.qwark.sheet.NoteDisplaySheet
import com.denizd.qwark.sheet.NoteOptionsSheet
import com.denizd.qwark.util.OnBackPressed
import com.denizd.qwark.databinding.*
import com.denizd.qwark.model.Note
import com.denizd.qwark.util.QwarkUtil
import com.denizd.qwark.viewmodel.NoteViewModel
import com.google.android.material.appbar.AppBarLayout
@@ -82,7 +81,7 @@ class NoteFragment : QwarkFragment(), NoteAdapter.OnNoteClickListener, OnBackPre
override fun onResume() {
super.onResume()
binding.recyclerView.applyPadding(verticalPadding = 4)
binding.recyclerView.applyPadding(horizontalPadding = 4)
}
override fun onDestroy() {
@@ -113,8 +112,8 @@ class NoteFragment : QwarkFragment(), NoteAdapter.OnNoteClickListener, OnBackPre
}
override fun onNoteClick(note: Note) {
openBottomSheet(NoteDisplayBottomSheet().also { sheet ->
QwarkUtil.putNoteInBundle(sheet, note)
openBottomSheet(NoteDisplaySheet().also { sheet ->
sheet.arguments = Bundle().apply { putInt("noteId", note.noteId) }
})
}
@@ -124,7 +123,7 @@ class NoteFragment : QwarkFragment(), NoteAdapter.OnNoteClickListener, OnBackPre
}
fun deleteNote(noteId: Int) {
val deletionSheet = ConfirmDeletionBottomSheet(getString(R.string.confirm_note_deletion)) {
val deletionSheet = ConfirmDeletionSheet(getString(R.string.confirm_note_deletion)) {
scrollPosition = binding.recyclerView.layoutManager?.onSaveInstanceState()
viewModel.delete(noteId)
binding.recyclerView.scheduleLayoutAnimation()
@@ -141,14 +140,14 @@ class NoteFragment : QwarkFragment(), NoteAdapter.OnNoteClickListener, OnBackPre
}
private fun createOptionsSheet(note: Note) {
openBottomSheet(NoteOptionsBottomSheet().also { sheet ->
QwarkUtil.putNoteInBundle(sheet, note)
openBottomSheet(NoteOptionsSheet().also { sheet ->
sheet.arguments = Bundle().apply { putInt("noteId", note.noteId) }
})
}
fun createNoteDialog(note: Note? = null) {
val createSheet = NoteCreateBottomSheet().also { sheet ->
if (note != null) QwarkUtil.putNoteInBundle(sheet, note)
val createSheet = NoteCreateSheet().also { sheet ->
if (note != null) sheet.arguments = Bundle().apply { putInt("noteId", note.noteId) }
}
openBottomSheet(createSheet)
}
@@ -165,4 +164,5 @@ class NoteFragment : QwarkFragment(), NoteAdapter.OnNoteClickListener, OnBackPre
fun insert(note: Note) { viewModel.insert(note) }
fun update(note: Note) { viewModel.update(note) }
fun getAllCategories(): List<String> = viewModel.getAllCategories()
fun getNote(noteId: Int) = viewModel.getNote(noteId)
}
@@ -14,9 +14,10 @@ import com.denizd.qwark.adapter.ParticipationAdapter
import com.denizd.qwark.databinding.GradeFragmentBinding
import com.denizd.qwark.model.Participation
import com.denizd.qwark.sheet.ClassSessionSheet
import com.denizd.qwark.sheet.ConfirmDeletionBottomSheet
import com.denizd.qwark.sheet.ConfirmDeletionSheet
import com.denizd.qwark.viewmodel.ParticipationCourseViewModel
import com.google.android.material.bottomnavigation.BottomNavigationView
import com.google.android.material.snackbar.Snackbar
class ParticipationCourseFragment : QwarkFragment(), ParticipationAdapter.ParticipationClickListener {
@@ -109,11 +110,24 @@ class ParticipationCourseFragment : QwarkFragment(), ParticipationAdapter.Partic
}
override fun onParticipationClick(participation: Participation) {
// do nothing
if (participation.time > System.currentTimeMillis() - 1000 * 60 * 90) {
openBottomSheet(ClassSessionSheet().also { sheet ->
sheet.arguments = Bundle(2).apply {
putInt("timesHandRaised", participation.timesHandRaised)
putInt("timesSpoken", participation.timesSpoken)
putInt("participationId", participation.participationId)
}
sheet.isCancelable = false
})
} else {
Snackbar
.make(snackBarContainer, getString(R.string.participation_too_old), Snackbar.LENGTH_LONG)
.show()
}
}
override fun onParticipationLongClick(participation: Participation) {
openBottomSheet(ConfirmDeletionBottomSheet(
openBottomSheet(ConfirmDeletionSheet(
getString(R.string.delete_participation_confirmation)
) {
viewModel.delete(participation)
@@ -122,19 +136,30 @@ class ParticipationCourseFragment : QwarkFragment(), ParticipationAdapter.Partic
private fun openGradeFragment() {
appBar.setExpanded(true)
val f = GradeFragment()
f.arguments = Bundle().apply {
putString("schoolYear", viewModel.getSchoolYearName())
putInt("courseId", courseId)
(context as FragmentActivity).supportFragmentManager.also { fm ->
if (fm.getBackStackEntryAt(0).name == "GradeFragment") {
fm.popBackStack()
} else {
val f = GradeFragment()
f.arguments = Bundle().apply {
putString("schoolYear", viewModel.getSchoolYearName())
putInt("courseId", courseId)
}
fm.beginTransaction()
.replace(R.id.fragment_container, f)
.addToBackStack("GradeFragment")
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit()
}
}
(context as FragmentActivity).supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, f)
.addToBackStack("GradeFragment")
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit()
}
fun createParticipation(timesHandRaised: Int, timesSpoken: Int, time: Long) {
viewModel.createParticipation(timesHandRaised, timesSpoken, time, courseId)
}
// TODO this function has the same name as another one with a different function signature
fun updateParticipation(timesHandRaised: Int, timesSpoken: Int, participationId: Int) {
viewModel.updateParticipation(timesHandRaised, timesSpoken, participationId)
}
}
@@ -7,7 +7,6 @@ import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentTransaction
import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.StaggeredGridLayoutManager
@@ -16,8 +15,8 @@ import com.denizd.qwark.adapter.CourseAdapter
import com.denizd.qwark.databinding.PaddedRecyclerViewBinding
import com.denizd.qwark.model.CourseExam
import com.denizd.qwark.model.Participation
import com.denizd.qwark.sheet.ConfirmDeletionBottomSheet
import com.denizd.qwark.sheet.ParticipationLinkBottomSheet
import com.denizd.qwark.sheet.ConfirmDeletionSheet
import com.denizd.qwark.sheet.ParticipationLinkSheet
import com.denizd.qwark.viewmodel.ParticipationViewModel
internal class ParticipationFragment : QwarkFragment(), CourseAdapter.CourseClickListener {
@@ -88,7 +87,7 @@ internal class ParticipationFragment : QwarkFragment(), CourseAdapter.CourseClic
override fun onResume() {
super.onResume()
binding.recyclerView.applyPadding(verticalPadding = 4)
binding.recyclerView.applyPadding(horizontalPadding = 4)
}
override fun onDestroy() {
@@ -118,11 +117,11 @@ internal class ParticipationFragment : QwarkFragment(), CourseAdapter.CourseClic
}
private fun openLinkSheet() {
openBottomSheet(ParticipationLinkBottomSheet())
openBottomSheet(ParticipationLinkSheet())
}
private fun openRemoveLinkSheet(courseName: String, relationId: Int) {
openBottomSheet(ConfirmDeletionBottomSheet(
openBottomSheet(ConfirmDeletionSheet(
getString(R.string.confirm_remove_participation_link, courseName, getDay())
) {
viewModel.removeLink(relationId)
@@ -50,8 +50,8 @@ open class QwarkFragment : Fragment() {
* Initialise view resources
*/
statusBarView = view.rootView.findViewById(R.id.status_bar_view)
appBarTitleView = view.rootView.findViewById(R.id.toolbarTxt)
superTitleView = view.rootView.findViewById(R.id.text_above)
appBarTitleView = view.rootView.findViewById(R.id.app_bar_title)
superTitleView = view.rootView.findViewById(R.id.super_title)
appBar = view.rootView.findViewById(R.id.app_bar_layout)
snackBarContainer = view.rootView.findViewById(R.id.root_view)
fab = view.rootView.findViewById(R.id.fab)
@@ -93,11 +93,12 @@ open class QwarkFragment : Fragment() {
* to its lifecycle owner and therefore cannot calculate the top padding properly. Invoke in
* onResume instead.
*/
protected fun <T : View> T.applyPadding(verticalPadding: Int = 0) {
protected fun <T : View> T.applyPadding(horizontalPadding: Int = 0) {
val horizontal = horizontalPadding.dpToPx()
setPadding(
verticalPadding.dpToPx(),
horizontal,
(statusBarView.height / 1) + appBar.height,
verticalPadding.dpToPx(),
horizontal,
0
)
}
@@ -5,15 +5,14 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.denizd.qwark.R
import com.denizd.qwark.sheet.ConfirmDeletionBottomSheet
import com.denizd.qwark.sheet.CopyCoursesBottomSheet
import com.denizd.qwark.sheet.ScoreProfileCreateBottomSheet
import com.denizd.qwark.sheet.YearCreateBottomSheet
import com.denizd.qwark.sheet.ConfirmDeletionSheet
import com.denizd.qwark.sheet.CopyCoursesSheet
import com.denizd.qwark.sheet.ScoreProfileCreateSheet
import com.denizd.qwark.sheet.YearCreateSheet
import com.denizd.qwark.databinding.SettingsFragmentBinding
import com.denizd.qwark.model.ScoreProfile
import com.denizd.qwark.model.SchoolYear
import com.denizd.qwark.viewmodel.SettingsViewModel
import com.google.android.material.snackbar.Snackbar
@@ -22,12 +21,7 @@ class SettingsFragment : QwarkFragment() {
private var _binding: SettingsFragmentBinding? = null
private val binding: SettingsFragmentBinding get() = _binding!!
private lateinit var viewModel: SettingsViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel = ViewModelProvider(this)[SettingsViewModel::class.java]
}
private val viewModel: SettingsViewModel by viewModels()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
_binding = SettingsFragmentBinding.inflate(inflater, container, false)
@@ -120,7 +114,7 @@ class SettingsFragment : QwarkFragment() {
if (binding.schoolYearDropdown.text.isNullOrBlank()) {
presentErrorSnackBar(getString(R.string.no_school_year_selected))
} else {
val deleteYearSheet = ConfirmDeletionBottomSheet(getString(R.string.delete_school_year_desc, binding.schoolYearDropdown.text.toString())) {
val deleteYearSheet = ConfirmDeletionSheet(getString(R.string.delete_school_year_desc, binding.schoolYearDropdown.text.toString())) {
viewModel.deleteSchoolYear()
binding.schoolYearDropdown.setText("")
}
@@ -128,7 +122,7 @@ class SettingsFragment : QwarkFragment() {
}
}
binding.copyCoursesButton.setOnClickListener {
openBottomSheet(CopyCoursesBottomSheet())
openBottomSheet(CopyCoursesSheet())
}
// binding.copyCoursesButton.setOnLongClickListener {
// // TODO this is currently an experiment
@@ -206,7 +200,7 @@ class SettingsFragment : QwarkFragment() {
if (binding.scoreProfileDropdown.text.isNullOrBlank()) {
presentErrorSnackBar(getString(R.string.no_score_profile_selected))
} else {
val deleteScoreProfileSheet = ConfirmDeletionBottomSheet(
val deleteScoreProfileSheet = ConfirmDeletionSheet(
getString(R.string.delete_score_profile_desc,
binding.scoreProfileDropdown.text.toString())
) {
@@ -243,7 +237,7 @@ class SettingsFragment : QwarkFragment() {
if (edit && currentYear == "") {
presentErrorSnackBar(getString(R.string.no_school_year_selected))
} else {
val yearCreateSheet = YearCreateBottomSheet().also { sheet ->
val yearCreateSheet = YearCreateSheet().also { sheet ->
sheet.arguments = Bundle(1).apply {
putString("currentYear", if (edit) currentYear else "")
}
@@ -264,7 +258,7 @@ class SettingsFragment : QwarkFragment() {
if (edit && currentScoreProfile == "") {
presentErrorSnackBar(getString(R.string.no_score_profile_selected))
} else {
openBottomSheet(ScoreProfileCreateBottomSheet().also { sheet ->
openBottomSheet(ScoreProfileCreateSheet().also { sheet ->
sheet.arguments = Bundle(1).apply {
putString("currentScoreProfile", if (edit) currentScoreProfile else "")
}
@@ -7,6 +7,7 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.Toast
import com.denizd.qwark.R
import com.denizd.qwark.databinding.ClassSessionSheetBinding
@@ -32,6 +33,7 @@ class ClassSessionSheet : BottomSheetDialogFragment() {
field = value
binding.spokenButton.text = "$value"
}
private var participationId = -1
private val time: Long = System.currentTimeMillis()
override fun onAttach(context: Context) {
@@ -46,12 +48,20 @@ class ClassSessionSheet : BottomSheetDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
participationFragment = targetFragment as ParticipationCourseFragment
arguments?.let { args ->
timesHandRaised = args.getInt ("timesHandRaised")
timesSpoken = args.getInt("timesSpoken")
participationId = args.getInt("participationId")
binding.title.text = getString(R.string.class_session_resumed)
}
binding.handRaisedButton.apply {
setCompoundDrawables(context.getDrawable(R.drawable.hand).also { drawable ->
drawable?.bounds = Rect(0, 0, 256, 256)
drawable?.setTint(mContext.getColor(R.color.colorAccent))
setCompoundDrawables(context.getDrawable(R.drawable.hand)?.also { drawable ->
drawable.bounds = Rect(0, 0, 256, 256)
drawable.setTint(mContext.getColor(R.color.colorAccent))
}, null, null, null)
text = "$timesHandRaised"
setOnClickListener {
@@ -66,9 +76,9 @@ class ClassSessionSheet : BottomSheetDialogFragment() {
}
}
binding.spokenButton.apply {
setCompoundDrawables(context.getDrawable(R.drawable.speech).also { drawable ->
drawable?.bounds = Rect(0, 0, 256, 256)
drawable?.setTint(mContext.getColor(R.color.colorAccent))
setCompoundDrawables(context.getDrawable(R.drawable.speech)?.also { drawable ->
drawable.bounds = Rect(0, 0, 256, 256)
drawable.setTint(mContext.getColor(R.color.colorAccent))
}, null, null, null)
text = "$timesSpoken"
setOnClickListener {
@@ -104,6 +114,16 @@ class ClassSessionSheet : BottomSheetDialogFragment() {
}
}
override fun onResume() {
super.onResume()
activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
override fun onPause() {
super.onPause()
activity?.window?.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
override fun onDestroy() {
super.onDestroy()
_binding = null
@@ -116,8 +136,10 @@ class ClassSessionSheet : BottomSheetDialogFragment() {
}
private fun finish() {
participationFragment.createParticipation(
timesHandRaised, timesSpoken, time
)
if (participationId == -1) {
participationFragment.createParticipation(timesHandRaised, timesSpoken, time)
} else {
participationFragment.updateParticipation(timesHandRaised, timesSpoken, participationId)
}
}
}
@@ -10,7 +10,7 @@ import com.denizd.qwark.databinding.ConfirmationDialogBinding
import com.denizd.qwark.viewmodel.ConfirmDeletionViewModel
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
class ConfirmDeletionBottomSheet() : BottomSheetDialogFragment() {
class ConfirmDeletionSheet() : BottomSheetDialogFragment() {
constructor(text: String, confirmedAction: () -> Unit) : this() {
this.text = text
@@ -12,7 +12,7 @@ import com.denizd.qwark.fragment.SettingsFragment
import com.denizd.qwark.model.SchoolYear
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
internal class CopyCoursesBottomSheet : BottomSheetDialogFragment(), YearAdapter.YearClickListener {
class CopyCoursesSheet : BottomSheetDialogFragment(), YearAdapter.YearClickListener {
private var _binding: RecyclerDialogBinding? = null
private val binding: RecyclerDialogBinding get() = _binding!!
@@ -41,7 +41,7 @@ internal class CopyCoursesBottomSheet : BottomSheetDialogFragment(), YearAdapter
layoutManager = LinearLayoutManager(context)
adapter = YearAdapter((settingsTargetFragment.getSchoolYears() ?: ArrayList()).filter { y ->
y.yearId != settingsTargetFragment.getCurrentSchoolYearId()
}, this@CopyCoursesBottomSheet)
}, this@CopyCoursesSheet)
scheduleLayoutAnimation()
}
}
@@ -7,6 +7,7 @@ import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.FragmentActivity
import com.denizd.qwark.R
import com.denizd.qwark.util.QwarkUtil
import com.denizd.qwark.databinding.CourseCreateDialogBinding
@@ -15,7 +16,7 @@ import com.denizd.qwark.model.Course
import com.denizd.qwark.model.CourseExam
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
internal class CourseCreateBottomSheet : BottomSheetDialogFragment() {
class CourseCreateSheet : BottomSheetDialogFragment() {
private var _binding: CourseCreateDialogBinding? = null
private val binding: CourseCreateDialogBinding get() = _binding!!
@@ -25,7 +26,7 @@ internal class CourseCreateBottomSheet : BottomSheetDialogFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (arguments?.size() ?: 0 != 0) course = QwarkUtil.getCourseFromBundle(arguments)
if (arguments?.size() ?: 0 != 0) course = (targetFragment as CourseFragment).getCourse(arguments?.getInt("courseId") ?: -1) // QwarkUtil.getCourseFromBundle(arguments)
}
override fun onAttach(context: Context) {
@@ -121,17 +122,17 @@ internal class CourseCreateBottomSheet : BottomSheetDialogFragment() {
_binding = null
}
private fun openIconBottomSheet() = fragmentManager?.let { fm ->
val sheet = IconPickerBottomSheet().apply {
private fun openIconBottomSheet() {
val sheet = IconPickerSheet().apply {
arguments = Bundle(1).apply {
putString("currentIcon", icon)
}
}
sheet.setTargetFragment(this, 42)
sheet.show(fm, sheet.tag)
sheet.show((context as FragmentActivity).supportFragmentManager, sheet.tag)
}
internal fun setIcon(icon: String) {
fun setIcon(icon: String) {
binding.imageView.setImageResource(QwarkUtil.getDrawableIntForString(icon))
this.icon = icon
}
@@ -8,21 +8,20 @@ import android.view.ViewGroup
import com.denizd.qwark.R
import com.denizd.qwark.databinding.CourseOptionsDialogBinding
import com.denizd.qwark.fragment.CourseFragment
import com.denizd.qwark.model.Course
import com.denizd.qwark.model.CourseExam
import com.denizd.qwark.util.QwarkUtil
import com.denizd.qwark.util.asCourse
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
internal class CourseOptionsBottomSheet : BottomSheetDialogFragment() {
class CourseOptionsSheet : BottomSheetDialogFragment() {
private var _binding: CourseOptionsDialogBinding? = null
private val binding: CourseOptionsDialogBinding get() = _binding!!
private lateinit var mContext: Context
private lateinit var course: CourseExam
private lateinit var courseExam: CourseExam
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
course = QwarkUtil.getCourseFromBundle(arguments)
courseExam = (targetFragment as CourseFragment).getCourse(arguments?.getInt("courseId") ?: -1)
}
override fun onAttach(context: Context) {
@@ -40,18 +39,18 @@ internal class CourseOptionsBottomSheet : BottomSheetDialogFragment() {
val targetFragment = targetFragment as CourseFragment
binding.title.text = getString(R.string.options_for_course, course.name)
binding.title.text = getString(R.string.options_for_course, courseExam.name)
binding.viewHistoryButton.setOnClickListener {
targetFragment.createHistoryDialog(course.courseId, course.name)
targetFragment.createHistoryDialog(courseExam.courseId, courseExam.name)
dismiss()
}
binding.editCourseButton.setOnClickListener {
targetFragment.createCourseDialog(course)
targetFragment.createCourseDialog(courseExam)
dismiss()
}
binding.deleteCourseButton.setOnClickListener {
targetFragment.deleteCourse(QwarkUtil.getCourseExamAsCourse(course))
targetFragment.deleteCourse(courseExam.asCourse())
dismiss()
}
}
@@ -5,24 +5,24 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import com.denizd.qwark.R
import com.denizd.qwark.util.QwarkUtil
import com.denizd.qwark.databinding.FinalGradeEditDialogBinding
import com.denizd.qwark.fragment.FinalsFragment
import com.denizd.qwark.model.FinalGrade
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
internal class FinalsCreateBottomSheet : BottomSheetDialogFragment() {
class FinalsCreateSheet : BottomSheetDialogFragment() {
private var _binding: FinalGradeEditDialogBinding? = null
private val binding: FinalGradeEditDialogBinding get() = _binding!!
private lateinit var mContext: Context
private lateinit var finalGrade: FinalGrade
private lateinit var finalsFragment: FinalsFragment
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
finalGrade = QwarkUtil.getFinalGradeFromBundle(arguments)
finalsFragment = targetFragment as FinalsFragment
finalGrade = finalsFragment.getFinalGrade(arguments?.getInt("finalGradeId") ?: -1)
}
override fun onAttach(context: Context) {
@@ -38,20 +38,7 @@ internal class FinalsCreateBottomSheet : BottomSheetDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val targetFragment = targetFragment as FinalsFragment
binding.courseEdittext.setText(finalGrade.name)
// val gradeArray = ArrayAdapter.createFromResource(mContext, R.array.grades_points, R.layout.dropdown_item)
// binding.gradePicker.setAdapter(gradeArray)
// binding.gradePicker.setText(
// if (finalGrade.grade == "-1") {
// binding.gradePicker.adapter.getItem(0).toString()
// } else {
// QwarkUtil.getGradeWithLeadingZero(finalGrade.grade.toInt())
// },
// false
// )
binding.gradePicker.value = if (finalGrade.grade == "-1") 0 else finalGrade.grade.toInt()
binding.cancelButton.setOnClickListener {
@@ -71,7 +58,7 @@ internal class FinalsCreateBottomSheet : BottomSheetDialogFragment() {
finalGradeId = finalGrade.finalGradeId,
scoreProfileId = finalGrade.scoreProfileId
)
targetFragment.update(newFinalGrade)
finalsFragment.update(newFinalGrade)
dismiss()
}
}
@@ -8,28 +8,28 @@ import androidx.recyclerview.widget.LinearLayoutManager
import com.denizd.qwark.R
import com.denizd.qwark.adapter.CourseAdapter
import com.denizd.qwark.adapter.YearAdapter
import com.denizd.qwark.util.QwarkUtil
import com.denizd.qwark.databinding.RecyclerDialogBinding
import com.denizd.qwark.fragment.FinalsFragment
import com.denizd.qwark.model.Course
import com.denizd.qwark.model.CourseExam
import com.denizd.qwark.model.FinalGrade
import com.denizd.qwark.model.SchoolYear
import com.denizd.qwark.util.getSorted
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import java.math.BigDecimal
import java.math.RoundingMode
internal class FinalsLinkBottomSheet : BottomSheetDialogFragment(), YearAdapter.YearClickListener, CourseAdapter.CourseClickListener {
class FinalsLinkSheet : BottomSheetDialogFragment(), YearAdapter.YearClickListener, CourseAdapter.CourseClickListener {
private lateinit var finalGrade: FinalGrade
private lateinit var binding: RecyclerDialogBinding
private var advanced = false
private var isSelectingCourse = false
private lateinit var finalsTargetFragment: FinalsFragment
private lateinit var finalsFragment: FinalsFragment
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
finalGrade = QwarkUtil.getFinalGradeFromBundle(arguments)
finalsFragment = targetFragment as FinalsFragment
finalGrade = finalsFragment.getFinalGrade(arguments?.getInt("finalGradeId") ?: -1)
advanced = finalGrade.type == "adv"
}
@@ -41,7 +41,7 @@ internal class FinalsLinkBottomSheet : BottomSheetDialogFragment(), YearAdapter.
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
finalsTargetFragment = targetFragment as FinalsFragment
finalsFragment = targetFragment as FinalsFragment
fillWithYears()
}
@@ -59,7 +59,7 @@ internal class FinalsLinkBottomSheet : BottomSheetDialogFragment(), YearAdapter.
finalGradeId = finalGrade.finalGradeId,
scoreProfileId = finalGrade.scoreProfileId
)
finalsTargetFragment.update(newFinalGrade)
finalsFragment.update(newFinalGrade)
dismiss()
}
@@ -69,7 +69,7 @@ internal class FinalsLinkBottomSheet : BottomSheetDialogFragment(), YearAdapter.
binding.title.text = getString(R.string.pick_a_year)
binding.recyclerView.apply {
layoutManager = LinearLayoutManager(context)
adapter = YearAdapter(finalsTargetFragment.getAllYears(), this@FinalsLinkBottomSheet)
adapter = YearAdapter(finalsFragment.getAllYears(), this@FinalsLinkSheet)
scheduleLayoutAnimation()
}
isSelectingCourse = false
@@ -77,14 +77,14 @@ internal class FinalsLinkBottomSheet : BottomSheetDialogFragment(), YearAdapter.
private fun fillWithCourses(schoolYear: SchoolYear) {
binding.title.text = getString(R.string.pick_a_course)
binding.recyclerView.adapter =
CourseAdapter(
QwarkUtil.getCoursesSorted(
finalsTargetFragment.getAllCourses().filter { c -> c.yearId == schoolYear.yearId && c.advanced == advanced },
finalsTargetFragment.getCourseSortType()
),
this,
finalsTargetFragment.getGradeType()
binding.recyclerView.adapter = CourseAdapter(
finalsFragment.getAllCourses().filter { c ->
c.yearId == schoolYear.yearId && c.advanced == advanced
}.getSorted(
finalsFragment.getCourseSortType()
),
this,
finalsFragment.getGradeType()
)
binding.recyclerView.scheduleLayoutAnimation()
isSelectingCourse = true
@@ -12,16 +12,18 @@ import com.denizd.qwark.model.FinalGrade
import com.denizd.qwark.util.QwarkUtil
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
internal class FinalsOptionsBottomSheet : BottomSheetDialogFragment() {
class FinalsOptionsSheet : BottomSheetDialogFragment() {
private var _binding: FinalGradeOptionsDialogBinding? = null
private val binding: FinalGradeOptionsDialogBinding get() = _binding!!
private lateinit var mContext: Context
private lateinit var finalGrade: FinalGrade
private lateinit var finalsFragment: FinalsFragment
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
finalGrade = QwarkUtil.getFinalGradeFromBundle(arguments)
finalsFragment = targetFragment as FinalsFragment
finalGrade = finalsFragment.getFinalGrade(arguments?.getInt("finalGradeId") ?: -1)
}
override fun onAttach(context: Context) {
@@ -36,30 +38,28 @@ internal class FinalsOptionsBottomSheet : BottomSheetDialogFragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val targetFragment = targetFragment as FinalsFragment
binding.title.text = getString(R.string.options_for_final_grade, if (finalGrade.name.isEmpty()) getString(R.string.final_grade) else finalGrade.name)
if (finalGrade.type == "exam") binding.linkGradeButton.visibility = View.GONE
if (finalGrade.courseId == -1) binding.viewLinkedCourseButton.visibility = View.GONE
binding.editGradeButton.setOnClickListener {
targetFragment.createEditGradeSheet(finalGrade)
finalsFragment.createEditGradeSheet(finalGrade)
dismiss()
}
binding.linkGradeButton.setOnClickListener {
targetFragment.createLinkGradeSheet(finalGrade)
finalsFragment.createLinkGradeSheet(finalGrade)
dismiss()
}
binding.viewLinkedCourseButton.setOnClickListener {
targetFragment.viewLinkedCourse(finalGrade.courseId)
finalsFragment.viewLinkedCourse(finalGrade.courseId)
dismiss()
}
binding.clearGradeButton.setOnClickListener {
if (finalGrade.grade == "-1") {
targetFragment.clearFinalGradeError()
finalsFragment.clearFinalGradeError()
} else {
targetFragment.clearFinalGrade(finalGrade)
finalsFragment.clearFinalGrade(finalGrade)
}
dismiss()
}
@@ -5,10 +5,10 @@ import android.content.Context
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import com.denizd.qwark.R
import com.denizd.qwark.util.QwarkUtil
import com.denizd.qwark.databinding.GradeCreateDialogBinding
@@ -18,18 +18,24 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import java.text.ParseException
import java.util.*
class GradeCreateBottomSheet : BottomSheetDialogFragment() {
class GradeCreateSheet : BottomSheetDialogFragment() {
private var _binding: GradeCreateDialogBinding? = null
private val binding: GradeCreateDialogBinding get() = _binding!!
private lateinit var mContext: Context
private lateinit var grade: Grade
private var courseId: Int = 0
private lateinit var gradeFragment: GradeFragment
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (arguments?.size() ?: 0 > 1) grade = QwarkUtil.getGradeFromBundle(arguments)
courseId = arguments?.getInt("courseId") ?: 0
gradeFragment = targetFragment as GradeFragment
val gradeId = arguments?.getInt("gradeId") ?: -1
if (gradeId == 0) { // 0 signifies no value has been set
courseId = arguments?.getInt("courseId") ?: -1
} else {
grade = gradeFragment.getGrade(gradeId)
}
}
override fun onAttach(context: Context) {
@@ -47,11 +53,9 @@ class GradeCreateBottomSheet : BottomSheetDialogFragment() {
LayoutTransition().apply {
setAnimateParentHierarchy(false)
(binding.root as LinearLayout).layoutTransition = this
binding.root.layoutTransition = this
}
val targetFragment = targetFragment as GradeFragment
// initGradeDropdown()
binding.verbalSwitch.setOnCheckedChangeListener { switch, isChecked ->
@@ -79,7 +83,7 @@ class GradeCreateBottomSheet : BottomSheetDialogFragment() {
}
}
binding.gradePicker.displayedValues = QwarkUtil.getGradeArray(targetFragment.getGradeType())
binding.gradePicker.displayedValues = QwarkUtil.getGradeArray(gradeFragment.getGradeType())
binding.examSwitch.setOnCheckedChangeListener { _, isChecked ->
setGradePickerVisibility(isChecked)
@@ -119,9 +123,9 @@ class GradeCreateBottomSheet : BottomSheetDialogFragment() {
examTime = if (binding.examSwitch.isChecked) examDate else -1L
)
if (::grade.isInitialized) {
targetFragment.update(newGrade)
gradeFragment.update(newGrade)
} else {
targetFragment.insert(newGrade)
gradeFragment.insert(newGrade)
}
dismiss()
} catch (e: ParseException) {
@@ -12,7 +12,7 @@ import com.denizd.qwark.databinding.RecyclerDialogBinding
import com.denizd.qwark.fragment.CourseFragment
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
internal class HistoricalAverageBottomSheet : BottomSheetDialogFragment() {
class HistoricalAverageSheet : BottomSheetDialogFragment() {
private var _binding: RecyclerDialogBinding? = null
private val binding: RecyclerDialogBinding get() = _binding!!
@@ -12,7 +12,7 @@ import com.denizd.qwark.databinding.IconDialogBinding
import com.denizd.qwark.model.CourseIcon
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
class IconPickerBottomSheet : BottomSheetDialogFragment(),
class IconPickerSheet : BottomSheetDialogFragment(),
IconAdapter.IconClickListener {
private var _binding: IconDialogBinding? = null
@@ -39,7 +39,7 @@ class IconPickerBottomSheet : BottomSheetDialogFragment(),
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val targetFragment = targetFragment as CourseCreateBottomSheet
val targetFragment = targetFragment as CourseCreateSheet
val icons = QwarkUtil.drawablesList
iconAdapter = IconAdapter(icons, this)
@@ -13,7 +13,7 @@ import com.denizd.qwark.model.Note
import com.denizd.qwark.util.QwarkUtil
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
internal class NoteCreateBottomSheet : BottomSheetDialogFragment() {
class NoteCreateSheet : BottomSheetDialogFragment() {
private var _binding: NoteCreateDialogBinding? = null
private val binding: NoteCreateDialogBinding get() = _binding!!
@@ -22,7 +22,7 @@ internal class NoteCreateBottomSheet : BottomSheetDialogFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (arguments?.size() ?: 0 != 0) note = QwarkUtil.getNoteFromBundle(arguments)
if (arguments?.size() ?: 0 != 0) note = (targetFragment as NoteFragment).getNote(arguments?.getInt("noteId") ?: -1)
}
override fun onAttach(context: Context) {
@@ -8,10 +8,11 @@ import android.view.ViewGroup
import com.denizd.qwark.R
import com.denizd.qwark.util.QwarkUtil
import com.denizd.qwark.databinding.NoteBottomSheetBinding
import com.denizd.qwark.fragment.NoteFragment
import com.denizd.qwark.model.Note
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
internal class NoteDisplayBottomSheet : BottomSheetDialogFragment() {
class NoteDisplaySheet : BottomSheetDialogFragment() {
private var _binding: NoteBottomSheetBinding? = null
private val binding: NoteBottomSheetBinding get() = _binding!!
@@ -20,7 +21,7 @@ internal class NoteDisplayBottomSheet : BottomSheetDialogFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
note = QwarkUtil.getNoteFromBundle(arguments)
note = (targetFragment as NoteFragment).getNote(arguments?.getInt("noteId") ?: -1)
}
override fun onAttach(context: Context) {
@@ -33,18 +34,6 @@ internal class NoteDisplayBottomSheet : BottomSheetDialogFragment() {
return binding.root
}
// override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
// return super.onCreateDialog(savedInstanceState).also { dialog ->
// dialog.setOnShowListener {
// BottomSheetBehavior.from(dialog.findViewById<FrameLayout>(
// com.google.android.material.R.id.design_bottom_sheet
// )).apply {
// state = BottomSheetBehavior.STATE_EXPANDED
// }
// }
// }
// }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@@ -12,7 +12,7 @@ import com.denizd.qwark.model.Note
import com.denizd.qwark.util.QwarkUtil
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
internal class NoteOptionsBottomSheet : BottomSheetDialogFragment() {
class NoteOptionsSheet : BottomSheetDialogFragment() {
private var _binding: NoteOptionsDialogBinding? = null
private val binding: NoteOptionsDialogBinding get() = _binding!!
@@ -21,7 +21,7 @@ internal class NoteOptionsBottomSheet : BottomSheetDialogFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
note = QwarkUtil.getNoteFromBundle(arguments)
note = (targetFragment as NoteFragment).getNote(arguments?.getInt("noteId") ?: -1)
}
override fun onAttach(context: Context) {
@@ -12,7 +12,7 @@ import com.denizd.qwark.fragment.ParticipationFragment
import com.denizd.qwark.model.*
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
internal class ParticipationLinkBottomSheet : BottomSheetDialogFragment(), CourseAdapter.CourseClickListener {
class ParticipationLinkSheet : BottomSheetDialogFragment(), CourseAdapter.CourseClickListener {
private lateinit var finalGrade: FinalGrade
private lateinit var binding: RecyclerDialogBinding
@@ -58,7 +58,7 @@ internal class ParticipationLinkBottomSheet : BottomSheetDialogFragment(), Cours
0
)
},
this@ParticipationLinkBottomSheet,
this@ParticipationLinkSheet,
null
)
layoutManager = LinearLayoutManager(context)
@@ -5,7 +5,7 @@ import android.view.View
import com.denizd.qwark.R
import com.denizd.qwark.fragment.SettingsFragment
internal class ScoreProfileCreateBottomSheet : TextInputBottomSheet() {
class ScoreProfileCreateSheet : TextInputSheet() {
private lateinit var settingsFragment: SettingsFragment
private var currentScoreProfile: String = ""
@@ -8,7 +8,7 @@ import android.view.ViewGroup
import com.denizd.qwark.databinding.TextInputSheetBinding
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
internal open class TextInputBottomSheet : BottomSheetDialogFragment() {
open class TextInputSheet : BottomSheetDialogFragment() {
protected var _binding: TextInputSheetBinding? = null
protected val binding: TextInputSheetBinding get() = _binding!!
@@ -6,7 +6,7 @@ import com.denizd.qwark.R
import com.denizd.qwark.fragment.SettingsFragment
import com.denizd.qwark.model.SchoolYear
internal class YearCreateBottomSheet : TextInputBottomSheet() {
class YearCreateSheet : TextInputSheet() {
private lateinit var settingsFragment: SettingsFragment
private var currentYear: String = ""
@@ -0,0 +1,28 @@
package com.denizd.qwark.util
import com.denizd.qwark.model.Course
import com.denizd.qwark.model.CourseExam
fun List<CourseExam>.getSorted(sortType: Int): List<CourseExam> = when (sortType) { // TODO check what ascending and descending really mean lol
QwarkUtil.SORT_COURSES_TIME_ASC -> this.asReversed()
QwarkUtil.SORT_COURSES_NAME_ASC -> this.sortedBy { c -> c.name }
QwarkUtil.SORT_COURSES_NAME_DESC -> this.sortedByDescending { c -> c.name }
QwarkUtil.SORT_COURSES_ADV -> this.sortedByDescending { c -> c.advanced }
QwarkUtil.SORT_COURSES_BASIC -> this.sortedBy { c -> c.advanced }
QwarkUtil.SORT_COURSES_AVG_ASC -> this.sortedBy { c -> c.average.toDouble() }
QwarkUtil.SORT_COURSES_AVG_DESC -> this.sortedByDescending { c -> c.average.toDouble() }
QwarkUtil.SORT_COURSES_NEXT_EXAM -> this.sortedBy { c -> if (c.examTime > 1L) c.examTime else Long.MAX_VALUE }
else -> this // TIME_DESC
}
fun CourseExam.asCourse(): Course = Course(
name = name,
advanced = advanced,
icon = icon,
colour = colour,
average = average,
oralWeighting = oralWeighting,
gradeCount = gradeCount,
time = time,
courseId = courseId,
yearId = yearId
)
@@ -1,5 +1,5 @@
package com.denizd.qwark.util
internal interface OnBackPressed {
interface OnBackPressed {
fun onBackPressed(): Boolean
}
@@ -4,14 +4,14 @@ import android.content.Context
import android.content.SharedPreferences
import androidx.preference.PreferenceManager
internal class QwarkPreferences private constructor(context: Context) {
class QwarkPreferences private constructor(context: Context) {
private val prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
private val edit: SharedPreferences.Editor = prefs.edit()
companion object {
private var qwarkPrefs: QwarkPreferences? = null
internal fun getPrefs(context: Context): QwarkPreferences {
fun getPrefs(context: Context): QwarkPreferences {
if (qwarkPrefs == null) {
synchronized (QwarkPreferences::class) {
qwarkPrefs = QwarkPreferences(context)
@@ -21,31 +21,31 @@ internal class QwarkPreferences private constructor(context: Context) {
}
}
internal fun getString(key: PreferenceKey, default: String = ""): String = prefs.getString(key.value, default) ?: default
internal fun getInt(key: PreferenceKey, default: Int = 0): Int = prefs.getInt(key.value, default)
internal fun getBool(key: PreferenceKey, default: Boolean = false): Boolean = prefs.getBoolean(key.value, 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 getBool(key: PreferenceKey, default: Boolean = false): Boolean = prefs.getBoolean(key.value, default)
internal fun putString(key: PreferenceKey, value: String): QwarkPreferences {
fun putString(key: PreferenceKey, value: String): QwarkPreferences {
edit.putString(key.value, value).apply()
return this
}
internal fun putInt(key: PreferenceKey, value: Int): QwarkPreferences {
fun putInt(key: PreferenceKey, value: Int): QwarkPreferences {
edit.putInt(key.value, value).apply()
return this
}
internal fun putBool(key: PreferenceKey, value: Boolean): QwarkPreferences {
fun putBool(key: PreferenceKey, value: Boolean): QwarkPreferences {
edit.putBoolean(key.value, value).apply()
return this
}
internal fun getShowGradeAverage(): Boolean = getBool(PreferenceKey.SHOW_GRADE_AVERAGE)
internal fun getGradeType(): Int = getInt(PreferenceKey.GRADE_TYPE)
internal fun getCourseSortType(): Int = getInt(PreferenceKey.COURSE_SORT_TYPE, 1)
internal fun setCourseSortType(value: Int) { putInt(PreferenceKey.COURSE_SORT_TYPE, value) }
internal fun getSchoolYear(): Int = getInt(PreferenceKey.SCHOOL_YEAR_ID)
internal fun getSchoolYearName(): String = getString(PreferenceKey.SCHOOL_YEAR_NAME)
internal fun getScoreProfileName(): String = getString(PreferenceKey.SCORE_PROFILE_NAME)
internal fun getScoreProfileId(): Int = getInt(PreferenceKey.SCORE_PROFILE_ID)
fun getShowGradeAverage(): Boolean = getBool(PreferenceKey.SHOW_GRADE_AVERAGE)
fun getGradeType(): Int = getInt(PreferenceKey.GRADE_TYPE)
fun getCourseSortType(): Int = getInt(PreferenceKey.COURSE_SORT_TYPE, 1)
fun setCourseSortType(value: Int) { putInt(PreferenceKey.COURSE_SORT_TYPE, value) }
fun getSchoolYear(): Int = getInt(PreferenceKey.SCHOOL_YEAR_ID)
fun getSchoolYearName(): String = getString(PreferenceKey.SCHOOL_YEAR_NAME)
fun getScoreProfileName(): String = getString(PreferenceKey.SCORE_PROFILE_NAME)
fun getScoreProfileId(): Int = getInt(PreferenceKey.SCORE_PROFILE_ID)
fun getParticipationDisplay(): Int = getInt(PreferenceKey.PARTICIPATION_DISPLAY)
fun getParticipationDay(): Int = getInt(PreferenceKey.PARTICIPATION_DAY)
@@ -148,16 +148,12 @@ object QwarkUtil {
else -> pointGradeArray
}
private fun Double.getGradeType(map: Map<Int, String>): String = map[this.roundToInt()] ?: ""
fun getNewGradeType(grade: Int, type: Int): String = when (type) {
GRADE_NUMBERED -> numberedGrades[grade] ?: "error"
GRADE_LETTERED -> letteredGrades[grade] ?: "error"
else -> "error"
}
fun getNumberForLetter(grade: String): Int = lettersToPoints[grade] ?: -1
val timeAtMidnight: Long = GregorianCalendar().apply {
set(Calendar.HOUR_OF_DAY, 0)
set(Calendar.MINUTE, 0)
@@ -170,27 +166,15 @@ object QwarkUtil {
const val GRADE_NUMBERED = 2
const val GRADE_LETTERED = 3
private const val SORT_COURSES_TIME_ASC = 0
private const val SORT_COURSES_TIME_DESC = 1
private const val SORT_COURSES_NAME_ASC = 2
private const val SORT_COURSES_NAME_DESC = 3
private const val SORT_COURSES_ADV = 4
private const val SORT_COURSES_BASIC = 5
private const val SORT_COURSES_AVG_ASC = 6
private const val SORT_COURSES_AVG_DESC = 7
private const val SORT_COURSES_NEXT_EXAM = 8
fun getCoursesSorted(courses: List<CourseExam>, sortType: Int): List<CourseExam> = when (sortType) { // TODO check what ascending and descending really mean lol
SORT_COURSES_TIME_ASC -> courses.asReversed()
SORT_COURSES_TIME_DESC -> courses
SORT_COURSES_NAME_ASC -> courses.sortedBy { c -> c.name }
SORT_COURSES_NAME_DESC -> courses.sortedByDescending { c -> c.name }
SORT_COURSES_ADV -> courses.sortedByDescending { c -> c.advanced }
SORT_COURSES_BASIC -> courses.sortedBy { c -> c.advanced }
SORT_COURSES_AVG_ASC -> courses.sortedBy { c -> c.average.toDouble() }
SORT_COURSES_AVG_DESC -> courses.sortedByDescending { c -> c.average.toDouble() }
else -> courses.sortedBy { c -> if (c.examTime > 1L) c.examTime else Long.MAX_VALUE } // NEXT_EXAM
}
const val SORT_COURSES_TIME_ASC = 0
const val SORT_COURSES_TIME_DESC = 1
const val SORT_COURSES_NAME_ASC = 2
const val SORT_COURSES_NAME_DESC = 3
const val SORT_COURSES_ADV = 4
const val SORT_COURSES_BASIC = 5
const val SORT_COURSES_AVG_ASC = 6
const val SORT_COURSES_AVG_DESC = 7
const val SORT_COURSES_NEXT_EXAM = 8
fun getGradeAsString(grade: Int, leadingZero: Boolean): String = (if (leadingZero && grade < 10) "0" else "") + grade
fun getGradeWithLeadingZero(grade: Int) = "${if (grade < 10) "0" else ""}$grade"
@@ -227,115 +211,4 @@ object QwarkUtil {
}
dialog.show()
}
fun putCourseInBundle(fragment: Fragment, course: CourseExam) {
val bundle = Bundle(11).apply {
putString("name", course.name)
putBoolean("advanced", course.advanced)
putString("icon", course.icon)
putString("colour", course.colour)
putString("average", course.average)
putInt("oralWeighting", course.oralWeighting)
putInt("gradeCount", course.gradeCount)
putLong("time", course.time)
putInt("courseId", course.courseId)
putInt("yearId", course.yearId)
putLong("examTime", course.examTime)
}
fragment.arguments = bundle
}
fun getCourseFromBundle(bundle: Bundle?) = CourseExam(
name = bundle?.getString("name") ?: "",
advanced = bundle?.getBoolean("advanced") ?: false,
icon = bundle?.getString("icon") ?: "",
colour = bundle?.getString("colour") ?: "",
average = bundle?.getString("average") ?: "",
oralWeighting = bundle?.getInt("oralWeighting") ?: 0,
gradeCount = bundle?.getInt("gradeCount") ?: 0,
time = bundle?.getLong("time") ?: 0L,
courseId = bundle?.getInt("courseId") ?: 0,
yearId = bundle?.getInt("yearId") ?: 0,
examTime = bundle?.getLong("examTime") ?: 0L
)
fun putFinalGradeInBundle(fragment: Fragment, finalGrade: FinalGrade) {
val bundle = Bundle(7).apply {
putString("name", finalGrade.name)
putInt("courseId", finalGrade.courseId)
putString("grade", finalGrade.grade)
putString("type", finalGrade.type)
putString("note", finalGrade.note)
putInt("finalGradeId", finalGrade.finalGradeId)
putInt("scoreProfileId", finalGrade.scoreProfileId)
}
fragment.arguments = bundle
}
fun getFinalGradeFromBundle(bundle: Bundle?) = FinalGrade(
name = bundle?.getString("name") ?: "",
courseId = bundle?.getInt("courseId") ?: 0,
grade = bundle?.getString("grade") ?: "",
type = bundle?.getString("type") ?: "",
note = bundle?.getString("note") ?: "",
finalGradeId = bundle?.getInt("finalGradeId") ?: 0,
scoreProfileId = bundle?.getInt("scoreProfileId") ?: 0
)
fun putGradeInBundle(fragment: Fragment, grade: Grade) {
val bundle = Bundle(8).apply {
putInt("grade", grade.grade)
putString("note", grade.note)
putBoolean("verbal", grade.verbal)
putLong("time", grade.time)
putInt("weighting", grade.weighting)
putLong("examTime", grade.examTime)
putInt("gradeId", grade.gradeId)
putInt("courseId", grade.courseId)
}
fragment.arguments = bundle
}
fun getGradeFromBundle(bundle: Bundle?) = Grade(
grade = bundle?.getInt("grade") ?: 0,
note = bundle?.getString("note") ?: "",
verbal = bundle?.getBoolean("verbal") ?: false,
time = bundle?.getLong("time") ?: 0L,
weighting = bundle?.getInt("weighting") ?: 0,
examTime = bundle?.getLong("examTime") ?: 0L,
gradeId = bundle?.getInt("gradeId") ?: 0,
courseId = bundle?.getInt("courseId") ?: 0
)
fun putNoteInBundle(fragment: Fragment, note: Note) {
val bundle = Bundle(5).apply {
putString("content", note.content)
putBoolean("dismissed", note.dismissed)
putLong("time", note.time)
putString("category", note.category)
putInt("noteId", note.noteId)
}
fragment.arguments = bundle
}
fun getNoteFromBundle(bundle: Bundle?) = Note(
content = bundle?.getString("content") ?: "",
dismissed = bundle?.getBoolean("dismissed") ?: false,
time = bundle?.getLong("time") ?: 0L,
category = bundle?.getString("category") ?: "",
noteId = bundle?.getInt("noteId") ?: 0
)
fun getCourseExamAsCourse(c: CourseExam): Course = Course(
name = c.name,
advanced = c.advanced,
icon = c.icon,
colour = c.colour,
average = c.average,
oralWeighting = c.oralWeighting,
gradeCount = c.gradeCount,
time = c.time,
courseId = c.courseId,
yearId = c.yearId
)
}
@@ -29,4 +29,5 @@ class CourseViewModel(application: Application) : QwarkViewModel(application) {
fun insert(course: Course) = doAsync { repo.insert(course) }
fun update(course: Course) = doAsync { repo.update(course) }
fun delete(course: Course) = doAsync { repo.delete(course) }
fun getCourse(courseId: Int): CourseExam = returnBlocking { repo.getCourse(courseId) }
}
@@ -14,7 +14,7 @@ import java.lang.NumberFormatException
class FinalsViewModel(app: Application) : QwarkViewModel(app) {
private val repo = FinalsRepository(app)
val allFinalGrades: LiveData<List<FinalGrade>>? = repo.getFinalGrades(repo.getFinalScoreId())
val allFinalGrades: LiveData<List<FinalGrade>> = repo.getFinalGrades(repo.getFinalScoreId())
fun update(finalGrade: FinalGrade) = viewModelScope.launch {
withContext(Dispatchers.IO) {
@@ -53,7 +53,7 @@ class FinalsViewModel(app: Application) : QwarkViewModel(app) {
private fun checkGrade(finalGrade: FinalGrade): Int = if (finalGrade.grade.toInt() > -1) finalGrade.grade.toInt() else throw NumberFormatException()
fun getFinalGrade(points: Int): Double = when (points) {
fun getFinalGradeScore(points: Int): Double = when (points) {
in 823..900 -> 1.0
in 805..822 -> 1.1
in 787..804 -> 1.2
@@ -107,11 +107,7 @@ class FinalsViewModel(app: Application) : QwarkViewModel(app) {
}
}
fun getCourse(courseId: Int) = runBlocking {
withContext(Dispatchers.IO) {
repo.getCourse(courseId)
}
}
fun getCourse(courseId: Int) = returnBlocking { repo.getCourse(courseId) }
fun getFinalGrade(finalGradeId: Int) = returnBlocking { repo.getFinalGrade(finalGradeId) }
fun getCourseSortType() = repo.getCourseSortType()
}
@@ -25,4 +25,5 @@ class GradeViewModel(application: Application) : QwarkViewModel(application) {
fun delete(gradeId: Int) = doAsync { repo.delete(gradeId) }
fun insert(avg: HistoricalAvg) = doAsync { repo.insert(avg) }
fun getGrade(gradeId: Int) = returnBlocking { repo.getGrade(gradeId) }
}
@@ -9,7 +9,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
class NoteViewModel(application: Application) : AndroidViewModel(application) {
class NoteViewModel(application: Application) : QwarkViewModel(application) {
private val repo = NoteRepository(application)
private val reloadTrigger = MutableLiveData<String>()
@@ -75,4 +75,6 @@ class NoteViewModel(application: Application) : AndroidViewModel(application) {
repo.getAllCategories()
}
}
fun getNote(noteId: Int) = returnBlocking { repo.getNote(noteId) }
}
@@ -13,7 +13,12 @@ class ParticipationCourseViewModel(app: Application) : QwarkViewModel(app) {
repo.getAllParticipationsForCourse(courseId)
}
fun getParticipationCount(participations: List<Participation>) = repo.getParticipationCount(participations)
fun updateParticipation(participation: String, courseId: Int) = doAsync { repo.updateParticipation(participation, courseId) }
fun updateParticipation(participation: String, courseId: Int) = doAsync {
repo.updateParticipation(participation, courseId)
}
fun updateParticipation(timesHandRaised: Int, timesSpoken: Int, participationId: Int) = doAsync {
repo.updateParticipation(timesHandRaised, timesSpoken, participationId)
}
fun createParticipation(timesHandRaised: Int, timesSpoken: Int, time: Long, courseId: Int) = doAsync {
repo.insert(timesHandRaised, timesSpoken, time, courseId)
}
+3 -3
View File
@@ -64,7 +64,7 @@
android:layout_height="match_parent">
<TextView
android:id="@+id/text_above"
android:id="@+id/super_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
@@ -78,7 +78,7 @@
app:layout_constraintEnd_toEndOf="parent"/>
<TextView
android:id="@+id/toolbarTxt"
android:id="@+id/app_bar_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="start"
@@ -91,7 +91,7 @@
android:layout_marginBottom="8dp"
android:singleLine="true"
android:ellipsize="marquee"
app:layout_constraintTop_toBottomOf="@+id/text_above"
app:layout_constraintTop_toBottomOf="@+id/super_title"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
@@ -4,7 +4,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:backgroundTint="@color/colorBackground"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<TextView
+5
View File
@@ -76,6 +76,7 @@
<string name="exam_date">Klausurdatum (yyyy-mm-dd)</string>
<string name="date_format_issue">Dieses Datum kann nicht verarbeitet werden</string>
<string name="exam_past_issue">Vergangene Klausuren müssen benotet werden</string>
<string name="open_participation_fragment">Beteiligung einsehen</string>
<!-- NotesFragment.kt -->
<string name="notes">Notizen</string>
@@ -104,8 +105,12 @@
<string name="participation_ratio_desc">Gemeldet : Gesprochen</string>
<string name="delete_participation_confirmation">Bist du dir sicher, dass du diese Beteiligung löschen möchtest?</string>
<string name="class_session">Klassenzimmermodus</string>
<string name="class_session_resumed">Klassenzimmermodus (fortgesetzt)</string>
<string name="long_press_to_cancel">Lange drücken um abzubrechen</string>
<string name="long_press_to_finish">Lange drücken um zu beenden</string>
<string name="open_grade_fragment">Kurs einsehen</string>
<string name="participation_too_old">Beteiligung zu alt, um fortgesetzt zu werden</string>
<string name="participation_resumable">" (fortsetzbar)"</string>
<string-array name="days">
<item>Montag</item>
+5 -2
View File
@@ -133,7 +133,7 @@
<string name="exam_date">Exam date (yyyy-mm-dd)</string>
<string name="date_format_issue">This date can\'t be parsed</string>
<string name="exam_past_issue">Passed exams must have a grade associated</string>
<string name="open_participation_fragment">Open participation</string>
<string name="open_participation_fragment">View participation</string>
<!-- NotesFragment.kt -->
<string name="notes">Notes</string>
@@ -163,9 +163,12 @@
<string name="participation_ratio_desc">Hand raised : Spoken</string>
<string name="delete_participation_confirmation">Are you sure you want to delete this participation?</string>
<string name="class_session">Class Session</string>
<string name="class_session_resumed">Class Session (resumed)</string>
<string name="long_press_to_cancel">Long-press to cancel</string>
<string name="long_press_to_finish">Long-press to finish</string>
<string name="open_grade_fragment">Open course</string>
<string name="open_grade_fragment">View course</string>
<string name="participation_too_old">Participation too old to be resumed</string>
<string name="participation_resumable">" (resumable)"</string>
<string-array name="days">
<item>Monday</item>