Skip to content

Commit a757e29

Browse files
committed
Add boads, improve decks
1 parent dc73b98 commit a757e29

File tree

11 files changed

+339
-46
lines changed

11 files changed

+339
-46
lines changed

api/lib/src/models/data.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ class SetonixData extends ArchiveData<SetonixData> {
141141

142142
Iterable<String> getBoards() => getAssets(kPackBoardsPath, true);
143143

144+
Iterable<PackItem<BoardDefinition>> getBoardItems([String namespace = '']) =>
145+
getBoards().map((e) => getBoardItem(e, namespace)).nonNulls;
146+
144147
BoardDefinition? getBoard(String id) {
145148
try {
146149
final data = getAsset('$kPackBoardsPath/$id.json');
@@ -160,6 +163,14 @@ class SetonixData extends ArchiveData<SetonixData> {
160163
item: getBoard(id),
161164
);
162165

166+
SetonixData removeBoard(String id) =>
167+
removeAsset('$kPackBoardsPath/$id.json');
168+
169+
SetonixData setBoard(String id, BoardDefinition definition) => setAsset(
170+
'$kPackBoardsPath/$id.json',
171+
utf8.encode(definition.toJson()),
172+
);
173+
163174
Iterable<String> getBackgrounds() =>
164175
getAssets('$kPackBackgroundsPath/', true);
165176

api/lib/src/models/deck.dart

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,10 @@ part 'deck.mapper.dart';
55

66
@MappableClass()
77
class DeckDefinition with DeckDefinitionMappable {
8-
final String? name;
9-
final String? description;
108
final List<FigureDeckDefinition> figures;
119
final List<BoardDeckDefinition> boards;
1210

1311
DeckDefinition({
14-
this.name,
15-
this.description,
1612
this.figures = const [],
1713
this.boards = const [],
1814
});

api/lib/src/models/deck.mapper.dart

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,6 @@ class DeckDefinitionMapper extends ClassMapperBase<DeckDefinition> {
2222
@override
2323
final String id = 'DeckDefinition';
2424

25-
static String? _$name(DeckDefinition v) => v.name;
26-
static const Field<DeckDefinition, String> _f$name =
27-
Field('name', _$name, opt: true);
28-
static String? _$description(DeckDefinition v) => v.description;
29-
static const Field<DeckDefinition, String> _f$description =
30-
Field('description', _$description, opt: true);
3125
static List<FigureDeckDefinition> _$figures(DeckDefinition v) => v.figures;
3226
static const Field<DeckDefinition, List<FigureDeckDefinition>> _f$figures =
3327
Field('figures', _$figures, opt: true, def: const []);
@@ -37,18 +31,13 @@ class DeckDefinitionMapper extends ClassMapperBase<DeckDefinition> {
3731

3832
@override
3933
final MappableFields<DeckDefinition> fields = const {
40-
#name: _f$name,
41-
#description: _f$description,
4234
#figures: _f$figures,
4335
#boards: _f$boards,
4436
};
4537

4638
static DeckDefinition _instantiate(DecodingData data) {
4739
return DeckDefinition(
48-
name: data.dec(_f$name),
49-
description: data.dec(_f$description),
50-
figures: data.dec(_f$figures),
51-
boards: data.dec(_f$boards));
40+
figures: data.dec(_f$figures), boards: data.dec(_f$boards));
5241
}
5342

5443
@override
@@ -115,10 +104,7 @@ abstract class DeckDefinitionCopyWith<$R, $In extends DeckDefinition, $Out>
115104
BoardDeckDefinitionCopyWith<$R, BoardDeckDefinition,
116105
BoardDeckDefinition>> get boards;
117106
$R call(
118-
{String? name,
119-
String? description,
120-
List<FigureDeckDefinition>? figures,
121-
List<BoardDeckDefinition>? boards});
107+
{List<FigureDeckDefinition>? figures, List<BoardDeckDefinition>? boards});
122108
DeckDefinitionCopyWith<$R2, $In, $Out2> $chain<$R2, $Out2>(
123109
Then<$Out2, $R2> t);
124110
}
@@ -147,20 +133,14 @@ class _DeckDefinitionCopyWithImpl<$R, $Out>
147133
$value.boards, (v, t) => v.copyWith.$chain(t), (v) => call(boards: v));
148134
@override
149135
$R call(
150-
{Object? name = $none,
151-
Object? description = $none,
152-
List<FigureDeckDefinition>? figures,
136+
{List<FigureDeckDefinition>? figures,
153137
List<BoardDeckDefinition>? boards}) =>
154138
$apply(FieldCopyWithData({
155-
if (name != $none) #name: name,
156-
if (description != $none) #description: description,
157139
if (figures != null) #figures: figures,
158140
if (boards != null) #boards: boards
159141
}));
160142
@override
161143
DeckDefinition $make(CopyWithData data) => DeckDefinition(
162-
name: data.get(#name, or: $value.name),
163-
description: data.get(#description, or: $value.description),
164144
figures: data.get(#figures, or: $value.figures),
165145
boards: data.get(#boards, or: $value.boards));
166146

app/lib/bloc/editor.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,9 @@ class EditorCubit extends Cubit<SetonixData> {
5959

6060
void setTexture(String name, Uint8List bytes) =>
6161
emit(state.setTexture(name, bytes));
62+
63+
void removeBoard(String id) => emit(state.removeBoard(id));
64+
65+
void setBoard(String id, BoardDefinition definition) =>
66+
emit(state.setBoard(id, definition));
6267
}

app/lib/l10n/app_en.arb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,5 +221,6 @@
221221
"clear": "Clear",
222222
"textures": "Textures",
223223
"texture": "Texture",
224-
"notSet": "Not set"
224+
"notSet": "Not set",
225+
"category": "Category"
225226
}

app/lib/pages/editor/boards.dart

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_bloc/flutter_bloc.dart';
3+
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
4+
import 'package:material_leap/material_leap.dart';
5+
import 'package:phosphor_flutter/phosphor_flutter.dart';
6+
import 'package:setonix/bloc/editor.dart';
7+
import 'package:setonix/pages/editor/textures.dart';
8+
import 'package:setonix_api/setonix_api.dart';
9+
10+
class BoardsEditorPage extends StatelessWidget {
11+
const BoardsEditorPage({super.key});
12+
13+
@override
14+
Widget build(BuildContext context) {
15+
final cubit = context.read<EditorCubit>();
16+
return Scaffold(
17+
body: SingleChildScrollView(
18+
child: Center(
19+
child: Container(
20+
constraints: BoxConstraints(maxWidth: LeapBreakpoints.expanded),
21+
padding: const EdgeInsets.all(4),
22+
child: BlocBuilder<EditorCubit, SetonixData>(
23+
builder: (context, state) {
24+
final boards = state.getBoardItems();
25+
if (boards.isEmpty) {
26+
return Center(
27+
child: Padding(
28+
padding: const EdgeInsets.all(8.0),
29+
child: Text(AppLocalizations.of(context).noData),
30+
),
31+
);
32+
}
33+
return Column(
34+
children: boards.map((board) {
35+
final id = board.id;
36+
return Dismissible(
37+
key: ValueKey(id),
38+
onDismissed: (direction) {
39+
cubit.removeBoard(id);
40+
},
41+
child: ListTile(
42+
title: Text(id),
43+
trailing: IconButton(
44+
icon: const Icon(PhosphorIconsLight.trash),
45+
onPressed: () {
46+
cubit.removeBoard(id);
47+
},
48+
),
49+
onTap: () {
50+
showDialog(
51+
context: context,
52+
builder: (context) => BlocProvider.value(
53+
value: cubit,
54+
child: BoardEditorDialog(name: id),
55+
),
56+
);
57+
},
58+
),
59+
);
60+
}).toList(),
61+
);
62+
},
63+
),
64+
),
65+
),
66+
),
67+
floatingActionButton: FloatingActionButton.extended(
68+
onPressed: () async {
69+
final name = await showDialog<String>(
70+
context: context,
71+
builder: (context) => NameDialog(
72+
validator: defaultNameValidator(
73+
context, cubit.state.getBoards().toList()),
74+
));
75+
if (name == null) return;
76+
cubit.setBoard(name, BoardDefinition(texture: ''));
77+
},
78+
label: Text(AppLocalizations.of(context).create),
79+
icon: const Icon(PhosphorIconsLight.plus),
80+
),
81+
);
82+
}
83+
}
84+
85+
class BoardEditorDialog extends StatefulWidget {
86+
final String name;
87+
88+
const BoardEditorDialog({super.key, required this.name});
89+
90+
@override
91+
State<BoardEditorDialog> createState() => _BoardEditorDialogState();
92+
}
93+
94+
class _BoardEditorDialogState extends State<BoardEditorDialog> {
95+
BoardDefinition? _value;
96+
late PackTranslation _translation;
97+
98+
@override
99+
void initState() {
100+
super.initState();
101+
final editorState = context.read<EditorCubit>().state;
102+
_value = editorState.getBoard(widget.name);
103+
_translation = editorState.getTranslationOrDefault();
104+
}
105+
106+
@override
107+
Widget build(BuildContext context) {
108+
final value = _value;
109+
if (value == null) return const SizedBox();
110+
return ResponsiveAlertDialog(
111+
title: Text(widget.name),
112+
constraints: const BoxConstraints(
113+
maxWidth: LeapBreakpoints.compact,
114+
),
115+
content: ListView(
116+
shrinkWrap: true,
117+
children: [
118+
TextFormField(
119+
decoration: InputDecoration(
120+
labelText: AppLocalizations.of(context).name,
121+
filled: true,
122+
icon: const Icon(PhosphorIconsLight.textT),
123+
),
124+
initialValue: _translation.boards[widget.name]?.name,
125+
onChanged: (value) {
126+
final translation = BoardTranslation(name: value);
127+
_translation =
128+
_translation.copyWith.boards.put(widget.name, translation);
129+
},
130+
),
131+
const SizedBox(height: 8),
132+
VisualEditingView(
133+
value: value,
134+
onChanged: (value) {
135+
setState(() {
136+
_value = value;
137+
});
138+
},
139+
),
140+
],
141+
),
142+
actions: [
143+
TextButton(
144+
onPressed: () {
145+
Navigator.of(context).pop();
146+
},
147+
child: Text(AppLocalizations.of(context).cancel),
148+
),
149+
ElevatedButton(
150+
onPressed: () {
151+
context.read<EditorCubit>().setBoard(widget.name, value);
152+
context.read<EditorCubit>().setTranslation(
153+
_translation,
154+
widget.name,
155+
);
156+
Navigator.of(context).pop();
157+
},
158+
child: Text(AppLocalizations.of(context).save),
159+
),
160+
],
161+
);
162+
}
163+
}

0 commit comments

Comments
 (0)