Compare commits

..

6 Commits

Author SHA1 Message Date
cd035198f5 Refinement dan Dokumentasi 2025-12-31 13:53:35 +07:00
ca6ff4410a Dokumentasi 2025-12-25 23:45:24 +07:00
3b9b2e030f Dokumentasi CHANGELOG.md 2025-12-25 23:43:54 +07:00
08dc54116e Dokumentasi README.md 2025-12-25 23:39:40 +07:00
171d808dad Penyesuaian Smart Search 2025-12-25 22:52:22 +07:00
4caea5c83e Penyesuaian fitur Filter/Pencarian 2025-12-25 20:15:38 +07:00
10 changed files with 964 additions and 471 deletions

361
CHANGELOG.md Normal file
View File

@ -0,0 +1,361 @@
# **AI Notes Changelog**
## **Tim Pengembang**
* Dendi Yogia Pratama
* Raihan Ariq Muzakki
* Fazri Abdurrahman
# **Version 1.0.0 Initial Release**
## **Sprint 1: Struktur Dasar Aplikasi**
### **Struktur & Navigation**
* **Setup navigation system** - Implementasi routing antar halaman (Beranda, Arsip, Sampah)
* **Menu Drawer** - Navigation drawer dengan list menu (Beranda, Berbintang, Arsip, Sampah)
* **Bottom Navigation** - Home & AI Helper tabs dengan icon navigation
* **Top App Bar** - Menu hamburger dan search icon dengan Material3 styling
* **Screen Architecture** - Pembuatan screen Arsip, Sampah, Berbintang, AI Helper
### **Theme & Styling**
* **Material3 Dark Theme** - Setup color scheme dengan dark mode default
* **Color System** - Primary/Secondary colors dengan gradient presets (8 kombinasi warna)
* **Consistent Design** - Rounded corners (12dp, 16dp, 20dp), shadow, elevation
* **Smooth Animations** - Drawer slide, FAB scale, card transitions dengan spring animations
* **Typography System** - Optimasi font sizes dan line heights untuk readability
### **Category Management**
* **Category Model** - Data class dengan gradient colors dan timestamp
* **Category Dialog** - Form tambah/edit kategori dengan nama + gradient picker
* **Category Card** - Design dengan icon folder, nama, jumlah catatan, gradient background
* **Staggered Grid Layout** - 2 kolom responsive dengan LazyVerticalStaggeredGrid
* **Category Actions** - Menu dropdown (⋮) untuk edit dan delete kategori
* **Empty State** - Pesan "Buat kategori pertama Anda" dengan icon
### **Note Management**
* **Note Model** - Data class dengan title, content, timestamp, isPinned, isArchived
* **Note Dialog** - Form dengan judul, deskripsi, simpan, batal, hapus
* **Note Card** - Preview dengan judul, deskripsi, timestamp, pin icon
* **Full-screen Editor** - Editable note view dengan auto-save dan actions
* **Pin Feature** - Toggle pin/unpin untuk catatan penting dengan sorting priority
* **Archive & Delete** - Actions untuk arsip dan soft delete notes
* **Search Functionality** - Real-time search berdasarkan judul dan isi (case-insensitive)
* **Smart Sorting** - Berdasarkan pin status dan timestamp (descending)
### **AI Assistant**
* **Gemini AI Integration** - Setup Google Generative AI SDK dengan gemini-2.5-flash
* **AI Helper Screen** - Layout chat interface dengan header dan statistics
* **Category Context Selector** - Dropdown untuk filter konteks AI berdasarkan kategori
* **Statistics Display** - Total catatan, pinned notes, jumlah kategori
* **Chat Interface** - User & AI bubble dengan different styling dan timestamp
* **Prompt Engineering** - Context builder dengan data catatan user (max 10 terbaru)
* **Suggestion Chips** - Quick question templates untuk user guidance
* **Copy to Clipboard** - Copy jawaban AI dengan confirmation feedback
* **Loading & Error States** - Circular progress indicator dan error messages
* **API Configuration** - Temperature 0.8, topK 40, topP 0.95, maxOutputTokens 4096
* **Auto-scroll Chat** - Scroll ke bottom otomatis dengan LaunchedEffect
### **Data Persistence**
* **DataStore Implementation** - Preferences DataStore untuk local storage
* **DataStoreManager Class** - Centralized dengan categoriesFlow & notesFlow
* **Auto-save dengan Debounce** - 500ms delay untuk optimize I/O operations
* **Flow-based Loading** - Reactive data loading dengan Flow collection
* **Error Handling** - Try-catch untuk semua I/O operations
* **Serializable Models** - JSON serialization dengan extension functions
### **UI/UX Enhancements**
* **Visual Feedback** - Click ripples, copy confirmation, loading states
* **Empty States** - Icon + descriptive messages untuk setiap screen
* **Confirmation Dialogs** - AlertDialog untuk arsip, hapus, delete actions
* **Search Empty State** - "Tidak ada hasil" message saat search kosong
* **Custom TextField** - Styled text input dengan consistent design
* **Date Formatter Utility** - Format timestamp ke readable Indonesian format
---
## **Sprint 2: Project Restructuring & Advanced Features**
### **Project Architecture**
* **Clean Architecture Migration** - Dari 3 file monolith ke modular structure
* **Data Layer Separation** - Models ke `data/model/` (Category, Note, ChatMessage)
* **Local Storage Layer** - DataStoreManager ke `data/local/` dengan PreferencesKeys
* **Component Extraction** - Screen components ke folder terpisah (main, starred, archive, trash)
* **Utilities Creation** - Constants.kt, DateFormatter.kt, Extensions.kt untuk reusability
* **Import Optimization** - Update semua import sesuai package structure baru
### **Search & Filter**
* **Beranda Search** - Real-time search kategori berdasarkan nama
* **Category Notes Search** - Search catatan di dalam kategori (judul & isi)
* **Search Filtering** - Live filtering saat user mengetik
* **Search Empty State** - Descriptive message dengan alternative suggestions
### **Category Features**
* **Edit Category** - Dialog untuk ubah nama dan gradient dengan pre-filled form
* **Delete Category** - Menu dropdown dengan confirmation dialog
* **Category Actions Menu** - Icon ⋮ untuk access edit & delete options
* **Gradient Preview** - Visual preview saat edit kategori
### **Trash System**
* **Soft Delete Implementation** - isDeleted flag untuk Category dan Note
* **Trash Screen** - Tampilkan kategori & notes yang terhapus
* **TrashCategoryCard Component** - Card khusus dengan restore & delete permanent actions
* **Restore Feature** - Pulihkan kategori beserta semua notes di dalamnya
* **Permanent Delete** - Hapus kategori dan notes secara irreversible dengan confirmation
* **Counter Display** - Jumlah items terhapus di trash
* **Global Filter** - Filter `!isDeleted` di semua screen untuk hide deleted items
### **Bug Fixes & Optimization**
* **Runtime Error Debugging** - Fix NotImplementedError & FATAL EXCEPTION issues
* **Google Play Services Handling** - Error handling untuk GMS dependencies
* **Component Migration** - Update deprecated Divider ke HorizontalDivider
* **Gradle Optimization** - Cleanup unnecessary dependencies
* **State Management** - Proper state hoisting dan recomposition optimization
### **Documentation**
* **Migration Guide** - Step-by-step panduan untuk project restructuring
* **Debugging Guide** - Troubleshooting common issues dan error handling
---
# **Version 1.1.0 AI Helper Screen Enhancement & UI Refinement**
## **Sprint 3: AI Helper Screen Features & Modern UI Redesign**
### **AI Assistant Enhancements**
* **History Chat AI dengan Drawer Menu** - Riwayat percakapan AI tersimpan permanen, dikelompokkan per kategori
* **Chat History Management** - Load previous chat, delete history, start new chat dengan auto-save
* **Markdown Parser untuk AI Response** - Support bold, italic, code blocks, headers, lists, quotes, links
* **Improved Error Handling** - User-friendly error messages untuk quota, network, API issues
* **Gemini Model Update** - Switch ke gemini-1.5-flash untuk stabilitas optimal
### **Theme System**
* **Dark/Light Theme Toggle** - Dual theme dengan persistent storage di drawer menu
* **Reactive Color System** - Dynamic color switching untuk semua components
* **Complete Color Palette** - DarkColors dan LightColors objects untuk consistency
### **UI/UX Modernization**
* **Floating Design System** - TopBar dan BottomBar dengan floating style, rounded corners, shadow
* **Consistent Component Style** - Unified design language dengan CircleShape buttons
* **Optimized Layouts** - Better spacing dan vertical action stack untuk maximize content space
### **Data & Navigation**
* **Note Edit & Delete from Card** - Menu dropdown pada NoteCard untuk quick actions
* **Race Condition Fix** - Guard flags dan lifecycle-aware auto-save untuk data persistence
* **Simplified Navigation** - Unified drawer menu, remove redundant back buttons
* **Extended DataStore** - Support chat history, theme preference, improved error handling
---
## **Sprint 4: Rich Text Editor Core Features & AI Chat History UI/UX Improvements**
### **Rich Text Editing**
* **Hybrid Rich Text Editor (WYSIWYG)** Edit teks dengan format langsung tanpa syntax markdown terlihat
* **Bold, Italic, Underline** Formatting bersifat toggle dan tetap aktif sampai dimatikan
* **Heading & Bullet List** Support heading (H1H3) dan bullet list tanpa konflik antar format
* **Undo / Redo** Riwayat perubahan editor terintegrasi
### **Floating Toolbar**
* **Draggable Mini Toolbar** Toolbar dapat dipindahkan bebas oleh user
* **Active State Indicator** Icon toolbar menandakan format aktif (Bold, Italic, dll)
* **Minimal UI** Toolbar kecil agar tidak mengganggu area pengetikan
* **Keyboard-Aware Positioning** Posisi toolbar menyesuaikan saat keyboard muncul
### **Cursor & Editing Stability**
* **Stable Cursor & Selection** Insertion point dan selection handle akurat saat mengetik
* **IME & Keyboard Safe** Editor tetap stabil saat keyboard resize / rotate
* **Auto Bring-Into-View** Cursor selalu terlihat saat mengetik di area bawah layar
### **Data Persistence**
* **Format Tersimpan Permanen** Rich text tidak hilang setelah save atau reopen
* **Auto Save Lifecycle-Aware** Catatan otomatis tersimpan saat app background / keluar
* **Markdown Compatibility** Support import & export markdown secara aman
### **Chat History Enhancements**
* **Compact Modern Design** - Item lebih kecil dengan horizontal layout dan 30 karakter limit
* **Search & Filter System** - Real-time search dengan category dropdown filtering
* **Date Grouping** - Auto-group: "Hari Ini", "Kemarin", "Minggu Ini", "Lebih Lama"
* **Edit Title with Markdown** - Custom title support: **bold**, *italic*, `code`, ~~strike~~
* **Context Menu** - Three-dot menu (⋮) untuk Edit dan Delete actions
* **Live Preview** - Real-time markdown preview saat edit title
### **Technical Updates**
* **ChatHistory Model** - Added `customTitle: String?` field
* **DataStore Integration** - New `updateChatHistoryTitle()` function
* **Smart Truncation** - Auto-truncate preview ke 30 char dengan `toSafeChatPreview()`
* **Markdown Parser** - Inline markdown rendering untuk titles dengan proper styling
* **Character Counter** - Visual feedback dengan color indicator (Gray → Primary → Red)
### **User Experience**
* **Better Empty States** - Informative UI untuk empty search dan no history
* **Smooth Animations** - Slide transitions untuk dialogs
* **Input Validation** - Max 30 char dengan real-time blocking
* **Focus Management** - Seamless editing experience dengan auto-focus
> Rich Text Editor butuh dikembangkan lagi lebih advance
---
## **Sprint 5: AI Assistant Enhancements & Smart Organization Features**
### **Copy Plain Text Feature**
* **Dual Copy Options** Dropdown menu dengan 2 pilihan: "Copy dengan Format" dan "Copy Teks Asli"
* **Smart Markdown Stripper** Utility untuk remove bold, italic, code, headers, lists, links dari text
* **Visual Feedback** Animated checkmark indicator dengan auto-hide setelah 2 detik
* **Format Preservation** Copy dengan format maintain semua markdown syntax
* **Clean Output** Plain text copy menghasilkan text bersih tanpa formatting apapun
### **Document Upload & AI Summary**
* **Multi-Format Support** Upload PDF, TXT, dan DOCX files dengan file picker
* **Smart PDF Parser** PDFBox Android integration untuk extract text dari PDF documents
* **Lightweight DOCX Parser** Custom XML-based parser tanpa Apache POI dependency
* **Auto-Summary Generation** AI auto-generate ringkasan maksimal 300 kata saat file di-upload
* **File Validation** Maximum 10MB dengan clear error messaging untuk setiap kasus
* **Loading Integration** Loading indicator "Membuat ringkasan..." terintegrasi di chat area
* **Chat Format** Upload result format: "📄 Upload file: filename" dengan summary response
### **Category Pin System**
* **Pin/Unpin Toggle** Quick access untuk kategori favorit dengan dropdown menu
* **Visual Pin Indicator** 📌 icon dengan scale dan fade animations
* **Smart Sorting Logic** Priority sorting: pinned categories (DESC) → timestamp (DESC)
* **Persistent Storage** Pin status tersimpan di DataStore dengan backward compatibility
* **Multiple Pins Support** User dapat pin multiple categories dengan proper grouping
* **Context Menu Integration** Pin option di dropdown: "Pin Kategori" / "Lepas Pin"
### **Technical Implementation**
* **MarkdownStripper.kt** Utility class dengan regex-based markdown removal
* **FileParser.kt** Centralized file parsing untuk PDF, TXT, DOCX
* **Category Model Update** Added `isPinned: Boolean` field dengan serialization support
* **FileParseResult** Sealed class untuk type-safe file parsing results
* **PDFBoxResourceLoader** Proper initialization dalam Application.onCreate()
* **State Management** Combined loading states untuk chat dan file upload
### **User Experience**
* **Smooth Transitions** Loading states dengan color differentiation (Primary vs Secondary)
* **Error Handling** Comprehensive error messages untuk berbagai failure scenarios
* **Auto-Scroll** Scroll to bottom saat upload file untuk show loading indicator
* **Disabled States** Upload button hidden saat processing untuk prevent duplicate actions
* **Persistence** Pin status dan file summary survive app restart
# **Sprint 6: Functional Testing & Documentation**
## **Testing Implementation**
### **Test Methodology Design**
* **Black-Box Functional Testing** Pengujian dari perspektif end-user dengan verifikasi Expected vs Actual Result
* **Automated Unit Testing** 59 automated tests untuk validasi business logic internal
* **Test Case Design** 6 comprehensive test cases (TC-01 hingga TC-06)
* **Evidence Collection** Screenshot documentation untuk setiap test case
* **Test Report Generation** Structured test summary dengan metrics dan status
### **Test Infrastructure Setup**
* **JUnit 4 Framework** Core testing framework untuk Android unit tests
* **AndroidX Test Library** Android-specific testing utilities dan test runners
* **Kotlin Coroutines Test** Testing library untuk asynchronous code dengan runBlocking
* **Test Isolation** Unique DataStore instances per test untuk prevent data contamination
* **Test Execution** Configure test runner dan gradle tasks untuk automated testing
### **Unit Test Development**
* **DataStoreManagerTest** 8 tests untuk CRUD operations, autosave, dan pin functionality
* **TrashFunctionalityTest** 11 tests untuk soft delete, restore, dan permanent delete
* **SearchFunctionalityTest** 14 tests untuk realtime search dengan berbagai scenarios
* **AIChatFunctionalityTest** 14 tests untuk context building dan chat history management
* **FileUploadFunctionalityTest** 12 tests untuk file parsing dan summary generation
### **Test Coverage Achievement**
* **Total Test Cases** 6 functional test cases dengan screenshot evidence
* **Total Unit Tests** 59 automated tests covering critical business logic
* **Success Rate** 100% pass rate untuk semua tests
* **Execution Time** Average ~2 minutes untuk full test suite
* **Code Coverage** 100% coverage untuk tested components (DataStore, Models, Utilities)
### **Bug Fixes & Test Iterations**
* **Test Isolation Issues** Fixed data contamination dengan unique DataStore per test
* **Async Testing** Resolved suspend function testing dengan proper runBlocking usage
* **Chat History Tests** Fixed unique ID collision dengan improved test data management
* **Error Handling** Added comprehensive error handling untuk file I/O operations
* **Test Stability** Achieved consistent test results dengan proper setup/teardown
---
## **Documentation Development**
### **Technical Documentation**
* **Testing Methodology** 16-section comprehensive document explaining black-box testing approach
* **Architecture Documentation** Package structure, data flow, dan component relationships
* **API Documentation** Gemini API integration, endpoints, dan configuration details
* **Code Comments** Inline documentation untuk complex logic dan business rules
* **Setup Guide** Step-by-step installation dan configuration instructions
### **User Documentation**
* **User Guide** Complete panduan penggunaan dengan 7 user flows dan screenshots
* **Feature Documentation** Detailed explanation untuk setiap fitur utama aplikasi
* **Quick Start Guide** 6-step quick reference untuk new users
* **Troubleshooting Guide** Common issues dan solutions untuk end-users
* **FAQ Section** Frequently asked questions dengan clear answers
### **Project Documentation**
* **README.md** Comprehensive project overview dengan badges, links, dan quick navigation
* **CHANGELOG.md** Detailed version history dengan sprint breakdown dan feature tracking
* **TEST_SUMMARY_REPORT.md** Complete test report dengan metrics, results, dan evidence
* **DEVELOPMENT_PLAN.md** Sprint history, roadmap, dan future development planning
* **Academic Report** 35-page formal documentation untuk course submission
### **Visual Documentation**
* **Wireframe Design** Complete app wireframe dengan all screens dan navigation flows
* **Screenshot Collection** 35+ screenshots documenting every feature dan user flow
* **Mockup Integration** High-fidelity mockups embedded dalam user guide
* **Architecture Diagrams** Visual representation of data layer, presentation layer, dan flow
* **Test Evidence** Screenshot proof untuk setiap test case execution
### **Reference Documentation**
* **Dependencies List** Complete list of libraries dengan version numbers
* **Tech Stack Documentation** Detailed explanation of technology choices
* **API References** Links to official documentation untuk Gemini, Android, Kotlin
* **Academic Citations** Proper citation format untuk research sources (33 references)
* **Version Control** Git workflow documentation dan branching strategy
---
## 🎯 Fitur Utama (Core Features)
1. **Note Management System** ⭐ (PRIMARY)
* Create, Read, Update, Delete catatan
* Organize notes dalam categories
* Pin notes untuk quick access
* Archive & Trash system dengan soft delete
* Full-screen rich text editor dengan WYSIWYG
* Real-time search & filter notes
2. **AI Assistant** 🤖 (PRIMARY)
* Chat dengan AI menggunakan Gemini 2.5 Flash
* Context-aware responses berdasarkan notes user
* Chat history management dengan persistent storage
* Document upload & auto-summary (PDF, TXT, DOCX)
* Markdown support untuk AI responses
* Copy plain text atau formatted text
3. **Category Organization** 📁 (CORE)
* Create & manage categories dengan 8 gradient color presets
* Pin favorite categories untuk quick access
* Smart sorting: pinned categories → timestamp descending
* Category-based note filtering dengan statistics
* Staggered grid layout responsive
4. **Rich Text Editor** ✏️ (CORE)
* WYSIWYG (What You See Is What You Get) editing experience tanpa raw markdown
* Bold, italic, underline, headings (H1-H3), bullet lists
* Floating draggable toolbar dengan active state indicators
* Undo/Redo functionality
* Markdown compatibility untuk import/export
* Auto-save lifecycle-aware
5. **Data Persistence** 💾 (ESSENTIAL)
* Local storage dengan DataStore Preferences
* Auto-save dengan debounce (500ms delay)
* Theme preference storage (dark/light mode)
* Chat history persistence dengan serialization
* Flow-based reactive data loading
* Error handling untuk semua I/O operations

823
README.md
View File

@ -1,306 +1,599 @@
# **AI Notes Changelog** # 📝 NotesAI - AI-Powered Note Taking App 1.1.0
## **Tim Pengembang**
* Dendi Yogia Pratama
* Raihan Ariq Muzakki
* Fazri Abdurrahman
# **Version 1.0.0 Initial Release** ![NotesAI Banner](https://img.shields.io/badge/NotesAI-v1.0-blue?style=for-the-badge)
![Platform](https://img.shields.io/badge/Platform-Android-green?style=for-the-badge&logo=android)
![Kotlin](https://img.shields.io/badge/Kotlin-100%25-purple?style=for-the-badge&logo=kotlin)
![License](https://img.shields.io/badge/License-MIT-yellow?style=for-the-badge)
## **Sprint 1: Struktur Dasar Aplikasi** **Aplikasi pencatatan cerdas berbasis AI untuk Android dengan fitur organisasi terstruktur dan AI Assistant**
### **Struktur & Navigation** [📖 Dokumentasi Lengkap](./docs/Laporan%20Dokumentasi%20Aplikasi%20-%20Kelompok%201.pdf) | [🧪 Test Report](./TEST_SUMMARY_REPORT.md) | [📋 Changelog](./CHANGELOG.md)
* **Setup navigation system** - Implementasi routing antar halaman (Beranda, Arsip, Sampah)
* **Menu Drawer** - Navigation drawer dengan list menu (Beranda, Berbintang, Arsip, Sampah)
* **Bottom Navigation** - Home & AI Helper tabs dengan icon navigation
* **Top App Bar** - Menu hamburger dan search icon dengan Material3 styling
* **Screen Architecture** - Pembuatan screen Arsip, Sampah, Berbintang, AI Helper
### **Theme & Styling**
* **Material3 Dark Theme** - Setup color scheme dengan dark mode default
* **Color System** - Primary/Secondary colors dengan gradient presets (8 kombinasi warna)
* **Consistent Design** - Rounded corners (12dp, 16dp, 20dp), shadow, elevation
* **Smooth Animations** - Drawer slide, FAB scale, card transitions dengan spring animations
* **Typography System** - Optimasi font sizes dan line heights untuk readability
### **Category Management**
* **Category Model** - Data class dengan gradient colors dan timestamp
* **Category Dialog** - Form tambah/edit kategori dengan nama + gradient picker
* **Category Card** - Design dengan icon folder, nama, jumlah catatan, gradient background
* **Staggered Grid Layout** - 2 kolom responsive dengan LazyVerticalStaggeredGrid
* **Category Actions** - Menu dropdown (⋮) untuk edit dan delete kategori
* **Empty State** - Pesan "Buat kategori pertama Anda" dengan icon
### **Note Management**
* **Note Model** - Data class dengan title, content, timestamp, isPinned, isArchived
* **Note Dialog** - Form dengan judul, deskripsi, simpan, batal, hapus
* **Note Card** - Preview dengan judul, deskripsi, timestamp, pin icon
* **Full-screen Editor** - Editable note view dengan auto-save dan actions
* **Pin Feature** - Toggle pin/unpin untuk catatan penting dengan sorting priority
* **Archive & Delete** - Actions untuk arsip dan soft delete notes
* **Search Functionality** - Real-time search berdasarkan judul dan isi (case-insensitive)
* **Smart Sorting** - Berdasarkan pin status dan timestamp (descending)
### **AI Assistant**
* **Gemini AI Integration** - Setup Google Generative AI SDK dengan gemini-2.5-flash
* **AI Helper Screen** - Layout chat interface dengan header dan statistics
* **Category Context Selector** - Dropdown untuk filter konteks AI berdasarkan kategori
* **Statistics Display** - Total catatan, pinned notes, jumlah kategori
* **Chat Interface** - User & AI bubble dengan different styling dan timestamp
* **Prompt Engineering** - Context builder dengan data catatan user (max 10 terbaru)
* **Suggestion Chips** - Quick question templates untuk user guidance
* **Copy to Clipboard** - Copy jawaban AI dengan confirmation feedback
* **Loading & Error States** - Circular progress indicator dan error messages
* **API Configuration** - Temperature 0.8, topK 40, topP 0.95, maxOutputTokens 4096
* **Auto-scroll Chat** - Scroll ke bottom otomatis dengan LaunchedEffect
### **Data Persistence**
* **DataStore Implementation** - Preferences DataStore untuk local storage
* **DataStoreManager Class** - Centralized dengan categoriesFlow & notesFlow
* **Auto-save dengan Debounce** - 500ms delay untuk optimize I/O operations
* **Flow-based Loading** - Reactive data loading dengan Flow collection
* **Error Handling** - Try-catch untuk semua I/O operations
* **Serializable Models** - JSON serialization dengan extension functions
### **UI/UX Enhancements**
* **Visual Feedback** - Click ripples, copy confirmation, loading states
* **Empty States** - Icon + descriptive messages untuk setiap screen
* **Confirmation Dialogs** - AlertDialog untuk arsip, hapus, delete actions
* **Search Empty State** - "Tidak ada hasil" message saat search kosong
* **Custom TextField** - Styled text input dengan consistent design
* **Date Formatter Utility** - Format timestamp ke readable Indonesian format
--- ---
## **Sprint 2: Project Restructuring & Advanced Features** ## 👥 Tim Pengembang
### **Project Architecture** **Kelompok 1 - Kelas F5A5**
* **Clean Architecture Migration** - Dari 3 file monolith ke modular structure
* **Data Layer Separation** - Models ke `data/model/` (Category, Note, ChatMessage)
* **Local Storage Layer** - DataStoreManager ke `data/local/` dengan PreferencesKeys
* **Component Extraction** - Screen components ke folder terpisah (main, starred, archive, trash)
* **Utilities Creation** - Constants.kt, DateFormatter.kt, Extensions.kt untuk reusability
* **Import Optimization** - Update semua import sesuai package structure baru
### **Search & Filter** | Nama | NPM |
* **Beranda Search** - Real-time search kategori berdasarkan nama |------|-----|
* **Category Notes Search** - Search catatan di dalam kategori (judul & isi) | Dendi Yogia Pratama | 202310715051 |
* **Search Filtering** - Live filtering saat user mengetik | Raihan Ariq Muzakki | 202310715297 |
* **Search Empty State** - Descriptive message dengan alternative suggestions | Fazri Abdurahman | 202310715082 |
### **Category Features** **Dosen Pengampu:** Arif Rifai Dwiyanto, ST., MTI
* **Edit Category** - Dialog untuk ubah nama dan gradient dengan pre-filled form **Mata Kuliah:** Pemrograman Perangkat Bergerak
* **Delete Category** - Menu dropdown dengan confirmation dialog **Institusi:** Universitas Bhayangkara Jakarta Raya
* **Category Actions Menu** - Icon ⋮ untuk access edit & delete options
* **Gradient Preview** - Visual preview saat edit kategori
### **Trash System**
* **Soft Delete Implementation** - isDeleted flag untuk Category dan Note
* **Trash Screen** - Tampilkan kategori & notes yang terhapus
* **TrashCategoryCard Component** - Card khusus dengan restore & delete permanent actions
* **Restore Feature** - Pulihkan kategori beserta semua notes di dalamnya
* **Permanent Delete** - Hapus kategori dan notes secara irreversible dengan confirmation
* **Counter Display** - Jumlah items terhapus di trash
* **Global Filter** - Filter `!isDeleted` di semua screen untuk hide deleted items
### **Bug Fixes & Optimization**
* **Runtime Error Debugging** - Fix NotImplementedError & FATAL EXCEPTION issues
* **Google Play Services Handling** - Error handling untuk GMS dependencies
* **Component Migration** - Update deprecated Divider ke HorizontalDivider
* **Gradle Optimization** - Cleanup unnecessary dependencies
* **State Management** - Proper state hoisting dan recomposition optimization
### **Documentation**
* **Migration Guide** - Step-by-step panduan untuk project restructuring
* **Debugging Guide** - Troubleshooting common issues dan error handling
--- ---
# **Version 1.1.0 AI Helper Screen Enhancement & UI Refinement** ## 📌 Informasi Proyek
## **Sprint 3: AI Helper Screen Features & Modern UI Redesign** - **Nama Aplikasi:** NotesAI
- **Repository:** [NotesAI](https://git.lab.ubharajaya.ac.id/202310715297-RAIHAN-ARIQ-MUZAKKI/NotesAI.git)
### **AI Assistant Enhancements** - **Platform:** Android (Minimum API 24 / Android 7.0)
* **History Chat AI dengan Drawer Menu** - Riwayat percakapan AI tersimpan permanen, dikelompokkan per kategori - **Bahasa:** Kotlin 100%
* **Chat History Management** - Load previous chat, delete history, start new chat dengan auto-save - **UI Framework:** Jetpack Compose + Material 3
* **Markdown Parser untuk AI Response** - Support bold, italic, code blocks, headers, lists, quotes, links
* **Improved Error Handling** - User-friendly error messages untuk quota, network, API issues
* **Gemini Model Update** - Switch ke gemini-1.5-flash untuk stabilitas optimal
### **Theme System**
* **Dark/Light Theme Toggle** - Dual theme dengan persistent storage di drawer menu
* **Reactive Color System** - Dynamic color switching untuk semua components
* **Complete Color Palette** - DarkColors dan LightColors objects untuk consistency
### **UI/UX Modernization**
* **Floating Design System** - TopBar dan BottomBar dengan floating style, rounded corners, shadow
* **Consistent Component Style** - Unified design language dengan CircleShape buttons
* **Optimized Layouts** - Better spacing dan vertical action stack untuk maximize content space
### **Data & Navigation**
* **Note Edit & Delete from Card** - Menu dropdown pada NoteCard untuk quick actions
* **Race Condition Fix** - Guard flags dan lifecycle-aware auto-save untuk data persistence
* **Simplified Navigation** - Unified drawer menu, remove redundant back buttons
* **Extended DataStore** - Support chat history, theme preference, improved error handling
--- ---
## **Sprint 4: Rich Text Editor Core Features & AI Chat History UI/UX Improvements** ## 🎯 Tujuan dan Sasaran Aplikasi
### **Rich Text Editing** ### Masalah yang Dipecahkan
* **Hybrid Rich Text Editor (WYSIWYG)** Edit teks dengan format langsung tanpa syntax markdown terlihat 1. **Catatan tidak terorganisir** - Catatan bercampur tanpa struktur yang jelas
* **Bold, Italic, Underline** Formatting bersifat toggle dan tetap aktif sampai dimatikan 2. **Sulit mencari informasi** - Kehilangan waktu mencari catatan penting
* **Heading & Bullet List** Support heading (H1H3) dan bullet list tanpa konflik antar format 3. **Kurang interaktif** - Tidak ada bantuan untuk merangkum atau menganalisis catatan
* **Undo / Redo** Riwayat perubahan editor terintegrasi 4. **Risiko kehilangan data** - Catatan terhapus permanen tanpa backup
### **Floating Toolbar** ### Target Pengguna
* **Draggable Mini Toolbar** Toolbar dapat dipindahkan bebas oleh user - 🎓 **Mahasiswa** (18-25 tahun) - Catatan kuliah, tugas, ringkasan dokumen
* **Active State Indicator** Icon toolbar menandakan format aktif (Bold, Italic, dll) - 💼 **Profesional** (22-40 tahun) - Meeting notes, to-do lists, catatan kerja
* **Minimal UI** Toolbar kecil agar tidak mengganggu area pengetikan - 👤 **Pengguna Umum** (18-40 tahun) - Catatan pribadi, jurnal, daftar belanja
* **Keyboard-Aware Positioning** Posisi toolbar menyesuaikan saat keyboard muncul
### **Cursor & Editing Stability** ### Keunggulan NotesAI
* **Stable Cursor & Selection** Insertion point dan selection handle akurat saat mengetik **Organisasi Terstruktur** - Sistem kategori dengan visual gradien warna
* **IME & Keyboard Safe** Editor tetap stabil saat keyboard resize / rotate **AI Assistant** - Powered by Gemini 2.5 Flash untuk respons kontekstual
* **Auto Bring-Into-View** Cursor selalu terlihat saat mengetik di area bawah layar **Rich Text Editor** - WYSIWYG editor dengan drag-and-drop toolbar
**Smart Search** - Pencarian realtime dengan filter kategori
### **Data Persistence** **Data Safety** - Soft delete dengan trash & restore functionality
* **Format Tersimpan Permanen** Rich text tidak hilang setelah save atau reopen **Document Parser** - Upload PDF/TXT/DOCX dengan auto-summary
* **Auto Save Lifecycle-Aware** Catatan otomatis tersimpan saat app background / keluar
* **Markdown Compatibility** Support import & export markdown secara aman
### **Chat History Enhancements**
* **Compact Modern Design** - Item lebih kecil dengan horizontal layout dan 30 karakter limit
* **Search & Filter System** - Real-time search dengan category dropdown filtering
* **Date Grouping** - Auto-group: "Hari Ini", "Kemarin", "Minggu Ini", "Lebih Lama"
* **Edit Title with Markdown** - Custom title support: **bold**, *italic*, `code`, ~~strike~~
* **Context Menu** - Three-dot menu (⋮) untuk Edit dan Delete actions
* **Live Preview** - Real-time markdown preview saat edit title
### **Technical Updates**
* **ChatHistory Model** - Added `customTitle: String?` field
* **DataStore Integration** - New `updateChatHistoryTitle()` function
* **Smart Truncation** - Auto-truncate preview ke 30 char dengan `toSafeChatPreview()`
* **Markdown Parser** - Inline markdown rendering untuk titles dengan proper styling
* **Character Counter** - Visual feedback dengan color indicator (Gray → Primary → Red)
### **User Experience**
* **Better Empty States** - Informative UI untuk empty search dan no history
* **Smooth Animations** - Slide transitions untuk dialogs
* **Input Validation** - Max 30 char dengan real-time blocking
* **Focus Management** - Seamless editing experience dengan auto-focus
> Rich Text Editor butuh dikembangkan lagi lebih advance
---
## **Sprint 5: AI Assistant Enhancements & Smart Organization Features**
### **Copy Plain Text Feature**
* **Dual Copy Options** Dropdown menu dengan 2 pilihan: "Copy dengan Format" dan "Copy Teks Asli"
* **Smart Markdown Stripper** Utility untuk remove bold, italic, code, headers, lists, links dari text
* **Visual Feedback** Animated checkmark indicator dengan auto-hide setelah 2 detik
* **Format Preservation** Copy dengan format maintain semua markdown syntax
* **Clean Output** Plain text copy menghasilkan text bersih tanpa formatting apapun
### **Document Upload & AI Summary**
* **Multi-Format Support** Upload PDF, TXT, dan DOCX files dengan file picker
* **Smart PDF Parser** PDFBox Android integration untuk extract text dari PDF documents
* **Lightweight DOCX Parser** Custom XML-based parser tanpa Apache POI dependency
* **Auto-Summary Generation** AI auto-generate ringkasan maksimal 300 kata saat file di-upload
* **File Validation** Maximum 10MB dengan clear error messaging untuk setiap kasus
* **Loading Integration** Loading indicator "Membuat ringkasan..." terintegrasi di chat area
* **Chat Format** Upload result format: "📄 Upload file: filename" dengan summary response
### **Category Pin System**
* **Pin/Unpin Toggle** Quick access untuk kategori favorit dengan dropdown menu
* **Visual Pin Indicator** 📌 icon dengan scale dan fade animations
* **Smart Sorting Logic** Priority sorting: pinned categories (DESC) → timestamp (DESC)
* **Persistent Storage** Pin status tersimpan di DataStore dengan backward compatibility
* **Multiple Pins Support** User dapat pin multiple categories dengan proper grouping
* **Context Menu Integration** Pin option di dropdown: "Pin Kategori" / "Lepas Pin"
### **Technical Implementation**
* **MarkdownStripper.kt** Utility class dengan regex-based markdown removal
* **FileParser.kt** Centralized file parsing untuk PDF, TXT, DOCX
* **Category Model Update** Added `isPinned: Boolean` field dengan serialization support
* **FileParseResult** Sealed class untuk type-safe file parsing results
* **PDFBoxResourceLoader** Proper initialization dalam Application.onCreate()
* **State Management** Combined loading states untuk chat dan file upload
### **User Experience**
* **Smooth Transitions** Loading states dengan color differentiation (Primary vs Secondary)
* **Error Handling** Comprehensive error messages untuk berbagai failure scenarios
* **Auto-Scroll** Scroll to bottom saat upload file untuk show loading indicator
* **Disabled States** Upload button hidden saat processing untuk prevent duplicate actions
* **Persistence** Pin status dan file summary survive app restart
--- ---
## 🎯 Fitur Utama (Core Features) ## ✨ Fitur Utama
1. **Note Management System** ⭐ (PRIMARY)
* Create, Read, Update, Delete catatan ### 1⃣ Note Management System
* Organize notes dalam categories - ✏️ **CRUD Operations** - Create, Read, Update, Delete catatan
* Pin notes untuk quick access - 📁 **Category Organization** - Pengelompokan visual dengan gradien warna
* Archive & Trash system dengan soft delete - 📌 **Pin Priority** - Pin notes/kategori untuk akses cepat
* Full-screen rich text editor dengan WYSIWYG - 🗄️ **Archive & Trash** - Soft delete dengan kemampuan restore
* Real-time search & filter notes - 🎨 **Rich Text Editor** - Bold, italic, underline, heading, bullet list
- 🔍 **Smart Search** - Realtime search dengan case-insensitive
2. **AI Assistant** 🤖 (PRIMARY) ### 2⃣ AI Assistant
- 🤖 **Contextual AI Chat** - AI memahami konteks dari catatan Anda
- 📄 **Document Upload** - Support PDF, TXT, DOCX
- 📝 **Auto Summary** - Ringkasan otomatis dari dokumen
- 💬 **Chat History** - Penyimpanan percakapan persistent
- 🎯 **Category Filter** - Filter konteks berdasarkan kategori
- ✍️ **Markdown Support** - Formatted AI responses
* Chat dengan AI menggunakan Gemini 2.5 Flash ### 3⃣ Data Management
* Context-aware responses berdasarkan notes user - 💾 **Local Storage** - DataStore Preferences untuk data persistence
* Chat history management dengan persistent storage - 🔄 **Autosave** - Lifecycle-aware autosave dengan debounce 500ms
* Document upload & auto-summary (PDF, TXT, DOCX) - 🌙 **Theme Preference** - Dark/Light mode support
* Markdown support untuk AI responses - 📊 **Reactive Data** - Flow-based reactive data loading
* Copy plain text atau formatted text - ⚡ **Fast Performance** - Optimized untuk pengalaman smooth
3. **Category Organization** 📁 (CORE)
* Create & manage categories dengan 8 gradient color presets
* Pin favorite categories untuk quick access
* Smart sorting: pinned categories → timestamp descending
* Category-based note filtering dengan statistics
* Staggered grid layout responsive
4. **Rich Text Editor** ✏️ (CORE)
* WYSIWYG (What You See Is What You Get) editing experience tanpa raw markdown
* Bold, italic, underline, headings (H1-H3), bullet lists
* Floating draggable toolbar dengan active state indicators
* Undo/Redo functionality
* Markdown compatibility untuk import/export
* Auto-save lifecycle-aware
5. **Data Persistence** 💾 (ESSENTIAL)
* Local storage dengan DataStore Preferences
* Auto-save dengan debounce (500ms delay)
* Theme preference storage (dark/light mode)
* Chat history persistence dengan serialization
* Flow-based reactive data loading
* Error handling untuk semua I/O operations
--- ---
## **Features for Sprint 3 v1.1.0** ## 📊 Riset dan Analisis
* History Chat AI berdasarkan Catatan yang ada didalam kategori dalam bentuk Drawer Menu di AI Helper (ok) ### Analisis Pasar
* Mengganti Preview Deskripsi NoteCard dan NoteDialog (ok) Berdasarkan riset pasar 2025:
* Dark/Light theme toggle (ok) - **70% responden** percaya AI meningkatkan produktivitas kerja *(Eurobarometer, Feb 2025)*
* Markdown Parser (ok) - **Pasar note-taking apps** menunjukkan pertumbuhan dengan tren integrasi AI
- **Gemini 2.5 Flash** dipilih sebagai model "price-performance" terbaik untuk low-latency tasks
### Diferensiasi NotesAI
🎯 **AI Contextual** - AI dapat membaca semua catatan sebagai konteks
🎯 **Document to Summary** - Upload file langsung dapat ringkasan
🎯 **Local-First** - Tidak butuh login, data tersimpan lokal
🎯 **Free & Open** - Tidak ada paywall untuk fitur utama
--- ---
## **Features for Sprint 4 v1.1.0** ## 🎨 Desain UI/UX
* Penyesuaian UI/UX History Chat AI (ok)
* Rich text editor (ok - Harus Pengembangan Lanjutan) ### Design System
- **Material Design 3** - Modern, clean, consistent
- **Color Scheme** - Dynamic gradients untuk kategori
- **Typography** - Clear hierarchy untuk readability
- **Spacing** - Consistent 4dp baseline grid
### User Flow
```
┌─────────────────────────────────────────────┐
│ 🏠 Main Screen (Home) │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Category │ │ Category │ │
│ │ Card │ │ Card │ │
│ └─────────────┘ └─────────────┘ │
└───────────┬─────────────────────────────────┘
│ Select Category
┌─────────────────────────────────────────────┐
│ 📄 Notes List Screen │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Note Card │ │ Note Card │ │
│ │ (Pinned) │ │ (Regular) │ │
│ └─────────────┘ └─────────────┘ │
└───────────┬─────────────────────────────────┘
│ Open Note
┌─────────────────────────────────────────────┐
│ ✏️ Full-Screen Editor │
│ • Rich Text Toolbar (Draggable) │
│ • Bold, Italic, Underline │
│ • Heading, Bullet List │
│ • Auto-save on background │
└─────────────────────────────────────────────┘
```
### Wireframe & Mockup
📐 **Wireframe lengkap** tersedia di [Dokumentasi](docs/Laporan%20Dokumentasi%20Aplikasi%20-%20Kelompok%201.pdf) Halaman 15
📸 **Screenshot aplikasi** tersedia di Panduan Pengguna (Halaman 21-28)
--- ---
## **Features for Sprint 5 v1.1.0** ## 🛠️ Teknologi dan Alat
* Fungsi AI (Upload File) (ok)
* Fitur Sematkan Category, otomatis paling atas (ok) ### Tech Stack
#### Core Technologies
```
// Build Configuration
Kotlin 1.9.0
Android Gradle Plugin 8.2.0
Compile SDK 34
Min SDK 24 (Android 7.0)
Target SDK 34
```
#### UI & Architecture
- **Jetpack Compose** - Modern declarative UI
- **Material 3** - Latest Material Design components
- **Navigation Compose** - Type-safe navigation
- **Lifecycle** - Lifecycle-aware components
#### Data & Storage
- **DataStore Preferences** - Key-value storage
- **Kotlinx Serialization** - JSON serialization
- **Kotlin Coroutines** - Asynchronous programming
- **Flow** - Reactive data streams
#### AI & Integration
- **Gemini API** - Google Generative AI (Gemini 2.5 Flash)
- **PDFBox-Android** - PDF text extraction
- **Activity Result API** - File picker for document upload
#### Development Tools
- **Android Studio**
- **Git** - Version control (git.lab.ubharajaya.ac.id)
- **Gradle** - Build automation
- **Claude AI** - AI-assisted development
### Dependencies
```gradle
dependencies {
// Compose
implementation("androidx.compose.ui:ui:1.6.0")
implementation("androidx.compose.material3:material3:1.2.0")
// DataStore
implementation("androidx.datastore:datastore-preferences:1.0.0")
// Serialization
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")
// AI
implementation("com.google.ai.client.generativeai:generativeai:0.1.2")
// PDF Parser
implementation("com.tom-roush:pdfbox-android:2.0.27.0")
// Testing
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
}
```
--- ---
## 🏗️ Arsitektur Aplikasi
### Architecture Pattern
```
┌──────────────────────────────────────────────────┐
│ PRESENTATION LAYER │
│ ┌──────────────────────────────────────────┐ │
│ │ Composable Screens │ │
│ │ • MainScreen │ │
│ │ • AIHelperScreen │ │
│ │ • ArchiveScreen, TrashScreen │ │
│ └──────────────────────────────────────────┘ │
└────────────────────┬─────────────────────────────┘
│ Uses
┌──────────────────────────────────────────────────┐
│ DATA LAYER │
│ ┌──────────────────────────────────────────┐ │
│ │ DataStoreManager │ │
│ │ • saveNotes() / notesFlow │ │
│ │ • saveCategories() / categoriesFlow │ │
│ │ • saveChatHistory() / chatHistoryFlow │ │
│ └──────────────────────────────────────────┘ │
└────────────────────┬─────────────────────────────┘
│ Stores
┌──────────────────────────────────────────────────┐
│ MODEL LAYER │
│ • Note (id, title, content, isPinned...) │
│ • Category (id, name, gradients, isPinned...) │
│ • ChatHistory (messages, timestamp...) │
└──────────────────────────────────────────────────┘
```
### Package Structure
```
com.example.notesai/
├── 📁 config/
│ └── APIKey.kt
├── 📁 data/
│ ├── 📁 local/
│ │ └── DataStoreManager.kt
│ └── 📁 model/
│ ├── Note.kt
│ ├── Category.kt
│ ├── ChatHistory.kt
│ └── ChatMessage.kt
├── 📁 presentation/
│ ├── 📁 components/
│ │ ├── DrawerMenu.kt
│ │ ├── ModernTopBar.kt
│ │ └── ModernBottomBar.kt
│ └── 📁 screens/
│ ├── 📁 main/
│ ├── 📁 ai/
│ ├── 📁 archive/
│ ├── 📁 trash/
│ └── 📁 note/
└── 📁 util/
├── FileParser.kt
├── Constants.kt
└── AppColors.kt
```
---
## 📚 Resource yang Digunakan
### Visual Assets
- 🎨 **Icons** - Material Icons & Lucide Icons
- 🌈 **Colors** - Material 3 Dynamic Color
- 🖼️ **Illustrations** - Custom empty states
### Content & Data
- 📖 **Sample Data** - Test categories & notes untuk demo
- 📄 **Documents** - Sample PDF/TXT untuk testing parser
### External Services
- 🤖 **Gemini API** - Google Generative AI
- 📚 **Documentation** - Android Developers, Kotlin Docs
### Learning Resources
Referensi utama yang digunakan:
- [Android App Architecture Guide](https://developer.android.com/topic/architecture)
- [Jetpack Compose Documentation](https://developer.android.com/jetpack/compose)
- [Gemini API Documentation](https://ai.google.dev/docs)
- [Kotlin Serialization](https://kotlinlang.org/docs/serialization.html)
---
## 🧪 Pengujian Aplikasi
### Metodologi Testing
**Primary Method:** Black-Box Functional Testing
**Supporting Method:** Automated Unit Testing
Pengujian dilakukan menggunakan metode **Black-Box Functional Testing** sebagai pendekatan utama, dimana setiap fitur divalidasi dari perspektif end-user dengan memverifikasi kesesuaian **Expected vs Actual Result**. Didukung oleh **59 automated unit tests** untuk validasi business logic internal.
### Test Coverage Summary
| Test Case | Fitur | Tests | Status |
|-----------|-------|-------|--------|
| **TC-01** | Create Note & Category + Autosave | 8 tests | ✅ PASSED |
| **TC-02** | Pin Note (Priority) | included | ✅ PASSED |
| **TC-03** | Soft Delete & Restore | 11 tests | ✅ PASSED |
| **TC-04** | Search Realtime | 14 tests | ✅ PASSED |
| **TC-05** | AI Chat with Context | 14 tests | ✅ PASSED |
| **TC-06** | Upload PDF → Summary | 12 tests | ✅ PASSED |
| **TOTAL** | **6 Test Cases** | **59 tests** | **✅ 100%** |
### Test Results
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 TEST SUMMARY REPORT
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Total Test Cases: 6
Passed Test Cases: 6
Failed Test Cases: 0
Success Rate: 100%
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Total Unit Tests: 59
Passed Tests: 59
Failed Tests: 0
Execution Time: ~2 minutes
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Status: ✅ ALL TESTS PASSED
Quality: ✅ PRODUCTION READY
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
```
📄 **Laporan lengkap:** [TEST_SUMMARY_REPORT.md](./TEST_SUMMARY_REPORT.md)
### Testing Framework
- **JUnit 4** - Unit testing framework
- **AndroidX Test** - Android testing utilities
- **Kotlin Coroutines Test** - Async testing
- **Truth** - Assertion library
---
## 🚀 Instalasi dan Penggunaan
### Prasyarat
- ✅ Android 7.0 (API 24) atau lebih tinggi
- ✅ Koneksi internet (untuk fitur AI)
- ✅ Minimal 50MB storage kosong
### Cara Menjalankan dari Source Code
#### 1. Clone Repository
```bash
git clone https://git.lab.ubharajaya.ac.id/kelompok-3/notesai.git
cd notesai
```
#### 2. Setup API Key
Buat file `local.properties` di root project:
```properties
GEMINI_API_KEY=your_gemini_api_key_here
```
#### 3. Open di Android Studio
1. Buka Android Studio
2. File → Open → Pilih folder project
3. Tunggu Gradle sync selesai
#### 4. Run Aplikasi
1. Pilih device/emulator
2. Klik Run (▶️) atau `Shift + F10`
3. Aplikasi akan terinstall dan berjalan
---
## 📱 Panduan Penggunaan
### Quick Start Guide
#### 1⃣ Membuat Kategori Pertama
```
Main Screen → Tap () → Pilih "Kategori Baru"
→ Isi nama kategori → Pilih warna → Save
```
#### 2⃣ Membuat Note
```
Main Screen → Tap kategori → Tap () floating button
→ Isi judul & konten → Auto-saved ✓
```
#### 3⃣ Menggunakan Rich Text Editor
```
Buka note → Tap area teks → Muncul draggable toolbar
→ Pilih format (Bold/Italic/Heading/Bullet) → Type away!
```
#### 4⃣ Pin untuk Prioritas
```
Long-press note → Tap ⭐ Pin icon
→ Note akan muncul di urutan teratas
```
#### 5⃣ Chat dengan AI
```
Drawer Menu → AI Assistant → Ketik pertanyaan
→ AI akan menjawab berdasarkan catatan Anda
```
#### 6⃣ Upload & Summarize Document
```
AI Assistant → Tap 📎 Upload → Pilih file (PDF/TXT/DOCX)
→ AI otomatis generate summary → Tersimpan di chat history
```
### User Flow Lengkap
📖 Panduan detail dengan screenshot tersedia di [Dokumentasi](./docs/Laporan%20Dokumentasi%20Aplikasi%20-%20Kelompok%201.pdf) Bab III (Halaman 21-28)
---
## ⚠️ Batasan dan Catatan
### Keterbatasan Saat Ini
1. **AI Dependency**
- ⚠️ Fitur AI memerlukan koneksi internet
- ⚠️ Menggunakan free tier Gemini API (rate limited)
- Catatan lokal tetap berfungsi offline
2. **Document Format**
- ✅ Support: PDF, TXT, DOCX
- ❌ Tidak support: XLS, PPT, Images
3. **Data Storage**
- 💾 Data tersimpan lokal (DataStore)
- ⚠️ Tidak ada cloud backup (planned v2.0)
- Risiko data loss jika uninstall app
4. **Performance**
- ⚡ Optimal untuk <1000 notes
- ⚠️ Search dapat melambat pada dataset besar
- 🔜 Indexing optimization planned
### Privasi & Keamanan
- ✅ Catatan disimpan **100% lokal**
- ⚠️ Saat menggunakan AI, konten relevan dikirim ke Gemini API
- 🔐 API key tidak hardcoded (menggunakan BuildConfig)
- Tidak ada tracking atau analytics
---
## 🔮 Roadmap & Future Development
### Version 1.2.0 (Q2 2025) 🎯
- [ ] **Cloud Sync** - Firebase/Supabase integration
- [ ] **Backup & Restore** - Export/import data
- [ ] **Widget** - Home screen quick note
- [ ] **Reminder** - Notification untuk note penting
- [ ] **Templates** - Pre-made note templates
### Version 1.3.0 (Q3 2025) 🚀
- [ ] **Collaboration** - Share notes dengan user lain
- [ ] **Voice Input** - Speech-to-text untuk note
- [ ] **Image Support** - Attach images ke notes
- [ ] **Tag System** - Alternative categorization
- [ ] **Advanced Search** - Filter by date, tag, etc.
### Version 1.4.0 (Q4 2025) 💎
- [ ] **Multi-device Sync** - Real-time sync
- [ ] **Encryption** - End-to-end encryption
- [ ] **Premium AI** - Upgrade ke Gemini Pro
- [ ] **Offline AI** - On-device AI model
- [ ] **iOS Version** - Cross-platform support
---
## 📄 Dokumentasi Tambahan
### File Dokumentasi
- 📖 [Laporan Lengkap](./docs/Laporan%20Dokumentasi%20Aplikasi%20-%20Kelompok%201.pdf) - Dokumentasi lengkap 35 halaman
- 🧪 [Test Summary Report](./TEST_SUMMARY_REPORT.md) - Laporan pengujian detail
- 📋 [Changelog](./CHANGELOG.md) - Riwayat perubahan versi
### API Documentation
- 🤖 [Gemini API Docs](https://ai.google.dev/docs)
- 📚 [Android Developers](https://developer.android.com)
- 📝 [Kotlin Documentation](https://kotlinlang.org/docs)
### Referensi Akademik
Semua referensi dan kutipan tercantum di [Daftar Pustaka](./docs/Laporan%20Dokumentasi%20Aplikasi%20-%20Kelompok%201.pdf) halaman 33
---
## 🤝 Kontribusi & Support
### Cara Berkontribusi
1. Fork repository ini
2. Buat branch fitur (`git checkout -b feature/AmazingFeature`)
3. Commit changes (`git commit -m 'Add some AmazingFeature'`)
4. Push ke branch (`git push origin feature/AmazingFeature`)
5. Buat Pull Request
### Coding Standards
- ✅ Follow Kotlin coding conventions
- ✅ Write descriptive commit messages
- ✅ Add unit tests untuk fitur baru
- ✅ Update documentation
### Laporkan Bug
Jika menemukan bug, silakan buat issue dengan:
- 📝 Deskripsi bug
- 📱 Device & Android version
- 🔄 Steps to reproduce
- 📸 Screenshot (jika ada)
---
## 📜 License
```
MIT License
Copyright (c) 2025 Kelompok 1 - NotesAI
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
---
## 🙏 Acknowledgments
### Special Thanks
- 🎓 **Bapak Arif Rifai Dwiyanto, ST., MTI** - Dosen pembimbing dan pengampu mata kuliah
- 🏫 **Universitas Bhayangkara Jakarta Raya** - Dukungan fasilitas
- 🤖 **Claude AI (Anthropic)** - AI assistant untuk pengembangan dan debugging
- 🎨 **Material Design Team** - Design system yang digunakan
- 📚 **Android Developer Community** - Dokumentasi dan best practices
### Tools & Services
- Android Studio - IDE terbaik untuk Android development
- Jetpack Compose - Modern UI toolkit
- Gemini API - AI capabilities
- PDFBox - PDF parsing library
- Git Lab UBHARA - Version control hosting
---
## 📞 Kontak
**Tim Pengembang Kelompok 3**
📧 Email: [kelompok3.notesai@ubharajaya.ac.id](mailto:kelompok3.notesai@ubharajaya.ac.id)
🌐 Repository: [NotesAI](https://git.lab.ubharajaya.ac.id/202310715297-RAIHAN-ARIQ-MUZAKKI/NotesAI.git)
🏫 Institusi: Universitas Bhayangkara Jakarta Raya
---
**Made with ❤️ by Kelompok 3**
**Fakultas Ilmu Komputer - Program Studi Informatika**
**Universitas Bhayangkara Jakarta Raya**
**2025**
[⬆️ Back to Top](#-notesai---ai-powered-note-taking-app)

View File

@ -8,18 +8,11 @@
**Total Unit Tests:** 59 **Total Unit Tests:** 59
**Status:** ✅ ALL PASSED **Status:** ✅ ALL PASSED
--- Pengujian fungsional dilakukan secara manual dengan metode black-box berbasis test case,
didukung oleh Automated Unit Tests, memverifikasi kesesuaian expected vs actual result pada fitur inti
## Test Cases Summary (notes, kategori, pin, trash/restore, search, AI context, dan upload-summary).
Unit testing adalah pengujian otomatis terhadap unit terkecil dari kode
| ID | Fitur | Skenario | Langkah Uji | Expected Result | Actual Result | Status | (functions, methods) untuk memvalidasi logic internal aplikasi.
|----|-------|----------|-------------|-----------------|---------------|--------|
| **TC-01** | **Create Note & Category + Autosave** | Membuat note dan category baru dengan autosave debounce 500ms | 1. Buat category baru<br>2. Buat note baru<br>3. Edit note<br>4. Tunggu 500ms<br>5. Verify autosave | - Category tersimpan dengan benar<br>- Note tersimpan dengan benar<br>- Autosave berjalan setelah 500ms debounce<br>- Data ter-update | - ✅ Category tersimpan: `testCreateCategory_shouldSaveSuccessfully`<br>- ✅ Note tersimpan: `testCreateNote_shouldSaveSuccessfully`<br>- ✅ Multiple categories: `testCreateMultipleCategories_shouldSaveInCorrectOrder`<br>- ✅ Autosave works: `testAutoSave_shouldUpdateExistingNote` | ✅ PASSED<br>(8 tests) |
| **TC-02** | **Pin Note** | Pin note muncul di urutan teratas | 1. Buat 3 notes dengan timestamp berbeda<br>2. Pin note terlama<br>3. Verify urutan | - Pinned note muncul di posisi teratas<br>- Unpinned notes diurutkan berdasarkan timestamp<br>- Multiple pinned notes diurutkan by timestamp | - ✅ Pinned note first: `testPinNote_shouldAppearFirst`<br>- ✅ Multiple pins sorted: `testMultiplePinnedNotes_shouldSortByTimestamp`<br>- ✅ Unpin works: `testUnpinNote_shouldMoveToNormalPosition`<br>- ✅ Category pin: `testPinCategory_shouldPersist` | ✅ PASSED<br>(included in TC-01) |
| **TC-03** | **Soft Delete & Restore** | Soft delete note/category dan restore dari trash | 1. Delete note/category (soft delete)<br>2. Verify item masuk trash<br>3. Restore item dari trash<br>4. Verify item kembali aktif<br>5. Test permanent delete | - Item ditandai `isDeleted=true`<br>- Item muncul di trash screen<br>- Restore mengembalikan `isDeleted=false`<br>- Data tetap preserved<br>- Permanent delete menghapus sepenuhnya | - ✅ Soft delete note: `testSoftDeleteNote_shouldMarkAsDeleted`<br>- ✅ Restore note: `testRestoreNoteFromTrash_shouldUnmarkDeleted`<br>- ✅ Soft delete category: `testSoftDeleteCategory_shouldMarkAsDeleted`<br>- ✅ Restore category: `testRestoreCategoryFromTrash_shouldUnmarkDeleted`<br>- ✅ Filter deleted: `testFilterDeletedNotes_shouldOnlyShowDeleted`<br>- ✅ Permanent delete: `testPermanentDeleteNote_shouldRemoveCompletely`<br>- ✅ Data preserved: `testDeletedNotePreservesAllData_shouldKeepContent` | ✅ PASSED<br>(11 tests) |
| **TC-04** | **Search Realtime** | Search realtime menemukan keyword di notes dan categories | 1. Buat multiple notes dengan content berbeda<br>2. Input search query<br>3. Verify hasil realtime<br>4. Test case-insensitive<br>5. Test partial match<br>6. Test filter by category | - Search menemukan notes by title<br>- Search menemukan notes by content<br>- Case-insensitive search works<br>- Partial match ditemukan<br>- Empty query return all<br>- Exclude deleted & archived notes | - ✅ Search by title: `testSearchNoteByTitle_shouldFindMatches`<br>- ✅ Search by content: `testSearchNoteByContent_shouldFindMatches`<br>- ✅ Case insensitive: `testSearchCaseInsensitive_shouldFindMatches`<br>- ✅ Partial match: `testSearchPartialMatch_shouldFindResults`<br>- ✅ Empty query: `testSearchEmptyQuery_shouldReturnAllNotes`<br>- ✅ Exclude deleted: `testSearchExcludesDeletedNotes_shouldNotFindDeleted`<br>- ✅ Search category: `testSearchCategory_shouldFindByName`<br>- ✅ Realtime update: `testSearchRealtime_shouldUpdateImmediately` | ✅ PASSED<br>(14 tests) |
| **TC-05** | **AI Chat with Context** | AI chat menjawab dengan konteks note (gunakan 1-2 contoh note) | 1. Buat 1-2 sample notes<br>2. Open AI chat<br>3. Send query tentang notes<br>4. Verify AI dapat akses context<br>5. Save chat history<br>6. Load chat history | - Context mencakup semua notes<br>- Context filtered by category<br>- Exclude archived notes<br>- Chat history tersimpan<br>- Chat history bisa di-load<br>- Custom title bisa di-set | - ✅ Build context: `testBuildNotesContext_shouldIncludeAllNotes`<br>- ✅ Filter by category: `testBuildNotesContext_shouldFilterByCategory`<br>- ✅ Exclude archived: `testBuildNotesContext_shouldExcludeArchivedNotes`<br>- ✅ Save history: `testSaveChatHistory_shouldPersist`<br>- ✅ Load history: `testLoadChatHistory_shouldRestoreMessages`<br>- ✅ Sort histories: `testMultipleChatHistories_shouldSortByTimestamp`<br>- ✅ Update history: `testUpdateChatHistory_shouldUpdateExisting`<br>- ✅ Delete history: `testDeleteChatHistory_shouldMarkAsDeleted`<br>- ✅ Custom title: `testCustomChatTitle_shouldPersist` | ✅ PASSED<br>(14 tests) |
| **TC-06** | **Upload PDF → Summary** | Upload PDF dan summary tersimpan/terbaca | 1. Upload file (PDF/TXT/DOCX)<br>2. Verify file parsed<br>3. Generate AI summary<br>4. Save summary to chat history<br>5. Verify summary readable<br>6. Test error handling | - File di-parse dengan benar<br>- Word count calculated<br>- File type identified<br>- Summary generated & saved<br>- Summary tersimpan di chat history<br>- Metadata preserved<br>- Error handling gracefully | - ✅ Word count: `testFileParseResult_shouldCalculateWordCount`<br>- ✅ File type: `testFileParseResult_shouldIdentifyFileType`<br>- ✅ File size format: `testFormatFileSize_shouldFormatCorrectly`<br>- ✅ Save summary: `testSaveSummaryToChatHistory_shouldPersist`<br>- ✅ Multiple uploads: `testMultipleFileUploads_shouldTrackAll`<br>- ✅ Summary readable: `testSummaryContent_shouldBeReadable`<br>- ✅ Error handling: `testFileUploadError_shouldHandleGracefully`<br>- ✅ Structured format: `testPDFSummaryFormat_shouldBeStructured`<br>- ✅ Metadata preserved: `testFileMetadata_shouldBePreserved` | ✅ PASSED<br>(12 tests) |
--- ---

View File

@ -247,21 +247,24 @@ fun NotesApp() {
if (!showFullScreenNote && currentScreen != "ai") { if (!showFullScreenNote && currentScreen != "ai") {
ModernTopBar( ModernTopBar(
title = when(currentScreen) { title = when(currentScreen) {
"main" -> if (selectedCategory != null) selectedCategory!!.name else "AI Notes" "main" -> if (selectedCategory != null) selectedCategory!!.name else "NotesAI"
"starred" -> "Berbintang" "starred" -> "Berbintang"
"archive" -> "Arsip" "archive" -> "Arsip"
"trash" -> "Sampah" "trash" -> "Sampah"
else -> "AI Notes" else -> "NotesAI"
}, },
showBackButton = (selectedCategory != null && currentScreen == "main"), showBackButton = (selectedCategory != null && currentScreen == "main"),
onBackClick = { onBackClick = {
selectedCategory = null selectedCategory = null
}, },
onMenuClick = { drawerState = !drawerState }, onMenuClick = { drawerState = !drawerState },
onSearchClick = { showSearch = !showSearch }, onSearchClick = {
showSearch = !showSearch
if (!showSearch) searchQuery = "" // Reset search saat close
},
searchQuery = searchQuery, searchQuery = searchQuery,
onSearchQueryChange = { searchQuery = it }, onSearchQueryChange = { searchQuery = it },
showSearch = showSearch && currentScreen == "main" showSearch = showSearch // AKTIFKAN UNTUK SEMUA SCREEN
) )
} }
}, },
@ -426,6 +429,7 @@ fun NotesApp() {
"trash" -> TrashScreen( "trash" -> TrashScreen(
notes = notes.filter { it.isDeleted }, notes = notes.filter { it.isDeleted },
categories = categories, categories = categories,
searchQuery = searchQuery, // TAMBAHKAN INI
onRestoreNote = { note -> onRestoreNote = { note ->
notes = notes.map { notes = notes.map {
if (it.id == note.id) it.copy(isDeleted = false, isArchived = false) if (it.id == note.id) it.copy(isDeleted = false, isArchived = false)
@ -454,6 +458,7 @@ fun NotesApp() {
"starred" -> StarredNotesScreen( "starred" -> StarredNotesScreen(
notes = notes, notes = notes,
categories = categories.filter { !it.isDeleted }, categories = categories.filter { !it.isDeleted },
searchQuery = searchQuery, // TAMBAHKAN INI
onNoteClick = { note -> onNoteClick = { note ->
fullScreenNote = note fullScreenNote = note
showFullScreenNote = true showFullScreenNote = true
@ -469,6 +474,7 @@ fun NotesApp() {
"archive" -> ArchiveScreen( "archive" -> ArchiveScreen(
notes = notes.filter { it.isArchived && !it.isDeleted }, notes = notes.filter { it.isArchived && !it.isDeleted },
categories = categories.filter { !it.isDeleted }, categories = categories.filter { !it.isDeleted },
searchQuery = searchQuery,
onRestore = { note -> onRestore = { note ->
notes = notes.map { notes = notes.map {
if (it.id == note.id) it.copy(isArchived = false) if (it.id == note.id) it.copy(isArchived = false)
@ -566,8 +572,8 @@ fun NotesApp() {
currentScreen = screen currentScreen = screen
selectedCategory = null selectedCategory = null
drawerState = false drawerState = false
showSearch = false showSearch = false // TUTUP SEARCH
searchQuery = "" searchQuery = "" // RESET SEARCH QUERY
}, },
onThemeToggle = { onThemeToggle = {
isDarkTheme = !isDarkTheme isDarkTheme = !isDarkTheme

View File

@ -4,27 +4,13 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Archive import androidx.compose.material.icons.filled.Archive
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.OutlinedTextFieldDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.example.notesai.data.model.Note import com.example.notesai.data.model.Note
import com.example.notesai.data.model.Category import com.example.notesai.data.model.Category
@ -35,12 +21,11 @@ import com.example.notesai.presentation.screens.archive.components.ArchiveNoteCa
fun ArchiveScreen( fun ArchiveScreen(
notes: List<Note>, notes: List<Note>,
categories: List<Category>, categories: List<Category>,
searchQuery: String = "", // Tambahkan parameter ini
onRestore: (Note) -> Unit, onRestore: (Note) -> Unit,
onDelete: (Note) -> Unit onDelete: (Note) -> Unit
) { ) {
var searchQuery by remember { mutableStateOf("") } // Filter berdasarkan search query dari ModernTopBar
// Filter berdasarkan search query
val filteredNotes = if (searchQuery.isBlank()) { val filteredNotes = if (searchQuery.isBlank()) {
notes notes
} else { } else {
@ -53,50 +38,6 @@ fun ArchiveScreen(
} }
Column(modifier = Modifier.fillMaxSize()) { Column(modifier = Modifier.fillMaxSize()) {
// Search Bar
OutlinedTextField(
value = searchQuery,
onValueChange = { searchQuery = it },
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp),
placeholder = {
Text(
"Cari catatan arsip...",
color = Color(0xFF64748B)
)
},
leadingIcon = {
Icon(
Icons.Default.Search,
contentDescription = null,
tint = Color(0xFF64748B)
)
},
trailingIcon = {
if (searchQuery.isNotEmpty()) {
IconButton(onClick = { searchQuery = "" }) {
Icon(
Icons.Default.Clear,
contentDescription = "Clear",
tint = Color(0xFF64748B)
)
}
}
},
shape = RoundedCornerShape(12.dp),
colors = OutlinedTextFieldDefaults.colors(
focusedContainerColor = Color(0xFF1E293B),
unfocusedContainerColor = Color(0xFF1E293B),
focusedBorderColor = Color(0xFF6366F1),
unfocusedBorderColor = Color(0xFF334155),
focusedTextColor = Color.White,
unfocusedTextColor = Color.White,
cursorColor = Color(0xFF6366F1)
),
singleLine = true
)
// Content // Content
if (filteredNotes.isEmpty()) { if (filteredNotes.isEmpty()) {
if (searchQuery.isNotEmpty()) { if (searchQuery.isNotEmpty()) {
@ -117,6 +58,7 @@ fun ArchiveScreen(
contentPadding = PaddingValues( contentPadding = PaddingValues(
start = 16.dp, start = 16.dp,
end = 16.dp, end = 16.dp,
top = 8.dp,
bottom = 100.dp bottom = 100.dp
), ),
verticalArrangement = Arrangement.spacedBy(12.dp) verticalArrangement = Arrangement.spacedBy(12.dp)

View File

@ -43,11 +43,25 @@ fun MainScreen(
) )
} else { } else {
// Filter kategori berdasarkan searchQuery // Filter kategori berdasarkan searchQuery
val filteredCategories = if (searchQuery.isEmpty()) { val filteredCategories = if (searchQuery.isBlank()) {
categories categories
} else { } else {
categories.filter { categories.filter { category ->
it.name.contains(searchQuery, ignoreCase = true) // 1. Cek nama kategori cocok
val categoryNameMatches = category.name.contains(searchQuery, ignoreCase = true)
// 2. Cek ada catatan yang cocok di kategori ini
val hasMatchingNotes = notes.any { note ->
note.categoryId == category.id &&
!note.isDeleted &&
!note.isArchived &&
(note.title.contains(searchQuery, ignoreCase = true) ||
note.description.contains(searchQuery, ignoreCase = true) ||
note.content.contains(searchQuery, ignoreCase = true))
}
// Kategori muncul jika salah satu kondisi terpenuhi
categoryNameMatches || hasMatchingNotes
} }
} }

View File

@ -3,32 +3,15 @@ package com.example.notesai.presentation.screens.starred
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.filled.Search
import androidx.compose.material.icons.filled.Star import androidx.compose.material.icons.filled.Star
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.OutlinedTextFieldDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.example.notesai.presentation.components.EmptyState import com.example.notesai.presentation.components.EmptyState
import com.example.notesai.presentation.screens.starred.components.StarredNoteCard import com.example.notesai.presentation.screens.starred.components.StarredNoteCard
@ -40,16 +23,15 @@ import com.example.notesai.data.model.Category
fun StarredNotesScreen( fun StarredNotesScreen(
notes: List<Note>, notes: List<Note>,
categories: List<Category>, categories: List<Category>,
searchQuery: String = "", // Tambahkan parameter ini
onNoteClick: (Note) -> Unit, onNoteClick: (Note) -> Unit,
onUnpin: (Note) -> Unit onUnpin: (Note) -> Unit
) { ) {
var searchQuery by remember { mutableStateOf("") }
val starredNotes = notes val starredNotes = notes
.filter { it.isPinned && !it.isArchived && !it.isDeleted } .filter { it.isPinned && !it.isArchived && !it.isDeleted }
.sortedByDescending { it.timestamp } .sortedByDescending { it.timestamp }
// Filter berdasarkan search query // Filter berdasarkan search query dari ModernTopBar
val filteredNotes = if (searchQuery.isBlank()) { val filteredNotes = if (searchQuery.isBlank()) {
starredNotes starredNotes
} else { } else {
@ -61,50 +43,6 @@ fun StarredNotesScreen(
} }
Column(modifier = Modifier.fillMaxSize()) { Column(modifier = Modifier.fillMaxSize()) {
// Search Bar
OutlinedTextField(
value = searchQuery,
onValueChange = { searchQuery = it },
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp),
placeholder = {
Text(
"Cari catatan berbintang...",
color = Color(0xFF64748B)
)
},
leadingIcon = {
Icon(
Icons.Default.Search,
contentDescription = null,
tint = Color(0xFF64748B)
)
},
trailingIcon = {
if (searchQuery.isNotEmpty()) {
IconButton(onClick = { searchQuery = "" }) {
Icon(
Icons.Default.Clear,
contentDescription = "Clear",
tint = Color(0xFF64748B)
)
}
}
},
shape = RoundedCornerShape(12.dp),
colors = OutlinedTextFieldDefaults.colors(
focusedContainerColor = Color(0xFF1E293B),
unfocusedContainerColor = Color(0xFF1E293B),
focusedBorderColor = Color(0xFF6366F1),
unfocusedBorderColor = Color(0xFF334155),
focusedTextColor = Color.White,
unfocusedTextColor = Color.White,
cursorColor = Color(0xFF6366F1)
),
singleLine = true
)
// Content // Content
if (filteredNotes.isEmpty()) { if (filteredNotes.isEmpty()) {
if (searchQuery.isNotEmpty()) { if (searchQuery.isNotEmpty()) {
@ -125,6 +63,7 @@ fun StarredNotesScreen(
contentPadding = PaddingValues( contentPadding = PaddingValues(
start = 16.dp, start = 16.dp,
end = 16.dp, end = 16.dp,
top = 8.dp,
bottom = 100.dp bottom = 100.dp
), ),
verticalArrangement = Arrangement.spacedBy(12.dp) verticalArrangement = Arrangement.spacedBy(12.dp)

View File

@ -4,26 +4,15 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.OutlinedTextFieldDefaults
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
@ -38,18 +27,17 @@ import com.example.notesai.data.model.Category
fun TrashScreen( fun TrashScreen(
notes: List<Note>, notes: List<Note>,
categories: List<Category>, categories: List<Category>,
searchQuery: String = "", // Tambahkan parameter ini
onRestoreNote: (Note) -> Unit, onRestoreNote: (Note) -> Unit,
onDeleteNotePermanent: (Note) -> Unit, onDeleteNotePermanent: (Note) -> Unit,
onRestoreCategory: (Category) -> Unit, onRestoreCategory: (Category) -> Unit,
onDeleteCategoryPermanent: (Category) -> Unit onDeleteCategoryPermanent: (Category) -> Unit
) { ) {
var searchQuery by remember { mutableStateOf("") }
// Filter kategori dan note yang dihapus // Filter kategori dan note yang dihapus
val deletedCategories = categories.filter { it.isDeleted } val deletedCategories = categories.filter { it.isDeleted }
val deletedNotes = notes.filter { it.isDeleted } val deletedNotes = notes.filter { it.isDeleted }
// Filter berdasarkan search query // Filter berdasarkan search query dari ModernTopBar
val filteredCategories = if (searchQuery.isBlank()) { val filteredCategories = if (searchQuery.isBlank()) {
deletedCategories deletedCategories
} else { } else {
@ -70,50 +58,6 @@ fun TrashScreen(
} }
Column(modifier = Modifier.fillMaxSize()) { Column(modifier = Modifier.fillMaxSize()) {
// Search Bar
OutlinedTextField(
value = searchQuery,
onValueChange = { searchQuery = it },
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 12.dp),
placeholder = {
Text(
"Cari di sampah...",
color = Color(0xFF64748B)
)
},
leadingIcon = {
Icon(
Icons.Default.Search,
contentDescription = null,
tint = Color(0xFF64748B)
)
},
trailingIcon = {
if (searchQuery.isNotEmpty()) {
IconButton(onClick = { searchQuery = "" }) {
Icon(
Icons.Default.Clear,
contentDescription = "Clear",
tint = Color(0xFF64748B)
)
}
}
},
shape = RoundedCornerShape(12.dp),
colors = OutlinedTextFieldDefaults.colors(
focusedContainerColor = Color(0xFF1E293B),
unfocusedContainerColor = Color(0xFF1E293B),
focusedBorderColor = Color(0xFF6366F1),
unfocusedBorderColor = Color(0xFF334155),
focusedTextColor = Color.White,
unfocusedTextColor = Color.White,
cursorColor = Color(0xFF6366F1)
),
singleLine = true
)
// Content // Content
if (filteredCategories.isEmpty() && filteredNotes.isEmpty()) { if (filteredCategories.isEmpty() && filteredNotes.isEmpty()) {
if (searchQuery.isNotEmpty()) { if (searchQuery.isNotEmpty()) {
@ -134,6 +78,7 @@ fun TrashScreen(
contentPadding = PaddingValues( contentPadding = PaddingValues(
start = 16.dp, start = 16.dp,
end = 16.dp, end = 16.dp,
top = 8.dp,
bottom = 100.dp bottom = 100.dp
), ),
verticalArrangement = Arrangement.spacedBy(12.dp) verticalArrangement = Arrangement.spacedBy(12.dp)

View File

@ -1,3 +1,3 @@
<resources> <resources>
<string name="app_name">AI Notes</string> <string name="app_name">NotesAI</string>
</resources> </resources>

Binary file not shown.