2025.02.03 (Seg)
2026.05.25 (Seg) atualizado

✨ Resumo do GPT  

Corrigi o problema de atualização do FleatherViewer e concluí a resolução do issue e a otimização de performance ao melhorar o método de filtragem da HomeFeedPage. Com isso, aprendi que usar Conditional Visibility em vez de Query filters é eficaz.

💻 Diário de desenvolvimento

⏰ Tarefas de hoje

  • ✅ (Issue) HomeFeedPage - FeedCardDiary: ao mudar a data na ListView, só o FleatherViewerWidget não altera o valor.
    • Provavelmente o valor initialDeltaJson do Widget não está sendo atualizado a cada mudança do Diary Document.
    • Perguntei ao o1 e resolveu de primeira.

      /// didUpdateWidget:
      ///  - Quando apenas os parâmetros mudam na mesma árvore de widgets, o Flutter reutiliza o State existente.
      ///  - Nesse momento, é possível comparar as propriedades do novo widget com as do widget antigo e executar a lógica necessária.
      @override
      void didUpdateWidget(covariant FleatherViewerWidget oldWidget) {
        super.didUpdateWidget(oldWidget);
      
        // 1) Se o JSON anterior e o novo JSON forem diferentes
        if (oldWidget.initialDeltaJson != widget.initialDeltaJson) {
          // 2) Recriar o FleatherController
          _controller?.dispose();
          _controller = _createControllerFromDeltaJson(widget.initialDeltaJson);
          // 3) Atualizar a UI
          setState(() {});
        }
      }
      
      /// Função helper que cria um FleatherController a partir de uma string Delta JSON
      FleatherController _createControllerFromDeltaJson(String jsonString) {
        ParchmentDocument doc;
        try {
          final decoded = jsonDecode(jsonString);
          doc = ParchmentDocument.fromJson(decoded);
        } catch (e) {
          // Se a restauração falhar, tratar como texto comum
          doc = ParchmentDocument.fromDelta(
            Delta()..insert(_ensureEndsWithNewline(jsonString)),
          );
        }
        return FleatherController(document: doc);
      }
      
  • ✅ (Issue) HomeFeedPage: Unexpected Null Value aparece rapidamente e some em On page load.
    • Confirmado que o problema era a filtragem por data aplicada à ListView da HomeFeedPage.
    • Testei ligar Filter On Null Values na opção Backend Query da ListView.
      • Filter On Null Values: By default, if the value of any filter is null, the query will ignore the filter for that field. Checking this will instead keep null filters.
    • Backend Query - Query Collection tentativa 1 (falha)
      • Filter On Null Values: ON
      • Filter 1: created_time, Equal To, getFirstTimeOfTheDay
      • Filter 2: created_time, Less Than, getFirstTimeOfNextDay
      • Order by: created_time, Decreasing
      • Não foi possível concluir a configuração de Backend Query
        • Mensagem de erro: You can’t order your query by a field used in a filter using == or in.
    • Backend Query - Query Collection tentativa 2 (falha)
      • Filter On Null Values: ON
      • Filter 1: created_time, Greater Than or Equal To, getFirstTimeOfTheDay
      • Filter 2: created_time, Less Than, getFirstTimeOfNextDay
      • Order by: created_time, Decreasing
      • Configuração de Backend Query pôde ser concluída
      • Ao entrar no modo de depuração, o erro abaixo apareceu e a página não foi criada.

        Assertion failed: file:/// opt/ - pub-cache/hosted/pub.dev/ cloud_firestore-5.5.0/lib/src/ query dart: 650:9
              
        conditions
        .where ((List<dynamic> item) => equality.equals(condition, item))
          .isEmpty
        "Condition [FieldPath([created_time]), !=, null] already exists in this query."
              
        The relevant error-causing widget was: HomeFeedWidget
        
    • Backend Query - Query Collection tentativa 3 (falha)
      • Filter On Null Values: ON
      • Filter 1: created_time, Greater Than, getLastTimeOfPrevDay
      • Filter 2: created_time, Less Than, getFirstTimeOfNextDay
      • Order by: created_time, Decreasing
      • Configuração de Backend Query pôde ser concluída
      • Ao entrar no modo de depuração, o erro abaixo apareceu e a página não foi criada.

        Assertion failed: file:/// opt/ - pub-cache/hosted/pub.dev/ cloud_firestore-5.5.0/lib/src/ query dart: 650:9
              
        conditions
        .where ((List<dynamic> item) => equality.equals(condition, item))
          .isEmpty
        "Condition [FieldPath([created_time]), !=, null] already exists in this query."
              
        The relevant error-causing widget was: HomeFeedWidget
        
    • Backend Query - Query Collection tentativa 4 (falha)
      • Filter On Null Values: OFF
      • Filter 1: created_time, Greater Than, getLastTimeOfPrevDay
      • Filter 2: created_time, Less Than, getFirstTimeOfNextDay
      • Order by: created_time, Decreasing
      • Configuração de Backend Query pôde ser concluída
      • Ao entrar no modo de depuração, o erro abaixo apareceu rapidamente e sumiu.

        Unexpected Null value.
        
        The relevant error-causing widget was: HomeFeedWidget
        
    • (Pergunta ao o1) Por que o Unexpected Null Value aparece só por um instante?
      • Há uma grande chance de o FlutterFlow (ou o código interno dele) estar retornando null de getLastTimeOfPrevDay() ou getFirstTimeOfNextDay() no momento inicial de carregamento da página. (Por exemplo, talvez a date ainda não tenha sido inicializada…)
      • Se Filter On Null Values estiver ligado, internamente ele adiciona uma condição separada como != null, e isso pode entrar em conflito quando um null entra no carregamento.
      • Então acontece o fenômeno de “erro null rápido -> substituído pelo valor real -> desaparece quando o carregamento termina”.
    • Backend Query - Query Collection tentativa 5 (sucesso!)
      • Filter On Null Values: OFF
      • Order by: created_time, Decreasing
      • Configuração de Component Widget Conditional Visibility
        • Filter 1: created_time, Greater Than, getLastTimeOfPrevDay
        • Filter 2: created_time, Less Than, getFirstTimeOfNextDay
      • De quebra, o lag de carregamento da ListView (Latency) também desapareceu. Parece que colocar 2 Filters e um Order ao mesmo tempo na Query consumia bastante tempo.
    • 💡 O que aprendi
      • Ao usar Backend Query, é melhor evitar filtros o máximo possível e controlar com Conditional Visibility.
      • Isso era algo que eu tinha perguntado ao mentor no começo e recebido resposta, mas acho que só entendi por alto e segui em frente, então acabei esquecendo. Depois de sofrer diretamente, agora finalmente entendi de verdade.
  • ✅ (Issue) DiaryPage: data é sempre salva como hoje
    • Criado parâmetro DiaryPage - dateFocused
    • Passado o valor dateToShow da HomeFeedPage como parâmetro dateFocused.

