You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 2c63c53
Browse filesBrowse the repository at this point in the historyBrowse files
feat: implement note list sorting and bump version to 8.5.9
- Add note list sorting functionality supporting 6 sort options across last modified date, creation date, and title (ascending/descending).
- Support reactive query sorting in SQLDelight and Room via `NoteDAO.noteSortFlow`.
- Introduce `SortField`, `SortOrder`, `NoteSort` domain models, `NoteSortUseCase`, and `PreferencesRepo` using `multiplatform-settings` for persistence.
- Add `SortMenuButton` and `SortOption` composables to `MainScreen` top app bar and update `NoteItem` to dynamically render creation and modification timestamps with icons.
- Add multiplatform Compose UI tests (`SortNotesTestCase`), database integration tests, ViewModel, and repository unit tests.
- Bump application version to 8.5.9 across Android, Desktop, and iOS targets.
- Update Gradle wrapper to 9.8.2 and update core dependencies including AGP, KSP, and Firebase.
Copy file name to clipboardExpand all lines: CHANGELOG.md
+29Lines changed: 29 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,6 +5,35 @@ All notable changes to this project will be documented in this file.
5
5
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
8
+
## [8.5.9] - 2026-11-02
9
+
10
+
### Features
11
+
- Add note list sorting functionality with 6 sort options: by last modified date (descending/ascending), creation date (descending/ascending), and title (A–Z / Z–A)
12
+
- Support reactive sorting updates in SQLite queries across both SQLDelight (`Note.sq`) and Room (`@RawQuery`) via `NoteDAO.noteSortFlow`
13
+
- Add `SortMenuButton` and `SortOption` to `MainScreen` top app bar with English and Russian localizations
14
+
- Add smart date display in `NoteItem`: show single creation timestamp with `CalendarToday` icon when unmodified, or both creation (`AddCircleOutline`) and modification (`Edit`) timestamps side-by-side when modified
15
+
- Persist sorting preferences across app restarts via `PreferencesRepo` / `PreferencesRepoImpl` backed by `multiplatform-settings`
16
+
17
+
### Refactoring
18
+
- Centralize note sorting domain models (`NoteSort`, `SortField`, `SortOrder`) and introduce `NoteSortUseCase` to synchronize sort preferences without coupling presentation to persistence
19
+
- Optimize and deduplicate SQLDelight `pagedNotes` query by computing sort field values within a subquery
20
+
- Place `companion object` at the bottom of Kotlin classes/interfaces across the codebase
21
+
- Simplify syntax in DAO, ViewModel, and UI: import companion members directly (`noteSortFlow`), inline redundant single-use variables, and use single-expression bodies for composable wrappers
22
+
23
+
### Tests
24
+
- Add `SortNotesTestCase` multiplatform Compose UI tests covering sorting flows on Android, Desktop, iOS, and Web
25
+
- Add `NoteSortingTest` (SQLDelight) and `RoomDatabaseIntegrationTest` (Room) verifying dynamic sorting order
26
+
- Add `MainViewModelTest` and `PreferencesRepoImplTest` unit test coverage for sort state management and persistence
27
+
28
+
### Documentation
29
+
- Document code style rules in `CONTRIBUTING.md` for companion object placement, companion member imports, local variable inlining, expression bodies, and component call-site parameter ordering
30
+
- Update `docs/ROADMAP.md` (mark Milestone 1.1 §2 Note Sorting complete and add pre-formatted date strings to technical debt)
31
+
- Update module `README.md` files for sorting domain models, presentation state, and UI components
32
+
33
+
### Chores
34
+
- Update Gradle wrapper to 9.8.2
35
+
- Update dependencies in `libs.versions.toml`: AGP (9.5.0), KSP (2.3.13), Firebase (35.1.0), AndroidX DataStore (1.3.0), Navigation (2.10.0), Tracing (2.0.5), kotlinx-serialization (1.12.0), and SQLCipher for Android (4.20.0)
Copy file name to clipboardExpand all lines: CONTRIBUTING.md
+16-10Lines changed: 16 additions & 10 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -84,6 +84,7 @@ kotlin.code.style=official
84
84
- No wildcard imports (except in tests)
85
85
- Organized and optimized
86
86
- Android Studio organize imports: ⌥⌘O (Mac) / Ctrl+Alt+O (Windows)
87
+
-**Remove unused imports** promptly; never leave orphaned imports after refactoring.
87
88
88
89
#### Blank Lines
89
90
- One blank line between functions
@@ -120,6 +121,9 @@ kotlin.code.style=official
120
121
over an inverted `if (!success) ... else ...` ladder.
121
122
-**Collapse trivial `viewModelScope.launch` blocks to a single line** when their body is one statement
122
123
(e.g. `private fun cancel() = viewModelScope.launch { router.popBackStack() }`).
124
+
-**Inline trivial, single-use local variables** directly into call sites or data class constructors
125
+
(e.g. `NoteListResult.Success(..., noteSort = NoteDAO.noteSortFlow.value)`) instead of declaring an
126
+
intermediate `val` that is immediately consumed only once.
123
127
-**Compose state edits**: prefer a single `mutableStateFlow.update { it.copy(...) }` that sets every field
124
128
affected by an event over multiple chained `update` calls. It keeps the resulting state atomic and
125
129
makes the visible transition obvious.
@@ -150,30 +154,30 @@ kotlin.code.style=official
150
154
151
155
```kotlin
152
156
classMyClass {
153
-
// 1. Companion object
154
-
companionobject {
155
-
constvalCONSTANT="value"
156
-
}
157
-
158
-
// 2. Properties
157
+
// 1. Properties
159
158
privateval privateProperty:String
160
159
val publicProperty:String
161
160
162
-
//3. Init blocks
161
+
//2. Init blocks
163
162
init {
164
163
// Initialization
165
164
}
166
165
167
-
//4. Secondary constructors
166
+
//3. Secondary constructors
168
167
constructor(param:String) :this(param, "default")
169
168
170
-
//5. Functions (public first, then private)
169
+
//4. Functions (public first, then private)
171
170
funpublicFunction() { }
172
171
173
172
privatefunprivateFunction() { }
174
173
175
-
//6. Nested classes/objects
174
+
//5. Nested classes/objects
176
175
innerclassNestedClass
176
+
177
+
// 6. Companion object (at the very bottom of the class or interface)
178
+
companionobject {
179
+
constvalCONSTANT="value"
180
+
}
177
181
}
178
182
```
179
183
@@ -280,6 +284,8 @@ private fun ScreenContent(
280
284
5.**Remember wisely**: Use `remember` for expensive calculations
281
285
6.**Keys in lists**: Provide stable keys for LazyColumn/LazyRow
282
286
7.**Adaptive drag handle**: Prefer method references for pane expansion, e.g. `paneExpansionDragHandle = ThreePaneScaffoldScope::VerticalPaneExpansionDragHandle` (use a lambda in Kotlin/Wasm actuals to avoid the current composable function reference compiler issue).
287
+
8.**Expression body for single-root composables**: Prefer single-expression syntax (`= Row(...) { ... }`, `= Column(...) { ... }`) for private helper composables or wrappers whose entire body is a single root layout composable, avoiding redundant curly braces and reducing indentation.
288
+
9.**Call site parameter ordering for leaf composables**: When calling standard visual leaf composables (such as `Icon`), place `modifier` first among named arguments (e.g. `Icon(modifier = Modifier.size(14.dp), imageVector = ..., contentDescription = ...)`) so that sizing and layout constraints are immediately visible before content properties.
0 commit comments