Skip to content

Commit 7b7c37d

Browse files
feat(cat-voices): workspace segments behaviour (#1204)
* feat: section initial expand/selection * feat: SpaceScaffold body expands * chore: renaming from selected to active * feat: select step from section when opening while others are closed * refactor: extract common section tile widget * feat: section header on tap * refactor: sections list view with each step as its own item * feat: scrolling to steps * feat: SectionsListViewBuilder * fix: SectionsListView separators * refactor: remove SectionStepOffstage * feat: animated ChevronExpandButton * fix: unused imports
1 parent 618f769 commit 7b7c37d

34 files changed

+555
-274
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,32 @@
1-
import 'package:catalyst_voices/pages/treasury/treasury_campaign_setup.dart';
1+
import 'package:catalyst_voices/pages/treasury/treasury_dummy_topic_step.dart';
2+
import 'package:catalyst_voices/widgets/widgets.dart';
23
import 'package:catalyst_voices_view_models/catalyst_voices_view_models.dart';
34
import 'package:flutter/material.dart';
5+
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
46

57
class TreasuryBody extends StatelessWidget {
6-
final List<TreasurySection> sections;
8+
final ItemScrollController itemScrollController;
79

810
const TreasuryBody({
911
super.key,
10-
required this.sections,
12+
required this.itemScrollController,
1113
});
1214

1315
@override
1416
Widget build(BuildContext context) {
15-
return ListView.separated(
16-
padding: const EdgeInsets.only(top: 10),
17-
itemCount: sections.length,
18-
itemBuilder: (context, index) {
19-
final section = sections[index];
20-
21-
switch (section) {
22-
case CampaignSetup():
23-
return TreasuryCampaignSetup(
24-
key: ValueKey('CampaignSetupSection[${section.id}]Key'),
25-
data: section,
26-
);
27-
}
17+
return SectionsListViewBuilder(
18+
builder: (context, value, child) {
19+
return SectionsListView<TreasurySection, TreasurySectionStep>(
20+
itemScrollController: itemScrollController,
21+
items: value,
22+
stepBuilder: (context, step) {
23+
switch (step) {
24+
case DummyTopicStep():
25+
return TreasuryDummyTopicStep(step: step);
26+
}
27+
},
28+
);
2829
},
29-
separatorBuilder: (context, index) => const SizedBox(height: 24),
3030
);
3131
}
3232
}

catalyst_voices/apps/voices/lib/pages/treasury/treasury_campaign_setup.dart

-87
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import 'package:catalyst_voices/widgets/navigation/section_step_state_builder.dart';
2+
import 'package:catalyst_voices/widgets/widgets.dart';
3+
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
4+
import 'package:catalyst_voices_view_models/catalyst_voices_view_models.dart';
5+
import 'package:flutter/material.dart';
6+
7+
class TreasuryDummyTopicStep extends StatelessWidget {
8+
final DummyTopicStep step;
9+
10+
const TreasuryDummyTopicStep({
11+
super.key,
12+
required this.step,
13+
});
14+
15+
@override
16+
Widget build(BuildContext context) {
17+
return SectionStepStateBuilder(
18+
id: step.sectionStepId,
19+
builder: (context, value, child) {
20+
return WorkspaceTextTileContainer(
21+
name: step.localizedName(context),
22+
isSelected: value.isSelected,
23+
headerActions: [
24+
VoicesTextButton(
25+
onTap: step.isEditable ? () {} : null,
26+
child: Text(context.l10n.stepEdit),
27+
),
28+
],
29+
content: step.localizedDesc(context),
30+
);
31+
},
32+
);
33+
}
34+
}

catalyst_voices/apps/voices/lib/pages/treasury/treasury_navigation_panel.dart

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import 'package:catalyst_voices/widgets/navigation/sections_controller.dart';
2-
import 'package:catalyst_voices/widgets/navigation/sections_menu.dart';
31
import 'package:catalyst_voices/widgets/widgets.dart';
42
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
53
import 'package:flutter/material.dart';
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
import 'package:catalyst_voices/pages/treasury/treasury_body.dart';
22
import 'package:catalyst_voices/pages/treasury/treasury_details_panel.dart';
33
import 'package:catalyst_voices/pages/treasury/treasury_navigation_panel.dart';
4-
import 'package:catalyst_voices/widgets/navigation/sections_controller.dart';
54
import 'package:catalyst_voices/widgets/widgets.dart';
65
import 'package:catalyst_voices_view_models/catalyst_voices_view_models.dart';
76
import 'package:flutter/material.dart';
7+
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
88

99
const sections = [
1010
CampaignSetup(
1111
id: 0,
1212
steps: [
13-
DummyTopicStep(id: 0, isEditable: false),
14-
DummyTopicStep(id: 1),
15-
DummyTopicStep(id: 2),
16-
DummyTopicStep(id: 3),
13+
DummyTopicStep(
14+
id: 0,
15+
sectionId: 0,
16+
isEditable: false,
17+
),
18+
DummyTopicStep(id: 1, sectionId: 0),
19+
DummyTopicStep(id: 2, sectionId: 0),
20+
DummyTopicStep(id: 3, sectionId: 0),
1721
],
1822
),
1923
];
@@ -29,12 +33,16 @@ class TreasuryPage extends StatefulWidget {
2933

3034
class _TreasuryPageState extends State<TreasuryPage> {
3135
late final SectionsController _sectionsController;
36+
late final ItemScrollController _bodyItemScrollController;
3237

3338
@override
3439
void initState() {
3540
super.initState();
3641

3742
_sectionsController = SectionsController();
43+
_bodyItemScrollController = ItemScrollController();
44+
45+
_sectionsController.attachItemsScrollController(_bodyItemScrollController);
3846

3947
_populateSections();
4048
}
@@ -49,24 +57,19 @@ class _TreasuryPageState extends State<TreasuryPage> {
4957
Widget build(BuildContext context) {
5058
return SectionsControllerScope(
5159
controller: _sectionsController,
52-
child: const SpaceScaffold(
53-
left: TreasuryNavigationPanel(),
54-
body: TreasuryBody(sections: sections),
55-
right: TreasuryDetailsPanel(),
60+
child: SpaceScaffold(
61+
left: const TreasuryNavigationPanel(),
62+
body: TreasuryBody(
63+
itemScrollController: _bodyItemScrollController,
64+
),
65+
right: const TreasuryDetailsPanel(),
5666
),
5767
);
5868
}
5969

6070
void _populateSections() {
61-
final section = sections.firstOrNull;
62-
final step = section?.steps.firstOrNull;
63-
64-
_sectionsController.value = SectionsControllerState(
71+
_sectionsController.value = SectionsControllerState.initial(
6572
sections: sections,
66-
openedSections: sections.map((e) => e.id).toSet(),
67-
selectedStep: section != null && step != null
68-
? (sectionId: section.id, stepId: step.id)
69-
: null,
7073
);
7174
}
7275
}
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,33 @@
1-
import 'package:catalyst_voices/pages/workspace/workspace_form_section.dart';
1+
import 'package:catalyst_voices/pages/workspace/workspace_rich_text_step.dart';
2+
import 'package:catalyst_voices/widgets/navigation/sections_list_view.dart';
3+
import 'package:catalyst_voices/widgets/navigation/sections_list_view_builder.dart';
24
import 'package:catalyst_voices_view_models/catalyst_voices_view_models.dart';
35
import 'package:flutter/material.dart';
6+
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
47

58
class WorkspaceBody extends StatelessWidget {
6-
final List<WorkspaceSection> sections;
9+
final ItemScrollController itemScrollController;
710

811
const WorkspaceBody({
912
super.key,
10-
required this.sections,
13+
required this.itemScrollController,
1114
});
1215

1316
@override
1417
Widget build(BuildContext context) {
15-
return ListView.separated(
16-
padding: const EdgeInsets.only(top: 10),
17-
itemCount: sections.length,
18-
itemBuilder: (context, index) {
19-
final section = sections[index];
20-
21-
return WorkspaceFormSection(
22-
key: ValueKey('WorkspaceSection[${section.id}]Key'),
23-
data: section,
18+
return SectionsListViewBuilder(
19+
builder: (context, value, child) {
20+
return SectionsListView<WorkspaceSection, WorkspaceSectionStep>(
21+
itemScrollController: itemScrollController,
22+
items: value,
23+
stepBuilder: (context, step) {
24+
switch (step) {
25+
case RichTextStep():
26+
return WorkspaceRichTextStep(step: step);
27+
}
28+
},
2429
);
2530
},
26-
separatorBuilder: (context, index) => const SizedBox(height: 24),
2731
);
2832
}
2933
}

catalyst_voices/apps/voices/lib/pages/workspace/workspace_form_section.dart

-79
This file was deleted.

catalyst_voices/apps/voices/lib/pages/workspace/workspace_navigation_panel.dart

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import 'package:catalyst_voices/widgets/navigation/sections_controller.dart';
2-
import 'package:catalyst_voices/widgets/navigation/sections_menu.dart';
31
import 'package:catalyst_voices/widgets/widgets.dart';
42
import 'package:catalyst_voices_localization/catalyst_voices_localization.dart';
53
import 'package:flutter/material.dart';

0 commit comments

Comments
 (0)