Skip to content

Commit

Permalink
injection system
Browse files Browse the repository at this point in the history
  • Loading branch information
leandroBorgesFerreira committed Jul 7, 2023
1 parent 622cbfb commit bf833fc
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 60 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package br.com.leandroferreira.app_sample.di

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import br.com.leandroferreira.editor.NoteDetailsViewModel
import br.com.leandroferreira.note_menu.data.usecase.NotesUseCase
import br.com.leandroferreira.note_menu.viewmodel.ChooseNoteViewModel
import com.github.leandroborgesferreira.storyteller.manager.StoryTellerManager
import com.github.leandroborgesferreira.storyteller.persistence.repository.DocumentRepositoryImpl

class NoteDetailsViewModelFactory(
private val storyTellerManager: StoryTellerManager,
private val documentRepository: DocumentRepositoryImpl
) : ViewModelProvider.Factory {

override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(NoteDetailsViewModel::class.java)) {
return NoteDetailsViewModel(storyTellerManager, documentRepository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}


class ChooseNoteViewModelFactory(
private val notesUseCase: NotesUseCase
) : ViewModelProvider.Factory {

override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(ChooseNoteViewModel::class.java)) {
return ChooseNoteViewModel(notesUseCase) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package br.com.leandroferreira.app_sample.di

import android.content.SharedPreferences
import androidx.compose.runtime.Composable
import androidx.lifecycle.viewmodel.compose.viewModel
import br.com.leandroferreira.editor.NoteDetailsViewModel
import br.com.leandroferreira.note_menu.data.usecase.NotesUseCase
import br.com.leandroferreira.note_menu.viewmodel.ChooseNoteViewModel
import com.github.leandroborgesferreira.storyteller.manager.DocumentRepository
import com.github.leandroborgesferreira.storyteller.manager.StoryTellerManager
import com.github.leandroborgesferreira.storyteller.persistence.database.StoryTellerDatabase
import com.github.leandroborgesferreira.storyteller.persistence.repository.DocumentRepositoryImpl

class NotesInjection(
private val database: StoryTellerDatabase,
private val sharedPreferences: SharedPreferences
) {

private fun provideStoryTellerManager() = StoryTellerManager()

private fun provideDocumentRepository(): DocumentRepository =
DocumentRepositoryImpl(
database.documentDao(),
database.storyUnitDao()
)

private fun provideNotesUseCase(
documentRepository: DocumentRepository = provideDocumentRepository()
): NotesUseCase {
return NotesUseCase(documentRepository, sharedPreferences)
}

@Composable
internal fun provideChooseNoteViewModel(
notesUseCase: NotesUseCase = provideNotesUseCase()
): ChooseNoteViewModel {
return viewModel(factory = ChooseNoteViewModelFactory(notesUseCase))
}

@Composable
internal fun provideNoteDetailsViewModel(
documentRepository: DocumentRepository = provideDocumentRepository(),
storyTellerManager: StoryTellerManager = provideStoryTellerManager()
): NoteDetailsViewModel {
return viewModel(initializer = {
NoteDetailsViewModel(storyTellerManager, documentRepository)
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,16 @@ import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import br.com.leandroferreira.app_sample.di.NotesInjection
import br.com.leandroferreira.app_sample.theme.ApplicationComposeTheme
import br.com.leandroferreira.editor.NoteDetailsScreen
import br.com.leandroferreira.editor.NoteDetailsViewModel
import br.com.leandroferreira.editor.NoteDetailsViewModelFactory
import br.com.leandroferreira.note_menu.data.usecase.NotesUseCase
import br.com.leandroferreira.note_menu.ui.screen.ChooseNoteScreen
import br.com.leandroferreira.note_menu.viewmodel.ChooseNoteViewModel
import com.github.leandroborgesferreira.storyteller.manager.StoryTellerManager
import com.github.leandroborgesferreira.storyteller.persistence.database.StoryTellerDatabase
import com.github.leandroborgesferreira.storyteller.persistence.repository.DocumentRepositoryImpl
import com.github.leandroborgesferreira.storyteller.video.VideoFrameConfig

class NavigationActivity : AppCompatActivity() {
Expand All @@ -38,6 +32,7 @@ class NavigationActivity : AppCompatActivity() {

@Composable
fun NavigationGraph() {

val navController = rememberNavController()
val context = LocalContext.current
val database = StoryTellerDatabase.database(context)
Expand All @@ -46,17 +41,12 @@ fun NavigationGraph() {
Context.MODE_PRIVATE
)

ApplicationComposeTheme {
val notesInjection = NotesInjection(database, sharedPreferences)

ApplicationComposeTheme {
NavHost(navController = navController, startDestination = Destinations.CHOOSE_NOTE.id) {
composable(Destinations.CHOOSE_NOTE.id) {
val repository = DocumentRepositoryImpl(
database.documentDao(),
database.storyUnitDao()
)

val notesUseCase = NotesUseCase(repository, sharedPreferences)
val chooseNoteViewModel = ChooseNoteViewModel(notesUseCase)
val chooseNoteViewModel = notesInjection.provideChooseNoteViewModel()

ChooseNoteScreen(chooseNoteViewModel = chooseNoteViewModel) { noteId, noteTitle ->
navController.navigate(
Expand All @@ -73,19 +63,7 @@ fun NavigationGraph() {
val noteTitle = backStackEntry.arguments?.getString("noteTitle")

if (noteId != null && noteTitle != null) {
val repository = DocumentRepositoryImpl(
database.documentDao(),
database.storyUnitDao()
)
val storyTellerManager = StoryTellerManager()

val noteDetailsViewModel: NoteDetailsViewModel =
viewModel(
factory = NoteDetailsViewModelFactory(
storyTellerManager,
repository
)
)
val noteDetailsViewModel = notesInjection.provideNoteDetailsViewModel()

NoteDetailsScreen(
noteId.takeIf { it != "null" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.compose.rememberNavController
import br.com.leandroferreira.editor.input.InputScreen
import br.com.leandroferreira.resourcers.R
import com.github.leandroborgesferreira.storyteller.StoryTellerEditor
Expand All @@ -59,8 +58,6 @@ fun NoteDetailsScreen(
noteDetailsViewModel: NoteDetailsViewModel,
navigateBack: () -> Unit,
) {
val navController = rememberNavController()

if (documentId != null) {
noteDetailsViewModel.requestDocumentContent(documentId)
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package br.com.leandroferreira.editor

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.github.leandroborgesferreira.storyteller.backstack.BackstackHandler
import com.github.leandroborgesferreira.storyteller.backstack.BackstackInform
import com.github.leandroborgesferreira.storyteller.manager.DocumentRepository
import com.github.leandroborgesferreira.storyteller.manager.StoryTellerManager
import com.github.leandroborgesferreira.storyteller.model.document.Document
import com.github.leandroborgesferreira.storyteller.model.story.DrawState
import com.github.leandroborgesferreira.storyteller.model.story.StoryState
import com.github.leandroborgesferreira.storyteller.persistence.repository.DocumentRepositoryImpl
import com.github.leandroborgesferreira.storyteller.utils.extensions.noContent
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
Expand All @@ -23,7 +22,7 @@ import java.util.Date

class NoteDetailsViewModel(
val storyTellerManager: StoryTellerManager,
private val documentRepository: DocumentRepositoryImpl
private val documentRepository: DocumentRepository
) : ViewModel(),
BackstackInform by storyTellerManager,
BackstackHandler by storyTellerManager {
Expand Down Expand Up @@ -113,16 +112,3 @@ class NoteDetailsViewModel(
}
}

class NoteDetailsViewModelFactory(
private val storyTellerManager: StoryTellerManager,
private val documentRepository: DocumentRepositoryImpl
) : ViewModelProvider.Factory {


override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(NoteDetailsViewModel::class.java)) {
return NoteDetailsViewModel(storyTellerManager, documentRepository) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,37 @@ import android.content.SharedPreferences
import br.com.leandroferreira.note_menu.data.supermarketList
import br.com.leandroferreira.note_menu.data.travelHistory
import br.com.leandroferreira.note_menu.viewmodel.NotesArrangement
import com.github.leandroborgesferreira.storyteller.manager.DocumentRepository
import com.github.leandroborgesferreira.storyteller.model.document.Document
import com.github.leandroborgesferreira.storyteller.persistence.repository.DocumentRepositoryImpl
import com.github.leandroborgesferreira.storyteller.persistence.sorting.OrderBy
import com.github.leandroborgesferreira.storyteller.persistence.sorting.toEntityField
import java.util.Date
import java.util.UUID

/**
* UseCase responsible to perform CRUD operations in the Notes (Documents) of the app.
*/
class NotesUseCase(
private val documentRepository: DocumentRepositoryImpl,
private val documentRepository: DocumentRepository,
private val sharedPreferences: SharedPreferences
) {

//Todo: Separate the preferences into another Repository
fun saveDocumentArrangementPref(arrangement: NotesArrangement) {
sharedPreferences.edit()
.run { putString(ARRANGE_PREFERENCE, arrangement.type) }
.commit()
}

//Todo: Separate the preferences into another Repository
fun saveDocumentSortingPref(orderBy: OrderBy) {
sharedPreferences.edit()
.run { putString(ORDER_BY_PREFERENCE, orderBy.type.toEntityField()) }
.commit()
}

//Todo: Separate the preferences into another Repository
fun arrangementPref(): String =
sharedPreferences
.getString(ARRANGE_PREFERENCE, NotesArrangement.GRID.type)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ class ChooseNoteViewModel(
private val previewParser: PreviewParser = PreviewParser()
) : ViewModel() {

private val _documentsState: MutableStateFlow<br.com.leandroferreira.utils.ResultData<List<DocumentCard>>> =
MutableStateFlow(br.com.leandroferreira.utils.ResultData.Idle())
val documentsState: StateFlow<br.com.leandroferreira.utils.ResultData<List<DocumentCard>>> = _documentsState
private val _documentsState: MutableStateFlow<ResultData<List<DocumentCard>>> =
MutableStateFlow(ResultData.Idle())
val documentsState: StateFlow<ResultData<List<DocumentCard>>> = _documentsState

private val _notesArrangement = MutableStateFlow<NotesArrangement?>(null)
val notesArrangement = _notesArrangement.asStateFlow()
Expand All @@ -31,7 +31,7 @@ class ChooseNoteViewModel(
val editState = _editState.asStateFlow()

fun requestDocuments() {
if (documentsState.value !is br.com.leandroferreira.utils.ResultData.Complete) {
if (documentsState.value !is ResultData.Complete) {
viewModelScope.launch(Dispatchers.IO) {
refreshDocuments()
}
Expand All @@ -47,7 +47,7 @@ class ChooseNoteViewModel(
}

private suspend fun refreshDocuments() {
_documentsState.value = br.com.leandroferreira.utils.ResultData.Loading()
_documentsState.value = ResultData.Loading()

try {
val data = notesUseCase.loadDocuments()
Expand All @@ -56,9 +56,9 @@ class ChooseNoteViewModel(
}

_notesArrangement.value = NotesArrangement.fromString(notesUseCase.arrangementPref())
_documentsState.value = br.com.leandroferreira.utils.ResultData.Complete(data)
_documentsState.value = ResultData.Complete(data)
} catch (e: Exception) {
_documentsState.value = br.com.leandroferreira.utils.ResultData.Error(e)
_documentsState.value = ResultData.Error(e)
}
}

Expand All @@ -71,7 +71,7 @@ class ChooseNoteViewModel(
document.toUiCard(previewParser)
}

_documentsState.value = br.com.leandroferreira.utils.ResultData.Complete(data)
_documentsState.value = ResultData.Complete(data)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package br.com.leandroferreira.note_menu.viewmodel

/**
* The possible arrangement for notes. The user is able to choose between the variants of the enum
* changing the way notes present themselves in the menu
*/
enum class NotesArrangement(val type: String) {
LIST("list"), GRID("grid");

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
package com.github.leandroborgesferreira.storyteller.manager

import com.github.leandroborgesferreira.storyteller.model.document.Document
import com.github.leandroborgesferreira.storyteller.model.story.StoryStep

//Todo: Add the methods from DocumentRepositoryImpl
interface DocumentRepository {

suspend fun loadDocuments(orderBy: String): List<Document>

suspend fun loadDocumentBy(id: String): Document?

suspend fun saveDocument(document: Document)

suspend fun save(documentId: String, content: Map<Int, StoryStep>)

suspend fun deleteDocument(document: Document)
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ class DocumentRepositoryImpl(
private val storyUnitDao: StoryUnitDao
) : DocumentRepository {

suspend fun loadDocuments(orderBy: String): List<Document> =
override suspend fun loadDocuments(orderBy: String): List<Document> =
documentDao.loadDocumentWithContent(orderBy)
?.map { (documentEntity, storyEntity) ->
val content = loadInnerSteps(storyEntity)
documentEntity.toModel(content)
} ?: emptyList()

suspend fun loadDocumentBy(id: String): Document? =
override suspend fun loadDocumentBy(id: String): Document? =
documentDao.loadDocumentWithContentById(id)
?.entries
?.firstOrNull()
Expand All @@ -30,7 +30,7 @@ class DocumentRepositoryImpl(
documentEntity.toModel(content)
}

suspend fun saveDocument(document: Document) {
override suspend fun saveDocument(document: Document) {
documentDao.insertDocuments(document.toEntity())

document.content?.toEntity(document.id)?.let { data ->
Expand All @@ -39,7 +39,7 @@ class DocumentRepositoryImpl(
}
}

suspend fun deleteDocument(document: Document) {
override suspend fun deleteDocument(document: Document) {
documentDao.deleteDocuments(document.toEntity())
}

Expand Down

0 comments on commit bf833fc

Please sign in to comment.