chore: eliminar PROJECT_SETUP.md - #1

Open
Ryusse wants to merge 30 commits into
mainfrom
dev
Open

chore: eliminar PROJECT_SETUP.md#1
Ryusse wants to merge 30 commits into
mainfrom
dev

Conversation

@Ryusse

Copy link
Copy Markdown
Owner

No description provided.

Ryusse added 30 commits July 11, 2026 22:17
…recto
ProfessorCard y tema duplicados sin uso, tests generados con package
com.utp.studyplanner que nunca coincidio con com.example.studyplanner.
…shboard
Completa el UseCase Map de PROJECT_SETUP.md: RF-007 (UpdateSubject),
RF-011 (UpdateTask), RF-013 (MarkTaskComplete), RF-022
(GetPendingTasksBySubject), RF-023 (GetTaskStats). Incluye tests con MockK.
…completado
TaskListScreen era un stub ("Pendiente implementar"). Agrega AddTaskDialog
(materia/prioridad/tipo/deadline), TaskFilterBar (materia/prioridad/estado),
checkbox de completado y boton para iniciar sesion de enfoque por tarea.
Cubre RF-009 a RF-013.
…profesor
FAB y edicion quedaban como TODO. Agrega AddSubjectDialog (dropdown de
profesor, selector de color) y SubjectCard con contador de tareas
pendientes. Cubre RF-005 a RF-008.
…oardViewModel
DashboardScreen calculaba todo ad-hoc desde TaskViewModel y mostraba
"Materia {id}" en vez del nombre real. Ahora usa DashboardViewModel con
GetTaskStatsUseCase y GetPendingTasksBySubjectUseCase (RF-022, RF-023).
RF-017 exigia iniciar focus atado a una tarea especifica, pero no habia
forma de llegar a FocusScreen con un taskId: la pestana Enfoque solo
mostraba "No hay sesion activa" sin entrada posible. Agrega ruta
focus/{taskId} y guarda contra iniciar dos sesiones si ya hay una activa.
Agrega provideDashboardUseCases/provideDashboardViewModel y registra
UpdateTaskUseCase, MarkTaskCompleteUseCase y UpdateSubjectUseCase en
sus respectivos wrappers.
RNF-3.3 pide DB indexada por deadline/materia/estado; Room advertia de
full table scans en cada FK sin indice (professorId, subjectId, taskId).
Agrega los indices y desactiva exportSchema (no se versiona el schema
en este proyecto).
Los tests existentes usaban org.mockito sin la dependencia declarada, no
compilaban. RNF-3.5 pide JUnit4 + MockK, asi que se reescriben con MockK
y se agrega kotlinx-coroutines-test. De paso alinea minSdk=30/targetSdk=36
con RNF-3.4 (estaban en 24/35).
… con icono
FAB extendido (Box+align) reemplaza Scaffold en Materias/Tareas/Profesores,
bottom sheets abren a altura completa, padding de listas consistente
(top 8dp, bottom 88dp para el FAB), y TaskFilterBar muestra icono de estado.
…acion
Room.Callback.onCreate inserta los 7 cursos del semestre (referencia:
CLAUDE.md del vault) con su profesor y horario, solo se ejecuta una vez
cuando la BD se crea por primera vez, asi cualquiera que instale el APK
ve datos reales en vez de una app vacia.
DeleteConfirmDialog (compartido) y DeleteConfirmationDialog (solo profesor)
eran dos componentes casi identicos con estilos distintos (Button relleno
vs TextButton plano). Se elimina el duplicado, Profesores ahora usa el
dialogo compartido con TextButton, igual que el resto. TaskCard tenia un
containerColor explicito que lo desviaba del color por defecto que usan
Materia y Profesor, se quita para que las tres cards se vean iguales.
resumeTimer() llamaba a startTimer() que siempre arrancaba con
timeRemaining = WORK_DURATION y cyclesCompleted = session.cyclesCompleted
(el valor original de creacion, nunca actualizado), asi que pausar y
reanudar volvia a 25:00 y ciclo 1 sin importar cuanto llevaba corriendo.
Ahora runCountdown() recibe el ciclo, fase y tiempo restante actuales
desde el estado en vivo. De paso: la UI mostraba el boton de pausa y
el de reanudar al mismo tiempo siempre, ahora alterna segun timerRunning.
bottomBarRoute compara contra el route pattern exacto (focus/{taskId}),
que nunca coincide con item.route (focus), asi que ningun tab quedaba
seleccionado al iniciar el enfoque desde el icono de una tarea.
Si se elimina la materia (o tarea) de un timer que esta corriendo, el
cascade delete borra la fila de FocusSession en la BD, pero la
coroutine del countdown no estaba enlazada a esa fila y seguia
contando en segundo plano. loadActiveSession ahora cancela el
timerJob cuando el Flow reporta que ya no hay sesion activa.
Las cards de Materia, Profesor y Tarea mostraban los botones de accion
directo en la fila (icono lapiz + icono basura, y en Tarea tambien
timer), ocupando espacio y sin lugar para crecer. CardActionsMenu
(componente compartido) reemplaza eso por un boton de 3 puntos que abre
un bottom sheet con las opciones (Editar, Eliminar, y en Tarea tambien
Iniciar enfoque si no esta completada).
Icon() con tint=Color.Unspecified no hereda LocalContentColor como Text,
directamente desactiva el tinte y muestra el color crudo del vector
(negro), por eso el icono de Editar se veia negro sin importar el tema.
Se usa LocalContentColor.current explicito. De paso se quita el
tint = colorScheme.error en Eliminar, no hay razon para que ese boton
sea rojo distinto al resto, CardAction ya no tiene el parametro tint.
Contador de ciclos sumaba por fase (trabajo o descanso) en vez de por
par completo, entregando solo 2 sesiones de 25min en vez de 4. La
sesion se guardaba en BD al iniciar el timer y quedaba huerfana si el
usuario abandonaba o rechazaba la validacion. Duracion del pomodoro
movida a domain/model/PomodoroPolicy (regla de negocio, no de UI).
El calculo solo contaba el largo de la ultima racha consecutiva en la
BD sin comparar contra la fecha actual, mostrando rachas viejas de
forma indefinida aunque el usuario no estudiara mas.
Deadline en el pasado y titulo/tiempo estimado invalidos solo se
frenaban en el Composable, sin garantia a nivel de dominio. Borrar una
tarea cascadeaba su historial de sesiones sin avisar. Prioridad, tipo
y limite de tareas urgentes centralizados en domain/model (antes
duplicados entre AddTaskDialog y TaskFilterBar, o numero magico en SQL).
Se podian crear dos materias con el mismo codigo. Borrar una materia
cascadeaba sus tareas y el historial de sesiones asociado sin avisar.
Nombre/email/departamento solo se validaban en el Composable, sin
garantia a nivel de dominio; regla movida a domain/model/ProfessorPolicy
y aplicada en Add/UpdateProfessorUseCase. Borrar un profesor cascadeaba
sus materias, tareas y sesiones sin avisar. AddProfessorDialog recibia
el ViewModel completo (unico caso asi en el proyecto); ahora recibe
editingProfessor/onSave/onDismiss como el resto de dialogos.
El card de progreso por materia solo mostraba conteo de pendientes,
sin desglose de completadas (ese dato solo existia de forma global).
Double-checked locking incompleto: no volvia a comprobar INSTANCE
dentro del bloque synchronized antes de construir la base de datos.
StreakCard y PointsCard existian pero no estaban conectados a ningun
ViewModel ni renderizados. Reutilizan GetStreakUseCase/CalculatePointsUseCase
ya existentes (no se duplica logica de negocio).
…rminar
Abandonar una sesion ahora guarda los ciclos realmente completados en
vez de descartar todo (0 ciclos si no se completo ninguno). abandonSession
y validateSession dejaban timerMs/currentCycle/isWorkPhase/phaseIndex con
valores viejos tras terminar, mostrando un timer congelado si el estado
se resucitaba. loadActiveSession ya no muestra sesiones huerfanas de la
BD como activas, solo las limpia (ninguna deberia poder resumirse segun
el diseño original de la app).
Sign up for freeto 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.

1 participant

@Ryusse
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

