Skip to content

[MBL-19925][Student] NGC Module Extraction and Dashboard Navigation Refactor#3631

Merged
tamaskozmer merged 15 commits intomasterfrom
MBL-19925-prepare-ngc-experience
Apr 14, 2026
Merged

[MBL-19925][Student] NGC Module Extraction and Dashboard Navigation Refactor#3631
tamaskozmer merged 15 commits intomasterfrom
MBL-19925-prepare-ngc-experience

Conversation

@tamaskozmer
Copy link
Copy Markdown
Contributor

@tamaskozmer tamaskozmer commented Apr 7, 2026

Summary

This PR extracts the Next Generation Canvas (NGC) code into a dedicated module (libs/ngc) and introduces a unified navigation event pattern for dashboard widgets. This architectural change prepares the codebase for the NGC experience while maintaining the classic Student app functionality.

Architecture Overview

Module Structure

canvas-api-2
     ↑
pandautils (shared: DashboardBody, DashboardViewModel, navigation handlers, widgets)
     ↑
    ngc (NGC-specific: NGCActivity, NGCDashboardScreen, design system, splash)
     ↑
  student (app: launches NGCActivity, provides RouteMatcherNavigationHandler)

Key Architectural Decisions

1. NGC Module (libs/ngc)

A standalone library module containing all NGC-specific code:

  • NGCActivity - Main entry point for NGC experience
  • NGCTheme - Compose theme using NGC typography and colors
  • NGCDashboardScreen - Dashboard with scrollable header
  • Design System - Standalone implementation (NGCTypography, NGCColors, NGCIconButton) without Horizon dependencies
  • Splash Screen - Initial loading screen with theme setup
  • Navigation - Compose Navigation with NGCComposeNavigationHandler

The NGC module depends only on pandautils (NOT on Horizon), allowing independent evolution of the NGC design system.

2. Dashboard Navigation Events Pattern

Replaced scattered router interfaces with a unified event-based navigation system:

// Sealed interface hierarchy for type-safe navigation
sealed interface DashboardNavigationEvent {
    sealed interface Dashboard : DashboardNavigationEvent { ... }
    sealed interface Courses : DashboardNavigationEvent { ... }
    sealed interface Todo : DashboardNavigationEvent { ... }
    // ... other widget navigation events
}

// Single handler interface
interface DashboardNavigationHandler {
    fun handleDashboardNavigation(event: Dashboard)
    fun handleCoursesNavigation(event: Courses)
    // ...
}

Implementations:

  • RouteMatcherNavigationHandler - For classic Student app (uses RouteMatcher/Fragments)
  • NGCComposeNavigationHandler - For NGC experience (uses Compose Navigation)

3. Shared Dashboard Components

Moved to pandautils for sharing between Student and NGC:

  • DashboardBody - Main content area with pull-to-refresh and widgets
  • DashboardViewModel - Widget loading and state management
  • DashboardUiState - UI state model
  • All widget composables (Courses, Todo, Forecast, Progress, Conferences, etc.)

4. Design System Abstraction

The NGC module includes an abstract design system layer for future NGC vs Legacy Canvas switching:

  • DSIconButton, DSTypography - Abstract interfaces
  • NGCIconButton, NGCTypography - NGC implementations
  • DesignSystem enum with NextGenCanvas and LegacyCanvas values

Benefits

  1. Separation of Concerns - NGC code is isolated from classic app code
  2. Independent Evolution - NGC design system can evolve without affecting Horizon
  3. Code Reuse - Dashboard widgets and logic shared via pandautils
  4. Type Safety - Navigation events provide compile-time safety
  5. Testability - Navigation handlers can be easily mocked

Test plan:

  1. Launch Student app normally → verify classic dashboard works
  2. Enable NGC flag and login → verify NGC dashboard launches
  3. Test all dashboard widgets in both experiences
  4. Verify pull-to-refresh works
  5. Test navigation from widgets (courses, assignments, etc.)

refs: MBL-19925
affects: Student
release note: Internal architecture improvements for the upcoming NGC experience

  • Follow-up e2e test ticket created or not needed
  • Tested in dark mode
  • Tested in light mode
  • Test in landscape mode and/or tablet
  • A11y checked
  • Approve from product

🤖 Generated with Claude Code

Co-Authored-By: Claude [email protected]

