diff --git a/app/src/main/java/com/rtbishop/look4sat/MainViewModel.kt b/app/src/main/java/com/rtbishop/look4sat/MainViewModel.kt index 62f15cf2..a6e30c7d 100644 --- a/app/src/main/java/com/rtbishop/look4sat/MainViewModel.kt +++ b/app/src/main/java/com/rtbishop/look4sat/MainViewModel.kt @@ -49,19 +49,33 @@ import javax.inject.Inject class MainViewModel(application: Application) : AndroidViewModel(application) { private val defValueLoc = application.getString(R.string.def_gsp_loc) - private val defValueHours = application.getString(R.string.def_hours_ahead) - private val defValueMinEl = application.getString(R.string.def_min_el) + private val defValueHours = application.getString(R.string.def_hours_ahead).toInt() + private val defValueMinEl = application.getString(R.string.def_min_el).toDouble() private val defValueUpdateFreq = application.getString(R.string.def_update_freq) + private val keyHours = application.getString(R.string.key_hours_ahead) + private val keyMinEl = application.getString(R.string.key_min_el) private val keyLat = application.getString(R.string.key_lat) private val keyLon = application.getString(R.string.key_lon) private val keyAlt = application.getString(R.string.key_alt) - private val keyHours = application.getString(R.string.key_hours_ahead) - private val keyMinEl = application.getString(R.string.key_min_el) - private val keyUpdateFreq = application.getString(R.string.key_update_freq) + private val keyDelay = application.getString(R.string.key_delay) private val tleMainListFileName = application.getString(R.string.tle_main_list_file_name) private val tleSelectionFileName = application.getString(R.string.tle_selection_file_name) private val app = application + private val _debugMessage = MutableLiveData() + val debugMessage: LiveData = _debugMessage + + private val _satPassList = MutableLiveData>() + val passSatList: LiveData> = _satPassList + + private val _gsp = MutableLiveData() + val gsp: LiveData = _gsp + + private val urlList = listOf( + "https://celestrak.com/NORAD/elements/amateur.txt", + "https://celestrak.com/NORAD/elements/weather.txt" + ) + @Inject lateinit var locationClient: FusedLocationProviderClient @Inject @@ -69,34 +83,24 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { @Inject lateinit var repository: Repository + lateinit var tleMainList: List + lateinit var tleSelection: MutableList + init { (app as Look4SatApp).appComponent.inject(this) + loadDataFromDisk() } - private val urlList = listOf( - "https://celestrak.com/NORAD/elements/amateur.txt", - "https://celestrak.com/NORAD/elements/weather.txt" - ) + val delay: Long + get() = preferences.getString(keyDelay, defValueUpdateFreq)!!.toLong() - private val _debugMessage = MutableLiveData() - val debugMessage: LiveData = _debugMessage + val hoursAhead: Int + get() = preferences.getInt(keyHours, defValueHours) - private val _gsp = MutableLiveData( - GroundStationPosition( - preferences.getString(keyLat, defValueLoc)!!.toDouble(), - preferences.getString(keyLon, defValueLoc)!!.toDouble(), - preferences.getString(keyAlt, defValueLoc)!!.toDouble() - ) - ) - val gsp: LiveData = _gsp + val minEl: Double + get() = preferences.getDouble(keyMinEl, defValueMinEl) - var satPassList = emptyList() - var tleMainList = loadTwoLineElementFile() - var selectionList = loadSelectionList() - val updateFreq: Long - get() = preferences.getString(keyUpdateFreq, defValueUpdateFreq)!!.toLong() - - fun updateGsp() { + fun setGroundStationPosition() { val lat = preferences.getString(keyLat, defValueLoc)!!.toDouble() val lon = preferences.getString(keyLon, defValueLoc)!!.toDouble() val alt = preferences.getString(keyAlt, defValueLoc)!!.toDouble() @@ -120,6 +124,14 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { } } + fun setPassPrefs(hoursAhead: Int, minEl: Double) { + preferences.edit { + putInt(keyHours, hoursAhead) + putDouble(keyMinEl, minEl) + apply() + } + } + fun updateAndSaveTleFile() { viewModelScope.launch(Dispatchers.IO) { try { @@ -132,7 +144,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { close() } tleMainList = tleList - selectionList = mutableListOf() + tleSelection = mutableListOf() _debugMessage.postValue("TLE file was updated") } catch (exception: IOException) { _debugMessage.postValue("Couldn't update TLE file") @@ -152,7 +164,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { } fun updateAndSaveSelectionList(list: MutableList) { - selectionList = list + tleSelection = list try { val fileOutputStream = app.openFileOutput(tleSelectionFileName, Context.MODE_PRIVATE) ObjectOutputStream(fileOutputStream).apply { @@ -166,11 +178,9 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { } suspend fun getPasses() { - val hoursAhead = preferences.getString(keyHours, defValueHours)!!.toInt() - val minEl = preferences.getString(keyMinEl, defValueMinEl)!!.toDouble() val passList = mutableListOf() withContext(Dispatchers.Default) { - selectionList.forEach { indexOfSelection -> + tleSelection.forEach { indexOfSelection -> val tle = tleMainList[indexOfSelection] try { val predictor = PassPredictor(tle, gsp.value) @@ -185,7 +195,7 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { passList.retainAll { it.pass.maxEl >= minEl } passList.sortBy { it.pass.startTime } } - satPassList = passList + _satPassList.postValue(passList) } suspend fun getTransmittersForSat(id: Int): List { @@ -193,30 +203,37 @@ class MainViewModel(application: Application) : AndroidViewModel(application) { } @Suppress("UNCHECKED_CAST") - private fun loadTwoLineElementFile(): List { - try { - val fileInputStream = app.openFileInput(tleMainListFileName) - val tleList = ObjectInputStream(fileInputStream).readObject() - return tleList as List + private fun loadDataFromDisk() { + tleMainList = try { + val tleStream = app.openFileInput(tleMainListFileName) + val tleList = ObjectInputStream(tleStream).readObject() + tleList as List } catch (exception: FileNotFoundException) { _debugMessage.postValue("TLE file wasn't found") + emptyList() } catch (exception: IOException) { _debugMessage.postValue(exception.toString()) + emptyList() } - return emptyList() - } - - @Suppress("UNCHECKED_CAST") - private fun loadSelectionList(): MutableList { - try { - val fileInputStream = app.openFileInput(tleSelectionFileName) - val selectionList = ObjectInputStream(fileInputStream).readObject() - return selectionList as MutableList + tleSelection = try { + val selectionStream = app.openFileInput(tleSelectionFileName) + val selectionList = ObjectInputStream(selectionStream).readObject() + selectionList as MutableList } catch (exception: FileNotFoundException) { _debugMessage.postValue("Selection file wasn't found") + mutableListOf() } catch (exception: IOException) { _debugMessage.postValue(exception.toString()) + mutableListOf() } - return mutableListOf() + setGroundStationPosition() } +} + +fun SharedPreferences.Editor.putDouble(key: String, double: Double) { + putLong(key, double.toRawBits()) +} + +fun SharedPreferences.getDouble(key: String, default: Double): Double { + return Double.fromBits(getLong(key, default.toRawBits())) } \ No newline at end of file diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/MainActivity.kt b/app/src/main/java/com/rtbishop/look4sat/ui/MainActivity.kt index 9b7dc195..bd7fb19b 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/MainActivity.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/MainActivity.kt @@ -126,8 +126,8 @@ class MainActivity : AppCompatActivity() { }) viewModel.gsp.observe(this, Observer { gsp -> - drawerLat.text = String.format(getString(R.string.pattern_lat), gsp.latitude) - drawerLon.text = String.format(getString(R.string.pattern_lon), gsp.longitude) + drawerLat.text = String.format(getString(R.string.pattern_location), gsp.latitude) + drawerLon.text = String.format(getString(R.string.pattern_location), gsp.longitude) }) } diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/RadarFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/RadarFragment.kt index ee94dfa6..7086dea8 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/RadarFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/RadarFragment.kt @@ -78,7 +78,7 @@ class RadarFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val delay = viewModel.updateFreq + val delay = viewModel.delay satPass = arguments?.get("satPass") as SatPass mainActivity.supportActionBar?.title = satPass.tle.name diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/SettingsFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/SettingsFragment.kt index 709453da..d0b56d89 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/SettingsFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/SettingsFragment.kt @@ -51,7 +51,7 @@ class SettingsFragment : PreferenceFragmentCompat(), if (key == context!!.getText(R.string.key_lat) || key == context!!.getText(R.string.key_lon) || key == context!!.getText(R.string.key_alt) - ) viewModel.updateGsp() + ) viewModel.setGroundStationPosition() } override fun onResume() { diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/SkyFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/SkyFragment.kt index 17115ee2..8cb8f35f 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/SkyFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/SkyFragment.kt @@ -24,11 +24,13 @@ import android.os.CountDownTimer import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.EditText import android.widget.ImageButton import android.widget.TextView import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.fragment.app.Fragment +import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager @@ -46,22 +48,23 @@ import java.util.concurrent.TimeUnit class SkyFragment : Fragment() { private lateinit var viewModel: MainViewModel - private lateinit var recViewFuture: RecyclerView - private lateinit var recAdapterFuture: SatPassAdapter + private lateinit var recyclerPasses: RecyclerView + private lateinit var recyclerAdapter: SatPassAdapter private lateinit var timeToAos: TextView - private lateinit var btnRefresh: ImageButton + private lateinit var btnPassPrefs: ImageButton private lateinit var fab: FloatingActionButton private lateinit var aosTimer: CountDownTimer private lateinit var swipeLayout: SwipeRefreshLayout - private lateinit var satPassList: List private lateinit var mainActivity: MainActivity + private lateinit var satPassList: List private var isTimerSet: Boolean = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mainActivity = activity as MainActivity viewModel = ViewModelProvider(mainActivity).get(MainViewModel::class.java) - recAdapterFuture = SatPassAdapter() + recyclerAdapter = SatPassAdapter() + satPassList = emptyList() } override fun onCreateView( @@ -72,80 +75,114 @@ class SkyFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - setupViews(view) + findViews(view) + setupComponents() + setupObservers() } - private fun setupViews(view: View) { + private fun findViews(view: View) { timeToAos = (mainActivity).findViewById(R.id.toolbar_time_to_aos) - btnRefresh = (mainActivity).findViewById(R.id.toolbar_btn_refresh) + btnPassPrefs = (mainActivity).findViewById(R.id.toolbar_btn_refresh) swipeLayout = view.findViewById(R.id.swipeRefreshLayout) - recViewFuture = view.findViewById(R.id.sky_recycler_future) + recyclerPasses = view.findViewById(R.id.sky_recycler_future) fab = view.findViewById(R.id.sky_fab) + } - satPassList = viewModel.satPassList - recViewFuture.apply { + private fun setupComponents() { + recyclerPasses.apply { layoutManager = LinearLayoutManager(mainActivity) - adapter = recAdapterFuture - } - recAdapterFuture.setList(satPassList) - recAdapterFuture.notifyDataSetChanged() - if (satPassList.isEmpty()) { - resetTimer() + adapter = recyclerAdapter } + recyclerAdapter.setList(satPassList) + recyclerAdapter.notifyDataSetChanged() + if (satPassList.isEmpty()) resetTimer() + swipeLayout.setProgressBackgroundColorSchemeResource(R.color.themeAccent) + swipeLayout.setColorSchemeResources(R.color.darkOnLight) swipeLayout.setOnRefreshListener { calculatePasses() } - btnRefresh.setOnClickListener { calculatePasses() } + btnPassPrefs.setOnClickListener { showSatPassPrefsDialog() } fab.setOnClickListener { - showSelectSatDialog(viewModel.tleMainList, viewModel.selectionList) + showSelectSatDialog(viewModel.tleMainList, viewModel.tleSelection) } } - private fun showSelectSatDialog(tleMainList: List, selectionList: MutableList) { - val tleNameArray = arrayOfNulls(tleMainList.size).apply { - tleMainList.withIndex().forEach { (position, tle) -> this[position] = tle.name } - } - val tleCheckedArray = BooleanArray(tleMainList.size).apply { - selectionList.forEach { this[it] = true } - } - val builder = AlertDialog.Builder(mainActivity) - builder.setTitle(getString(R.string.dialog_select_sat)) - .setMultiChoiceItems(tleNameArray, tleCheckedArray) { _, which, isChecked -> - if (isChecked) selectionList.add(which) - else if (selectionList.contains(which)) selectionList.remove(which) - } - .setPositiveButton(getString(R.string.btn_ok)) { _, _ -> - viewModel.updateAndSaveSelectionList(selectionList) - calculatePasses() - } - .setNegativeButton(getString(R.string.btn_cancel)) { dialog, _ -> - dialog.cancel() - } - .setNeutralButton(getString(R.string.btn_clear)) { _, _ -> - selectionList.clear() - viewModel.updateAndSaveSelectionList(selectionList) - calculatePasses() - } - .create() - .show() - } - - private fun calculatePasses() { - lifecycleScope.launch(Dispatchers.Main) { - viewModel.getPasses() - satPassList = viewModel.satPassList - recAdapterFuture.setList(satPassList) - recAdapterFuture.notifyDataSetChanged() + private fun setupObservers() { + viewModel.passSatList.observe(viewLifecycleOwner, Observer { + satPassList = it + recyclerAdapter.setList(satPassList) + recyclerAdapter.notifyDataSetChanged() if (satPassList.isNotEmpty()) setTimer(satPassList.first().pass.startTime.time) else { resetTimer() timeToAos.text = String.format(getString(R.string.pattern_aos), 0, 0, 0) } swipeLayout.isRefreshing = false + }) + } + + private fun showSatPassPrefsDialog() { + val satPassPrefView = View.inflate(mainActivity, R.layout.sat_pass_pref, null) + val etHoursAhead = satPassPrefView.findViewById(R.id.pref_hours_ahead_et) + val etMinEl = satPassPrefView.findViewById(R.id.pref_min_el_et) + etHoursAhead.setText(viewModel.hoursAhead.toString()) + etMinEl.setText(viewModel.minEl.toString()) + + val builder = AlertDialog.Builder(mainActivity) + builder.setTitle(getString(R.string.dialog_pass_prefs)) + .setPositiveButton(getString(R.string.btn_ok)) { _, _ -> + val hoursAhead = etHoursAhead.text.toString().toInt() + val minEl = etMinEl.text.toString().toDouble() + viewModel.setPassPrefs(hoursAhead, minEl) + calculatePasses() + } + .setNegativeButton(getString(R.string.btn_cancel)) { dialog, _ -> + dialog.cancel() + } + .setView(satPassPrefView) + .create() + .show() + } + + private fun showSelectSatDialog(tleMainList: List, selectionList: MutableList) { + if (tleMainList.isEmpty()) { + Toast.makeText(mainActivity, "Please, update your TLE", Toast.LENGTH_SHORT).show() + } else { + val tleNameArray = arrayOfNulls(tleMainList.size).apply { + tleMainList.withIndex().forEach { (position, tle) -> this[position] = tle.name } + } + val tleCheckedArray = BooleanArray(tleMainList.size).apply { + selectionList.forEach { this[it] = true } + } + val builder = AlertDialog.Builder(mainActivity) + builder.setTitle(getString(R.string.dialog_select_sat)) + .setMultiChoiceItems(tleNameArray, tleCheckedArray) { _, which, isChecked -> + if (isChecked) selectionList.add(which) + else if (selectionList.contains(which)) selectionList.remove(which) + } + .setPositiveButton(getString(R.string.btn_ok)) { _, _ -> + viewModel.updateAndSaveSelectionList(selectionList) + calculatePasses() + } + .setNegativeButton(getString(R.string.btn_cancel)) { dialog, _ -> + dialog.cancel() + } + .setNeutralButton(getString(R.string.btn_clear)) { _, _ -> + selectionList.clear() + viewModel.updateAndSaveSelectionList(selectionList) + calculatePasses() + } + .create() + .show() } } + private fun calculatePasses() { + swipeLayout.isRefreshing = true + lifecycleScope.launch(Dispatchers.Main) { viewModel.getPasses() } + } + private fun setTimer(passTime: Long) { - if (isTimerSet) resetTimer() + resetTimer() val totalMillis = passTime.minus(System.currentTimeMillis()) aosTimer = object : CountDownTimer(totalMillis, 1000) { override fun onFinish() { @@ -155,7 +192,7 @@ class SkyFragment : Fragment() { override fun onTick(millisUntilFinished: Long) { timeToAos.text = String.format( - getString(R.string.pattern_aos), + mainActivity.getString(R.string.pattern_aos), TimeUnit.MILLISECONDS.toHours(millisUntilFinished) % 60, TimeUnit.MILLISECONDS.toMinutes(millisUntilFinished) % 60, TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) % 60 diff --git a/app/src/main/java/com/rtbishop/look4sat/ui/WorldMapFragment.kt b/app/src/main/java/com/rtbishop/look4sat/ui/WorldMapFragment.kt index 1b4f6407..dde5181a 100644 --- a/app/src/main/java/com/rtbishop/look4sat/ui/WorldMapFragment.kt +++ b/app/src/main/java/com/rtbishop/look4sat/ui/WorldMapFragment.kt @@ -30,10 +30,7 @@ import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider -import com.github.amsacode.predict4java.PassPredictor -import com.github.amsacode.predict4java.Position -import com.github.amsacode.predict4java.SatPos -import com.github.amsacode.predict4java.TLE +import com.github.amsacode.predict4java.* import com.google.android.material.floatingactionbutton.FloatingActionButton import com.rtbishop.look4sat.MainViewModel import com.rtbishop.look4sat.R @@ -45,7 +42,6 @@ import kotlin.math.abs class WorldMapFragment : Fragment() { private val service = Executors.newSingleThreadScheduledExecutor() - private lateinit var viewModel: MainViewModel private lateinit var trackView: TrackView private lateinit var mapFrame: FrameLayout @@ -54,7 +50,8 @@ class WorldMapFragment : Fragment() { private lateinit var mainActivity: MainActivity private lateinit var selectedSat: TLE private lateinit var tleMainList: List - private lateinit var selectionList: MutableList + private lateinit var tleSelection: MutableList + private lateinit var gsp: GroundStationPosition private var checkedItem = 0 override fun onCreate(savedInstanceState: Bundle?) { @@ -73,15 +70,24 @@ class WorldMapFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val delay = viewModel.updateFreq - tleMainList = viewModel.tleMainList - selectionList = viewModel.selectionList + findViews(view) + setupComponents() + } + + private fun findViews(view: View) { mapFrame = view.findViewById(R.id.worldmap_frame) fab = view.findViewById(R.id.worldmap_fab) + } - if (tleMainList.isNotEmpty() && selectionList.isNotEmpty()) { - fab.setOnClickListener { showSelectSatDialog(tleMainList, selectionList) } - selectedSat = tleMainList[selectionList[0]] + private fun setupComponents() { + val delay = viewModel.delay + tleMainList = viewModel.tleMainList + tleSelection = viewModel.tleSelection + gsp = viewModel.gsp.value!! + + if (tleMainList.isNotEmpty() && tleSelection.isNotEmpty()) { + fab.setOnClickListener { showSelectSatDialog(tleMainList, tleSelection) } + selectedSat = tleMainList[tleSelection[0]] predictor = PassPredictor(selectedSat, viewModel.gsp.value) trackView = TrackView(mainActivity) mapFrame.addView(trackView) @@ -97,8 +103,7 @@ class WorldMapFragment : Fragment() { mainActivity, getString(R.string.no_selected_sat), Toast.LENGTH_SHORT - ) - .show() + ).show() } } } @@ -115,7 +120,7 @@ class WorldMapFragment : Fragment() { .setSingleChoiceItems(tleNameArray, checkedItem) { dialog, which -> checkedItem = which selectedSat = tleMainList[selectionList[which]] - predictor = PassPredictor(selectedSat, viewModel.gsp.value) + predictor = PassPredictor(selectedSat, gsp) trackView.invalidate() dialog.dismiss() } @@ -124,7 +129,6 @@ class WorldMapFragment : Fragment() { } inner class TrackView(context: Context) : View(context) { - private val gsp = viewModel.gsp.value!! private val scale = resources.displayMetrics.density private val groundTrackPaint = Paint().apply { isAntiAlias = true @@ -166,7 +170,7 @@ class WorldMapFragment : Fragment() { val satPosList = predictor.getPositions(currentTime, 60, 0, orbitalPeriod * 3) drawGroundTrack(canvas, degLon, degLat, satPosList) - selectionList.forEach { + tleSelection.forEach { drawSat(it, currentTime, canvas, degLon, degLat) } } diff --git a/app/src/main/res/drawable/ic_prefs.xml b/app/src/main/res/drawable/ic_prefs.xml new file mode 100644 index 00000000..16e5164d --- /dev/null +++ b/app/src/main/res/drawable/ic_prefs.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_refresh.xml b/app/src/main/res/drawable/ic_refresh.xml deleted file mode 100644 index 3a766bc2..00000000 --- a/app/src/main/res/drawable/ic_refresh.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/layout/sat_pass_pref.xml b/app/src/main/res/layout/sat_pass_pref.xml new file mode 100644 index 00000000..2c5322f9 --- /dev/null +++ b/app/src/main/res/layout/sat_pass_pref.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a0362d8b..23fd9167 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -41,16 +41,17 @@ Select satellites to track Show ground track for… + Satellite pass preferences + + Show passes that occur within X hours + Hours ahead + Show passes with max elevation above + Minimum elevation Ground station position settings Latitude Longitude Altitude - Satellite pass settings - Hours ahead - Show passes that occur within X hours - Minimum elevation - Show passes with max elevation above Other settings Update frequency Views update interval, ms @@ -63,9 +64,9 @@ latitude longitude altitude - hours_ahead - min_elevation - update_freq + hoursAhead + minEl + delay tleFile.txt tleSelection @@ -83,8 +84,7 @@ Inverted: Yes Transmitters: - %.4f - %.4f + %.4f AOS -%02d:%02d:%02d Mode: %s Inverted: %s diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index a87381b0..b42da771 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -64,7 +64,7 @@ diff --git a/app/src/main/res/xml/preference.xml b/app/src/main/res/xml/preference.xml index 7c16e3c4..17f0d6f7 100644 --- a/app/src/main/res/xml/preference.xml +++ b/app/src/main/res/xml/preference.xml @@ -20,26 +20,10 @@ android:singleLine="true" android:title="@string/pref_alt_title" /> - - - -