/** * TrackerMap * Copyright (C) 2021-2022 Iván Ávalos , Henoch Ojeda * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package mx.trackermap.TrackerMap.android.details.information import android.content.Intent import android.net.Uri import android.os.Bundle import android.util.Log import android.util.TypedValue import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.LinearLayout import android.widget.TextView import androidx.core.content.res.ResourcesCompat import androidx.core.widget.TextViewCompat import androidx.fragment.app.Fragment import com.google.android.material.button.MaterialButton import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.serialization.json.longOrNull import mx.trackermap.TrackerMap.android.R import mx.trackermap.TrackerMap.android.databinding.UnitDetailsInformationBinding import mx.trackermap.TrackerMap.android.details.UnitDetailsAdapter import mx.trackermap.TrackerMap.android.shared.MarkerTransformations import mx.trackermap.TrackerMap.client.models.UnitInformation import mx.trackermap.TrackerMap.utils.Formatter import mx.trackermap.TrackerMap.utils.SpeedUnit import org.koin.androidx.viewmodel.ext.android.viewModel import kotlin.time.ExperimentalTime @DelicateCoroutinesApi @ExperimentalTime class UnitInformationFragment : Fragment() { private var _binding: UnitDetailsInformationBinding? = null private val binding get() = _binding!! private val unitInformationViewModel: UnitInformationViewModel by viewModel() override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = UnitDetailsInformationBinding.inflate(inflater, container, false) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) fetchInformation() setupObservers() } override fun onDestroyView() { super.onDestroyView() removeObservers() _binding = null } private fun setupObservers() { unitInformationViewModel.unit.observe(viewLifecycleOwner) { unitInformation -> Log.d("UnitInformationFragment", "Unit Information Fetched - $unitInformation") binding.reportLoading.root.visibility = View.GONE unitInformation?.let { displayInformation(it) } } } private fun removeObservers() { unitInformationViewModel.unit.removeObservers(viewLifecycleOwner) } private fun fetchInformation() { val id = arguments?.getInt(UnitDetailsAdapter.DEVICE_ID_ARG) val name = arguments?.getString(UnitDetailsAdapter.DEVICE_NAME_ARG) val category = arguments?.getString(UnitDetailsAdapter.DEVICE_CATEGORY_ARG) unitInformationViewModel.fetchUnit(id ?: 0) binding.nameDetail.text = name context?.let { val metrics = it.resources.displayMetrics val icon = ResourcesCompat.getDrawable( it.resources, MarkerTransformations.categoryToResourceId(category), it.theme ) icon?.setBounds(0, 0, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 40f, metrics).toInt(), TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 40f, metrics).toInt() ) binding.nameDetail.setCompoundDrawables( icon, null, null, null ) } binding.nameDetail.compoundDrawablePadding = resources.getDimensionPixelSize(R.dimen.card_icon_margin) binding.reportLoading.root.visibility = View.VISIBLE } private fun displayInformation(unit: UnitInformation) { val context = context!! val details: MutableList> = mutableListOf() unit.device.contact?.let { contact -> details.add(getString(R.string.unit_info_contact) to contact) } unit.device.uniqueId?.let { uniqueId -> details.add(getString(R.string.unit_info_uniqueid) to uniqueId) } unit.position?.fixTime?.let { fixTime -> details.add(getString(R.string.unit_info_datetime) to Formatter.formatDate(fixTime)) } unit.position?.latitude?.let { latitude -> details.add(getString(R.string.unit_info_latitude) to "$latitude") } unit.position?.longitude?.let { longitude -> details.add(getString(R.string.unit_info_longitude) to "$longitude") } unit.position?.speed?.let { speed -> details.add( getString(R.string.unit_info_speed) to Formatter.formatSpeed( speed, SpeedUnit.KMH ) ) } unit.position?.address?.let { address -> details.add(getString(R.string.unit_info_address) to address) } unit.position?.attributes?.get("hours")?.longOrNull?.let { if (it > 0) { details.add( getString(R.string.unit_hourmeter) to Formatter.formatHours(it) ) } } unit.position?.protocol?.let { protocol -> details.add(getString(R.string.unit_info_protocol) to protocol) } details.forEach { entry -> val layout = LinearLayout(context) layout.orientation = LinearLayout.VERTICAL val params = LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT ) params.setMargins(0, 0, 0, resources.getDimensionPixelSize(R.dimen.fields_spacing)) layout.layoutParams = params val text1 = TextView(context) TextViewCompat.setTextAppearance(text1, R.style.TextAppearance_AppCompat_Body2) text1.text = entry.first val text2 = TextView(context) text2.text = entry.second layout.addView(text1) layout.addView(text2) binding.detailsLayout.addView(layout) } if (unit.position?.latitude != null && unit.position?.longitude != null) { val mapButton = MaterialButton(context) mapButton.text = getString(R.string.unit_info_map_button) mapButton.setOnClickListener { val latitude = unit.position!!.latitude val longitude = unit.position!!.longitude val url = getString(R.string.maps_url_template, latitude, longitude) startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) } binding.detailsLayout.addView(mapButton) } } }