Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Lückemeyer
VoCoach
Commits
e2362072
Commit
e2362072
authored
Apr 18, 2026
by
Lückemeyer
Browse files
claude added learn direction toggle switch
parent
044bb284
Changes
5
Hide whitespace changes
Inline
Side-by-side
app/src/main/java/dev/lueckemeyer/vocoach/db/dao/LeitnerStateDao.java
View file @
e2362072
...
@@ -24,5 +24,20 @@ public interface LeitnerStateDao {
...
@@ -24,5 +24,20 @@ public interface LeitnerStateDao {
"JOIN unit u ON u.id = v.unit_id "
+
"JOIN unit u ON u.id = v.unit_id "
+
"WHERE ls.direction = :direction AND ls.box_number = :box "
+
"WHERE ls.direction = :direction AND ls.box_number = :box "
+
"ORDER BY u.book_id ASC, u.position ASC, v.position ASC"
)
"ORDER BY u.book_id ASC, u.position ASC, v.position ASC"
)
List
<
LeitnerState
>
getByBoxOrderedSync
(
String
direction
,
int
box
);
List
<
LeitnerState
>
getByBoxOrderedAsc
(
String
direction
,
int
box
);
@Query
(
"SELECT ls.* FROM leitner_state ls "
+
"JOIN card c ON c.id = ls.card_id "
+
"JOIN volet v ON v.id = c.volet_id "
+
"JOIN unit u ON u.id = v.unit_id "
+
"WHERE ls.direction = :direction AND ls.box_number = :box "
+
"ORDER BY u.book_id DESC, u.position DESC, v.position DESC"
)
List
<
LeitnerState
>
getByBoxOrderedDesc
(
String
direction
,
int
box
);
/** Dispatches to ASC or DESC based on the ascending flag. */
default
List
<
LeitnerState
>
getByBoxOrderedSync
(
String
direction
,
int
box
,
boolean
ascending
)
{
return
ascending
?
getByBoxOrderedAsc
(
direction
,
box
)
:
getByBoxOrderedDesc
(
direction
,
box
);
}
}
}
app/src/main/java/dev/lueckemeyer/vocoach/repository/TrainingRepository.java
View file @
e2362072
...
@@ -68,7 +68,7 @@ public class TrainingRepository {
...
@@ -68,7 +68,7 @@ public class TrainingRepository {
// ── Scheduling ────────────────────────────────────────────────────────────
// ── Scheduling ────────────────────────────────────────────────────────────
public
TrainingCard
nextCard
(
String
direction
)
{
public
TrainingCard
nextCard
(
String
direction
,
boolean
ascending
)
{
long
dayStart
=
todayStartEpochSeconds
();
long
dayStart
=
todayStartEpochSeconds
();
// Pending card first
// Pending card first
...
@@ -83,13 +83,7 @@ public class TrainingRepository {
...
@@ -83,13 +83,7 @@ public class TrainingRepository {
Set
<
Integer
>
attempted
=
new
HashSet
<>(
attemptedIds
);
Set
<
Integer
>
attempted
=
new
HashSet
<>(
attemptedIds
);
for
(
int
box
=
1
;
box
<=
5
;
box
++)
{
for
(
int
box
=
1
;
box
<=
5
;
box
++)
{
for
(
LeitnerState
ls
:
db
.
leitnerStateDao
().
getByBoxOrderedSync
(
direction
,
box
))
{
for
(
LeitnerState
ls
:
db
.
leitnerStateDao
().
getByBoxOrderedSync
(
direction
,
box
,
ascending
))
{
if
(!
attempted
.
contains
(
ls
.
id
))
return
buildCard
(
ls
);
}
}
attempted
=
new
HashSet
<>();
for
(
int
box
=
1
;
box
<=
5
;
box
++)
{
for
(
LeitnerState
ls
:
db
.
leitnerStateDao
().
getByBoxOrderedSync
(
direction
,
box
))
{
if
(!
attempted
.
contains
(
ls
.
id
))
return
buildCard
(
ls
);
if
(!
attempted
.
contains
(
ls
.
id
))
return
buildCard
(
ls
);
}
}
}
}
...
...
app/src/main/java/dev/lueckemeyer/vocoach/ui/home/HomeFragment.java
View file @
e2362072
...
@@ -26,9 +26,14 @@ public class HomeFragment extends Fragment {
...
@@ -26,9 +26,14 @@ public class HomeFragment extends Fragment {
public
void
onViewCreated
(
@NonNull
View
view
,
@Nullable
Bundle
savedInstanceState
)
{
public
void
onViewCreated
(
@NonNull
View
view
,
@Nullable
Bundle
savedInstanceState
)
{
super
.
onViewCreated
(
view
,
savedInstanceState
);
super
.
onViewCreated
(
view
,
savedInstanceState
);
// Toggle: checked = Learn (DESC = higher boxes first), unchecked = Repeat (ASC)
// Default to Repeat (ASC) on first launch
binding
.
toggleMode
.
setChecked
(
false
);
binding
.
btnFrToNative
.
setOnClickListener
(
v
->
{
binding
.
btnFrToNative
.
setOnClickListener
(
v
->
{
Bundle
args
=
new
Bundle
();
Bundle
args
=
new
Bundle
();
args
.
putString
(
"direction"
,
"fr_to_native"
);
args
.
putString
(
"direction"
,
"fr_to_native"
);
args
.
putBoolean
(
"ascending"
,
isRepeatMode
());
Navigation
.
findNavController
(
v
)
Navigation
.
findNavController
(
v
)
.
navigate
(
R
.
id
.
action_home_to_training
,
args
);
.
navigate
(
R
.
id
.
action_home_to_training
,
args
);
});
});
...
@@ -36,6 +41,7 @@ public class HomeFragment extends Fragment {
...
@@ -36,6 +41,7 @@ public class HomeFragment extends Fragment {
binding
.
btnNativeToFr
.
setOnClickListener
(
v
->
{
binding
.
btnNativeToFr
.
setOnClickListener
(
v
->
{
Bundle
args
=
new
Bundle
();
Bundle
args
=
new
Bundle
();
args
.
putString
(
"direction"
,
"native_to_fr"
);
args
.
putString
(
"direction"
,
"native_to_fr"
);
args
.
putBoolean
(
"ascending"
,
isRepeatMode
());
Navigation
.
findNavController
(
v
)
Navigation
.
findNavController
(
v
)
.
navigate
(
R
.
id
.
action_home_to_training
,
args
);
.
navigate
(
R
.
id
.
action_home_to_training
,
args
);
});
});
...
@@ -45,6 +51,11 @@ public class HomeFragment extends Fragment {
...
@@ -45,6 +51,11 @@ public class HomeFragment extends Fragment {
.
navigate
(
R
.
id
.
action_home_to_stats
));
.
navigate
(
R
.
id
.
action_home_to_stats
));
}
}
/** Returns true when the toggle is in Repeat position (ASC ordering). */
private
boolean
isRepeatMode
()
{
return
!
binding
.
toggleMode
.
isChecked
();
}
@Override
@Override
public
void
onDestroyView
()
{
public
void
onDestroyView
()
{
super
.
onDestroyView
();
super
.
onDestroyView
();
...
...
app/src/main/java/dev/lueckemeyer/vocoach/ui/training/TrainingFragment.java
View file @
e2362072
...
@@ -20,6 +20,7 @@ public class TrainingFragment extends Fragment {
...
@@ -20,6 +20,7 @@ public class TrainingFragment extends Fragment {
private
FragmentTrainingBinding
binding
;
private
FragmentTrainingBinding
binding
;
private
TrainingRepository
repo
;
private
TrainingRepository
repo
;
private
String
direction
;
private
String
direction
;
private
boolean
ascending
;
private
int
sessionId
;
private
int
sessionId
;
private
TrainingCard
current
;
private
TrainingCard
current
;
private
final
ExecutorService
exec
=
Executors
.
newSingleThreadExecutor
();
private
final
ExecutorService
exec
=
Executors
.
newSingleThreadExecutor
();
...
@@ -35,8 +36,9 @@ public class TrainingFragment extends Fragment {
...
@@ -35,8 +36,9 @@ public class TrainingFragment extends Fragment {
public
void
onViewCreated
(
@NonNull
View
view
,
@Nullable
Bundle
savedInstanceState
)
{
public
void
onViewCreated
(
@NonNull
View
view
,
@Nullable
Bundle
savedInstanceState
)
{
super
.
onViewCreated
(
view
,
savedInstanceState
);
super
.
onViewCreated
(
view
,
savedInstanceState
);
// Read direction argument passed
via Bundle
// Read direction
and sort order
argument
s
passed
from HomeFragment
direction
=
requireArguments
().
getString
(
"direction"
,
"fr_to_native"
);
direction
=
requireArguments
().
getString
(
"direction"
,
"fr_to_native"
);
ascending
=
requireArguments
().
getBoolean
(
"ascending"
,
true
);
repo
=
new
TrainingRepository
(
requireContext
());
repo
=
new
TrainingRepository
(
requireContext
());
exec
.
execute
(()
->
{
exec
.
execute
(()
->
{
...
@@ -64,7 +66,7 @@ public class TrainingFragment extends Fragment {
...
@@ -64,7 +66,7 @@ public class TrainingFragment extends Fragment {
binding
.
layoutSolution
.
setVisibility
(
View
.
GONE
);
binding
.
layoutSolution
.
setVisibility
(
View
.
GONE
);
exec
.
execute
(()
->
{
exec
.
execute
(()
->
{
current
=
repo
.
nextCard
(
direction
);
current
=
repo
.
nextCard
(
direction
,
ascending
);
requireActivity
().
runOnUiThread
(()
->
{
requireActivity
().
runOnUiThread
(()
->
{
if
(
current
==
null
)
showAllDone
();
if
(
current
==
null
)
showAllDone
();
else
{
else
{
...
...
app/src/main/res/layout/fragment_home.xml
View file @
e2362072
...
@@ -11,7 +11,40 @@
...
@@ -11,7 +11,40 @@
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:text=
"What would you like to do?"
android:text=
"What would you like to do?"
android:textAppearance=
"?attr/textAppearanceHeadline6"
android:textAppearance=
"?attr/textAppearanceHeadline6"
android:layout_marginBottom=
"40dp"
/>
android:layout_marginBottom=
"32dp"
/>
<!-- Repeat / Learn toggle -->
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:orientation=
"horizontal"
android:gravity=
"center_vertical"
android:layout_marginBottom=
"24dp"
>
<TextView
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_weight=
"1"
android:text=
"Repeat"
android:textAppearance=
"?attr/textAppearanceBody1"
android:gravity=
"end"
android:paddingEnd=
"12dp"
/>
<com.google.android.material.switchmaterial.SwitchMaterial
android:id=
"@+id/toggle_mode"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
/>
<TextView
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_weight=
"1"
android:text=
"Learn"
android:textAppearance=
"?attr/textAppearanceBody1"
android:gravity=
"start"
android:paddingStart=
"12dp"
/>
</LinearLayout>
<com.google.android.material.button.MaterialButton
<com.google.android.material.button.MaterialButton
android:id=
"@+id/btn_fr_to_native"
android:id=
"@+id/btn_fr_to_native"
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment