Skip to content

Commit e91930d

Browse files
authored
Merge pull request #6 from botstar/develop
Release v0.5.1 - 20241111
2 parents acd08bd + 9a1a1d0 commit e91930d

File tree

8 files changed

+409
-93
lines changed

8 files changed

+409
-93
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,16 @@
1717
- `reload()`: Reload the chat widget.
1818
- `clearData()`: Clear data (localStorage) the chat widget
1919

20+
*Release Date: 2024-11-08*
21+
22+
## 0.5.1
23+
24+
### Android
25+
- **Bug Fix**: Resolved issue with file selection in the file picker.
26+
27+
### Global
28+
- **Bug Fix**: Addressed uninitialized `_state` error occurring in various method calls within `ChativeWidgetController`.
29+
30+
*Release Date: 2024-11-11*
31+
2032

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ Then, run:
4141
flutter pub get --no-example
4242
```
4343

44-
> **Note**: This library already includes [`webview_flutter`](https://pub.dev/packages/webview_flutter). Ensure you follow the [webview_flutter configuration instructions](https://pub.dev/packages/webview_flutter/install) for your platform.
44+
> **Note**: This library includes [`webview_flutter`](https://pub.dev/packages/webview_flutter/versions/4.5.0) and uses [`file_picker`](https://pub.dev/packages/file_picker/versions/7.0.2).
45+
> To avoid errors, ensure you follow the configuration instructions for both:
46+
> - [webview_flutter setup](https://pub.dev/packages/webview_flutter/versions/4.5.0)
47+
> - [file_picker setup](https://pub.dev/packages/file_picker/versions/7.0.2)
48+
4549

4650
## Usage
4751

@@ -210,6 +214,9 @@ _controller.hide();
210214
211215
// To reload the chat widget
212216
await _controller.reload();
217+
218+
// To clear data on the chat widget
219+
await _controller.clearData();
213220
```
214221

215222
## Customization

example/pubspec.lock

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ packages:
3131
path: ".."
3232
relative: true
3333
source: path
34-
version: "0.0.1"
34+
version: "0.5.0"
3535
clock:
3636
dependency: transitive
3737
description:
@@ -48,6 +48,14 @@ packages:
4848
url: "https://pub.dev"
4949
source: hosted
5050
version: "1.18.0"
51+
cross_file:
52+
dependency: transitive
53+
description:
54+
name: cross_file
55+
sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670"
56+
url: "https://pub.dev"
57+
source: hosted
58+
version: "0.3.4+2"
5159
cupertino_icons:
5260
dependency: "direct main"
5361
description:
@@ -64,6 +72,22 @@ packages:
6472
url: "https://pub.dev"
6573
source: hosted
6674
version: "1.3.1"
75+
ffi:
76+
dependency: transitive
77+
description:
78+
name: ffi
79+
sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6"
80+
url: "https://pub.dev"
81+
source: hosted
82+
version: "2.1.3"
83+
file_picker:
84+
dependency: transitive
85+
description:
86+
name: file_picker
87+
sha256: a7965f87b5894605771d8fffd29236f7d697f73bd254d1e599e7075cb7b1f8bf
88+
url: "https://pub.dev"
89+
source: hosted
90+
version: "7.1.0+1"
6791
flutter:
6892
dependency: "direct main"
6993
description: flutter
@@ -77,11 +101,24 @@ packages:
77101
url: "https://pub.dev"
78102
source: hosted
79103
version: "4.0.0"
104+
flutter_plugin_android_lifecycle:
105+
dependency: transitive
106+
description:
107+
name: flutter_plugin_android_lifecycle
108+
sha256: "9b78450b89f059e96c9ebb355fa6b3df1d6b330436e0b885fb49594c41721398"
109+
url: "https://pub.dev"
110+
source: hosted
111+
version: "2.0.23"
80112
flutter_test:
81113
dependency: "direct dev"
82114
description: flutter
83115
source: sdk
84116
version: "0.0.0"
117+
flutter_web_plugins:
118+
dependency: transitive
119+
description: flutter
120+
source: sdk
121+
version: "0.0.0"
85122
leak_tracker:
86123
dependency: transitive
87124
description:
@@ -223,22 +260,30 @@ packages:
223260
url: "https://pub.dev"
224261
source: hosted
225262
version: "14.2.5"
263+
web:
264+
dependency: transitive
265+
description:
266+
name: web
267+
sha256: cd3543bd5798f6ad290ea73d210f423502e71900302dde696f8bff84bf89a1cb
268+
url: "https://pub.dev"
269+
source: hosted
270+
version: "1.1.0"
226271
webview_flutter:
227272
dependency: transitive
228273
description:
229274
name: webview_flutter
230-
sha256: "889a0a678e7c793c308c68739996227c9661590605e70b1f6cf6b9a6634f7aec"
275+
sha256: ec81f57aa1611f8ebecf1d2259da4ef052281cb5ad624131c93546c79ccc7736
231276
url: "https://pub.dev"
232277
source: hosted
233-
version: "4.10.0"
278+
version: "4.9.0"
234279
webview_flutter_android:
235280
dependency: transitive
236281
description:
237282
name: webview_flutter_android
238-
sha256: dec83a8da0a2dcd8a25418534cc59348dbc2855fa1dd0cc929c62b6029fde392
283+
sha256: "47a8da40d02befda5b151a26dba71f47df471cddd91dfdb7802d0a87c5442558"
239284
url: "https://pub.dev"
240285
source: hosted
241-
version: "4.0.1"
286+
version: "3.16.9"
242287
webview_flutter_platform_interface:
243288
dependency: transitive
244289
description:
@@ -255,6 +300,14 @@ packages:
255300
url: "https://pub.dev"
256301
source: hosted
257302
version: "3.16.1"
303+
win32:
304+
dependency: transitive
305+
description:
306+
name: win32
307+
sha256: "84ba388638ed7a8cb3445a320c8273136ab2631cd5f2c57888335504ddab1bc2"
308+
url: "https://pub.dev"
309+
source: hosted
310+
version: "5.8.0"
258311
sdks:
259312
dart: ">=3.5.4 <4.0.0"
260313
flutter: ">=3.24.0"

example/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ environment:
3030
dependencies:
3131
flutter:
3232
sdk: flutter
33-
chative_sdk:
33+
chative_sdk:
3434
path: ../
3535

3636

lib/src/chative_widget.dart

Lines changed: 95 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'dart:collection';
2+
13
import 'package:flutter/material.dart';
24
import 'package:chative_sdk/src/webview.dart';
35
import 'package:chative_sdk/src/utils.dart';
@@ -7,41 +9,102 @@ typedef OnLoaded = void Function();
79
typedef OnNewMessage = void Function();
810
typedef OnError = void Function(String message);
911

12+
/// Controller for managing the ChativeWidget's state and interactions
1013
class ChativeWidgetController {
11-
late _ChativeWidgetState _state;
14+
_ChativeWidgetState? _state;
15+
final Queue<Function> _actionQueue = Queue<Function>();
16+
17+
/// Sets the state of the ChativeWidget
18+
void _setState(_ChativeWidgetState state) {
19+
_state = state;
20+
_processQueue();
21+
}
22+
23+
/// Processes the action queue
24+
void _processQueue() {
25+
while (_actionQueue.isNotEmpty) {
26+
final action = _actionQueue.removeFirst();
27+
action();
28+
}
29+
}
1230

31+
/// Enqueues an action to be executed when the state is set
32+
void _enqueueOrExecute(Function action) {
33+
if (_state != null) {
34+
action();
35+
} else {
36+
_actionQueue.add(action);
37+
}
38+
}
39+
40+
/// Function to show the ChativeWidget
1341
void show() {
14-
_state.show();
42+
_enqueueOrExecute(() {
43+
_state!.show();
44+
});
1545
}
1646

47+
/// Function to hide the ChativeWidget
1748
void hide() {
18-
_state.hide();
49+
_enqueueOrExecute(() {
50+
_state!.hide();
51+
});
1952
}
2053

54+
/// Inject JavaScript code into the WebView
2155
Future<void> injectJavascript(String script) async {
22-
await _state.injectJavaScript(script);
56+
_enqueueOrExecute(() async {
57+
await _state!.injectJavaScript(script);
58+
});
2359
}
2460

61+
/// Reloads the WebView content
2562
Future<void> reload() async {
26-
await _state.reload();
63+
_enqueueOrExecute(() async {
64+
await _state!.reload();
65+
});
2766
}
2867

68+
/// Clears the WebView's local storage
2969
Future<void> clearData() async {
30-
await _state.clearLocalStorage();
70+
_enqueueOrExecute(() async {
71+
await _state!.clearLocalStorage();
72+
});
3173
}
3274
}
3375

76+
/// A StatefulWidget that displays a chat interface using WebView
3477
class ChativeWidget extends StatefulWidget {
3578
final ChativeWidgetController? controller;
79+
80+
/// The channel ID to be used for the chat widget
3681
final String channelId;
82+
83+
/// The user data to be passed to the chat widget
3784
final Map<String, dynamic>? user;
85+
86+
/// The widget to be displayed as the header of the chat widget
3887
final Widget? headerWidget;
88+
89+
/// The decoration to be applied to the chat widget container
3990
final BoxDecoration? containerDecoration;
91+
92+
/// The top inset of the chat widget
4093
final double insetTop;
94+
95+
/// The bottom inset of the chat widget
4196
final double insetBottom;
97+
98+
/// Callback function to be called when the chat widget is closed
4299
final OnClosed? onClosed;
100+
101+
/// Callback function to be called when the chat widget is loaded
43102
final OnLoaded? onLoaded;
103+
104+
/// Callback function to be called when a new message is received
44105
final OnNewMessage? onNewMessage;
106+
107+
/// Callback function to be called when an error occurs
45108
final OnError? onError;
46109

47110
const ChativeWidget({
@@ -65,50 +128,66 @@ class ChativeWidget extends StatefulWidget {
65128

66129
class _ChativeWidgetState extends State<ChativeWidget> {
67130
bool isVisible = false;
68-
late ChativeWidgetController controller;
131+
late ChativeWidgetController _controller;
132+
133+
/// Key to access the WebViewState
134+
final GlobalKey<WebviewState> _webViewKey = GlobalKey<WebviewState>();
69135

70136
@override
71137
void initState() {
72138
super.initState();
73-
controller = widget.controller ?? ChativeWidgetController();
74-
controller._state = this;
139+
_initializeController();
140+
}
141+
142+
/// Initializes the controller, either using the provided one or creating a new instance
143+
void _initializeController() {
144+
_controller = widget.controller ?? ChativeWidgetController();
145+
_controller._setState(this);
75146
}
76147

148+
/// Shows the chat widget and sends a command to open the chat window
77149
void show() {
78150
setState(() {
79151
isVisible = true;
80152
});
81153
injectJavaScript(widgetApi('openChatWindow', {}));
82154
}
83155

84-
void handleClosed() {
156+
/// Hides the chat widget and sends a command to close the chat window
157+
void hide() {
85158
setState(() {
86159
isVisible = false;
87160
});
88-
injectJavaScript(widgetApi('openChatWindow', {}));
89-
if (widget.onClosed != null) widget.onClosed!();
90161
}
91162

92-
void hide() {
163+
/// Handles the closure of the chat widget
164+
void handleClosed() {
93165
setState(() {
94166
isVisible = false;
95167
});
168+
injectJavaScript(widgetApi('openChatWindow', {}));
169+
if (widget.onClosed != null) widget.onClosed!();
96170
}
97171

172+
/// Reloads the WebView content
98173
Future<void> reload() async {
99174
await _webViewKey.currentState?.reload();
100175
}
101176

177+
/// Injects JavaScript code into the WebView
102178
Future<void> injectJavaScript(dynamic script) async {
103-
await _webViewKey.currentState?.injectJavaScript(script);
179+
if (isScriptSafe(script)) {
180+
await _webViewKey.currentState?.injectJavaScript(script);
181+
} else {
182+
widget.onError?.call('unsafe_script');
183+
}
104184
}
105185

186+
/// Clears the WebView's local storage and reloads the content
106187
Future<void> clearLocalStorage() async {
107188
await _webViewKey.currentState?.clearLocalStorage();
108189
}
109190

110-
final GlobalKey<WebviewState> _webViewKey = GlobalKey<WebviewState>();
111-
112191
@override
113192
Widget build(BuildContext context) {
114193
return Positioned(

0 commit comments

Comments
 (0)