-
Notifications
You must be signed in to change notification settings - Fork 1
[REF/#637] mlkit 로직 분리 #697
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 5 commits
3cc09e0
4eab9ef
0f7fc8c
d933861
0c27173
3cf975d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 모듈을 따로 분리하지 않고 다이어리 모듈 안에 구현하신 이유가 궁금합니다!
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 좋은 리뷰 감사합니다 ㅎㅎ 텍스트 인식이 diary 도메인의 핵심 책임은 아니라는 데 동의합니다. 다만 현재는 일기 작성에서만 사용되고 Repository로 이미 추상화되어 있어 실제 재사용 필요성이 생길 때 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package com.hilingual.data.diary.repository | ||
|
|
||
| import android.net.Uri | ||
|
|
||
| interface TextRecognitionRepository { | ||
| suspend fun extractTextFromImage(uri: Uri): Result<String> | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 메소드명 굉장히 직관적이고 좋은 것 같습니다👍🏻👍🏻 |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package com.hilingual.data.diary.repositoryimpl | ||
|
|
||
| import android.content.Context | ||
| import android.net.Uri | ||
| import com.google.mlkit.vision.common.InputImage | ||
| import com.google.mlkit.vision.text.TextRecognition | ||
| import com.google.mlkit.vision.text.latin.TextRecognizerOptions | ||
| import com.hilingual.data.diary.repository.TextRecognitionRepository | ||
| import dagger.hilt.android.qualifiers.ApplicationContext | ||
| import kotlinx.coroutines.Dispatchers | ||
| import kotlinx.coroutines.tasks.await | ||
| import kotlinx.coroutines.withContext | ||
| import javax.inject.Inject | ||
|
|
||
| class TextRecognitionRepositoryImpl @Inject constructor( | ||
| @ApplicationContext private val context: Context | ||
| ) : TextRecognitionRepository { | ||
|
|
||
| private val recognizer by lazy { | ||
| TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS) | ||
| } | ||
|
||
|
|
||
| override suspend fun extractTextFromImage(uri: Uri): Result<String> = | ||
| withContext(Dispatchers.IO) { | ||
| runCatching { | ||
| val image = InputImage.fromFilePath(context, uri) | ||
| recognizer.process(image).await().text | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,24 +15,20 @@ | |
| */ | ||
| package com.hilingual.presentation.diarywrite | ||
|
|
||
| import android.content.Context | ||
| import android.net.Uri | ||
| import androidx.lifecycle.SavedStateHandle | ||
| import androidx.lifecycle.ViewModel | ||
| import androidx.lifecycle.viewModelScope | ||
| import androidx.navigation.toRoute | ||
| import com.google.mlkit.vision.common.InputImage | ||
| import com.google.mlkit.vision.text.TextRecognition | ||
| import com.google.mlkit.vision.text.latin.TextRecognizerOptions | ||
| import com.hilingual.core.common.extension.onLogFailure | ||
| import com.hilingual.core.common.util.UiState | ||
| import com.hilingual.core.navigation.DiaryWriteMode | ||
| import com.hilingual.data.calendar.repository.CalendarRepository | ||
| import com.hilingual.data.diary.localstorage.DiaryTempRepository | ||
| import com.hilingual.data.diary.repository.DiaryRepository | ||
| import com.hilingual.data.diary.repository.TextRecognitionRepository | ||
| import com.hilingual.presentation.diarywrite.navigation.DiaryWrite | ||
| import dagger.hilt.android.lifecycle.HiltViewModel | ||
| import dagger.hilt.android.qualifiers.ApplicationContext | ||
| import kotlinx.coroutines.Dispatchers | ||
| import kotlinx.coroutines.flow.MutableSharedFlow | ||
| import kotlinx.coroutines.flow.MutableStateFlow | ||
|
|
@@ -42,7 +38,6 @@ import kotlinx.coroutines.flow.asSharedFlow | |
| import kotlinx.coroutines.flow.asStateFlow | ||
| import kotlinx.coroutines.flow.update | ||
| import kotlinx.coroutines.launch | ||
| import kotlinx.coroutines.tasks.await | ||
| import kotlinx.coroutines.withContext | ||
| import timber.log.Timber | ||
| import java.io.File | ||
|
|
@@ -52,10 +47,10 @@ import javax.inject.Inject | |
| @HiltViewModel | ||
| internal class DiaryWriteViewModel @Inject constructor( | ||
| savedStateHandle: SavedStateHandle, | ||
| @ApplicationContext private val context: Context, | ||
| private val calendarRepository: CalendarRepository, | ||
| private val diaryRepository: DiaryRepository, | ||
| private val diaryTempRepository: DiaryTempRepository | ||
| private val diaryTempRepository: DiaryTempRepository, | ||
| private val textRecognitionRepository: TextRecognitionRepository | ||
| ) : ViewModel() { | ||
| private val route: DiaryWrite = savedStateHandle.toRoute<DiaryWrite>() | ||
|
|
||
|
|
@@ -186,22 +181,17 @@ internal class DiaryWriteViewModel @Inject constructor( | |
| fun extractTextFromImage(uri: Uri, tempFileToDelete: File? = null) { | ||
| viewModelScope.launch { | ||
| try { | ||
| runCatching { | ||
| withContext(Dispatchers.IO) { | ||
| val image = InputImage.fromFilePath(context, uri) | ||
| val recognizer = | ||
| TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS) | ||
| recognizer.process(image).await().text | ||
| textRecognitionRepository.extractTextFromImage(uri) | ||
| .onSuccess { extractedText -> | ||
| _uiState.update { | ||
| it.copy( | ||
| diaryText = extractedText.take(MAX_DIARY_TEXT_LENGTH) | ||
| ) | ||
| } | ||
| } | ||
| }.onSuccess { extractedText -> | ||
| _uiState.update { | ||
| it.copy( | ||
| diaryText = extractedText.take(MAX_DIARY_TEXT_LENGTH) | ||
| ) | ||
| .onFailure { throwable -> | ||
|
||
| Timber.tag("DiaryWriteViewModel").e(throwable, "Text recognition failed") | ||
|
||
| } | ||
| }.onFailure { throwable -> | ||
| Timber.tag("DiaryWriteViewModel").e(throwable, "Text recognition failed") | ||
| } | ||
| } finally { | ||
| withContext(Dispatchers.IO) { | ||
| if (tempFileToDelete?.exists() == true) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오호 레포지토리를 새로 만드니까 얘네 의존성도
data > diary로 이동하는군요There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
음...이 부분도 고민은 한번 해봤으면 해요.
data:diary모듈은 다이어리 데이터의 영속성을 관리하는 역할에 집중해야 한다고 생각해요. 지금은 '이미지에서 텍스트를 추출하는 기능' 이고 과연 Diary라는 도메인의 기능인가? 라는 의문이 생기네요. 장기적으로 보면core:ml혹은data:recognition같은 모듈로 분리하는 과정이 필요할 수도 있을 것 같아요ㅎㅎ 그냥 고민만 해보셔