Skip to content

Commit 02b851c

Browse files
committed
feat: daily updates
1 parent a6eabee commit 02b851c

File tree

7 files changed

+230
-5
lines changed

7 files changed

+230
-5
lines changed

lib/screens/labels/controllers/index.dart

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import '/screens/labels/widgets/editor.dart';
12
import '../widgets/picker.dart';
23
import '/imports.dart';
34

@@ -40,7 +41,20 @@ class LabelsController extends GetxController {
4041
}
4142
}
4243

43-
Future<void> addLabel() async {}
44+
Future<void> add() async {
45+
Get.bottomSheet(LabelEditor());
46+
}
47+
48+
Future<void> edit(LabelInfo info) async {
49+
Get.bottomSheet(LabelEditor(edit: info));
50+
}
51+
52+
Future<void> delete(LabelInfo info) async {
53+
if (!await confirm(t.confirm_delete_message(info.title))) return;
54+
_api.deleteLabel(label_id: info.id).then((_) {
55+
items.remove(info);
56+
});
57+
}
4458

4559
Future<List<LabelInfo>> showPicker({List<String>? selected}) async {
4660
final result = await Get.bottomSheet<List<LabelInfo>?>(
@@ -50,6 +64,4 @@ class LabelsController extends GetxController {
5064
);
5165
return result ?? [];
5266
}
53-
54-
Future<void> delete(LabelInfo info) async {}
5567
}

lib/screens/labels/views/index.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class LabelsView extends GetView<LabelsController> {
4242
],
4343
),
4444
floatingActionButton: FloatingActionButton.extended(
45-
onPressed: controller.addLabel,
45+
onPressed: kDebugMode ? controller.add : null,
4646
label: Text(t.labels_add),
4747
icon: Icon(Icons.add_outlined),
4848
),
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
import 'package:flutter_colorpicker/flutter_colorpicker.dart';
2+
3+
import '/imports.dart';
4+
5+
class LabelEditorController extends GetxController {
6+
final _api = Get.find<ApiService>();
7+
final _labels = Get.find<LabelsController>();
8+
9+
final loading = false.obs;
10+
final edit = Rxn<LabelInfo>();
11+
final formKey = GlobalKey<FormState>();
12+
final title = TextEditingController();
13+
final description = TextEditingController();
14+
final color = Colors.green.obs;
15+
final show_on_sidebar = false.obs;
16+
17+
LabelEditorController({LabelInfo? edit}) {
18+
if (edit != null) this.edit.value = edit;
19+
}
20+
21+
Future<void> showColorPicker() async {
22+
final result = await Get.dialog<Color?>(AlertDialog(
23+
titlePadding: const EdgeInsets.all(0),
24+
contentPadding: const EdgeInsets.all(0),
25+
content: SingleChildScrollView(
26+
child: MaterialPicker(
27+
pickerColor: color.value,
28+
onColorChanged: (color) {},
29+
// enableLabel: _enableLabel,
30+
// portraitOnly: _portraitOnly,
31+
),
32+
),
33+
));
34+
print(result);
35+
}
36+
37+
Future<void> submit() async {
38+
if (!formKey.currentState!.validate()) {
39+
return;
40+
}
41+
42+
try {
43+
loading.value = true;
44+
45+
final result = await _api.createLabel(
46+
title: title.text,
47+
description: description.text,
48+
color: color.value.toHexString(),
49+
show_on_sidebar: show_on_sidebar.value,
50+
);
51+
52+
_labels.items.insert(0, result.getOrThrow());
53+
title.text = '';
54+
description.text = '';
55+
} finally {
56+
loading.value = false;
57+
}
58+
// Navigator.of(context).pop(c.selected.value)
59+
}
60+
}
61+
62+
class LabelEditor extends StatelessWidget {
63+
final LabelEditorController controller;
64+
final labels = Get.find<LabelsController>();
65+
66+
LabelEditor({
67+
super.key,
68+
LabelInfo? edit,
69+
}) : controller = Get.put(LabelEditorController(edit: edit));
70+
71+
@override
72+
Widget build(BuildContext context) {
73+
return bottomSheet(
74+
context,
75+
child: Padding(
76+
padding: const EdgeInsets.all(8.0),
77+
child: Obx(() {
78+
final loading = controller.loading.value;
79+
80+
return Form(
81+
key: controller.formKey,
82+
child: ListView(
83+
shrinkWrap: true,
84+
children: [
85+
TextFormField(
86+
enabled: !loading,
87+
controller: controller.title,
88+
decoration: InputDecoration(
89+
label: Text(t.labels_editor_title),
90+
hintText: t.labels_editor_title_hint,
91+
),
92+
validator: (value) {
93+
if (value == null || value.length < 3) {
94+
return t.labels_editor_title_invalid;
95+
}
96+
return null;
97+
},
98+
),
99+
Padding(
100+
padding: const EdgeInsets.only(top: 8),
101+
),
102+
TextFormField(
103+
enabled: !loading,
104+
controller: controller.description,
105+
decoration: InputDecoration(
106+
label: Text(t.labels_editor_description),
107+
hintText: t.labels_editor_description_hint,
108+
),
109+
minLines: 1,
110+
maxLines: 5,
111+
),
112+
Padding(
113+
padding: const EdgeInsets.only(top: 8),
114+
),
115+
Obx(() {
116+
final color = controller.color.value;
117+
118+
return Row(
119+
children: [
120+
SizedBox(
121+
width: 40,
122+
height: 40,
123+
child: InkWell(
124+
onTap: controller.showColorPicker,
125+
child: Container(
126+
decoration: BoxDecoration(
127+
border: Border.all(
128+
color: context.theme.colorScheme.outlineVariant,
129+
),
130+
color: color,
131+
borderRadius: BorderRadius.circular(4),
132+
),
133+
),
134+
),
135+
),
136+
],
137+
);
138+
}),
139+
Padding(
140+
padding: const EdgeInsets.only(top: 8),
141+
),
142+
Obx(() {
143+
final show_on_sidebar = controller.show_on_sidebar.value;
144+
return Row(
145+
spacing: 8,
146+
children: [
147+
Switch(
148+
value: show_on_sidebar,
149+
onChanged: (next) =>
150+
controller.show_on_sidebar.value = next,
151+
),
152+
Text(t.labels_editor_show_on_sidebar),
153+
],
154+
);
155+
}),
156+
primaryButton(
157+
block: true,
158+
label: t.save_changes,
159+
onPressed: controller.submit,
160+
loading: loading,
161+
),
162+
],
163+
),
164+
);
165+
}),
166+
),
167+
);
168+
}
169+
}