chore: eliminar PROJECT_SETUP.md - #1

Open
Ryusse wants to merge 30 commits into
mainfrom
dev
Open

chore: eliminar PROJECT_SETUP.md#1
Ryusse wants to merge 30 commits into
mainfrom
dev

Conversation

@Ryusse

Copy link
Copy Markdown
Owner

No description provided.

Ryusse added 30 commits July 11, 2026 22:17
…recto
ProfessorCard y tema duplicados sin uso, tests generados con package
com.utp.studyplanner que nunca coincidio con com.example.studyplanner.
…shboard
Completa el UseCase Map de PROJECT_SETUP.md: RF-007 (UpdateSubject),
RF-011 (UpdateTask), RF-013 (MarkTaskComplete), RF-022
(GetPendingTasksBySubject), RF-023 (GetTaskStats). Incluye tests con MockK.
…completado
TaskListScreen era un stub ("Pendiente implementar"). Agrega AddTaskDialog
(materia/prioridad/tipo/deadline), TaskFilterBar (materia/prioridad/estado),
checkbox de completado y boton para iniciar sesion de enfoque por tarea.
Cubre RF-009 a RF-013.
…profesor
FAB y edicion quedaban como TODO. Agrega AddSubjectDialog (dropdown de
profesor, selector de color) y SubjectCard con contador de tareas
pendientes. Cubre RF-005 a RF-008.
…oardViewModel
DashboardScreen calculaba todo ad-hoc desde TaskViewModel y mostraba
"Materia {id}" en vez del nombre real. Ahora usa DashboardViewModel con
GetTaskStatsUseCase y GetPendingTasksBySubjectUseCase (RF-022, RF-023).
RF-017 exigia iniciar focus atado a una tarea especifica, pero no habia
forma de llegar a FocusScreen con un taskId: la pestana Enfoque solo
mostraba "No hay sesion activa" sin entrada posible. Agrega ruta
focus/{taskId} y guarda contra iniciar dos sesiones si ya hay una activa.
Agrega provideDashboardUseCases/provideDashboardViewModel y registra
UpdateTaskUseCase, MarkTaskCompleteUseCase y UpdateSubjectUseCase en
sus respectivos wrappers.
RNF-3.3 pide DB indexada por deadline/materia/estado; Room advertia de
full table scans en cada FK sin indice (professorId, subjectId, taskId).
Agrega los indices y desactiva exportSchema (no se versiona el schema
en este proyecto).
Los tests existentes usaban org.mockito sin la dependencia declarada, no
compilaban. RNF-3.5 pide JUnit4 + MockK, asi que se reescriben con MockK
y se agrega kotlinx-coroutines-test. De paso alinea minSdk=30/targetSdk=36
con RNF-3.4 (estaban en 24/35).
… con icono
FAB extendido (Box+align) reemplaza Scaffold en Materias/Tareas/Profesores,
bottom sheets abren a altura completa, padding de listas consistente
(top 8dp, bottom 88dp para el FAB), y TaskFilterBar muestra icono de estado.
…acion
Room.Callback.onCreate inserta los 7 cursos del semestre (referencia:
CLAUDE.md del vault) con su profesor y horario, solo se ejecuta una vez
cuando la BD se crea por primera vez, asi cualquiera que instale el APK
ve datos reales en vez de una app vacia.
DeleteConfirmDialog (compartido) y DeleteConfirmationDialog (solo profesor)
eran dos componentes casi identicos con estilos distintos (Button relleno
vs TextButton plano). Se elimina el duplicado, Profesores ahora usa el
dialogo compartido con TextButton, igual que el resto. TaskCard tenia un
containerColor explicito que lo desviaba del color por defecto que usan
Materia y Profesor, se quita para que las tres cards se vean iguales.
resumeTimer() llamaba a startTimer() que siempre arrancaba con
timeRemaining = WORK_DURATION y cyclesCompleted = session.cyclesCompleted
(el valor original de creacion, nunca actualizado), asi que pausar y
reanudar volvia a 25:00 y ciclo 1 sin importar cuanto llevaba corriendo.
Ahora runCountdown() recibe el ciclo, fase y tiempo restante actuales
desde el estado en vivo. De paso: la UI mostraba el boton de pausa y
el de reanudar al mismo tiempo siempre, ahora alterna segun timerRunning.
bottomBarRoute compara contra el route pattern exacto (focus/{taskId}),
que nunca coincide con item.route (focus), asi que ningun tab quedaba
seleccionado al iniciar el enfoque desde el icono de una tarea.
Si se elimina la materia (o tarea) de un timer que esta corriendo, el
cascade delete borra la fila de FocusSession en la BD, pero la
coroutine del countdown no estaba enlazada a esa fila y seguia
contando en segundo plano. loadActiveSession ahora cancela el
timerJob cuando el Flow reporta que ya no hay sesion activa.
Las cards de Materia, Profesor y Tarea mostraban los botones de accion
directo en la fila (icono lapiz + icono basura, y en Tarea tambien
timer), ocupando espacio y sin lugar para crecer. CardActionsMenu
(componente compartido) reemplaza eso por un boton de 3 puntos que abre
un bottom sheet con las opciones (Editar, Eliminar, y en Tarea tambien
Iniciar enfoque si no esta completada).
Icon() con tint=Color.Unspecified no hereda LocalContentColor como Text,
directamente desactiva el tinte y muestra el color crudo del vector
(negro), por eso el icono de Editar se veia negro sin importar el tema.
Se usa LocalContentColor.current explicito. De paso se quita el
tint = colorScheme.error en Eliminar, no hay razon para que ese boton
sea rojo distinto al resto, CardAction ya no tiene el parametro tint.
Contador de ciclos sumaba por fase (trabajo o descanso) en vez de por
par completo, entregando solo 2 sesiones de 25min en vez de 4. La
sesion se guardaba en BD al iniciar el timer y quedaba huerfana si el
usuario abandonaba o rechazaba la validacion. Duracion del pomodoro
movida a domain/model/PomodoroPolicy (regla de negocio, no de UI).
El calculo solo contaba el largo de la ultima racha consecutiva en la
BD sin comparar contra la fecha actual, mostrando rachas viejas de
forma indefinida aunque el usuario no estudiara mas.
Deadline en el pasado y titulo/tiempo estimado invalidos solo se
frenaban en el Composable, sin garantia a nivel de dominio. Borrar una
tarea cascadeaba su historial de sesiones sin avisar. Prioridad, tipo
y limite de tareas urgentes centralizados en domain/model (antes
duplicados entre AddTaskDialog y TaskFilterBar, o numero magico en SQL).
Se podian crear dos materias con el mismo codigo. Borrar una materia
cascadeaba sus tareas y el historial de sesiones asociado sin avisar.
Nombre/email/departamento solo se validaban en el Composable, sin
garantia a nivel de dominio; regla movida a domain/model/ProfessorPolicy
y aplicada en Add/UpdateProfessorUseCase. Borrar un profesor cascadeaba
sus materias, tareas y sesiones sin avisar. AddProfessorDialog recibia
el ViewModel completo (unico caso asi en el proyecto); ahora recibe
editingProfessor/onSave/onDismiss como el resto de dialogos.
El card de progreso por materia solo mostraba conteo de pendientes,
sin desglose de completadas (ese dato solo existia de forma global).
Double-checked locking incompleto: no volvia a comprobar INSTANCE
dentro del bloque synchronized antes de construir la base de datos.
StreakCard y PointsCard existian pero no estaban conectados a ningun
ViewModel ni renderizados. Reutilizan GetStreakUseCase/CalculatePointsUseCase
ya existentes (no se duplica logica de negocio).
…rminar
Abandonar una sesion ahora guarda los ciclos realmente completados en
vez de descartar todo (0 ciclos si no se completo ninguno). abandonSession
y validateSession dejaban timerMs/currentCycle/isWorkPhase/phaseIndex con
valores viejos tras terminar, mostrando un timer congelado si el estado
se resucitaba. loadActiveSession ya no muestra sesiones huerfanas de la
BD como activas, solo las limpia (ninguna deberia poder resumirse segun
el diseño original de la app).
Sign up for freeto 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.

1 participant

@Ryusse
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

