Skip to content

Full Program refactors for clear structure, fragments, readme update, advanced scanner#19

Merged
jerrya-code merged 3 commits into
mainfrom
feature/fragmentMain
Apr 30, 2026
Merged

Full Program refactors for clear structure, fragments, readme update, advanced scanner#19
jerrya-code merged 3 commits into
mainfrom
feature/fragmentMain

Conversation

@Trosper3

@Trosper3 Trosper3 commented Apr 29, 2026

Copy link
Copy Markdown
Owner

Program refactored for better structure, fragments added, Readme Updated to show functionality and structure, advanced scanner feature with AI for page recognition and adding assignments at camera capture

File structure was changed to be more feature focused, consolidating file structure under features to contain the following:
assignments/
campus_map/
home/
pdf_scanner/
video_lectures/

Fragments were added to allow the bottom navigation bar to persist across each of the features

Scanner activity now has a smart scan button that enable AI to recognize pages and capture them for PDF creation
Scanner activity now has functionality to add assignments based on keyword recognition via OCR and user editing post capture.

Closes #21
Closes #22
Closes #23
Closes #24

Copilot AI review requested due to automatic review settings April 29, 2026 22:44
@Trosper3 Trosper3 requested review from jerrya-code and removed request for Copilot April 29, 2026 22:45
@Trosper3 Trosper3 force-pushed the feature/fragmentMain branch from de6e481 to 3648333 Compare April 30, 2026 02:33
Copilot AI review requested due to automatic review settings April 30, 2026 02:33

@jerrya-code jerrya-code left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Nice! Thanks for making these changes

@jerrya-code jerrya-code merged commit 4b5206c into main Apr 30, 2026
3 checks passed
@jerrya-code jerrya-code deleted the feature/fragmentMain branch April 30, 2026 02:39

Copilot AI left a comment

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.

Pull request overview

This PR refactors the app into a more feature-focused structure, introduces fragment-based navigation for the Home/Schedule experience under MainActivity, and adds an “advanced/smart scan” flow using ML Kit Document Scanner + OCR to support PDF creation and assignment creation. It also updates documentation and adjusts navigation so other features can deep-link back into the Schedule tab hosted by MainActivity.

