Flutter Templates
Como Construir um Aplicativo de Resposta de E-mail com IA usando Flutter e Back4App
41 min
introdução neste tutorial, você irá construir um aplicativo de resposta de e mail alimentado por ia usando flutter para o frontend e back4app para o backend o aplicativo irá integrar se a serviços de e mail como gmail ou outlook, analisar e mails recebidos usando modelos de ia (como o gpt 3 da openai) e gerar respostas personalizadas ao final deste tutorial, você terá um aplicativo funcional que pode gerenciar e mails, gerar respostas automatizadas e permitir que os usuários personalizem suas interações por e mail este aplicativo aproveita o poder do parse server do back4app para lidar com autenticação de usuários, armazenamento de dados e funções em nuvem, proporcionando uma solução de backend escalável sem a necessidade de gerenciar a infraestrutura do servidor integrar capacidades de ia e serviços de e mail irá aprimorar suas habilidades de desenvolvimento em flutter e fornecer uma base para construir aplicações avançadas e orientadas a dados pré requisitos para completar este tutorial, você precisará de uma conta back4app inscreva se para uma conta gratuita em https //www back4app com/ flutter sdk instalado em sua máquina local siga o https //flutter dev/docs/get started/install para o seu sistema operacional conhecimento básico de dart e flutter desenvolvimento se você é novo no flutter, considere revisar a https //flutter dev/docs antes de prosseguir familiaridade com apis rest e programação assíncrona em dart uma conta com um provedor de serviços de ia (por exemplo, openai) inscreva se para uma chave de api para acessar modelos de ia uma conta de e mail (gmail ou outlook) para testes de integração passo 1 — configurando seu backend back4app neste passo, você irá criar um novo aplicativo back4app, configurar suas classes de dados e configurar o backend para trabalhar com seu aplicativo flutter 1 1 criar um novo aplicativo no back4app faça login no seu https //dashboard back4app com/ clique em "criar novo app" digite um nome do app (por exemplo, "ai email responder") e selecione seu ícone do app escolha a localização do seu servidor, se solicitado clique em "criar" 1 2 recupere as chaves da aplicação no painel do seu app, navegue até configurações do app > segurança e chaves anote o id da aplicação e chave do cliente você precisará disso para a configuração do seu app flutter 1 3 defina suas classes de modelo de dados nós criaremos as seguintes classes no back4app usuário (padrão) emailaccount emailtemplate responsehistory 1 3 1 crie a classe emailaccount vá para banco de dados > navegador clique "criar uma classe" escolha "personalizado" e nomeie como emailaccount clique "criar classe" adicione as seguintes colunas a emailaccount usuário (pointer< user>) aponta para o user objeto endereçodeemail (string) tipodeconta (string) por exemplo, gmail, outlook tokendeautenticação (string) armazenará tokens criptografados 1 3 2 crie a classe emailtemplate repita os passos para criar uma nova classe chamada emailtemplate adicione as seguintes colunas a emailtemplate usuário (pointer< user>) nomedotemplate (string) conteúdodotemplate (string) tipodotemplate (string) por exemplo, formal, casual, acompanhamento 1 3 3 crie a classe responsehistory crie uma nova classe chamada responsehistory adicione as seguintes colunas a responsehistory usuário (pointer< user>) resumoemailoriginal (string) respostagerada (string) respostaeditadapelousuário (string) tempoeconomizado (número) 1 4 definir permissões em nível de classe certifique se de que apenas usuários autenticados possam acessar seus dados em cada classe, vá para a segurança seção defina permissões em nível de classe (clp) para permitir acesso de leitura/gravação apenas a usuários autenticados passo 2 — inicializando seu projeto flutter neste passo, você configurará seu projeto flutter e o conectará ao back4app 2 1 criar um novo projeto flutter abra seu terminal e execute flutter create ai email responder navegue até o diretório do projeto cd ai email responder 2 2 adicione dependências necessárias abra pubspec yaml e adicione as seguintes dependências dependencies flutter sdk flutter parse server sdk flutter ^4 0 1 flutter email sender ^5 0 2 http ^0 13 4 provider ^6 0 2 fl chart ^0 45 1 execute flutter pub get para instalar os pacotes 2 3 inicialize o parse em seu app crie um novo arquivo lib/config/back4app config dart // lib/config/back4app config dart const string keyapplicationid = 'your application id'; const string keyclientkey = 'your client key'; const string keyparseserverurl = 'https //parseapi back4app com'; substitua 'your application id' e 'your client key' pelas chaves do back4app em lib/main dart , inicialize o parse // lib/main dart import 'package\ flutter/material dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; import 'config/back4app config dart'; import 'app dart'; void main() async { widgetsflutterbinding ensureinitialized(); await parse() initialize( keyapplicationid, keyparseserverurl, clientkey keyclientkey, autosendsessionid true, debug true, ); runapp(myapp()); } crie lib/app dart // lib/app dart import 'package\ flutter/material dart'; import 'screens/home screen dart'; class myapp extends statelesswidget { @override widget build(buildcontext context) { return materialapp( title 'ai email responder', theme themedata( primaryswatch colors blue, ), home homescreen(), ); } } passo 3 — implementando a autenticação de usuário agora você implementará o registro e login de usuários usando o parse server 3 1 criar telas de autenticação criar lib/screens/login screen dart e lib/screens/signup screen dart para brevidade, vamos nos concentrar na funcionalidade de login // lib/screens/login screen dart import 'package\ flutter/material dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; import 'home screen dart'; class loginscreen extends statefulwidget { @override loginscreenstate createstate() => loginscreenstate(); } class loginscreenstate extends state\<loginscreen> { final texteditingcontroller usernamecontroller = texteditingcontroller(); final texteditingcontroller passwordcontroller = texteditingcontroller(); future\<void> douserlogin() async { final username = usernamecontroller text trim(); final password = passwordcontroller text trim(); final user = parseuser(username, password, null); final response = await user login(); if (response success) { navigator pushreplacement( context, materialpageroute(builder (context) => homescreen()), ); } else { showerror(response error! message); } } void showerror(string message) { scaffoldmessenger of(context) showsnackbar(snackbar(content text('error $message'))); } @override widget build(buildcontext context) { return scaffold( appbar appbar( title text('login'), ), body padding( padding const edgeinsets all(16), child column( children \[ textfield( controller usernamecontroller, decoration inputdecoration(labeltext 'username', icon icon(icons person)), ), textfield( controller passwordcontroller, decoration inputdecoration(labeltext 'password', icon icon(icons lock)), obscuretext true, ), sizedbox(height 20), elevatedbutton( onpressed douserlogin, child text('login'), ), ], ), ), ); } } 3 2 atualizar navegação da tela inicial modifique lib/app dart para direcionar os usuários para a tela de login se eles não estiverem autenticados // lib/app dart import 'package\ flutter/material dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; import 'screens/home screen dart'; import 'screens/login screen dart'; class myapp extends statelesswidget { future\<bool> hasuserloggedin() async { final currentuser = await parseuser currentuser() as parseuser?; return currentuser != null; } @override widget build(buildcontext context) { return futurebuilder\<bool>( future hasuserloggedin(), builder (context, snapshot) { if (snapshot hasdata && snapshot data == true) { return materialapp( title 'ai email responder', theme themedata(primaryswatch colors blue), home homescreen(), ); } else { return materialapp( title 'ai email responder', theme themedata(primaryswatch colors blue), home loginscreen(), ); } }, ); } } passo 4 — integrando serviços de email neste passo, você irá configurar a integração de email usando o flutter email sender pacote 4 1 configurar enviador de email adicione as permissões necessárias às suas configurações do android e ios para android , atualize android/app/src/main/androidmanifest xml \<uses permission android\ name="android permission internet"/> para ios , certifique se de que seu info plist inclui \<key>nsapptransportsecurity\</key> \<dict> \<key>nsallowsarbitraryloads\</key> \<true/> \</dict> 4 2 implementar funcionalidade de envio de email crie lib/services/email service dart // lib/services/email service dart import 'package\ flutter email sender/flutter email sender dart'; class emailservice { future\<void> sendemail(string subject, string body, list\<string> recipients) async { final email email = email( body body, subject subject, recipients recipients, ishtml false, ); await flutteremailsender send(email); } } 4 3 implementar a busca de emails (placeholder) a busca de emails de provedores como gmail requer oauth e integração de api, o que pode ser complexo para este tutorial, simularemos a busca de emails criar lib/models/email dart // lib/models/email dart class email { final string sender; final string subject; final string body; final datetime date; email({ required this sender, required this subject, required this body, required this date, }); } criar lib/services/email service dart (atualizar com dados fictícios) // lib/services/email service dart import ' /models/email dart'; class emailservice { future\<list\<email>> fetchemails() async { // simulate network delay await future delayed(duration(seconds 2)); return \[ email( sender 'john doe\@example com', subject 'meeting reminder', body 'don\\'t forget about our meeting tomorrow at 10 am ', date datetime now() subtract(duration(hours 1)), ), // add more dummy emails ]; } // existing sendemail method } passo 5 — integrando serviços de ia para geração de respostas agora você irá configurar a integração de ia para gerar respostas de email 5 1 configurar solicitações http para a api de ia instale o http pacote (já adicionado) crie lib/services/ai service dart // lib/services/ai service dart import 'dart\ convert'; import 'package\ http/http dart' as http; class aiservice { final string apikey = 'your openai api key'; final string apiurl = 'https //api openai com/v1/engines/davinci/completions'; future\<string> generateresponse(string emailcontent) async { final response = await http post( uri parse(apiurl), headers { 'authorization' 'bearer $apikey', 'content type' 'application/json', }, body jsonencode({ 'prompt' 'reply to the following email \n$emailcontent', 'max tokens' 150, }), ); if (response statuscode == 200) { final data = jsondecode(response body); return data\['choices']\[0]\['text'] trim(); } else { throw exception('failed to generate response'); } } } nota substitua 'your openai api key' pela sua chave de api real 5 2 implementar o widget editor de resposta crie lib/widgets/response editor dart // lib/widgets/response editor dart import 'package\ flutter/material dart'; class responseeditor extends statelesswidget { final string initialresponse; final texteditingcontroller controller; responseeditor({required this initialresponse}) controller = texteditingcontroller(text initialresponse); @override widget build(buildcontext context) { return textfield( controller controller, maxlines null, decoration inputdecoration( hinttext 'edit your response here ', border outlineinputborder(), ), ); } } 5 3 exibindo respostas geradas por ia em lib/screens/email detail screen dart , integre o serviço de ia // lib/screens/email detail screen dart import 'package\ flutter/material dart'; import ' /models/email dart'; import ' /services/ai service dart'; import ' /widgets/response editor dart'; import ' /services/email service dart'; class emaildetailscreen extends statefulwidget { final email email; emaildetailscreen({required this email}); @override emaildetailscreenstate createstate() => emaildetailscreenstate(); } class emaildetailscreenstate extends state\<emaildetailscreen> { final aiservice aiservice = aiservice(); final emailservice emailservice = emailservice(); string? airesponse; bool isloading = false; future\<void> generateresponse() async { setstate(() { isloading = true; }); try { final response = await aiservice generateresponse(widget email body); setstate(() { airesponse = response; }); } catch (e) { scaffoldmessenger of(context) showsnackbar(snackbar(content text('ai error $e'))); } finally { setstate(() { isloading = false; }); } } void sendresponse(string responsetext) { emailservice sendemail( 're ${widget email subject}', responsetext, \[widget email sender], ); scaffoldmessenger of(context) showsnackbar(snackbar(content text('email sent'))); } @override void initstate() { super initstate(); generateresponse(); } @override widget build(buildcontext context) { final responseeditor = airesponse != null ? responseeditor(initialresponse airesponse!) null; return scaffold( appbar appbar( title text('email from ${widget email sender}'), ), body padding( padding const edgeinsets all(16), child isloading ? center(child circularprogressindicator()) column( children \[ text(widget email body), sizedbox(height 20), responseeditor != null ? expanded(child responseeditor) container(), elevatedbutton( onpressed () { if (responseeditor != null) { sendresponse(responseeditor controller text); } }, child text('send response'), ), ], ), ), ); } } passo 6 — gerenciando modelos de email agora você implementará o gerenciamento de modelos de email usando o back4app 6 1 defina o modelo emailtemplate crie lib/models/email template dart // lib/models/email template dart import 'package\ parse server sdk flutter/parse server sdk dart'; class emailtemplate extends parseobject implements parsecloneable { emailtemplate() super('emailtemplate'); emailtemplate clone() this(); @override emailtemplate clone(map\<string, dynamic> map) => emailtemplate clone() fromjson(map); string? get templatename => get\<string>('templatename'); set templatename(string? value) => set\<string>('templatename', value); string? get templatecontent => get\<string>('templatecontent'); set templatecontent(string? value) => set\<string>('templatecontent', value); string? get templatetype => get\<string>('templatetype'); set templatetype(string? value) => set\<string>('templatetype', value); } 6 2 implemente o serviço de template criar lib/services/template service dart // lib/services/template service dart import 'package\ parse server sdk flutter/parse server sdk dart'; import ' /models/email template dart'; class templateservice { future\<list\<emailtemplate>> fetchtemplates() async { final query = querybuilder\<emailtemplate>(emailtemplate()); final response = await query find(); if (response success && response results != null) { return response results as list\<emailtemplate>; } else { return \[]; } } future\<void> addtemplate(emailtemplate template) async { await template save(); } } 6 3 criar tela de gerenciamento de modelos criar lib/screens/template management screen dart // lib/screens/template management screen dart import 'package\ flutter/material dart'; import ' /models/email template dart'; import ' /services/template service dart'; class templatemanagementscreen extends statefulwidget { @override templatemanagementscreenstate createstate() => templatemanagementscreenstate(); } class templatemanagementscreenstate extends state\<templatemanagementscreen> { final templateservice templateservice = templateservice(); list\<emailtemplate> templates = \[]; bool isloading = true; future\<void> loadtemplates() async { final fetchedtemplates = await templateservice fetchtemplates(); setstate(() { templates = fetchedtemplates; isloading = false; }); } @override void initstate() { super initstate(); loadtemplates(); } @override widget build(buildcontext context) { return scaffold( appbar appbar( title text('email templates'), ), body isloading ? center(child circularprogressindicator()) listview\ builder( itemcount templates length, itembuilder (context, index) { final template = templates\[index]; return listtile( title text(template templatename ?? 'unnamed'), subtitle text(template templatetype ?? 'no type'), ); }, ), floatingactionbutton floatingactionbutton( onpressed () { // implement template creation }, child icon(icons add), )); } } passo 7 — implementando o rastreamento de histórico de respostas agora você irá salvar as respostas geradas pela ia e as edições dos usuários no back4app para análises 7 1 definir o modelo responsehistory criar lib/models/response history dart // lib/models/response history dart import 'package\ parse server sdk flutter/parse server sdk dart'; class responsehistory extends parseobject implements parsecloneable { responsehistory() super('responsehistory'); responsehistory clone() this(); @override responsehistory clone(map\<string, dynamic> map) => responsehistory clone() fromjson(map); string? get originalemailsummary => get\<string>('originalemailsummary'); set originalemailsummary(string? value) => set\<string>('originalemailsummary', value); string? get generatedresponse => get\<string>('generatedresponse'); set generatedresponse(string? value) => set\<string>('generatedresponse', value); string? get usereditedresponse => get\<string>('usereditedresponse'); set usereditedresponse(string? value) => set\<string>('usereditedresponse', value); int? get timesaved => get\<int>('timesaved'); set timesaved(int? value) => set\<int>('timesaved', value); } 7 2 salvar histórico de respostas após enviar email atualizar lib/screens/email detail screen dart no sendresponse método import ' /models/response history dart'; // void sendresponse(string responsetext) async { await emailservice sendemail( 're ${widget email subject}', responsetext, \[widget email sender], ); // save response history final responsehistory = responsehistory() set('originalemailsummary', widget email body) set('generatedresponse', airesponse) set('usereditedresponse', responsetext) set('timesaved', calculatetimesaved()); await responsehistory save(); scaffoldmessenger of(context) showsnackbar(snackbar(content text('email sent'))); navigator pop(context); } int calculatetimesaved() { // placeholder implementation return 5; // assume 5 minutes saved } passo 8 — adicionando análises com gráficos você agora implementará um painel básico de análises usando fl chart 8 1 implementar serviço de análises criar lib/services/analytics service dart // lib/services/analytics service dart import 'package\ parse server sdk flutter/parse server sdk dart'; import ' /models/response history dart'; class analyticsservice { future\<list\<responsehistory>> fetchresponsehistories() async { final query = querybuilder\<responsehistory>(responsehistory()); final response = await query find(); if (response success && response results != null) { return response results as list\<responsehistory>; } else { return \[]; } } future\<int> calculatetotaltimesaved() async { final histories = await fetchresponsehistories(); return histories fold(0, (sum, item) => sum + (item timesaved ?? 0)); } } 8 2 criar painel de análise criar lib/screens/analytics screen dart // lib/screens/analytics screen dart import 'package\ flutter/material dart'; import 'package\ fl chart/fl chart dart'; import ' /services/analytics service dart'; class analyticsscreen extends statefulwidget { @override analyticsscreenstate createstate() => analyticsscreenstate(); } class analyticsscreenstate extends state\<analyticsscreen> { final analyticsservice analyticsservice = analyticsservice(); int totaltimesaved = 0; future\<void> loadanalytics() async { final timesaved = await analyticsservice calculatetotaltimesaved(); setstate(() { totaltimesaved = timesaved; }); } @override void initstate() { super initstate(); loadanalytics(); } @override widget build(buildcontext context) { return scaffold( appbar appbar( title text('analytics'), ), body center( child text('total time saved $totaltimesaved minutes'), )); } } passo 9 — implementando suporte offline agora você adicionará capacidades offline ao seu aplicativo usando o armazenamento de dados local do parse 9 1 habilitar armazenamento de dados local em lib/main dart , habilite o armazenamento de dados local await parse() initialize( keyapplicationid, keyparseserverurl, clientkey keyclientkey, autosendsessionid true, debug true, corestore await corestoresembastimp getinstance(), ); 9 2 modificar modelos de dados para fixação em seus modelos (por exemplo, responsehistory ), adicione métodos para fixar e desfixar objetos future\<void> pin() async { await this pin(); } future\<void> unpin() async { await this unpin(); } 9 3 implementar gerenciador offline criar lib/utils/offline manager dart // lib/utils/offline manager dart import ' /models/email dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; class offlinemanager { future\<void> cacheemails(list\<email> emails) async { for (var email in emails) { final parseobject = parseobject('email') set('sender', email sender) set('subject', email subject) set('body', email body) set('date', email date); await parseobject pin(); } } future\<list\<email>> getcachedemails() async { final query = querybuilder\<parseobject>(parseobject('email')); final response = await query frompin() find(); if (response success && response results != null) { return response results! map((e) { return email( sender e get\<string>('sender') ?? '', subject e get\<string>('subject') ?? '', body e get\<string>('body') ?? '', date e get\<datetime>('date') ?? datetime now(), ); }) tolist(); } else { return \[]; } } } 9 4 usar dados offline quando não houver conectividade na sua lógica de busca de e mails, verifique a conectividade e use dados em cache se estiver offline conclusão neste tutorial, você construiu um aplicativo de resposta automática de e mail usando flutter e back4app você configurou um backend back4app com os modelos de dados necessários e configurações de segurança inicializou um projeto flutter e o conectou ao back4app implementou autenticação de usuário com o parse server integrou o envio de e mails e simulou a busca de e mails integrou serviços de ia para gerar respostas de e mail gerenciou modelos de e mail e os armazenou no back4app acompanhou o histórico de respostas para análises adicionou análises básicas usando fl chart implementou suporte offline usando o armazenamento de dados local do parse este aplicativo fornece uma base para construir recursos mais avançados, como integração real de e mail com oauth, capacidades avançadas de ia e design de ui/ux aprimorado próximos passos integração de e mail implementar a busca real de e mails usando as apis do gmail ou outlook com autenticação oauth recursos avançados de ia ajustar os prompts de ia para melhores respostas e implementar personalização com base nos dados do usuário melhorias de ui/ux melhorar a interface do aplicativo para uma melhor experiência do usuário testes e implantação escrever testes unitários e de integração e preparar o aplicativo para implantação nas lojas de aplicativos aprimoramentos de segurança criptografar dados sensíveis e implementar um tratamento de erros robusto e validação de entrada para mais informações sobre como usar o back4app com flutter, consulte o https //www back4app com/docs/flutter/parse sdk/