Skip to content

Commit 930b74a

Browse files
authored
Merge pull request #78 from talkjs/fix/crash-on-ios-26
Add true at the end of evaluateJavascript to fix the crash on iOS 26 once and for all
2 parents 1bbdaa9 + ddcce67 commit 930b74a

6 files changed

Lines changed: 39 additions & 38 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.17.4
2+
3+
- Fix crash on iOS 26
4+
15
## 0.17.3
26

37
- Fix runtime type error when triggering `onSelectConversation`.

example/push_notifications/pubspec.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ packages:
563563
path: "../.."
564564
relative: true
565565
source: path
566-
version: "0.17.1"
566+
version: "0.17.3"
567567
talkjs_flutter_inappwebview:
568568
dependency: transitive
569569
description:

lib/src/chatbox.dart

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ class ChatBoxState extends State<ChatBox> {
246246
247247
// Notify the backend of the UI's focus state
248248
setTimeout(() => chatBox.onWindowVisibleChanged(document.visibilityState === "visible"), 1000);
249-
}); true;
249+
});
250250
'''
251251
.trim(),
252252
);
@@ -280,7 +280,7 @@ class ChatBoxState extends State<ChatBox> {
280280
chatBox.mount(document.getElementById("talkjs-container")).then(() => {
281281
// Notify the backend of the UI's focus state
282282
setTimeout(() => chatBox.onWindowVisibleChanged(document.visibilityState === "visible"), 1000);
283-
}); true;
283+
});
284284
'''
285285
.trim(),
286286
);
@@ -427,25 +427,23 @@ class ChatBoxState extends State<ChatBox> {
427427
translateConversations: widget.translateConversations,
428428
);
429429

430-
// This statemement without the `true;` at the end results in a build that crashes on iOS 26.2 when built using Xcode 26.2
431-
// Building on Xcode 26.1.1 and running on iOS 26.2 does not result in a crash.
432-
execute('chatBox = session.createChatbox(${_oldOptions}); true;');
430+
execute('chatBox = session.createChatbox(${_oldOptions});');
433431

434432
_setMessageFilter();
435433
_setHighlightedWords();
436434

437435
execute(
438-
'chatBox.onSendMessage((event) => window.flutter_inappwebview.callHandler("JSCSendMessage", JSON.stringify(event))); true;',
436+
'chatBox.onSendMessage((event) => window.flutter_inappwebview.callHandler("JSCSendMessage", JSON.stringify(event)));',
439437
);
440438
execute(
441-
'chatBox.onTranslationToggled((event) => window.flutter_inappwebview.callHandler("JSCTranslationToggled", JSON.stringify(event))); true;',
439+
'chatBox.onTranslationToggled((event) => window.flutter_inappwebview.callHandler("JSCTranslationToggled", JSON.stringify(event)));',
442440
);
443441

444442
if (widget.onCustomMessageAction != null) {
445443
_oldCustomMessageActions = Set.of(widget.onCustomMessageAction!.keys);
446444
for (var action in _oldCustomMessageActions) {
447445
execute(
448-
'chatBox.onCustomMessageAction("$action", customMessageActionHandler); true;',
446+
'chatBox.onCustomMessageAction("$action", customMessageActionHandler);',
449447
);
450448
}
451449
} else {
@@ -458,7 +456,7 @@ class ChatBoxState extends State<ChatBox> {
458456
);
459457
for (var action in _oldCustomConversationActions) {
460458
execute(
461-
'chatBox.onCustomConversationAction("$action", customConversationActionHandler); true;',
459+
'chatBox.onCustomConversationAction("$action", customConversationActionHandler);',
462460
);
463461
}
464462
} else {
@@ -507,7 +505,7 @@ class ChatBoxState extends State<ChatBox> {
507505
_oldCustomMessageActions.add(action);
508506

509507
execute(
510-
'chatBox.onCustomMessageAction("$action", customMessageActionHandler); true;',
508+
'chatBox.onCustomMessageAction("$action", customMessageActionHandler);',
511509
);
512510

513511
retval = true;
@@ -540,7 +538,7 @@ class ChatBoxState extends State<ChatBox> {
540538
_oldCustomConversationActions.add(action);
541539

542540
execute(
543-
'chatBox.onCustomConversationAction("$action", customConversationActionHandler); true;',
541+
'chatBox.onCustomConversationAction("$action", customConversationActionHandler);',
544542
);
545543

546544
retval = true;
@@ -564,13 +562,13 @@ class ChatBoxState extends State<ChatBox> {
564562

565563
if (_oldConversation != null) {
566564
execute(
567-
'chatBox.select(${getConversationVariableName(_oldConversation!)}, ${json.encode(result)}); true;',
565+
'chatBox.select(${getConversationVariableName(_oldConversation!)}, ${json.encode(result)});',
568566
);
569567
} else {
570568
if (result.isNotEmpty) {
571-
execute('chatBox.select(undefined, ${json.encode(result)}); true;');
569+
execute('chatBox.select(undefined, ${json.encode(result)});');
572570
} else {
573-
execute('chatBox.select(undefined); true;');
571+
execute('chatBox.select(undefined);');
574572
}
575573
}
576574
}
@@ -591,7 +589,7 @@ class ChatBoxState extends State<ChatBox> {
591589
_oldHighlightedWords = List.of(widget.highlightedWords);
592590

593591
execute(
594-
'chatBox.setHighlightedWords(${json.encode(_oldHighlightedWords)}); true;',
592+
'chatBox.setHighlightedWords(${json.encode(_oldHighlightedWords)});',
595593
);
596594
}
597595

@@ -775,15 +773,13 @@ class ChatBoxState extends State<ChatBox> {
775773

776774
_users[user.id] = variableName;
777775

778-
execute(
779-
'let $variableName = new Talk.User(${user.getJsonString()}); true;',
780-
);
776+
execute('let $variableName = new Talk.User(${user.getJsonString()});');
781777

782778
_userObjs[user.id] = User.of(user);
783779
} else if (_userObjs[user.id] != user) {
784780
final variableName = _users[user.id]!;
785781

786-
execute('$variableName = new Talk.User(${user.getJsonString()}); true;');
782+
execute('$variableName = new Talk.User(${user.getJsonString()});');
787783

788784
_userObjs[user.id] = User.of(user);
789785
}
@@ -799,7 +795,7 @@ class ChatBoxState extends State<ChatBox> {
799795
_conversations[conversation.id] = variableName;
800796

801797
execute(
802-
'let $variableName = session.getOrCreateConversation("${conversation.id}"); true;',
798+
'let $variableName = session.getOrCreateConversation("${conversation.id}");',
803799
);
804800

805801
_setConversationAttributes(variableName, conversation);
@@ -868,7 +864,9 @@ class ChatBoxState extends State<ChatBox> {
868864
print('📗 chatbox.execute: $statement');
869865
}
870866

871-
controller.evaluateJavascript(source: statement);
867+
// This statemement without the `true;` at the end results in a build that crashes on iOS 26.2 when built using Xcode 26.2
868+
// Building on Xcode 26.1.1 and running on iOS 26.2 does not result in a crash.
869+
controller.evaluateJavascript(source: '$statement; true;');
872870
} else {
873871
if (kDebugMode) {
874872
print('📘 chatbox.execute: $statement');

lib/src/conversationlist.dart

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ class ConversationListState extends State<ConversationList> {
250250
execute('''conversationList.onSelectConversation((event) => {
251251
event.preventDefault();
252252
window.flutter_inappwebview.callHandler("JSCSelectConversation", JSON.stringify(event));
253-
}); ''');
253+
});''');
254254
}
255255

256256
void _setFeedFilter() {
@@ -328,11 +328,6 @@ class ConversationListState extends State<ConversationList> {
328328
print('📗 conversationlist._jscSelectConversation: $message');
329329
}
330330

331-
final x = json.decode(message);
332-
print('conversation: ${x['conversation']}');
333-
print('me: ${x['me']}');
334-
print('others: ${x['others']}');
335-
336331
widget.onSelectConversation?.call(
337332
SelectConversationEvent.fromJson(json.decode(message)),
338333
);
@@ -394,7 +389,9 @@ class ConversationListState extends State<ConversationList> {
394389
print('📗 conversationlist.execute: $statement');
395390
}
396391

397-
controller.evaluateJavascript(source: statement);
392+
// This statemement without the `true;` at the end results in a build that crashes on iOS 26.2 when built using Xcode 26.2
393+
// Building on Xcode 26.1.1 and running on iOS 26.2 does not result in a crash.
394+
controller.evaluateJavascript(source: '$statement; true;');
398395
} else {
399396
if (kDebugMode) {
400397
print('📘 conversationlist.execute: $statement');

lib/src/session.dart

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,9 @@ class Session with ChangeNotifier {
216216
}
217217

218218
// We're sure that _execute only gets called with a valid _webViewController
219-
return _webViewController!.evaluateJavascript(source: statement);
219+
// This statemement without the `true;` at the end results in a build that crashes on iOS 26.2 when built using Xcode 26.2
220+
// Building on Xcode 26.1.1 and running on iOS 26.2 does not result in a crash.
221+
return _webViewController!.evaluateJavascript(source: '$statement; true;');
220222
}
221223

222224
void _jscOnMessage(List<dynamic> arguments) {
@@ -265,18 +267,18 @@ class Session with ChangeNotifier {
265267
if (enable) {
266268
if (fcmToken != null) {
267269
statement =
268-
'session.setPushRegistration({provider: "fcm", pushRegistrationId: "$fcmToken"}); true;';
270+
'session.setPushRegistration({provider: "fcm", pushRegistrationId: "$fcmToken"});';
269271
} else if (apnsToken != null) {
270272
statement =
271-
'session.setPushRegistration({provider: "apns", pushRegistrationId: "$apnsToken"}); true;';
273+
'session.setPushRegistration({provider: "apns", pushRegistrationId: "$apnsToken"});';
272274
}
273275
} else {
274276
if (fcmToken != null) {
275277
statement =
276-
'session.unsetPushRegistration({provider: "fcm", pushRegistrationId: "$fcmToken"}); true;';
278+
'session.unsetPushRegistration({provider: "fcm", pushRegistrationId: "$fcmToken"});';
277279
} else if (apnsToken != null) {
278280
statement =
279-
'session.unsetPushRegistration({provider: "apns", pushRegistrationId: "$apnsToken"}); true;';
281+
'session.unsetPushRegistration({provider: "apns", pushRegistrationId: "$apnsToken"});';
280282
}
281283
}
282284

@@ -425,7 +427,7 @@ class Session with ChangeNotifier {
425427
_setOrUnsetPushRegistration(true);
426428
} else {
427429
_execute(
428-
'session.setPushRegistration({provider: "${provider!.name}", pushRegistrationId: "$pushRegistrationId"}); true;',
430+
'session.setPushRegistration({provider: "${provider!.name}", pushRegistrationId: "$pushRegistrationId"});',
429431
);
430432
}
431433
}
@@ -475,7 +477,7 @@ class Session with ChangeNotifier {
475477
_setOrUnsetPushRegistration(false);
476478
} else {
477479
_execute(
478-
'session.unsetPushRegistration({provider: "${provider!.name}", pushRegistrationId: "$pushRegistrationId"}); true;',
480+
'session.unsetPushRegistration({provider: "${provider!.name}", pushRegistrationId: "$pushRegistrationId"});',
479481
);
480482
}
481483
}
@@ -508,7 +510,7 @@ class Session with ChangeNotifier {
508510
print('📗 session clearPushRegistrations: Clearing push notifications');
509511
}
510512

511-
_execute('session.clearPushRegistrations(); true;');
513+
_execute('session.clearPushRegistrations();');
512514
}
513515

514516
/// For internal use only. Implementation detail that may change anytime.

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: talkjs_flutter
22
description: Official TalkJS SDK for Flutter
3-
version: 0.17.3
3+
version: 0.17.4
44
homepage: https://talkjs.com
55

66
environment:

0 commit comments

Comments
 (0)