[π ] Keymory Dev Log #7: Fixed FleatherViewer Issue, Fixed HomeFeedPage Unexpected Null Value Issue
β¨ GPT Summary γ
I fixed the FleatherViewer update issue and completed issue resolution and performance optimization by improving the HomeFeedPage filtering method. Thanks to that, I learned that using Conditional Visibility instead of Query filters is effective.
π» Development Log
β° Todayβs tasks
- β
(Issue) HomeFeedPage - FeedCardDiary: when changing dates in ListView, only FleatherViewerWidget does not update its value.
- It looks like the Widgetβs initialDeltaJson value is not updated every time the Diary Document changes.
-
Asked o1, and it solved it in one shot.
/// 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 briefly appears and disappears on page load.
- Confirmed that the
date filteringapplied to HomeFeedPageβs ListView was the problem. - Tried turning on Filter On Null Values in the
Backend Queryoption ofListView.- 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 attempt 1 (failed)
- Filter On Null Values: ON
- Filter 1:
created_time,Equal To,getFirstTimeOfTheDay - Filter 2:
created_time,Less Than,getFirstTimeOfNextDay - Order by:
created_time,Decreasing - Could not complete Backend Query setup
- Error message: You canβt order your query by a field used in a filter using
==orin.
- Error message: You canβt order your query by a field used in a filter using
- Backend Query - Query Collection attempt 2 (failed)
- 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 - Backend Query setup can be completed
-
When entering debugging mode, the error below appears and the page is not created.
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 attempt 3 (failed)
- Filter On Null Values: ON
- Filter 1:
created_time,Greater Than,getLastTimeOfPrevDay - Filter 2:
created_time,Less Than,getFirstTimeOfNextDay - Order by:
created_time,Decreasing - Backend Query setup can be completed
-
When entering debugging mode, the error below appears and the page is not created.
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 attempt 4 (failed)
- Filter On Null Values: OFF
- Filter 1:
created_time,Greater Than,getLastTimeOfPrevDay - Filter 2:
created_time,Less Than,getFirstTimeOfNextDay - Order by:
created_time,Decreasing - Backend Query setup can be completed
-
When entering debugging mode, the error below briefly appears and disappears.
Unexpected Null value. The relevant error-causing widget was: HomeFeedWidget
- (Question to o1) Why does Unexpected Null Value briefly appear?
- There is a high chance that FlutterFlow (or its internal code) is returning null from getLastTimeOfPrevDay() or getFirstTimeOfNextDay() at the initial page loading moment. (For example, maybe the date has not been initialized yetβ¦)
- If Filter On Null Values is enabled, it internally adds a separate condition like != null, and that can collide when null enters during loading.
- So the βbrief null error -> replaced with actual value -> disappears after loading finishesβ phenomenon happens.
- Backend Query - Query Collection attempt 5 (success!)
- Filter On Null Values: OFF
- Order by:
created_time,Decreasing - Component Widget Conditional Visibility settings
- Filter 1:
created_time,Greater Than,getLastTimeOfPrevDay - Filter 2:
created_time,Less Than,getFirstTimeOfNextDay
- Filter 1:
- As a bonus, ListView loading lag (Latency) disappeared too. It seems like giving the Query two filters and an Order at the same time took a lot of time.
- π‘ What I learned
- When using Backend Query, it is better to exclude filters as much as possible and control things with Conditional Visibility.
- This was something I asked the mentor about early on and received an answer for, but I think I only understood it roughly in my head and moved on, so I eventually forgot. After suffering through it directly, I finally understand it clearly.
- Confirmed that the
- β
(Issue) DiaryPage: date is always saved as today
- Created DiaryPage - dateFocused parameter
- Passed HomeFeedPageβs dateToShow value as the dateFocused parameter.
π― Summary of what I did
FleatherViewer update issue resolved
- Used didUpdateWidget so FleatherViewer updates normally whenever the Diary Document changes. HomeFeedPage filter optimization
Used Conditional Visibility instead of Backend Query filtering to improve performance.
- Improved loading speed by minimizing Query filtering.
DiaryPage date saving error fixed
- Improved it so the selected date is reflected when writing a new diary by passing the dateFocused value from HomeFeedPage to DiaryPage.
π― Future tasks
Click to see details
- β (Issue) DiaryPage: use markdown viewer (prevent overflow: Container Height)
- β (Issue) HomeFeedPage - FeedCardDiary: apply AI Comment character image properly
- β DiaryPage - AI Comment: when saving, also save the Ref of the character who wrote the comment to Diary.
- β HomeFeedPage - FeedCardDiary - AI Image: load Character Doc with Backend Query and specify Image Path.
-
β DiaryPage: change face expression Emoji according to Mood Slider value
- β Chat Page - Create New Chat: apply system prompt
- βΆοΈ OpenAI API Call implementation: createChatCompletion
- Input: System Prompt (Chat)
- Output: New Chat Message by AI ($.choices[0].message.content)
- Additional Actions: Create New Chat, Create New Message
- βΆοΈ OpenAI API Call implementation: createChatCompletion
- β DiaryPage - Create New Chat by Diary: create a New Chat based on diary content
- β OpenAI API Call implementation: createDiaryComment
- Input: Diary Content, System Prompt (AI Comment)
- Output: AI Comment ($.choices[0].message.content)
- β OpenAI API Call implementation: createDiarySummary
- Input: Diary Content, AI Comment, System Prompt (Diary Summary)
- Output: Diary Summary ($.choices[0].message.content)
- β OpenAI API Call implementation: 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
- β OpenAI API Call implementation: createDiaryComment
- β ChatPage - Create New Diary: create a New Diary based on conversation content
- β OpenAI API Call implementation: createChatSummary
- Input: Chat Content, System Prompt (Diary From Chat)
- Output: Chat Summary
- β OpenAI API Call implementation: createChatSummary
- β ChatPage - Create New Diary: create a New Diary based on conversation content
- β OpenAI API Call implementation: createDiaryFromChat
- Input: Chat Summary, System Prompt (Diary From Chat)
- Output: New Diary (Title, Content, Mood score)
- β OpenAI API Call implementation: createDiaryFromChat
-
β ChatPage: Go to Linked Diary
- β HomeFeedPage - import and apply flutter_slidable:4.0.0
-
β HomeFeedPage: on left/right slide from FeedCardDiary, chat/edit/delete
- β ChatPage: align user conversation output to the right
-
β Chat/Diary: GPT Streaming API
- β ChatPage - implement AI first message (Alarm/Notification)
- The core of the chat system prompt is proactivity.
- To make it more realistic, it might be good to pass create_date of diary/chat too, so the AI can mention dates like βyesterday.β
- Alarm implementation reference
- The core of the chat system prompt is proactivity.
- β DiaryPage: add detailed emotion keyword Choice Chips and set DB integration
- β DiaryPage - AI Comment: change inputs such as Choice chips and mood slider to fit the
AI Comment System Prompt.- β **previous
diaryor entireconversation history(patchy technical debt) - β basic user information: name, gender, MBTI, β¦
- β detailed emotion keywords: happy, sad, β¦
- β character settings: Somi, Sena, Minhyuk
- β emotion score: 1 to 100
- β response format: Healing, Suggestion, Informative
- β response length: short, normal, detailed
- is New Chat
- Since this Chatβs messages are being created for the first time, set
is_initial = trueon the first message document and shove in all system prompts.- is_initial = false
- Limit: if I put the system prompt into the very first message document, it is hard to modify in the middle of a conversation, but possible. If there is an is_initial = true document and it was modified, I can delete that document and put it back in. I do not know how, but still.
- Since this Chatβs messages are being created for the first time, set
- β **previous
- β DiaryPage - AI Comment: complete CRUD
- β remove tmp_ai_comment field and use doc_ref
- β DiaryPage - AI Comment: character settings
- β remove tmp_ai_comment_by field and use doc_ref
- β output image using profile_image field value
-
β DiaryPage - Drawer - ChatHistoryListTile: order by updated_time
-
β DiaryPage - import and apply Interactive Slider
-
β HomeFeedPage: implement Search Diary feature
- β CalendarPage (top) - Mood Calendar
- β Check the number of posts written by date
- β Move to the selected date when clicking a date
- β CalendarPage (bottom) - Mood stats
- β Output statistics for the focused month
- β Output AI comment on the displayed statistics
- β Output statistics for the focused month
-
β AuthPage: implement Google Login
- β HomeFeedPage - Bottom Sheet (
+Button): make it possible to choose one of several options- New diary: Go to DiaryPage
- Emotion record: Go to MoodPage
- β MoodPage (popup): Mood setting slider CRUD
- Create
- Read
- Update
- Delete
- β HomeFeedPage - ListView - show FeedCardMood
-
β HomeFeedPage - ListView: sort FeedCardDiary, FeedCardMood, FeedCardChat components chronologically (using Cloud Function)
- β Extract and install the final presentation APK by
Wed 2025.2.5
π Diary
There is not much time left now, so I wanted to implement more⦠but I spent the whole workday resolving issues.
I should just drop the greed. This project is not something that will flash briefly for the AIFFELTHON and then end anyway.
β¨ GPT-4o Comment (KPT)
β What Went Well (Keep)
- π Resolved FleatherViewer update issue: It was excellent that you solved the widget state update problem by using
didUpdateWidget. - β‘ Optimized HomeFeedPage filtering: Using Conditional Visibility instead of Query filters was an effective performance optimization.
- π Learning through debugging: It was meaningful that you tried several approaches, experienced the limits of Query filters, and concluded that Conditional Visibility was more appropriate.
β What Was Missing (Problem)
- β³ Took more time than expected: It is unfortunate that most of the time went into issue resolution rather than the features you originally planned to implement.
- π Did not organize earlier issue advice: There was a moment where time was spent again because advice from previous mentoring had not been put into practice.
π What to Try (Try)
- π Use issue-resolution notes: Build a habit of recording resolved issues so similar problems can be solved quickly later.
- π Adjust the remaining feature strategy: Since there is not much time left, think about prioritizing only the necessary features and pushing the rest to later improvements.
- π Study FlutterFlow internals more: Increase your understanding of FlutterFlow data handling and widget state management to prevent similar problems in advance.
Conclusion
Today took more time than expected for issue resolution, but you gained important learning from it. For the remaining period, you need a strategy of implementing only the necessary features first and letting go of unnecessary greed. Keep going until the end! πͺπ₯
Leave a comment