From b3802c388ed30f4578e82d4d593083bbf1ef03cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Irland?= Date: Mon, 23 Oct 2023 17:41:54 +0200 Subject: [PATCH] feat: Edge function improvement (#21) --- backend/supabase/.vscode/settings.json | 5 +++ .../functions/uppercase_message/index.ts | 44 ++++++++++++------- mobile/.idea/runConfigurations/main_dev.xml | 11 +++++ mobile/.idea/runConfigurations/main_prod.xml | 11 +++++ mobile/.vscode/launch.json | 17 ++++++- mobile/SOLUTION_CODE.md | 4 ++ .../core/source/messages_remote_source.dart | 14 ++++-- .../extensions/screen_utils_extensions.dart | 11 +++++ mobile/lib/ui/widgets/message_box.dart | 24 ++++++---- mobile/pubspec.lock | 16 +++++++ mobile/pubspec.yaml | 1 + 11 files changed, 127 insertions(+), 31 deletions(-) create mode 100644 backend/supabase/.vscode/settings.json create mode 100644 mobile/.idea/runConfigurations/main_dev.xml create mode 100644 mobile/.idea/runConfigurations/main_prod.xml create mode 100644 mobile/lib/ui/extensions/screen_utils_extensions.dart diff --git a/backend/supabase/.vscode/settings.json b/backend/supabase/.vscode/settings.json new file mode 100644 index 0000000..01cede9 --- /dev/null +++ b/backend/supabase/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "deno.enable": true, + "deno.lint": true, + "deno.unstable": false +} \ No newline at end of file diff --git a/backend/supabase/functions/uppercase_message/index.ts b/backend/supabase/functions/uppercase_message/index.ts index d5d265b..e0224af 100644 --- a/backend/supabase/functions/uppercase_message/index.ts +++ b/backend/supabase/functions/uppercase_message/index.ts @@ -2,7 +2,7 @@ // https://deno.land/manual/getting_started/setup_your_environment // This enables autocomplete, go to definition, etc. -import { serve } from "https://deno.land/std@0.168.0/http/server.ts" +import { serve } from "https://deno.land/std@0.168.0/http/server.ts"; import { createClient } from "https://esm.sh/@supabase/supabase-js@2.22.0?target=deno"; const supabaseClient = createClient( @@ -12,33 +12,45 @@ const supabaseClient = createClient( global: { headers: { Authorization: "Bearer " + Deno.env.get("SUPABASE_SERVICE_ROLE_KEY"), + "Access-Control-Allow-Origin": "*", }, }, }, ); -serve(async (req) => { - const { id } = await req.json() +export const corsHeaders = { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Headers": + "authorization, x-client-info, apikey, content-type", +}; - const { data, error: getBodyError } = await supabaseClient.from("messages").select("body").eq("id", id) +const createApiResponse = (statusCode: number, body: { message: string }) => { + const headers = { ...corsHeaders, "Content-Type": "application/json" }; + return new Response(JSON.stringify(body), { headers, status: statusCode }); +}; - if (getBodyError != null) { - return new Response(JSON.stringify({ "message": "Error getting message body" }), { headers: { "Content-Type": "application/json" } },) +serve(async (req) => { + // Required for web browsers + if (req.method === "OPTIONS") { + return createApiResponse(200, { message: "ok" }); } - const body = data[0].body + const { id } = await req.json(); + const { data: messages, error: getBodyError } = await supabaseClient.from( + "messages", + ).select("body").eq("id", id); - const capitalizedMessage = body.toUpperCase() + if (getBodyError != null || !messages || messages.length !== 1) { + return createApiResponse(400, { message: "Error getting message" }); + } - const { error: updateMessageError } = await supabaseClient.from("messages").update({ body: capitalizedMessage }).eq("id", id) + const capitalizedBody = messages[0].body.toUpperCase(); + const { error: updateMessageError } = await supabaseClient.from("messages") + .update({ body: capitalizedBody }).eq("id", id); if (updateMessageError != null) { - return new Response(JSON.stringify({ "message": "Error updating message" }), { headers: { "Content-Type": "application/json" } },) + return createApiResponse(500, { message: "Error updating message" }); } - - return new Response( - JSON.stringify({ "message": "Success" }), - { headers: { "Content-Type": "application/json" } }, - ) -}) + return createApiResponse(200, { "message": "Success" }); +}); diff --git a/mobile/.idea/runConfigurations/main_dev.xml b/mobile/.idea/runConfigurations/main_dev.xml new file mode 100644 index 0000000..1c69cb9 --- /dev/null +++ b/mobile/.idea/runConfigurations/main_dev.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/mobile/.idea/runConfigurations/main_prod.xml b/mobile/.idea/runConfigurations/main_prod.xml new file mode 100644 index 0000000..9696055 --- /dev/null +++ b/mobile/.idea/runConfigurations/main_prod.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/mobile/.vscode/launch.json b/mobile/.vscode/launch.json index 4745704..6fbcb40 100644 --- a/mobile/.vscode/launch.json +++ b/mobile/.vscode/launch.json @@ -5,12 +5,25 @@ "version": "0.2.0", "configurations": [ { - "name": "supabase-ws-flutter-development", + "name": "Main Dev", "request": "launch", "type": "dart", "program": "lib/main.dart", "args": [ - "--flavor=dev" + "--flavor=dev", + "--dart-define=ENV=dev", + "--web-port=3003" + ] + }, + { + "name": "Main prod", + "request": "launch", + "type": "dart", + "program": "lib/main.dart", + "args": [ + "--flavor=prod", + "--web-port=3003", + "--dart-define=ENV=prod" ] } ] diff --git a/mobile/SOLUTION_CODE.md b/mobile/SOLUTION_CODE.md index 9cdced9..fc3d9d0 100644 --- a/mobile/SOLUTION_CODE.md +++ b/mobile/SOLUTION_CODE.md @@ -105,6 +105,10 @@ CREATE TABLE ) tablespace pg_default; +-- Enable Realtime +alter + publication supabase_realtime add table public.users; + -- Insert alias into the new table INSERT INTO public.users (id, alias) diff --git a/mobile/lib/core/source/messages_remote_source.dart b/mobile/lib/core/source/messages_remote_source.dart index b923527..63bf228 100644 --- a/mobile/lib/core/source/messages_remote_source.dart +++ b/mobile/lib/core/source/messages_remote_source.dart @@ -45,9 +45,15 @@ class MessagesRemoteSourceImpl implements MessagesRemoteSource { } @override - Future uppercaseMessage({required String id}) => - supabaseClient.functions.invoke( - 'uppercase_message', - body: {'id': id}, + Future uppercaseMessage({required String id}) async { + final response = await supabaseClient.functions.invoke( + 'uppercase_message', + body: {'id': id}, + ); + if (response.status! > 299) { + throw Exception( + 'Error calling function: code ${response.status} body ${response.data}', ); + } + } } diff --git a/mobile/lib/ui/extensions/screen_utils_extensions.dart b/mobile/lib/ui/extensions/screen_utils_extensions.dart new file mode 100644 index 0000000..70f76cf --- /dev/null +++ b/mobile/lib/ui/extensions/screen_utils_extensions.dart @@ -0,0 +1,11 @@ +import 'dart:math'; + +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +extension SizeExtension on num { + double get wf => min(this * 1.08, w); + + double get hf => min(this * 1.08, h); + + double get rf => min(this * 1.08, r); +} diff --git a/mobile/lib/ui/widgets/message_box.dart b/mobile/lib/ui/widgets/message_box.dart index 710285f..e924951 100644 --- a/mobile/lib/ui/widgets/message_box.dart +++ b/mobile/lib/ui/widgets/message_box.dart @@ -1,11 +1,14 @@ import 'package:flutter/material.dart'; +import 'package:flutter_linkify/flutter_linkify.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_template/core/common/extension/date_time_extensions.dart'; import 'package:flutter_template/core/model/message.dart'; import 'package:flutter_template/core/model/user_message.dart'; import 'package:flutter_template/ui/extensions/context_extensions.dart'; +import 'package:flutter_template/ui/extensions/screen_utils_extensions.dart'; import 'package:flutter_template/ui/theme/app_theme.dart'; import 'package:flutter_template/ui/theme/text_styles.dart'; +import 'package:url_launcher/url_launcher.dart'; class MessageBox extends StatelessWidget { final UserMessage userMessage; @@ -36,10 +39,10 @@ class MessageBox extends StatelessWidget { _UserAliasSection(userMessage: userMessage), Container( padding: EdgeInsets.only( - right: 12.w, - left: 12.w, - top: 8.h, - bottom: 12.h, + right: 12.rf, + left: 12.rf, + top: 8.rf, + bottom: 12.rf, ), decoration: BoxDecoration( color: userMessage.isFromCurrentUser @@ -59,11 +62,12 @@ class MessageBox extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - SelectableText( - userMessage.message.body, + SelectableLinkify( + text: userMessage.message.body, style: context.theme.textStyles.bodyMedium?.copyWith( color: context.theme.colors.textColor.shade100, ), + onOpen: (link) => launchUrl(Uri.parse(link.url)), ), SizedBox(height: 2.h), Text( @@ -96,9 +100,11 @@ class _UppercaseButton extends StatelessWidget { @override Widget build(BuildContext context) => InkWell( onTap: () => onTap(message), - child: SizedBox( - height: 20.h, - width: 60.w, + child: Padding( + padding: EdgeInsets.symmetric( + vertical: 7.rf, + horizontal: 5.rf, + ), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index 9710b78..de36827 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -406,6 +406,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.13.1" + flutter_linkify: + dependency: "direct main" + description: + name: flutter_linkify + sha256: "74669e06a8f358fee4512b4320c0b80e51cffc496607931de68d28f099254073" + url: "https://pub.dev" + source: hosted + version: "6.0.0" flutter_lints: dependency: "direct dev" description: @@ -677,6 +685,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.1" + linkify: + dependency: transitive + description: + name: linkify + sha256: "4139ea77f4651ab9c315b577da2dd108d9aa0bd84b5d03d33323f1970c645832" + url: "https://pub.dev" + source: hosted + version: "5.0.0" lints: dependency: "direct dev" description: diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index 01e27ab..d161c54 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -29,6 +29,7 @@ dependencies: floor: 1.4.2 flutter_bloc: 8.1.3 flutter_dotenv: 5.1.0 + flutter_linkify: 6.0.0 flutter_native_splash: 2.3.2 flutter_screenutil: 5.9.0 flutter_secure_storage: 9.0.0