Refactor: Refactored the settings for widgets.

This commit is contained in:
HeCodes2Much
2024-06-10 15:59:00 +01:00
parent 578f136fe6
commit 91d34ae6b3
14 changed files with 735 additions and 59 deletions

View File

@@ -34,6 +34,14 @@ class PreferenceHelper @Inject constructor(@ApplicationContext context: Context)
get() = prefs.getBoolean(Constants.SHOW_DAILY_WORD, false)
set(value) = prefs.edit().putBoolean(Constants.SHOW_DAILY_WORD, value).apply()
var showWeatherWidget: Boolean
get() = prefs.getBoolean(Constants.SHOW_WEATHER_WIDGET, false)
set(value) = prefs.edit().putBoolean(Constants.SHOW_WEATHER_WIDGET, value).apply()
var showBatteryWidget: Boolean
get() = prefs.getBoolean(Constants.SHOW_BATTERY_WIDGET, false)
set(value) = prefs.edit().putBoolean(Constants.SHOW_BATTERY_WIDGET, value).apply()
var dateColor: Int
get() = prefs.getInt(Constants.DATE_COLOR, 0xFFFFFFFF.toInt())
set(value) = prefs.edit().putInt(Constants.DATE_COLOR, value).apply()
@@ -114,6 +122,14 @@ class PreferenceHelper @Inject constructor(@ApplicationContext context: Context)
get() = prefs.getFloat(Constants.DAILY_WORD_TEXT_SIZE, 18f)
set(value) = prefs.edit().putFloat(Constants.DAILY_WORD_TEXT_SIZE, value).apply()
var weatherOrderNumber: Int
get() = prefs.getInt(Constants.WIDGET_WEATHER, 1)
set(value) = prefs.edit().putInt(Constants.WIDGET_WEATHER, value).apply()
var batteryOrderNumber: Int
get() = prefs.getInt(Constants.WIDGET_BATTERY, 2)
set(value) = prefs.edit().putInt(Constants.WIDGET_BATTERY, value).apply()
var settingsLock: Boolean
get() = prefs.getBoolean(Constants.TOGGLE_SETTING_LOCK, false)
set(value) = prefs.edit().putBoolean(Constants.TOGGLE_SETTING_LOCK, value).apply()

View File

@@ -0,0 +1,36 @@
package com.github.droidworksstudio.launcher.ui.numberpicker
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.github.droidworksstudio.launcher.R
class NumberPickerAdapter(
private val numbers: List<Int>,
private val onNumberSelected: (Int) -> Unit
) : RecyclerView.Adapter<NumberPickerAdapter.NumberViewHolder>() {
inner class NumberViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val numberText: TextView = itemView.findViewById(R.id.number_text)
init {
itemView.setOnClickListener {
onNumberSelected(numbers[adapterPosition])
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NumberViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_number, parent, false)
return NumberViewHolder(view)
}
override fun onBindViewHolder(holder: NumberViewHolder, position: Int) {
holder.numberText.text = numbers[position].toString()
}
override fun getItemCount(): Int = numbers.size
}

View File

