feat: complete DataViewModel with DataRepository integration and export/delete functionality
Build APK / build (push) Failing after 16m57s
Build APK / build (push) Failing after 16m57s
This commit is contained in:
@@ -7,8 +7,10 @@ import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.senstools.databinding.FragmentDataBinding
|
||||
import com.senstools.presentation.adapter.DataFileAdapter
|
||||
import com.senstools.presentation.viewmodel.DataFile
|
||||
import com.senstools.presentation.viewmodel.DataViewModel
|
||||
|
||||
class DataFragment : Fragment() {
|
||||
@@ -38,8 +40,8 @@ class DataFragment : Fragment() {
|
||||
private fun setupRecyclerView() {
|
||||
adapter = DataFileAdapter(
|
||||
onItemClick = { file -> viewModel.openFile(file) },
|
||||
onExportClick = { file -> viewModel.exportFile(file) },
|
||||
onDeleteClick = { file -> viewModel.deleteFile(file) }
|
||||
onExportClick = { file -> showExportDialog(file) },
|
||||
onDeleteClick = { file -> showDeleteConfirmDialog(file) }
|
||||
)
|
||||
binding.recyclerView.layoutManager = LinearLayoutManager(requireContext())
|
||||
binding.recyclerView.adapter = adapter
|
||||
@@ -49,6 +51,17 @@ class DataFragment : Fragment() {
|
||||
viewModel.dataFiles.observe(viewLifecycleOwner) { files ->
|
||||
adapter.submitList(files)
|
||||
}
|
||||
|
||||
viewModel.isExporting.observe(viewLifecycleOwner) { exporting ->
|
||||
binding.swipeRefresh.isEnabled = !exporting
|
||||
}
|
||||
|
||||
viewModel.exportResult.observe(viewLifecycleOwner) { result ->
|
||||
result?.let {
|
||||
showToast(it)
|
||||
viewModel.clearExportResult()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupListeners() {
|
||||
@@ -58,6 +71,34 @@ class DataFragment : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun showExportDialog(file: DataFile) {
|
||||
val options = arrayOf("Export to CSV", "Export to JSON")
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle("Export: " + file.name)
|
||||
.setItems(options) { _, which ->
|
||||
when (which) {
|
||||
0 -> viewModel.exportToCSV(file)
|
||||
1 -> viewModel.exportToJSON(file)
|
||||
}
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun showDeleteConfirmDialog(file: DataFile) {
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle("Delete File")
|
||||
.setMessage("Delete " + file.name + "?")
|
||||
.setPositiveButton("Delete") { _, _ ->
|
||||
viewModel.deleteFile(file)
|
||||
}
|
||||
.setNegativeButton("Cancel", null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun showToast(message: String) {
|
||||
android.widget.Toast.makeText(requireContext(), message, android.widget.Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
_binding = null
|
||||
|
||||
@@ -1,37 +1,117 @@
|
||||
package com.senstools.presentation.viewmodel
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.senstools.domain.repository.DataRepository
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
|
||||
class DataViewModel : ViewModel() {
|
||||
class DataViewModel(application: Application) : AndroidViewModel(application) {
|
||||
|
||||
private val _dataFiles = MutableLiveData<List<DataFile>>()
|
||||
val dataFiles: LiveData<List<DataFile>> = _dataFiles
|
||||
|
||||
private val _isExporting = MutableLiveData(false)
|
||||
val isExporting: LiveData<Boolean> = _isExporting
|
||||
|
||||
private val _exportResult = MutableLiveData<String?>()
|
||||
val exportResult: LiveData<String?> = _exportResult
|
||||
|
||||
private val dataRepository: DataRepository
|
||||
|
||||
init {
|
||||
dataRepository = DataRepository(application.filesDir)
|
||||
loadFiles()
|
||||
}
|
||||
|
||||
private fun loadFiles() {
|
||||
// Load files from storage
|
||||
_dataFiles.value = emptyList()
|
||||
val files = dataRepository.listDataFiles().map { info ->
|
||||
DataFile(
|
||||
name = info.name,
|
||||
path = info.path,
|
||||
size = info.size,
|
||||
date = info.lastModified
|
||||
)
|
||||
}
|
||||
_dataFiles.value = files
|
||||
}
|
||||
|
||||
fun refreshFiles() {
|
||||
loadFiles()
|
||||
}
|
||||
|
||||
fun openFile(file: DataFile) {
|
||||
// Open file for viewing
|
||||
fun openFile(file: DataFile) { // placeholder
|
||||
}
|
||||
|
||||
fun exportFile(file: DataFile) {
|
||||
// Export file to CSV/JSON
|
||||
fun exportToCSV(file: DataFile) {
|
||||
viewModelScope.launch {
|
||||
_isExporting.value = true
|
||||
val result = withContext(Dispatchers.IO) {
|
||||
val exportDir = File(
|
||||
getApplication<Application>().filesDir,
|
||||
"senstools_export"
|
||||
)
|
||||
exportDir.mkdirs()
|
||||
val csvPath = File(exportDir, file.name.replace(".bin", ".csv")).absolutePath
|
||||
val success = dataRepository.exportToCSV(file.path, csvPath)
|
||||
success to csvPath
|
||||
}
|
||||
_exportResult.value = if (result.first) {
|
||||
"CSV exported to: " + result.second
|
||||
} else {
|
||||
"CSV export failed"
|
||||
}
|
||||
_isExporting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
fun exportToJSON(file: DataFile) {
|
||||
viewModelScope.launch {
|
||||
_isExporting.value = true
|
||||
val result = withContext(Dispatchers.IO) {
|
||||
val exportDir = File(
|
||||
getApplication<Application>().filesDir,
|
||||
"senstools_export"
|
||||
)
|
||||
exportDir.mkdirs()
|
||||
val jsonPath = File(exportDir, file.name.replace(".bin", ".json")).absolutePath
|
||||
val success = dataRepository.exportToJSON(file.path, jsonPath)
|
||||
success to jsonPath
|
||||
}
|
||||
_exportResult.value = if (result.first) {
|
||||
"JSON exported to: " + result.second
|
||||
} else {
|
||||
"JSON export failed"
|
||||
}
|
||||
_isExporting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteFile(file: DataFile) {
|
||||
// Delete file
|
||||
viewModelScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
dataRepository.deleteFile(file.name)
|
||||
}
|
||||
loadFiles()
|
||||
}
|
||||
}
|
||||
|
||||
fun deleteAll() {
|
||||
viewModelScope.launch {
|
||||
withContext(Dispatchers.IO) {
|
||||
dataRepository.deleteAll()
|
||||
}
|
||||
loadFiles()
|
||||
}
|
||||
}
|
||||
|
||||
fun clearExportResult() {
|
||||
_exportResult.value = null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user