Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
## [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.5.0] - 2025-02-06
#### [@rickypid](https://github.com/rickypid)

Expand Down
41 changes: 34 additions & 7 deletions doc/docs/guides/supabse-trigges.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,47 @@ CREATE OR REPLACE FUNCTION chats.update_last_messages()
SET search_path = ''
AS $$
DECLARE
latest_message jsonb;
ts_in_milliseconds bigint;
affected_room_id bigint;
BEGIN
SELECT EXTRACT(epoch FROM NOW()) * 1000 INTO ts_in_milliseconds;
UPDATE chats.rooms
SET "updatedAt" = ts_in_milliseconds,
"lastMessages" = jsonb_build_array(NEW)
WHERE id = NEW."roomId";
RETURN NEW;
IF TG_OP = 'DELETE' THEN
affected_room_id := OLD."roomId";
ELSE
affected_room_id := NEW."roomId";
END IF;

SELECT to_jsonb(m)
INTO latest_message
FROM chats.messages m
WHERE m."roomId" = affected_room_id
ORDER BY m."createdAt" DESC
LIMIT 1;

IF latest_message IS DISTINCT FROM (
SELECT value FROM jsonb_array_elements(
(SELECT "lastMessages" FROM chats.rooms WHERE id = affected_room_id)
) LIMIT 1
) THEN
SELECT EXTRACT(epoch FROM NOW()) * 1000 INTO ts_in_milliseconds;

UPDATE chats.rooms
SET "updatedAt" = ts_in_milliseconds,
"lastMessages" = jsonb_build_array(latest_message)
WHERE id = affected_room_id;
END IF;

IF TG_OP = 'DELETE' THEN
RETURN OLD;
ELSE
RETURN NEW;
END IF;
END;
$$ LANGUAGE plpgsql;