tamaskozmer and others added 8 commits March 27, 2026 07:40
More descriptive name for the navigation handler implementation that uses
RouteMatcher for navigation in the classic Student app experience.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
# Conflicts:
#	apps/student/src/main/java/com/instructure/student/features/dashboard/compose/DashboardScreen.kt
@tamaskozmer tamaskozmer changed the title [MBL-19800][Student] NGC Module Extraction and Dashboard Navigation Refactor [MBL-19925][Student] NGC Module Extraction and Dashboard Navigation Refactor Apr 8, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 8, 2026

🧪 Unit Test Results

✅ 📱 Student App

  • Tests: 1210 total, 0 failed, 0 skipped
  • Duration: 0.000s
  • Success Rate: 100%

✅ 🌅 Horizon

  • Tests: 790 total, 0 failed, 0 skipped
  • Duration: 36.434s
  • Success Rate: 100%

✅ 📦 Submodules

  • Tests: 3406 total, 0 failed, 0 skipped
  • Duration: 63.223s
  • Success Rate: 100%

📊 Summary

  • Total Tests: 5406
  • Failed: 0
  • Skipped: 0
  • Status: ✅ All tests passed!

Last updated: Mon, 13 Apr 2026 14:08:47 GMT

Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review Update — Synchronize Push

This push introduces the libs/ngc module (NGC activity, theme, navigation, dashboard, and design system) alongside completing the dashboard refactoring that replaces DashboardRouter with DashboardNavigationHandler.

Summary of Changes

  • New libs/ngc moduleNGCActivity, NGCTheme, NGCNavigation, NGCDashboardScreen, design system components (NGCIconButton, NGCTypography, NGCColors, DSIconButton, DSTypography, DesignSystem), splash screen + VM
  • Dashboard refactoring completedDashboardBody, DashboardViewModel, DashboardUiState moved to pandautils; all widgets now emit SharedFlow<DashboardNavigationEvent> instead of calling routers with FragmentActivity
  • Login flow extended with Experience.NextGenCanvas backed by NEXT_GEN_CANVAS remote config
  • New use casesLoadSplashDataUseCase, SetupPendoTrackingUseCase; ThemeRepository and FeaturesRepository added

Issues Requiring Changes

  • Incorrect accessibility content descriptions — cloud-download button announces "Notebook", edit button announces "Inbox" (strings.xml lines 23–24, NGCDashboardScreen.kt lines 170 & 180)
  • forceRefresh = true default in LoadSplashDataUseCase — will force-refresh all startup data on every cold launch; should be false (line 35)
  • Duplicate ngc_dashboardTitle string — defined in both libs/ngc and libs/pandares; will cause aapt2 duplicate resource error (pandares line 2479)
  • Unreferenced proguard-rules.txt — not referenced by build.gradle.kts, contains unrelated Amazon/AWS rules; should be deleted
  • Unused @Serializable on NGCNavigationRoute — string-based routing is used throughout; annotation creates false impression of type-safe navigation (NGCNavigation.kt line 32)

Positive Notes

  • The DashboardNavigationHandler + DashboardNavigationEvent pattern is well-structured and testable. The accompanying test updates (switching from verify to SharedFlow collection assertions) are thorough and correct.
  • Removing FragmentActivity from all widget callback signatures is a clean improvement — widgets are now properly decoupled from the Android framework.
  • RouteMatcherNavigationHandler correctly centralises all student-app routing in one place, making future navigation changes easier to track.

Comment thread libs/ngc/src/main/res/values/strings.xml Outdated
Comment thread libs/pandares/src/main/res/values/strings.xml Outdated
Comment thread libs/ngc/proguard-rules.txt Outdated
Comment thread libs/ngc/src/main/java/com/instructure/ngc/dashboard/NGCDashboardScreen.kt Outdated
Comment thread libs/ngc/src/main/java/com/instructure/ngc/dashboard/NGCDashboardScreen.kt Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 9, 2026

Student Install Page

claude[bot]
claude Bot previously requested changes Apr 9, 2026
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review Update — Synchronize Event

Summary of Changes

