127 lines
12 KiB
TeX
127 lines
12 KiB
TeX
\section{Implementation}
|
|
|
|
The implementation of Study Sprint was carried out as a gradual refinement of both product structure and technical behaviour. Rather than building every feature as an isolated part, the work focused on making the different parts of the application support one coherent study flow. This meant that navigation, CRUD functionality, timer behaviour, persistence, progress tracking, notifications, and onboarding all had to be made to work together as parts of the same product.
|
|
|
|
\vspace{2mm}
|
|
|
|
The application was implemented using React Native with Expo on the frontend and Supabase as the main backend for authentication and persistent user data. In practice, this gave the project a relatively fast development workflow while still allowing the application to move beyond a purely local prototype. At the same time, some state was intentionally kept local on the device, especially when that state was closely tied to temporary interaction flow
|
|
rather than long-term user data.
|
|
|
|
\subsection{Core Data and CRUD Implementation}
|
|
|
|
A large early part of the implementation focused on establishing the application's core academic structure through subjects, assignments, and tasks. These three entities form the conceptual hierarchy of the product:
|
|
|
|
\begin{center}
|
|
\textbf{Subject $\rightarrow$ Assignment $\rightarrow$ Task}
|
|
\end{center}
|
|
|
|
\vspace{2mm}
|
|
|
|
This structure was implemented through full CRUD support for each level. Users can create, edit, view, and delete subjects, assignments, and tasks, and the entities are linked together through their parent-child relationships. Subjects act as the top-level organisational unit, assignments belong to subjects, and tasks belong to assignments.
|
|
|
|
\vspace{2mm}
|
|
|
|
An important implementation decision was to move away from separate create and edit screens wherever the form structure was nearly identical. Instead, the project used upsert-style screens for the main entities. In this pattern, the same screen handles both creation and editing, depending on whether an existing id is passed into the route. This reduced duplicated form logic and made it easier to keep validation, styling, and layout consistent across related flows.
|
|
\clearpage
|
|
|
|
\subsection{Navigation and Screen-Structure Implementation}
|
|
|
|
As the project developed, it became clear that the original screen structure did not reflect the intended product model strongly enough. Earlier versions exposed subjects, assignments, and tasks too much as parallel top-level concepts, even though they were not conceptually independent. This created duplicated views, weaker context, and a flatter structure than intended.
|
|
|
|
\vspace{2mm}
|
|
|
|
To address this, the implementation shifted toward a hierarchy-driven navigation model. Subjects became the main entry point into academic content, while assignments and tasks were accessed through their parent screens instead of being treated as separate top-level browsing areas. Subject details, assignment details, and task details were each implemented more as management hubs than as static detail pages. This made it easier to preserve context and reduced unnecessary navigation noise.
|
|
|
|
\vspace{2mm}
|
|
|
|
The dashboard remained a cross-cutting overview screen. As development progressed, the timer was eventually integrated into the task flow as originally intended, instead of functioning as a detached utility page. This was an important decision, as the product goal was not merely to provide a timer, but to connect focused work directly to actual study tasks.
|
|
|
|
\subsection{Timer, Session Flow, and Break Handling}
|
|
|
|
The timer implementation developed significantly over time. Earlier versions focused mainly on starting and cancelling sessions, but later iterations expanded the flow into a more complete model with linked tasks, persistent active-session recovery, break handling, and safer finalisation rules.
|
|
|
|
\vspace{2mm}
|
|
|
|
A major implementation step was to move the timer into the real task workflow. Instead of starting a generic timer in isolation, the user starts a sprint from a specific task. This makes the session part of the study structure rather than a separate feature beside it. The timer was therefore implemented to receive task context, display relevant task information, and preserve that context when moving between focus sessions and breaks.
|
|
|
|
\clearpage
|
|
|
|
The final timer flow supports focus sessions, short breaks, and long breaks. Shared session defaults were introduced so that common durations could be reused consistently across the app. This reduced hardcoded duplication and helped align task-start, dashboard-start, and timer-entry behaviour. At the same time, the implementation kept room for alternative durations when needed, so that the timer would not become too rigid in practice. A total time window of 1 - 60 minutes was chosen based on the research material suggesting that shorter sessions with frequent breaks were the most beneficial \cite{cirillo_pomodoro_2018, pomodoro_scoping_review}.
|
|
|
|
\vspace{2mm}
|
|
|
|
Another important refinement was the implementation of a small local study-cycle model for break logic. Rather than deciding long breaks based on total historical sessions, the application tracks the current study cycle more narrowly. This makes the break flow behave more like a real continuous work rhythm and avoids misleading long-break prompts based on unrelated earlier activity.
|
|
|
|
\subsection{Persistence and Session Reliability}
|
|
|
|
Persistence in the project was implemented through a combination of Supabase and local device storage. Supabase was used for durable user-specific data such as subjects, assignments, tasks, and recorded session information. Local storage was used for more temporary or interaction-sensitive state, such as active-session recovery, study-cycle continuity, and notification identifiers.
|
|
|
|
\vspace{2mm}
|
|
|
|
This split was a deliberate implementation decision. Not all state in the application serves the same purpose. Academic structure and recorded session history belong in persistent backend storage, while temporary control state related to the current device session is better handled locally for faster and simpler recovery.
|
|
|
|
\vspace{2mm}
|
|
|
|
As the timer flow became more central to the app, reliability problems in session handling became more important. Different screens could detect expired, cancelled, or replaced sessions, but earlier implementations risked treating those cases inconsistently. To reduce that risk, session-finalization logic was moved into a shared lifecycle helper. This ensured that active local session state and stored session records were handled more consistently when sessions ended, expired, or were replaced.
|
|
|
|
\vspace{2mm}
|
|
|
|
This part of the implementation was especially important because the usefulness of the app depends heavily on users being able to trust the timer and recorded study activity. If local UI state and stored session history drift apart, the core study flow becomes less dependable.
|
|
|
|
\subsection{Progress Tracking and Visual Feedback}
|
|
|
|
The application also required implementation work around progress tracking so that planning and studying would feel meaningfully connected. Task completion was used as the main source of truth, and this was then used to calculate assignment-level and subject-level progress.
|
|
|
|
\vspace{2mm}
|
|
|
|
To support this, related tasks were grouped and evaluated so that progress could be displayed in a more understandable way. This included both visual progress bars and simple completion ratios. The implementation intentionally limited these indicators to screens where they were structurally useful, such as subject and assignment detail screens, instead of placing them aggressively throughout the app.
|
|
|
|
\vspace{2mm}
|
|
|
|
This choice was partly technical and partly design-orientated. From a technical side, it required consistent progress calculation based on task state. From a product perspective, it reduced visual clutter and kept browsing views calmer while still making progress visible where it mattered most.
|
|
|
|
\subsection{Notifications and Reminder Logic}
|
|
|
|
Another practical implementation area was assignment reminders through local notifications. These were implemented using Expo Notifications and were tied directly to assignment deadlines. The reminder logic schedules notifications for valid upcoming deadlines and updates or cancels them when assignments are edited or deleted.
|
|
|
|
\vspace{2mm}
|
|
|
|
An important implementation detail here was that notification identifiers were stored locally on the device rather than in the backend. This made reminder clean-up and rescheduling easier while keeping the reminder system lightweight. The project, therefore, avoided a more complex push-notification architecture since that would have added scope without being necessary for the intended use case.
|
|
|
|
\vspace{2mm}
|
|
|
|
Because notification behaviour depends on native capabilities, this part of the project was tested through an Expo development build rather than relying only on Expo Go. That made the implementation more realistic and gave better confidence in behaviour on Android devices.
|
|
|
|
\subsection{Android Internal Testing and Delivery Preparation}
|
|
|
|
Toward the end of the project, the application was also prepared for internal testing through Google Play Console. This required uploading the Android app bundle, configuring an internal test track, adding at least one tester email address, and publishing the internal test so that testers could gain access to the application.
|
|
|
|
\vspace{2mm}
|
|
|
|
After the internal test was published, Google Play Console provided a direct link to the app listing in Google Play. At this stage, the listing used a temporary name and was not publicly searchable. Access was limited to users with the link and the configured tester access. This made it possible to test the distribution flow in a more realistic way without treating the application as a full public release.
|
|
|
|
\vspace{2mm}
|
|
|
|
This step was part of the practical delivery work rather than the product solution itself. It helped confirm that the application could be packaged, uploaded, and distributed through the expected Android testing channel, which was important for validating the project as more than a local development prototype.
|
|
\clearpage
|
|
|
|
\subsection{Onboarding and Low-Friction Flow Improvements}
|
|
|
|
Later implementation work focused more strongly on reducing friction for first-time users and making the main study flow easier to enter. This included guided setup behaviour, clearer help flows, faster sprint-start paths, and more direct routing from dashboard and task screens into the timer.
|
|
|
|
\vspace{2mm}
|
|
|
|
One specific refinement was to make the default sprint flow faster by presenting a sensible default focus duration immediately instead of forcing the user through a configuration step every time. A custom-duration path was still preserved, but it became an optional side path rather than the default interaction.
|
|
|
|
\vspace{2mm}
|
|
|
|
The onboarding flow was also adjusted so that incomplete users are routed into setup more consistently, and the first guided sprint was shortened to a small demo session rather than a full, normal-length focus block. This was done to support the product goal that the app should be understandable and usable quickly, without making the first interaction feel unnecessarily heavy.
|
|
|
|
\subsection{Implementation Outcome}
|
|
|
|
In implementation terms, the final application became much more than a basic CRUD prototype. The main technical result was a mobile application where planning structure, task ownership, timed study sessions, breaks, reminders, progress tracking, and persistence all support the same study workflow.
|
|
|
|
\vspace{2mm}
|
|
|
|
Several of the most important implementation choices were therefore not about adding more features, but about improving coherence between features that already existed. The shift toward hierarchy-driven navigation, task-linked timers, shared lifecycle handling, limited but meaningful progress feedback, and lower-friction session starts all helped move the application closer to its intended product identity.
|