[๐ ] Log Pengembangan Keymory #7: Perbaikan Issue FleatherViewer, Perbaikan Issue Unexpected Null Value di HomeFeedPage
โจ Ringkasan GPT ใ
Masalah update FleatherViewer diperbaiki, lalu penyelesaian issue dan optimasi performa diselesaikan dengan memperbaiki metode filtering HomeFeedPage. Dari situ terbukti bahwa memakai Conditional Visibility alih-alih Query filter ternyata efektif.
๐ป Log Pengembangan
โฐ Yang Dikerjakan Hari Ini
- โ
(Issue) HomeFeedPage - FeedCardDiary: saat tanggal diubah di ListView, hanya FleatherViewerWidget yang nilainya tidak berubah.
- Sepertinya nilai initialDeltaJson pada Widget tidak ikut diperbarui setiap kali Diary Document berubah.
-
Begitu bertanya ke o1, langsung selesai dalam sekali jawab.
/// didUpdateWidget: /// - Saat hanya parameter yang berubah dalam widget tree yang sama, Flutter memakai ulang State yang sudah ada. /// - Pada titik ini, properti widget baru bisa dibandingkan dengan properti widget lama dan logic yang diperlukan bisa dijalankan. @override void didUpdateWidget(covariant FleatherViewerWidget oldWidget) { super.didUpdateWidget(oldWidget); // 1) Jika JSON lama dan JSON baru berbeda if (oldWidget.initialDeltaJson != widget.initialDeltaJson) { // 2) Buat ulang FleatherController _controller?.dispose(); _controller = _createControllerFromDeltaJson(widget.initialDeltaJson); // 3) Refresh UI setState(() {}); } } /// Helper function untuk membuat FleatherController dari string Delta JSON FleatherController _createControllerFromDeltaJson(String jsonString) { ParchmentDocument doc; try { final decoded = jsonDecode(jsonString); doc = ParchmentDocument.fromJson(decoded); } catch (e) { // Jika restore gagal, tangani sebagai plain text doc = ParchmentDocument.fromDelta( Delta()..insert(_ensureEndsWithNewline(jsonString)), ); } return FleatherController(document: doc); }
- โ
(Issue) HomeFeedPage: Unexpected Null Value sempat muncul lalu hilang saat page load.
- Terkonfirmasi bahwa
date filteringyang dipasang pada ListView di HomeFeedPage adalah sumber masalah. - Mencoba menyalakan Filter On Null Values di opsi
Backend QuerymilikListView.- 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 percobaan 1 (gagal)
- Filter On Null Values: ON
- Filter 1:
created_time,Equal To,getFirstTimeOfTheDay - Filter 2:
created_time,Less Than,getFirstTimeOfNextDay - Order by:
created_time,Decreasing - Backend Query tidak bisa diselesaikan
- Pesan error: You canโt order your query by a field used in a filter using
==orin.
- Pesan error: You canโt order your query by a field used in a filter using
- Backend Query - Query Collection percobaan 2 (gagal)
- 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 bisa diselesaikan
-
Saat masuk debugging mode, error di bawah muncul dan halaman tidak dibuat.
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 percobaan 3 (gagal)
- 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 bisa diselesaikan
-
Saat masuk debugging mode, error di bawah muncul dan halaman tidak dibuat.
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 percobaan 4 (gagal)
- 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 bisa diselesaikan
-
Saat masuk debugging mode, error di bawah sempat muncul lalu hilang.
Unexpected Null value. The relevant error-causing widget was: HomeFeedWidget
- (Bertanya ke o1) Mengapa Unexpected Null Value sempat muncul?
- Kemungkinan besar FlutterFlow (atau kode internalnya) mengembalikan null dari getLastTimeOfPrevDay() atau getFirstTimeOfNextDay() pada momen loading awal halaman. (Misalnya date belum terinisialisasiโฆ)
- Jika Filter On Null Values dinyalakan, kondisi tambahan seperti != null dimasukkan secara internal, dan itu bisa bertabrakan ketika nilai null masuk saat loading.
- Jadi fenomenanya menjadi โerror null muncul sebentar -> diganti dengan nilai asli -> hilang setelah loading selesai.โ
- Backend Query - Query Collection percobaan 5 (berhasil!)
- Filter On Null Values: OFF
- Order by:
created_time,Decreasing - Pengaturan Component Widget Conditional Visibility
- Filter 1:
created_time,Greater Than,getLastTimeOfPrevDay - Filter 2:
created_time,Less Than,getFirstTimeOfNextDay
- Filter 1:
- Bonusnya, lag loading ListView (Latency) juga hilang. Sepertinya memberi Query dua filter dan satu Order sekaligus memang memakan banyak waktu.
- ๐ก Yang dipelajari
- Saat memakai Backend Query, sebaiknya filter sebisa mungkin dikurangi dan kontrol dilakukan dengan Conditional Visibility.
- Ini sebenarnya pernah ditanyakan ke mentor di awal dan sudah mendapat jawaban, tetapi rasanya dulu hanya paham kira-kira di kepala lalu lewat begitu saja, jadi akhirnya lupa. Setelah merasakan sendiri susahnya, baru sekarang benar-benar paham.
- Terkonfirmasi bahwa
- โ
(Issue) DiaryPage: tanggal selalu tersimpan sebagai hari ini
- Membuat parameter DiaryPage - dateFocused
- Mengirim nilai dateToShow dari HomeFeedPage sebagai parameter dateFocused.
๐ฏ Ringkasan yang Sudah Dikerjakan
Issue update FleatherViewer terselesaikan
- Menggunakan didUpdateWidget agar FleatherViewer diperbarui secara normal setiap kali Diary Document berubah. Optimasi filter HomeFeedPage
Menggunakan Conditional Visibility alih-alih filtering Backend Query untuk meningkatkan performa.
- Kecepatan loading meningkat dengan meminimalkan Query filtering.
Error penyimpanan tanggal DiaryPage diperbaiki
- Memperbaiki agar tanggal yang dipilih ikut tercermin saat menulis diary baru, dengan mengirim nilai dateFocused dari HomeFeedPage ke DiaryPage.
๐ฏ Rencana Berikutnya
Klik untuk melihat detail
- โ (Issue) DiaryPage: gunakan markdown viewer (mencegah overflow: Container Height)
- โ (Issue) HomeFeedPage - FeedCardDiary: terapkan gambar karakter AI Comment dengan benar
- โ DiaryPage - AI Comment: saat Save, simpan juga Ref karakter yang menulis komentar ke Diary.
- โ HomeFeedPage - FeedCardDiary - AI Image: muat Character Doc dengan Backend Query lalu tentukan Image Path.
-
โ DiaryPage: ubah Emoji ekspresi wajah sesuai nilai Mood Slider
- โ Chat Page - Create New Chat: terapkan system prompt
- โถ๏ธ Implementasi 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
- โถ๏ธ Implementasi OpenAI API Call: createChatCompletion
- โ DiaryPage - Create New Chat by Diary: membuat New Chat berdasarkan isi diary
- โ Implementasi OpenAI API Call: createDiaryComment
- Input: Diary Content, System Prompt (AI Comment)
- Output: AI Comment ($.choices[0].message.content)
- โ Implementasi OpenAI API Call: createDiarySummary
- Input: Diary Content, AI Comment, System Prompt (Diary Summary)
- Output: Diary Summary ($.choices[0].message.content)
- โ Implementasi 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
- โ Implementasi OpenAI API Call: createDiaryComment
- โ ChatPage - Create New Diary: membuat New Diary berdasarkan isi percakapan
- โ Implementasi OpenAI API Call: createChatSummary
- Input: Chat Content, System Prompt (Diary From Chat)
- Output: Chat Summary
- โ Implementasi OpenAI API Call: createChatSummary
- โ ChatPage - Create New Diary: membuat New Diary berdasarkan isi percakapan
- โ Implementasi OpenAI API Call: createDiaryFromChat
- Input: Chat Summary, System Prompt (Diary From Chat)
- Output: New Diary (Title, Content, Mood score)
- โ Implementasi OpenAI API Call: createDiaryFromChat
-
โ ChatPage: Go to Linked Diary
- โ HomeFeedPage - import dan terapkan flutter_slidable:4.0.0
-
โ HomeFeedPage: saat slide kiri/kanan dari FeedCardDiary, tampilkan chat/edit/delete
- โ ChatPage: ratakan output percakapan user ke kanan
-
โ Chat/Diary: GPT Streaming API
- โ ChatPage - implementasi pesan pertama dari AI (Alarm/Notification)
- Inti dari chat system prompt adalah sifat proaktif.
- Agar terasa lebih nyata, mungkin bagus juga mengirim create_date of diary/chat, supaya AI bisa menyebut tanggal seperti โkemarin.โ
- Referensi implementasi Alarm
- Inti dari chat system prompt adalah sifat proaktif.
- โ DiaryPage: tambahkan Choice Chips untuk kata kunci emosi detail dan atur integrasi DB
- โ DiaryPage - AI Comment: sesuaikan input seperti Choice chips dan mood slider agar cocok dengan
AI Comment System Prompt.- โ **
diarysebelumnya atau seluruhconversation history(technical debt tambalan) - โ informasi dasar pengguna: nama, gender, MBTI, โฆ
- โ kata kunci emosi detail: senang, sedih, โฆ
- โ pengaturan karakter: Somi, Sena, Minhyuk
- โ skor emosi: 1~100 poin
- โ format jawaban: Healing, Suggestion, Informative
- โ panjang jawaban: pendek, normal, detail
- is New Chat
- Karena messages untuk Chat ini dibuat pertama kali, berikan nilai
is_initial = truepada message document pertama dan masukkan semua system prompt.- is_initial = false
- Batasan: kalau system prompt dimasukkan ke message document paling awal, memang sulit diubah di tengah percakapan, tetapi masih mungkin. Kalau ada document dengan is_initial = true dan isinya diubah, document itu bisa dihapus lalu dimasukkan lagi. Caranya belum tahu, tapi bisa saja.
- Karena messages untuk Chat ini dibuat pertama kali, berikan nilai
- โ **
- โ DiaryPage - AI Comment: selesaikan CRUD
- โ hapus field tmp_ai_comment dan gunakan doc_ref
- โ DiaryPage - AI Comment: pengaturan karakter
- โ hapus field tmp_ai_comment_by dan gunakan doc_ref
- โ tampilkan gambar memakai nilai field profile_image
-
โ DiaryPage - Drawer - ChatHistoryListTile: order by updated_time
-
โ DiaryPage - import dan terapkan Interactive Slider
-
โ HomeFeedPage: implementasi fitur Search Diary
- โ CalendarPage (atas) - Mood Calendar
- โ Bisa mengecek jumlah post yang ditulis per tanggal
- โ Saat tanggal diklik, pindah ke tanggal tersebut
- โ CalendarPage (bawah) - Mood stats
- โ Tampilkan statistik terkait bulan yang sedang difokuskan
- โ Tampilkan komentar AI terhadap statistik yang muncul
- โ Tampilkan statistik terkait bulan yang sedang difokuskan
-
โ AuthPage: implementasi Google Login
- โ HomeFeedPage - Bottom Sheet (
+Button): buat agar bisa memilih 1 dari beberapa opsi- Diary baru: Go to DiaryPage
- Catatan emosi: Go to MoodPage
- โ MoodPage (popup): CRUD slider pengaturan Mood
- Create
- Read
- Update
- Delete
- โ HomeFeedPage - ListView - tampilkan FeedCardMood
-
โ HomeFeedPage - ListView: urutkan komponen FeedCardDiary, FeedCardMood, FeedCardChat secara kronologis (menggunakan Cloud Function)
- โ Ekstrak dan instal APK versi final untuk presentasi sampai
Rab 2025.2.5
Tinggalkan komentar