chore: eliminar PROJECT_SETUP.md - #1

Open
Ryusse wants to merge 30 commits into
mainfrom
dev
Open

chore: eliminar PROJECT_SETUP.md#1
Ryusse wants to merge 30 commits into
mainfrom
dev

Conversation

@Ryusse

Copy link
Copy Markdown
Owner

No description provided.

Ryusse added 30 commits July 11, 2026 22:17
…recto
ProfessorCard y tema duplicados sin uso, tests generados con package
com.utp.studyplanner que nunca coincidio con com.example.studyplanner.
…shboard
Completa el UseCase Map de PROJECT_SETUP.md: RF-007 (UpdateSubject),
RF-011 (UpdateTask), RF-013 (MarkTaskComplete), RF-022
(GetPendingTasksBySubject), RF-023 (GetTaskStats). Incluye tests con MockK.
…completado
TaskListScreen era un stub ("Pendiente implementar"). Agrega AddTaskDialog
(materia/prioridad/tipo/deadline), TaskFilterBar (materia/prioridad/estado),
checkbox de completado y boton para iniciar sesion de enfoque por tarea.
Cubre RF-009 a RF-013.
…profesor
FAB y edicion quedaban como TODO. Agrega AddSubjectDialog (dropdown de
profesor, selector de color) y SubjectCard con contador de tareas
pendientes. Cubre RF-005 a RF-008.
…oardViewModel
DashboardScreen calculaba todo ad-hoc desde TaskViewModel y mostraba
"Materia {id}" en vez del nombre real. Ahora usa DashboardViewModel con
GetTaskStatsUseCase y GetPendingTasksBySubjectUseCase (RF-022, RF-023).
RF-017 exigia iniciar focus atado a una tarea especifica, pero no habia
forma de llegar a FocusScreen con un taskId: la pestana Enfoque solo
mostraba "No hay sesion activa" sin entrada posible. Agrega ruta
focus/{taskId} y guarda contra iniciar dos sesiones si ya hay una activa.
Agrega provideDashboardUseCases/provideDashboardViewModel y registra
UpdateTaskUseCase, MarkTaskCompleteUseCase y UpdateSubjectUseCase en
sus respectivos wrappers.
RNF-3.3 pide DB indexada por deadline/materia/estado; Room advertia de
full table scans en cada FK sin indice (professorId, subjectId, taskId).
Agrega los indices y desactiva exportSchema (no se versiona el schema
en este proyecto).
Los tests existentes usaban org.mockito sin la dependencia declarada, no
compilaban. RNF-3.5 pide JUnit4 + MockK, asi que se reescriben con MockK
y se agrega kotlinx-coroutines-test. De paso alinea minSdk=30/targetSdk=36
con RNF-3.4 (estaban en 24/35).
… con icono
FAB extendido (Box+align) reemplaza Scaffold en Materias/Tareas/Profesores,
bottom sheets abren a altura completa, padding de listas consistente
(top 8dp, bottom 88dp para el FAB), y TaskFilterBar muestra icono de estado.
…acion
Room.Callback.onCreate inserta los 7 cursos del semestre (referencia:
CLAUDE.md del vault) con su profesor y horario, solo se ejecuta una vez
cuando la BD se crea por primera vez, asi cualquiera que instale el APK
ve datos reales en vez de una app vacia.
DeleteConfirmDialog (compartido) y DeleteConfirmationDialog (solo profesor)
eran dos componentes casi identicos con estilos distintos (Button relleno
vs TextButton plano). Se elimina el duplicado, Profesores ahora usa el
dialogo compartido con TextButton, igual que el resto. TaskCard tenia un
containerColor explicito que lo desviaba del color por defecto que usan
Materia y Profesor, se quita para que las tres cards se vean iguales.
resumeTimer() llamaba a startTimer() que siempre arrancaba con
timeRemaining = WORK_DURATION y cyclesCompleted = session.cyclesCompleted
(el valor original de creacion, nunca actualizado), asi que pausar y
reanudar volvia a 25:00 y ciclo 1 sin importar cuanto llevaba corriendo.
Ahora runCountdown() recibe el ciclo, fase y tiempo restante actuales
desde el estado en vivo. De paso: la UI mostraba el boton de pausa y
el de reanudar al mismo tiempo siempre, ahora alterna segun timerRunning.
bottomBarRoute compara contra el route pattern exacto (focus/{taskId}),
que nunca coincide con item.route (focus), asi que ningun tab quedaba
seleccionado al iniciar el enfoque desde el icono de una tarea.
Si se elimina la materia (o tarea) de un timer que esta corriendo, el
cascade delete borra la fila de FocusSession en la BD, pero la
coroutine del countdown no estaba enlazada a esa fila y seguia
contando en segundo plano. loadActiveSession ahora cancela el
timerJob cuando el Flow reporta que ya no hay sesion activa.
Las cards de Materia, Profesor y Tarea mostraban los botones de accion
directo en la fila (icono lapiz + icono basura, y en Tarea tambien
timer), ocupando espacio y sin lugar para crecer. CardActionsMenu
(componente compartido) reemplaza eso por un boton de 3 puntos que abre
un bottom sheet con las opciones (Editar, Eliminar, y en Tarea tambien
Iniciar enfoque si no esta completada).
Icon() con tint=Color.Unspecified no hereda LocalContentColor como Text,
directamente desactiva el tinte y muestra el color crudo del vector
(negro), por eso el icono de Editar se veia negro sin importar el tema.
Se usa LocalContentColor.current explicito. De paso se quita el
tint = colorScheme.error en Eliminar, no hay razon para que ese boton
sea rojo distinto al resto, CardAction ya no tiene el parametro tint.
Contador de ciclos sumaba por fase (trabajo o descanso) en vez de por
par completo, entregando solo 2 sesiones de 25min en vez de 4. La
sesion se guardaba en BD al iniciar el timer y quedaba huerfana si el
usuario abandonaba o rechazaba la validacion. Duracion del pomodoro
movida a domain/model/PomodoroPolicy (regla de negocio, no de UI).
El calculo solo contaba el largo de la ultima racha consecutiva en la
BD sin comparar contra la fecha actual, mostrando rachas viejas de
forma indefinida aunque el usuario no estudiara mas.
Deadline en el pasado y titulo/tiempo estimado invalidos solo se
frenaban en el Composable, sin garantia a nivel de dominio. Borrar una
tarea cascadeaba su historial de sesiones sin avisar. Prioridad, tipo
y limite de tareas urgentes centralizados en domain/model (antes
duplicados entre AddTaskDialog y TaskFilterBar, o numero magico en SQL).
Se podian crear dos materias con el mismo codigo. Borrar una materia
cascadeaba sus tareas y el historial de sesiones asociado sin avisar.
Nombre/email/departamento solo se validaban en el Composable, sin
garantia a nivel de dominio; regla movida a domain/model/ProfessorPolicy
y aplicada en Add/UpdateProfessorUseCase. Borrar un profesor cascadeaba
sus materias, tareas y sesiones sin avisar. AddProfessorDialog recibia
el ViewModel completo (unico caso asi en el proyecto); ahora recibe
editingProfessor/onSave/onDismiss como el resto de dialogos.
El card de progreso por materia solo mostraba conteo de pendientes,
sin desglose de completadas (ese dato solo existia de forma global).
Double-checked locking incompleto: no volvia a comprobar INSTANCE
dentro del bloque synchronized antes de construir la base de datos.
StreakCard y PointsCard existian pero no estaban conectados a ningun
ViewModel ni renderizados. Reutilizan GetStreakUseCase/CalculatePointsUseCase
ya existentes (no se duplica logica de negocio).
…rminar
Abandonar una sesion ahora guarda los ciclos realmente completados en
vez de descartar todo (0 ciclos si no se completo ninguno). abandonSession
y validateSession dejaban timerMs/currentCycle/isWorkPhase/phaseIndex con
valores viejos tras terminar, mostrando un timer congelado si el estado
se resucitaba. loadActiveSession ya no muestra sesiones huerfanas de la
BD como activas, solo las limpia (ninguna deberia poder resumirse segun
el diseño original de la app).
Sign up for freeto 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.

1 participant

@Ryusse
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

