package com.skulixlabs.iotcontrol; import android.Manifest; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.widget.Toast; import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.core.content.ContextCompat; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.Fragment; import androidx.navigation.Navigation; import androidx.preference.ListPreference; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; import androidx.preference.SwitchPreferenceCompat; import com.skulixlabs.iotcontrol.util.jackson.JsonUtils; import java.io.InputStream; import static android.content.ClipDescription.MIMETYPE_TEXT_PLAIN; import static com.skulixlabs.iotcontrol.util.jackson.JsonUtils.REQUEST_READ_FILE; import static com.skulixlabs.iotcontrol.util.jackson.JsonUtils.REQUEST_READ_STORAGE; /** Preference screens does not currently support Data Binding * because it is not a xml layout file */ public class SettingsFragment extends PreferenceFragmentCompat { @ColorInt public static Integer primaryColor = null; public SettingsFragment() { } @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { setPreferencesFromResource(R.xml.root_preferences, rootKey); ((Preference) findPreference("load_json_commands")).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { showImportDialog(); return true; }; }); ((SwitchPreferenceCompat) findPreference("dark_theme")).setOnPreferenceChangeListener(updateThemeListener(themeAction())); ((ListPreference) findPreference("theme_color")).setOnPreferenceChangeListener(updateThemeListener(themeAction())); ((Preference) findPreference("version")).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { Navigation.findNavController(getActivity(), R.id.my_nav_host_fragment).navigate(R.id.action_settingsFragment_to_aboutFragment); return true; }; }); shouldShowImportDialog(); } private void shouldShowImportDialog() { if (SettingsFragmentArgs.fromBundle(getArguments()).getImportCmds()) { getArguments().putBoolean("importCmds", false); showImportDialog(); } } private void showImportDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); LayoutInflater inflater = requireActivity().getLayoutInflater(); // Inflate and set the layout for the dialog // Pass null as the parent view because its going in the dialog layout builder.setView(inflater.inflate(R.layout.dialog_import_method, null)); final AlertDialog alertDialog = builder.create(); alertDialog.show(); alertDialog.findViewById(R.id.btnFromClipboard).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { ClipboardManager clipboard = (ClipboardManager) getActivity().getSystemService(Context.CLIPBOARD_SERVICE); String json = ""; // If the clipboard doesn't contain data, else start the process after validation if (!(clipboard.hasPrimaryClip()) || !(clipboard.getPrimaryClipDescription().hasMimeType(MIMETYPE_TEXT_PLAIN))) { Toast.makeText(getActivity(), "Not valid!", Toast.LENGTH_SHORT).show(); ((Preference) findPreference("load_json_commands")).setIcon(R.drawable.ic_error_outline_red_48dp); } else { try { ClipData.Item item = clipboard.getPrimaryClip().getItemAt(0); // Since the clipboard contains plain text. json = item.getText().toString(); // Gets the clipboard as text. new JsonUtils().saveCommands(getActivity(), json); ((Preference) findPreference("load_json_commands")).setIcon(R.drawable.ic_check_green_48dp); alertDialog.cancel(); } catch (Exception e) { Toast.makeText(getActivity(), "Not valid!", Toast.LENGTH_SHORT).show(); ((Preference) findPreference("load_json_commands")).setIcon(R.drawable.ic_error_outline_red_48dp); } } } }); alertDialog.findViewById(R.id.btnFromFile).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { selectFile(); } }); } public Runnable themeAction() { return new Runnable() { @Override public void run() { primaryColor = null; ((MainActivity) getActivity()).theme(); getActivity().recreate(); } }; } public static synchronized int getPrimaryColor(Context context) { if (primaryColor == null) { TypedValue typedValue = new TypedValue(); context.getTheme().resolveAttribute(R.attr.colorPrimary, typedValue, true); primaryColor = typedValue.data; } return primaryColor; } private String FRAGMENT_DIALOG = "dialog"; public void selectFile() { if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { requestReadStoragePermission(); return; } openFileManager(); } private void openFileManager() { Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("*/*"); startActivityForResult(intent, REQUEST_READ_FILE); } private void requestReadStoragePermission() { if (shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) { new ConfirmationDialog().show(getChildFragmentManager(), FRAGMENT_DIALOG); } else { requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_READ_STORAGE); } } public static class ConfirmationDialog extends DialogFragment { @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Fragment parent = getParentFragment(); return new AlertDialog.Builder(getActivity()) .setMessage(R.string.request_read_external_storage_permission) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { parent.requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_READ_STORAGE); } }) .create(); } } public static class ErrorDialog extends DialogFragment { private static final String ARG_MESSAGE = "message"; public static ErrorDialog newInstance(String message) { ErrorDialog dialog = new ErrorDialog(); Bundle args = new Bundle(); args.putString(ARG_MESSAGE, message); dialog.setArguments(args); return dialog; } @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Activity activity = getActivity(); return new AlertDialog.Builder(activity) .setMessage(getArguments().getString(ARG_MESSAGE)) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int i) { getDialog().cancel(); } }) .create(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == REQUEST_READ_STORAGE) { if (grantResults.length != 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED) { // one requested permission, one result expected (in results array) ErrorDialog.newInstance(getString(R.string.request_read_external_storage_permission)) .show(getChildFragmentManager(), FRAGMENT_DIALOG); } else { openFileManager(); } } else { super.onRequestPermissionsResult(requestCode, permissions, grantResults); } } @Override public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { if (requestCode == REQUEST_READ_FILE && resultCode == Activity.RESULT_OK) { if (data != null) { Uri uri = data.getData(); try { InputStream is = getActivity().getContentResolver().openInputStream(uri); JsonUtils jsonUtils = new JsonUtils(); jsonUtils.saveCommands(getActivity(), is); ((Preference) findPreference("load_json_commands")).setIcon(R.drawable.ic_check_green_48dp); System.out.println(); } catch (Exception e) { ((Preference) findPreference("load_json_commands")).setIcon(R.drawable.ic_error_outline_red_48dp); e.printStackTrace(); } } } } public static Preference.OnPreferenceChangeListener updateThemeListener(final Runnable action) { return new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { action.run(); return true; } }; } }