diff --git a/app/src/main/java/eu/ottop/yamlauncher/AppMenuAdapter.kt b/app/src/main/java/eu/ottop/yamlauncher/AppMenuAdapter.kt index f699424..29b9ade 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/AppMenuAdapter.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/AppMenuAdapter.kt @@ -112,15 +112,15 @@ class AppMenuAdapter( val app = apps[position] if (app.second.second != 0) { - holder.textView.setCompoundDrawablesWithIntrinsicBounds(ResourcesCompat.getDrawable(activity.resources, R.drawable.ic_work_app, null),null,null,null) + holder.textView.setCompoundDrawablesWithIntrinsicBounds(ResourcesCompat.getDrawable(activity.resources, R.drawable.ic_work_app, null),null, ResourcesCompat.getDrawable(activity.resources, R.drawable.ic_empty, null),null) } else { - holder.textView.setCompoundDrawablesWithIntrinsicBounds(ResourcesCompat.getDrawable(activity.resources, R.drawable.ic_empty, null),null,null,null) + holder.textView.setCompoundDrawablesWithIntrinsicBounds(ResourcesCompat.getDrawable(activity.resources, R.drawable.ic_empty, null),null,ResourcesCompat.getDrawable(activity.resources, R.drawable.ic_empty, null),null) } when (preferences.getString("appMenuAlignment", "left")) { "left" -> { - holder.textView.setCompoundDrawablesWithIntrinsicBounds(holder.textView.compoundDrawables.filterNotNull().first(),null, null, null) + holder.textView.setCompoundDrawablesWithIntrinsicBounds(holder.textView.compoundDrawables.filterNotNull().first(),null, ResourcesCompat.getDrawable(activity.resources, R.drawable.ic_empty, null), null) holder.textView.gravity = Gravity.CENTER_VERTICAL or Gravity.START } "center" -> { @@ -129,7 +129,7 @@ class AppMenuAdapter( } "right" -> { - holder.textView.setCompoundDrawablesWithIntrinsicBounds(null,null, holder.textView.compoundDrawables.filterNotNull().first(), null) + holder.textView.setCompoundDrawablesWithIntrinsicBounds(ResourcesCompat.getDrawable(activity.resources, R.drawable.ic_empty, null),null, holder.textView.compoundDrawables.filterNotNull().first(), null) holder.textView.gravity = Gravity.CENTER_VERTICAL or Gravity.END } } diff --git a/app/src/main/java/eu/ottop/yamlauncher/BatteryReceiver.kt b/app/src/main/java/eu/ottop/yamlauncher/BatteryReceiver.kt index 4915ab5..0658202 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/BatteryReceiver.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/BatteryReceiver.kt @@ -7,21 +7,21 @@ import android.content.IntentFilter import android.os.BatteryManager import android.widget.TextClock -class BatteryReceiver(private val dateText: TextClock) : BroadcastReceiver() { +class BatteryReceiver(private val activity: MainActivity) : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { intent?.let { val level = it.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) val scale = it.getIntExtra(BatteryManager.EXTRA_SCALE, -1) val batteryPct = level * 100 / scale.toFloat() - dateText.format12Hour = "dd MMM yyyy | ${batteryPct.toInt()}%" - dateText.format24Hour = "dd MMM yyyy | ${batteryPct.toInt()}%" + activity.modifyDate("${batteryPct.toInt()}%", 2) + } } companion object { - fun register(context: Context, textView: TextClock): BatteryReceiver { - val receiver = BatteryReceiver(textView) + fun register(context: Context, activity: MainActivity): BatteryReceiver { + val receiver = BatteryReceiver(activity) val filter = IntentFilter(Intent.ACTION_BATTERY_CHANGED) context.registerReceiver(receiver, filter) return receiver diff --git a/app/src/main/java/eu/ottop/yamlauncher/HiddenAppsAdapter.kt b/app/src/main/java/eu/ottop/yamlauncher/HiddenAppsAdapter.kt index 0f767ca..d5d0771 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/HiddenAppsAdapter.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/HiddenAppsAdapter.kt @@ -35,7 +35,7 @@ class HiddenAppsAdapter( inner class AppViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { private val listItem: FrameLayout = itemView.findViewById(R.id.list_item) val textView: TextView = listItem.findViewById(R.id.app_name) - val actionMenuLayout: LinearLayout = listItem.findViewById(R.id.action_menu) + private val actionMenuLayout: LinearLayout = listItem.findViewById(R.id.action_menu) private val editView: LinearLayout = listItem.findViewById(R.id.rename_view) val editText: EditText = editView.findViewById(R.id.app_name_edit) @@ -103,14 +103,6 @@ class HiddenAppsAdapter( val appInfo = app.first.activityInfo.applicationInfo holder.textView.text = sharedPreferenceManager.getAppName(activity, app.first.applicationInfo.packageName,app.second.second, holder.itemView.context.packageManager.getApplicationLabel(appInfo)) - holder.editText.setText(holder.textView.text) - - if (appInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0) { - holder.actionMenuLayout.findViewById(R.id.uninstall).visibility = View.GONE - } - else { - holder.actionMenuLayout.findViewById(R.id.uninstall).visibility = View.VISIBLE - } holder.textView.visibility = View.VISIBLE } diff --git a/app/src/main/java/eu/ottop/yamlauncher/HiddenAppsFragment.kt b/app/src/main/java/eu/ottop/yamlauncher/HiddenAppsFragment.kt index 94a186d..f458fa0 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/HiddenAppsFragment.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/HiddenAppsFragment.kt @@ -31,6 +31,7 @@ class HiddenAppsFragment : Fragment(), HiddenAppsAdapter.OnItemClickListener { private val appUtils = AppUtils() private val sharedPreferenceManager = SharedPreferenceManager() private var adapter: HiddenAppsAdapter? = null + private var stringUtils = StringUtils() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -89,7 +90,7 @@ class HiddenAppsFragment : Fragment(), HiddenAppsAdapter.OnItemClickListener { private fun filterItems(query: String?) { - val cleanQuery = query?.clean() + val cleanQuery = stringUtils.cleanString(query) val newFilteredApps = mutableListOf>>() val updatedApps = appUtils.getHiddenApps(requireActivity()) @@ -104,9 +105,11 @@ class HiddenAppsFragment : Fragment(), HiddenAppsAdapter.OnItemClickListener { newFilteredApps.addAll(updatedApps) } else { updatedApps.forEach { - val cleanItemText = sharedPreferenceManager.getAppName(requireActivity(), it.first.applicationInfo.packageName, it.second.second, requireActivity().packageManager.getApplicationLabel(it.first.applicationInfo)).toString().clean() - if (cleanItemText.contains(cleanQuery, ignoreCase = true)) { - newFilteredApps.add(it) + val cleanItemText = stringUtils.cleanString(sharedPreferenceManager.getAppName(requireActivity(), it.first.applicationInfo.packageName, it.second.second, requireActivity().packageManager.getApplicationLabel(it.first.applicationInfo)).toString()) + if (cleanItemText != null) { + if (cleanItemText.contains(cleanQuery, ignoreCase = true)) { + newFilteredApps.add(it) + } } } } @@ -116,10 +119,6 @@ class HiddenAppsFragment : Fragment(), HiddenAppsAdapter.OnItemClickListener { adapter?.updateApps(newFilteredApps) } - private fun String.clean(): String { - return this.replace("[^a-zA-Z0-9]".toRegex(), "") - } - private fun showConfirmationDialog(appInfo: LauncherActivityInfo, appName: String, profile: Int) { AlertDialog.Builder(requireContext()).apply { setTitle("Confirmation") diff --git a/app/src/main/java/eu/ottop/yamlauncher/LocationFragment.kt b/app/src/main/java/eu/ottop/yamlauncher/LocationFragment.kt new file mode 100644 index 0000000..160b129 --- /dev/null +++ b/app/src/main/java/eu/ottop/yamlauncher/LocationFragment.kt @@ -0,0 +1,109 @@ +package eu.ottop.yamlauncher + +import android.app.AlertDialog +import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.EditText +import androidx.fragment.app.setFragmentResult +import androidx.preference.Preference +import androidx.recyclerview.widget.RecyclerView +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +class LocationFragment : Fragment(), LocationListAdapter.OnItemClickListener { + + private var adapter: LocationListAdapter? = null + private val weatherSystem = WeatherSystem() + private val sharedPreferenceManager = SharedPreferenceManager() + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + // Inflate the layout for this fragment + return inflater.inflate(R.layout.fragment_location, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + val searchView = view.findViewById(R.id.locationSearch) + + adapter = LocationListAdapter(requireContext(), weatherSystem.getSearchedLocations( + searchView.text.toString() + ), this) + val recyclerView = view.findViewById(R.id.locationrecycler) + val appMenuEdgeFactory = AppMenuEdgeFactory(requireActivity()) + + recyclerView.edgeEffectFactory = appMenuEdgeFactory + recyclerView.adapter = adapter + + recyclerView.scrollToPosition(0) + + + + recyclerView.addOnLayoutChangeListener { _, _, top, _, bottom, _, oldTop, _, oldBottom -> + + if (bottom - top > oldBottom - oldTop) { + searchView.clearFocus() + } + } + + searchView.addTextChangedListener(object : + TextWatcher { + override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { + } + + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { + println(searchView.text.toString()) + CoroutineScope(Dispatchers.IO).launch { + val locations = weatherSystem.getSearchedLocations( + searchView.text.toString() + ) + withContext(Dispatchers.Main) { + adapter?.updateApps(locations) + } + } + + } + + override fun afterTextChanged(s: Editable?) { + + } + }) + } + + private fun showConfirmationDialog(appName: String?, latitude: String?, longitude: String?) { + AlertDialog.Builder(requireContext()).apply { + setTitle("Confirmation") + setMessage("Are you sure you want to select $appName?") + setPositiveButton("Yes") { _, _ -> + // Perform action on confirmation + performConfirmedAction(appName, latitude, longitude) + } + setNegativeButton("Cancel") { _, _ -> + + } + + }.create().show() + } + + private fun performConfirmedAction(appName: String?, latitude: String?, longitude: String?) { + sharedPreferenceManager.setWeatherLocation(requireContext(), "latitude=${latitude}&longitude=${longitude}", appName) + requireActivity().supportFragmentManager.popBackStack() + } + + + override fun onItemClick(name: String?, latitude: String?, longitude: String?) { + showConfirmationDialog(name, latitude, longitude) + } + + + +} \ No newline at end of file diff --git a/app/src/main/java/eu/ottop/yamlauncher/LocationListAdapter.kt b/app/src/main/java/eu/ottop/yamlauncher/LocationListAdapter.kt index 880bf71..2477103 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/LocationListAdapter.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/LocationListAdapter.kt @@ -2,9 +2,7 @@ package eu.ottop.yamlauncher import android.annotation.SuppressLint import android.content.Context -import android.content.pm.ApplicationInfo import android.content.pm.LauncherActivityInfo -import android.os.UserHandle import android.view.Gravity import android.view.LayoutInflater import android.view.View @@ -13,84 +11,37 @@ import android.widget.EditText import android.widget.FrameLayout import android.widget.LinearLayout import android.widget.TextView +import androidx.constraintlayout.widget.ConstraintLayout import androidx.core.content.res.ResourcesCompat import androidx.preference.PreferenceManager import androidx.recyclerview.widget.RecyclerView class LocationListAdapter( - private val activity: Context, - var apps: MutableList>>, - private val itemClickListener: OnItemClickListener, - private val shortcutListener: OnShortcutListener, - private val itemLongClickListener: OnItemLongClickListener + activity: Context, + var apps: MutableList>, + private val itemClickListener: OnItemClickListener ) : RecyclerView.Adapter() { - var menuMode: String = "app" - var shortcutTextView: TextView? = null - - private val sharedPreferenceManager = SharedPreferenceManager() - private var preferences = PreferenceManager.getDefaultSharedPreferences(activity) + private var preferences = PreferenceManager.getDefaultSharedPreferences(activity) interface OnItemClickListener { - fun onItemClick(appInfo: LauncherActivityInfo, userHandle: UserHandle) - } - - interface OnShortcutListener { - fun onShortcut(appInfo: LauncherActivityInfo, userHandle: UserHandle, textView: TextView, userProfile: Int, shortcutView: TextView) - } - - interface OnItemLongClickListener { - fun onItemLongClick( - appInfo: LauncherActivityInfo, - userHandle: UserHandle, - userProfile: Int, - textView: TextView, - actionMenuLayout: LinearLayout, - editView: LinearLayout, - position: Int - ) + fun onItemClick(name: String?, latitude: String?, longitude: String?) } inner class AppViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - private val listItem: FrameLayout = itemView.findViewById(R.id.list_item) - val textView: TextView = listItem.findViewById(R.id.app_name) - val actionMenuLayout: LinearLayout = listItem.findViewById(R.id.action_menu) - private val editView: LinearLayout = listItem.findViewById(R.id.rename_view) - val editText: EditText = editView.findViewById(R.id.app_name_edit) + private val listItem: ConstraintLayout = itemView.findViewById(R.id.location_place) + val textView: TextView = listItem.findViewById(R.id.location_name) + val regionText: TextView = listItem.findViewById(R.id.region_name) init { - actionMenuLayout.visibility = View.INVISIBLE - editView.visibility = View.INVISIBLE - - textView.setOnClickListener { - val position = bindingAdapterPosition - val app = apps[position].first - if (menuMode == "shortcut") { - shortcutListener.onShortcut(app, apps[position].second.first, textView, apps[position].second.second, shortcutTextView!!) - } - else if (menuMode == "app") { - itemClickListener.onItemClick(app, apps[position].second.first) - } - } - - if (menuMode == "app") { - textView.setOnLongClickListener { - val position = bindingAdapterPosition - - val app = apps[position].first - itemLongClickListener.onItemLongClick( - app, - apps[position].second.first, - apps[position].second.second, - textView, - actionMenuLayout, - editView, - position - ) - return@setOnLongClickListener true - } + listItem.setOnClickListener { + val position = bindingAdapterPosition + val name = apps[position]["name"] + val latitude = apps[position]["latitude"] + val longitude = apps[position]["longitude"] + itemClickListener.onItemClick(name, latitude, longitude) } } @@ -98,63 +49,49 @@ class LocationListAdapter( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppViewHolder { val view = LayoutInflater.from(parent.context) - .inflate(R.layout.app_item_layout, parent, false) + .inflate(R.layout.location_item_layout, parent, false) return AppViewHolder(view) } override fun onBindViewHolder(holder: AppViewHolder, position: Int) { val app = apps[position] - if (app.second.second != 0) { - holder.textView.setCompoundDrawablesWithIntrinsicBounds(ResourcesCompat.getDrawable(activity.resources, R.drawable.ic_work_app, null),null,null,null) - } - else { - holder.textView.setCompoundDrawablesWithIntrinsicBounds(ResourcesCompat.getDrawable(activity.resources, R.drawable.ic_empty, null),null,null,null) - } - when (preferences.getString("appMenuAlignment", "left")) { "left" -> { - holder.textView.setCompoundDrawablesWithIntrinsicBounds(holder.textView.compoundDrawables.filterNotNull().first(),null, null, null) holder.textView.gravity = Gravity.CENTER_VERTICAL or Gravity.START + holder.regionText.gravity = Gravity.CENTER_VERTICAL or Gravity.START } "center" -> { - holder.textView.setCompoundDrawablesWithIntrinsicBounds(holder.textView.compoundDrawables.filterNotNull().first(),null,holder.textView.compoundDrawables.filterNotNull().first(), null) holder.textView.gravity = Gravity.CENTER + holder.regionText.gravity = Gravity.CENTER + } "right" -> { - holder.textView.setCompoundDrawablesWithIntrinsicBounds(null,null, holder.textView.compoundDrawables.filterNotNull().first(), null) holder.textView.gravity = Gravity.CENTER_VERTICAL or Gravity.END + holder.regionText.gravity = Gravity.CENTER_VERTICAL or Gravity.END } } when (preferences.getString("appMenuSize", "medium")) { "small" -> { holder.textView.textSize = 24F - holder.editText.textSize = 24F + holder.regionText.textSize = 14F } "medium" -> { holder.textView.textSize = 26F - holder.editText.textSize = 26F + holder.regionText.textSize = 16F } "large" -> { holder.textView.textSize = 28F - holder.editText.textSize = 28F + holder.regionText.textSize = 18F } } - val appInfo = app.first.activityInfo.applicationInfo - holder.textView.text = sharedPreferenceManager.getAppName(activity, app.first.applicationInfo.packageName,app.second.second, holder.itemView.context.packageManager.getApplicationLabel(appInfo)) - holder.editText.setText(holder.textView.text) - - if (appInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0) { - holder.actionMenuLayout.findViewById(R.id.uninstall).visibility = View.GONE - } - else { - holder.actionMenuLayout.findViewById(R.id.uninstall).visibility = View.VISIBLE - } + holder.textView.text = app["name"] + holder.regionText.text = "${app["region"]}${app["country"]}" holder.textView.visibility = View.VISIBLE } @@ -164,8 +101,9 @@ class LocationListAdapter( } @SuppressLint("NotifyDataSetChanged") - fun updateApps(newApps: List>>) { - apps = newApps.toMutableList() + fun updateApps(newApps: MutableList>) { + apps.clear() + apps = newApps notifyDataSetChanged() } } \ No newline at end of file diff --git a/app/src/main/java/eu/ottop/yamlauncher/MainActivity.kt b/app/src/main/java/eu/ottop/yamlauncher/MainActivity.kt index 214fca1..92a8f28 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/MainActivity.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/MainActivity.kt @@ -57,6 +57,7 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh private lateinit var searchView: EditText private var adapter: AppMenuAdapter? = null private var job: Job? = null + private var weatherJob: Job? = null val cameraIntent = Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE) val phoneIntent = Intent(Intent.ACTION_DIAL) private lateinit var batteryReceiver: BatteryReceiver @@ -79,6 +80,12 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh private lateinit var preferences: SharedPreferences + private val stringUtils = StringUtils() + + private var dateElements = mutableListOf() + + private val weatherSystem = WeatherSystem() + @SuppressLint("ClickableViewAccessibility") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -105,6 +112,8 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh dateText = findViewById(R.id.text_date) + dateElements = mutableListOf(dateText.format12Hour.toString(), dateText.format24Hour.toString(), "", "") + setClockAlignment(preferences.getString("clockAlignment", "left"), clock.id, clockMargin) setupApps() @@ -121,7 +130,7 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh setSearchSize(preferences.getString("searchSize", "medium")) - batteryReceiver = BatteryReceiver.register(this, dateText) + batteryReceiver = BatteryReceiver.register(this, this@MainActivity) binding.homeView.setOnTouchListener { _, event -> gestureDetector.onTouchEvent(event) @@ -137,6 +146,25 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh } + fun modifyDate(value: String, index: Int) { + dateElements[index] = value + dateText.format12Hour = "${dateElements[0]}${stringUtils.addStartTextIfNotEmpty(dateElements[2], " | ")}${stringUtils.addStartTextIfNotEmpty(dateElements[3], " | ")}" + dateText.format24Hour = "${dateElements[1]}${stringUtils.addStartTextIfNotEmpty(dateElements[2], " | ")}${stringUtils.addStartTextIfNotEmpty(dateElements[3], " | ")}" + } + + private fun startWeatherMonitor() { + weatherJob?.cancel() + weatherJob = CoroutineScope(Dispatchers.IO).launch { + while (true) { + val currentWeather = weatherSystem.getTemp(this@MainActivity) + withContext(Dispatchers.Main) { + modifyDate(stringUtils.addEndTextIfNotEmpty(currentWeather, "°C"), 3) + } + delay(300000) + } + } + } + override fun onSharedPreferenceChanged(preferences: SharedPreferences?, key: String?) { when (key) { @@ -190,6 +218,7 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh override fun onStart() { super.onStart() startTask() + startWeatherMonitor() // Keyboard is sometimes open when going back to the app, so close it. closeKeyboard() @@ -392,7 +421,7 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh private suspend fun filterItems(query: String?) { - val cleanQuery = query?.clean() + val cleanQuery = stringUtils.cleanString(query) val newFilteredApps = mutableListOf>>() val updatedApps = appUtils.getInstalledApps(this@MainActivity) @@ -408,9 +437,11 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh newFilteredApps.addAll(installedApps) } else { updatedApps.forEach { - val cleanItemText = sharedPreferenceManager.getAppName(this@MainActivity, it.first.applicationInfo.packageName, it.second.second, packageManager.getApplicationLabel(it.first.applicationInfo)).toString().clean() - if (cleanItemText.contains(cleanQuery, ignoreCase = true)) { - newFilteredApps.add(it) + val cleanItemText = stringUtils.cleanString(sharedPreferenceManager.getAppName(this@MainActivity, it.first.applicationInfo.packageName, it.second.second, packageManager.getApplicationLabel(it.first.applicationInfo)).toString()) + if (cleanItemText != null) { + if (cleanItemText.contains(cleanQuery, ignoreCase = true)) { + newFilteredApps.add(it) + } } } } @@ -425,10 +456,6 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh } } - private fun String.clean(): String { - return this.replace("[^a-zA-Z0-9]".toRegex(), "") - } - private fun startTask() { job?.cancel() job = CoroutineScope(Dispatchers.Default).launch { diff --git a/app/src/main/java/eu/ottop/yamlauncher/SettingsFragment.kt b/app/src/main/java/eu/ottop/yamlauncher/SettingsFragment.kt index 0ce61b1..93c0e37 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/SettingsFragment.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/SettingsFragment.kt @@ -1,38 +1,64 @@ package eu.ottop.yamlauncher import android.os.Bundle +import androidx.fragment.app.setFragmentResultListener import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import androidx.preference.SwitchPreference class SettingsFragment : PreferenceFragmentCompat() { + private var manualLocationPref: Preference? = null + private val sharedPreferenceManager = SharedPreferenceManager() + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { setPreferencesFromResource(R.xml.root_preferences, rootKey) + val weatherSystem = WeatherSystem() + val gpsLocationPref: SwitchPreference? = findPreference("gps_location") - val manualLocationPref: Preference? = findPreference("manual_location") + manualLocationPref = findPreference("manual_location") + + manualLocationPref?.summary = sharedPreferenceManager.getWeatherRegion(requireContext()) if (gpsLocationPref != null && manualLocationPref != null) { // Initial setup - manualLocationPref.isEnabled = !gpsLocationPref.isChecked + manualLocationPref?.isEnabled = !gpsLocationPref.isChecked // Set up a listener to update the enabled state of manualLocationPref gpsLocationPref.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue -> val isGpsEnabled = newValue as Boolean - manualLocationPref.isEnabled = !isGpsEnabled + if (isGpsEnabled) { + weatherSystem.setGpsLocation(requireActivity()) + } + manualLocationPref?.isEnabled = !isGpsEnabled true // Returning true means the change is persisted } + + manualLocationPref?.onPreferenceClickListener = + Preference.OnPreferenceClickListener { + requireActivity().supportFragmentManager + .beginTransaction() + .replace(R.id.settings_layout, LocationFragment()) + .addToBackStack(null) + .commit() + true + } } findPreference("hidden_apps")?.onPreferenceClickListener = Preference.OnPreferenceClickListener { - activity?.supportFragmentManager - ?.beginTransaction() - ?.replace(R.id.settings_layout, HiddenAppsFragment()) - ?.addToBackStack(null) - ?.commit() + requireActivity().supportFragmentManager + .beginTransaction() + .replace(R.id.settings_layout, HiddenAppsFragment()) + .addToBackStack(null) + .commit() true } } + + override fun onResume() { + super.onResume() + manualLocationPref?.summary = sharedPreferenceManager.getWeatherRegion(requireContext()) + } } \ No newline at end of file diff --git a/app/src/main/java/eu/ottop/yamlauncher/SharedPreferenceManager.kt b/app/src/main/java/eu/ottop/yamlauncher/SharedPreferenceManager.kt index de9240f..c7daecf 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/SharedPreferenceManager.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/SharedPreferenceManager.kt @@ -60,17 +60,25 @@ class SharedPreferenceManager { editor.apply() } - fun setWeatherLocation(cont: Context, location: String) { + fun setWeatherLocation(cont: Context, location: String, region: String?) { val editor = cont.getSharedPreferences("weather_location", AppCompatActivity.MODE_PRIVATE).edit() val key = "location" + val regionKey = "location_region" editor.putString(key, location) + editor.putString(regionKey, region) editor.apply() } fun getWeatherLocation(cont: Context) : String? { val sharedPreferences = cont.getSharedPreferences("weather_location", AppCompatActivity.MODE_PRIVATE) val key = "location" - return sharedPreferences.getString(key, null) + return sharedPreferences.getString(key, "") + } + + fun getWeatherRegion(cont: Context) : String? { + val sharedPreferences = cont.getSharedPreferences("weather_location", AppCompatActivity.MODE_PRIVATE) + val key = "location_region" + return sharedPreferences.getString(key, "") } fun setClockAlignment(cont: Context, alignment: Int) { diff --git a/app/src/main/java/eu/ottop/yamlauncher/StringUtils.kt b/app/src/main/java/eu/ottop/yamlauncher/StringUtils.kt new file mode 100644 index 0000000..8ff5493 --- /dev/null +++ b/app/src/main/java/eu/ottop/yamlauncher/StringUtils.kt @@ -0,0 +1,17 @@ +package eu.ottop.yamlauncher + +class StringUtils { + + fun addEndTextIfNotEmpty(value: String, addition: String): String { + return if (value.isNotEmpty()) "$value$addition" else value + } + + fun addStartTextIfNotEmpty(value: String, addition: String): String { + return if (value.isNotEmpty()) "$addition$value" else value + } + + fun cleanString(string: String?) : String? { + return string?.replace("[^a-zA-Z0-9]".toRegex(), "") + } + +} \ No newline at end of file diff --git a/app/src/main/java/eu/ottop/yamlauncher/WeatherSystem.kt b/app/src/main/java/eu/ottop/yamlauncher/WeatherSystem.kt index 8fbb9be..2cc365b 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/WeatherSystem.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/WeatherSystem.kt @@ -10,9 +10,7 @@ import android.location.LocationManager import android.widget.Toast import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import org.json.JSONObject import java.net.HttpURLConnection @@ -21,8 +19,9 @@ import java.net.URL class WeatherSystem { private val sharedPreferenceManager = SharedPreferenceManager() + private val stringUtils = StringUtils() - fun getWeatherForCurrentLocation(activity: Activity) { + fun setGpsLocation(activity: Activity) { val locationManager = activity.getSystemService(Context.LOCATION_SERVICE) as LocationManager val locationListener = object : LocationListener { @@ -49,18 +48,50 @@ class WeatherSystem { if (currentLocation != null) { - sharedPreferenceManager.setWeatherLocation(activity, "latitude=${currentLocation.latitude}&longitude=${currentLocation.longitude}") + sharedPreferenceManager.setWeatherLocation(activity, "latitude=${currentLocation.latitude}&longitude=${currentLocation.longitude}", sharedPreferenceManager.getWeatherRegion(activity)) } else { Toast.makeText(activity, "Unable to get location", Toast.LENGTH_SHORT).show() } - } - fun getTemp(context: Context) { - CoroutineScope(Dispatchers.IO).launch { + // Run within Dispatchers.IO from the outside (doesn't refresh properly otherwise) + fun getSearchedLocations(searchTerm: String?) : MutableList> { + val foundLocations = mutableListOf>() + + val url = URL("https://geocoding-api.open-meteo.com/v1/search?name=$searchTerm&count=50&language=en&format=json") + with(url.openConnection() as HttpURLConnection) { + requestMethod = "GET" + try { + inputStream.bufferedReader().use { + val response = it.readText() + println("yo") + val jsonObject = JSONObject(response) + val resultArray = jsonObject.getJSONArray("results") + + for (i in 0 until resultArray.length()) { + val resultObject: JSONObject = resultArray.getJSONObject(i) + + foundLocations.add(mapOf( + "name" to resultObject.getString("name"), + "latitude" to resultObject.getDouble("latitude").toString(), + "longitude" to resultObject.getDouble("longitude").toString(), + "country" to resultObject.optString("country", resultObject.optString("country_code","")), + "region" to stringUtils.addEndTextIfNotEmpty(resultObject.optString("admin2", resultObject.optString("admin1",resultObject.optString("admin3",""))), ", ") + )) + } + } + }catch (e: Exception){ + e.printStackTrace() + } + } + return foundLocations + } + + suspend fun getTemp(context: Context) : String { + val location = sharedPreferenceManager.getWeatherLocation(context) if (location != null) { val url = URL("https://api.open-meteo.com/v1/forecast?$location¤t=temperature_2m") @@ -73,9 +104,9 @@ class WeatherSystem { val jsonObject = JSONObject(response) val currentData = jsonObject.getJSONObject("current") - val currentWeather = currentData.getInt("temperature_2m") - println("Field1: $currentWeather") + return currentData.getInt("temperature_2m").toString() + } } } @@ -84,7 +115,8 @@ class WeatherSystem { Toast.makeText(context, "No weather location set", Toast.LENGTH_SHORT).show() } } - } + + return "" } } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_location.xml b/app/src/main/res/layout/fragment_location.xml new file mode 100644 index 0000000..037c18d --- /dev/null +++ b/app/src/main/res/layout/fragment_location.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/location_item_layout.xml b/app/src/main/res/layout/location_item_layout.xml new file mode 100644 index 0000000..6f93589 --- /dev/null +++ b/app/src/main/res/layout/location_item_layout.xml @@ -0,0 +1,47 @@ + + + + + + + + \ No newline at end of file