chore: eliminar PROJECT_SETUP.md - #1

Open
Ryusse wants to merge 30 commits into
mainfrom
dev
Open

chore: eliminar PROJECT_SETUP.md#1
Ryusse wants to merge 30 commits into
mainfrom
dev

Conversation

@Ryusse

Copy link
Copy Markdown
Owner

No description provided.

Ryusse added 30 commits July 11, 2026 22:17
…recto
ProfessorCard y tema duplicados sin uso, tests generados con package
com.utp.studyplanner que nunca coincidio con com.example.studyplanner.
…shboard
Completa el UseCase Map de PROJECT_SETUP.md: RF-007 (UpdateSubject),
RF-011 (UpdateTask), RF-013 (MarkTaskComplete), RF-022
(GetPendingTasksBySubject), RF-023 (GetTaskStats). Incluye tests con MockK.
…completado
TaskListScreen era un stub ("Pendiente implementar"). Agrega AddTaskDialog
(materia/prioridad/tipo/deadline), TaskFilterBar (materia/prioridad/estado),
checkbox de completado y boton para iniciar sesion de enfoque por tarea.
Cubre RF-009 a RF-013.
…profesor
FAB y edicion quedaban como TODO. Agrega AddSubjectDialog (dropdown de
profesor, selector de color) y SubjectCard con contador de tareas
pendientes. Cubre RF-005 a RF-008.
…oardViewModel
DashboardScreen calculaba todo ad-hoc desde TaskViewModel y mostraba
"Materia {id}" en vez del nombre real. Ahora usa DashboardViewModel con
GetTaskStatsUseCase y GetPendingTasksBySubjectUseCase (RF-022, RF-023).
RF-017 exigia iniciar focus atado a una tarea especifica, pero no habia
forma de llegar a FocusScreen con un taskId: la pestana Enfoque solo
mostraba "No hay sesion activa" sin entrada posible. Agrega ruta
focus/{taskId} y guarda contra iniciar dos sesiones si ya hay una activa.
Agrega provideDashboardUseCases/provideDashboardViewModel y registra
UpdateTaskUseCase, MarkTaskCompleteUseCase y UpdateSubjectUseCase en
sus respectivos wrappers.
RNF-3.3 pide DB indexada por deadline/materia/estado; Room advertia de
full table scans en cada FK sin indice (professorId, subjectId, taskId).
Agrega los indices y desactiva exportSchema (no se versiona el schema
en este proyecto).
Los tests existentes usaban org.mockito sin la dependencia declarada, no
compilaban. RNF-3.5 pide JUnit4 + MockK, asi que se reescriben con MockK
y se agrega kotlinx-coroutines-test. De paso alinea minSdk=30/targetSdk=36
con RNF-3.4 (estaban en 24/35).
… con icono
FAB extendido (Box+align) reemplaza Scaffold en Materias/Tareas/Profesores,
bottom sheets abren a altura completa, padding de listas consistente
(top 8dp, bottom 88dp para el FAB), y TaskFilterBar muestra icono de estado.
…acion
Room.Callback.onCreate inserta los 7 cursos del semestre (referencia:
CLAUDE.md del vault) con su profesor y horario, solo se ejecuta una vez
cuando la BD se crea por primera vez, asi cualquiera que instale el APK
ve datos reales en vez de una app vacia.
DeleteConfirmDialog (compartido) y DeleteConfirmationDialog (solo profesor)
eran dos componentes casi identicos con estilos distintos (Button relleno
vs TextButton plano). Se elimina el duplicado, Profesores ahora usa el
dialogo compartido con TextButton, igual que el resto. TaskCard tenia un
containerColor explicito que lo desviaba del color por defecto que usan
Materia y Profesor, se quita para que las tres cards se vean iguales.
resumeTimer() llamaba a startTimer() que siempre arrancaba con
timeRemaining = WORK_DURATION y cyclesCompleted = session.cyclesCompleted
(el valor original de creacion, nunca actualizado), asi que pausar y
reanudar volvia a 25:00 y ciclo 1 sin importar cuanto llevaba corriendo.
Ahora runCountdown() recibe el ciclo, fase y tiempo restante actuales
desde el estado en vivo. De paso: la UI mostraba el boton de pausa y
el de reanudar al mismo tiempo siempre, ahora alterna segun timerRunning.
bottomBarRoute compara contra el route pattern exacto (focus/{taskId}),
que nunca coincide con item.route (focus), asi que ningun tab quedaba
seleccionado al iniciar el enfoque desde el icono de una tarea.
Si se elimina la materia (o tarea) de un timer que esta corriendo, el
cascade delete borra la fila de FocusSession en la BD, pero la
coroutine del countdown no estaba enlazada a esa fila y seguia
contando en segundo plano. loadActiveSession ahora cancela el
timerJob cuando el Flow reporta que ya no hay sesion activa.
Las cards de Materia, Profesor y Tarea mostraban los botones de accion
directo en la fila (icono lapiz + icono basura, y en Tarea tambien
timer), ocupando espacio y sin lugar para crecer. CardActionsMenu
(componente compartido) reemplaza eso por un boton de 3 puntos que abre
un bottom sheet con las opciones (Editar, Eliminar, y en Tarea tambien
Iniciar enfoque si no esta completada).
Icon() con tint=Color.Unspecified no hereda LocalContentColor como Text,
directamente desactiva el tinte y muestra el color crudo del vector
(negro), por eso el icono de Editar se veia negro sin importar el tema.
Se usa LocalContentColor.current explicito. De paso se quita el
tint = colorScheme.error en Eliminar, no hay razon para que ese boton
sea rojo distinto al resto, CardAction ya no tiene el parametro tint.
Contador de ciclos sumaba por fase (trabajo o descanso) en vez de por
par completo, entregando solo 2 sesiones de 25min en vez de 4. La
sesion se guardaba en BD al iniciar el timer y quedaba huerfana si el
usuario abandonaba o rechazaba la validacion. Duracion del pomodoro
movida a domain/model/PomodoroPolicy (regla de negocio, no de UI).
El calculo solo contaba el largo de la ultima racha consecutiva en la
BD sin comparar contra la fecha actual, mostrando rachas viejas de
forma indefinida aunque el usuario no estudiara mas.
Deadline en el pasado y titulo/tiempo estimado invalidos solo se
frenaban en el Composable, sin garantia a nivel de dominio. Borrar una
tarea cascadeaba su historial de sesiones sin avisar. Prioridad, tipo
y limite de tareas urgentes centralizados en domain/model (antes
duplicados entre AddTaskDialog y TaskFilterBar, o numero magico en SQL).
Se podian crear dos materias con el mismo codigo. Borrar una materia
cascadeaba sus tareas y el historial de sesiones asociado sin avisar.
Nombre/email/departamento solo se validaban en el Composable, sin
garantia a nivel de dominio; regla movida a domain/model/ProfessorPolicy
y aplicada en Add/UpdateProfessorUseCase. Borrar un profesor cascadeaba
sus materias, tareas y sesiones sin avisar. AddProfessorDialog recibia
el ViewModel completo (unico caso asi en el proyecto); ahora recibe
editingProfessor/onSave/onDismiss como el resto de dialogos.
El card de progreso por materia solo mostraba conteo de pendientes,
sin desglose de completadas (ese dato solo existia de forma global).
Double-checked locking incompleto: no volvia a comprobar INSTANCE
dentro del bloque synchronized antes de construir la base de datos.
StreakCard y PointsCard existian pero no estaban conectados a ningun
ViewModel ni renderizados. Reutilizan GetStreakUseCase/CalculatePointsUseCase
ya existentes (no se duplica logica de negocio).
…rminar
Abandonar una sesion ahora guarda los ciclos realmente completados en
vez de descartar todo (0 ciclos si no se completo ninguno). abandonSession
y validateSession dejaban timerMs/currentCycle/isWorkPhase/phaseIndex con
valores viejos tras terminar, mostrando un timer congelado si el estado
se resucitaba. loadActiveSession ya no muestra sesiones huerfanas de la
BD como activas, solo las limpia (ninguna deberia poder resumirse segun
el diseño original de la app).
Sign up for freeto 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.

1 participant

@Ryusse
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

chore: eliminar PROJECT_SETUP.md - #1

Open
Ryusse wants to merge 30 commits into
mainfrom
dev
Open

chore: eliminar PROJECT_SETUP.md#1
Ryusse wants to merge 30 commits into
mainfrom
dev

Conversation

@Ryusse

Copy link
Copy Markdown
Owner

No description provided.

Ryusse added 30 commits July 11, 2026 22:17
…recto
ProfessorCard y tema duplicados sin uso, tests generados con package
com.utp.studyplanner que nunca coincidio con com.example.studyplanner.
…shboard
Completa el UseCase Map de PROJECT_SETUP.md: RF-007 (UpdateSubject),
RF-011 (UpdateTask), RF-013 (MarkTaskComplete), RF-022
(GetPendingTasksBySubject), RF-023 (GetTaskStats). Incluye tests con MockK.
…completado
TaskListScreen era un stub ("Pendiente implementar"). Agrega AddTaskDialog
(materia/prioridad/tipo/deadline), TaskFilterBar (materia/prioridad/estado),
checkbox de completado y boton para iniciar sesion de enfoque por tarea.
Cubre RF-009 a RF-013.
…profesor
FAB y edicion quedaban como TODO. Agrega AddSubjectDialog (dropdown de
profesor, selector de color) y SubjectCard con contador de tareas
pendientes. Cubre RF-005 a RF-008.
…oardViewModel
DashboardScreen calculaba todo ad-hoc desde TaskViewModel y mostraba
"Materia {id}" en vez del nombre real. Ahora usa DashboardViewModel con
GetTaskStatsUseCase y GetPendingTasksBySubjectUseCase (RF-022, RF-023).
RF-017 exigia iniciar focus atado a una tarea especifica, pero no habia
forma de llegar a FocusScreen con un taskId: la pestana Enfoque solo
mostraba "No hay sesion activa" sin entrada posible. Agrega ruta
focus/{taskId} y guarda contra iniciar dos sesiones si ya hay una activa.
Agrega provideDashboardUseCases/provideDashboardViewModel y registra
UpdateTaskUseCase, MarkTaskCompleteUseCase y UpdateSubjectUseCase en
sus respectivos wrappers.
RNF-3.3 pide DB indexada por deadline/materia/estado; Room advertia de
full table scans en cada FK sin indice (professorId, subjectId, taskId).
Agrega los indices y desactiva exportSchema (no se versiona el schema
en este proyecto).
Los tests existentes usaban org.mockito sin la dependencia declarada, no
compilaban. RNF-3.5 pide JUnit4 + MockK, asi que se reescriben con MockK
y se agrega kotlinx-coroutines-test. De paso alinea minSdk=30/targetSdk=36
con RNF-3.4 (estaban en 24/35).
… con icono
FAB extendido (Box+align) reemplaza Scaffold en Materias/Tareas/Profesores,
bottom sheets abren a altura completa, padding de listas consistente
(top 8dp, bottom 88dp para el FAB), y TaskFilterBar muestra icono de estado.
…acion
Room.Callback.onCreate inserta los 7 cursos del semestre (referencia:
CLAUDE.md del vault) con su profesor y horario, solo se ejecuta una vez
cuando la BD se crea por primera vez, asi cualquiera que instale el APK
ve datos reales en vez de una app vacia.
DeleteConfirmDialog (compartido) y DeleteConfirmationDialog (solo profesor)
eran dos componentes casi identicos con estilos distintos (Button relleno
vs TextButton plano). Se elimina el duplicado, Profesores ahora usa el
dialogo compartido con TextButton, igual que el resto. TaskCard tenia un
containerColor explicito que lo desviaba del color por defecto que usan
Materia y Profesor, se quita para que las tres cards se vean iguales.
resumeTimer() llamaba a startTimer() que siempre arrancaba con
timeRemaining = WORK_DURATION y cyclesCompleted = session.cyclesCompleted
(el valor original de creacion, nunca actualizado), asi que pausar y
reanudar volvia a 25:00 y ciclo 1 sin importar cuanto llevaba corriendo.
Ahora runCountdown() recibe el ciclo, fase y tiempo restante actuales
desde el estado en vivo. De paso: la UI mostraba el boton de pausa y
el de reanudar al mismo tiempo siempre, ahora alterna segun timerRunning.
bottomBarRoute compara contra el route pattern exacto (focus/{taskId}),
que nunca coincide con item.route (focus), asi que ningun tab quedaba
seleccionado al iniciar el enfoque desde el icono de una tarea.
Si se elimina la materia (o tarea) de un timer que esta corriendo, el
cascade delete borra la fila de FocusSession en la BD, pero la
coroutine del countdown no estaba enlazada a esa fila y seguia
contando en segundo plano. loadActiveSession ahora cancela el
timerJob cuando el Flow reporta que ya no hay sesion activa.
Las cards de Materia, Profesor y Tarea mostraban los botones de accion
directo en la fila (icono lapiz + icono basura, y en Tarea tambien
timer), ocupando espacio y sin lugar para crecer. CardActionsMenu
(componente compartido) reemplaza eso por un boton de 3 puntos que abre
un bottom sheet con las opciones (Editar, Eliminar, y en Tarea tambien
Iniciar enfoque si no esta completada).
Icon() con tint=Color.Unspecified no hereda LocalContentColor como Text,
directamente desactiva el tinte y muestra el color crudo del vector
(negro), por eso el icono de Editar se veia negro sin importar el tema.
Se usa LocalContentColor.current explicito. De paso se quita el
tint = colorScheme.error en Eliminar, no hay razon para que ese boton
sea rojo distinto al resto, CardAction ya no tiene el parametro tint.
Contador de ciclos sumaba por fase (trabajo o descanso) en vez de por
par completo, entregando solo 2 sesiones de 25min en vez de 4. La
sesion se guardaba en BD al iniciar el timer y quedaba huerfana si el
usuario abandonaba o rechazaba la validacion. Duracion del pomodoro
movida a domain/model/PomodoroPolicy (regla de negocio, no de UI).
El calculo solo contaba el largo de la ultima racha consecutiva en la
BD sin comparar contra la fecha actual, mostrando rachas viejas de
forma indefinida aunque el usuario no estudiara mas.
Deadline en el pasado y titulo/tiempo estimado invalidos solo se
frenaban en el Composable, sin garantia a nivel de dominio. Borrar una
tarea cascadeaba su historial de sesiones sin avisar. Prioridad, tipo
y limite de tareas urgentes centralizados en domain/model (antes
duplicados entre AddTaskDialog y TaskFilterBar, o numero magico en SQL).
Se podian crear dos materias con el mismo codigo. Borrar una materia
cascadeaba sus tareas y el historial de sesiones asociado sin avisar.
Nombre/email/departamento solo se validaban en el Composable, sin
garantia a nivel de dominio; regla movida a domain/model/ProfessorPolicy
y aplicada en Add/UpdateProfessorUseCase. Borrar un profesor cascadeaba
sus materias, tareas y sesiones sin avisar. AddProfessorDialog recibia
el ViewModel completo (unico caso asi en el proyecto); ahora recibe
editingProfessor/onSave/onDismiss como el resto de dialogos.
El card de progreso por materia solo mostraba conteo de pendientes,
sin desglose de completadas (ese dato solo existia de forma global).
Double-checked locking incompleto: no volvia a comprobar INSTANCE
dentro del bloque synchronized antes de construir la base de datos.
StreakCard y PointsCard existian pero no estaban conectados a ningun
ViewModel ni renderizados. Reutilizan GetStreakUseCase/CalculatePointsUseCase
ya existentes (no se duplica logica de negocio).
…rminar
Abandonar una sesion ahora guarda los ciclos realmente completados en
vez de descartar todo (0 ciclos si no se completo ninguno). abandonSession
y validateSession dejaban timerMs/currentCycle/isWorkPhase/phaseIndex con
valores viejos tras terminar, mostrando un timer congelado si el estado
se resucitaba. loadActiveSession ya no muestra sesiones huerfanas de la
BD como activas, solo las limpia (ninguna deberia poder resumirse segun
el diseño original de la app).
Sign up for freeto 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.

1 participant

@Ryusse
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

