Skip to content

Commit ee54d56

Browse files
committed
Add lazy load to the sound files page
1 parent 94b720c commit ee54d56

File tree

1 file changed

+53
-24
lines changed

1 file changed

+53
-24
lines changed

lib/feature/sound/sound_file_entries.dart

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:async_redux/async_redux.dart';
22
import 'package:flutter/material.dart';
33
import 'package:stelaris/api/model/sound/sound_file_source.dart';
4+
import 'package:stelaris/api/paginated_result.dart';
45
import 'package:stelaris/api/state/actions/sound/sound_actions.dart';
56
import 'package:stelaris/api/state/actions/sound/sound_file_actions.dart';
67
import 'package:stelaris/api/state/app_state.dart';
@@ -39,7 +40,7 @@ class _SoundFileEntriesState extends State<SoundFileEntryPage> {
3940
Widget build(BuildContext context) {
4041
return StoreConnector<AppState, SelectedSoundView>(
4142
vm: () => SelectedSoundState(),
42-
onInit: (store) => InitSoundFileAction(),
43+
onInit: (store) => store.dispatch(InitSoundFileAction()),
4344
onDidChange: (context, store, viewModel) {
4445
_vm = viewModel;
4546
},
@@ -55,22 +56,10 @@ class _SoundFileEntriesState extends State<SoundFileEntryPage> {
5556
vm.hasNoFiles
5657
? const Flexible(flex: 1, child: EmptyDataWidget())
5758
: Expanded(
58-
child: ListView.builder(
59-
controller: _scrollController,
60-
padding: const EdgeInsets.all(8),
61-
itemCount: vm.fileCount, // Example: 10 items
62-
itemBuilder: (context, index) {
63-
return ConstrainedBox(
64-
constraints: const BoxConstraints(
65-
minWidth: 220,
66-
maxWidth: 400,
67-
),
68-
child: SoundFileCard(eventModel: vm[index]),
69-
);
70-
},
71-
),
72-
),
73-
],
59+
child: _buildListView(vm),
60+
),
61+
]
62+
,
7463
);
7564
},
7665
);
@@ -86,10 +75,11 @@ class _SoundFileEntriesState extends State<SoundFileEntryPage> {
8675
void _openAddDialog() {
8776
showDialog(
8877
context: context,
89-
builder: (context) => SoundFileModal(
90-
create: true,
91-
onSave:
92-
({
78+
builder: (context) =>
79+
SoundFileModal(
80+
create: true,
81+
onSave:
82+
({
9383
required name,
9484
required volume,
9585
required pitch,
@@ -111,7 +101,31 @@ class _SoundFileEntriesState extends State<SoundFileEntryPage> {
111101
context.dispatch(SoundFileSourceAddAction(fileSource));
112102
// Handle save logic here
113103
},
114-
),
104+
),
105+
);
106+
}
107+
108+
Widget _buildListView(SelectedSoundView state) {
109+
final PaginatedResult<SoundFileSource> files = state.selected.files;
110+
final hasFooter = state.isLoadingFiles || state.hasNextPage;
111+
final itemCount = files.items.length + (hasFooter ? 1 : 0);
112+
return ListView.builder(
113+
controller: _scrollController,
114+
padding: const EdgeInsets.all(8),
115+
itemCount: itemCount,
116+
clipBehavior: Clip.none,
117+
itemBuilder: (context, index) {
118+
if (index >= files.items.length) {
119+
return _buildFooter(state.isLoadingFiles);
120+
}
121+
return ConstrainedBox(
122+
constraints: const BoxConstraints(
123+
minWidth: 220,
124+
maxWidth: 400,
125+
),
126+
child: SoundFileCard(eventModel: files.items[index]),
127+
);
128+
},
115129
);
116130
}
117131

@@ -121,10 +135,25 @@ class _SoundFileEntriesState extends State<SoundFileEntryPage> {
121135
final SelectedSoundView view = _vm!;
122136

123137
if (_scrollController.position.pixels >=
124-
_scrollController.position.maxScrollExtent - 200 &&
138+
_scrollController.position.maxScrollExtent - 200 &&
125139
view.hasNextPage &&
126140
!view.isLoadingFiles) {
127141
view.onLoadMoreSoundFiles();
128142
}
129143
}
130-
}
144+
145+
Widget _buildFooter(bool isLoading) {
146+
return Padding(
147+
padding: const EdgeInsets.symmetric(vertical: 12),
148+
child: Center(
149+
child: isLoading
150+
? const SizedBox(
151+
width: 20,
152+
height: 20,
153+
child: CircularProgressIndicator(strokeWidth: 2),
154+
)
155+
: const SizedBox.shrink(),
156+
),
157+
);
158+
}
159+
}

0 commit comments

Comments
 (0)