drop trigger if exists update_last_messages_trigger on chats.messages;
CREATE TRIGGER update_last_messages_trigger
AFTER INSERT OR UPDATE ON chats.messages
AFTER INSERT OR UPDATE OR DELETE ON chats.messages
FOR EACH ROW
EXECUTE FUNCTION chats.update_last_messages();
```
Expand Down
22 changes: 22 additions & 0 deletions example/lib/src/pages/room.dart
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,28 @@ class _RoomPageState extends State<RoomPage> {
enabled: true,
onTextChanged: (text) => _chatController.onTyping(),
),
onMessageLongPress: (context, p1) async {
final confirm = await showDialog<bool>(
context: context,
builder: (context) => AlertDialog(
title: Text('Confirmation of deletion'),
content: Text('Do you really want to delete this message?'),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(false),
child: Text('Cancel'),
),
TextButton(
onPressed: () => Navigator.of(context).pop(true),
child: Text('Delete'),
),
],
),
);
if (confirm == true) {
await _chatController.deleteMessage(widget.room.id, p1.id);
}
},
),
),
),
Expand Down
14 changes: 7 additions & 7 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: example
description: A new Flutter project.
publish_to: 'none'

version: 1.5.0
version: 1.5.1

environment:
sdk: '>=3.4.0 <4.0.0'
Expand All @@ -11,7 +11,7 @@ dependencies:
cupertino_icons: ^1.0.8
dio: ^5.8.0+1
faker: ^2.2.0
file_picker: ^8.3.1
file_picker: ^10.2.0
file_saver: ^0.2.14
flutter:
sdk: flutter
Expand All @@ -20,14 +20,14 @@ dependencies:
flutter_login: ^5.0.0
flutter_supabase_chat_core:
path: ../
flutter_svg: ^2.0.17
http: ^1.3.0
flutter_svg: ^2.2.0
http: ^1.4.0
image_picker: ^1.1.2
infinite_scroll_pagination: ^4.1.0
open_filex: ^4.6.0
open_filex: ^4.7.0
path_provider: ^2.1.5
supabase_flutter: ^2.8.3
timeago: ^3.7.0
supabase_flutter: ^2.9.1
timeago: ^3.7.1


dev_dependencies:
Expand Down
70 changes: 33 additions & 37 deletions example/utils/sql/02_database_trigger.sql
Original file line number Diff line number Diff line change
Expand Up @@ -30,50 +30,46 @@ AS $$
DECLARE
latest_message jsonb;
ts_in_milliseconds bigint;
affected_room_id bigint;
BEGIN
SELECT jsonb_build_object(
'id', id,
'createdAt', "createdAt",
'metadata', metadata,
'duration', duration,
'mimeType', "mimeType",
'name', name,
'remoteId', "remoteId",
'repliedMessage', "repliedMessage",
'roomId', "roomId",
'showStatus', "showStatus",
'size', size,
'status', status,
'type', type,
'updatedAt', "updatedAt",
'uri', uri,
'waveForm', "waveForm",
'isLoading', "isLoading",
'height', height,
'width', width,
'previewData', "previewData",
'authorId', "authorId",
'text', text
)
INTO latest_message
FROM chats.messages
WHERE "roomId" = NEW."roomId"
ORDER BY "createdAt" DESC
LIMIT 1;
IF latest_message IS DISTINCT FROM (SELECT "lastMessages" FROM chats.rooms WHERE id = NEW."roomId") THEN
SELECT EXTRACT(epoch FROM NOW()) * 1000 INTO ts_in_milliseconds;
UPDATE chats.rooms
SET "updatedAt" = ts_in_milliseconds,
"lastMessages" = jsonb_build_array(latest_message)
WHERE id = NEW."roomId";
END IF;
IF TG_OP = 'DELETE' THEN
affected_room_id := OLD."roomId";
ELSE
affected_room_id := NEW."roomId";
END IF;

SELECT to_jsonb(m)
INTO latest_message
FROM chats.messages m
WHERE m."roomId" = affected_room_id
ORDER BY m."createdAt" DESC
LIMIT 1;

IF latest_message IS DISTINCT FROM (
SELECT value FROM jsonb_array_elements(
(SELECT "lastMessages" FROM chats.rooms WHERE id = affected_room_id)
) LIMIT 1
) THEN
SELECT EXTRACT(epoch FROM NOW()) * 1000 INTO ts_in_milliseconds;

UPDATE chats.rooms
SET "updatedAt" = ts_in_milliseconds,
"lastMessages" = jsonb_build_array(latest_message)
WHERE id = affected_room_id;
END IF;

IF TG_OP = 'DELETE' THEN
RETURN OLD;
ELSE
RETURN NEW;
END IF;
END;
$$ LANGUAGE plpgsql;


drop trigger if exists update_last_messages_trigger on chats.messages;
CREATE TRIGGER update_last_messages_trigger
AFTER INSERT OR UPDATE ON chats.messages
AFTER INSERT OR UPDATE OR DELETE ON chats.messages
FOR EACH ROW
EXECUTE FUNCTION chats.update_last_messages();

Expand Down
17 changes: 15 additions & 2 deletions lib/src/class/supabase_chat_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,10 @@ class SupabaseChatController {
.order('createdAt', ascending: false)
.range(pageSize * _currentPage, (_currentPage * pageSize) + pageSize);

void _onData(List<Map<String, dynamic>> data) {
for (var val in data) {
void _onData(
List<Map<String, dynamic>> newData,
) {
for (var val in newData) {
final author = _room.users.firstWhere(
(u) => u.id == val['authorId'],
orElse: () => types.User(id: val['authorId'] as String),
Expand Down Expand Up @@ -158,6 +160,17 @@ class SupabaseChatController {
'typing': typing,
};

/// Removes message.
Future<bool> deleteMessage(String roomId, String messageId) async {
final result =
await SupabaseChatCore.instance.deleteMessage(roomId, messageId);
if (result) {
_messages.removeWhere((e) => messageId == e.id);
_messagesController.sink.add(_messages);
}
return result;
}

void dispose() {
_typingChannel.untrack();
}
Expand Down
8 changes: 5 additions & 3 deletions lib/src/class/supabase_chat_core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -282,13 +282,15 @@ class SupabaseChatCore {
}

/// Removes message.
Future<void> deleteMessage(String roomId, String messageId) async {
await client
Future<bool> deleteMessage(String roomId, String messageId) async {
final result = await client
.schema(config.schema)
.from(config.messagesTableName)
.delete()
.eq('roomId', roomId)
.eq('id', messageId);
.eq('id', messageId)
.select();
return result.isNotEmpty;
}

/// Removes room.
Expand Down
32 changes: 17 additions & 15 deletions lib/src/widgets/user_status_detector/web_platform.dart
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
// ignore: avoid_web_libraries_in_flutter
import 'dart:html';

import 'dart:js_interop';
import 'package:flutter/material.dart';
import 'package:web/web.dart' as web;

import 'platforms_widgets_binding.dart';

PlatformsWidgetsBinding getInstance() => WebWidgetsBinding();

class WebWidgetsBinding extends PlatformsWidgetsBinding {
late JSFunction _focusListener;
late JSFunction _blurListener;

@override
void addObserver(WidgetsBindingObserver state) {
window.addEventListener('focus', (event) => onFocus(event, state));
window.addEventListener('blur', (event) => onBlur(event, state));
}
_focusListener = ((web.Event _) {
state.didChangeAppLifecycleState(AppLifecycleState.resumed);
}).toJS;

@override
void removeObserver(WidgetsBindingObserver state) {
window.removeEventListener('focus', (event) => onFocus(event, state));
window.removeEventListener('blur', (event) => onBlur(event, state));
}
_blurListener = ((web.Event _) {
state.didChangeAppLifecycleState(AppLifecycleState.paused);
}).toJS;

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

void onBlur(Event e, WidgetsBindingObserver state) {
state.didChangeAppLifecycleState(AppLifecycleState.paused);
@override
void removeObserver(WidgetsBindingObserver state) {
web.window.removeEventListener('focus', _focusListener);
web.window.removeEventListener('blur', _blurListener);
}
}
7 changes: 4 additions & 3 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: flutter_supabase_chat_core
description: >
Actively maintained, community-driven Supabase BaaS for chat applications
with an optional chat UI.
version: 1.5.0
version: 1.6.0
homepage: https://flutter-supabase-chat-core.insideapp.it
repository: https://github.com/insideapp-srl/flutter_supabase_chat_core

Expand All @@ -14,10 +14,11 @@ dependencies:
flutter:
sdk: flutter
flutter_chat_types: ^3.6.2
meta: ^1.15.0
meta: ^1.16.0
mime: '>=1.0.2 <3.0.0'
supabase_flutter: ^2.8.3
supabase_flutter: ^2.9.1
uuid: ^4.5.1
web: ^1.1.1

dev_dependencies:
flutter_lints: ^5.0.0
Expand Down