-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extract methods to interfaces & change way of providing dependencies (#…
…25) * Extract methods to interfaces and provide dependencies * Provide preferences and replace singleton * Create module * Extract methods to interfaces * Replace singleton * Use callback instead of using singleton * Refactor and hook callback * Rename method
- Loading branch information
Showing
10 changed files
with
239 additions
and
180 deletions.
There are no files selected for viewing
137 changes: 6 additions & 131 deletions
137
app/src/main/java/space/taran/arkmemo/data/repositories/TextNotesRepo.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,138 +1,13 @@ | ||
package space.taran.arkmemo.data.repositories | ||
|
||
import android.util.Log | ||
import dev.arkbuilders.arklib.ResourceId | ||
import dev.arkbuilders.arklib.computeId | ||
import dev.arkbuilders.arklib.data.index.RootIndex | ||
import dev.arkbuilders.arklib.user.properties.Properties | ||
import dev.arkbuilders.arklib.user.properties.PropertiesStorage | ||
import dev.arkbuilders.arklib.user.properties.PropertiesStorageRepo | ||
import kotlinx.coroutines.CoroutineScope | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.flow.MutableStateFlow | ||
import kotlinx.coroutines.flow.StateFlow | ||
import kotlinx.coroutines.job | ||
import kotlinx.coroutines.withContext | ||
import space.taran.arkmemo.data.ResourceMeta | ||
import space.taran.arkmemo.models.TextNote | ||
import java.nio.file.Files | ||
import java.nio.file.Path | ||
import javax.inject.Inject | ||
import javax.inject.Singleton | ||
import kotlin.io.path.deleteIfExists | ||
import kotlin.io.path.exists | ||
import kotlin.io.path.extension | ||
import kotlin.io.path.fileSize | ||
import kotlin.io.path.forEachLine | ||
import kotlin.io.path.getLastModifiedTime | ||
import kotlin.io.path.moveTo | ||
import kotlin.io.path.name | ||
import kotlin.io.path.writeLines | ||
|
||
@Singleton | ||
class TextNotesRepo @Inject constructor() { | ||
|
||
private val iODispatcher = Dispatchers.IO | ||
|
||
private lateinit var propertiesStorage: PropertiesStorage | ||
private lateinit var propertiesStorageRepo: PropertiesStorageRepo | ||
|
||
private lateinit var root: Path | ||
|
||
suspend fun init(root: Path, scope: CoroutineScope) { | ||
this.root = root | ||
propertiesStorageRepo = PropertiesStorageRepo(scope) | ||
propertiesStorage = propertiesStorageRepo.provide(RootIndex.provide(root)) | ||
} | ||
|
||
suspend fun save(note: TextNote) { | ||
write(note) | ||
} | ||
|
||
suspend fun delete(note: TextNote) = withContext(iODispatcher) { | ||
val path = root.resolve("${note.meta?.name}") | ||
delete(path) | ||
propertiesStorage.remove(note.meta?.id!!) | ||
propertiesStorage.persist() | ||
Log.d("text-repo", "${note.meta?.name!!} has been deleted") | ||
} | ||
|
||
suspend fun read(): List<TextNote> = withContext(Dispatchers.IO) { | ||
val notes = mutableListOf<TextNote>() | ||
Files.list(root).forEach { path -> | ||
if (path.fileName.extension == NOTE_EXT) { | ||
val data = StringBuilder() | ||
path.forEachLine { | ||
data.appendLine(it) | ||
} | ||
val size = path.fileSize() | ||
val id = computeId(size, path) | ||
val meta = ResourceMeta( | ||
id, | ||
path.fileName.name, | ||
path.extension, | ||
path.getLastModifiedTime(), | ||
size | ||
) | ||
val titles = propertiesStorage.getProperties(id).titles | ||
val content = TextNote.Content(titles.elementAt(0), data.toString()) | ||
val note = TextNote(content, meta) | ||
notes.add(note) | ||
} | ||
} | ||
Log.d("text-repo", "${notes.size} text note resources found") | ||
notes | ||
} | ||
|
||
private suspend fun write(note: TextNote) = withContext(Dispatchers.IO) { | ||
val tempPath = kotlin.io.path.createTempFile() | ||
val lines = note.content.data.split('\n') | ||
tempPath.writeLines(lines) | ||
val size = tempPath.fileSize() | ||
val id = computeId(size, tempPath) | ||
Log.d("text-repo", "initial resource name ${tempPath.name}") | ||
persistNoteProperties(resourceId = id, noteTitle = note.content.title) | ||
|
||
val resourcePath = root.resolve("$id.$NOTE_EXT") | ||
renameResourceWithNewResourceMeta( | ||
note = note, | ||
tempPath = tempPath, | ||
resourcePath = resourcePath, | ||
resourceId = id, | ||
size = size | ||
) | ||
} | ||
|
||
private suspend fun persistNoteProperties(resourceId: ResourceId, noteTitle: String) { | ||
with(propertiesStorage) { | ||
val properties = Properties(setOf(noteTitle), setOf()) | ||
setProperties(resourceId, properties) | ||
persist() | ||
} | ||
} | ||
|
||
private fun renameResourceWithNewResourceMeta( | ||
note: TextNote, | ||
tempPath: Path, | ||
resourcePath: Path, | ||
resourceId: ResourceId, | ||
size: Long | ||
) { | ||
tempPath.moveTo(resourcePath) | ||
note.meta = ResourceMeta( | ||
id = resourceId, | ||
name = resourcePath.fileName.name, | ||
extension = resourcePath.extension, | ||
modified = resourcePath.getLastModifiedTime(), | ||
size = size | ||
) | ||
Log.d("notes-repo", "resource renamed to ${resourcePath.name} successfully") | ||
} | ||
|
||
private fun delete(path: Path) { | ||
path.deleteIfExists() | ||
} | ||
} | ||
|
||
private const val NOTE_EXT = "note" | ||
interface TextNotesRepo { | ||
suspend fun init(root: Path, scope: CoroutineScope) | ||
suspend fun save(note: TextNote) | ||
suspend fun delete(note: TextNote): Int | ||
suspend fun read(): List<TextNote> | ||
|
||
} |
132 changes: 132 additions & 0 deletions
132
app/src/main/java/space/taran/arkmemo/data/repositories/TextNotesRepoImpl.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
package space.taran.arkmemo.data.repositories | ||
|
||
import android.util.Log | ||
import dev.arkbuilders.arklib.ResourceId | ||
import dev.arkbuilders.arklib.computeId | ||
import dev.arkbuilders.arklib.data.index.RootIndex | ||
import dev.arkbuilders.arklib.user.properties.Properties | ||
import dev.arkbuilders.arklib.user.properties.PropertiesStorage | ||
import dev.arkbuilders.arklib.user.properties.PropertiesStorageRepo | ||
import kotlinx.coroutines.CoroutineScope | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.withContext | ||
import space.taran.arkmemo.data.ResourceMeta | ||
import space.taran.arkmemo.models.TextNote | ||
import java.nio.file.Files | ||
import java.nio.file.Path | ||
import javax.inject.Inject | ||
import kotlin.io.path.deleteIfExists | ||
import kotlin.io.path.extension | ||
import kotlin.io.path.fileSize | ||
import kotlin.io.path.forEachLine | ||
import kotlin.io.path.getLastModifiedTime | ||
import kotlin.io.path.moveTo | ||
import kotlin.io.path.name | ||
import kotlin.io.path.writeLines | ||
|
||
class TextNotesRepoImpl @Inject constructor(): TextNotesRepo { | ||
|
||
private val iODispatcher = Dispatchers.IO | ||
|
||
private lateinit var propertiesStorage: PropertiesStorage | ||
private lateinit var propertiesStorageRepo: PropertiesStorageRepo | ||
|
||
private lateinit var root: Path | ||
|
||
override suspend fun init(root: Path, scope: CoroutineScope) { | ||
this.root = root | ||
propertiesStorageRepo = PropertiesStorageRepo(scope) | ||
propertiesStorage = propertiesStorageRepo.provide(RootIndex.provide(root)) | ||
} | ||
|
||
override suspend fun save(note: TextNote) { | ||
write(note) | ||
} | ||
|
||
override suspend fun delete(note: TextNote) = withContext(iODispatcher) { | ||
val path = root.resolve("${note.meta?.name}") | ||
delete(path) | ||
propertiesStorage.remove(note.meta?.id!!) | ||
propertiesStorage.persist() | ||
Log.d("text-repo", "${note.meta?.name!!} has been deleted") | ||
} | ||
|
||
override suspend fun read(): List<TextNote> = withContext(Dispatchers.IO) { | ||
val notes = mutableListOf<TextNote>() | ||
Files.list(root).forEach { path -> | ||
if (path.fileName.extension == NOTE_EXT) { | ||
val data = StringBuilder() | ||
path.forEachLine { | ||
data.appendLine(it) | ||
} | ||
val size = path.fileSize() | ||
val id = computeId(size, path) | ||
val meta = ResourceMeta( | ||
id, | ||
path.fileName.name, | ||
path.extension, | ||
path.getLastModifiedTime(), | ||
size | ||
) | ||
val titles = propertiesStorage.getProperties(id).titles | ||
val content = TextNote.Content(titles.elementAt(0), data.toString()) | ||
val note = TextNote(content, meta) | ||
notes.add(note) | ||
} | ||
} | ||
Log.d("text-repo", "${notes.size} text note resources found") | ||
notes | ||
} | ||
|
||
private suspend fun write(note: TextNote) = withContext(Dispatchers.IO) { | ||
val tempPath = kotlin.io.path.createTempFile() | ||
val lines = note.content.data.split('\n') | ||
tempPath.writeLines(lines) | ||
val size = tempPath.fileSize() | ||
val id = computeId(size, tempPath) | ||
Log.d("text-repo", "initial resource name ${tempPath.name}") | ||
persistNoteProperties(resourceId = id, noteTitle = note.content.title) | ||
|
||
val resourcePath = root.resolve("$id.$NOTE_EXT") | ||
renameResourceWithNewResourceMeta( | ||
note = note, | ||
tempPath = tempPath, | ||
resourcePath = resourcePath, | ||
resourceId = id, | ||
size = size | ||
) | ||
} | ||
|
||
private suspend fun persistNoteProperties(resourceId: ResourceId, noteTitle: String) { | ||
with(propertiesStorage) { | ||
val properties = Properties(setOf(noteTitle), setOf()) | ||
setProperties(resourceId, properties) | ||
persist() | ||
} | ||
} | ||
|
||
private fun renameResourceWithNewResourceMeta( | ||
note: TextNote, | ||
tempPath: Path, | ||
resourcePath: Path, | ||
resourceId: ResourceId, | ||
size: Long | ||
) { | ||
tempPath.moveTo(resourcePath) | ||
note.meta = ResourceMeta( | ||
id = resourceId, | ||
name = resourcePath.fileName.name, | ||
extension = resourcePath.extension, | ||
modified = resourcePath.getLastModifiedTime(), | ||
size = size | ||
) | ||
Log.d("notes-repo", "resource renamed to ${resourcePath.name} successfully") | ||
} | ||
|
||
private fun delete(path: Path) { | ||
path.deleteIfExists() | ||
} | ||
} | ||
|
||
private const val NOTE_EXT = "note" | ||
|
15 changes: 15 additions & 0 deletions
15
app/src/main/java/space/taran/arkmemo/di/PreferencesModule.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package space.taran.arkmemo.di | ||
|
||
import dagger.Binds | ||
import dagger.Module | ||
import dagger.hilt.InstallIn | ||
import dagger.hilt.components.SingletonComponent | ||
import space.taran.arkmemo.preferences.MemoPreferences | ||
import space.taran.arkmemo.preferences.MemoPreferencesImpl | ||
|
||
@InstallIn(SingletonComponent::class) | ||
@Module | ||
abstract class PreferencesModule { | ||
@Binds | ||
abstract fun bindMemoPreferences(impl: MemoPreferencesImpl): MemoPreferences | ||
} |
16 changes: 16 additions & 0 deletions
16
app/src/main/java/space/taran/arkmemo/di/RepositoryModule.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package space.taran.arkmemo.di | ||
|
||
import dagger.Binds | ||
import dagger.Module | ||
import dagger.hilt.InstallIn | ||
import dagger.hilt.components.SingletonComponent | ||
import space.taran.arkmemo.data.repositories.TextNotesRepo | ||
import space.taran.arkmemo.data.repositories.TextNotesRepoImpl | ||
|
||
|
||
@InstallIn(SingletonComponent::class) | ||
@Module | ||
abstract class RepositoryModule { | ||
@Binds | ||
abstract fun bindRepository(impl: TextNotesRepoImpl): TextNotesRepo | ||
} |
44 changes: 4 additions & 40 deletions
44
app/src/main/java/space/taran/arkmemo/preferences/MemoPreferences.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,47 +1,11 @@ | ||
package space.taran.arkmemo.preferences | ||
|
||
import android.content.Context | ||
import android.content.Context.MODE_PRIVATE | ||
import java.io.File | ||
import java.nio.file.Path | ||
|
||
class MemoPreferences private constructor(context: Context) { | ||
private val sharedPreferences = context.getSharedPreferences(NAME, MODE_PRIVATE) | ||
private val prefEditor = sharedPreferences.edit() | ||
interface MemoPreferences { | ||
fun storePath(path: String) | ||
|
||
fun storePath(path: String){ | ||
prefEditor.apply{ | ||
putString(CURRENT_NOTES_PATH, path) | ||
apply() | ||
} | ||
} | ||
fun getPathString(): String? | ||
|
||
fun getPathString() = sharedPreferences.getString(CURRENT_NOTES_PATH, null) | ||
|
||
fun getPath(): Path? { | ||
val pathString = getPathString() | ||
var path: Path? = null | ||
try { | ||
val file = File(pathString!!) | ||
file.mkdir() | ||
path = file.toPath() | ||
} catch (e: Exception) { | ||
e.printStackTrace() | ||
} | ||
return path | ||
} | ||
|
||
companion object{ | ||
private const val NAME = "memo_prefs" | ||
private const val CURRENT_NOTES_PATH = "current_notes_path" | ||
private var preferences: MemoPreferences? = null | ||
|
||
fun getInstance(context: Context): MemoPreferences{ | ||
if(preferences == null) | ||
preferences = MemoPreferences(context) | ||
return preferences!! | ||
} | ||
|
||
fun getInstance() = preferences!! | ||
} | ||
fun getPath(): Path? | ||
} |
Oops, something went wrong.