chore: eliminar PROJECT_SETUP.md - #1

Open
Ryusse wants to merge 30 commits into
mainfrom
dev
Open

chore: eliminar PROJECT_SETUP.md#1
Ryusse wants to merge 30 commits into
mainfrom
dev

Conversation

@Ryusse

Copy link
Copy Markdown
Owner

No description provided.

Ryusse added 30 commits July 11, 2026 22:17
…recto
ProfessorCard y tema duplicados sin uso, tests generados con package
com.utp.studyplanner que nunca coincidio con com.example.studyplanner.
…shboard
Completa el UseCase Map de PROJECT_SETUP.md: RF-007 (UpdateSubject),
RF-011 (UpdateTask), RF-013 (MarkTaskComplete), RF-022
(GetPendingTasksBySubject), RF-023 (GetTaskStats). Incluye tests con MockK.
…completado
TaskListScreen era un stub ("Pendiente implementar"). Agrega AddTaskDialog
(materia/prioridad/tipo/deadline), TaskFilterBar (materia/prioridad/estado),
checkbox de completado y boton para iniciar sesion de enfoque por tarea.
Cubre RF-009 a RF-013.
…profesor
FAB y edicion quedaban como TODO. Agrega AddSubjectDialog (dropdown de
profesor, selector de color) y SubjectCard con contador de tareas
pendientes. Cubre RF-005 a RF-008.
…oardViewModel
DashboardScreen calculaba todo ad-hoc desde TaskViewModel y mostraba
"Materia {id}" en vez del nombre real. Ahora usa DashboardViewModel con
GetTaskStatsUseCase y GetPendingTasksBySubjectUseCase (RF-022, RF-023).
RF-017 exigia iniciar focus atado a una tarea especifica, pero no habia
forma de llegar a FocusScreen con un taskId: la pestana Enfoque solo
mostraba "No hay sesion activa" sin entrada posible. Agrega ruta
focus/{taskId} y guarda contra iniciar dos sesiones si ya hay una activa.
Agrega provideDashboardUseCases/provideDashboardViewModel y registra
UpdateTaskUseCase, MarkTaskCompleteUseCase y UpdateSubjectUseCase en
sus respectivos wrappers.
RNF-3.3 pide DB indexada por deadline/materia/estado; Room advertia de
full table scans en cada FK sin indice (professorId, subjectId, taskId).
Agrega los indices y desactiva exportSchema (no se versiona el schema
en este proyecto).
Los tests existentes usaban org.mockito sin la dependencia declarada, no
compilaban. RNF-3.5 pide JUnit4 + MockK, asi que se reescriben con MockK
y se agrega kotlinx-coroutines-test. De paso alinea minSdk=30/targetSdk=36
con RNF-3.4 (estaban en 24/35).
… con icono
FAB extendido (Box+align) reemplaza Scaffold en Materias/Tareas/Profesores,
bottom sheets abren a altura completa, padding de listas consistente
(top 8dp, bottom 88dp para el FAB), y TaskFilterBar muestra icono de estado.
…acion
Room.Callback.onCreate inserta los 7 cursos del semestre (referencia:
CLAUDE.md del vault) con su profesor y horario, solo se ejecuta una vez
cuando la BD se crea por primera vez, asi cualquiera que instale el APK
ve datos reales en vez de una app vacia.
DeleteConfirmDialog (compartido) y DeleteConfirmationDialog (solo profesor)
eran dos componentes casi identicos con estilos distintos (Button relleno
vs TextButton plano). Se elimina el duplicado, Profesores ahora usa el
dialogo compartido con TextButton, igual que el resto. TaskCard tenia un
containerColor explicito que lo desviaba del color por defecto que usan
Materia y Profesor, se quita para que las tres cards se vean iguales.
resumeTimer() llamaba a startTimer() que siempre arrancaba con
timeRemaining = WORK_DURATION y cyclesCompleted = session.cyclesCompleted
(el valor original de creacion, nunca actualizado), asi que pausar y
reanudar volvia a 25:00 y ciclo 1 sin importar cuanto llevaba corriendo.
Ahora runCountdown() recibe el ciclo, fase y tiempo restante actuales
desde el estado en vivo. De paso: la UI mostraba el boton de pausa y
el de reanudar al mismo tiempo siempre, ahora alterna segun timerRunning.
bottomBarRoute compara contra el route pattern exacto (focus/{taskId}),
que nunca coincide con item.route (focus), asi que ningun tab quedaba
seleccionado al iniciar el enfoque desde el icono de una tarea.
Si se elimina la materia (o tarea) de un timer que esta corriendo, el
cascade delete borra la fila de FocusSession en la BD, pero la
coroutine del countdown no estaba enlazada a esa fila y seguia
contando en segundo plano. loadActiveSession ahora cancela el
timerJob cuando el Flow reporta que ya no hay sesion activa.
Las cards de Materia, Profesor y Tarea mostraban los botones de accion
directo en la fila (icono lapiz + icono basura, y en Tarea tambien
timer), ocupando espacio y sin lugar para crecer. CardActionsMenu
(componente compartido) reemplaza eso por un boton de 3 puntos que abre
un bottom sheet con las opciones (Editar, Eliminar, y en Tarea tambien
Iniciar enfoque si no esta completada).
Icon() con tint=Color.Unspecified no hereda LocalContentColor como Text,
directamente desactiva el tinte y muestra el color crudo del vector
(negro), por eso el icono de Editar se veia negro sin importar el tema.
Se usa LocalContentColor.current explicito. De paso se quita el
tint = colorScheme.error en Eliminar, no hay razon para que ese boton
sea rojo distinto al resto, CardAction ya no tiene el parametro tint.
Contador de ciclos sumaba por fase (trabajo o descanso) en vez de por
par completo, entregando solo 2 sesiones de 25min en vez de 4. La
sesion se guardaba en BD al iniciar el timer y quedaba huerfana si el
usuario abandonaba o rechazaba la validacion. Duracion del pomodoro
movida a domain/model/PomodoroPolicy (regla de negocio, no de UI).
El calculo solo contaba el largo de la ultima racha consecutiva en la
BD sin comparar contra la fecha actual, mostrando rachas viejas de
forma indefinida aunque el usuario no estudiara mas.
Deadline en el pasado y titulo/tiempo estimado invalidos solo se
frenaban en el Composable, sin garantia a nivel de dominio. Borrar una
tarea cascadeaba su historial de sesiones sin avisar. Prioridad, tipo
y limite de tareas urgentes centralizados en domain/model (antes
duplicados entre AddTaskDialog y TaskFilterBar, o numero magico en SQL).
Se podian crear dos materias con el mismo codigo. Borrar una materia
cascadeaba sus tareas y el historial de sesiones asociado sin avisar.
Nombre/email/departamento solo se validaban en el Composable, sin
garantia a nivel de dominio; regla movida a domain/model/ProfessorPolicy
y aplicada en Add/UpdateProfessorUseCase. Borrar un profesor cascadeaba
sus materias, tareas y sesiones sin avisar. AddProfessorDialog recibia
el ViewModel completo (unico caso asi en el proyecto); ahora recibe
editingProfessor/onSave/onDismiss como el resto de dialogos.
El card de progreso por materia solo mostraba conteo de pendientes,
sin desglose de completadas (ese dato solo existia de forma global).
Double-checked locking incompleto: no volvia a comprobar INSTANCE
dentro del bloque synchronized antes de construir la base de datos.
StreakCard y PointsCard existian pero no estaban conectados a ningun
ViewModel ni renderizados. Reutilizan GetStreakUseCase/CalculatePointsUseCase
ya existentes (no se duplica logica de negocio).
…rminar
Abandonar una sesion ahora guarda los ciclos realmente completados en
vez de descartar todo (0 ciclos si no se completo ninguno). abandonSession
y validateSession dejaban timerMs/currentCycle/isWorkPhase/phaseIndex con
valores viejos tras terminar, mostrando un timer congelado si el estado
se resucitaba. loadActiveSession ya no muestra sesiones huerfanas de la
BD como activas, solo las limpia (ninguna deberia poder resumirse segun
el diseño original de la app).
Sign up for freeto 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.

1 participant

@Ryusse
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