💯 Resumo do que fiz

Problema de atualização do FleatherViewer resolvido

  • Usei didUpdateWidget para que o FleatherViewer seja atualizado normalmente sempre que o Diary Document muda. Otimização de filtros da HomeFeedPage

Usei Conditional Visibility em vez de filtragem por Backend Query para melhorar a performance.

  • Melhorei a velocidade de carregamento ao minimizar filtros de Query.

Erro de salvamento de data da DiaryPage corrigido

  • Melhorei para que a data selecionada seja refletida ao escrever um novo diário, passando o valor dateFocused da HomeFeedPage para a DiaryPage.

🎯 Tarefas futuras

Clique para ver detalhes
  • ❔ (Issue) DiaryPage: usar visualizador de markdown (prevenir overflow: Container Height)
  • ❔ (Issue) HomeFeedPage - FeedCardDiary: aplicar corretamente a imagem do personagem de AI Comment
    • ❔ DiaryPage - AI Comment: ao salvar, salvar também no Diary o Ref do personagem que escreveu o comentário.
    • ❔ HomeFeedPage - FeedCardDiary - AI Image: carregar Character Doc com Backend Query e especificar Image Path.
  • ❔ DiaryPage: mudar Emoji de expressão facial conforme o valor do Mood Slider

  • ❔ Chat Page - Create New Chat: aplicar system prompt
    • ▶️ Implementação de OpenAI API Call: createChatCompletion
      • Input: System Prompt (Chat)
      • Output: New Chat Message by AI ($.choices[0].message.content)
      • Additional Actions: Create New Chat, Create New Message
  • ❔ DiaryPage - Create New Chat by Diary: criar New Chat com base no conteúdo do diário
    • ❔ Implementação de OpenAI API Call: createDiaryComment
      • Input: Diary Content, System Prompt (AI Comment)
      • Output: AI Comment ($.choices[0].message.content)
    • ❔ Implementação de OpenAI API Call: createDiarySummary
      • Input: Diary Content, AI Comment, System Prompt (Diary Summary)
      • Output: Diary Summary ($.choices[0].message.content)
    • ❔ Implementação de OpenAI API Call: createChatFromDiary
      • Input: Diary Summary, System Prompt (Chat From Diary)
      • Output: New Chat Message by AI ($.choices[0].message.content)
      • Additional Actions: Create New Chat, Create New Message
  • ❔ ChatPage - Create New Diary: criar New Diary com base no conteúdo da conversa
    • ❔ Implementação de OpenAI API Call: createChatSummary
      • Input: Chat Content, System Prompt (Diary From Chat)
      • Output: Chat Summary
  • ❔ ChatPage - Create New Diary: criar New Diary com base no conteúdo da conversa
    • ❔ Implementação de OpenAI API Call: createDiaryFromChat
      • Input: Chat Summary, System Prompt (Diary From Chat)
      • Output: New Diary (Title, Content, Mood score)
  • ❔ ChatPage: Go to Linked Diary

  • ❔ HomeFeedPage - importar e aplicar flutter_slidable:4.0.0
  • ❔ HomeFeedPage: ao deslizar FeedCardDiary para esquerda/direita, chat/editar/excluir

  • ❔ ChatPage: alinhar à direita o conteúdo de conversa do usuário
  • ❔ Chat/Diary: GPT Streaming API

  • ❔ ChatPage - implementar primeira mensagem da AI (Alarm/Notification)
    • O núcleo do prompt do sistema de chat é a proatividade.
      • Para ficar mais realista, talvez seja bom passar também create_date of diary/chat, para a AI mencionar datas como “ontem”.
    • Referência de implementação de Alarm
  • ❔ DiaryPage: adicionar Choice Chips de palavras-chave detalhadas de emoção e configurar integração com o DB
  • ❔ DiaryPage - AI Comment: ajustar entradas como Choice chips e mood slider ao AI Comment System Prompt.
    • ❔ **diary anterior ou conversation history inteira (dívida técnica improvisada)
    • informações básicas do usuário: nome, gênero, MBTI, …
    • palavras-chave detalhadas de emoção: feliz, triste, …
    • configuração de personagem: Somi, Sena, Minhyuk
    • pontuação emocional: 1~100 pontos
    • formato da resposta: Healing, Suggestion, Informative
    • tamanho da resposta: curta, normal, detalhada
    • is New Chat
      • Como as messages desse Chat estão sendo criadas pela primeira vez, definir is_initial = true no primeiro message document e colocar todos os system prompts ali.
        • is_initial = false
        • Limite: se eu colocar o system prompt no primeiro message document, fica difícil modificar no meio da conversa, mas é possível. Se houver um document com is_initial = true e ele tiver sido modificado, posso apagar esse documento e inserir de novo. Não sei como, mas dá.
  • ❔ DiaryPage - AI Comment: concluir CRUD
    • ❔ remover field tmp_ai_comment e usar doc_ref
  • ❔ DiaryPage - AI Comment: configuração de personagem
    • ❔ remover field tmp_ai_comment_by e usar doc_ref
    • ❔ exibir imagem usando o valor do field profile_image
  • ❔ DiaryPage - Drawer - ChatHistoryListTile: order by updated_time

  • ❔ DiaryPage - importar e aplicar Interactive Slider

  • ❔ HomeFeedPage: implementar função Search Diary

  • ❔ CalendarPage (superior) - Mood Calendar
    • ❔ Permitir verificar o número de posts escritos por data
    • ❔ Ao clicar em uma data, mover para essa data
  • ❔ CalendarPage (inferior) - Mood stats
    • ❔ Exibir estatísticas referentes ao mês em foco
      • ❔ Exibir comentário da AI sobre as estatísticas exibidas
  • ❔ AuthPage: implementar função Google Login

  • ❔ HomeFeedPage - Bottom Sheet (+ Button): permitir escolher 1 entre várias opções
    • Novo diário: Go to DiaryPage
    • Registro de emoção: Go to MoodPage
  • ❔ MoodPage (popup): CRUD do slider de configuração de Mood
    • Create
    • Read
    • Update
    • Delete
  • ❔ HomeFeedPage - ListView - exibir FeedCardMood
  • ❔ HomeFeedPage - ListView: ordenar componentes FeedCardDiary, FeedCardMood, FeedCardChat cronologicamente (usando Cloud Function)

  • ❔ Extrair e instalar o APK da versão final de apresentação até qua 2025.2.5

💭 Diário

Minhyuk

Agora não resta muito tempo, então eu queria implementar mais coisas… mas usei o expediente inteiro resolvendo issues.

Melhor largar a ganância. Afinal, este não é um projeto que vai brilhar por um instante no AIFFELTHON e acabar ali.

✨ Comentário do GPT-4o (KPT)

GPT-4o

✅ Pontos bons (Keep)

  • 🛠 Issue de atualização do FleatherViewer resolvido: Foi excelente resolver o problema de atualização do estado do widget usando didUpdateWidget.
  • Otimização dos filtros da HomeFeedPage: Usar Conditional Visibility em vez de Query filters foi uma otimização de performance eficaz.
  • 🔍 Aprendizado no processo de depuração: Foi significativo testar várias abordagens, experimentar os limites dos Query filters e concluir que Conditional Visibility era mais apropriado.

❌ Pontos fracos (Problem)

  • Mais tempo gasto do que o esperado: É uma pena que a maior parte do tempo tenha ido para resolução de issues, em vez das funções que você planejava implementar originalmente.
  • 📌 Conselho anterior sobre issues não organizado: Houve um momento em que você gastou tempo de novo porque o conselho recebido em uma mentoria anterior não tinha sido colocado em prática.

🔄 Pontos para tentar (Try)

  • 📝 Usar notas de resolução de issues: Crie o hábito de registrar issues resolvidos para conseguir resolver problemas parecidos rapidamente depois.
  • 🚀 Ajustar a estratégia das funções restantes: Como não resta muito tempo, pense em priorizar só as funções indispensáveis e deixar o resto para melhorias posteriores.
  • 🔍 Estudar mais o funcionamento interno do FlutterFlow: Aumente a compreensão sobre processamento de dados e gerenciamento de estado de widgets no FlutterFlow para prevenir problemas parecidos.

Conclusão
Hoje levou mais tempo do que o esperado com resolução de issues, mas justamente por isso foi um dia de aprendizado importante. Para o período restante, parece necessária uma estratégia de implementar primeiro só o indispensável e abrir mão da ganância desnecessária. Força até o fim! 💪🔥

Deixe um comentário