lib/services/api.dart

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,24 @@ class ApiService extends GetxService {
694694
}
695695
}
696696

697+
Future<Result<MessageInfo>> deleteConversationMessage({
698+
int? account_id,
699+
required int conversation_id,
700+
required int message_id,
701+
}) async {
702+
try {
703+
account_id ??= _getAuth.profile.value!.account_id;
704+
final path =
705+
'/accounts/$account_id/conversations/$conversation_id/messages/$message_id';
706+
final result = await _http.delete(path);
707+
return MessageInfo.fromJson(result.data).toSuccess();
708+
} on DioException catch (error) {
709+
return ApiError.fromException(error).toFailure();
710+
} on Exception catch (error) {
711+
return error.toFailure();
712+
}
713+
}
714+
697715
Future<Result<bool>> saveDeviceDetails({
698716
required String push_token,
699717
}) async {
@@ -1393,6 +1411,24 @@ class ApiService extends GetxService {
13931411
}
13941412
}
13951413

1414+
Future<Result<bool>> deleteLabel({
1415+
int? account_id,
1416+
required int label_id,
1417+
}) async {
1418+
try {
1419+
account_id ??= _getAuth.profile.value!.account_id;
1420+
final path = '/accounts/$account_id/labels/$label_id';
1421+
1422+
await _http.delete(path);
1423+
1424+
return true.toSuccess();
1425+
} on DioException catch (error) {
1426+
return ApiError.fromException(error).toFailure();
1427+
} on Exception catch (error) {
1428+
return error.toFailure();
1429+
}
1430+
}
1431+
13961432
Future<Result<LabelInfo>> updateLabel({
13971433
int? account_id,
13981434
required int label_id,

lib/utils/regex.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'package:chatwoot/utils/common.dart';
2+
13
bool isEmail(String email) {
24
const pattern = r"(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'"
35
r'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-'
@@ -23,3 +25,7 @@ bool isPassword(String value) {
2325
bool isFullName(String value) {
2426
return value.isNotEmpty && value.length >= 6;
2527
}
28+
29+
bool isHexColor(String value) {
30+
return !isNotNullOrEmpty(value) && value.startsWith('#') && value.length == 7;
31+
}

lib/widgets/bottom_sheet.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Widget bottomSheet(
66
}) {
77
return Container(
88
decoration: BoxDecoration(
9-
color: context.theme.colorScheme.surfaceContainer,
9+
color: context.theme.colorScheme.surface,
1010
borderRadius: BorderRadius.only(
1111
topLeft: Radius.circular(16),
1212
topRight: Radius.circular(16),

macos/Flutter/GeneratedPluginRegistrant.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Foundation
77

88
import audio_session
99
import device_info_plus
10+
import file_picker
1011
import firebase_analytics
1112
import firebase_core
1213
import firebase_messaging
@@ -28,6 +29,7 @@ import window_manager
2829
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
2930
AudioSessionPlugin.register(with: registry.registrar(forPlugin: "AudioSessionPlugin"))
3031
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
32+
FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin"))
3133
FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin"))
3234
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
3335
FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))

0 commit comments

Comments
 (0)