UI polish stretch goals#25
Merged
Merged
Conversation
Update agp version in gradle/libs.versions.toml from 9.0.1 to 9.1.0 to adopt the newer Android Gradle Plugin release. Keeps build tooling up-to-date and includes upstream fixes and improvements.
…d a notification system.
Trosper3
approved these changes
Apr 30, 2026
Trosper3
left a comment
Owner
There was a problem hiding this comment.
I love the notification system and username editing. Nice job!
Contributor
There was a problem hiding this comment.
Pull request overview
This PR bundles several “UI polish stretch goals” into the StudentProductivityApp, including new settings-driven personalization, bulk assignment deletion, and a first pass at assignment notifications (plus build tooling bumps).
Changes:
- Add a unified settings dialog to set display name, choose theme mode, and sync Canvas assignments.
- Add “Clear” (delete all) action on the tasks/schedule screen and introduce notifications infrastructure for upcoming assignments.
- Update build tooling versions (Gradle wrapper / AGP) and adjust a few UI layouts.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
| gradle/wrapper/gradle-wrapper.properties | Bumps Gradle wrapper distribution version. |
| gradle/libs.versions.toml | Updates AGP version in the version catalog. |
| app/build.gradle.kts | Adds dependencies (including duplicate Retrofit entries + ML Kit document scanner). |
| app/src/main/res/layout/item_assignment.xml | Layout constraint tweaks for assignment rows. |
| app/src/main/res/layout/activity_schedule.xml | Adds “Clear” UI element for bulk deletion. |
| app/src/main/res/layout/activity_main.xml | Minor constraint adjustments to main screen layout. |
| app/src/main/java/com/example/studentproductivityapp/viewmodel/AssignmentViewModel.kt | Adds deleteAll() entry point. |
| app/src/main/java/com/example/studentproductivityapp/database/AssignmentRepository.kt | Adds repository deleteAll(). |
| app/src/main/java/com/example/studentproductivityapp/database/AssignmentDao.kt | Adds DAO deleteAll() query. |
| app/src/main/java/com/example/studentproductivityapp/ScheduleActivity.kt | Wires “Clear” action to deleteAll() with confirmation dialog. |
| app/src/main/java/com/example/studentproductivityapp/features/home/MainActivity.kt | Adds greeting-by-time-of-day, settings dialog (name/theme/token), Canvas sync, notification permission request. |
| app/src/main/java/com/example/studentproductivityapp/features/video_lectures/VideoLectureActivity.kt | Switches to AppCompatActivity, loads local transcript, updates YouTube loading/seek behavior. |
| app/src/main/java/com/example/studentproductivityapp/features/notifications/NotificationHelper.kt | Schedules alarms for assignment notifications. |
| app/src/main/java/com/example/studentproductivityapp/features/notifications/AssignmentAlarmReceiver.kt | Posts the notification when the alarm fires. |
| app/src/main/java/com/example/studentproductivityapp/CanvasAPI.kt | Adds Retrofit API client + models for Canvas todo endpoint. |
| app/src/main/assets/NoteGPT_TRANSCRIPT_Lecture 1 Introduction to CS and Programming Using Python.txt | Adds a bundled transcript asset used by VideoLectureActivity. |
| app/src/main/AndroidManifest.xml | Adds notification/alarm permissions and registers the receiver. |
Comments suppressed due to low confidence (1)
app/src/main/java/com/example/studentproductivityapp/features/home/MainActivity.kt:293
- These RadioButton IDs are set to AppCompatDelegate night-mode constants. MODE_NIGHT_FOLLOW_SYSTEM is -1, which equals View.NO_ID, so the "System" option won't behave correctly (RadioGroup.check(-1) clears selection and clicks may not register as expected). Use generated view IDs for the radio buttons and map the selected button to the desired night-mode value separately.
Toast.makeText(this, "Please enter a token", Toast.LENGTH_SHORT).show()
}
}
.setNegativeButton("Cancel", null)
.show()
}
private fun fetchCanvasAssignments(token: String) {
//ensure that the Canvas token has 'Bearer' prefix for enterprise APIs
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+25
to
+38
| <TextView | ||
| android:id="@+id/tvDeleteAssignment" | ||
| android:layout_width="wrap_content" | ||
| android:layout_height="wrap_content" | ||
| 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" | ||
| app:layout_constraintTop_toTopOf="parent" /> |
Comment on lines
+28
to
+32
| try { | ||
| alarmManager.setExact(AlarmManager.RTC_WAKEUP, triggerTime, pendingIntent) | ||
| } catch (e: SecurityException) { | ||
|
|
||
| } |
Comment on lines
+231
to
+244
| val sharedPref = getSharedPreferences("user_prefs", MODE_PRIVATE) | ||
| val isLoggedIn = sharedPref.getBoolean("is_logged_in", false) | ||
|
|
||
| //Default to "User" if not logged in | ||
| val savedName = sharedPref.getString("user_name", "User") | ||
|
|
||
| //fetch current hour of day | ||
| val hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY) | ||
| val timeOfDayGreeting = when (hour) { | ||
| in 0..11 -> "Good Morning" | ||
| in 12..16 -> "Good Afternoon" | ||
| else -> "Good Evening" | ||
| } | ||
|
|
| // Login (Simulated) | ||
| sharedPref.edit().putBoolean("is_logged_in", true).apply() | ||
| sharedPref.edit { putBoolean("is_logged_in", true) } | ||
| Toast.makeText(this, "Logged in as Jerry", Toast.LENGTH_SHORT).show() |
Comment on lines
+24
to
+27
| //For DEMO: Trigger exactly 10 seconds from right now. | ||
| //For PRODUCTION: val triggerTime = assignment.dueDateMillis - (24 * 60 * 60 * 1000) | ||
| val triggerTime = System.currentTimeMillis() + 10000 | ||
|
|
Comment on lines
+25
to
+37
| <TextView | ||
| android:id="@+id/tvDeleteAssignment" | ||
| android:layout_width="wrap_content" | ||
| android:layout_height="wrap_content" | ||
| 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" |
Comment on lines
340
to
+367
| ).show() | ||
| } | ||
| } | ||
| } | ||
|
|
||
| catch (e: Exception) { | ||
| withContext(Dispatchers.Main) { | ||
| Toast.makeText(this@MainActivity, "Canvas Sync Failed", Toast.LENGTH_SHORT) | ||
| .show() | ||
| } | ||
| } | ||
|
|
||
| } | ||
| } | ||
|
|
||
|
|
||
| //-------------------Unified Settings Dialog for Changing name, theme, and Syncing Canvas------------------------------------ | ||
| private fun showSettingsDialog() { | ||
|
|
||
| val sharedPref = getSharedPreferences("user_prefs", Context.MODE_PRIVATE) | ||
| val paddingPx = (24 * resources.displayMetrics.density).toInt() | ||
|
|
||
| val layout = LinearLayout(this).apply { | ||
| orientation = LinearLayout.VERTICAL | ||
| setPadding(paddingPx, paddingPx, paddingPx, paddingPx) | ||
| } | ||
|
|
||
| val nameInput = EditText(this).apply { |
Comment on lines
345
to
352
| catch (e: Exception) { | ||
| withContext(Dispatchers.Main) { | ||
| Toast.makeText(this@MainActivity, "Canvas Sync Failed", Toast.LENGTH_SHORT) | ||
| .show() | ||
| } | ||
| } | ||
|
|
||
| } |
Comment on lines
+1
to
+28
| 00:00:00 | ||
| [SQUEAKING] [RUSTLING] [CLICKING] ANA BELL: All right, so welcome to the first lecture of 6.100L. That's our new number. My name is Ana Bell. That's two separate names, first name Ana, last name Bell-- super confusing. But I've been a lecturer here in the EECS Department for probably almost 10 years now. And I've been doing the intro course for a while. I'm really happy to be teaching this full semester version of 6.100A. So today what we're going to do is go over a little bit of course administrative information, | ||
|
|
||
| 00:00:49 | ||
| and then we'll dive right into some thoughts about computers, high level how they work. And then we'll start going into some Python basics. So we're going to get coding right away. So I highly encourage you, since you're in this class, to download the lecture slides beforehand, to take notes, and run code when I do. Some of the lectures are interactive. And we'll have breaks, so there'll be a place where you can take a break to actually do some coding. And that's important-- | ||
|
|
||
| 00:01:18 | ||
| I call them "you try it" breaks. That's important to make sure that you're actually practicing what we are learning right at this time. The main idea for lectures is, yes, I will do some teaching, but there will also be opportunities for questions and for you guys to try some programming right on the spot. Even if you don't finish writing a program that we start talking about, I will finish it, and we can all talk about it together. And I'll show you some pitfalls and things like that. | ||
|
|
||
| 00:01:46 | ||
| There will be lots of opportunities to practice in this class at various degrees of granularity. And then there's also lots of opportunities that I have in the handouts to do extra practice at home and through a bunch of different resources as well. The reason why I stress participation and practice is because part of the reason you're here is you want to learn how to program. You don't know how to program yet. And programming is actually a skill. it's like math or reading. It's something that you have to practice. | ||
|
|
||
| 00:02:18 | ||
| You can't just watch me type in a bunch of lines of code And then when it comes time to do the quiz, you automatically know how to do it. You need to do it often, more and more so that it becomes sort of second nature. So the three big things you'll get out of this class are knowledge of concepts, obviously-- we're going to learn some computer science ideas-- programming skill, and problem solving-- problem solving skills. Lectures and exams basically help you with your knowledge of-- test your knowledge of concepts | ||
|
|
||
| 00:02:50 | ||
| and help you get knowledge of concepts. Finger exercises give you the programming skills. And the problem sets help you with problem solving. Basically, if you're given an English version of-- a problem in English, how do you go from that to thinking about what computer science concepts can I apply? And then after that, how do I take those computer science concepts and actually do the programming? So what are some topics we'll be covering? We will be, at the core of it, learning computational thinking. | ||
|
|
||
| 00:03:25 | ||
| So in the future, when you encounter a problem, your first thought shouldn't be, How do I mathematically solve this? or, How do I brute force or manually solve this problem? How can I apply computation to help me solve this problem? And throughout these lectures, you're going to see some examples of us applying computation to a problem you might have already seen and maybe solved mathematically, which is pretty cool. Obviously, to get that, we're going to learn the Python programming language. | ||
|
|
||
| 00:03:55 | ||
| Once we get the basics, we're going to see how we can start to structure our code to look a little bit better so we don't just have a bunch of code dumped in a file. We're going to start to organize our code and see how we can make it neat, readable, and modular. And then towards the-- not in this lecture but in a couple of lectures and as a theme throughout this class, we're going to look at some algorithms. They're not super complicated, but they're kind of the base algorithms for a bunch of algorithms | ||
|
|
||
| 00:04:26 | ||
| you might see in the future if you decide to take more CS classes. Lastly, towards the end of the class, we're going to see algorithmic complexity, which basically means we're going to start asking or trying to answer the question, how do we know the programs we write are efficient? We can write programs, but how do we know that they're fast, and how do we know that they don't take up all the memory in the computer? So things like that, comparing different algorithms that do the same thing against each other. | ||
|
|
||
| 00:04:56 |
Comment on lines
106
to
109
| val currentDate = sdf.format(Date()) | ||
| textDateView.text = currentDate | ||
|
|
||
| //settings button |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Thanks for using StudentProductivityApp!
Here's what's new:
Heads up to the game devs out there: at this year's Game Developers Conference, Discord announced a bunch of new ways for devs to grow their games. Take a look at their blog for more info.
Copilot's Overview
This pull request introduces important updates to support new features related to API integration, document scanning, and notifications. The main changes include adding dependencies for Retrofit and Google ML Kit, updating the Android manifest with new permissions, and registering a notification receiver.
Dependency additions:
RetrofitandGson converterdependencies to enable Canvas API calls.Google ML Kit Document Scannerdependency for document scanning functionality.AndroidManifest updates:
AssignmentAlarmReceiveras a broadcast receiver to handle assignment-related notifications.Closes #20