diff --git a/app/src/main/java/com/tomhempel/rbarometer/ui/HandlerOpeningScreen.kt b/app/src/main/java/com/tomhempel/rbarometer/ui/HandlerOpeningScreen.kt index d783d18..532e060 100644 --- a/app/src/main/java/com/tomhempel/rbarometer/ui/HandlerOpeningScreen.kt +++ b/app/src/main/java/com/tomhempel/rbarometer/ui/HandlerOpeningScreen.kt @@ -39,6 +39,7 @@ import com.tomhempel.rbarometer.questionnaire.QuestionnaireValidation import com.google.android.material.button.MaterialButton import com.google.android.material.card.MaterialCardView import com.google.android.material.bottomsheet.BottomSheetDialog +import com.google.android.material.dialog.MaterialAlertDialogBuilder import org.json.JSONObject import com.tomhempel.rbarometer.utils.ScreenLoading import com.tomhempel.rbarometer.utils.ViewUtils @@ -63,11 +64,15 @@ class HandlerOpeningScreen(private val activity: MainActivity) { private lateinit var sessionMetricClientsValue: TextView private lateinit var sessionMetricMeasuresValue: TextView private lateinit var sessionMetricSyncValue: TextView + private lateinit var todaySessionsTitle: TextView + private lateinit var todaySessionsSummary: TextView + private lateinit var todaySessionsContainer: LinearLayout private lateinit var nextStepBannerCard: View private lateinit var nextStepEyebrow: TextView private lateinit var nextStepTitle: TextView private lateinit var nextStepBody: TextView private lateinit var nextStepActionButton: MaterialButton + private lateinit var questionnaireListHost: View private lateinit var questionnaireScroll: View private lateinit var buttonContainer: LinearLayout private lateinit var bottomUploadDock: View @@ -108,6 +113,65 @@ class HandlerOpeningScreen(private val activity: MainActivity) { UPLOAD, } + private data class TodaySession( + val clientCode: String, + val status: String, + val cycle: Int, + val session: Int, + val totalSessions: Int, + val plannedDate: String, + val lastSession: String, + val nextSuggestedDate: String, + val measures: List, + ) + + private val dummyTodaySessions = listOf( + TodaySession( + clientCode = "A102", + status = "Today", + cycle = 3, + session = 2, + totalSessions = 6, + plannedDate = "Today 14:00", + lastSession = "Jun 17", + nextSuggestedDate = "Jul 01", + measures = listOf("WHO-5", "Stress thermometer", "Relationship check"), + ), + TodaySession( + clientCode = "B447", + status = "Overdue", + cycle = 1, + session = 5, + totalSessions = 6, + plannedDate = "Jun 18", + lastSession = "Jun 10", + nextSuggestedDate = "Jun 26", + measures = listOf("Mood check", "Goal tracking", "Counselor score review"), + ), + TodaySession( + clientCode = "C083", + status = "Upcoming", + cycle = 2, + session = 1, + totalSessions = 6, + plannedDate = "Tomorrow", + lastSession = "Jun 21", + nextSuggestedDate = "Jul 08", + measures = listOf("Cycle baseline", "WHO-5", "Stress thermometer"), + ), + TodaySession( + clientCode = "D219", + status = "Inactive", + cycle = 4, + session = 6, + totalSessions = 6, + plannedDate = "Not planned", + lastSession = "Jun 03", + nextSuggestedDate = "On hold", + measures = listOf("End-of-cycle review", "Participation status"), + ), + ) + private fun color(@ColorRes res: Int) = ContextCompat.getColor(activity, res) private fun t(id: String) = LanguageManager.getText(languageID, id) @@ -186,6 +250,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) { bindViews() loadQuestionnaireOrder() + renderTodaySessions() createQuestionnaireButtons() setupCoachDisplay() setupLanguageSpinner() @@ -219,11 +284,15 @@ class HandlerOpeningScreen(private val activity: MainActivity) { sessionMetricClientsValue = activity.findViewById(R.id.sessionMetricClientsValue) sessionMetricMeasuresValue = activity.findViewById(R.id.sessionMetricMeasuresValue) sessionMetricSyncValue = activity.findViewById(R.id.sessionMetricSyncValue) + todaySessionsTitle = activity.findViewById(R.id.todaySessionsTitle) + todaySessionsSummary = activity.findViewById(R.id.todaySessionsSummary) + todaySessionsContainer = activity.findViewById(R.id.todaySessionsContainer) nextStepBannerCard = activity.findViewById(R.id.nextStepBannerCard) nextStepEyebrow = activity.findViewById(R.id.nextStepEyebrow) nextStepTitle = activity.findViewById(R.id.nextStepTitle) nextStepBody = activity.findViewById(R.id.nextStepBody) nextStepActionButton = activity.findViewById(R.id.nextStepActionButton) + questionnaireListHost = activity.findViewById(R.id.questionnaireListHost) questionnaireScroll = activity.findViewById(R.id.questionnaireScroll) bottomUploadDock = activity.findViewById(R.id.bottomUploadDock) questionnaireListLoading = activity.findViewById(R.id.questionnaireListLoading) @@ -242,6 +311,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) { textView.text = hubFallback("Sitzungsinstrumente", "Session measures") applyHubLabels() updateSessionMetrics() + renderTodaySessions() applyCoachDisplay() } @@ -276,6 +346,355 @@ class HandlerOpeningScreen(private val activity: MainActivity) { } } + private fun renderTodaySessions() { + if (!::todaySessionsContainer.isInitialized) return + todaySessionsTitle.text = hubFallback("Sitzungen", "Sessions") + val dueCount = dummyTodaySessions.count { it.status == "Today" || it.status == "Overdue" } + todaySessionsSummary.text = "$dueCount today" + todaySessionsContainer.removeAllViews() + addSessionGroup( + title = hubFallback("Heute", "Today"), + sessions = dummyTodaySessions.filter { it.status == "Today" || it.status == "Overdue" }, + ) + addSessionGroup( + title = hubFallback("Demnächst", "Upcoming"), + sessions = dummyTodaySessions.filter { it.status == "Upcoming" }, + ) + addSessionGroup( + title = hubFallback("Inaktiv", "Inactive"), + sessions = dummyTodaySessions.filter { it.status == "Inactive" }, + ) + } + + private fun addSessionGroup(title: String, sessions: List) { + if (sessions.isEmpty()) return + todaySessionsContainer.addView(TextView(activity).apply { + text = title + setPadding(dp(2), if (todaySessionsContainer.childCount == 0) 0 else dp(14), 0, dp(4)) + setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f) + setTypeface(typeface, android.graphics.Typeface.BOLD) + setTextColor(color(R.color.brand_text_dark)) + }) + sessions.forEach { session -> + todaySessionsContainer.addView(createTodaySessionCard(session)) + } + } + + private fun createTodaySessionCard(session: TodaySession): View { + val card = MaterialCardView(activity).apply { + layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT, + ).also { + it.setMargins(0, 0, 0, dp(10)) + } + radius = dp(14).toFloat() + strokeWidth = dp(if (session.status == "Today") 2 else 1) + setStrokeColor(color(if (session.status == "Overdue") R.color.brand_chip_start_fill else R.color.brand_purple)) + setCardBackgroundColor(color(R.color.brand_header_surface)) + cardElevation = dp(2).toFloat() + } + val content = LinearLayout(activity).apply { + orientation = LinearLayout.VERTICAL + setPadding(dp(16), dp(14), dp(16), dp(14)) + } + val header = LinearLayout(activity).apply { + orientation = LinearLayout.HORIZONTAL + gravity = Gravity.CENTER_VERTICAL + } + val titleBlock = LinearLayout(activity).apply { + orientation = LinearLayout.VERTICAL + layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f) + } + titleBlock.addView(TextView(activity).apply { + text = session.clientCode + setTextSize(TypedValue.COMPLEX_UNIT_SP, 20f) + setTypeface(typeface, android.graphics.Typeface.BOLD) + setTextColor(color(R.color.brand_text_dark)) + }) + titleBlock.addView(TextView(activity).apply { + text = "Cycle ${session.cycle} - Session ${session.session} of ${session.totalSessions}" + setTextSize(TypedValue.COMPLEX_UNIT_SP, 13f) + setTextColor(color(R.color.brand_text_muted)) + }) + header.addView(titleBlock) + header.addView(sessionStatusChip(session.status)) + content.addView(header) + + content.addView(TextView(activity).apply { + text = "Planned: ${session.plannedDate} Last: ${session.lastSession}" + setPadding(0, dp(10), 0, dp(8)) + setTextSize(TypedValue.COMPLEX_UNIT_SP, 13f) + setTextColor(color(R.color.brand_text_dark)) + }) + content.addView(TextView(activity).apply { + text = hubFallback("Startet automatisch", "Starts automatically") + setTextSize(TypedValue.COMPLEX_UNIT_SP, 13f) + setTypeface(typeface, android.graphics.Typeface.BOLD) + setTextColor(color(R.color.brand_text_muted)) + }) + session.measures.forEachIndexed { index, measure -> + content.addView(measureRow(measure, checked = index == 0)) + } + content.addView(scheduleNextDateBlock(session.nextSuggestedDate)) + + val actions = LinearLayout(activity).apply { + orientation = LinearLayout.HORIZONTAL + setPadding(0, dp(12), 0, 0) + } + actions.addView(todayAction("Manage", filled = false, weight = 1f) { + showManageSessionSheet(session) + }) + actions.addView(todayAction("Start session", filled = true, weight = 1.25f)) + content.addView(actions) + card.addView(content) + return card + } + + private fun sessionStatusChip(status: String): TextView = + TextView(activity).apply { + text = status + setTextSize(TypedValue.COMPLEX_UNIT_SP, 12f) + setTypeface(typeface, android.graphics.Typeface.BOLD) + setTextColor(color(if (status == "Upcoming" || status == "Inactive") R.color.brand_chip_locked_text else R.color.brand_text_on_dark)) + setBackgroundResource( + when (status) { + "Overdue" -> R.drawable.bg_chip_amber + "Upcoming", "Inactive" -> R.drawable.bg_chip_locked + else -> R.drawable.bg_chip_green + }, + ) + setPadding(dp(10), dp(6), dp(10), dp(6)) + } + + private fun measureRow(label: String, checked: Boolean): View = + LinearLayout(activity).apply { + orientation = LinearLayout.HORIZONTAL + gravity = Gravity.CENTER_VERTICAL + setPadding(0, dp(7), 0, 0) + addView(TextView(activity).apply { + text = if (checked) "[x]" else "[ ]" + setTextSize(TypedValue.COMPLEX_UNIT_SP, 13f) + setTypeface(typeface, android.graphics.Typeface.BOLD) + setTextColor(color(if (checked) R.color.brand_purple else R.color.brand_text_muted)) + }) + addView(TextView(activity).apply { + text = label + setPadding(dp(8), 0, 0, 0) + setTextSize(TypedValue.COMPLEX_UNIT_SP, 14f) + setTextColor(color(R.color.brand_text_dark)) + }) + } + + private fun scheduleNextDateBlock(suggestedDate: String): View = + LinearLayout(activity).apply { + orientation = LinearLayout.VERTICAL + background = ContextCompat.getDrawable(activity, R.drawable.bg_session_metric) + setPadding(dp(12), dp(10), dp(12), dp(10)) + val lp = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT, + ) + lp.setMargins(0, dp(12), 0, 0) + layoutParams = lp + addView(TextView(activity).apply { + text = hubFallback("Nächsten Termin planen", "Schedule next date") + setTextSize(TypedValue.COMPLEX_UNIT_SP, 11f) + setTextColor(color(R.color.brand_text_muted)) + }) + val row = LinearLayout(activity).apply { + orientation = LinearLayout.HORIZONTAL + gravity = Gravity.CENTER_VERTICAL + setPadding(0, dp(4), 0, 0) + } + row.addView(TextView(activity).apply { + text = suggestedDate + layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f) + setTextSize(TypedValue.COMPLEX_UNIT_SP, 16f) + setTypeface(typeface, android.graphics.Typeface.BOLD) + setTextColor(color(R.color.brand_text_dark)) + }) + row.addView(todayAction("Edit date", filled = false, weight = 0f, fixedWidth = dp(96))) + addView(row) + } + + private fun todayAction( + label: String, + filled: Boolean, + weight: Float, + fixedWidth: Int? = null, + onClick: (() -> Unit)? = null, + ): MaterialButton = + MaterialButton(activity).apply { + layoutParams = LinearLayout.LayoutParams( + fixedWidth ?: 0, + dp(40), + if (fixedWidth == null) weight else 0f, + ).also { it.setMargins(0, 0, dp(8), 0) } + text = label + isAllCaps = false + setTextSize(TypedValue.COMPLEX_UNIT_SP, 12f) + cornerRadius = dp(18) + strokeWidth = dp(1) + insetTop = 0 + insetBottom = 0 + setTextColor(color(if (filled) R.color.brand_text_on_dark else R.color.brand_purple)) + backgroundTintList = ColorStateList.valueOf(color(if (filled) R.color.brand_purple else R.color.brand_header_surface)) + strokeColor = ColorStateList.valueOf(color(R.color.brand_purple)) + setOnClickListener { + if (onClick != null) onClick() + else Toast.makeText(activity, "$label is prototype-only", Toast.LENGTH_SHORT).show() + } + } + + private fun showManageSessionSheet(session: TodaySession) { + val container = LinearLayout(activity).apply { + orientation = LinearLayout.VERTICAL + setBackgroundColor(color(R.color.brand_surface)) + setPadding(dp(20), dp(18), dp(20), dp(18)) + } + + val header = LinearLayout(activity).apply { + orientation = LinearLayout.HORIZONTAL + gravity = Gravity.CENTER_VERTICAL + } + val titleBlock = LinearLayout(activity).apply { + orientation = LinearLayout.VERTICAL + layoutParams = LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1f) + } + titleBlock.addView(TextView(activity).apply { + text = "Manage ${session.clientCode}" + setTextSize(TypedValue.COMPLEX_UNIT_SP, 20f) + setTypeface(typeface, android.graphics.Typeface.BOLD) + setTextColor(color(R.color.brand_text_dark)) + }) + titleBlock.addView(TextView(activity).apply { + text = "Cycle ${session.cycle} - Session ${session.session} of ${session.totalSessions}" + setPadding(0, dp(3), 0, 0) + setTextSize(TypedValue.COMPLEX_UNIT_SP, 13f) + setTextColor(color(R.color.brand_text_muted)) + }) + val closeButton = MaterialButton(activity).apply { + layoutParams = LinearLayout.LayoutParams(dp(78), dp(40)) + text = "Close" + isAllCaps = false + cornerRadius = dp(18) + strokeWidth = dp(1) + insetTop = 0 + insetBottom = 0 + setTextColor(color(R.color.brand_purple)) + backgroundTintList = ColorStateList.valueOf(color(R.color.brand_header_surface)) + strokeColor = ColorStateList.valueOf(color(R.color.brand_header_stroke)) + } + header.addView(titleBlock) + header.addView(closeButton) + + val body = LinearLayout(activity).apply { + orientation = LinearLayout.VERTICAL + setPadding(0, dp(14), 0, 0) + } + body.addView(manageSectionTitle("Client status")) + body.addView(LinearLayout(activity).apply { + orientation = LinearLayout.HORIZONTAL + addView(manageStatusButton("Active", selected = session.status != "Inactive")) + addView(manageStatusButton("Inactive", selected = session.status == "Inactive")) + addView(manageStatusButton("Archived", selected = false)) + }) + body.addView(manageSectionTitle("Scheduling")) + body.addView(manageAction("Edit next planned date", "Current suggestion: ${session.nextSuggestedDate}")) + body.addView(manageAction("Reschedule current session", "Move this session to another date")) + body.addView(manageAction("Skip this occurrence", "Keep the cycle but omit this planned visit")) + body.addView(manageSectionTitle("Session")) + body.addView(manageAction("View session protocol", "${session.measures.size} measures assigned")) + body.addView(manageAction("Add counselor note", "Attach a local note to this client")) + body.addView(manageAction("Sync client data", "Review pending local data for this client")) + body.addView(manageSectionTitle("Lifecycle")) + body.addView(manageAction("Mark no longer participating", "Move client to inactive")) + body.addView(manageAction("Archive client", "Hide from active scheduling")) + body.addView(manageAction("Delete client", "Prototype-only destructive option", destructive = true)) + + val scroll = ScrollView(activity).apply { + layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + dp(430), + ) + isFillViewport = false + addView(body) + } + + container.addView(header) + container.addView(scroll) + + val dialog = MaterialAlertDialogBuilder(activity) + .setView(container) + .create() + closeButton.setOnClickListener { dialog.dismiss() } + dialog.show() + } + + private fun manageSectionTitle(title: String): View = + TextView(activity).apply { + text = title + setPadding(dp(2), dp(14), 0, dp(7)) + setTextSize(TypedValue.COMPLEX_UNIT_SP, 12f) + setTypeface(typeface, android.graphics.Typeface.BOLD) + setTextColor(color(R.color.brand_text_muted)) + } + + private fun manageStatusButton(label: String, selected: Boolean): MaterialButton = + MaterialButton(activity).apply { + layoutParams = LinearLayout.LayoutParams(0, dp(40), 1f).also { + it.setMargins(0, 0, dp(8), 0) + } + text = label + isAllCaps = false + setTextSize(TypedValue.COMPLEX_UNIT_SP, 13f) + cornerRadius = dp(18) + strokeWidth = dp(1) + insetTop = 0 + insetBottom = 0 + setTextColor(color(if (selected) R.color.brand_text_on_dark else R.color.brand_text_dark)) + backgroundTintList = ColorStateList.valueOf( + color(if (selected) R.color.brand_purple else R.color.brand_header_surface), + ) + strokeColor = ColorStateList.valueOf(color(R.color.brand_purple)) + setOnClickListener { + Toast.makeText(activity, "Set status to $label is prototype-only", Toast.LENGTH_SHORT).show() + } + } + + private fun manageAction( + title: String, + subtitle: String, + destructive: Boolean = false, + ): View = + MaterialButton(activity).apply { + layoutParams = LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT, + ).also { it.setMargins(0, 0, 0, dp(8)) } + text = "$title\n$subtitle" + isAllCaps = false + gravity = Gravity.START or Gravity.CENTER_VERTICAL + textAlignment = View.TEXT_ALIGNMENT_VIEW_START + setTextSize(TypedValue.COMPLEX_UNIT_SP, 13f) + cornerRadius = dp(16) + strokeWidth = dp(1) + insetTop = 0 + insetBottom = 0 + setPadding(dp(14), dp(11), dp(14), dp(11)) + setTextColor(color(if (destructive) R.color.brand_destructive_text else R.color.brand_text_dark)) + backgroundTintList = ColorStateList.valueOf( + color(if (destructive) R.color.brand_destructive_fill else R.color.brand_header_surface), + ) + strokeColor = ColorStateList.valueOf( + color(if (destructive) R.color.brand_destructive_fill else R.color.brand_header_stroke), + ) + setOnClickListener { + Toast.makeText(activity, "$title is prototype-only", Toast.LENGTH_SHORT).show() + } + } + private fun loadQuestionnaireOrder() { val serverItems = QuestionnaireCache.getQuestionnaireList(activity) Log.d(TAG, "loadQuestionnaireOrder: serverItems from cache = ${serverItems.map { it.id }}") @@ -765,11 +1184,11 @@ class HandlerOpeningScreen(private val activity: MainActivity) { val hasClients = assignedClientsForUi().isNotEmpty() if (hasClients) { noClientsAssignedText.visibility = View.GONE - textView.visibility = View.VISIBLE - nextStepBannerCard.visibility = View.VISIBLE - questionnaireScroll.visibility = View.VISIBLE + textView.visibility = View.GONE + nextStepBannerCard.visibility = View.GONE + questionnaireListHost.visibility = View.GONE + questionnaireScroll.visibility = View.GONE bottomUploadDock.visibility = View.VISIBLE - updateNextStepBanner() } else { clearLoadedClientState() noClientsAssignedText.text = t("no_clients_assigned") @@ -777,6 +1196,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) { textView.visibility = View.GONE updateSessionMetrics() nextStepBannerCard.visibility = View.GONE + questionnaireListHost.visibility = View.GONE questionnaireScroll.visibility = View.GONE bottomUploadDock.visibility = View.GONE } @@ -784,53 +1204,9 @@ class HandlerOpeningScreen(private val activity: MainActivity) { private fun updateNextStepBanner() { if (!::nextStepBannerCard.isInitialized) return - val total = dynamicButtons.size - if (total == 0) { - nextStepBannerCard.visibility = View.GONE - return - } - if (assignedClientsForUi().isEmpty()) return - - nextStepBannerCard.visibility = View.VISIBLE - val completed = dynamicButtons.count { isCompleted(it) } - nextStepEyebrow.text = hubFallback("Nächster Sitzungsschritt", "Next session step") - nextStepTitle.text = hubFallback("Sitzungsstatus wird geprüft", "Checking session status") - nextStepBody.text = hubFallback("Lokale Daten, Reviews und Synchronisation werden ausgewertet.", "Reviewing local measures, scoring work, and sync status.") + nextStepBannerCard.visibility = View.GONE nextStepActionButton.visibility = View.GONE nextStepActionButton.setOnClickListener(null) - - nextStepJob?.cancel() - val clientCode = selectedClientCode - val token = TokenStore.getToken(activity) - nextStepJob = CoroutineScope(Dispatchers.Main).launch { - val summary = withContext(Dispatchers.IO) { UnuploadedWorkRepository.summarize() } - val needsReview = withContext(Dispatchers.IO) { - if (clientCode.isBlank() || token.isNullOrBlank() || !TokenStore.isSessionValid(activity)) { - false - } else { - ReviewScoresHandler.hasPendingReviewsForClient(activity, token, clientCode) - } - } - val action = when { - summary.pendingQuestionnaires > 0 || summary.pendingScoringReviews > 0 -> NextStepAction.UPLOAD - needsReview -> NextStepAction.REVIEW - completed < total && nextAvailableQuestionnaireButton() != null -> NextStepAction.QUESTIONNAIRE - else -> NextStepAction.NONE - } - val titleKey = when { - action == NextStepAction.UPLOAD -> "next_step_upload_title" - action == NextStepAction.REVIEW -> "next_step_review_title" - completed < total -> "next_step_questionnaire_title" - else -> "next_step_completed_title" - } - val bodyKey = when { - action == NextStepAction.UPLOAD -> "next_step_upload_body" - action == NextStepAction.REVIEW -> "next_step_review_body" - completed < total -> "next_step_questionnaire_body" - else -> "next_step_completed_body" - } - applyNextStepBanner(titleKey, bodyKey, action) - } } private fun applyNextStepBanner(titleKey: String, bodyKey: String, action: NextStepAction) { @@ -1120,6 +1496,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) { } } reviewScoresButton.text = t("review_scores") + reviewScoresButton.visibility = View.GONE uploadButton.text = t("upload") applyHubLabels() applyCoachDisplay() @@ -1230,6 +1607,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) { private fun setupReviewScoresButton() { reviewScoresButton.text = t("review_scores") + reviewScoresButton.visibility = View.GONE reviewScoresButton.setOnClickListener { openReviewScores() } } @@ -1258,7 +1636,7 @@ class HandlerOpeningScreen(private val activity: MainActivity) { } private fun setupUploadButton() { - reviewScoresButton.text = t("review_scores") + reviewScoresButton.visibility = View.GONE uploadButton.text = t("upload") uploadButton.setOnClickListener { TokenStore.ensureLegacyLoginTimestamp(activity) diff --git a/app/src/main/res/layout-sw360dp/opening_screen.xml b/app/src/main/res/layout-sw360dp/opening_screen.xml index c46c28b..0ee5d01 100644 --- a/app/src/main/res/layout-sw360dp/opening_screen.xml +++ b/app/src/main/res/layout-sw360dp/opening_screen.xml @@ -176,6 +176,7 @@ + app:layout_constraintTop_toBottomOf="@id/todaySessionsSection" /> + + + + + + + + + + + + + + + + app:layout_constraintTop_toBottomOf="@id/todaySessionsSection"> + android:src="@drawable/ic_launcher_foreground" /> + app:layout_constraintTop_toBottomOf="@id/todaySessionsSection" /> + + + + + + + + + + + + + + + + app:layout_constraintTop_toBottomOf="@id/todaySessionsSection">