Migrate SettingsFragment to Kotlin

This commit is contained in:
TPJ Schikhof
2024-10-03 03:07:41 +00:00
committed by Albert Vaca Cintora
parent 0ffd9cd9dc
commit 8cb9a1809d
4 changed files with 188 additions and 212 deletions

View File

@@ -567,6 +567,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
<string name="plugin_stats">Plugin stats</string>
<string name="enable_udp_broadcast">Enable UDP device discovery</string>
<string name="enable_bluetooth">Enable bluetooth (beta)</string>
<string name="receive_notifications_permission_explanation">Notifications need to be allowed to receive them from other devices</string>
<string name="findmyphone_notifications_explanation">The notifications permission is needed so the phone can ring when the app is in the background</string>

View File

@@ -1,211 +0,0 @@
/*
* SPDX-FileCopyrightText: 2023 Albert Vaca Cintora <albertvaka@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
package org.kde.kdeconnect.UserInterface;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.text.InputFilter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.preference.EditTextPreference;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import androidx.preference.TwoStatePreference;
import com.google.android.material.snackbar.Snackbar;
import org.apache.commons.lang3.StringUtils;
import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.Helpers.DeviceHelper;
import org.kde.kdeconnect.Helpers.NotificationHelper;
import org.kde.kdeconnect_tp.R;
public class SettingsFragment extends PreferenceFragmentCompat {
public static final String KEY_UDP_BROADCAST_ENABLED = "udp_broadcast_enabled";
public static final String KEY_BLUETOOTH_ENABLED = "bluetooth_enabled";
public static final String KEY_APP_THEME = "theme_pref";
private EditTextPreference renameDevice;
@NonNull
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
if (getActivity() != null) {
((MainActivity) requireActivity()).getSupportActionBar().setTitle(R.string.settings);
}
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
Context context = getPreferenceManager().getContext();
PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(context);
// Rename device
renameDevice = new EditTextPreference(context);
renameDevice.setKey(DeviceHelper.KEY_DEVICE_NAME_PREFERENCE);
renameDevice.setSelectable(true);
renameDevice.setOnBindEditTextListener(TextView::setSingleLine);
renameDevice.setOnBindEditTextListener(editText -> editText.setFilters(new InputFilter[] {
(source, start, end, dest, dstart, dend) -> DeviceHelper.filterName(source.subSequence(start, end).toString()),
new InputFilter.LengthFilter(DeviceHelper.MAX_DEVICE_NAME_LENGTH),
}));
String deviceName = DeviceHelper.getDeviceName(context);
renameDevice.setTitle(R.string.settings_rename);
renameDevice.setSummary(deviceName);
renameDevice.setDialogTitle(R.string.device_rename_title);
renameDevice.setText(deviceName);
renameDevice.setPositiveButtonText(R.string.device_rename_confirm);
renameDevice.setNegativeButtonText(R.string.cancel);
renameDevice.setOnPreferenceChangeListener((preference, newValue) -> {
String name = (String) newValue;
if (StringUtils.isBlank(name)) {
if (getView() != null) {
Snackbar snackbar = Snackbar.make(getView(), R.string.invalid_device_name, Snackbar.LENGTH_LONG);
int currentTheme = getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
if (currentTheme != Configuration.UI_MODE_NIGHT_YES) {
// white color is set to the background of snackbar if dark mode is off
snackbar.getView().setBackgroundColor(Color.WHITE);
}
snackbar.show();
}
return false;
}
renameDevice.setSummary((String)newValue);
return true;
});
screen.addPreference(renameDevice);
// Theme Selector
ListPreference themeSelector = new ListPreference(context);
themeSelector.setKey(KEY_APP_THEME);
themeSelector.setTitle(R.string.theme_dialog_title);
themeSelector.setDialogTitle(R.string.theme_dialog_title);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
themeSelector.setEntries(R.array.theme_list_v28);
} else {
themeSelector.setEntries(R.array.theme_list);
}
themeSelector.setEntryValues(R.array.theme_list_values);
themeSelector.setDefaultValue(ThemeUtil.DEFAULT_MODE);
themeSelector.setSummaryProvider(ListPreference.SimpleSummaryProvider.getInstance());
themeSelector.setOnPreferenceChangeListener((preference, newValue) -> {
String themeValue = (String) newValue;
ThemeUtil.applyTheme(themeValue);
return true;
});
screen.addPreference(themeSelector);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Preference persistentNotif = new Preference(context);
persistentNotif.setTitle(R.string.setting_persistent_notification_oreo);
persistentNotif.setSummary(R.string.setting_persistent_notification_description);
persistentNotif.setOnPreferenceClickListener(preference -> {
Intent intent = new Intent();
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
intent.putExtra("android.provider.extra.APP_PACKAGE", context.getPackageName());
context.startActivity(intent);
return true;
});
screen.addPreference(persistentNotif);
} else {
// Persistent notification toggle for Android Versions below Oreo
final TwoStatePreference notificationSwitch = new SwitchPreference(context);
notificationSwitch.setPersistent(false);
notificationSwitch.setChecked(NotificationHelper.isPersistentNotificationEnabled(context));
notificationSwitch.setTitle(R.string.setting_persistent_notification);
notificationSwitch.setOnPreferenceChangeListener((preference, newValue) -> {
final boolean isChecked = (Boolean) newValue;
NotificationHelper.setPersistentNotificationEnabled(context, isChecked);
BackgroundService service = BackgroundService.getInstance();
if (service != null) {
service.changePersistentNotificationVisibility(isChecked);
}
NotificationHelper.setPersistentNotificationEnabled(context, isChecked);
return true;
});
screen.addPreference(notificationSwitch);
}
// Trusted Networks
Preference trustedNetworkPref = new Preference(context);
trustedNetworkPref.setPersistent(false);
trustedNetworkPref.setTitle(R.string.trusted_networks);
trustedNetworkPref.setSummary(R.string.trusted_networks_desc);
screen.addPreference(trustedNetworkPref);
trustedNetworkPref.setOnPreferenceClickListener(preference -> {
startActivity(new Intent(context, TrustedNetworksActivity.class));
return true;
});
// Add device by IP
Preference devicesByIpPreference = new Preference(context);
devicesByIpPreference.setPersistent(false);
devicesByIpPreference.setTitle(R.string.custom_device_list);
screen.addPreference(devicesByIpPreference);
devicesByIpPreference.setOnPreferenceClickListener(preference -> {
startActivity(new Intent(context, CustomDevicesActivity.class));
return true;
});
// UDP broadcast toggle
final TwoStatePreference udpBroadcastDiscovery = new SwitchPreference(context);
udpBroadcastDiscovery.setDefaultValue(true);
udpBroadcastDiscovery.setKey(KEY_UDP_BROADCAST_ENABLED);
udpBroadcastDiscovery.setTitle(R.string.enable_udp_broadcast);
screen.addPreference(udpBroadcastDiscovery);
final TwoStatePreference enableBluetoothSupport = new SwitchPreference(context);
enableBluetoothSupport.setDefaultValue(false);
enableBluetoothSupport.setKey(KEY_BLUETOOTH_ENABLED);
enableBluetoothSupport.setTitle("Enable bluetooth (beta)");
enableBluetoothSupport.setOnPreferenceChangeListener((preference, newValue) -> {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && (boolean)newValue) {
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN}, 2);
}
return true;
});
screen.addPreference(enableBluetoothSupport);
// More settings text
Preference moreSettingsText = new Preference(context);
moreSettingsText.setPersistent(false);
moreSettingsText.setSelectable(false);
moreSettingsText.setTitle(R.string.settings_more_settings_title);
moreSettingsText.setSummary(R.string.settings_more_settings_text);
screen.addPreference(moreSettingsText);
setPreferenceScreen(screen);
}
}

View File

@@ -0,0 +1,187 @@
/*
* SPDX-FileCopyrightText: 2023 Albert Vaca Cintora <albertvaka@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
package org.kde.kdeconnect.UserInterface
import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.text.InputFilter
import android.text.InputFilter.LengthFilter
import android.text.Spanned
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.EditText
import androidx.core.app.ActivityCompat
import androidx.preference.EditTextPreference
import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.SwitchPreference
import androidx.preference.TwoStatePreference
import com.google.android.material.snackbar.Snackbar
import org.kde.kdeconnect.BackgroundService
import org.kde.kdeconnect.Helpers.DeviceHelper
import org.kde.kdeconnect.Helpers.DeviceHelper.filterName
import org.kde.kdeconnect.Helpers.DeviceHelper.getDeviceName
import org.kde.kdeconnect.Helpers.NotificationHelper
import org.kde.kdeconnect.UserInterface.ThemeUtil.applyTheme
import org.kde.kdeconnect_tp.R
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
if (activity != null) {
(activity as MainActivity).supportActionBar?.setTitle(R.string.settings)
}
return super.onCreateView(inflater, container, savedInstanceState)
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
val context = preferenceManager.context
val screen = preferenceManager.createPreferenceScreen(context)
listOf(
deviceNamePref(context),
themePref(context),
persistentNotificationPref(context),
trustedNetworkPref(context),
devicesByIpPref(context),
udpBroadcastPref(context),
bluetoothSupportPref(context),
moreSettingsPref(context),
).forEach(screen::addPreference)
preferenceScreen = screen
}
private fun deviceNamePref(context: Context) = EditTextPreference(context).apply {
key = DeviceHelper.KEY_DEVICE_NAME_PREFERENCE
isSelectable = true
setOnBindEditTextListener(EditText::setSingleLine)
setOnBindEditTextListener { editText: EditText ->
editText.filters = arrayOf(
InputFilter { source: CharSequence, start: Int, end: Int, _: Spanned?, _: Int, _: Int -> filterName(source.subSequence(start, end).toString()) },
LengthFilter(DeviceHelper.MAX_DEVICE_NAME_LENGTH),
)
}
val deviceName = getDeviceName(context)
setTitle(R.string.settings_rename)
summary = deviceName
setDialogTitle(R.string.device_rename_title)
text = deviceName
setPositiveButtonText(R.string.device_rename_confirm)
setNegativeButtonText(R.string.cancel)
onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _: Preference?, new: Any? ->
val name = new as String?
if (!name.isNullOrBlank()) {
if (view != null) {
val snackbar = Snackbar.make(requireView(), R.string.invalid_device_name, Snackbar.LENGTH_LONG)
val currentTheme = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
if (currentTheme != Configuration.UI_MODE_NIGHT_YES) {
// white color is set to the background of snackbar if dark mode is off
snackbar.view.setBackgroundColor(Color.WHITE)
}
snackbar.show()
}
false
}
else {
summary = new
true
}
}
}
private fun themePref(context: Context) = ListPreference(context).apply {
key = KEY_APP_THEME
setTitle(R.string.theme_dialog_title)
setDialogTitle(R.string.theme_dialog_title)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) setEntries(R.array.theme_list_v28) else setEntries(R.array.theme_list)
setEntryValues(R.array.theme_list_values)
setDefaultValue(ThemeUtil.DEFAULT_MODE)
summaryProvider = ListPreference.SimpleSummaryProvider.getInstance()
onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _: Preference?, new: Any? ->
if (new is String) {
applyTheme(new)
}
true
}
}
private fun persistentNotificationPref(context: Context): Preference =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) Preference(context).apply {
setTitle(R.string.setting_persistent_notification_oreo)
setSummary(R.string.setting_persistent_notification_description)
onPreferenceClickListener = Preference.OnPreferenceClickListener {
val intent = Intent()
intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS")
intent.putExtra("android.provider.extra.APP_PACKAGE", context.packageName)
context.startActivity(intent)
true
}
}
// Persistent notification toggle for Android Versions below Oreo
else SwitchPreference(context).apply {
isPersistent = false
isChecked = NotificationHelper.isPersistentNotificationEnabled(context)
setTitle(R.string.setting_persistent_notification)
onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _: Preference?, new: Any ->
val isChecked = new as Boolean
NotificationHelper.setPersistentNotificationEnabled(context, isChecked)
BackgroundService.instance?.changePersistentNotificationVisibility(isChecked)
NotificationHelper.setPersistentNotificationEnabled(context, isChecked)
true
}
}
private fun trustedNetworkPref(context: Context) = Preference(context).apply {
isPersistent = false
setTitle(R.string.trusted_networks)
setSummary(R.string.trusted_networks_desc)
onPreferenceClickListener = Preference.OnPreferenceClickListener {
startActivity(Intent(context, TrustedNetworksActivity::class.java))
true
}
}
/** Opens activity to configure device by IP when clicked */
private fun devicesByIpPref(context: Context) = Preference(context).apply {
isPersistent = false
setTitle(R.string.custom_device_list)
onPreferenceClickListener = Preference.OnPreferenceClickListener {
startActivity(Intent(context, CustomDevicesActivity::class.java))
true
}
}
private fun udpBroadcastPref(context: Context) = SwitchPreference(context).apply {
setDefaultValue(true)
key = KEY_UDP_BROADCAST_ENABLED
setTitle(R.string.enable_udp_broadcast)
}
private fun bluetoothSupportPref(context: Context) = SwitchPreference(context).apply {
setDefaultValue(false)
key = KEY_BLUETOOTH_ENABLED
setTitle(R.string.enable_bluetooth)
onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _: Preference?, newValue: Any ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && newValue as Boolean) {
ActivityCompat.requestPermissions(requireActivity(), arrayOf(Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN), 2)
}
true
}
}
private fun moreSettingsPref(context: Context) = Preference(context).apply {
isPersistent = false
isSelectable = false
setTitle(R.string.settings_more_settings_title)
setSummary(R.string.settings_more_settings_text)
}
companion object {
const val KEY_UDP_BROADCAST_ENABLED: String = "udp_broadcast_enabled"
const val KEY_BLUETOOTH_ENABLED: String = "bluetooth_enabled"
const val KEY_APP_THEME: String = "theme_pref"
}
}

View File

@@ -22,7 +22,6 @@ object ThemeUtil {
const val DARK_MODE: String = "dark"
const val DEFAULT_MODE: String = "default"
@JvmStatic
fun applyTheme(themePref: String) {
when (themePref) {
LIGHT_MODE -> {