-
-
Notifications
You must be signed in to change notification settings - Fork 20
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
Added import/export to html functionality #54
Added import/export to html functionality #54
Conversation
app/src/main/java/com/amrdeveloper/linkhub/ui/importexporthtml/ImportExportFragmentHtml.kt
Outdated
Show resolved
Hide resolved
app/src/main/java/com/amrdeveloper/linkhub/ui/importexporthtml/ImportExportHtmlViewModel.kt
Outdated
Show resolved
Hide resolved
Hello @GalievBulat, The code looks great for me but we need to make the design more simpler so we can add more extensions on the same view Maybe Allow the intent to select json or html and depending on the file we select parser, or make the Import button open a dialog or spinner with options |
@AmrDeveloper yes, I see your point: I think it would be a better decision to implement the functionality on the single fragment, and then change the type of import/export, according to the user's preferences |
@AmrDeveloper in new commit I've moved import/export functionality into a single abstract Parser class, so check it out, please |
moved import/export data handling logic to view model
@AmrDeveloper thank you, I think the requested changes are important to do: so I've made a file type picking dialog on an ImportExportFragment. So when user clicks import/export he first needs to pick a file type first |
package com.amrdeveloper.linkhub.data | ||
|
||
enum class ImportExportFileType(val mimeType: String, val extension: String, val fileTypeName: String) { | ||
|
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.
Please remove empty line
@@ -34,6 +34,13 @@ class FolderLocalDataSource internal constructor( | |||
Result.failure(e) | |||
} | |||
} | |||
override suspend fun getFolderByName(name : String): Result<Folder> = withContext(ioDispatcher) { |
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.
Add new line before method declaration
@@ -42,11 +43,19 @@ class ImportExportFragment : Fragment() { | |||
|
|||
private fun setupListeners() { | |||
binding.importAction.setOnClickListener { | |||
importDataFile() | |||
context?.let { ImportExportFileTypePickerDialog.launch(it) { fileType -> |
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.
Please format the code
context?.let {
ImportExportFileTypePickerDialog.launch(it) { fileType ->
importExportViewModel.setFileType(fileType)
importDataFile()
}
}
@@ -29,73 +29,75 @@ class ImportExportViewModel @Inject constructor ( | |||
) : ViewModel() { | |||
|
|||
private val _stateMessages = MutableLiveData<Int>() | |||
private var importExportFileParser: ImportExportFileParser = JsonImportExportFileParser() |
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.
We don't need to create instance of JsonImportExportFileParser then depending on type we create another parser instance so lets pass FileType to import and export functions and use the correct parser for this type
It will make code simpler and save memory
val mimeType: String | ||
get() = | ||
importExportFileParser.getFileType().mimeType | ||
val extension: String | ||
get() = | ||
importExportFileParser.getFileType().extension |
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.
Remove those variables and pass the selected FileType to the place we need it
// Import theme flag if it available | ||
val lastThemeOption = uiPreferences.getThemeType() | ||
uiPreferences.setThemeType(dataPackage.theme ?: lastThemeOption) | ||
fun setFileType(fileType: ImportExportFileType){ |
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.
Remove this function and pass the FileType directly to import / export functions
Thank you for update, there are some design points and feel free to discuss your idea and suggestion My point is that import and export functions on view model should take the type and do their work, later they will pass this type to factory for example
The view model will not know which parser it used and don't save the file type |
@AmrDeveloper thanks for the suggested changes: I've change the code according to them, so please review the commit |
@@ -28,79 +26,77 @@ class ImportExportViewModel @Inject constructor ( | |||
private val uiPreferences: UiPreferences, | |||
) : ViewModel() { | |||
|
|||
private var importExportFileType: ImportExportFileType? = null |
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.
Now we don't need this variable
object ImportExportFileTypePickerDialog { | ||
|
||
fun launch(context: Context, onFileTypeSelected: (ImportExportFileType)->Unit) { | ||
val fileTypes = ImportExportFileType.entries.map { it.fileTypeName } | ||
val builder = AlertDialog.Builder(context) | ||
builder.setTitle(context.getString(R.string.import_export_choose_file_type)) | ||
builder.setItems(fileTypes.toTypedArray()) { dialog, which -> | ||
val selectedFileType = ImportExportFileType.entries[which] | ||
onFileTypeSelected(selectedFileType) | ||
dialog.dismiss() | ||
} | ||
val dialog = builder.create() | ||
dialog.show() | ||
} | ||
} |
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.
We can move this to a function in ImportExport settings because it's only needed their launchImportExportFileTypePicker
object ImportExportFileParserFactory { | ||
fun getInstance(fileType: ImportExportFileType): ImportExportFileParser { | ||
return when (fileType) { | ||
ImportExportFileType.JSON -> JsonImportExportFileParser() | ||
ImportExportFileType.HTML -> HtmlImportExportFileParser() | ||
} | ||
} | ||
} |
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.
You can create the factory pattern but as a single function in the view model for now
fun getDataParser(fileType: ImportExportFileType): ImportExportFileParser {
return when (fileType) {
ImportExportFileType.JSON -> JsonImportExportFileParser()
ImportExportFileType.HTML -> HtmlImportExportFileParser()
}
}
@@ -42,11 +45,21 @@ class ImportExportFragment : Fragment() { | |||
|
|||
private fun setupListeners() { | |||
binding.importAction.setOnClickListener { | |||
importDataFile() | |||
context?.let { |
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.
After converting this picker to function you can use requireContext()
it will return non nullable context to you to use directly
@@ -23,6 +25,7 @@ import dagger.hilt.android.AndroidEntryPoint | |||
@AndroidEntryPoint | |||
class ImportExportFragment : Fragment() { | |||
|
|||
private var importExportFileType: ImportExportFileType? = null |
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.
Can be remove this variable and pass the state between functions?
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.
I think there the state of importExportFileType cannot be omitted because registerForActivityResult should be declared before they fragment is created, so I think we cannot pass the state between functions
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.
Okey lets keep it for now
Thank you @GalievBulat for changes, i have a little changes in places and file structure and everything else is good for me, |
I've made the requested changes, so please check once again |
Thank you for great work @GalievBulat |
I've made the requested functionality, while preserving the original code style. I've made the import/export setting close to the import/export setting of json files functionality. Feel free to make changes to the code/design.