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.Fragment
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.senstools.databinding.FragmentDataBinding
|
import com.senstools.databinding.FragmentDataBinding
|
||||||
import com.senstools.presentation.adapter.DataFileAdapter
|
import com.senstools.presentation.adapter.DataFileAdapter
|
||||||
|
import com.senstools.presentation.viewmodel.DataFile
|
||||||
import com.senstools.presentation.viewmodel.DataViewModel
|
import com.senstools.presentation.viewmodel.DataViewModel
|
||||||
|
|
||||||
class DataFragment : Fragment() {
|
class DataFragment : Fragment() {
|
||||||
@@ -38,8 +40,8 @@ class DataFragment : Fragment() {
|
|||||||
private fun setupRecyclerView() {
|
private fun setupRecyclerView() {
|
||||||
adapter = DataFileAdapter(
|
adapter = DataFileAdapter(
|
||||||
onItemClick = { file -> viewModel.openFile(file) },
|
onItemClick = { file -> viewModel.openFile(file) },
|
||||||
onExportClick = { file -> viewModel.exportFile(file) },
|
onExportClick = { file -> showExportDialog(file) },
|
||||||
onDeleteClick = { file -> viewModel.deleteFile(file) }
|
onDeleteClick = { file -> showDeleteConfirmDialog(file) }
|
||||||
)
|
)
|
||||||
binding.recyclerView.layoutManager = LinearLayoutManager(requireContext())
|
binding.recyclerView.layoutManager = LinearLayoutManager(requireContext())
|
||||||
binding.recyclerView.adapter = adapter
|
binding.recyclerView.adapter = adapter
|
||||||
@@ -49,6 +51,17 @@ class DataFragment : Fragment() {
|
|||||||
viewModel.dataFiles.observe(viewLifecycleOwner) { files ->
|
viewModel.dataFiles.observe(viewLifecycleOwner) { files ->
|
||||||
adapter.submitList(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() {
|
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() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
_binding = null
|
_binding = null
|
||||||
|
|||||||
@@ -1,37 +1,117 @@
|
|||||||
package com.senstools.presentation.viewmodel
|
package com.senstools.presentation.viewmodel
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import androidx.lifecycle.AndroidViewModel
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
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>>()
|
private val _dataFiles = MutableLiveData<List<DataFile>>()
|
||||||
val dataFiles: LiveData<List<DataFile>> = _dataFiles
|
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 {
|
init {
|
||||||
|
dataRepository = DataRepository(application.filesDir)
|
||||||
loadFiles()
|
loadFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadFiles() {
|
private fun loadFiles() {
|
||||||
// Load files from storage
|
val files = dataRepository.listDataFiles().map { info ->
|
||||||
_dataFiles.value = emptyList()
|
DataFile(
|
||||||
|
name = info.name,
|
||||||
|
path = info.path,
|
||||||
|
size = info.size,
|
||||||
|
date = info.lastModified
|
||||||
|
)
|
||||||
|
}
|
||||||
|
_dataFiles.value = files
|
||||||
}
|
}
|
||||||
|
|
||||||
fun refreshFiles() {
|
fun refreshFiles() {
|
||||||
loadFiles()
|
loadFiles()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun openFile(file: DataFile) {
|
fun openFile(file: DataFile) { // placeholder
|
||||||
// Open file for viewing
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exportFile(file: DataFile) {
|
fun exportToCSV(file: DataFile) {
|
||||||
// Export file to CSV/JSON
|
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) {
|
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