This is a large, well-structured PR with two primary goals:

  1. Navigation architecture refactor: Replaces the DashboardRouter + per-widget *Router/*Behavior pattern with a unified DashboardNavigationHandler + DashboardNavigationEvent sealed interface. All FragmentActivity references are removed from widget composables and ViewModels — a clean move toward proper Compose-first design.

  2. New NGC (Next Gen Canvas) module: Introduces libs/ngc with its own NGCActivity, design system, navigation scaffold, and splash screen, gated behind a new Experience.NextGenCanvas remote-config flag.

The architecture is significantly cleaner after this refactor. Test coverage was maintained and updated throughout.


Issues Requiring Changes

Severity Issue
🔴 Wrong accessibility content descriptions on NGC top bar buttons ("Notebook" for offline content, "Inbox" for customize dashboard)
🔴 LoadSplashDataUseCase defaults forceRefresh = true with a TODO — will force a network call on every cold start
🟡 ngc_dashboardTitle string defined in both libs/ngc and libs/pandares — duplicate resource
🟡 NGCActivity.loginWithToken is public with no @VisibleForTesting guard or debug-build check
🟡 libs/ngc/proguard-rules.txt is unreferenced and should be deleted
🟡 NGCComposeNavigationHandler is entirely stub — worth documenting this is intentional in the PR description

Inline comments mark the specific locations. The accessibility issues are the blocking ones; the rest are improvements.


Positive Changes

  • FragmentActivity cleanly removed from all widget callbacks
  • DashboardViewModel, DashboardUiState, and DashboardBody moved to pandautils for proper reuse by both Student and NGC
  • Navigation events use typed sealed interfaces — exhaustive when prevents missed cases
  • All unit tests updated to assert on emitted navigation events rather than mock verify calls
  • Old per-widget router/behavior classes fully deleted with no dead code left behind

Comment thread libs/ngc/src/main/java/com/instructure/ngc/NGCActivity.kt
Comment thread libs/ngc/proguard-rules.txt Outdated
Comment thread libs/ngc/src/main/res/values/strings.xml
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 9, 2026

📊 Code Coverage Report

⚠️ Student

  • PR Coverage: 42.64%
  • Master Coverage: 42.65%
  • Delta: -0.01%

⚠️ Teacher

  • PR Coverage: 25.31%
  • Master Coverage: 25.37%
  • Delta: -0.07%

✅ Pandautils

  • PR Coverage: 23.88%
  • Master Coverage: 23.69%
  • Delta: +0.19%

📈 Overall Average

  • PR Coverage: 30.61%
  • Master Coverage: 30.57%
  • Delta: +0.04%

Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review Summary

This PR implements a significant architectural improvement: replacing callback-based widget routers with an event-driven navigation system (DashboardNavigationEvent sealed interface + DashboardNavigationHandler), and introduces a new ngc library module with NGCActivity as the entry point for Next Generation Canvas.

The direction is sound and the sealed interface hierarchy is well-structured. A few concerns need attention before merging:

Issues Requiring Changes

  1. MutableSharedFlow missing backpressure config — All five widget ViewModels declare MutableSharedFlow<...>() with no replay or extraBufferCapacity. Events emitted before a collector subscribes are silently dropped. See inline comment on TodoWidgetViewModel.kt.

  2. SplashViewModel has 6 critical TODOs — Unread counts, user settings, launch definitions, and to-do counts are all stubbed out. These affect visible UI (nav badges, course appearance) and feature gating. These should be tracked as explicit tickets or addressed before shipping. See inline comment on SplashViewModel.kt.

  3. DashboardNavigationHandler has no safety net for missing implementations — The interface has 6 required methods; a missing handler silently swallows navigation events. A no-op default with debug logging would make gaps detectable. See inline comment on DashboardNavigationEvent.kt.

  4. Deleted app-layer behaviour tests have no replacementStudentCoursesWidgetBehaviorTest (144 lines) and StudentTodoWidgetBehaviorTest (175 lines) are deleted. The Student-app-specific handler that performs actual routing should have equivalent coverage. See inline comment.

Positive Notes

  • The sealed interface hierarchy for DashboardNavigationEvent is clean and exhaustive — all widget navigation cases are covered.
  • NGCActivity is correctly marked android:exported="false" in the manifest.
  • Moving DashboardViewModel to pandautils improves reusability across apps.
  • The switch from FragmentActivity parameters in callbacks to stateless event objects is the right call for testability.

Copy link
Copy Markdown
Contributor

@adamNagy56 adamNagy56 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QA +1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have test for this

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have test for this

Comment thread libs/ngc/src/main/java/com/instructure/ngc/NGCActivity.kt
Comment thread libs/ngc/src/main/java/com/instructure/ngc/dashboard/NGCDashboardScreen.kt Outdated
Comment thread libs/ngc/src/main/java/com/instructure/ngc/dashboard/NGCDashboardScreen.kt Outdated
@tamaskozmer tamaskozmer merged commit b5a5da5 into master Apr 14, 2026
27 checks passed
@tamaskozmer tamaskozmer deleted the MBL-19925-prepare-ngc-experience branch April 14, 2026 07:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants