@@ -21,7 +20,7 @@
[

](https://f-droid.org/packages/com.mhss.app.mybrain)
-[

](https://github.com/mhss1/MyBrain/releases/latest)
From ed9f94b15e37e78243ebdc95ac35927b9a76c7c4 Mon Sep 17 00:00:00 2001
From: Mohamed
Date: Sun, 5 May 2024 17:46:07 +0300
Subject: [PATCH 29/36] Add internet permission
---
app/src/main/AndroidManifest.xml | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 9c4981c8..a658ee89 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,9 +6,12 @@
-
+
+
+
+
Date: Sun, 5 May 2024 17:48:03 +0300
Subject: [PATCH 30/36] Update description remove no internet text
---
README.md | 2 +-
fastlane/metadata/android/en-US/full_description.txt | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 39b19fbc..cb68096c 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@
height="80">](https://github.com/mhss1/MyBrain/releases/latest)
## Features
-- Private with no data collection and no internet permission at all.
+- Private with no data collection at all.
- Create tasks with priority, sub-tasks, description and due date and reminders.
- Create Notes that supports markdown which enables you to use Headers, lists, links etc..
- Record your mood daily and view your mood summary with beautiful graphs.
diff --git a/fastlane/metadata/android/en-US/full_description.txt b/fastlane/metadata/android/en-US/full_description.txt
index ba7c1803..73376d44 100644
--- a/fastlane/metadata/android/en-US/full_description.txt
+++ b/fastlane/metadata/android/en-US/full_description.txt
@@ -1,7 +1,7 @@
My Brain is an Open source, All in one productivity app for Tasks, Notes, Calendar, Diary and Bookmarks.
Features :
-- Private with no data collection and no internet permission at all.
+- Private with no data collection at all.
- Create tasks with priority, sub-tasks, description and due date and reminders.
- Create Notes that supports markdown which enables you to use Headers, lists, links etc..
- Record your mood daily and view your mood summary with beautiful graphs.
From 4fb0cdb9d6117ede634c5092b70cd6e64dc50738 Mon Sep 17 00:00:00 2001
From: Mohamed
Date: Sun, 5 May 2024 19:13:39 +0300
Subject: [PATCH 31/36] Remove MIGRATION_4_5 and revert migrated parts back
---
.../app/mybrain/data/local/MyBrainDatabase.kt | 2 +-
.../app/mybrain/data/local/dao/NoteDao.kt | 9 ++--
.../data/local/migrations/RoomMigrations.kt | 54 -------------------
.../data/repository/NoteRepositoryImpl.kt | 10 +++-
.../java/com/mhss/app/mybrain/di/AppModule.kt | 3 +-
.../com/mhss/app/mybrain/domain/model/Note.kt | 4 +-
.../app/mybrain/domain/model/NoteFolder.kt | 5 +-
.../domain/repository/NoteRepository.kt | 4 +-
.../notes/GetAllNoteFoldersUseCase.kt | 2 +-
.../use_case/notes/GetNoteFolderUseCase.kt | 10 ++++
.../use_case/notes/GetNotesByFolderUseCase.kt | 2 +-
.../use_case/notes/NoteFolderDetailsScreen.kt | 6 +--
.../mybrain/presentation/main/MainActivity.kt | 8 +--
.../presentation/notes/NoteDetailsScreen.kt | 16 +++---
.../mybrain/presentation/notes/NoteEvent.kt | 4 +-
.../mybrain/presentation/notes/NotesScreen.kt | 7 +--
.../presentation/notes/NotesViewModel.kt | 13 ++---
17 files changed, 64 insertions(+), 95 deletions(-)
create mode 100644 app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/GetNoteFolderUseCase.kt
diff --git a/app/src/main/java/com/mhss/app/mybrain/data/local/MyBrainDatabase.kt b/app/src/main/java/com/mhss/app/mybrain/data/local/MyBrainDatabase.kt
index 4387827b..47d23f6b 100644
--- a/app/src/main/java/com/mhss/app/mybrain/data/local/MyBrainDatabase.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/data/local/MyBrainDatabase.kt
@@ -9,7 +9,7 @@ import com.mhss.app.mybrain.domain.model.*
@Database(
entities = [Note::class, Task::class, DiaryEntry::class, Bookmark::class, Alarm::class, NoteFolder::class],
- version = 5
+ version = 4
)
@TypeConverters(DBConverters::class)
abstract class MyBrainDatabase: RoomDatabase() {
diff --git a/app/src/main/java/com/mhss/app/mybrain/data/local/dao/NoteDao.kt b/app/src/main/java/com/mhss/app/mybrain/data/local/dao/NoteDao.kt
index 5ada61a5..85f80e96 100644
--- a/app/src/main/java/com/mhss/app/mybrain/data/local/dao/NoteDao.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/data/local/dao/NoteDao.kt
@@ -17,8 +17,8 @@ interface NoteDao {
@Query("SELECT * FROM notes WHERE title LIKE '%' || :query || '%' OR content LIKE '%' || :query || '%'")
suspend fun getNotesByTitle(query: String): List
- @Query("SELECT * FROM notes WHERE folder_id = :folderName")
- fun getNotesByFolder(folderName: String): Flow>
+ @Query("SELECT * FROM notes WHERE folder_id = :folderId")
+ fun getNotesByFolder(folderId: Int): Flow>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertNote(note: Note)
@@ -36,7 +36,7 @@ interface NoteDao {
suspend fun insertNoteFolder(folder: NoteFolder)
@Insert(onConflict = OnConflictStrategy.IGNORE)
- suspend fun insertNoteFolders(folders: List)
+ suspend fun insertNoteFolders(folders: List): List
@Update
suspend fun updateNoteFolder(folder: NoteFolder)
@@ -46,4 +46,7 @@ interface NoteDao {
@Query("SELECT * FROM note_folders")
fun getAllNoteFolders(): Flow>
+
+ @Query("SELECT * FROM note_folders WHERE id = :folderId")
+ fun getNoteFolder(folderId: Int): NoteFolder?
}
\ No newline at end of file
diff --git a/app/src/main/java/com/mhss/app/mybrain/data/local/migrations/RoomMigrations.kt b/app/src/main/java/com/mhss/app/mybrain/data/local/migrations/RoomMigrations.kt
index cff6e7f4..3f0f7468 100644
--- a/app/src/main/java/com/mhss/app/mybrain/data/local/migrations/RoomMigrations.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/data/local/migrations/RoomMigrations.kt
@@ -27,57 +27,3 @@ val MIGRATION_3_4 = object : Migration(3, 4) {
db.execSQL("ALTER TABLE tasks ADD COLUMN frequency_amount INTEGER NOT NULL DEFAULT 1")
}
}
-
-val MIGRATION_4_5 = object : Migration(4, 5) {
- override fun migrate(db: SupportSQLiteDatabase) {
-
- db.execSQL("CREATE TABLE note_folders_temp (name TEXT PRIMARY KEY NOT NULL)")
- db.execSQL("INSERT INTO note_folders_temp (name) SELECT DISTINCT name FROM note_folders")
-
- db.execSQL(
- """
- CREATE TABLE notes_temp (
- title TEXT NOT NULL,
- content TEXT NOT NULL,
- created_date INTEGER NOT NULL,
- updated_date INTEGER NOT NULL,
- pinned INTEGER NOT NULL,
- folder_id TEXT,
- id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
- FOREIGN KEY (folder_id) REFERENCES note_folders_temp (name) ON UPDATE NO ACTION ON DELETE CASCADE
- )
- """
- )
-
- db.execSQL(
- """
- INSERT INTO notes_temp (title, content, created_date, updated_date, pinned, folder_id, id)
- SELECT n.title, n.content, n.created_date, n.updated_date, n.pinned, nf.name, n.id
- FROM notes n
- LEFT JOIN note_folders nf ON n.folder_id = nf.id
- """
- )
-
- db.execSQL("DROP TABLE notes")
- db.execSQL("DROP TABLE note_folders")
- db.execSQL("ALTER TABLE note_folders_temp RENAME TO note_folders")
-
- db.execSQL(
- """
- CREATE TABLE notes (
- title TEXT NOT NULL,
- content TEXT NOT NULL,
- created_date INTEGER NOT NULL,
- updated_date INTEGER NOT NULL,
- pinned INTEGER NOT NULL,
- folder_id TEXT,
- id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
- FOREIGN KEY (folder_id) REFERENCES note_folders (name) ON UPDATE NO ACTION ON DELETE CASCADE
- )
- """
- )
- db.execSQL("INSERT INTO notes (title, content, created_date, updated_date, pinned, folder_id, id) SELECT * FROM notes_temp")
-
- db.execSQL("DROP TABLE notes_temp")
- }
-}
diff --git a/app/src/main/java/com/mhss/app/mybrain/data/repository/NoteRepositoryImpl.kt b/app/src/main/java/com/mhss/app/mybrain/data/repository/NoteRepositoryImpl.kt
index 4d60714b..543076b5 100644
--- a/app/src/main/java/com/mhss/app/mybrain/data/repository/NoteRepositoryImpl.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/data/repository/NoteRepositoryImpl.kt
@@ -30,8 +30,8 @@ class NoteRepositoryImpl(
}
}
- override fun getNotesByFolder(folderName: String): Flow> {
- return noteDao.getNotesByFolder(folderName)
+ override fun getNotesByFolder(folderId: Int): Flow> {
+ return noteDao.getNotesByFolder(folderId)
}
override suspend fun addNote(note: Note) {
@@ -73,4 +73,10 @@ class NoteRepositoryImpl(
override fun getAllNoteFolders(): Flow> {
return noteDao.getAllNoteFolders()
}
+
+ override suspend fun getNoteFolder(folderId: Int): NoteFolder? {
+ return withContext(Dispatchers.IO) {
+ noteDao.getNoteFolder(folderId)
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/mhss/app/mybrain/di/AppModule.kt b/app/src/main/java/com/mhss/app/mybrain/di/AppModule.kt
index 82f4131e..a8a20aa1 100644
--- a/app/src/main/java/com/mhss/app/mybrain/di/AppModule.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/di/AppModule.kt
@@ -9,7 +9,6 @@ import com.mhss.app.mybrain.data.local.dao.*
import com.mhss.app.mybrain.data.local.migrations.MIGRATION_1_2
import com.mhss.app.mybrain.data.local.migrations.MIGRATION_2_3
import com.mhss.app.mybrain.data.local.migrations.MIGRATION_3_4
-import com.mhss.app.mybrain.data.local.migrations.MIGRATION_4_5
import com.mhss.app.mybrain.data.repository.*
import com.mhss.app.mybrain.domain.repository.*
import dagger.Module
@@ -31,7 +30,7 @@ object AppModule {
context,
MyBrainDatabase::class.java,
MyBrainDatabase.DATABASE_NAME
- ).addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5)
+ ).addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4)
.build()
@Singleton
diff --git a/app/src/main/java/com/mhss/app/mybrain/domain/model/Note.kt b/app/src/main/java/com/mhss/app/mybrain/domain/model/Note.kt
index d0f29325..393322d2 100644
--- a/app/src/main/java/com/mhss/app/mybrain/domain/model/Note.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/domain/model/Note.kt
@@ -11,7 +11,7 @@ import kotlinx.serialization.Serializable
foreignKeys = [
ForeignKey(
entity = NoteFolder::class,
- parentColumns = ["name"],
+ parentColumns = ["id"],
childColumns = ["folder_id"],
onDelete = ForeignKey.CASCADE,
onUpdate = ForeignKey.NO_ACTION
@@ -28,7 +28,7 @@ data class Note(
val updatedDate: Long = 0L,
val pinned: Boolean = false,
@ColumnInfo(name = "folder_id")
- val folderId: String? = null,
+ val folderId: Int? = null,
@PrimaryKey(autoGenerate = true)
val id: Int = 0,
)
diff --git a/app/src/main/java/com/mhss/app/mybrain/domain/model/NoteFolder.kt b/app/src/main/java/com/mhss/app/mybrain/domain/model/NoteFolder.kt
index 275dd4da..fe96a3fb 100644
--- a/app/src/main/java/com/mhss/app/mybrain/domain/model/NoteFolder.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/domain/model/NoteFolder.kt
@@ -9,6 +9,7 @@ import kotlinx.serialization.Serializable
)
@Serializable
data class NoteFolder(
- @PrimaryKey(autoGenerate = false)
- val name: String
+ val name: String,
+ @PrimaryKey(autoGenerate = true)
+ val id: Int = 0
)
diff --git a/app/src/main/java/com/mhss/app/mybrain/domain/repository/NoteRepository.kt b/app/src/main/java/com/mhss/app/mybrain/domain/repository/NoteRepository.kt
index 83bdfa39..5d4c75aa 100644
--- a/app/src/main/java/com/mhss/app/mybrain/domain/repository/NoteRepository.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/domain/repository/NoteRepository.kt
@@ -12,7 +12,7 @@ interface NoteRepository {
suspend fun searchNotes(query: String): List
- fun getNotesByFolder(folderName: String): Flow>
+ fun getNotesByFolder(folderId: Int): Flow>
suspend fun addNote(note: Note)
@@ -28,4 +28,6 @@ interface NoteRepository {
fun getAllNoteFolders(): Flow>
+ suspend fun getNoteFolder(folderId: Int): NoteFolder?
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/GetAllNoteFoldersUseCase.kt b/app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/GetAllNoteFoldersUseCase.kt
index 0dda0f0f..83229d68 100644
--- a/app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/GetAllNoteFoldersUseCase.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/GetAllNoteFoldersUseCase.kt
@@ -6,5 +6,5 @@ import javax.inject.Inject
class GetAllNoteFoldersUseCase @Inject constructor(
private val repository: NoteRepository
) {
- suspend operator fun invoke() = repository.getAllNoteFolders()
+ operator fun invoke() = repository.getAllNoteFolders()
}
\ No newline at end of file
diff --git a/app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/GetNoteFolderUseCase.kt b/app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/GetNoteFolderUseCase.kt
new file mode 100644
index 00000000..dc1c9363
--- /dev/null
+++ b/app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/GetNoteFolderUseCase.kt
@@ -0,0 +1,10 @@
+package com.mhss.app.mybrain.domain.use_case.notes
+
+import com.mhss.app.mybrain.domain.repository.NoteRepository
+import javax.inject.Inject
+
+class GetNoteFolderUseCase @Inject constructor(
+ private val repository: NoteRepository
+) {
+ suspend operator fun invoke(folderId: Int) = repository.getNoteFolder(folderId)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/GetNotesByFolderUseCase.kt b/app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/GetNotesByFolderUseCase.kt
index 58b3e654..30abcec5 100644
--- a/app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/GetNotesByFolderUseCase.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/GetNotesByFolderUseCase.kt
@@ -9,7 +9,7 @@ import javax.inject.Inject
class GetNotesByFolderUseCase @Inject constructor(
private val notesRepository: NoteRepository
) {
- operator fun invoke(folderName: String, order: Order) = notesRepository.getNotesByFolder(folderName).map { list ->
+ operator fun invoke(id: Int, order: Order) = notesRepository.getNotesByFolder(id).map { list ->
when (order.orderType) {
is OrderType.ASC -> {
when (order) {
diff --git a/app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/NoteFolderDetailsScreen.kt b/app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/NoteFolderDetailsScreen.kt
index 3ec02563..b1ba6a02 100644
--- a/app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/NoteFolderDetailsScreen.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/NoteFolderDetailsScreen.kt
@@ -37,7 +37,7 @@ import com.mhss.app.mybrain.util.settings.ItemView
@Composable
fun NoteFolderDetailsScreen(
navController: NavHostController,
- name: String,
+ id: Int,
viewModel: NotesViewModel = hiltViewModel()
) {
val uiState = viewModel.notesUiState
@@ -47,7 +47,7 @@ fun NoteFolderDetailsScreen(
var openEditDialog by remember { mutableStateOf(false) }
val scaffoldState = rememberScaffoldState()
- LaunchedEffect(true) {viewModel.onEvent(NoteEvent.GetFolderNotes(name)) }
+ LaunchedEffect(true) {viewModel.onEvent(NoteEvent.GetFolderNotes(id)) }
LaunchedEffect(uiState) {
if (viewModel.notesUiState.navigateUp) {
navController.popBackStack(route = Screen.NotesScreen.route, inclusive = false)
@@ -90,7 +90,7 @@ fun NoteFolderDetailsScreen(
"${-1}"
).replace(
"{${Constants.FOLDER_ID}}",
- name
+ "$id"
)
)
},
diff --git a/app/src/main/java/com/mhss/app/mybrain/presentation/main/MainActivity.kt b/app/src/main/java/com/mhss/app/mybrain/presentation/main/MainActivity.kt
index 4421bb6b..8cfcf0bd 100644
--- a/app/src/main/java/com/mhss/app/mybrain/presentation/main/MainActivity.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/presentation/main/MainActivity.kt
@@ -179,14 +179,14 @@ class MainActivity : AppCompatActivity() {
type = NavType.IntType
},
navArgument(Constants.FOLDER_ID) {
- type = NavType.StringType
+ type = NavType.IntType
}
),
) {
NoteDetailsScreen(
navController,
it.arguments?.getInt(Constants.NOTE_ID_ARG) ?: -1,
- it.arguments?.getString(Constants.FOLDER_ID) ?: ""
+ it.arguments?.getInt(Constants.FOLDER_ID) ?: -1
)
}
composable(Screen.NoteSearchScreen.route) {
@@ -260,12 +260,12 @@ class MainActivity : AppCompatActivity() {
composable(
Screen.NoteFolderDetailsScreen.route,
arguments = listOf(navArgument(Constants.FOLDER_ID) {
- type = NavType.StringType
+ type = NavType.IntType
})
) {
NoteFolderDetailsScreen(
navController = navController,
- it.arguments?.getString(Constants.FOLDER_ID) ?: ""
+ it.arguments?.getInt(Constants.FOLDER_ID) ?: -1
)
}
composable(Screen.ImportExportScreen.route) {
diff --git a/app/src/main/java/com/mhss/app/mybrain/presentation/notes/NoteDetailsScreen.kt b/app/src/main/java/com/mhss/app/mybrain/presentation/notes/NoteDetailsScreen.kt
index e14643ca..b6e0eef5 100644
--- a/app/src/main/java/com/mhss/app/mybrain/presentation/notes/NoteDetailsScreen.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/presentation/notes/NoteDetailsScreen.kt
@@ -33,12 +33,12 @@ import dev.jeziellago.compose.markdowntext.MarkdownText
fun NoteDetailsScreen(
navController: NavHostController,
noteId: Int,
- folderId: String,
+ folderId: Int,
viewModel: NotesViewModel = hiltViewModel()
) {
LaunchedEffect(true) {
if (noteId != -1) viewModel.onEvent(NoteEvent.GetNote(noteId))
- if (folderId.isNotBlank()) viewModel.onEvent(NoteEvent.GetFolder(folderId))
+ if (folderId != -1) viewModel.onEvent(NoteEvent.GetFolder(folderId))
}
val state = viewModel.notesUiState
val scaffoldState = rememberScaffoldState()
@@ -85,7 +85,7 @@ fun NoteDetailsScreen(
title = title,
content = content,
pinned = pinned,
- folderId = folder?.name
+ folderId = folder?.id
),
state.note,
onNotChanged = {
@@ -101,7 +101,7 @@ fun NoteDetailsScreen(
state.note.copy(
title = title,
content = content,
- folderId = folder?.name
+ folderId = folder?.id
)
)
)
@@ -112,7 +112,7 @@ fun NoteDetailsScreen(
title = title,
content = content,
pinned = pinned,
- folderId = folder?.name
+ folderId = folder?.id
)
)
)
@@ -318,7 +318,7 @@ fun NoteDetailsScreen(
folder = it
openFolderDialog = false
}
- .background(if (folder?.name == it.name) MaterialTheme.colors.onBackground else Color.Transparent),
+ .background(if (folder?.id == it.id) MaterialTheme.colors.onBackground else Color.Transparent),
verticalAlignment = Alignment.CenterVertically
) {
Icon(
@@ -329,7 +329,7 @@ fun NoteDetailsScreen(
top = 8.dp,
bottom = 8.dp
),
- tint = if (folder?.name == it.name) MaterialTheme.colors.background else MaterialTheme.colors.onBackground
+ tint = if (folder?.id == it.id) MaterialTheme.colors.background else MaterialTheme.colors.onBackground
)
Spacer(Modifier.width(8.dp))
Text(
@@ -340,7 +340,7 @@ fun NoteDetailsScreen(
bottom = 8.dp
),
style = MaterialTheme.typography.body1,
- color = if (folder?.name == it.name) MaterialTheme.colors.background else MaterialTheme.colors.onBackground
+ color = if (folder?.id == it.id) MaterialTheme.colors.background else MaterialTheme.colors.onBackground
)
}
}
diff --git a/app/src/main/java/com/mhss/app/mybrain/presentation/notes/NoteEvent.kt b/app/src/main/java/com/mhss/app/mybrain/presentation/notes/NoteEvent.kt
index 39ffa16a..869509b0 100644
--- a/app/src/main/java/com/mhss/app/mybrain/presentation/notes/NoteEvent.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/presentation/notes/NoteEvent.kt
@@ -19,6 +19,6 @@ sealed class NoteEvent {
data class CreateFolder(val folder: NoteFolder): NoteEvent()
data class DeleteFolder(val folder: NoteFolder): NoteEvent()
data class UpdateFolder(val folder: NoteFolder): NoteEvent()
- data class GetFolderNotes(val name: String): NoteEvent()
- data class GetFolder(val name: String): NoteEvent()
+ data class GetFolderNotes(val id: Int): NoteEvent()
+ data class GetFolder(val id: Int): NoteEvent()
}
\ No newline at end of file
diff --git a/app/src/main/java/com/mhss/app/mybrain/presentation/notes/NotesScreen.kt b/app/src/main/java/com/mhss/app/mybrain/presentation/notes/NotesScreen.kt
index 2e95b61d..d5384a86 100644
--- a/app/src/main/java/com/mhss/app/mybrain/presentation/notes/NotesScreen.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/presentation/notes/NotesScreen.kt
@@ -17,6 +17,7 @@ import androidx.compose.foundation.lazy.staggeredgrid.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.runtime.*
+import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@@ -43,7 +44,7 @@ fun NotesScreen(
) {
val uiState = viewModel.notesUiState
var orderSettingsVisible by remember { mutableStateOf(false) }
- var selectedTab by remember { mutableIntStateOf(0) }
+ var selectedTab by rememberSaveable { mutableIntStateOf(0) }
var openCreateFolderDialog by remember { mutableStateOf(false) }
val scaffoldState = rememberScaffoldState()
LaunchedEffect(uiState.error) {
@@ -77,7 +78,7 @@ fun NotesScreen(
navController.navigate(
Screen.NoteDetailsScreen.route.replace(
"{${Constants.NOTE_ID_ARG}}",
- "${-1}"
+ "-1"
).replace(
"{${Constants.FOLDER_ID}}",
"-1"
@@ -217,7 +218,7 @@ fun NotesScreen(
navController.navigate(
Screen.NoteFolderDetailsScreen.route.replace(
"{${Constants.FOLDER_ID}}",
- it.name
+ "${it.id}"
)
)
}
diff --git a/app/src/main/java/com/mhss/app/mybrain/presentation/notes/NotesViewModel.kt b/app/src/main/java/com/mhss/app/mybrain/presentation/notes/NotesViewModel.kt
index da7c2813..1400f837 100644
--- a/app/src/main/java/com/mhss/app/mybrain/presentation/notes/NotesViewModel.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/presentation/notes/NotesViewModel.kt
@@ -36,6 +36,7 @@ class NotesViewModel @Inject constructor(
private val deleteFolder: DeleteNoteFolderUseCass,
private val updateFolder: UpdateNoteFolderUseCass,
private val getFolderNotes: GetNotesByFolderUseCase,
+ private val getNoteFolder: GetNoteFolderUseCase
) : ViewModel() {
var notesUiState by mutableStateOf((UiState()))
@@ -87,7 +88,7 @@ class NotesViewModel @Inject constructor(
}
is NoteEvent.GetNote -> viewModelScope.launch {
val note = getNote(event.noteId)
- val folder = getAllFolders().first().firstOrNull { it.name == note.folderId }
+ val folder = getAllFolders().first().firstOrNull { it.id == note.folderId }
notesUiState = notesUiState.copy(note = note, folder = folder, readingMode = true)
}
is NoteEvent.SearchNotes -> viewModelScope.launch {
@@ -148,10 +149,10 @@ class NotesViewModel @Inject constructor(
}
}
is NoteEvent.GetFolderNotes -> {
- getNotesFromFolder(event.name, notesUiState.notesOrder)
+ getNotesFromFolder(event.id, notesUiState.notesOrder)
}
is NoteEvent.GetFolder -> viewModelScope.launch {
- val folder = getAllFolders().first().firstOrNull { it.name == event.name }
+ val folder = getNoteFolder(event.id)
notesUiState = notesUiState.copy(folder = folder)
}
}
@@ -182,11 +183,11 @@ class NotesViewModel @Inject constructor(
}.launchIn(viewModelScope)
}
- private fun getNotesFromFolder(name: String, order: Order) {
+ private fun getNotesFromFolder(id: Int, order: Order) {
getFolderNotesJob?.cancel()
- getFolderNotesJob = getFolderNotes(name, order)
+ getFolderNotesJob = getFolderNotes(id, order)
.onEach { notes ->
- val noteFolder = getAllFolders().first().firstOrNull { it.name == name }
+ val noteFolder = getNoteFolder(id)
notesUiState = notesUiState.copy(
folderNotes = notes,
folder = noteFolder
From 06f357200477bd97c14bb55427621e2d36292347 Mon Sep 17 00:00:00 2001
From: Mohamed
Date: Sun, 5 May 2024 23:33:44 +0300
Subject: [PATCH 32/36] Fix import notes with folders
---
.../data/backup/RoomBackupRepositoryImpl.kt | 16 +++++++++++++---
.../mhss/app/mybrain/data/local/dao/NoteDao.kt | 5 ++++-
.../data/repository/NoteRepositoryImpl.kt | 4 ++--
.../mybrain/domain/repository/NoteRepository.kt | 2 +-
.../domain/use_case/notes/GetAllNotesUseCase.kt | 2 +-
5 files changed, 21 insertions(+), 8 deletions(-)
diff --git a/app/src/main/java/com/mhss/app/mybrain/data/backup/RoomBackupRepositoryImpl.kt b/app/src/main/java/com/mhss/app/mybrain/data/backup/RoomBackupRepositoryImpl.kt
index 1094ab48..9728544d 100644
--- a/app/src/main/java/com/mhss/app/mybrain/data/backup/RoomBackupRepositoryImpl.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/data/backup/RoomBackupRepositoryImpl.kt
@@ -40,7 +40,7 @@ class RoomBackupRepositoryImpl @Inject constructor(
val pickedDir = DocumentFile.fromTreeUri(context, directoryUri)
val destination = pickedDir!!.createFile("application/json", fileName)
- val notes = notesDao.getAllNotes().first().map {
+ val notes = notesDao.getAllNotes().map {
it.copy(id = 0)
}
val noteFolders = notesDao.getAllNoteFolders().first()
@@ -85,8 +85,18 @@ class RoomBackupRepositoryImpl @Inject constructor(
val backupJson = inputStream?.bufferedReader().use { it?.readText() }
?: return@withContext false
val backupData = Json.decodeFromString(backupJson)
- notesDao.insertNoteFolders(backupData.noteFolders)
- notesDao.insertNotes(backupData.notes)
+ val noteFolders = backupData.noteFolders
+ val oldNoteFolderIds = noteFolders.map { it.id }
+ val newNoteFolderIds = notesDao.insertNoteFolders(noteFolders.map { it.copy(id = 0) })
+ if (newNoteFolderIds.size != oldNoteFolderIds.size) return@withContext false
+ val notes = backupData.notes.map { note ->
+ if (note.folderId != null) {
+ note.copy(
+ folderId = newNoteFolderIds[oldNoteFolderIds.indexOf(note.folderId)].toInt()
+ )
+ } else note
+ }
+ notesDao.insertNotes(notes)
tasksDao.insertTasks(backupData.tasks)
diaryDao.insertEntries(backupData.diary)
bookmarksDao.insertBookmarks(backupData.bookmarks)
diff --git a/app/src/main/java/com/mhss/app/mybrain/data/local/dao/NoteDao.kt b/app/src/main/java/com/mhss/app/mybrain/data/local/dao/NoteDao.kt
index 85f80e96..fed45abf 100644
--- a/app/src/main/java/com/mhss/app/mybrain/data/local/dao/NoteDao.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/data/local/dao/NoteDao.kt
@@ -9,7 +9,10 @@ import kotlinx.coroutines.flow.Flow
interface NoteDao {
@Query("SELECT * FROM notes WHERE folder_id IS NULL")
- fun getAllNotes(): Flow>
+ fun getAllFolderlessNotes(): Flow>
+
+ @Query("SELECT * FROM notes")
+ suspend fun getAllNotes(): List
@Query("SELECT * FROM notes WHERE id = :id")
suspend fun getNote(id: Int): Note
diff --git a/app/src/main/java/com/mhss/app/mybrain/data/repository/NoteRepositoryImpl.kt b/app/src/main/java/com/mhss/app/mybrain/data/repository/NoteRepositoryImpl.kt
index 543076b5..bd979b5b 100644
--- a/app/src/main/java/com/mhss/app/mybrain/data/repository/NoteRepositoryImpl.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/data/repository/NoteRepositoryImpl.kt
@@ -14,8 +14,8 @@ class NoteRepositoryImpl(
private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO
) : NoteRepository {
- override fun getAllNotes(): Flow> {
- return noteDao.getAllNotes()
+ override fun getAllFolderlessNotes(): Flow> {
+ return noteDao.getAllFolderlessNotes()
}
override suspend fun getNote(id: Int): Note {
diff --git a/app/src/main/java/com/mhss/app/mybrain/domain/repository/NoteRepository.kt b/app/src/main/java/com/mhss/app/mybrain/domain/repository/NoteRepository.kt
index 5d4c75aa..f4612e46 100644
--- a/app/src/main/java/com/mhss/app/mybrain/domain/repository/NoteRepository.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/domain/repository/NoteRepository.kt
@@ -6,7 +6,7 @@ import kotlinx.coroutines.flow.Flow
interface NoteRepository {
- fun getAllNotes(): Flow>
+ fun getAllFolderlessNotes(): Flow>
suspend fun getNote(id: Int): Note
diff --git a/app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/GetAllNotesUseCase.kt b/app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/GetAllNotesUseCase.kt
index 7f47ee1a..9d78f77e 100644
--- a/app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/GetAllNotesUseCase.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/domain/use_case/notes/GetAllNotesUseCase.kt
@@ -12,7 +12,7 @@ class GetAllNotesUseCase @Inject constructor(
private val notesRepository: NoteRepository
) {
operator fun invoke(order: Order) : Flow> {
- return notesRepository.getAllNotes().map { list ->
+ return notesRepository.getAllFolderlessNotes().map { list ->
when (order.orderType) {
is OrderType.ASC -> {
when (order) {
From 769904556fe1d866a6b5fea168e863e7f10f2fc9 Mon Sep 17 00:00:00 2001
From: Mohamed
Date: Mon, 6 May 2024 12:18:18 +0300
Subject: [PATCH 33/36] Improve notes list performance by limiting the
retrieved content length
---
.../main/java/com/mhss/app/mybrain/data/local/dao/NoteDao.kt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/src/main/java/com/mhss/app/mybrain/data/local/dao/NoteDao.kt b/app/src/main/java/com/mhss/app/mybrain/data/local/dao/NoteDao.kt
index fed45abf..865f2418 100644
--- a/app/src/main/java/com/mhss/app/mybrain/data/local/dao/NoteDao.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/data/local/dao/NoteDao.kt
@@ -8,7 +8,7 @@ import kotlinx.coroutines.flow.Flow
@Dao
interface NoteDao {
- @Query("SELECT * FROM notes WHERE folder_id IS NULL")
+ @Query("SELECT title, SUBSTR(content, 1, 450) AS content, created_date, updated_date, pinned, folder_id, id FROM notes WHERE folder_id IS NULL")
fun getAllFolderlessNotes(): Flow>
@Query("SELECT * FROM notes")
@@ -20,7 +20,7 @@ interface NoteDao {
@Query("SELECT * FROM notes WHERE title LIKE '%' || :query || '%' OR content LIKE '%' || :query || '%'")
suspend fun getNotesByTitle(query: String): List
- @Query("SELECT * FROM notes WHERE folder_id = :folderId")
+ @Query("SELECT title, SUBSTR(content, 1, 450) AS content, created_date, updated_date, pinned, folder_id, id FROM notes WHERE folder_id = :folderId")
fun getNotesByFolder(folderId: Int): Flow>
@Insert(onConflict = OnConflictStrategy.REPLACE)
From f67b5b496340cf85199aac7e7178d4ea89ea7783 Mon Sep 17 00:00:00 2001
From: Mohamed
Date: Mon, 6 May 2024 13:23:39 +0300
Subject: [PATCH 34/36] Improve import and export memory usage and data
integrity
---
.../data/backup/RoomBackupRepositoryImpl.kt | 70 +++++++++----------
.../java/com/mhss/app/mybrain/di/AppModule.kt | 10 +--
2 files changed, 37 insertions(+), 43 deletions(-)
diff --git a/app/src/main/java/com/mhss/app/mybrain/data/backup/RoomBackupRepositoryImpl.kt b/app/src/main/java/com/mhss/app/mybrain/data/backup/RoomBackupRepositoryImpl.kt
index 9728544d..78165731 100644
--- a/app/src/main/java/com/mhss/app/mybrain/data/backup/RoomBackupRepositoryImpl.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/data/backup/RoomBackupRepositoryImpl.kt
@@ -3,10 +3,8 @@ package com.mhss.app.mybrain.data.backup
import android.content.Context
import android.net.Uri
import androidx.documentfile.provider.DocumentFile
-import com.mhss.app.mybrain.data.local.dao.BookmarkDao
-import com.mhss.app.mybrain.data.local.dao.DiaryDao
-import com.mhss.app.mybrain.data.local.dao.NoteDao
-import com.mhss.app.mybrain.data.local.dao.TaskDao
+import androidx.room.withTransaction
+import com.mhss.app.mybrain.data.local.MyBrainDatabase
import com.mhss.app.mybrain.domain.model.Bookmark
import com.mhss.app.mybrain.domain.model.DiaryEntry
import com.mhss.app.mybrain.domain.model.Note
@@ -16,19 +14,19 @@ import com.mhss.app.mybrain.domain.repository.RoomBackupRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.withContext
+import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable
-import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
+import kotlinx.serialization.json.decodeFromStream
+import kotlinx.serialization.json.encodeToStream
import javax.inject.Inject
class RoomBackupRepositoryImpl @Inject constructor(
private val context: Context,
- private val notesDao: NoteDao,
- private val tasksDao: TaskDao,
- private val diaryDao: DiaryDao,
- private val bookmarksDao: BookmarkDao,
+ private val database: MyBrainDatabase
) : RoomBackupRepository {
+ @OptIn(ExperimentalSerializationApi::class)
override suspend fun exportDatabase(
directoryUri: Uri,
encrypted: Boolean, // To be added in a future version
@@ -40,30 +38,28 @@ class RoomBackupRepositoryImpl @Inject constructor(
val pickedDir = DocumentFile.fromTreeUri(context, directoryUri)
val destination = pickedDir!!.createFile("application/json", fileName)
- val notes = notesDao.getAllNotes().map {
+ val notes = database.noteDao().getAllNotes().map {
it.copy(id = 0)
}
- val noteFolders = notesDao.getAllNoteFolders().first()
- val tasks = tasksDao.getAllTasks().first().map {
+ val noteFolders = database.noteDao().getAllNoteFolders().first()
+ val tasks = database.taskDao().getAllTasks().first().map {
it.copy(id = 0)
}
- val diary = diaryDao.getAllEntries().first().map {
+ val diary = database.diaryDao().getAllEntries().first().map {
it.copy(id = 0)
}
- val bookmarks = bookmarksDao.getAllBookmarks().first().map {
+ val bookmarks = database.bookmarkDao().getAllBookmarks().first().map {
it.copy(id = 0)
}
val backupData = BackupData(notes, noteFolders, tasks, diary, bookmarks)
- val backupJson = Json.encodeToString(backupData)
-
val outputStream =
destination?.let { context.contentResolver.openOutputStream(it.uri) }
?: return@withContext false
outputStream.use {
- it.write(backupJson.toByteArray())
+ Json.encodeToStream(backupData, outputStream)
}
true
@@ -74,6 +70,7 @@ class RoomBackupRepositoryImpl @Inject constructor(
}
}
+ @OptIn(ExperimentalSerializationApi::class)
override suspend fun importDatabase(
fileUri: Uri,
encrypted: Boolean, // To be added in a future version
@@ -81,25 +78,28 @@ class RoomBackupRepositoryImpl @Inject constructor(
): Boolean {
return withContext(Dispatchers.IO) {
try {
- val inputStream = context.contentResolver.openInputStream(fileUri)
- val backupJson = inputStream?.bufferedReader().use { it?.readText() }
- ?: return@withContext false
- val backupData = Json.decodeFromString(backupJson)
- val noteFolders = backupData.noteFolders
- val oldNoteFolderIds = noteFolders.map { it.id }
- val newNoteFolderIds = notesDao.insertNoteFolders(noteFolders.map { it.copy(id = 0) })
- if (newNoteFolderIds.size != oldNoteFolderIds.size) return@withContext false
- val notes = backupData.notes.map { note ->
- if (note.folderId != null) {
- note.copy(
- folderId = newNoteFolderIds[oldNoteFolderIds.indexOf(note.folderId)].toInt()
- )
- } else note
+ val json = Json {
+ ignoreUnknownKeys = true
+ }
+ val backupData = context.contentResolver.openInputStream(fileUri)?.use {
+ json.decodeFromStream(it)
+ } ?: return@withContext false
+ val oldNoteFolderIds = backupData.noteFolders.map { it.id }
+ database.withTransaction {
+ val newNoteFolderIds = database.noteDao().insertNoteFolders(backupData.noteFolders.map { it.copy(id = 0) })
+ if (newNoteFolderIds.size != oldNoteFolderIds.size) throw Exception("New folder count does not match old folder count.")
+ val notes = backupData.notes.map { note ->
+ if (note.folderId != null) {
+ note.copy(
+ folderId = newNoteFolderIds[oldNoteFolderIds.indexOf(note.folderId)].toInt()
+ )
+ } else note
+ }
+ database.noteDao().insertNotes(notes)
+ database.taskDao().insertTasks(backupData.tasks)
+ database.diaryDao().insertEntries(backupData.diary)
+ database.bookmarkDao().insertBookmarks(backupData.bookmarks)
}
- notesDao.insertNotes(notes)
- tasksDao.insertTasks(backupData.tasks)
- diaryDao.insertEntries(backupData.diary)
- bookmarksDao.insertBookmarks(backupData.bookmarks)
true
} catch (e: Exception) {
e.printStackTrace()
diff --git a/app/src/main/java/com/mhss/app/mybrain/di/AppModule.kt b/app/src/main/java/com/mhss/app/mybrain/di/AppModule.kt
index a8a20aa1..34c945f3 100644
--- a/app/src/main/java/com/mhss/app/mybrain/di/AppModule.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/di/AppModule.kt
@@ -92,15 +92,9 @@ object AppModule {
@Provides
fun provideBackupRepository(
@ApplicationContext context: Context,
- notesDao: NoteDao,
- tasksDao: TaskDao,
- diaryDao: DiaryDao,
- bookmarksDao: BookmarkDao,
+ database: MyBrainDatabase
): RoomBackupRepository = RoomBackupRepositoryImpl(
context,
- notesDao,
- tasksDao,
- diaryDao,
- bookmarksDao,
+ database
)
}
\ No newline at end of file
From 07d4111a5d36c49281823eb11fe767d2d02dc386 Mon Sep 17 00:00:00 2001
From: Mohamed
Date: Mon, 6 May 2024 16:03:54 +0300
Subject: [PATCH 35/36] Fix TaskDetailScreen not closing when due date is
unchecked
---
.../com/mhss/app/mybrain/presentation/tasks/TasksViewModel.kt | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/app/src/main/java/com/mhss/app/mybrain/presentation/tasks/TasksViewModel.kt b/app/src/main/java/com/mhss/app/mybrain/presentation/tasks/TasksViewModel.kt
index 6334e5f6..6e644f9d 100644
--- a/app/src/main/java/com/mhss/app/mybrain/presentation/tasks/TasksViewModel.kt
+++ b/app/src/main/java/com/mhss/app/mybrain/presentation/tasks/TasksViewModel.kt
@@ -139,8 +139,10 @@ class TasksViewModel @Inject constructor(
taskDetailsUiState.copy(navigateUp = true)
}
}
- else
+ else {
deleteAlarm(event.task.id)
+ taskDetailsUiState = taskDetailsUiState.copy(navigateUp = true)
+ }
} else {
taskDetailsUiState = taskDetailsUiState.copy(navigateUp = true)
}
From 39925b6a96db90b01fbcddb5f7902373b0c23ea6 Mon Sep 17 00:00:00 2001
From: Mohamed
Date: Mon, 6 May 2024 18:44:24 +0300
Subject: [PATCH 36/36] Bump version code and name
---
app/build.gradle.kts | 4 ++--
fastlane/metadata/android/en-US/changelogs/8.txt | 11 +++++++++++
2 files changed, 13 insertions(+), 2 deletions(-)
create mode 100644 fastlane/metadata/android/en-US/changelogs/8.txt
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 15906386..46680a06 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -15,8 +15,8 @@ android {
applicationId = "com.mhss.app.mybrain"
minSdk = 26
targetSdk = 34
- versionCode = 7
- versionName = "1.0.6"
+ versionCode = 8
+ versionName = "1.0.7"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
diff --git a/fastlane/metadata/android/en-US/changelogs/8.txt b/fastlane/metadata/android/en-US/changelogs/8.txt
new file mode 100644
index 00000000..b3de0b0c
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/8.txt
@@ -0,0 +1,11 @@
+- Added Vietnamese language by @ngocanhtve
+- Added lock app option
+- Added the ability to save text to note from share menu
+- Added subtasks progress in task card
+- Fixed backup problems causing missing data
+- Performance Improvements
+- UX improvements
+- Bug fixes
+### Notes:
+- The backup file format has been changed. You won't be able to import old backups in the new version so please create a new backup as soon as you install the new update to be able to restore it later.
+- Added internet permission for markdown features that require it and other future app features
\ No newline at end of file