diff --git a/app/release/baselineProfiles/0/app-release.dm b/app/release/baselineProfiles/0/app-release.dm index 0a36505..1459877 100644 Binary files a/app/release/baselineProfiles/0/app-release.dm and b/app/release/baselineProfiles/0/app-release.dm differ diff --git a/app/release/baselineProfiles/1/app-release.dm b/app/release/baselineProfiles/1/app-release.dm index 0123e74..a3e9a08 100644 Binary files a/app/release/baselineProfiles/1/app-release.dm and b/app/release/baselineProfiles/1/app-release.dm differ diff --git a/app/release/ver1.apk b/app/release/ver1.1.apk similarity index 88% rename from app/release/ver1.apk rename to app/release/ver1.1.apk index e55c495..1b6d1ec 100644 Binary files a/app/release/ver1.apk and b/app/release/ver1.1.apk differ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index fbd0327..010eeb2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,7 +3,6 @@ xmlns:tools="http://schemas.android.com/tools"> - - - - - = _notes.asStateFlow() - private val _updateInfo = MutableStateFlow(null) - val updateInfo: StateFlow = _updateInfo.asStateFlow() - - data class UpdateInfo(val versionCode: Int, val apkUrl: String) - - fun checkForUpdates(context: Context) { - viewModelScope.launch(Dispatchers.IO) { + fun loadState(context: Context) { + val prefs = context.getSharedPreferences("inventory_prefs", Context.MODE_PRIVATE) + _notes.value = prefs.getString("notes", "") ?: "" + + val machinesJson = prefs.getString("machines", null) + if (machinesJson != null) { try { - val url = URL("https://bbjsolution.org/AR/InwentARyzacja/src/branch/master/update.json") - val connection = url.openConnection() as HttpURLConnection - connection.connectTimeout = 5000 - connection.readTimeout = 5000 - - if (connection.responseCode == 200) { - val scanner = Scanner(connection.inputStream).useDelimiter("\\A") - val result = if (scanner.hasNext()) scanner.next() else "" - val json = JSONObject(result) - - val newVersionCode = json.getInt("versionCode") - val apkUrl = json.getString("url") - - val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0) - @Suppress("DEPRECATION") - val currentVersionCode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - packageInfo.longVersionCode.toInt() - } else { - packageInfo.versionCode - } - - if (newVersionCode > currentVersionCode) { - _updateInfo.value = UpdateInfo(newVersionCode, apkUrl) - } + val jsonArray = JSONArray(machinesJson) + val loadedList = mutableListOf() + for (i in 0 until jsonArray.length()) { + val obj = jsonArray.getJSONObject(i) + loadedList.add( + Machine( + id = obj.getString("id"), + name = obj.getString("name"), + category = obj.getString("category"), + originalStatus = obj.getString("originalStatus"), + isChecked = obj.getBoolean("isChecked") + ) + ) } + _machines.value = loadedList } catch (e: Exception) { e.printStackTrace() } } } - fun downloadAndInstall(context: Context, apkUrl: String) { - val request = DownloadManager.Request(Uri.parse(apkUrl)) - .setTitle("Aktualizacja inwentARyzacja") - .setDescription("Pobieranie nowej wersji...") - .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) - .setDestinationInExternalFilesDir(context, Environment.DIRECTORY_DOWNLOADS, "update.apk") - .setAllowedOverMetered(true) - .setAllowedOverRoaming(true) - - val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager - downloadManager.enqueue(request) + private fun saveState(context: Context) { + val prefs = context.getSharedPreferences("inventory_prefs", Context.MODE_PRIVATE) + val editor = prefs.edit() + editor.putString("notes", _notes.value) + + val jsonArray = JSONArray() + _machines.value.forEach { machine -> + val obj = JSONObject() + obj.put("id", machine.id) + obj.put("name", machine.name) + obj.put("category", machine.category) + obj.put("originalStatus", machine.originalStatus) + obj.put("isChecked", machine.isChecked) + jsonArray.put(obj) + } + editor.putString("machines", jsonArray.toString()) + editor.apply() } fun setSearchQuery(query: String) { _searchQuery.value = query } - fun setNotes(newNotes: String) { + fun setNotes(context: Context, newNotes: String) { _notes.value = newNotes + saveState(context) } fun appendDigit(digit: String) { @@ -181,7 +162,7 @@ class InventoryViewModel : ViewModel() { .sorted() } - fun markMachinesByStatuses(statuses: Set, isChecked: Boolean) { + fun markMachinesByStatuses(context: Context, statuses: Set, isChecked: Boolean) { _machines.value = _machines.value.map { machine -> if (statuses.contains(machine.originalStatus)) { machine.copy(isChecked = isChecked) @@ -189,9 +170,10 @@ class InventoryViewModel : ViewModel() { machine } } + saveState(context) } - fun toggleMachineCheck(machineId: String) { + fun toggleMachineCheck(context: Context, machineId: String) { _machines.value = _machines.value.map { machine -> if (machine.id == machineId) { machine.copy(isChecked = !machine.isChecked) @@ -199,10 +181,11 @@ class InventoryViewModel : ViewModel() { machine } } + saveState(context) } // Parser zoptymalizowany pod strukturę raportu z systemu - fun parseXlsFile(inputStream: InputStream) { + fun parseXlsFile(context: Context, inputStream: InputStream) { try { // WorkbookFactory automatycznie obsługuje zarówno .xls jak i .xlsx val workbook = WorkbookFactory.create(inputStream) @@ -232,6 +215,7 @@ class InventoryViewModel : ViewModel() { } _machines.value = parsedList workbook.close() + saveState(context) } catch (e: Exception) { e.printStackTrace() } @@ -242,38 +226,10 @@ class InventoryViewModel : ViewModel() { // 3. GŁÓWNA AKTYWNOŚĆ // ========================================== class MainActivity : ComponentActivity() { - private val onDownloadComplete = object : BroadcastReceiver() { - override fun onReceive(context: Context, intent: Intent) { - val id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1) - if (id != -1L) { - installApk(context) - } - } - } - - private fun installApk(context: Context) { - val file = File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "update.apk") - if (file.exists()) { - val uri = FileProvider.getUriForFile(context, "${context.packageName}.fileprovider", file) - val intent = Intent(Intent.ACTION_VIEW) - intent.setDataAndType(uri, "application/vnd.android.package-archive") - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - context.startActivity(intent) - } - } - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() - ContextCompat.registerReceiver( - this, - onDownloadComplete, - IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE), - ContextCompat.RECEIVER_EXPORTED - ) - setContent { MaterialTheme( colorScheme = darkColorScheme( @@ -291,10 +247,6 @@ class MainActivity : ComponentActivity() { } } } - override fun onDestroy() { - super.onDestroy() - unregisterReceiver(onDownloadComplete) - } } // ========================================== @@ -308,42 +260,12 @@ fun InventoryScreen(viewModel: InventoryViewModel = viewModel()) { val searchQuery by viewModel.searchQuery.collectAsState() val filterMissing by viewModel.filterMissing.collectAsState() val notes by viewModel.notes.collectAsState() - val updateInfo by viewModel.updateInfo.collectAsState() var showStatusDialog by remember { mutableStateOf(false) } var showNotesDialog by remember { mutableStateOf(false) } - var showUpdateDialog by remember { mutableStateOf(false) } LaunchedEffect(Unit) { - viewModel.checkForUpdates(context) - } - - LaunchedEffect(updateInfo) { - if (updateInfo != null) { - showUpdateDialog = true - } - } - - if (showUpdateDialog && updateInfo != null) { - AlertDialog( - onDismissRequest = { showUpdateDialog = false }, - title = { Text("Dostępna aktualizacja", color = Color.White) }, - text = { Text("Czy chcesz pobrać i zainstalować nową wersję aplikacji?", color = Color.White) }, - confirmButton = { - Button(onClick = { - viewModel.downloadAndInstall(context, updateInfo!!.apkUrl) - showUpdateDialog = false - }) { - Text("Pobierz") - } - }, - dismissButton = { - TextButton(onClick = { showUpdateDialog = false }) { - Text("Później") - } - }, - containerColor = Color(0xFF1E2638) - ) + viewModel.loadState(context) } // Launcher akceptujący pliki .xlsx oraz .xls @@ -352,7 +274,7 @@ fun InventoryScreen(viewModel: InventoryViewModel = viewModel()) { ) { uri: Uri? -> uri?.let { context.contentResolver.openInputStream(it)?.use { inputStream -> - viewModel.parseXlsFile(inputStream) + viewModel.parseXlsFile(context, inputStream) } } } @@ -362,7 +284,7 @@ fun InventoryScreen(viewModel: InventoryViewModel = viewModel()) { statuses = viewModel.getUniqueStatuses(), onDismiss = { showStatusDialog = false }, onConfirm = { selectedStatuses -> - viewModel.markMachinesByStatuses(selectedStatuses, true) + viewModel.markMachinesByStatuses(context, selectedStatuses, true) showStatusDialog = false } ) @@ -371,7 +293,7 @@ fun InventoryScreen(viewModel: InventoryViewModel = viewModel()) { if (showNotesDialog) { NotesDialog( notes = notes, - onNotesChange = { viewModel.setNotes(it) }, + onNotesChange = { viewModel.setNotes(context, it) }, onDismiss = { showNotesDialog = false } ) } @@ -484,7 +406,7 @@ fun InventoryScreen(viewModel: InventoryViewModel = viewModel()) { items(filteredMachines, key = { it.id }) { machine -> MachineItem( machine = machine, - onToggle = { viewModel.toggleMachineCheck(machine.id) } + onToggle = { viewModel.toggleMachineCheck(context, machine.id) } ) } } diff --git a/app/src/main/res/xml/file_paths.xml b/app/src/main/res/xml/file_paths.xml deleted file mode 100644 index 7f68867..0000000 --- a/app/src/main/res/xml/file_paths.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file