Skip to content

Commit a620c64

Browse files
authored
Merge pull request #313 from DenserMeerkat/resolve-issue-remove-add-buttons
feat: automatic row adding, handling checkbox selection when empty
2 parents a076a7a + fb36f05 commit a620c64

File tree

4 files changed

+167
-110
lines changed

4 files changed

+167
-110
lines changed

lib/screens/home_page/editor_pane/details_card/request_pane/request_form_data.dart

Lines changed: 55 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -17,48 +17,67 @@ class FormDataWidget extends ConsumerStatefulWidget {
1717
class _FormDataBodyState extends ConsumerState<FormDataWidget> {
1818
late int seed;
1919
final random = Random.secure();
20-
late List<FormDataModel> rows;
20+
late List<FormDataModel> formRows;
21+
2122
@override
2223
void initState() {
2324
super.initState();
2425
seed = random.nextInt(kRandMax);
2526
}
2627

28+
void _onFieldChange(String selectedId) {
29+
ref.read(collectionStateNotifierProvider.notifier).update(
30+
selectedId,
31+
requestFormDataList: formRows.sublist(0, formRows.length - 1),
32+
);
33+
}
34+
2735
@override
2836
Widget build(BuildContext context) {
2937
final selectedId = ref.watch(selectedIdStateProvider);
30-
var formRows = ref.read(selectedRequestModelProvider)?.requestFormDataList;
31-
rows =
32-
formRows == null || formRows.isEmpty ? [kFormDataEmptyModel] : formRows;
38+
ref.watch(selectedRequestModelProvider
39+
.select((value) => value?.requestFormDataList?.length));
40+
var rF = ref.read(selectedRequestModelProvider)?.requestFormDataList;
41+
bool isFormDataEmpty = rF == null || rF.isEmpty;
42+
List<FormDataModel> rows = (isFormDataEmpty)
43+
? [
44+
kFormDataEmptyModel,
45+
]
46+
: rF;
47+
formRows = isFormDataEmpty ? rows : rows + [kFormDataEmptyModel];
3348

3449
DaviModel<FormDataModel> daviModelRows = DaviModel<FormDataModel>(
35-
rows: rows,
50+
rows: formRows,
3651
columns: [
3752
DaviColumn(
3853
cellPadding: kpsV5,
3954
name: 'Key',
4055
grow: 4,
4156
cellBuilder: (_, row) {
4257
int idx = row.index;
58+
bool isLast = idx + 1 == formRows.length;
4359
return Theme(
4460
data: Theme.of(context),
4561
child: FormDataField(
4662
keyId: "$selectedId-$idx-form-v-$seed",
47-
initialValue: rows[idx].name,
63+
initialValue: formRows[idx].name,
4864
hintText: " Add Key",
4965
onChanged: (value) {
50-
rows[idx] = rows[idx].copyWith(
51-
name: value,
52-
);
66+
formRows[idx] = formRows[idx].copyWith(name: value);
67+
if (isLast) formRows.add(kFormDataEmptyModel);
5368
_onFieldChange(selectedId!);
5469
},
5570
colorScheme: Theme.of(context).colorScheme,
56-
formDataType: rows[idx].type,
71+
formDataType: formRows[idx].type,
5772
onFormDataTypeChanged: (value) {
58-
rows[idx] = rows[idx].copyWith(
73+
bool hasChanged = formRows[idx].type != value;
74+
formRows[idx] = formRows[idx].copyWith(
5975
type: value ?? FormDataType.text,
6076
);
61-
rows[idx] = rows[idx].copyWith(value: "");
77+
formRows[idx] = formRows[idx].copyWith(value: "");
78+
if (idx == formRows.length - 1 && hasChanged) {
79+
formRows.add(kFormDataEmptyModel);
80+
}
6281
setState(() {});
6382
_onFieldChange(selectedId!);
6483
},
@@ -84,7 +103,8 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
84103
cellPadding: kpsV5,
85104
cellBuilder: (_, row) {
86105
int idx = row.index;
87-
return rows[idx].type == FormDataType.file
106+
bool isLast = idx + 1 == formRows.length;
107+
return formRows[idx].type == FormDataType.file
88108
? Align(
89109
alignment: Alignment.centerLeft,
90110
child: Row(
@@ -109,17 +129,17 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
109129
if (pickedResult != null &&
110130
pickedResult.files.isNotEmpty &&
111131
pickedResult.files.first.path != null) {
112-
rows[idx] = rows[idx].copyWith(
132+
formRows[idx] = formRows[idx].copyWith(
113133
value: pickedResult.files.first.path!,
114134
);
115135
setState(() {});
116136
_onFieldChange(selectedId!);
117137
}
118138
},
119139
label: Text(
120-
(rows[idx].type == FormDataType.file &&
121-
rows[idx].value.isNotEmpty)
122-
? rows[idx].value.toString()
140+
(formRows[idx].type == FormDataType.file &&
141+
formRows[idx].value.isNotEmpty)
142+
? formRows[idx].value.toString()
123143
: "Select File",
124144
textAlign: TextAlign.center,
125145
overflow: TextOverflow.ellipsis,
@@ -133,10 +153,11 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
133153
)
134154
: CellField(
135155
keyId: "$selectedId-$idx-form-v-$seed",
136-
initialValue: rows[idx].value,
156+
initialValue: formRows[idx].value,
137157
hintText: " Add Value",
138158
onChanged: (value) {
139-
rows[idx] = rows[idx].copyWith(value: value);
159+
formRows[idx] = formRows[idx].copyWith(value: value);
160+
if (isLast) formRows.add(kFormDataEmptyModel);
140161
_onFieldChange(selectedId!);
141162
},
142163
colorScheme: Theme.of(context).colorScheme,
@@ -148,22 +169,24 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
148169
pinStatus: PinStatus.none,
149170
width: 30,
150171
cellBuilder: (_, row) {
172+
bool isLast = row.index + 1 == formRows.length;
151173
return InkWell(
174+
onTap: isLast
175+
? null
176+
: () {
177+
seed = random.nextInt(kRandMax);
178+
if (formRows.length == 2) {
179+
setState(() {
180+
formRows = [kFormDataEmptyModel];
181+
});
182+
} else {
183+
formRows.removeAt(row.index);
184+
}
185+
_onFieldChange(selectedId!);
186+
},
152187
child: Theme.of(context).brightness == Brightness.dark
153188
? kIconRemoveDark
154189
: kIconRemoveLight,
155-
onTap: () {
156-
seed = random.nextInt(kRandMax);
157-
if (rows.length == 1) {
158-
setState(() {
159-
rows = [kFormDataEmptyModel];
160-
});
161-
} else {
162-
rows.removeAt(row.index);
163-
}
164-
_onFieldChange(selectedId!);
165-
setState(() {});
166-
},
167190
);
168191
},
169192
),
@@ -194,9 +217,7 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
194217
padding: const EdgeInsets.only(bottom: 30),
195218
child: ElevatedButton.icon(
196219
onPressed: () {
197-
setState(() {
198-
rows.add(kFormDataEmptyModel);
199-
});
220+
formRows.add(kFormDataEmptyModel);
200221
_onFieldChange(selectedId!);
201222
},
202223
icon: const Icon(Icons.add),
@@ -210,11 +231,4 @@ class _FormDataBodyState extends ConsumerState<FormDataWidget> {
210231
],
211232
);
212233
}
213-
214-
void _onFieldChange(String selectedId) {
215-
ref.read(collectionStateNotifierProvider.notifier).update(
216-
selectedId,
217-
requestFormDataList: rows,
218-
);
219-
}
220234
}

lib/screens/home_page/editor_pane/details_card/request_pane/request_headers.dart

Lines changed: 56 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ class EditRequestHeaders extends ConsumerStatefulWidget {
1515
}
1616

1717
class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
18+
late int seed;
1819
final random = Random.secure();
19-
late List<NameValueModel> rows;
20+
late List<NameValueModel> headerRows;
2021
late List<bool> isRowEnabledList;
21-
late int seed;
2222

2323
@override
2424
void initState() {
@@ -29,8 +29,9 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
2929
void _onFieldChange(String selectedId) {
3030
ref.read(collectionStateNotifierProvider.notifier).update(
3131
selectedId,
32-
requestHeaders: rows,
33-
isHeaderEnabledList: isRowEnabledList,
32+
requestHeaders: headerRows.sublist(0, headerRows.length - 1),
33+
isHeaderEnabledList:
34+
isRowEnabledList.sublist(0, headerRows.length - 1),
3435
);
3536
}
3637

@@ -40,32 +41,38 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
4041
ref.watch(selectedRequestModelProvider
4142
.select((value) => value?.requestHeaders?.length));
4243
var rH = ref.read(selectedRequestModelProvider)?.requestHeaders;
43-
rows = (rH == null || rH.isEmpty)
44+
bool isHeadersEmpty = rH == null || rH.isEmpty;
45+
List<NameValueModel> rows = (isHeadersEmpty)
4446
? [
4547
kNameValueEmptyModel,
4648
]
4749
: rH;
50+
headerRows = isHeadersEmpty ? rows : rows + [kNameValueEmptyModel];
4851
isRowEnabledList =
4952
ref.read(selectedRequestModelProvider)?.isHeaderEnabledList ??
50-
List.filled(rows.length, true, growable: true);
53+
List.filled(rH?.length ?? 0, true, growable: true);
54+
isRowEnabledList.add(false);
5155

5256
DaviModel<NameValueModel> model = DaviModel<NameValueModel>(
53-
rows: rows,
57+
rows: headerRows,
5458
columns: [
5559
DaviColumn(
5660
name: 'Checkbox',
5761
width: 30,
5862
cellBuilder: (_, row) {
5963
int idx = row.index;
64+
bool isLast = idx + 1 == headerRows.length;
6065
return CheckBox(
6166
keyId: "$selectedId-$idx-headers-c-$seed",
6267
value: isRowEnabledList[idx],
63-
onChanged: (value) {
64-
setState(() {
65-
isRowEnabledList[idx] = value!;
66-
});
67-
_onFieldChange(selectedId!);
68-
},
68+
onChanged: isLast
69+
? null
70+
: (value) {
71+
setState(() {
72+
isRowEnabledList[idx] = value!;
73+
});
74+
_onFieldChange(selectedId!);
75+
},
6976
colorScheme: Theme.of(context).colorScheme,
7077
);
7178
},
@@ -76,12 +83,18 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
7683
grow: 1,
7784
cellBuilder: (_, row) {
7885
int idx = row.index;
86+
bool isLast = idx + 1 == headerRows.length;
7987
return HeaderField(
8088
keyId: "$selectedId-$idx-headers-k-$seed",
81-
initialValue: rows[idx].name,
89+
initialValue: headerRows[idx].name,
8290
hintText: "Add Header Name",
8391
onChanged: (value) {
84-
rows[idx] = rows[idx].copyWith(name: value);
92+
headerRows[idx] = headerRows[idx].copyWith(name: value);
93+
if (isLast) {
94+
isRowEnabledList[idx] = true;
95+
headerRows.add(kNameValueEmptyModel);
96+
isRowEnabledList.add(false);
97+
}
8598
_onFieldChange(selectedId!);
8699
},
87100
colorScheme: Theme.of(context).colorScheme,
@@ -103,12 +116,18 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
103116
grow: 1,
104117
cellBuilder: (_, row) {
105118
int idx = row.index;
119+
bool isLast = idx + 1 == headerRows.length;
106120
return CellField(
107121
keyId: "$selectedId-$idx-headers-v-$seed",
108-
initialValue: rows[idx].value,
122+
initialValue: headerRows[idx].value,
109123
hintText: " Add Header Value",
110124
onChanged: (value) {
111-
rows[idx] = rows[idx].copyWith(value: value);
125+
headerRows[idx] = headerRows[idx].copyWith(value: value);
126+
if (isLast) {
127+
isRowEnabledList[idx] = true;
128+
headerRows.add(kNameValueEmptyModel);
129+
isRowEnabledList.add(false);
130+
}
112131
_onFieldChange(selectedId!);
113132
},
114133
colorScheme: Theme.of(context).colorScheme,
@@ -120,25 +139,28 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
120139
pinStatus: PinStatus.none,
121140
width: 30,
122141
cellBuilder: (_, row) {
142+
bool isLast = row.index + 1 == headerRows.length;
123143
return InkWell(
144+
onTap: isLast
145+
? null
146+
: () {
147+
seed = random.nextInt(kRandMax);
148+
if (headerRows.length == 2) {
149+
setState(() {
150+
headerRows = [
151+
kNameValueEmptyModel,
152+
];
153+
isRowEnabledList = [false];
154+
});
155+
} else {
156+
headerRows.removeAt(row.index);
157+
isRowEnabledList.removeAt(row.index);
158+
}
159+
_onFieldChange(selectedId!);
160+
},
124161
child: Theme.of(context).brightness == Brightness.dark
125162
? kIconRemoveDark
126163
: kIconRemoveLight,
127-
onTap: () {
128-
seed = random.nextInt(kRandMax);
129-
if (rows.length == 1) {
130-
setState(() {
131-
rows = [
132-
kNameValueEmptyModel,
133-
];
134-
isRowEnabledList = [true];
135-
});
136-
} else {
137-
rows.removeAt(row.index);
138-
isRowEnabledList.removeAt(row.index);
139-
}
140-
_onFieldChange(selectedId!);
141-
},
142164
);
143165
},
144166
),
@@ -169,8 +191,8 @@ class EditRequestHeadersState extends ConsumerState<EditRequestHeaders> {
169191
padding: const EdgeInsets.only(bottom: 30),
170192
child: ElevatedButton.icon(
171193
onPressed: () {
172-
rows.add(kNameValueEmptyModel);
173-
isRowEnabledList.add(true);
194+
headerRows.add(kNameValueEmptyModel);
195+
isRowEnabledList.add(false);
174196
_onFieldChange(selectedId!);
175197
},
176198
icon: const Icon(Icons.add),

0 commit comments

Comments
 (0)