Changes:

  • Refactor navigation: MainActivity hosts HomeFragment and ScheduleFragment via a FragmentContainerView, while other features remain separate activities and deep-link into Schedule using show_schedule.
  • Add “Smart Scan” support in the scanner flow using ML Kit Document Scanner and enrich OCR parsing to extract due dates/titles for assignment creation.
  • Move assignment-related data/model/viewmodel code under features/assignments/* and update README/documentation accordingly.

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
gradle/libs.versions.toml Adds ML Kit Document Scanner dependency version.
app/src/main/res/values/strings.xml Adds strings for Smart Scan and Create Assignment.
app/src/main/res/layout/fragment_schedule.xml New Schedule fragment layout (assignments lists + actions).
app/src/main/res/layout/fragment_home.xml New Home fragment layout (quick view + recent scans).
app/src/main/res/layout/activity_schedule.xml Updates legacy schedule activity layout styling/constraints.
app/src/main/res/layout/activity_main.xml Replaces in-activity content with a fragment container + shared header.
app/src/main/res/layout/activity_campus_map.xml Constrains WebView to fit above the nav bar.
app/src/main/res/layout/activity_camera.xml Adds Smart Scan + Create Assignment controls to the camera UI.
app/src/main/res/layout-w600dp/activity_schedule.xml Adds delete-all control in tablet schedule layout variant.
app/src/main/java/com/example/studentproductivityapp/features/video_lectures/VideoLectureActivity.kt Routes Assignments nav to MainActivity with show_schedule.
app/src/main/java/com/example/studentproductivityapp/features/pdf_scanner/ReviewActivity.kt Adds API annotations around PDF creation lifecycle methods.
app/src/main/java/com/example/studentproductivityapp/features/pdf_scanner/PdfHubActivity.kt Routes Assignments nav to MainActivity with show_schedule.
app/src/main/java/com/example/studentproductivityapp/features/pdf_scanner/NoteParser.kt Adds date/title parsing helpers to support assignment extraction.
app/src/main/java/com/example/studentproductivityapp/features/pdf_scanner/CameraActivity.kt Implements Smart Scan launch + OCR processing + assignment deep link.
app/src/main/java/com/example/studentproductivityapp/features/notifications/NotificationHelper.kt Updates import path to new Assignment package.
app/src/main/java/com/example/studentproductivityapp/features/home/ScheduleFragment.kt New fragment implementation of the assignment tracker UI/logic.
app/src/main/java/com/example/studentproductivityapp/features/home/MainActivity.kt Hosts fragments, updates settings/sync flow, and handles deep-link tab selection.
app/src/main/java/com/example/studentproductivityapp/features/home/HomeFragment.kt New fragment implementation of dashboard quick views.
app/src/main/java/com/example/studentproductivityapp/features/campus_map/CampusMapActivity.kt Routes Assignments nav to MainActivity with show_schedule.
app/src/main/java/com/example/studentproductivityapp/features/assignments/viewmodel/AssignmentViewModel.kt Moves viewmodel into features/assignments/viewmodel.
app/src/main/java/com/example/studentproductivityapp/features/assignments/database/AssignmentRepository.kt Moves repository into features/assignments/database.
app/src/main/java/com/example/studentproductivityapp/features/assignments/database/AssignmentDao.kt Moves DAO into features/assignments/database.
app/src/main/java/com/example/studentproductivityapp/features/assignments/database/Assignment.kt Moves entity into features/assignments/database.
app/src/main/java/com/example/studentproductivityapp/features/assignments/database/AppDatabase.kt Moves Room DB into features/assignments/database.
app/src/main/java/com/example/studentproductivityapp/features/assignments/CanvasAPI.kt Moves Canvas API client under assignments feature.
app/src/main/java/com/example/studentproductivityapp/features/assignments/AssignmentAdapter.kt Moves adapter under assignments feature and updates imports.
app/src/main/java/com/example/studentproductivityapp/features/assignments/AddAssignmentActivity.kt Adds OCR-based prepopulation + schedules notifications on save.
app/src/main/java/com/example/studentproductivityapp/ScheduleActivity.kt Legacy activity updated but no longer manifest-registered.
app/src/main/AndroidManifest.xml Removes ScheduleActivity registration; updates AddAssignmentActivity path.
app/build.gradle.kts Adds ML Kit Document Scanner dependency.
README.md Expanded documentation of features and structure.
.artifacts/.../walkthrough.artifact.md Adds walkthrough artifact describing fragment refactor.
.artifacts/.../task.artifact.md Adds task artifact checklist for the refactor.
.artifacts/.../implementation_plan.artifact.md Adds implementation plan artifact for fragment refactor.
Comments suppressed due to low confidence (1)

app/src/main/java/com/example/studentproductivityapp/features/assignments/AddAssignmentActivity.kt:87

  • scheduleNotification(this, newAssignment) is called with an Assignment that still has the default id = 0 (Room autogenerates it on insert), and NotificationHelper currently keys alarms off assignment.title.hashCode(). This can cause alarm collisions/overwrites (e.g., repeated titles) and makes it hard to update/cancel a specific assignment’s notification later. Also note NotificationHelper currently schedules alarms ~10 seconds from now (demo logic), so this won’t align with dueDateMillis unless you switch it to compute a real trigger time.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if (!canvasAssign.due_at.isNullOrEmpty()) {
try{
try {
val sdf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.getDefault())

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

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

Canvas due_at values are parsed with SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'") without setting the timezone (and with 'Z' treated as a literal). This will interpret the UTC timestamp as local time and shift due dates. Prefer parsing as an Instant/OffsetDateTime (or use a pattern like ...ssX / set sdf.timeZone = UTC) so due dates are correct across timezones.

Suggested change
val sdf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.getDefault())
val sdf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX", Locale.US)

Copilot uses AI. Check for mistakes.
Comment on lines +25 to +29
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="320dp"
android:layout_marginTop="32dp"
android:text="Clear"

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

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

tvDeleteAssignment uses a hard-coded layout_marginStart="320dp" with a start-to-start constraint, which won’t scale across different widths and can be misaligned/off-screen. Prefer constraining it to the end (end-to-end with layout_marginEnd) or chaining it with the header TextView for responsive placement.

Copilot uses AI. Check for mistakes.
Comment on lines +239 to 242
newAssignments.forEach {
assignmentDao.insert(it)
// Schedule notification for each new assignment
NotificationHelper.scheduleNotification(this@MainActivity, it)

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

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

Notifications are scheduled immediately after assignmentDao.insert(it), but the inserted row's generated ID isn't captured and NotificationHelper keys alarms off assignment.title.hashCode(). This can cause different assignments with the same/similar titles to overwrite each other’s alarms and makes cancellation/updates hard. Also, NotificationHelper currently triggers notifications ~10 seconds after scheduling (demo logic), so Canvas-synced assignments won’t notify near their actual due dates—consider scheduling based on dueDateMillis (e.g., dueDate - 24h) once you’re out of demo mode.

Suggested change
newAssignments.forEach {
assignmentDao.insert(it)
// Schedule notification for each new assignment
NotificationHelper.scheduleNotification(this@MainActivity, it)
newAssignments.forEach {
val insertedId = assignmentDao.insert(it)
// Schedule notification using a unique key derived from the persisted row ID
// so assignments with the same title do not overwrite each other's alarms.
val notificationAssignment = it.copy(title = "${it.title}#db:$insertedId")
NotificationHelper.scheduleNotification(this@MainActivity, notificationAssignment)

Copilot uses AI. Check for mistakes.
Comment on lines +86 to +90
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvCompleted"
android:layout_width="0dp"
android:layout_height="0dp"
android:padding="8dp"

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

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

rvCompleted is missing a contentDescription while rvPending has one. For accessibility/screen readers, consider adding a suitable android:contentDescription (potentially distinct from the pending list) to the completed RecyclerView as well.

Copilot uses AI. Check for mistakes.
//ensure that the Canvas token has 'Bearer' prefix for enterprise APIs
val authHeader = if (token.startsWith("Bearer", ignoreCase = true)) token else "Bearer $token"
val assignmentDao = AppDatabase.getDatabase(this@MainActivity).assignmentDao()
val authHeader = if (token.startsWith("Bearer")) token else "Bearer $token"

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

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

fetchCanvasAssignments builds the auth header with a case-sensitive startsWith("Bearer"). This will fail for users who paste tokens starting with e.g. bearer ... or include leading whitespace. Consider trimming and using a case-insensitive check (or normalizing) before prefixing with Bearer .

Suggested change
val authHeader = if (token.startsWith("Bearer")) token else "Bearer $token"
val normalizedToken = token.trim()
val authHeader = if (normalizedToken.startsWith("Bearer ", ignoreCase = true)) {
"Bearer ${normalizedToken.substringAfter(' ').trim()}"
} else {
"Bearer $normalizedToken"
}

Copilot uses AI. Check for mistakes.
Comment on lines 211 to 212
} else {
textDetected.visibility = View.GONE

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

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

In handleDetectedText, the success path makes btnCreateAssignment visible, but the failure path only hides textDetected. This can leave the "Create Assignment" button visible from a previous detection even when the current frame has no match (same issue in the blank-text branch of processImageProxy). Ensure the else path hides the button and clears any related UI state.

Suggested change
} else {
textDetected.visibility = View.GONE
} else {
lastDetectedDate = null
lastDetectedTitle = null
textDetected.text = ""
textDetected.visibility = View.GONE
btnCreateAssignment.visibility = View.GONE

Copilot uses AI. Check for mistakes.
Comment on lines +103 to +106
android:layout_margin="24dp"
android:contentDescription="Add Assignment/HW"
android:src="@android:drawable/ic_input_add"
app:layout_constraintBottom_toBottomOf="parent"

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

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

The FAB contentDescription is hard-coded ("Add Assignment/HW"). To support localization and consistent accessibility text, move this to a @string/... resource and reference it here.

Copilot uses AI. Check for mistakes.
Comment on lines +42 to +50
android:layout_marginStart="320dp"
android:layout_marginTop="32dp"
android:text="Clear"
android:textColor="@color/isu_orange"
android:textSize="21sp"
android:textStyle="bold"
android:clickable="true"
android:focusable="true"
app:layout_constraintStart_toStartOf="parent"

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

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

In the w600dp layout, tvDeleteAssignment is constrained to the parent's start with a hard-coded layout_marginStart="320dp". On tablets (and with the NavigationRail), this will likely place the control inconsistently relative to textToDo/the rail. Prefer constraining it relative to textToDo (end) or to the parent end with layout_marginEnd so it adapts to different widths.

Suggested change
android:layout_marginStart="320dp"
android:layout_marginTop="32dp"
android:text="Clear"
android:textColor="@color/isu_orange"
android:textSize="21sp"
android:textStyle="bold"
android:clickable="true"
android:focusable="true"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginTop="32dp"
android:layout_marginEnd="24dp"
android:text="Clear"
android:textColor="@color/isu_orange"
android:textSize="21sp"
android:textStyle="bold"
android:clickable="true"
android:focusable="true"
app:layout_constraintEnd_toEndOf="parent"

Copilot uses AI. Check for mistakes.
Comment on lines +24 to 28
class ScheduleActivity : AppCompatActivity() {

private lateinit var viewModel: AssignmentViewModel

//open another activity when the user clicks on the add assignment button
override fun onCreate(savedInstanceState: Bundle?) {

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

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

ScheduleActivity appears to be legacy now that navigation deep-links to MainActivity + show_schedule and the manifest entry was removed. Keeping it (and its layouts) risks duplicated logic and confusion for future contributors. Consider deleting it (and activity_schedule* resources) or clearly marking it as non-entry-point/legacy.

Copilot uses AI. Check for mistakes.
Comment thread README.md
Comment on lines +27 to +28
database/: Room persistence layer.
viewmodel/: State management and business logic.

Copilot AI Apr 30, 2026

Copy link

Choose a reason for hiding this comment

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

The README’s package structure section lists database/ and viewmodel/ as top-level modules, but the code in this PR moved these under features/assignments/... (e.g. features/assignments/database, features/assignments/viewmodel). Updating the README to match the actual package paths will prevent confusion for contributors.

Suggested change
database/: Room persistence layer.
viewmodel/: State management and business logic.
features/assignments/database/: Room persistence layer for the assignments feature.
features/assignments/viewmodel/: State management and business logic for the assignments feature.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants