Skip to content

Commit 1087cdd

Browse files
authored
Fixed #29 update messages list after delete message (#30)
## [1.6.0] - 2025-06-17 #### [@rickypid](https://github.com/rickypid) ℹ️ ℹ️ **Recommended scheme migration** ℹ️ ℹ️ ### Fixed * Fixed #29 update messages list after delete message * Fixed update room last message trigger ### Dependencies * Upgraded `supabase_flutter` to `^2.9.1` * Upgraded `meta` to `^1.16.0` * Added `web` `^1.1.1`
1 parent 5b76782 commit 1087cdd

File tree

9 files changed

+153
-74
lines changed

9 files changed

+153
-74
lines changed

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
## [1.6.0] - 2025-06-17
2+
#### [@rickypid](https://github.com/rickypid)
3+
4+
ℹ️ ℹ️ **Recommended scheme migration** ℹ️ ℹ️
5+
6+
### Fixed
7+
8+
* Fixed #29 update messages list after delete message
9+
* Fixed update room last message trigger
10+
11+
### Dependencies
12+
13+
* Upgraded `supabase_flutter` to `^2.9.1`
14+
* Upgraded `meta` to `^1.16.0`
15+
* Added `web` `^1.1.1`
16+
117
## [1.5.0] - 2025-02-06
218
#### [@rickypid](https://github.com/rickypid)
319

doc/docs/guides/supabse-trigges.md

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,47 @@ CREATE OR REPLACE FUNCTION chats.update_last_messages()
1313
SET search_path = ''
1414
AS $$
1515
DECLARE
16+
latest_message jsonb;
1617
ts_in_milliseconds bigint;
18+
affected_room_id bigint;
1719
BEGIN
18-
SELECT EXTRACT(epoch FROM NOW()) * 1000 INTO ts_in_milliseconds;
19-
UPDATE chats.rooms
20-
SET "updatedAt" = ts_in_milliseconds,
21-
"lastMessages" = jsonb_build_array(NEW)
22-
WHERE id = NEW."roomId";
23-
RETURN NEW;
20+
IF TG_OP = 'DELETE' THEN
21+
affected_room_id := OLD."roomId";
22+
ELSE
23+
affected_room_id := NEW."roomId";
24+
END IF;
25+
26+
SELECT to_jsonb(m)
27+
INTO latest_message
28+
FROM chats.messages m
29+
WHERE m."roomId" = affected_room_id
30+
ORDER BY m."createdAt" DESC
31+
LIMIT 1;
32+
33+
IF latest_message IS DISTINCT FROM (
34+
SELECT value FROM jsonb_array_elements(
35+
(SELECT "lastMessages" FROM chats.rooms WHERE id = affected_room_id)
36+
) LIMIT 1
37+
) THEN
38+
SELECT EXTRACT(epoch FROM NOW()) * 1000 INTO ts_in_milliseconds;
39+
40+
UPDATE chats.rooms
41+
SET "updatedAt" = ts_in_milliseconds,
42+
"lastMessages" = jsonb_build_array(latest_message)
43+
WHERE id = affected_room_id;
44+
END IF;
45+
46+
IF TG_OP = 'DELETE' THEN
47+
RETURN OLD;
48+
ELSE
49+
RETURN NEW;
50+
END IF;
2451
END;
2552
$$ LANGUAGE plpgsql;
2653

2754
drop trigger if exists update_last_messages_trigger on chats.messages;
2855
CREATE TRIGGER update_last_messages_trigger
29-
AFTER INSERT OR UPDATE ON chats.messages
56+
AFTER INSERT OR UPDATE OR DELETE ON chats.messages
3057
FOR EACH ROW
3158
EXECUTE FUNCTION chats.update_last_messages();
3259
```

example/lib/src/pages/room.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,28 @@ class _RoomPageState extends State<RoomPage> {
223223
enabled: true,
224224
onTextChanged: (text) => _chatController.onTyping(),
225225
),
226+
onMessageLongPress: (context, p1) async {
227+
final confirm = await showDialog<bool>(
228+
context: context,
229+
builder: (context) => AlertDialog(
230+
title: Text('Confirmation of deletion'),
231+
content: Text('Do you really want to delete this message?'),
232+
actions: [
233+
TextButton(
234+
onPressed: () => Navigator.of(context).pop(false),
235+
child: Text('Cancel'),
236+
),
237+
TextButton(
238+
onPressed: () => Navigator.of(context).pop(true),
239+
child: Text('Delete'),
240+
),
241+
],
242+
),
243+
);
244+
if (confirm == true) {
245+
await _chatController.deleteMessage(widget.room.id, p1.id);
246+
}
247+
},
226248
),
227249
),
228250
),

example/pubspec.yaml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: example
22
description: A new Flutter project.
33
publish_to: 'none'
44

5-
version: 1.5.0
5+
version: 1.5.1
66

77
environment:
88
sdk: '>=3.4.0 <4.0.0'
@@ -11,7 +11,7 @@ dependencies:
1111
cupertino_icons: ^1.0.8
1212
dio: ^5.8.0+1
1313
faker: ^2.2.0
14-
file_picker: ^8.3.1
14+
file_picker: ^10.2.0
1515
file_saver: ^0.2.14
1616
flutter:
1717
sdk: flutter
@@ -20,14 +20,14 @@ dependencies:
2020
flutter_login: ^5.0.0
2121
flutter_supabase_chat_core:
2222
path: ../
23-
flutter_svg: ^2.0.17
24-
http: ^1.3.0
23+
flutter_svg: ^2.2.0
24+
http: ^1.4.0
2525
image_picker: ^1.1.2
2626
infinite_scroll_pagination: ^4.1.0
27-
open_filex: ^4.6.0
27+
open_filex: ^4.7.0
2828
path_provider: ^2.1.5
29-
supabase_flutter: ^2.8.3
30-
timeago: ^3.7.0
29+
supabase_flutter: ^2.9.1
30+
timeago: ^3.7.1
3131

3232

3333
dev_dependencies:

example/utils/sql/02_database_trigger.sql

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -30,50 +30,46 @@ AS $$
3030
DECLARE
3131
latest_message jsonb;
3232
ts_in_milliseconds bigint;
33+
affected_room_id bigint;
3334
BEGIN
34-
SELECT jsonb_build_object(
35-
'id', id,
36-
'createdAt', "createdAt",
37-
'metadata', metadata,
38-
'duration', duration,
39-
'mimeType', "mimeType",
40-
'name', name,
41-
'remoteId', "remoteId",
42-
'repliedMessage', "repliedMessage",
43-
'roomId', "roomId",
44-
'showStatus', "showStatus",
45-
'size', size,
46-
'status', status,
47-
'type', type,
48-
'updatedAt', "updatedAt",
49-
'uri', uri,
50-
'waveForm', "waveForm",
51-
'isLoading', "isLoading",
52-
'height', height,
53-
'width', width,
54-
'previewData', "previewData",
55-
'authorId', "authorId",
56-
'text', text
57-
)
58-
INTO latest_message
59-
FROM chats.messages
60-
WHERE "roomId" = NEW."roomId"
61-
ORDER BY "createdAt" DESC
62-
LIMIT 1;
63-
IF latest_message IS DISTINCT FROM (SELECT "lastMessages" FROM chats.rooms WHERE id = NEW."roomId") THEN
64-
SELECT EXTRACT(epoch FROM NOW()) * 1000 INTO ts_in_milliseconds;
65-
UPDATE chats.rooms
66-
SET "updatedAt" = ts_in_milliseconds,
67-
"lastMessages" = jsonb_build_array(latest_message)
68-
WHERE id = NEW."roomId";
69-
END IF;
35+
IF TG_OP = 'DELETE' THEN
36+
affected_room_id := OLD."roomId";
37+
ELSE
38+
affected_room_id := NEW."roomId";
39+
END IF;
40+
41+
SELECT to_jsonb(m)
42+
INTO latest_message
43+
FROM chats.messages m
44+
WHERE m."roomId" = affected_room_id
45+
ORDER BY m."createdAt" DESC
46+
LIMIT 1;
47+
48+
IF latest_message IS DISTINCT FROM (
49+
SELECT value FROM jsonb_array_elements(
50+
(SELECT "lastMessages" FROM chats.rooms WHERE id = affected_room_id)
51+
) LIMIT 1
52+
) THEN
53+
SELECT EXTRACT(epoch FROM NOW()) * 1000 INTO ts_in_milliseconds;
54+
55+
UPDATE chats.rooms
56+
SET "updatedAt" = ts_in_milliseconds,
57+
"lastMessages" = jsonb_build_array(latest_message)
58+
WHERE id = affected_room_id;
59+
END IF;
60+
61+
IF TG_OP = 'DELETE' THEN
62+
RETURN OLD;
63+
ELSE
7064
RETURN NEW;
65+
END IF;
7166
END;
7267
$$ LANGUAGE plpgsql;
7368

69+
7470
drop trigger if exists update_last_messages_trigger on chats.messages;
7571
CREATE TRIGGER update_last_messages_trigger
76-
AFTER INSERT OR UPDATE ON chats.messages
72+
AFTER INSERT OR UPDATE OR DELETE ON chats.messages
7773
FOR EACH ROW
7874
EXECUTE FUNCTION chats.update_last_messages();
7975

lib/src/class/supabase_chat_controller.dart

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,10 @@ class SupabaseChatController {
7575
.order('createdAt', ascending: false)
7676
.range(pageSize * _currentPage, (_currentPage * pageSize) + pageSize);
7777

78-
void _onData(List<Map<String, dynamic>> data) {
79-
for (var val in data) {
78+
void _onData(
79+
List<Map<String, dynamic>> newData,
80+
) {
81+
for (var val in newData) {
8082
final author = _room.users.firstWhere(
8183
(u) => u.id == val['authorId'],
8284
orElse: () => types.User(id: val['authorId'] as String),
@@ -158,6 +160,17 @@ class SupabaseChatController {
158160
'typing': typing,
159161
};
160162

163+
/// Removes message.
164+
Future<bool> deleteMessage(String roomId, String messageId) async {
165+
final result =
166+
await SupabaseChatCore.instance.deleteMessage(roomId, messageId);
167+
if (result) {
168+
_messages.removeWhere((e) => messageId == e.id);
169+
_messagesController.sink.add(_messages);
170+
}
171+
return result;
172+
}
173+
161174
void dispose() {
162175
_typingChannel.untrack();
163176
}

lib/src/class/supabase_chat_core.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -282,13 +282,15 @@ class SupabaseChatCore {
282282
}
283283

284284
/// Removes message.
285-
Future<void> deleteMessage(String roomId, String messageId) async {
286-
await client
285+
Future<bool> deleteMessage(String roomId, String messageId) async {
286+
final result = await client
287287
.schema(config.schema)
288288
.from(config.messagesTableName)
289289
.delete()
290290
.eq('roomId', roomId)
291-
.eq('id', messageId);
291+
.eq('id', messageId)
292+
.select();
293+
return result.isNotEmpty;
292294
}
293295

294296
/// Removes room.
Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,32 @@
1-
// ignore: avoid_web_libraries_in_flutter
2-
import 'dart:html';
3-
1+
import 'dart:js_interop';
42
import 'package:flutter/material.dart';
3+
import 'package:web/web.dart' as web;
54

65
import 'platforms_widgets_binding.dart';
76

87
PlatformsWidgetsBinding getInstance() => WebWidgetsBinding();
98

109
class WebWidgetsBinding extends PlatformsWidgetsBinding {
10+
late JSFunction _focusListener;
11+
late JSFunction _blurListener;
12+
1113
@override
1214
void addObserver(WidgetsBindingObserver state) {
13-
window.addEventListener('focus', (event) => onFocus(event, state));
14-
window.addEventListener('blur', (event) => onBlur(event, state));
15-
}
15+
_focusListener = ((web.Event _) {
16+
state.didChangeAppLifecycleState(AppLifecycleState.resumed);
17+
}).toJS;
1618

17-
@override
18-
void removeObserver(WidgetsBindingObserver state) {
19-
window.removeEventListener('focus', (event) => onFocus(event, state));
20-
window.removeEventListener('blur', (event) => onBlur(event, state));
21-
}
19+
_blurListener = ((web.Event _) {
20+
state.didChangeAppLifecycleState(AppLifecycleState.paused);
21+
}).toJS;
2222

23-
void onFocus(Event e, WidgetsBindingObserver state) {
24-
state.didChangeAppLifecycleState(AppLifecycleState.resumed);
23+
web.window.addEventListener('focus', _focusListener);
24+
web.window.addEventListener('blur', _blurListener);
2525
}
2626

27-
void onBlur(Event e, WidgetsBindingObserver state) {
28-
state.didChangeAppLifecycleState(AppLifecycleState.paused);
27+
@override
28+
void removeObserver(WidgetsBindingObserver state) {
29+
web.window.removeEventListener('focus', _focusListener);
30+
web.window.removeEventListener('blur', _blurListener);
2931
}
3032
}

pubspec.yaml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: flutter_supabase_chat_core
22
description: >
33
Actively maintained, community-driven Supabase BaaS for chat applications
44
with an optional chat UI.
5-
version: 1.5.0
5+
version: 1.6.0
66
homepage: https://flutter-supabase-chat-core.insideapp.it
77
repository: https://github.com/insideapp-srl/flutter_supabase_chat_core
88

@@ -14,10 +14,11 @@ dependencies:
1414
flutter:
1515
sdk: flutter
1616
flutter_chat_types: ^3.6.2
17-
meta: ^1.15.0
17+
meta: ^1.16.0
1818
mime: '>=1.0.2 <3.0.0'
19-
supabase_flutter: ^2.8.3
19+
supabase_flutter: ^2.9.1
2020
uuid: ^4.5.1
21+
web: ^1.1.1
2122

2223
dev_dependencies:
2324
flutter_lints: ^5.0.0

0 commit comments

Comments
 (0)