@@ -12,6 +12,8 @@ import android.graphics.drawable.GradientDrawable
import android.os.BatteryManager
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.view.LayoutInflater
import android.view.View
@@ -22,6 +24,7 @@ import androidx.core.content.res.ResourcesCompat
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
import androidx.navigation.NavOptions
import androidx.navigation.fragment.findNavController
import com.github.droidworksstudio.common.capitalizeEachWord
import com.github.droidworksstudio.common.hasInternetPermission
@@ -34,12 +37,17 @@ import com.github.droidworksstudio.launcher.listener.OnSwipeTouchListener
import com.github.droidworksstudio.launcher.listener.ScrollEventListener
import com.github.droidworksstudio.launcher.utils.Constants
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import java.util.Locale
import javax.inject.Inject
import kotlin.math.absoluteValue
@AndroidEntryPoint
class WidgetFragment : Fragment(),
@@ -74,6 +82,7 @@ class WidgetFragment : Fragment(),
super.onViewCreated(view, savedInstanceState)
initializeInjectedDependencies()
orderWidgetsBySettings()
setupWeatherWidget()
setupBatteryWidget()
observeSwipeTouchListener()
@@ -83,10 +92,36 @@ class WidgetFragment : Fragment(),
private fun initializeInjectedDependencies() {
context = requireContext()
binding.nestScrollView.hideKeyboard()
//
binding.nestScrollView.scrollEventListener = this
}
private fun orderWidgetsBySettings() {
val linearLayout = binding.linearLayoutContainer
// Find RelativeLayouts by their IDs
val weatherRoot = binding.weatherRoot
val batteryRoot = binding.batteryRoot
// Order the list of layouts
val orderList = listOf(
Pair(weatherRoot, preferenceHelper.weatherOrderNumber),
Pair(batteryRoot, preferenceHelper.batteryOrderNumber)
)
// Sort the list based on the second value of the pairs (the order number)
val sortedOrderList = orderList.sortedBy { it.second }
// Remove all views from the LinearLayout
linearLayout.removeAllViews()
// Add the RelativeLayouts back in the sorted order
for ((relativeLayout, _) in sortedOrderList) {
linearLayout.addView(relativeLayout)
}
}
private fun setupWeatherWidget() {
val sharedPreferences =
context.getSharedPreferences(Constants.WEATHER_PREFS, Context.MODE_PRIVATE)
@@ -94,41 +129,58 @@ class WidgetFragment : Fragment(),
val longitude = sharedPreferences.getFloat(Constants.LONGITUDE, 0f)
val timestamp = convertTimestampToReadableDate(sharedPreferences.getLong("cachedDataTimestamp", 0))
// Pre-fetch preferences
val showWeatherWidget = preferenceHelper.showWeatherWidget
val temperatureScale = if (preferenceHelper.weatherUnits == Constants.Units.Metric) getString(R.string.widget_c) else getString(
R.string.widget_f
)
val speedScale = if (preferenceHelper.weatherUnits == Constants.Units.Metric) getString(R.string.widget_weather_mps) else getString(R.string.widget_weather_mph)
val widgetTextColor = preferenceHelper.widgetTextColor
val widgetBackgroundColor = preferenceHelper.widgetBackgroundColor
lifecycleScope.launch {
if (!showWeatherWidget || !context.hasInternetPermission()) return@launch
try {
if (!context.hasInternetPermission()) return@launch
binding.weatherRoot.visibility = View.VISIBLE
val weatherResponse = appHelper.fetchWeatherData(context, latitude, longitude)
val weatherDeferred = async { appHelper.fetchWeatherData(context, latitude, longitude) }
// Prepare UI elements concurrently
withContext(Dispatchers.Main) {
binding.apply {
weatherCity.setTextColor(widgetTextColor)
weatherTemperature.setTextColor(widgetTextColor)
weatherDescription.setTextColor(widgetTextColor)
weatherWind.setTextColor(widgetTextColor)
weatherHumidity.setTextColor(widgetTextColor)
weatherRefresh.setTextColor(widgetTextColor)
weatherLastRun.setTextColor(widgetTextColor)
weatherRefresh.typeface = ResourcesCompat.getFont(requireActivity(), R.font.weather)
}
}
val weatherResponse = weatherDeferred.await()
Log.d("weatherResponse", "$weatherResponse")
val temperatureScale = if (preferenceHelper.weatherUnits == Constants.Units.Metric) getString(R.string.widget_c) else getString(
R.string.widget_f
)
val speedScale = if (preferenceHelper.weatherUnits == Constants.Units.Metric) getString(R.string.widget_weather_mps) else getString(R.string.widget_weather_mph)
binding.weatherCity.setTextColor(preferenceHelper.widgetTextColor)
binding.weatherTemperature.setTextColor(preferenceHelper.widgetTextColor)
binding.weatherDescription.setTextColor(preferenceHelper.widgetTextColor)
binding.weatherWind.setTextColor(preferenceHelper.widgetTextColor)
binding.weatherHumidity.setTextColor(preferenceHelper.widgetTextColor)
binding.weatherRefresh.setTextColor(preferenceHelper.widgetTextColor)
binding.weatherLastRun.setTextColor(preferenceHelper.widgetTextColor)
binding.weatherRefresh.typeface = ResourcesCompat.getFont(requireActivity(), R.font.weather)
withContext(Dispatchers.Main) {
binding.apply {
weatherCity.text = getString(R.string.widget_weather_location, weatherResponse.name, weatherResponse.sys.country)
weatherTemperature.text = getString(R.string.widget_weather_temp, weatherResponse.main.temp, temperatureScale)
weatherDescription.text = getString(R.string.widget_weather_description, weatherResponse.weather[0].description).capitalizeEachWord()
weatherWind.text = getString(R.string.widget_weather_wind, weatherResponse.wind.speed, speedScale)
weatherHumidity.text = getString(R.string.widget_weather_humidity, weatherResponse.main.humidity)
weatherLastRun.text = timestamp
weatherRefresh.text = getString(R.string.widget_weather_refresh, getString(R.string.refresh_icon))
binding.weatherCity.text = getString(R.string.widget_weather_location, weatherResponse.name, weatherResponse.sys.country)
binding.weatherTemperature.text = getString(R.string.widget_weather_temp, weatherResponse.main.temp, temperatureScale)
binding.weatherDescription.text = getString(R.string.widget_weather_description, weatherResponse.weather[0].description).capitalizeEachWord()
binding.weatherWind.text = getString(R.string.widget_weather_wind, weatherResponse.wind.speed, speedScale)
binding.weatherHumidity.text = getString(R.string.widget_weather_humidity, weatherResponse.main.humidity)
binding.weatherLastRun.text = timestamp
binding.weatherRefresh.text = getString(R.string.widget_weather_refresh, getString(R.string.refresh_icon))
val weatherIconBitmap = createWeatherIcon(context, setWeatherIcon(context, weatherResponse.weather[0].id))
weatherIcon.setImageBitmap(weatherIconBitmap) // Ensure this matches your ImageView ID
weatherIcon.setColorFilter(widgetTextColor)
val weatherIcon = createWeatherIcon(context, setWeatherIcon(context, weatherResponse.weather[0].id))
binding.weatherIcon.setImageBitmap(weatherIcon)
binding.weatherIcon.setColorFilter(preferenceHelper.widgetTextColor)
val weatherWidgetDrawable = binding.weatherRoot.background
if (weatherWidgetDrawable is GradientDrawable) {
weatherWidgetDrawable.setColor(preferenceHelper.widgetBackgroundColor)
val weatherWidgetDrawable = weatherRoot.background
if (weatherWidgetDrawable is GradientDrawable) {
weatherWidgetDrawable.setColor(widgetBackgroundColor)
}
weatherRoot.visibility = View.VISIBLE
}
}
} catch (e: Exception) {
Log.e("Weather", "Failed to fetch weather data: ${e.message}")
@@ -136,6 +188,7 @@ class WidgetFragment : Fragment(),
}
}
private fun createWeatherIcon(context: Context, text: String): Bitmap {
val bitmap = Bitmap.createBitmap(256, 256, Bitmap.Config.ARGB_8888)
val canvas = Canvas(bitmap)
@@ -183,37 +236,45 @@ class WidgetFragment : Fragment(),
}
private fun setupBatteryWidget() {
try {
binding.batteryLevel.setTextColor(preferenceHelper.widgetTextColor)
binding.batteryCount.setTextColor(preferenceHelper.widgetTextColor)
binding.chargingStatus.setTextColor(preferenceHelper.widgetTextColor)
binding.batteryHealth.setTextColor(preferenceHelper.widgetTextColor)
binding.batteryVoltage.setTextColor(preferenceHelper.widgetTextColor)
binding.batteryTemperature.setTextColor(preferenceHelper.widgetTextColor)
lifecycleScope.launch {
if (!preferenceHelper.showBatteryWidget) return@launch
try {
binding.batteryLevel.setTextColor(preferenceHelper.widgetTextColor)
binding.batteryCount.setTextColor(preferenceHelper.widgetTextColor)
binding.chargingStatus.setTextColor(preferenceHelper.widgetTextColor)
binding.batteryHealth.setTextColor(preferenceHelper.widgetTextColor)
binding.batteryCurrent.setTextColor(preferenceHelper.widgetTextColor)
binding.batteryVoltage.setTextColor(preferenceHelper.widgetTextColor)
binding.batteryTemperature.setTextColor(preferenceHelper.widgetTextColor)
val weatherBatteryDrawable = binding.batteryRoot.background
if (weatherBatteryDrawable is GradientDrawable) {
weatherBatteryDrawable.setColor(preferenceHelper.widgetBackgroundColor)
val weatherBatteryDrawable = binding.batteryRoot.background
if (weatherBatteryDrawable is GradientDrawable) {
weatherBatteryDrawable.setColor(preferenceHelper.widgetBackgroundColor)
}
binding.batteryRoot.visibility = View.VISIBLE
} catch (e: Exception) {
Log.e("Battery", "Failed to fetch battery data: ${e.message}")
}
} catch (e: Exception) {
Log.e("Battery", "Failed to fetch battery data: ${e.message}")
}
binding.batteryRoot.visibility = View.VISIBLE
}
private val batteryReceiver = object : BroadcastReceiver() {
@RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
override fun onReceive(context: Context?, intent: Intent?) {
val batteryManager = requireContext().getSystemService(Context.BATTERY_SERVICE) as BatteryManager
if (intent?.action == Intent.ACTION_BATTERY_CHANGED) {
val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
val scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
val isCharging = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1)
val health = intent.getIntExtra(BatteryManager.EXTRA_HEALTH, BatteryManager.BATTERY_HEALTH_UNKNOWN)
val count = intent.getIntExtra(BatteryManager.EXTRA_CYCLE_COUNT, 0)
val current = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CURRENT_NOW)
val voltage = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, 0)
val temperature = intent.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0)
val temperatureCelsius = temperature / 10.0
val voltageScale = getString(R.string.widget_mv)
val currentScale = getString(R.string.widget_ma)
val temperatureScale = getString(R.string.widget_c)
val batteryPct = (level / scale.toFloat() * 100).toInt()
@@ -236,7 +297,8 @@ class WidgetFragment : Fragment(),
binding.chargingStatus.text = getString(R.string.widgets_battery_status, chargingStatusText)
binding.batteryHealth.text = getString(R.string.widgets_battery_health, healthStatus)
binding.batteryVoltage.text = getString(R.string.widgets_battery_voltage, voltage, voltageScale)
binding.batteryTemperature.text = getString(R.string.widgets_battery_temperature, temperature, temperatureScale)
binding.batteryCurrent.text = getString(R.string.widgets_battery_current, current, currentScale)
binding.batteryTemperature.text = getString(R.string.widgets_battery_temperature, temperatureCelsius, temperatureScale)
}
}
}
@@ -250,6 +312,20 @@ class WidgetFragment : Fragment(),
private fun getSwipeGestureListener(context: Context): View.OnTouchListener {
return object : OnSwipeTouchListener(context) {
override fun onLongClick() {
super.onLongClick()
val actionTypeNavOptions: NavOptions =
appHelper.getActionType(Constants.Swipe.DoubleTap)
Handler(Looper.getMainLooper()).post {
findNavController().navigate(
R.id.action_WidgetsFragment_to_WidgetsSettingsFragment,
null,
actionTypeNavOptions
)
}
return
}
override fun onSwipeLeft() {
super.onSwipeLeft()
findNavController().popBackStack()

View File

@@ -0,0 +1,187 @@
package com.github.droidworksstudio.launcher.ui.widgets.settings
import android.annotation.SuppressLint
import android.content.Context
import android.content.DialogInterface
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.navigation.NavController
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.github.droidworksstudio.launcher.R
import com.github.droidworksstudio.launcher.databinding.FragmentSettingsWidgetsBinding
import com.github.droidworksstudio.launcher.helper.AppHelper
import com.github.droidworksstudio.launcher.helper.PreferenceHelper
import com.github.droidworksstudio.launcher.listener.OnSwipeTouchListener
import com.github.droidworksstudio.launcher.listener.ScrollEventListener
import com.github.droidworksstudio.launcher.ui.bottomsheetdialog.ColorBottomSheetDialogFragment
import com.github.droidworksstudio.launcher.ui.numberpicker.NumberPickerAdapter
import com.github.droidworksstudio.launcher.utils.Constants
import com.github.droidworksstudio.launcher.viewmodel.PreferenceViewModel
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
class SettingsFragment : Fragment(),
ScrollEventListener {
private var _binding: FragmentSettingsWidgetsBinding? = null
private val binding get() = _binding!!
private val preferenceViewModel: PreferenceViewModel by viewModels()
@Inject
lateinit var preferenceHelper: PreferenceHelper
@Inject
lateinit var appHelper: AppHelper
private lateinit var navController: NavController
private lateinit var context: Context
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout for this fragment
_binding = FragmentSettingsWidgetsBinding.inflate(inflater, container, false)
_binding = binding
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
navController = findNavController()
// Set according to the system theme mode
appHelper.dayNightMod(requireContext(), binding.nestScrollView)
super.onViewCreated(view, savedInstanceState)
context = requireContext()
initializeInjectedDependencies()
observeClickListener()
observeSwipeTouchListener()
}
private fun initializeInjectedDependencies() {
binding.nestScrollView.scrollEventListener = this
// Set initial values and listeners for switches
binding.weatherSwitchCompat.isChecked = preferenceHelper.showWeatherWidget
binding.batterySwitchCompat.isChecked = preferenceHelper.showBatteryWidget
binding.weatherOrderControl.text = preferenceHelper.weatherOrderNumber.toString()
binding.batteryOrderControl.text = preferenceHelper.batteryOrderNumber.toString()
}
private fun observeClickListener() {
setupSwitchListeners()
binding.weatherOrderControl.setOnClickListener {
showOrderChangeDialog(binding.weatherOrderControl)
}
binding.batteryOrderControl.setOnClickListener {
showOrderChangeDialog(binding.batteryOrderControl)
}
binding.selectBatteryWidgetColor.setOnClickListener {
val bottomSheetFragment = ColorBottomSheetDialogFragment()
bottomSheetFragment.show(parentFragmentManager, "BottomSheetDialog")
}
binding.selectBatteryWidgetColor.setOnClickListener {
val bottomSheetFragment = ColorBottomSheetDialogFragment()
bottomSheetFragment.show(parentFragmentManager, "BottomSheetDialog")
}
}
private fun setupSwitchListeners() {
binding.weatherSwitchCompat.setOnCheckedChangeListener { _, isChecked ->
preferenceViewModel.setShowWeatherWidget(isChecked)
}
binding.batterySwitchCompat.setOnCheckedChangeListener { _, isChecked ->
preferenceViewModel.setShowBatteryWidget(isChecked)
}
}
@SuppressLint("ClickableViewAccessibility")
private fun observeSwipeTouchListener() {
binding.touchArea.setOnTouchListener(getSwipeGestureListener(context))
}
private fun getSwipeGestureListener(context: Context): View.OnTouchListener {
return object : OnSwipeTouchListener(context) {
override fun onSwipeLeft() {
super.onSwipeLeft()
findNavController().popBackStack()
}
override fun onSwipeRight() {
super.onSwipeRight()
findNavController().popBackStack()
}
}
}
@SuppressLint("InflateParams")
private fun showOrderChangeDialog(view: View) {
val numberPickerDialog = MaterialAlertDialogBuilder(context).create()
val numberPickerView = layoutInflater.inflate(R.layout.item_number_picker, null)
val recyclerView = numberPickerView.findViewById<RecyclerView>(R.id.recycler_view)
recyclerView.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
val numbers = (1..Constants.WIDGETS_COUNT).toList() // Replace with your desired range
when (view) {
binding.weatherOrderControl -> {
val adapter = NumberPickerAdapter(numbers) { selectedNumber ->
// Save the order number to SharedPreferences or ViewModel
preferenceViewModel.setWeatherOrderNumber(selectedNumber)
binding.weatherOrderControl.text = preferenceHelper.weatherOrderNumber.toString()
numberPickerDialog.dismiss()
}
recyclerView.adapter = adapter
}
binding.batteryOrderControl -> {
val adapter = NumberPickerAdapter(numbers) { selectedNumber ->
// Save the order number to SharedPreferences or ViewModel
preferenceViewModel.setBatteryOrderNumber(selectedNumber)
binding.batteryOrderControl.text = preferenceHelper.batteryOrderNumber.toString()
numberPickerDialog.dismiss()
}
recyclerView.adapter = adapter
}
else -> {
Log.d("showOrderChangeDialog", "else")
}
}
numberPickerDialog.apply {
setTitle("Change Order")
setView(numberPickerView)
setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel") { dialog, _ ->
dialog.dismiss()
}
}
numberPickerDialog.show()
}
}

View File

@@ -8,6 +8,9 @@ object Constants {
const val PACKAGE_NAME_DEBUG = "$PACKAGE_NAME.debug"
const val WIDGETS_PREFS = "EasyLauncherWidgets.pref"
const val WIDGETS_COUNT = 2
const val WIDGET_WEATHER = "WIDGET_WEATHER"
const val WIDGET_BATTERY = "WIDGET_BATTERY"
const val WEATHER_PREFS = "EasyWeather.pref"
const val LATITUDE = "LATITUDE"
@@ -21,6 +24,9 @@ object Constants {
const val SHOW_BATTERY = "SHOW_BATTERY"
const val SHOW_STATUS_BAR = "SHOW_STATUS_BAR"
const val SHOW_WEATHER_WIDGET = "SHOW_WEATHER_WIDGET"
const val SHOW_BATTERY_WIDGET = "SHOW_BATTERY_WIDGET"
const val DATE_COLOR = "DATE_COLOR"
const val TIME_COLOR = "TIME_COLOR"
const val BATTERY_COLOR = "BATTERY_COLOR"

View File

@@ -18,6 +18,8 @@ class PreferenceViewModel @Inject constructor(
val showDateLiveData: MutableLiveData<Boolean> = MutableLiveData()
val showDailyWordLiveData: MutableLiveData<Boolean> = MutableLiveData()
val showBatteryLiveData: MutableLiveData<Boolean> = MutableLiveData()
private val showWeatherWidgetLiveData: MutableLiveData<Boolean> = MutableLiveData()
private val showBatteryWidgetLiveData: MutableLiveData<Boolean> = MutableLiveData()
private val showAppIconLiveData: MutableLiveData<Boolean> = MutableLiveData()
private val homeAppAlignmentLiveData: MutableLiveData<Int> = MutableLiveData()
private val homeDateAlignmentLiveData: MutableLiveData<Int> = MutableLiveData()
@@ -39,6 +41,9 @@ class PreferenceViewModel @Inject constructor(
private val lockSettingsLiveData: MutableLiveData<Boolean> = MutableLiveData()
private val appPaddingSizeLiveData: MutableLiveData<Float> = MutableLiveData()
private val weatherOrderNumberLiveData: MutableLiveData<Int> = MutableLiveData()
private val batteryOrderNumberLiveData: MutableLiveData<Int> = MutableLiveData()
private val searchEngineLiveData: MutableLiveData<Constants.SearchEngines> = MutableLiveData()
private val doubleTapActionLiveData: MutableLiveData<Constants.Action> = MutableLiveData()
private val swipeUpActionLiveData: MutableLiveData<Constants.Action> = MutableLiveData()
@@ -86,11 +91,31 @@ class PreferenceViewModel @Inject constructor(
dailyWordColorLiveData.postValue(preferenceHelper.dailyWordColor)
}
fun setShowWeatherWidget(showWeather: Boolean) {
preferenceHelper.showWeatherWidget = showWeather
showWeatherWidgetLiveData.postValue(preferenceHelper.showWeatherWidget)
}
fun setShowBatteryWidget(showBattery: Boolean) {
preferenceHelper.showBatteryWidget = showBattery
showBatteryWidgetLiveData.postValue(preferenceHelper.showBatteryWidget)
}
fun setAppColor(appColor: Int) {
preferenceHelper.appColor = appColor
appColorLiveData.postValue(preferenceHelper.appColor)
}
fun setWeatherOrderNumber(orderNumber: Int) {
preferenceHelper.weatherOrderNumber = orderNumber
weatherOrderNumberLiveData.postValue(preferenceHelper.weatherOrderNumber)
}
fun setBatteryOrderNumber(orderNumber: Int) {
preferenceHelper.batteryOrderNumber = orderNumber
batteryOrderNumberLiveData.postValue(preferenceHelper.batteryOrderNumber)
}
fun setDateColor(dateColor: Int) {
preferenceHelper.dateColor = dateColor
dateColorLiveData.postValue(preferenceHelper.dateColor)

View File

@@ -21,7 +21,8 @@
android:fadingEdgeLength="48dp"
android:overScrollMode="never"
android:requiresFadingEdge="vertical"
android:scrollbars="none">
android:scrollbars="none"
tools:ignore="TooManyViews">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
@@ -117,6 +118,7 @@
tools:ignore="RtlHardcoded" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
@@ -228,6 +230,7 @@
tools:ignore="TouchTargetSizeCheck" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
@@ -435,6 +438,7 @@
tools:ignore="TouchTargetSizeCheck" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
@@ -456,7 +460,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="20dp"
android:layout_marginVertical="10dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
@@ -479,7 +483,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="20dp"
android:layout_marginVertical="10dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
@@ -502,7 +506,7 @@
android:layout_width="match_parent"
android:layout_height="28dp"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="20dp"
android:layout_marginVertical="10dp"
tools:ignore="MissingConstraints,TextSizeCheck">
<androidx.appcompat.widget.AppCompatTextView
@@ -524,7 +528,7 @@
android:layout_width="match_parent"
android:layout_height="28dp"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="20dp"
android:layout_marginVertical="10dp"
tools:ignore="MissingConstraints,TextSizeCheck">
<androidx.appcompat.widget.AppCompatTextView
@@ -546,7 +550,7 @@
android:layout_width="match_parent"
android:layout_height="28dp"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="20dp"
android:layout_marginVertical="10dp"
tools:ignore="MissingConstraints,TextSizeCheck">
<androidx.appcompat.widget.AppCompatTextView
@@ -751,6 +755,14 @@
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -774,7 +786,7 @@
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/miscellaneous_searchEngine"
android:id="@+id/miscellaneous_searchEngine_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
@@ -787,7 +799,7 @@
style="@style/TextDefaultStyle" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/searchEngine_text"
android:id="@+id/miscellaneous_searchEngine_control"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left|center"
@@ -800,11 +812,19 @@
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:ignore="MissingConstraints,TooManyViews">
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
@@ -843,6 +863,14 @@
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -863,7 +891,7 @@
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginHorizontal="20dp"
android:layout_marginBottom="20dp"
android:layout_marginVertical="10dp"
android:layout_weight="4"
android:gravity="center"
tools:ignore="MissingConstraints">

View File

@@ -0,0 +1,254 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.settings.SettingsFragment">
<FrameLayout
android:id="@+id/touchArea"
android:layout_marginVertical="20dp"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.github.droidworksstudio.launcher.view.GestureNestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/nestScrollView"
android:clipChildren="false"
android:clipToPadding="false"
android:fadingEdgeLength="48dp"
android:overScrollMode="never"
android:requiresFadingEdge="vertical"
android:scrollbars="none"
tools:ignore="TooManyViews">
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="10dp"
android:layout_marginVertical="32dp"
android:orientation="vertical"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginTop="48dp"
android:text="@string/settings_widgets_name"
android:textSize="@dimen/text_super_large"
style="@style/TextDefaultStyle" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:text="@string/widgets_settings_display_weather"
android:textSize="@dimen/text_super_large"
style="@style/TextDefaultStyle" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/weather_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="left|center"
android:text="@string/widgets_settings_display"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/weather_switchCompat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleX="0.7"
android:scaleY="0.8"
android:thumb="@drawable/shape_switch_thumb"
app:track="@drawable/selector_switch"
tools:ignore="DuplicateSpeakableTextCheck,TouchTargetSizeCheck" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginVertical="10dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/weather_order_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="left|center"
android:text="@string/widgets_settings_select_order"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/weather_order_control"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left|center"
android:text="@string/widgets_settings_select_order"
android:textSize="@dimen/text_large"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/select_weather_widget_color"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginVertical="10dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="left|center"
android:text="@string/settings_appearance_color_title"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:text="@string/widgets_settings_display_battery"
android:textSize="@dimen/text_super_large"
style="@style/TextDefaultStyle" />
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/battery_text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="left|center"
android:text="@string/widgets_settings_display"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/battery_switchCompat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleX="0.7"
android:scaleY="0.8"
android:thumb="@drawable/shape_switch_thumb"
app:track="@drawable/selector_switch"
tools:ignore="TouchTargetSizeCheck" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginVertical="10dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/battery_order_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="left|center"
android:text="@string/widgets_settings_select_order"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/battery_order_control"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left|center"
android:text="@string/widgets_settings_select_order"
android:textSize="@dimen/text_large"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle" />
</androidx.appcompat.widget.LinearLayoutCompat>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/select_battery_widget_color"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="20dp"
android:layout_marginVertical="10dp"
android:orientation="horizontal"
tools:ignore="MissingConstraints">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="left|center"
android:text="@string/settings_appearance_color_title"
android:textSize="@dimen/text_large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="RtlHardcoded"
style="@style/TextDefaultStyle" />
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</androidx.appcompat.widget.LinearLayoutCompat>
</com.github.droidworksstudio.launcher.view.GestureNestedScrollView>
</FrameLayout>

View File

@@ -32,6 +32,7 @@
tools:ignore="SpeakableTextPresentCheck">
<LinearLayout
android:id="@+id/linearLayoutContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="50dp"
@@ -228,6 +229,16 @@
android:text="@string/widgets_battery_voltage"
android:textSize="14sp" />
<TextView
android:id="@+id/battery_current"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:paddingTop="2dp"
android:text="@string/widgets_battery_current"
android:textSize="14sp" />
<TextView
android:id="@+id/battery_temperature"
android:layout_width="match_parent"

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/number_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:textSize="24sp"
android:gravity="center" />

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" />
</LinearLayout>

View File

@@ -41,7 +41,18 @@
android:id="@+id/WidgetsFragment"
android:name="com.github.droidworksstudio.launcher.ui.widgets.WidgetFragment"
android:label="@string/widgets_fragment_label"
tools:layout="@layout/fragment_widgets" />
tools:layout="@layout/fragment_widgets">
<action
android:id="@+id/action_WidgetsFragment_to_WidgetsSettingsFragment"
app:destination="@id/WidgetsSettingsFragment" />
</fragment>
<fragment
android:id="@+id/WidgetsSettingsFragment"
android:name="com.github.droidworksstudio.launcher.ui.widgets.settings.SettingsFragment"
android:label="@string/widgets_fragment_label"
tools:layout="@layout/fragment_settings_widgets" />
<fragment
android:id="@+id/DrawFragment"

View File

@@ -1,7 +1,8 @@
<resources>
<string name="battery_level" translatable="false">%s%%</string>
<string name="widget_mv" translatable="false">mV</string>
<string name="widget_mv" translatable="false">mV</string>
<string name="widget_ma" translatable="false">mA</string>
<string name="widget_c" translatable="false">°C</string>
<string name="widget_f" translatable="false">°F</string>

View File

@@ -29,6 +29,7 @@
<string name="settings_name">Launcher Settings</string>
<string name="settings_version">%1$s Version: %2$s</string>
<string name="settings_widgets_name">Widgets Settings</string>
<string name="settings_title_home_display_preferences">Display</string>
<string name="settings_title_home_behavior_preferences">Behavior</string>
@@ -84,7 +85,6 @@
<string name="settings_swipe_left">Swipe Left</string>
<string name="settings_swipe_right">Swipe Right</string>
<string name="settings_search_engine">Search Engine</string>
<string name="settings_others_share">Share</string>
@@ -598,10 +598,14 @@
<string name="widgets_battery_level">Battery Level : %d %%</string>
<string name="widgets_battery_count">Battery Charge Count : %1$d</string>
<string name="widgets_battery_current">Battery Current : %1$d %2$s</string>
<string name="widgets_battery_status">Charging Status : %1$s</string>
<string name="widgets_battery_health">Battery Health : %1$s</string>
<string name="widgets_battery_voltage">Battery Voltage : %1$d %2$s</string>
<string name="widgets_battery_temperature">Battery Temperature : %1$d %2$s</string>
<string name="widgets_battery_temperature">Battery Temperature : %1.2f %2$s</string>
<string name="widgets_settings_display_weather">Weather Widget</string>
<string name="widgets_settings_display_battery">Battery Widget</string>
<string name="widgets_settings_display">Display</string>
<string name="widgets_settings_select_order">Select Order</string>
</resources>