chore: eliminar PROJECT_SETUP.md - #1

Open
Ryusse wants to merge 30 commits into
mainfrom
dev
Open

chore: eliminar PROJECT_SETUP.md#1
Ryusse wants to merge 30 commits into
mainfrom
dev

Conversation

@Ryusse

Copy link
Copy Markdown
Owner

No description provided.

Ryusse added 30 commits July 11, 2026 22:17
…recto
ProfessorCard y tema duplicados sin uso, tests generados con package
com.utp.studyplanner que nunca coincidio con com.example.studyplanner.
…shboard
Completa el UseCase Map de PROJECT_SETUP.md: RF-007 (UpdateSubject),
RF-011 (UpdateTask), RF-013 (MarkTaskComplete), RF-022
(GetPendingTasksBySubject), RF-023 (GetTaskStats). Incluye tests con MockK.
…completado
TaskListScreen era un stub ("Pendiente implementar"). Agrega AddTaskDialog
(materia/prioridad/tipo/deadline), TaskFilterBar (materia/prioridad/estado),
checkbox de completado y boton para iniciar sesion de enfoque por tarea.
Cubre RF-009 a RF-013.
…profesor
FAB y edicion quedaban como TODO. Agrega AddSubjectDialog (dropdown de
profesor, selector de color) y SubjectCard con contador de tareas
pendientes. Cubre RF-005 a RF-008.
…oardViewModel
DashboardScreen calculaba todo ad-hoc desde TaskViewModel y mostraba
"Materia {id}" en vez del nombre real. Ahora usa DashboardViewModel con
GetTaskStatsUseCase y GetPendingTasksBySubjectUseCase (RF-022, RF-023).
RF-017 exigia iniciar focus atado a una tarea especifica, pero no habia
forma de llegar a FocusScreen con un taskId: la pestana Enfoque solo
mostraba "No hay sesion activa" sin entrada posible. Agrega ruta
focus/{taskId} y guarda contra iniciar dos sesiones si ya hay una activa.
Agrega provideDashboardUseCases/provideDashboardViewModel y registra
UpdateTaskUseCase, MarkTaskCompleteUseCase y UpdateSubjectUseCase en
sus respectivos wrappers.
RNF-3.3 pide DB indexada por deadline/materia/estado; Room advertia de
full table scans en cada FK sin indice (professorId, subjectId, taskId).
Agrega los indices y desactiva exportSchema (no se versiona el schema
en este proyecto).
Los tests existentes usaban org.mockito sin la dependencia declarada, no
compilaban. RNF-3.5 pide JUnit4 + MockK, asi que se reescriben con MockK
y se agrega kotlinx-coroutines-test. De paso alinea minSdk=30/targetSdk=36
con RNF-3.4 (estaban en 24/35).
… con icono
FAB extendido (Box+align) reemplaza Scaffold en Materias/Tareas/Profesores,
bottom sheets abren a altura completa, padding de listas consistente
(top 8dp, bottom 88dp para el FAB), y TaskFilterBar muestra icono de estado.
…acion
Room.Callback.onCreate inserta los 7 cursos del semestre (referencia:
CLAUDE.md del vault) con su profesor y horario, solo se ejecuta una vez
cuando la BD se crea por primera vez, asi cualquiera que instale el APK
ve datos reales en vez de una app vacia.
DeleteConfirmDialog (compartido) y DeleteConfirmationDialog (solo profesor)
eran dos componentes casi identicos con estilos distintos (Button relleno
vs TextButton plano). Se elimina el duplicado, Profesores ahora usa el
dialogo compartido con TextButton, igual que el resto. TaskCard tenia un
containerColor explicito que lo desviaba del color por defecto que usan
Materia y Profesor, se quita para que las tres cards se vean iguales.
resumeTimer() llamaba a startTimer() que siempre arrancaba con
timeRemaining = WORK_DURATION y cyclesCompleted = session.cyclesCompleted
(el valor original de creacion, nunca actualizado), asi que pausar y
reanudar volvia a 25:00 y ciclo 1 sin importar cuanto llevaba corriendo.
Ahora runCountdown() recibe el ciclo, fase y tiempo restante actuales
desde el estado en vivo. De paso: la UI mostraba el boton de pausa y
el de reanudar al mismo tiempo siempre, ahora alterna segun timerRunning.
bottomBarRoute compara contra el route pattern exacto (focus/{taskId}),
que nunca coincide con item.route (focus), asi que ningun tab quedaba
seleccionado al iniciar el enfoque desde el icono de una tarea.
Si se elimina la materia (o tarea) de un timer que esta corriendo, el
cascade delete borra la fila de FocusSession en la BD, pero la
coroutine del countdown no estaba enlazada a esa fila y seguia
contando en segundo plano. loadActiveSession ahora cancela el
timerJob cuando el Flow reporta que ya no hay sesion activa.
Las cards de Materia, Profesor y Tarea mostraban los botones de accion
directo en la fila (icono lapiz + icono basura, y en Tarea tambien
timer), ocupando espacio y sin lugar para crecer. CardActionsMenu
(componente compartido) reemplaza eso por un boton de 3 puntos que abre
un bottom sheet con las opciones (Editar, Eliminar, y en Tarea tambien
Iniciar enfoque si no esta completada).
Icon() con tint=Color.Unspecified no hereda LocalContentColor como Text,
directamente desactiva el tinte y muestra el color crudo del vector
(negro), por eso el icono de Editar se veia negro sin importar el tema.
Se usa LocalContentColor.current explicito. De paso se quita el
tint = colorScheme.error en Eliminar, no hay razon para que ese boton
sea rojo distinto al resto, CardAction ya no tiene el parametro tint.
Contador de ciclos sumaba por fase (trabajo o descanso) en vez de por
par completo, entregando solo 2 sesiones de 25min en vez de 4. La
sesion se guardaba en BD al iniciar el timer y quedaba huerfana si el
usuario abandonaba o rechazaba la validacion. Duracion del pomodoro
movida a domain/model/PomodoroPolicy (regla de negocio, no de UI).
El calculo solo contaba el largo de la ultima racha consecutiva en la
BD sin comparar contra la fecha actual, mostrando rachas viejas de
forma indefinida aunque el usuario no estudiara mas.
Deadline en el pasado y titulo/tiempo estimado invalidos solo se
frenaban en el Composable, sin garantia a nivel de dominio. Borrar una
tarea cascadeaba su historial de sesiones sin avisar. Prioridad, tipo
y limite de tareas urgentes centralizados en domain/model (antes
duplicados entre AddTaskDialog y TaskFilterBar, o numero magico en SQL).
Se podian crear dos materias con el mismo codigo. Borrar una materia
cascadeaba sus tareas y el historial de sesiones asociado sin avisar.
Nombre/email/departamento solo se validaban en el Composable, sin
garantia a nivel de dominio; regla movida a domain/model/ProfessorPolicy
y aplicada en Add/UpdateProfessorUseCase. Borrar un profesor cascadeaba
sus materias, tareas y sesiones sin avisar. AddProfessorDialog recibia
el ViewModel completo (unico caso asi en el proyecto); ahora recibe
editingProfessor/onSave/onDismiss como el resto de dialogos.
El card de progreso por materia solo mostraba conteo de pendientes,
sin desglose de completadas (ese dato solo existia de forma global).
Double-checked locking incompleto: no volvia a comprobar INSTANCE
dentro del bloque synchronized antes de construir la base de datos.
StreakCard y PointsCard existian pero no estaban conectados a ningun
ViewModel ni renderizados. Reutilizan GetStreakUseCase/CalculatePointsUseCase
ya existentes (no se duplica logica de negocio).
…rminar
Abandonar una sesion ahora guarda los ciclos realmente completados en
vez de descartar todo (0 ciclos si no se completo ninguno). abandonSession
y validateSession dejaban timerMs/currentCycle/isWorkPhase/phaseIndex con
valores viejos tras terminar, mostrando un timer congelado si el estado
se resucitaba. loadActiveSession ya no muestra sesiones huerfanas de la
BD como activas, solo las limpia (ninguna deberia poder resumirse segun
el diseño original de la app).
Sign up for freeto 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.

1 participant

@Ryusse
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

