From 47d395de7188d959071f0a244848e5eefc91c243 Mon Sep 17 00:00:00 2001 From: Kacper Ziubryniewicz Date: Fri, 29 Nov 2019 23:16:21 +0100 Subject: [PATCH] [Home] Add home grades card. --- .../data/db/modules/grades/GradeDao.java | 14 +- .../ui/modules/home/HomeFragmentV2.kt | 6 +- .../ui/modules/home/cards/HomeGradesCard.kt | 189 ++++++++++++++++++ .../utils/models/ItemGradesSubjectModel.java | 7 +- app/src/main/res/layout/card_home_grades.xml | 37 ++++ app/src/main/res/values/strings.xml | 1 + 6 files changed, 244 insertions(+), 10 deletions(-) create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeGradesCard.kt create mode 100644 app/src/main/res/layout/card_home_grades.xml diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/grades/GradeDao.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/grades/GradeDao.java index 5765d235..43b1ce1c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/grades/GradeDao.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/modules/grades/GradeDao.java @@ -1,18 +1,16 @@ package pl.szczodrzynski.edziennik.data.db.modules.grades; +import android.util.LongSparseArray; + import androidx.lifecycle.LiveData; -import androidx.sqlite.db.SimpleSQLiteQuery; -import androidx.sqlite.db.SupportSQLiteQuery; import androidx.room.Dao; import androidx.room.Insert; import androidx.room.OnConflictStrategy; import androidx.room.Query; import androidx.room.RawQuery; import androidx.room.Transaction; - -import android.util.LongSparseArray; -import android.util.SparseArray; -import android.util.SparseIntArray; +import androidx.sqlite.db.SimpleSQLiteQuery; +import androidx.sqlite.db.SupportSQLiteQuery; import java.util.List; @@ -133,4 +131,8 @@ public abstract class GradeDao { } } } + + public LiveData> getAllFromDate(int profileId, int semester, long date) { + return getAllWhere(profileId, "gradeSemester = " + semester + " AND addedDate > " + date); + } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragmentV2.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragmentV2.kt index 9a92cfe3..ef515456 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragmentV2.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/HomeFragmentV2.kt @@ -28,6 +28,7 @@ import pl.szczodrzynski.edziennik.MainActivity import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.databinding.FragmentHomeV2Binding import pl.szczodrzynski.edziennik.ui.dialogs.home.StudentNumberDialog +import pl.szczodrzynski.edziennik.ui.modules.home.cards.HomeGradesCard import pl.szczodrzynski.edziennik.ui.modules.home.cards.HomeLuckyNumberCard import pl.szczodrzynski.edziennik.ui.modules.home.cards.HomeTimetableCard import pl.szczodrzynski.edziennik.utils.Themes @@ -94,7 +95,8 @@ class HomeFragmentV2 : Fragment(), CoroutineScope { val items = mutableListOf( HomeLuckyNumberCard(0, app, activity, this, app.profile), - HomeTimetableCard(1, app, activity, this, app.profile) + HomeTimetableCard(1, app, activity, this, app.profile), + HomeGradesCard(2, app, activity, this, app.profile) ) val adapter = HomeCardAdapter(items) @@ -138,4 +140,4 @@ class HomeFragmentV2 : Fragment(), CoroutineScope { }) itemTouchHelper.attachToRecyclerView(b.list) } -} \ No newline at end of file +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeGradesCard.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeGradesCard.kt new file mode 100644 index 00000000..01192859 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/home/cards/HomeGradesCard.kt @@ -0,0 +1,189 @@ +/* + * Copyright (c) Kacper Ziubryniewicz 2019-11-29 + */ + +package pl.szczodrzynski.edziennik.ui.modules.home.cards + +import android.graphics.PorterDuff +import android.graphics.PorterDuffColorFilter +import android.graphics.Typeface +import android.os.Build +import android.text.TextUtils +import android.view.LayoutInflater +import android.view.View.GONE +import android.view.View.VISIBLE +import android.view.ViewGroup +import android.widget.FrameLayout +import android.widget.LinearLayout +import android.widget.LinearLayout.HORIZONTAL +import android.widget.LinearLayout.LayoutParams.WRAP_CONTENT +import android.widget.TextView +import androidx.core.graphics.ColorUtils +import androidx.core.view.plusAssign +import androidx.core.view.setMargins +import androidx.lifecycle.Observer +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import pl.szczodrzynski.edziennik.App +import pl.szczodrzynski.edziennik.MainActivity +import pl.szczodrzynski.edziennik.R +import pl.szczodrzynski.edziennik.data.db.modules.grades.Grade.* +import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeFull +import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile +import pl.szczodrzynski.edziennik.data.db.modules.subjects.Subject +import pl.szczodrzynski.edziennik.databinding.CardHomeGradesBinding +import pl.szczodrzynski.edziennik.dp +import pl.szczodrzynski.edziennik.ui.modules.home.HomeCard +import pl.szczodrzynski.edziennik.ui.modules.home.HomeCardAdapter +import pl.szczodrzynski.edziennik.ui.modules.home.HomeFragmentV2 +import pl.szczodrzynski.edziennik.utils.Colors +import pl.szczodrzynski.edziennik.utils.Utils +import pl.szczodrzynski.edziennik.utils.models.ItemGradesSubjectModel +import kotlin.coroutines.CoroutineContext + +class HomeGradesCard( + val id: Int, + val app: App, + val activity: MainActivity, + val fragment: HomeFragmentV2, + val profile: Profile +) : HomeCard, CoroutineScope { + + private var job = Job() + override val coroutineContext: CoroutineContext + get() = job + Dispatchers.Main + + private lateinit var b: CardHomeGradesBinding + + private val grades = mutableListOf() + private val subjects = mutableListOf() + + override fun bind(position: Int, holder: HomeCardAdapter.ViewHolder) { + holder.root.removeAllViews() + b = CardHomeGradesBinding.inflate(LayoutInflater.from(holder.root.context)) + b.root.layoutParams = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply { + setMargins(8.dp) + } + holder.root += b.root + + val sevenDaysAgo = System.currentTimeMillis() - 7 * 24 * 60 * 60 * 1000 + + app.db.gradeDao().getAllFromDate(profile.id, profile.currentSemester, sevenDaysAgo).observe(fragment, Observer { + grades.apply { + clear() + addAll(it) + } + update() + }) + + b.root.setOnClickListener { + activity.loadTarget(MainActivity.DRAWER_ITEM_GRADES) + } + } + + private fun update() { + subjects.clear() + + grades.forEach { grade -> + val model = ItemGradesSubjectModel.searchModelBySubjectId(subjects, grade.subjectId) + ?: run { + subjects.add(ItemGradesSubjectModel( + profile, + Subject(profile.id, grade.subjectId, grade.subjectLongName, grade.subjectShortName), + mutableListOf(), + mutableListOf() + )) + ItemGradesSubjectModel.searchModelBySubjectId(subjects, grade.subjectId) + } + + model?.grades1?.add(grade) + } + + b.gradeList.removeAllViews() + + val textLayoutParams = LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT) + textLayoutParams.setMargins(0, 0, 5.dp, 0) + + val linearLayoutParams = LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT) + linearLayoutParams.setMargins(8.dp, 0, 8.dp, 5.dp) + + subjects.forEach { subject -> + val gradeItem = LinearLayout(b.gradeList.context) + gradeItem.orientation = HORIZONTAL + + var totalWidth = 0 + val maxWidth = (app.resources.displayMetrics.widthPixels - + Utils.dpToPx((if (app.appConfig.miniDrawerVisible) 72 else 0) /*miniDrawer size*/ + + 24 + 24 /*left and right offsets*/ + + 16 /*ellipsize width*/)) / 1.5f + + subject.grades1.onEach { grade -> + val gradeColor = when (app.profile.gradeColorMode) { + Profile.COLOR_MODE_DEFAULT -> grade.color + else -> Colors.gradeToColor(grade) + } + + val gradeName = TextView(gradeItem.context).apply { + text = when (grade.type) { + TYPE_SEMESTER1_PROPOSED, TYPE_SEMESTER2_PROPOSED -> app.getString(R.string.grade_semester_proposed_format, grade.name) + TYPE_SEMESTER1_FINAL, TYPE_SEMESTER2_FINAL -> app.getString(R.string.grade_semester_final_format, grade.name) + TYPE_YEAR_PROPOSED -> app.getString(R.string.grade_year_proposed_format, grade.name) + TYPE_YEAR_FINAL -> app.getString(R.string.grade_year_final_format, grade.name) + else -> grade.name + } + + setTextColor(when (ColorUtils.calculateLuminance(gradeColor) > 0.25) { + true -> 0xff000000 + else -> 0xffffffff + }.toInt()) + + setTypeface(null, Typeface.BOLD) + setBackgroundResource(R.drawable.bg_rounded_4dp) + background.colorFilter = PorterDuffColorFilter(gradeColor, PorterDuff.Mode.MULTIPLY) + setPadding(5.dp, 0, 5.dp, 0) + + measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) + } + + totalWidth += gradeName.measuredWidth + 5.dp + + if (totalWidth >= maxWidth) { + val ellipsisText = TextView(gradeItem.context).apply { + text = app.getString(R.string.ellipsis) + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + setTextAppearance(context, R.style.NavView_TextView) + } else { + setTextAppearance(R.style.NavView_TextView) + } + + setTypeface(null, Typeface.BOLD) + setPadding(0, 0, 0, 0) + } + + gradeItem.addView(ellipsisText, textLayoutParams) + return@forEach + } else { + gradeItem.addView(gradeName, textLayoutParams) + } + } + + val subjectName = TextView(gradeItem.context).apply { + text = app.getString(R.string.grade_subject_format, subject.subject?.longName + ?: "") + ellipsize = TextUtils.TruncateAt.END + setSingleLine() + measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) + } + + gradeItem.addView(subjectName, textLayoutParams) + b.gradeList.addView(gradeItem, linearLayoutParams) + } + + b.noData.visibility = if (subjects.isEmpty()) VISIBLE else GONE + b.gradeList.visibility = if (subjects.isEmpty()) GONE else VISIBLE + } + + override fun unbind(position: Int, holder: HomeCardAdapter.ViewHolder) = Unit +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/ItemGradesSubjectModel.java b/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/ItemGradesSubjectModel.java index 2d2bc614..17c45b7b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/ItemGradesSubjectModel.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/utils/models/ItemGradesSubjectModel.java @@ -1,5 +1,7 @@ package pl.szczodrzynski.edziennik.utils.models; +import androidx.annotation.Nullable; + import java.util.List; import pl.szczodrzynski.edziennik.data.db.modules.grades.GradeFull; @@ -43,8 +45,9 @@ public class ItemGradesSubjectModel { public boolean expandView = false; - public static ItemGradesSubjectModel searchModelBySubjectId(List subjectList, long id) { - for (ItemGradesSubjectModel subjectModel: subjectList) { + public static @Nullable + ItemGradesSubjectModel searchModelBySubjectId(List subjectList, long id) { + for (ItemGradesSubjectModel subjectModel : subjectList) { if (subjectModel.subject != null && subjectModel.subject.id == id) { return subjectModel; } diff --git a/app/src/main/res/layout/card_home_grades.xml b/app/src/main/res/layout/card_home_grades.xml new file mode 100644 index 00000000..8485f829 --- /dev/null +++ b/app/src/main/res/layout/card_home_grades.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1fd6a5d0..ea933cc3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1055,4 +1055,5 @@ Teraz: %s Za chwilę: %s Pozostało lekcji: %d - do %s + z %s