Skip to content
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

Merged
merged 6 commits into from
Mar 27, 2024

Conversation

GalievBulat
Copy link
Contributor

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.

@AmrDeveloper
Copy link
Owner

AmrDeveloper commented Mar 20, 2024

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

@GalievBulat
Copy link
Contributor Author

@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

@GalievBulat
Copy link
Contributor Author

@AmrDeveloper in new commit I've moved import/export functionality into a single abstract Parser class, so check it out, please

app/src/main/res/layout/fragment_setting.xml Outdated Show resolved Hide resolved
app/src/main/res/layout/fragment_setting.xml Outdated Show resolved Hide resolved
app/src/main/res/navigation/nav_graph.xml Show resolved Hide resolved
@GalievBulat
Copy link
Contributor Author

@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) {

Copy link
Owner

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) {
Copy link
Owner

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 ->
Copy link
Owner

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()
Copy link
Owner

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

Comment on lines 35 to 40
val mimeType: String
get() =
importExportFileParser.getFileType().mimeType
val extension: String
get() =
importExportFileParser.getFileType().extension
Copy link
Owner

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){
Copy link
Owner

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

@AmrDeveloper
Copy link
Owner

@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

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

val parser = FileParserFactory.getInstance(fileType)
parser.import() or parser.export()

The view model will not know which parser it used and don't save the file type

@GalievBulat
Copy link
Contributor Author

@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
Copy link
Owner

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

Comment on lines 8 to 22
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()
}
}
Copy link
Owner

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

Comment on lines 10 to 17
object ImportExportFileParserFactory {
fun getInstance(fileType: ImportExportFileType): ImportExportFileParser {
return when (fileType) {
ImportExportFileType.JSON -> JsonImportExportFileParser()
ImportExportFileType.HTML -> HtmlImportExportFileParser()
}
}
}
Copy link
Owner

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 {
Copy link
Owner

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
Copy link
Owner

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?

Copy link
Contributor Author

@GalievBulat GalievBulat Mar 27, 2024

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

Copy link
Owner

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

@AmrDeveloper
Copy link
Owner

Thank you @GalievBulat for changes, i have a little changes in places and file structure and everything else is good for me,

@GalievBulat
Copy link
Contributor Author

I've made the requested changes, so please check once again

@AmrDeveloper
Copy link
Owner

Thank you for great work @GalievBulat

@AmrDeveloper AmrDeveloper merged commit ae2c071 into AmrDeveloper:master Mar 27, 2024
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants