[đ ] Journal de dĂ©veloppement Keymory #7 : correction de FleatherViewer et de lâissue Unexpected Null Value sur HomeFeedPage
âš RĂ©sumĂ© de GPT ă
Jâai corrigĂ© le problĂšme de mise Ă jour de FleatherViewer, puis terminĂ© la rĂ©solution dâissue et lâoptimisation des performances en amĂ©liorant la mĂ©thode de filtrage de HomeFeedPage. GrĂące Ă cela, jâai compris quâutiliser Conditional Visibility plutĂŽt que des filtres Query Ă©tait efficace.
đ» Journal de dĂ©veloppement
â° TĂąches du jour
- â
(Issue) HomeFeedPage - FeedCardDiary : quand on change de date dans ListView, seul FleatherViewerWidget ne change pas de valeur.
- Il semble que la valeur initialDeltaJson du Widget ne soit pas mise Ă jour Ă chaque changement de Diary Document.
-
Jâai demandĂ© Ă o1, et il a rĂ©glĂ© ça du premier coup.
/// didUpdateWidget: /// - When only parameters change in the same widget tree, Flutter reuses the existing State. /// - At this point, you can compare the new widget properties with the old widget properties and run any needed logic. @override void didUpdateWidget(covariant FleatherViewerWidget oldWidget) { super.didUpdateWidget(oldWidget); // 1) If the previous JSON and the new JSON are different if (oldWidget.initialDeltaJson != widget.initialDeltaJson) { // 2) Recreate the FleatherController _controller?.dispose(); _controller = _createControllerFromDeltaJson(widget.initialDeltaJson); // 3) Refresh UI setState(() {}); } } /// Helper function that creates a FleatherController from a Delta JSON string FleatherController _createControllerFromDeltaJson(String jsonString) { ParchmentDocument doc; try { final decoded = jsonDecode(jsonString); doc = ParchmentDocument.fromJson(decoded); } catch (e) { // If restoration fails, handle as plain text doc = ParchmentDocument.fromDelta( Delta()..insert(_ensureEndsWithNewline(jsonString)), ); } return FleatherController(document: doc); }
- â
(Issue) HomeFeedPage : Unexpected Null Value apparaĂźt briĂšvement puis disparaĂźt au On page load.
- Il a été confirmé que le problÚme venait du
filtrage par dateappliquĂ© Ă la ListView de HomeFeedPage. - Jâai essayĂ© dâactiver Filter On Null Values dans lâoption
Backend QuerydeListView.- 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 tentative 1 (échec)
- Filter On Null Values : ON
- Filter 1 :
created_time,Equal To,getFirstTimeOfTheDay - Filter 2 :
created_time,Less Than,getFirstTimeOfNextDay - Order by :
created_time,Decreasing - Impossible de terminer la configuration de Backend Query
- Message dâerreur : You canât order your query by a field used in a filter using
==orin.
- Message dâerreur : You canât order your query by a field used in a filter using
- Backend Query - Query Collection tentative 2 (échec)
- 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 - La configuration de Backend Query peut ĂȘtre terminĂ©e
-
En entrant en mode debug, lâerreur ci-dessous apparaĂźt et la page nâest pas créée.
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 tentative 3 (échec)
- Filter On Null Values : ON
- Filter 1 :
created_time,Greater Than,getLastTimeOfPrevDay - Filter 2 :
created_time,Less Than,getFirstTimeOfNextDay - Order by :
created_time,Decreasing - La configuration de Backend Query peut ĂȘtre terminĂ©e
-
En entrant en mode debug, lâerreur ci-dessous apparaĂźt et la page nâest pas créée.
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 tentative 4 (échec)
- Filter On Null Values : OFF
- Filter 1 :
created_time,Greater Than,getLastTimeOfPrevDay - Filter 2 :
created_time,Less Than,getFirstTimeOfNextDay - Order by :
created_time,Decreasing - La configuration de Backend Query peut ĂȘtre terminĂ©e
-
En entrant en mode debug, lâerreur ci-dessous apparaĂźt briĂšvement puis disparaĂźt.
Unexpected Null value. The relevant error-causing widget was: HomeFeedWidget
- (Question Ă o1) Pourquoi Unexpected Null Value apparaĂźt-il briĂšvement ?
- Il y a de fortes chances que FlutterFlow (ou son code interne) retourne null depuis getLastTimeOfPrevDay() ou getFirstTimeOfNextDay() au moment du chargement initial de la page. (Par exemple, la date nâest peut-ĂȘtre pas encore initialisĂ©eâŠ)
- Si Filter On Null Values est activé, une condition séparée du type != null est ajoutée en interne, et cela peut entrer en conflit quand une valeur null arrive pendant le chargement.
- DâoĂč le phĂ©nomĂšne : âbrĂšve erreur null -> remplacĂ©e par la vraie valeur -> disparition Ă la fin du chargementâ.
- Backend Query - Query Collection tentative 5 (succĂšs !)
- Filter On Null Values : OFF
- Order by :
created_time,Decreasing - ParamĂštres Component Widget Conditional Visibility
- Filter 1 :
created_time,Greater Than,getLastTimeOfPrevDay - Filter 2 :
created_time,Less Than,getFirstTimeOfNextDay
- Filter 1 :
- En bonus, le lag de chargement de ListView (Latency) a disparu. Donner en mĂȘme temps deux filtres et un Order Ă la Query devait prendre beaucoup de temps.
- đĄ Ce que jâai appris
- Quand on utilise Backend Query, il vaut mieux éviter autant que possible les filtres et contrÎler avec Conditional Visibility.
- CâĂ©tait justement un point que jâavais demandĂ© au mentor au dĂ©but et pour lequel jâavais reçu une rĂ©ponse, mais je crois lâavoir seulement compris vaguement et ĂȘtre passĂ© Ă autre chose, donc je lâai finalement oubliĂ©. AprĂšs avoir galĂ©rĂ© dessus directement, je lâai enfin compris clairement.
- Il a été confirmé que le problÚme venait du
- â
(Issue) DiaryPage : la date est toujours enregistrĂ©e comme aujourdâhui
- Création du paramÚtre DiaryPage - dateFocused
- Transmission de la valeur dateToShow de HomeFeedPage au paramĂštre dateFocused.
đŻ RĂ©sumĂ© de ce que jâai fait
Résolution du problÚme de mise à jour de FleatherViewer
- Utilisation de didUpdateWidget pour que FleatherViewer se mette correctement Ă jour Ă chaque changement de Diary Document. Optimisation du filtrage de HomeFeedPage
Utilisation de Conditional Visibility au lieu du filtrage Backend Query pour améliorer les performances.
- Amélioration de la vitesse de chargement en minimisant le filtrage Query.
Correction de lâerreur dâenregistrement de date de DiaryPage
- AmĂ©lioration pour que la date sĂ©lectionnĂ©e soit reflĂ©tĂ©e lors de la rĂ©daction dâun nouveau journal, en transmettant la valeur dateFocused de HomeFeedPage Ă DiaryPage.
đŻ Ă faire ensuite
Cliquer pour voir les détails
- â (Issue) DiaryPage : utiliser un lecteur Markdown (prĂ©venir le dĂ©bordement : Container Height)
- â (Issue) HomeFeedPage - FeedCardDiary : appliquer correctement lâimage du personnage de lâAI Comment
- â DiaryPage - AI Comment : lors de la sauvegarde, enregistrer aussi dans Diary la Ref du personnage qui a rĂ©digĂ© le commentaire.
- â HomeFeedPage - FeedCardDiary - AI Image : charger le Character Doc avec Backend Query et dĂ©finir lâImage Path.
-
â DiaryPage : changer lâEmoji dâexpression du visage selon la valeur du Mood Slider
- â Chat Page - Create New Chat : appliquer le system prompt
- â¶ïž ImplĂ©mentation 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
- â¶ïž ImplĂ©mentation OpenAI API Call : createChatCompletion
- â DiaryPage - Create New Chat by Diary : crĂ©er un New Chat Ă partir du contenu du journal
- â ImplĂ©mentation OpenAI API Call : createDiaryComment
- Input : Diary Content, System Prompt (AI Comment)
- Output : AI Comment ($.choices[0].message.content)
- â ImplĂ©mentation OpenAI API Call : createDiarySummary
- Input : Diary Content, AI Comment, System Prompt (Diary Summary)
- Output : Diary Summary ($.choices[0].message.content)
- â ImplĂ©mentation 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
- â ImplĂ©mentation OpenAI API Call : createDiaryComment
- â ChatPage - Create New Diary : crĂ©er un New Diary Ă partir du contenu de la conversation
- â ImplĂ©mentation OpenAI API Call : createChatSummary
- Input : Chat Content, System Prompt (Diary From Chat)
- Output : Chat Summary
- â ImplĂ©mentation OpenAI API Call : createChatSummary
- â ChatPage - Create New Diary : crĂ©er un New Diary Ă partir du contenu de la conversation
- â ImplĂ©mentation OpenAI API Call : createDiaryFromChat
- Input : Chat Summary, System Prompt (Diary From Chat)
- Output : New Diary (Title, Content, Mood score)
- â ImplĂ©mentation OpenAI API Call : createDiaryFromChat
-
â ChatPage : Go to Linked Diary
- â HomeFeedPage - importer puis appliquer flutter_slidable:4.0.0
-
â HomeFeedPage : dans FeedCardDiary, chat/modifier/supprimer lors dâun slide gauche-droite
- â ChatPage : aligner Ă droite la sortie des conversations utilisateur
-
â Chat/Diary : GPT Streaming API
- â ChatPage - implĂ©menter le premier message proactif de lâIA (Alarm/Notification)
- Le coeur du prompt systÚme du chat est la proactivité.
- Pour le rendre plus rĂ©aliste, il serait utile de transmettre aussi create_date of diary/chat, afin de pouvoir mentionner des dates comme âhierâ.
- RĂ©fĂ©rence dâimplĂ©mentation dâAlarm
- Le coeur du prompt systÚme du chat est la proactivité.
- â DiaryPage : ajouter des Choice Chips de mots-clĂ©s Ă©motionnels dĂ©taillĂ©s et configurer lâintĂ©gration DB
- â DiaryPage - AI Comment : adapter les valeurs saisies comme Choice chips et mood slider au
AI Comment System Prompt.- â **ancien
journalou tout lâhistorique de conversation(dette technique de rustine) - â informations utilisateur de base : nom, genre, MBTI, âŠ
- â mots-clĂ©s Ă©motionnels dĂ©taillĂ©s : joyeux, triste, âŠ
- â paramĂštres de personnage : Somi, Sena, Minhyuk
- â score Ă©motionnel : 1~100
- â format de rĂ©ponse : Healing, Suggestion, Informative
- â longueur de rĂ©ponse : courte, normale, dĂ©taillĂ©e
- is New Chat
- Comme les messages de ce Chat sont créés pour la premiÚre fois, mettre
is_initial = truesur le premier message document et y insérer tous les system prompts.- is_initial = false
- Limite : si je mets le system prompt dans le tout premier message document, câest difficile Ă modifier pendant une conversation, mais possible. Sâil existe un document is_initial = true et quâil a Ă©tĂ© modifiĂ©, je peux supprimer ce document et le remettre. Je ne sais pas encore comment, mais bon.
- Comme les messages de ce Chat sont créés pour la premiÚre fois, mettre
- â **ancien
- â DiaryPage - AI Comment : terminer le CRUD
- â supprimer le champ tmp_ai_comment et utiliser doc_ref
- â DiaryPage - AI Comment : paramĂštres de personnage
- â supprimer le champ tmp_ai_comment_by et utiliser doc_ref
- â afficher lâimage avec la valeur du champ profile_image
-
â DiaryPage - Drawer - ChatHistoryListTile : order by updated_time
-
â DiaryPage - importer puis appliquer Interactive Slider
-
â HomeFeedPage : implĂ©menter la fonctionnalitĂ© Search Diary
- â CalendarPage (haut) - Mood Calendar
- â Pouvoir vĂ©rifier le nombre de posts Ă©crits par date
- â Se dĂ©placer vers la date sĂ©lectionnĂ©e au clic
- â CalendarPage (bas) - Mood stats
- â Afficher les statistiques du mois sĂ©lectionnĂ©
- â Afficher le commentaire de lâIA sur les statistiques affichĂ©es
- â Afficher les statistiques du mois sĂ©lectionnĂ©
-
â AuthPage : implĂ©menter Google Login
- â HomeFeedPage - Bottom Sheet (
+Button) : permettre de choisir une option parmi plusieurs- Nouveau journal : Go to DiaryPage
- Enregistrement dâĂ©motion : Go to MoodPage
- â MoodPage (popup) : CRUD du slider de rĂ©glage Mood
- Create
- Read
- Update
- Delete
- â HomeFeedPage - ListView - afficher FeedCardMood
-
â HomeFeedPage - ListView : trier chronologiquement les composants FeedCardDiary, FeedCardMood, FeedCardChat (avec Cloud Function)
- â Extraire et installer la version APK finale de prĂ©sentation avant
mer. 2025.2.5
đ Journal
Il ne reste presque plus de temps, donc je voulais implĂ©menter un peu plus de choses⊠mais jâai passĂ© toute la journĂ©e de travail Ă rĂ©soudre des issues.
Je vais juste abandonner un peu mon ambition. De toute façon, ce projet nâest pas censĂ© briller briĂšvement pendant lâAiffelthon puis sâarrĂȘter lĂ .
âš Commentaire de GPT-4o (KPT)
â Points rĂ©ussis (Keep)
- đ RĂ©solution de lâissue de mise Ă jour de FleatherViewer : utiliser
didUpdateWidgetpour rĂ©soudre le problĂšme de rafraĂźchissement de lâĂ©tat du widget Ă©tait excellent. - ⥠Optimisation du filtrage de HomeFeedPage : utiliser Conditional Visibility plutĂŽt que des filtres Query pour optimiser les performances a Ă©tĂ© efficace.
- đ Apprentissage pendant le debugging : tester plusieurs approches, expĂ©rimenter les limites des filtres Query, puis conclure que Conditional Visibility Ă©tait plus adaptĂ© a vraiment du sens.
â Points regrettables (Problem)
- âł Plus de temps que prĂ©vu : il est dommage dâavoir utilisĂ© la majeure partie du temps Ă rĂ©soudre des issues plutĂŽt quâĂ implĂ©menter les fonctionnalitĂ©s prĂ©vues.
- đ Conseil dâissue non formalisĂ© Ă lâavance : le fait de ne pas avoir appliquĂ© un conseil reçu lors dâun ancien mentorat a fait perdre du temps sur le mĂȘme type de problĂšme.
đ Pistes Ă essayer (Try)
- đ Utiliser des notes de rĂ©solution dâissues : noter les issues rĂ©solues pour pouvoir rĂ©agir plus vite quand des problĂšmes similaires apparaissent.
- đ RĂ©ajuster la stratĂ©gie pour les fonctionnalitĂ©s restantes : comme il reste peu de temps, dĂ©finir les prioritĂ©s autour des fonctionnalitĂ©s indispensables et reporter le reste aux amĂ©liorations futures.
- đ Approfondir le fonctionnement interne de FlutterFlow : renforcer la comprĂ©hension du traitement des donnĂ©es et de la gestion dâĂ©tat des widgets dans FlutterFlow pour prĂ©venir ce type de problĂšme.
Conclusion
Aujourdâhui, tu as passĂ© plus de temps que prĂ©vu Ă rĂ©soudre des issues, mais tu en as aussi tirĂ© un apprentissage important. Pour le temps restant, il faudra implĂ©menter en prioritĂ© les fonctionnalitĂ©s vraiment nĂ©cessaires et abandonner les ambitions inutiles. Tiens bon jusquâau bout ! đȘđ„
Laisser un commentaire