This commit is contained in:
coco
2026-07-03 15:47:27 +08:00
commit 7846a45f2c
38575 changed files with 4736783 additions and 0 deletions
@@ -0,0 +1,24 @@
package com.dailystudio.devbricksx.notebook
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.dailystudio.devbricksx.notebook", appContext.packageName)
}
}
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>
@@ -0,0 +1,134 @@
package com.dailystudio.devbricksx.notebook
import android.content.Context
import androidx.lifecycle.LifecycleCoroutineScope
import androidx.lifecycle.lifecycleScope
import com.dailystudio.devbricksx.development.Logger
import com.dailystudio.devbricksx.notebook.db.Note
import com.dailystudio.devbricksx.notebook.db.Notebook
import com.dailystudio.devbricksx.notebook.db.NotesDatabase
import com.dailystudio.devbricksx.utils.JSONUtils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.Date
object DummyDataUtils {
private val notebooks = """
[
{ "name": "Games" },
{ "name": "Techs" },
{ "name": "English" }
]
""".trimIndent()
private val notes = """
[
[
{ "title": "Call of Duty: Mobile", "desc": "Call of Duty: Mobile is a free-to-play first-person shooter video game developed by TiMi Studio Group and published by Activision for Android and iOS." },
{ "title": "Pokémon GO", "desc": "Pokémon Go is a 2016 augmented reality mobile game, part of the Pokémon franchise, developed and published by Niantic in collaboration with Nintendo and The Pokémon Company for iOS and Android devices." },
{ "title": "Candy Crush Saga", "desc": "Pokémon Go is a 2016 augmented reality mobile game, part of the Pokémon franchise, developed and published by Niantic in collaboration with Nintendo and The Pokémon Company for iOS and Android devices." }
],
[
{ "title": "Kotlin", "desc": "Kotlin is a programming language that makes coding concise, cross-platform, and fun. It is Google's preferred language for Android app development." },
{ "title": "Jetpack Compose", "desc": "Jetpack Compose is Android's recommended modern toolkit for building native UI. It simplifies and accelerates UI development on Android." },
{ "title": "KSP", "desc": "Kotlin Symbol Processing (KSP) is an API that you can use to develop lightweight compiler plugins." },
{ "title": "Unidirectional Data Flow", "desc": "UDF is a waterfall, information flows in one direction through a single source providing many benefits." },
{ "title": "KMM", "desc": "Kotlin Multiplatform technology simplifies the development of cross-platform projects. It reduces time spent writing and maintaining the same code for different platforms while retaining the flexibility and benefits of native programming." }
],
[
{ "title": "Old Saying 1", "desc": "Well done is better than well said." },
{ "title": "Old Saying 2", "desc": "Once you choose hope, anything's possible." },
{ "title": "Old Saying 3", "desc": "You only live once but if you do it right, once is enough." },
{ "title": "Old Saying 4", "desc": "Sometimes the heart sees what is invisible to the eye." }
]
]
""".trimIndent()
fun createSampleNotes(
context: Context,
coroutineScope: LifecycleCoroutineScope
) {
coroutineScope.launch(Dispatchers.IO) {
// val notebooks = arrayOf(
// "Games", "Tech",
// "Books", "Office",
// "Home"
// )
val notebooks =
try {
JSONUtils.fromString(notebooks, Array<Notebook>::class.java)
} catch (e: Exception) {
Logger.error("failed to parse notebooks: $e")
null
}
val notes =
try {
JSONUtils.fromString(DummyDataUtils.notes, Array<Array<Note>>::class.java)
} catch (e: Exception) {
Logger.error("failed to parse notes: $e")
null
}
if (notebooks == null || notes == null) {
Logger.warn("data of notebooks or notes are incorrect, skip generating dummy data")
return@launch
}
val maxNotes = 5
val database = NotesDatabase.getDatabase(
context)
database.clearAllTables()
val notesInNotebook = mutableListOf<Note>()
for ((i, nb) in notebooks.withIndex()) {
val notebookId = i + 1
val nb = Notebook(notebookId).apply {
name = nb.name
created = Date()
lastModified = created
}
// for (j in 0 until maxNotes) {
// val noteId = notebookId * maxNotes + j + 1
//
// notes.add(Note(noteId).apply {
// notebook_id = notebookId
// title = "$j"
// desc = "Write something for $j"
//
// created = Date()
// lastModified = created
// })
// }
notesInNotebook.clear()
for ((j, note) in notes[i].withIndex()) {
val noteId = notebookId * maxNotes + j + 1
Logger.debug("adding note = $note")
Logger.debug("noteId = $noteId")
notesInNotebook.add(Note(noteId).apply {
title = note.title
desc = note.desc
notebook_id = notebookId
created = Date()
lastModified = created
})
}
Logger.debug("ADD: notebook = [$nb]")
database.notebookDao().insertOrUpdate(nb)
Logger.debug("ADD: notesInNotebook = [$notesInNotebook]")
database.noteDao().insertOrUpdate(notesInNotebook)
}
}
}
}
@@ -0,0 +1,12 @@
package com.dailystudio.devbricksx.notebook
import com.dailystudio.devbricksx.app.DevBricksMultiDexApplication
import com.dailystudio.devbricksx.notebook.core.BuildConfig
class NotebookApplication : DevBricksMultiDexApplication() {
override fun isDebugBuild(): Boolean {
return BuildConfig.DEBUG
}
}
@@ -0,0 +1,99 @@
package com.dailystudio.devbricksx.notebook.db
import androidx.room.ForeignKey
import androidx.room.Ignore
import com.dailystudio.devbricksx.annotations.data.IgnoreField
import com.dailystudio.devbricksx.annotations.data.RoomCompanion
import com.dailystudio.devbricksx.annotations.viewmodel.ViewModel
import com.dailystudio.devbricksx.database.DateConverter
import com.dailystudio.devbricksx.database.SelectableRecord
import java.util.*
@RoomCompanion(primaryKeys = ["id"],
autoGenerate = true,
converters = [DateConverter::class],
extension = NotebookDaoExtension::class,
database = "notes",
)
@ViewModel(group = "notebook")
open class Notebook(id: Int = 0) : SelectableRecord(id) {
companion object {
fun createNoteBook(name: String): Notebook {
return Notebook(0).apply {
val now = System.currentTimeMillis()
this.name = name
this.created = Date(now)
this.lastModified = this.created
}
}
}
var name: String? = null
override fun toString(): String {
return buildString {
append("Notebook [$id]: $name")
}
}
}
class NotebookInfo(override val id: Int): Notebook(id) {
var notesCount: Int = 0
}
@RoomCompanion(primaryKeys = ["id"],
autoGenerate = true,
extension = NoteDaoExtension::class,
database = "notes",
foreignKeys = [ ForeignKey(entity = Notebook::class,
parentColumns = ["id"],
childColumns = ["notebook_id"],
onDelete = ForeignKey.CASCADE
)]
)
@ViewModel(group = "notebook")
class Note(id: Int = 0) : SelectableRecord(id) {
companion object {
fun createNote(notebookId: Int = -1,
title: String? = null,
desc: String? = null): Note {
return Note(0).apply {
val now = System.currentTimeMillis()
this.notebook_id = notebookId
this.title = title
this.desc = desc
this.created = Date(now)
this.lastModified = this.created
}
}
fun copyNote(note: Note): Note {
return Note(note.id).apply {
notebook_id = note.notebook_id
title = note.title
desc = note.desc
created = note.created
lastModified = note.lastModified
}
}
}
var notebook_id: Int = -1
var title: String? = null
var desc: String? = null
override fun toString(): String {
return buildString {
append("Note [$id, notebook: $notebook_id]: $title, [desc: $desc]")
}
}
}
@@ -0,0 +1,42 @@
package com.dailystudio.devbricksx.notebook.db
import androidx.paging.PagingSource
import androidx.room.Query
import com.dailystudio.devbricksx.annotations.data.DaoExtension
import com.dailystudio.devbricksx.annotations.data.Page
import kotlinx.coroutines.flow.Flow
@DaoExtension(entity = Notebook::class)
abstract class NotebookDaoExtension {
/*
@Query("SELECT * FROM notebook ORDER BY last_modified DESC")
@Page(pageSize = 50)
abstract fun getAllNotebooksOrderedByLastModifiedLivePaged(): LiveData<PagedList<Notebook>>
*/
@Query("SELECT notebook.id, notebook.name, notebook.created, notebook.last_modified, count(note.id) as notesCount FROM notebook LEFT OUTER JOIN note ON note.notebook_id = notebook.id GROUP BY notebook.id ORDER BY notebook.last_modified DESC")
abstract fun getAllNotebooksOrderedByLastModifiedPagingSource(): PagingSource<Int, NotebookInfo>
@Query("SELECT * FROM notebook ORDER BY last_modified DESC")
abstract fun getAllNotebooksOrderedByLastModifiedLivePaged(): Flow<List<Notebook>>
@Query("DELETE FROM notebook WHERE id IN (:ids)")
abstract fun deleteNotebooks(ids: IntArray)
}
@DaoExtension(entity = Note::class)
abstract class NoteDaoExtension {
@Query("SELECT * FROM note WHERE notebook_id = :notebookId ORDER BY last_modified DESC ")
@Page(pageSize = 50)
abstract fun getAllNotesOrderedByLastModifiedLivePaged(notebookId: Int): PagingSource<Int, Note>
@Query("SELECT COUNT(*) FROM note WHERE notebook_id = :notebookId")
abstract fun countNotes(notebookId: Int): Int
@Query("DELETE FROM note WHERE id IN (:ids)")
abstract fun deleteNotes(ids: IntArray)
}
@@ -0,0 +1,95 @@
package com.dailystudio.devbricksx.notebook.model
import android.app.Application
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.PagingSource
import androidx.paging.cachedIn
import androidx.paging.map
import com.dailystudio.devbricksx.development.Logger
import com.dailystudio.devbricksx.notebook.db.Note
import com.dailystudio.devbricksx.notebook.db.Notebook
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.launch
class NotebookViewModelExt(application: Application): NotebookViewModel(application) {
val allNotebooksCounted: Flow<PagingData<Notebook>> =
Pager(
PagingConfig(20)
) {
notebookRepository.getAllNotebooksOrderedByLastModifiedPagingSource() as PagingSource<Int, Notebook>
}.flow.flowOn(Dispatchers.IO)
private val _currentNoteId = MutableStateFlow(-1)
private val _currentNotebookId = MutableStateFlow(-1)
val currentNote: LiveData<Note> =
_currentNoteId.flatMapLatest { noteId ->
Logger.debug("[DC] retrieve note: $noteId")
noteRepository.getNoteFlow(noteId).mapLatest {
it ?: Note.createNote()
}
}.flowOn(Dispatchers.IO).asLiveData()
val notesInOpenedNotebook: Flow<PagingData<Note>> =
_currentNotebookId.flatMapLatest { notebookId ->
Logger.debug("[Note Data}: notebookId = $notebookId")
Pager (
PagingConfig(20),
) {
getAllNotesOrderedByLastModifiedLivePaged(notebookId)
}.flow.mapLatest {
it.map {
it.also {
Logger.debug("[Note Data]: note = $it")
}
}
}.flowOn(Dispatchers.IO).cachedIn(viewModelScope)
}.flowOn(Dispatchers.IO)
private val _currentNote: MutableLiveData<Note> =
MutableLiveData(Note.createNote())
fun openNotebook(notebookId: Int) {
_currentNotebookId.value = notebookId
}
fun closeNotebook() {
_currentNotebookId.value = -1
}
fun openNote(id: Int) {
_currentNoteId.value = id
}
fun closeNote() {
_currentNoteId.value = -1
}
fun deleteNotes(ids: Set<Int>): Job =
viewModelScope.launch(Dispatchers.IO) {
noteRepository.deleteNotes(ids.toIntArray())
}
fun deleteNotebooks(ids: Set<Int>): Job =
viewModelScope.launch(Dispatchers.IO) {
notebookRepository.deleteNotebooks(ids.toIntArray())
}
}
@@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#FFFFFF"
android:alpha="0.8">
<group android:scaleX="0.90909094"
android:scaleY="0.90909094"
android:translateX="1.0909091"
android:translateY="1.0909091">
<path
android:fillColor="@android:color/white"
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
</group>
</vector>
@@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#FFFFFF"
android:alpha="0.8">
<group android:scaleX="0.90909094"
android:scaleY="0.90909094"
android:translateX="1.0909091"
android:translateY="1.0909091">
<path
android:fillColor="@android:color/white"
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
</group>
</vector>
@@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#FFFFFF"
android:alpha="0.8">
<group android:scaleX="0.90909094"
android:scaleY="0.90909094"
android:translateX="1.0909091"
android:translateY="1.0909091">
<path
android:fillColor="@android:color/white"
android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/>
</group>
</vector>
@@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#FFFFFF"
android:alpha="0.8">
<group android:scaleX="0.90909094"
android:scaleY="0.90909094"
android:translateX="1.0909091"
android:translateY="1.0909091">
<path
android:fillColor="@android:color/white"
android:pathData="M3,17.25V21h3.75L17.81,9.94l-3.75,-3.75L3,17.25zM20.71,7.04c0.39,-0.39 0.39,-1.02 0,-1.41l-2.34,-2.34c-0.39,-0.39 -1.02,-0.39 -1.41,0l-1.83,1.83 3.75,3.75 1.83,-1.83z"/>
</group>
</vector>
@@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="26.4"
android:viewportHeight="26.4"
android:tint="#FFFFFF"
android:alpha="0.8">
<group android:translateX="1.2"
android:translateY="1.2">
<path
android:fillColor="#FF000000"
android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</group>
</vector>
@@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#503E4E"
android:alpha="0.8">
<group android:scaleX="0.90909094"
android:scaleY="0.90909094"
android:translateX="1.0909091"
android:translateY="1.0909091">
<path
android:fillColor="@android:color/white"
android:pathData="M19,3L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM14,17L7,17v-2h7v2zM17,13L7,13v-2h10v2zM17,9L7,9L7,7h10v2z"/>
</group>
</vector>
@@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="#503E4E"
android:alpha="0.8">
<group android:scaleX="0.90909094"
android:scaleY="0.90909094"
android:translateX="1.0909091"
android:translateY="1.0909091">
<path
android:fillColor="@android:color/white"
android:pathData="M7,11v2h10v-2L7,11zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
</group>
</vector>
Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108"
android:tint="#FFFFFF">
<group android:scaleX="2.2021875"
android:scaleY="2.2021875"
android:translateX="27.57375"
android:translateY="27.57375">
<path
android:fillColor="@android:color/white"
android:pathData="M6,17h3l2,-4L11,7L5,7v6h3zM14,17h3l2,-4L19,7h-6v6h3z"/>
</group>
</vector>
Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 585 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 298 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 840 B

@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>
@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108"
android:tint="#FFFFFF">
<group android:scaleX="2.2021875"
android:scaleY="2.2021875"
android:translateX="27.57375"
android:translateY="27.57375">
<path
android:fillColor="@android:color/white"
android:pathData="M6,17h3l2,-4L11,7L5,7v6h3zM14,17h3l2,-4L19,7h-6v6h3z"/>
</group>
</vector>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>
Binary file not shown.

After

Width:  |  Height:  |  Size: 985 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

@@ -0,0 +1,20 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.SampleNotebook" parent="Theme.Material3.Light.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/primaryColor</item>
<item name="colorPrimaryVariant">@color/primaryLightColor</item>
<item name="colorOnPrimary">@color/primaryTextColor</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/secondaryColor</item>
<item name="colorSecondaryVariant">@color/secondaryLightColor</item>
<item name="colorOnSecondary">@color/primaryTextColor</item>
<item name="statusBarBackground">@color/primaryColor</item>
<item name="android:statusBarColor">@color/primaryColor</item>
<item name="appBarLayoutStyle">@style/Widget.App.AppBarLayout</item>
<item name="toolbarStyle">@style/Widget.App.Toolbar</item>
</style>
</resources>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="primaryColor">#503E4E</color>
<color name="primaryDarkColor">#503E4E</color>
<color name="accentColor">#503E4E</color>
<color name="secondaryColor">#503E4E</color>
<color name="secondaryLightColor">#503E4E</color>
<color name="secondaryDarkColor">#503E4E</color>
<color name="primaryTextColor">#ffffff</color>
<color name="secondaryTextColor">#ffffff</color>
</resources>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="title_font_size">20dp</dimen>
<dimen name="selector_width">8dp</dimen>
</resources>
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#503E4E</color>
</resources>
@@ -0,0 +1,21 @@
<resources>
<string name="app_name">Notes</string>
<string name="app_desc">This is a sample application written with DevbricksX library. It illustrates how to use the library to compose a notebook app in the most efficient way.\n\nIt includes a set of functions that a notebook app should have. And, all the notes are store permanently in you local storage.\n\nIf you have any problem, please feel free to contact me:\n\n\t\t\tdailystudio2010@gmail.com\n</string>
<string name="dialog_title_new_notebook">New notebook</string>
<string name="hint_new_notebook">Name</string>
<string name="label_delete">Delete</string>
<string name="label_finish">Finish</string>
<string name="label_empty">&lt;empty&gt;</string>
<string name="menu_about">About</string>
<string name="hint_title">Note Title</string>
<string name="hint_content">Start writing here …</string>
<string name="prompt_selection">Selected %1$d</string>
<string name="prompt_deletion">Are you sure you want to delete these items?</string>
</resources>
@@ -0,0 +1,54 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.SampleNotebook" parent="Theme.Material3.Light.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/primaryColor</item>
<item name="colorPrimaryVariant">@color/primaryLightColor</item>
<item name="colorOnPrimary">@color/primaryTextColor</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/secondaryColor</item>
<item name="colorSecondaryVariant">@color/secondaryLightColor</item>
<item name="colorOnSecondary">@color/primaryTextColor</item>
<item name="statusBarBackground">@color/primaryColor</item>
<item name="android:statusBarColor">@color/primaryColor</item>
<item name="appBarLayoutStyle">@style/Widget.App.AppBarLayout</item>
<item name="toolbarStyle">@style/Widget.App.Toolbar</item>
</style>
<style name="Widget.App.AppBarLayout" parent="Widget.Material3.AppBarLayout">
<!-- Change the background color of the AppBarLayout so the AppBarLayout is green.
The toolbar is transparent by default so you will see this color through the toolbar. -->
<item name="android:background">@color/primaryColor</item>
</style>
<style name="Widget.App.Toolbar" parent="Widget.Material3.Toolbar">
<item name="materialThemeOverlay">@style/ThemeOverlay.App.Toolbar</item>
<item name="titleTextColor">@color/white</item>
<item name="navigationIconTint">@color/white</item>
<item name="colorControlActivated">#FFffffff</item>
</style>
<style name="ThemeOverlay.App.Toolbar" parent="">
<!-- Text color -->
<item name="android:editTextColor">@color/white</item>
<!-- Hint text color -->
<item name="android:textColorHint">@color/white</item>
<item name="colorControlNormal">@color/white</item>
<item name="colorControlActivated">@color/white</item>
</style>
<style name="ToolbarChip" parent="Widget.Material3.Chip.Input">
<item name="chipBackgroundColor">@color/white</item>
<item name="chipStrokeWidth">0dp</item>
<item name="checkedIconVisible">true</item>
<item name="shapeAppearanceOverlay">@style/ShapeAppearance.App.SmallComponent</item>
</style>
<style name="ShapeAppearance.App.SmallComponent" parent="ShapeAppearance.Material3.SmallComponent">
<item name="cornerSize">16dp</item>
</style>
</resources>
@@ -0,0 +1,17 @@
package com.dailystudio.devbricksx.notebook
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}