diff --git a/app/src/main/java/eu/ottop/yamlauncher/AppUtils.kt b/app/src/main/java/eu/ottop/yamlauncher/AppUtils.kt index 2e326ba..1878845 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/AppUtils.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/AppUtils.kt @@ -24,7 +24,7 @@ class AppUtils(private val context: Context, private val launcherApps: LauncherA i ) && app.applicationInfo.packageName != context.applicationInfo.packageName // Hide the launcher itself ) { - allApps.add(Triple(app, launcherApps.profiles[i], i)) + allApps.add(Triple(app, launcherApps.profiles[i], i)) // The i variable gets used to determine whether an app is in the personal profile or work profile } } } diff --git a/app/src/main/java/eu/ottop/yamlauncher/LocationFragment.kt b/app/src/main/java/eu/ottop/yamlauncher/LocationFragment.kt index 23f18bc..e66d9cb 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/LocationFragment.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/LocationFragment.kt @@ -77,19 +77,19 @@ class LocationFragment : Fragment(), LocationListAdapter.OnItemClickListener { } override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { + + } + + override fun afterTextChanged(s: Editable?) { + // Filtering is not needed since we are creating a list with data pulled from the Open-Meteo api instead of searching an existing list lifecycleScope.launch(Dispatchers.IO){ val locations = weatherSystem.getSearchedLocations( searchView.text.toString() ) withContext(Dispatchers.Main) { - adapter?.updateApps(locations) + adapter?.updateLocations(locations) } } - - } - - override fun afterTextChanged(s: Editable?) { - } }) diff --git a/app/src/main/java/eu/ottop/yamlauncher/LocationListAdapter.kt b/app/src/main/java/eu/ottop/yamlauncher/LocationListAdapter.kt index 5d2c925..5a1fa7a 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/LocationListAdapter.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/LocationListAdapter.kt @@ -11,7 +11,7 @@ import androidx.recyclerview.widget.RecyclerView class LocationListAdapter( private val context: Context, - private var apps: MutableList>, + private var locations: MutableList>, private val itemClickListener: OnItemClickListener ) : RecyclerView.Adapter() { @@ -31,9 +31,9 @@ class LocationListAdapter( listItem.setOnClickListener { val position = bindingAdapterPosition - val name = apps[position]["name"] - val latitude = apps[position]["latitude"] - val longitude = apps[position]["longitude"] + val name = locations[position]["name"] + val latitude = locations[position]["latitude"] + val longitude = locations[position]["longitude"] itemClickListener.onItemClick(name, latitude, longitude) } @@ -47,26 +47,26 @@ class LocationListAdapter( } override fun onBindViewHolder(holder: AppViewHolder, position: Int) { - val app = apps[position] + val location = locations[position] uiUtils.setAppAlignment(holder.textView, null, holder.regionText) uiUtils.setAppSize(holder.textView, null, holder.regionText) - holder.textView.text = app["name"] - holder.regionText.text = context.getString(R.string.region_text, app["region"], app["country"]) + holder.textView.text = location["name"] + holder.regionText.text = context.getString(R.string.region_text, location["region"], location["country"]) holder.textView.visibility = View.VISIBLE } override fun getItemCount(): Int { - return apps.size + return locations.size } @SuppressLint("NotifyDataSetChanged") - fun updateApps(newApps: MutableList>) { - apps.clear() - apps = newApps + fun updateLocations(newApps: MutableList>) { + locations.clear() + locations = 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 7cf251d..3fbe06b 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/MainActivity.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/MainActivity.kt @@ -100,6 +100,7 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh setHomeListeners() + // Task to update the app menu every 5 seconds lifecycleScope.launch { lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { while (true) { @@ -109,6 +110,7 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh } } + // Task to update the weather every 10 minutes lifecycleScope.launch(Dispatchers.IO) { repeatOnLifecycle(Lifecycle.State.STARTED) { while (true) { @@ -171,9 +173,9 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh for (i in shortcuts.indices) { val textView = findViewById(shortcuts[i]) - val shortcutNo = sharedPreferenceManager.getShortcutNumber() + // Only show the chosen number of shortcuts (default 4). Hide the rest. if (i >= shortcutNo!!) { textView.visibility = View.GONE } @@ -181,37 +183,35 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh else { textView.visibility = View.VISIBLE - unsetShortcutSetup(textView) + val savedView = sharedPreferenceManager.getShortcut(textView) + // Set the non-work profile drawable by default + textView.setCompoundDrawablesWithIntrinsicBounds(ResourcesCompat.getDrawable(resources, R.drawable.ic_empty, null),null,null,null) + + shortcutListeners(textView) + if (savedView?.get(1) != "e") { setShortcutSetup(textView, savedView) } + else { + unsetShortcutSetup(textView) + } uiUtils.setShortcutsAlignment(binding.homeView) } - } - } @SuppressLint("ClickableViewAccessibility") - private fun unsetShortcutSetup(textView: TextView) { + private fun shortcutListeners(textView: TextView) { + // Don't go to settings on long click, but keep other gestures functional textView.setOnTouchListener {_, event -> shortcutGestureDetector.onTouchEvent(event) super.onTouchEvent(event) } - textView.setCompoundDrawablesWithIntrinsicBounds(ResourcesCompat.getDrawable(resources, R.drawable.ic_empty, null),null,null,null) - - unsetShortcutListeners(textView) - } - - private fun unsetShortcutListeners(textView: TextView) { - textView.setOnClickListener { - Toast.makeText(this, "Long click to select an app", Toast.LENGTH_SHORT).show() - } textView.setOnLongClickListener { uiUtils.setMenuTitleAlignment(binding.menuTitle) binding.menuTitle.visibility = View.VISIBLE @@ -225,6 +225,7 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh private fun toAppMenu() { try { + // The menu opens from the top recyclerView.scrollToPosition(0) } catch (_: UninitializedPropertyAccessException) { @@ -240,13 +241,22 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh } } + private fun unsetShortcutSetup(textView: TextView) { + unsetShortcutListeners(textView) + } + + private fun unsetShortcutListeners(textView: TextView) { + textView.setOnClickListener { + Toast.makeText(this, "Long click to select an app", Toast.LENGTH_SHORT).show() + } + } + private fun setShortcutSetup(textView: TextView, savedView: List?) { + // Set the work profile drawable for work profile apps if (savedView?.get(1) != "0") { textView.setCompoundDrawablesWithIntrinsicBounds(ResourcesCompat.getDrawable(resources, R.drawable.ic_work_app, null),null,null,null) } - else { - textView.setCompoundDrawablesWithIntrinsicBounds(ResourcesCompat.getDrawable(resources, R.drawable.ic_empty, null),null,null,null) - } + textView.text = savedView?.get(2) setShortcutListeners(textView, savedView) } @@ -278,6 +288,7 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh true } + // Return to home on back onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { backToHome() @@ -299,6 +310,7 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh } } + // Only reload items that have had preferences changed override fun onSharedPreferenceChanged(preferences: SharedPreferences?, key: String?) { if (preferences != null) { when (key) { @@ -368,6 +380,11 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh } fun modifyDate(value: String, index: Int) { + /*Indexes: + 0 = 12h time + 1 = 24h time + 2 = Weather + 3 = Battery level*/ 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], " | ")}" @@ -378,6 +395,9 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh animations.showHome(binding.homeView, binding.appView) animations.backgroundOut(this@MainActivity) val animSpeed = sharedPreferenceManager.getAnimationSpeed() + + // Delay app menu changes so that the user doesn't see them + val handler = Handler(Looper.getMainLooper()) handler.postDelayed({ try { @@ -405,6 +425,8 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh suspend fun refreshAppMenu() { try { + + // Don't reset app menu while under a search if (isJobActive) { val updatedApps = appUtils.getInstalledApps() if (!listsEqual(installedApps, updatedApps)) { @@ -487,6 +509,7 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh setupRecyclerListener() } + // Inform the layout manager of scroll states to calculate whether the menu is on the top private fun setupRecyclerListener() { recyclerView.addOnScrollListener(object: RecyclerView.OnScrollListener() { override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { @@ -502,10 +525,12 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh binding.appView.addOnLayoutChangeListener { _, _, top, _, bottom, _, oldTop, _, oldBottom -> if (bottom - top > oldBottom - oldTop) { + // Allow the app menu to be closed after the keyboard is closed canExit = true searchView.clearFocus() } else if (bottom - top < oldBottom - oldTop) { + // The app menu can't be closed with the keyboard open canExit = false } } @@ -572,6 +597,7 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh } } + // On home key or swipe, return to home screen override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) backToHome() diff --git a/app/src/main/java/eu/ottop/yamlauncher/ScreenLockService.kt b/app/src/main/java/eu/ottop/yamlauncher/ScreenLockService.kt index a6776c2..6eeb5a0 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/ScreenLockService.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/ScreenLockService.kt @@ -7,11 +7,9 @@ import android.view.accessibility.AccessibilityEvent class ScreenLockService : AccessibilityService() { override fun onAccessibilityEvent(event: AccessibilityEvent?) { - // Handle accessibility events if needed } override fun onInterrupt() { - // Handle interrupt } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { diff --git a/app/src/main/java/eu/ottop/yamlauncher/SettingsFragment.kt b/app/src/main/java/eu/ottop/yamlauncher/SettingsFragment.kt index 71d9dde..87d379a 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/SettingsFragment.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/SettingsFragment.kt @@ -1,8 +1,6 @@ package eu.ottop.yamlauncher import android.os.Bundle -import androidx.fragment.app.clearFragmentResultListener -import androidx.fragment.app.setFragmentResultListener import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import androidx.preference.SwitchPreference @@ -26,10 +24,6 @@ class SettingsFragment : PreferenceFragmentCompat() { val aboutPref = findPreference("aboutPage") val hiddenPref = findPreference("hiddenApps") - manualLocationPref?.summary = sharedPreferenceManager.getWeatherRegion() - leftSwipePref?.summary = sharedPreferenceManager.getGestureName("left") - rightSwipePref?.summary = sharedPreferenceManager.getGestureName("right") - // Only enable manual location when gps location is disabled if (gpsLocationPref != null && manualLocationPref != null) { manualLocationPref?.isEnabled = !gpsLocationPref.isChecked diff --git a/app/src/main/java/eu/ottop/yamlauncher/SharedPreferenceManager.kt b/app/src/main/java/eu/ottop/yamlauncher/SharedPreferenceManager.kt index aae61b6..f609402 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/SharedPreferenceManager.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/SharedPreferenceManager.kt @@ -9,6 +9,40 @@ class SharedPreferenceManager (context: Context) { private val preferences = PreferenceManager.getDefaultSharedPreferences(context) + // General UI + fun getBgColor(): Int { + return Color.parseColor(preferences.getString("bgColor", "#00000000")) + } + + fun getTextColor(): Int { + return Color.parseColor(preferences.getString("textColor", "#FFF3F3F3")) + } + + fun isBarVisible(): Boolean { + return preferences.getBoolean("barVisibility", false) + } + + fun getAnimationSpeed(): Long { + val animSpeed = preferences.getString("animationSpeed", "200")?.toLong() + if (animSpeed != null) { + return animSpeed + } + return 200 + } + + // Home Screen + fun getClockAlignment(): String? { + return preferences.getString("clockAlignment", "left") + } + + fun getClockSize(): String? { + return preferences.getString("clockSize","medium") + } + + fun getDateSize(): String? { + return preferences.getString("dateSize", "medium") + } + fun setShortcut(textView: TextView, packageName: String, profile: Int) { val editor = preferences.edit() editor.putString("shortcut${textView.id}", "$packageName§splitter§$profile§splitter§${textView.text}") @@ -24,36 +58,25 @@ class SharedPreferenceManager (context: Context) { return preferences.getString("shortcutNo", "4")?.toInt() } - fun setAppHidden(packageName: String, profile: Int, hidden: Boolean) { - val editor = preferences.edit() - editor.putBoolean("hidden$packageName-$profile", hidden) - editor.apply() + fun getShortcutAlignment(): String? { + return preferences.getString("shortcutAlignment", "left") } - fun isAppHidden(packageName: String, profile: Int): Boolean { - return preferences.getBoolean("hidden$packageName-$profile", false) // Default to false (visible) + fun getShortcutSize(): String? { + return preferences.getString("shortcutSize", "medium") } - fun setAppVisible(packageName: String, profile: Int) { - val editor = preferences.edit() - editor.remove("hidden$packageName-$profile") - editor.apply() + fun isBatteryEnabled(): Boolean { + return preferences.getBoolean("batteryEnabled", false) } - fun setAppName(packageName: String, profile: Int, newName: String) { - val editor = preferences.edit() - editor.putString("name$packageName-$profile", newName) - editor.apply() + // Weather + fun isWeatherEnabled(): Boolean { + return preferences.getBoolean("weatherEnabled", false) } - fun getAppName(packageName: String, profile: Int, appName: CharSequence): CharSequence? { - return preferences.getString("name$packageName-$profile", appName.toString()) - } - - fun resetAppName(packageName: String, profile: Int) { - val editor = preferences.edit() - editor.remove("name$packageName-$profile") - editor.apply() + fun isWeatherGPS(): Boolean { + return preferences.getBoolean("gpsLocation", false) } fun setWeatherLocation(location: String, region: String?) { @@ -71,6 +94,11 @@ class SharedPreferenceManager (context: Context) { return preferences.getString("locationRegion", "") } + fun getTempUnits(): String? { + return preferences.getString("tempUnits", "celsius") + } + + // Gestures fun setGestures(direction: String, appName: String?) { val editor = preferences.edit() editor.putString("${direction}SwipeApp", appName) @@ -94,79 +122,58 @@ class SharedPreferenceManager (context: Context) { return preferences.getBoolean("doubleTap", false) } - fun getBgColor(): Int { - return Color.parseColor(preferences.getString("bgColor", "#00000000")) - } - - fun getTextColor(): Int { - return Color.parseColor(preferences.getString("textColor", "#FFF3F3F3")) - } - - fun getClockAlignment(): String? { - return preferences.getString("clockAlignment", "left") - } - - fun getShortcutAlignment(): String? { - return preferences.getString("shortcutAlignment", "left") - } - + // Application Menu fun getAppAlignment(): String? { return preferences.getString("appMenuAlignment", "left") } - fun getSearchAlignment(): String? { - return preferences.getString("searchAlignment", "left") - } - - fun getClockSize(): String? { - return preferences.getString("clockSize","medium") - } - - fun getDateSize(): String? { - return preferences.getString("dateSize", "medium") - } - - fun getShortcutSize(): String? { - return preferences.getString("shortcutSize", "medium") - } - fun getAppSize(): String? { return preferences.getString("appMenuSize", "medium") } - fun getSearchSize(): String? { - return preferences.getString("searchSize", "medium") + fun getSearchAlignment(): String? { + return preferences.getString("searchAlignment", "left") } - fun isBarVisible(): Boolean { - return preferences.getBoolean("barVisibility", false) + fun getSearchSize(): String? { + return preferences.getString("searchSize", "medium") } fun isAutoKeyboardEnabled(): Boolean { return preferences.getBoolean("autoKeyboard", false) } - fun getTempUnits(): String? { - return preferences.getString("tempUnits", "celsius") + // Hidden Apps + fun setAppHidden(packageName: String, profile: Int, hidden: Boolean) { + val editor = preferences.edit() + editor.putBoolean("hidden$packageName-$profile", hidden) + editor.apply() } - fun isWeatherEnabled(): Boolean { - return preferences.getBoolean("weatherEnabled", false) + fun isAppHidden(packageName: String, profile: Int): Boolean { + return preferences.getBoolean("hidden$packageName-$profile", false) // Default to false (visible) } - fun isWeatherGPS(): Boolean { - return preferences.getBoolean("gpsLocation", false) + fun setAppVisible(packageName: String, profile: Int) { + val editor = preferences.edit() + editor.remove("hidden$packageName-$profile") + editor.apply() } - fun isBatteryEnabled(): Boolean { - return preferences.getBoolean("batteryEnabled", false) + //Renaming apps + fun setAppName(packageName: String, profile: Int, newName: String) { + val editor = preferences.edit() + editor.putString("name$packageName-$profile", newName) + editor.apply() } - fun getAnimationSpeed(): Long { - val animSpeed = preferences.getString("animationSpeed", "200")?.toLong() - if (animSpeed != null) { - return animSpeed - } - return 200 + fun getAppName(packageName: String, profile: Int, appName: CharSequence): CharSequence? { + return preferences.getString("name$packageName-$profile", appName.toString()) + } + + fun resetAppName(packageName: String, profile: Int) { + val editor = preferences.edit() + editor.remove("name$packageName-$profile") + editor.apply() } } \ No newline at end of file diff --git a/app/src/main/java/eu/ottop/yamlauncher/UIUtils.kt b/app/src/main/java/eu/ottop/yamlauncher/UIUtils.kt index 6eb7eaf..3c19bd5 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/UIUtils.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/UIUtils.kt @@ -22,6 +22,7 @@ class UIUtils(context: Context) { private val sharedPreferenceManager = SharedPreferenceManager(context) + // Colors fun setBackground(window: Window) { window.decorView.setBackgroundColor( sharedPreferenceManager.getBgColor() @@ -70,7 +71,6 @@ class UIUtils(context: Context) { val globalLayoutListener = object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { searchView.viewTreeObserver.removeOnGlobalLayoutListener(this) - println("yoooooooo") val color = sharedPreferenceManager.getTextColor() searchView.setTextColor(color) searchView.setHintTextColor(setAlpha(color, "A9")) @@ -83,6 +83,7 @@ class UIUtils(context: Context) { } } + // Alignment fun setClockAlignment(clock: TextClock, dateText: TextClock) { val alignment = sharedPreferenceManager.getClockAlignment() setTextAlignment(clock, alignment) @@ -190,6 +191,7 @@ class UIUtils(context: Context) { } catch (_: Exception) {} } + // Size fun setClockSize(clock: TextClock) { setTextSize(clock, sharedPreferenceManager.getClockSize(), 58F, 68F, 78F) } @@ -288,6 +290,7 @@ class UIUtils(context: Context) { } catch (_: Exception) {} } + // Status bar visibility fun setStatusBar(window: Window) { val windowInsetsController = window.insetsController diff --git a/app/src/main/java/eu/ottop/yamlauncher/WeatherSystem.kt b/app/src/main/java/eu/ottop/yamlauncher/WeatherSystem.kt index 3e24078..9629435 100644 --- a/app/src/main/java/eu/ottop/yamlauncher/WeatherSystem.kt +++ b/app/src/main/java/eu/ottop/yamlauncher/WeatherSystem.kt @@ -32,23 +32,24 @@ class WeatherSystem(private val context: Context) { } locationManager.getCurrentLocation( - LocationManager.GPS_PROVIDER, // Use GPS provider - null, // No cancellation signal + LocationManager.GPS_PROVIDER, // Only GPS provider functions on my phone with CalyxOS, so that's what you get. + null, ContextCompat.getMainExecutor(context) ) - { location: Location? -> // Lambda expression for the callback + { location: Location? -> if (location != null) { CoroutineScope(Dispatchers.IO).launch { val latitude = location.latitude val longitude = location.longitude sharedPreferenceManager.setWeatherLocation("latitude=${latitude}&longitude=${longitude}", sharedPreferenceManager.getWeatherRegion()) - activity.updateWeatherText()} + activity.updateWeatherText() + } } } } - // Run within Dispatchers.IO from the outside (doesn't refresh properly otherwise) + // Run within Dispatchers.IO from the outside (doesn't seem to refresh properly otherwise) fun getSearchedLocations(searchTerm: String?) : MutableList> { val foundLocations = mutableListOf>() @@ -79,6 +80,7 @@ class WeatherSystem(private val context: Context) { return foundLocations } + // Run with Dispatchers.IO from the outside fun getTemp() : String { val tempUnits = sharedPreferenceManager.getTempUnits() @@ -103,19 +105,19 @@ class WeatherSystem(private val context: Context) { when (currentData.getInt("weather_code")) { 0, 1 -> { - weatherType = "☀\uFE0E" + weatherType = "☀\uFE0E" // Sunny } 2, 3, 45, 48 -> { - weatherType = "☁\uFE0E" + weatherType = "☁\uFE0E" // Sunny } 51, 53, 55, 56, 57, 61, 63, 65, 67, 80, 81, 82 -> { - weatherType = "☂\uFE0E" + weatherType = "☂\uFE0E" // Rain } 71, 73, 75, 77, 85, 86 -> { - weatherType = "❄\uFE0E" + weatherType = "❄\uFE0E" // Snow } 95, 96, 99 -> { - weatherType = "⛈\uFE0E" + weatherType = "⛈\uFE0E" // Thunder } } diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml index a24e08e..4556dbd 100644 --- a/app/src/main/res/xml/root_preferences.xml +++ b/app/src/main/res/xml/root_preferences.xml @@ -45,15 +45,6 @@ android:layout_height="wrap_content" app:allowDividerAbove="false" app:title="Home Screen"> - +