chore: eliminar PROJECT_SETUP.md - #1

Open
Ryusse wants to merge 30 commits into
mainfrom
dev
Open

chore: eliminar PROJECT_SETUP.md#1
Ryusse wants to merge 30 commits into
mainfrom
dev

Conversation

@Ryusse

Copy link
Copy Markdown
Owner

No description provided.

Ryusse added 30 commits July 11, 2026 22:17
…recto
ProfessorCard y tema duplicados sin uso, tests generados con package
com.utp.studyplanner que nunca coincidio con com.example.studyplanner.
…shboard
Completa el UseCase Map de PROJECT_SETUP.md: RF-007 (UpdateSubject),
RF-011 (UpdateTask), RF-013 (MarkTaskComplete), RF-022
(GetPendingTasksBySubject), RF-023 (GetTaskStats). Incluye tests con MockK.
…completado
TaskListScreen era un stub ("Pendiente implementar"). Agrega AddTaskDialog
(materia/prioridad/tipo/deadline), TaskFilterBar (materia/prioridad/estado),
checkbox de completado y boton para iniciar sesion de enfoque por tarea.
Cubre RF-009 a RF-013.
…profesor
FAB y edicion quedaban como TODO. Agrega AddSubjectDialog (dropdown de
profesor, selector de color) y SubjectCard con contador de tareas
pendientes. Cubre RF-005 a RF-008.
…oardViewModel
DashboardScreen calculaba todo ad-hoc desde TaskViewModel y mostraba
"Materia {id}" en vez del nombre real. Ahora usa DashboardViewModel con
GetTaskStatsUseCase y GetPendingTasksBySubjectUseCase (RF-022, RF-023).
RF-017 exigia iniciar focus atado a una tarea especifica, pero no habia
forma de llegar a FocusScreen con un taskId: la pestana Enfoque solo
mostraba "No hay sesion activa" sin entrada posible. Agrega ruta
focus/{taskId} y guarda contra iniciar dos sesiones si ya hay una activa.
Agrega provideDashboardUseCases/provideDashboardViewModel y registra
UpdateTaskUseCase, MarkTaskCompleteUseCase y UpdateSubjectUseCase en
sus respectivos wrappers.
RNF-3.3 pide DB indexada por deadline/materia/estado; Room advertia de
full table scans en cada FK sin indice (professorId, subjectId, taskId).
Agrega los indices y desactiva exportSchema (no se versiona el schema
en este proyecto).
Los tests existentes usaban org.mockito sin la dependencia declarada, no
compilaban. RNF-3.5 pide JUnit4 + MockK, asi que se reescriben con MockK
y se agrega kotlinx-coroutines-test. De paso alinea minSdk=30/targetSdk=36
con RNF-3.4 (estaban en 24/35).
… con icono
FAB extendido (Box+align) reemplaza Scaffold en Materias/Tareas/Profesores,
bottom sheets abren a altura completa, padding de listas consistente
(top 8dp, bottom 88dp para el FAB), y TaskFilterBar muestra icono de estado.
…acion
Room.Callback.onCreate inserta los 7 cursos del semestre (referencia:
CLAUDE.md del vault) con su profesor y horario, solo se ejecuta una vez
cuando la BD se crea por primera vez, asi cualquiera que instale el APK
ve datos reales en vez de una app vacia.
DeleteConfirmDialog (compartido) y DeleteConfirmationDialog (solo profesor)
eran dos componentes casi identicos con estilos distintos (Button relleno
vs TextButton plano). Se elimina el duplicado, Profesores ahora usa el
dialogo compartido con TextButton, igual que el resto. TaskCard tenia un
containerColor explicito que lo desviaba del color por defecto que usan
Materia y Profesor, se quita para que las tres cards se vean iguales.
resumeTimer() llamaba a startTimer() que siempre arrancaba con
timeRemaining = WORK_DURATION y cyclesCompleted = session.cyclesCompleted
(el valor original de creacion, nunca actualizado), asi que pausar y
reanudar volvia a 25:00 y ciclo 1 sin importar cuanto llevaba corriendo.
Ahora runCountdown() recibe el ciclo, fase y tiempo restante actuales
desde el estado en vivo. De paso: la UI mostraba el boton de pausa y
el de reanudar al mismo tiempo siempre, ahora alterna segun timerRunning.
bottomBarRoute compara contra el route pattern exacto (focus/{taskId}),
que nunca coincide con item.route (focus), asi que ningun tab quedaba
seleccionado al iniciar el enfoque desde el icono de una tarea.
Si se elimina la materia (o tarea) de un timer que esta corriendo, el
cascade delete borra la fila de FocusSession en la BD, pero la
coroutine del countdown no estaba enlazada a esa fila y seguia
contando en segundo plano. loadActiveSession ahora cancela el
timerJob cuando el Flow reporta que ya no hay sesion activa.
Las cards de Materia, Profesor y Tarea mostraban los botones de accion
directo en la fila (icono lapiz + icono basura, y en Tarea tambien
timer), ocupando espacio y sin lugar para crecer. CardActionsMenu
(componente compartido) reemplaza eso por un boton de 3 puntos que abre
un bottom sheet con las opciones (Editar, Eliminar, y en Tarea tambien
Iniciar enfoque si no esta completada).
Icon() con tint=Color.Unspecified no hereda LocalContentColor como Text,
directamente desactiva el tinte y muestra el color crudo del vector
(negro), por eso el icono de Editar se veia negro sin importar el tema.
Se usa LocalContentColor.current explicito. De paso se quita el
tint = colorScheme.error en Eliminar, no hay razon para que ese boton
sea rojo distinto al resto, CardAction ya no tiene el parametro tint.
Contador de ciclos sumaba por fase (trabajo o descanso) en vez de por
par completo, entregando solo 2 sesiones de 25min en vez de 4. La
sesion se guardaba en BD al iniciar el timer y quedaba huerfana si el
usuario abandonaba o rechazaba la validacion. Duracion del pomodoro
movida a domain/model/PomodoroPolicy (regla de negocio, no de UI).
El calculo solo contaba el largo de la ultima racha consecutiva en la
BD sin comparar contra la fecha actual, mostrando rachas viejas de
forma indefinida aunque el usuario no estudiara mas.
Deadline en el pasado y titulo/tiempo estimado invalidos solo se
frenaban en el Composable, sin garantia a nivel de dominio. Borrar una
tarea cascadeaba su historial de sesiones sin avisar. Prioridad, tipo
y limite de tareas urgentes centralizados en domain/model (antes
duplicados entre AddTaskDialog y TaskFilterBar, o numero magico en SQL).
Se podian crear dos materias con el mismo codigo. Borrar una materia
cascadeaba sus tareas y el historial de sesiones asociado sin avisar.
Nombre/email/departamento solo se validaban en el Composable, sin
garantia a nivel de dominio; regla movida a domain/model/ProfessorPolicy
y aplicada en Add/UpdateProfessorUseCase. Borrar un profesor cascadeaba
sus materias, tareas y sesiones sin avisar. AddProfessorDialog recibia
el ViewModel completo (unico caso asi en el proyecto); ahora recibe
editingProfessor/onSave/onDismiss como el resto de dialogos.
El card de progreso por materia solo mostraba conteo de pendientes,
sin desglose de completadas (ese dato solo existia de forma global).
Double-checked locking incompleto: no volvia a comprobar INSTANCE
dentro del bloque synchronized antes de construir la base de datos.
StreakCard y PointsCard existian pero no estaban conectados a ningun
ViewModel ni renderizados. Reutilizan GetStreakUseCase/CalculatePointsUseCase
ya existentes (no se duplica logica de negocio).
…rminar
Abandonar una sesion ahora guarda los ciclos realmente completados en
vez de descartar todo (0 ciclos si no se completo ninguno). abandonSession
y validateSession dejaban timerMs/currentCycle/isWorkPhase/phaseIndex con
valores viejos tras terminar, mostrando un timer congelado si el estado
se resucitaba. loadActiveSession ya no muestra sesiones huerfanas de la
BD como activas, solo las limpia (ninguna deberia poder resumirse segun
el diseño original de la app).
Sign up for freeto 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.

1 participant

@Ryusse