From 76444527e0fc8a752fb02597ecd2a7a2229c8a88 Mon Sep 17 00:00:00 2001 From: iusmac Date: Sun, 9 Jun 2024 10:34:21 +0200 Subject: [PATCH 1/9] Convert `SIM PIN` preference to a FAB button --- res/color/fab_pin_background_tint_color.xml | 6 + res/color/fab_pin_tint_color.xml | 18 ++ res/drawable/ic_pin_lock_24dp.xml | 20 ++ res/drawable/ic_pin_lock_not_set_24dp.xml | 15 ++ res/drawable/sd_pin_lock_24dp.xml | 5 + res/layout/dialog_edittext.xml | 29 +++ res/layout/scheduler_fabs.xml | 23 +++ res/menu/scheduler_pin_options.xml | 15 ++ res/values/colors.xml | 4 + res/values/dimens.xml | 1 + res/values/strings.xml | 3 +- res/values/styles.xml | 23 +++ res/xml/scheduler_preferences.xml | 4 - .../ui/components/EditTextDialogFragment.java | 179 ++++++++++++++++++ .../ui/scheduler/SchedulerFragment.java | 171 +++++++++++++---- .../ui/scheduler/SchedulerViewModel.java | 25 ++- 16 files changed, 496 insertions(+), 45 deletions(-) create mode 100644 res/color/fab_pin_background_tint_color.xml create mode 100644 res/color/fab_pin_tint_color.xml create mode 100644 res/drawable/ic_pin_lock_24dp.xml create mode 100644 res/drawable/ic_pin_lock_not_set_24dp.xml create mode 100644 res/drawable/sd_pin_lock_24dp.xml create mode 100644 res/layout/dialog_edittext.xml create mode 100644 res/layout/scheduler_fabs.xml create mode 100644 res/menu/scheduler_pin_options.xml create mode 100644 res/values/styles.xml create mode 100644 src/com/github/iusmac/sevensim/ui/components/EditTextDialogFragment.java diff --git a/res/color/fab_pin_background_tint_color.xml b/res/color/fab_pin_background_tint_color.xml new file mode 100644 index 0000000..054f0c6 --- /dev/null +++ b/res/color/fab_pin_background_tint_color.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/res/color/fab_pin_tint_color.xml b/res/color/fab_pin_tint_color.xml new file mode 100644 index 0000000..583d4e9 --- /dev/null +++ b/res/color/fab_pin_tint_color.xml @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/res/drawable/ic_pin_lock_24dp.xml b/res/drawable/ic_pin_lock_24dp.xml new file mode 100644 index 0000000..5cf55a5 --- /dev/null +++ b/res/drawable/ic_pin_lock_24dp.xml @@ -0,0 +1,20 @@ + + + + + + diff --git a/res/drawable/ic_pin_lock_not_set_24dp.xml b/res/drawable/ic_pin_lock_not_set_24dp.xml new file mode 100644 index 0000000..9a4fb2c --- /dev/null +++ b/res/drawable/ic_pin_lock_not_set_24dp.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/res/drawable/sd_pin_lock_24dp.xml b/res/drawable/sd_pin_lock_24dp.xml new file mode 100644 index 0000000..9aeb54a --- /dev/null +++ b/res/drawable/sd_pin_lock_24dp.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/res/layout/dialog_edittext.xml b/res/layout/dialog_edittext.xml new file mode 100644 index 0000000..81b72d3 --- /dev/null +++ b/res/layout/dialog_edittext.xml @@ -0,0 +1,29 @@ + + + + + + + + diff --git a/res/layout/scheduler_fabs.xml b/res/layout/scheduler_fabs.xml new file mode 100644 index 0000000..a9f083e --- /dev/null +++ b/res/layout/scheduler_fabs.xml @@ -0,0 +1,23 @@ + + + + + diff --git a/res/menu/scheduler_pin_options.xml b/res/menu/scheduler_pin_options.xml new file mode 100644 index 0000000..ac06a95 --- /dev/null +++ b/res/menu/scheduler_pin_options.xml @@ -0,0 +1,15 @@ + + + + + + + + + + diff --git a/res/values/colors.xml b/res/values/colors.xml index 6a97e34..4796682 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -2,4 +2,8 @@ #FFFFDDB4 #FF4F4539 + #FFCFEBC0 + #FFF0E3A8 + #1D7233 + #895900 diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 79abff8..db932a0 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -16,4 +16,5 @@ --> 80dp + 16dp diff --git a/res/values/strings.xml b/res/values/strings.xml index 461258d..d195913 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -58,6 +58,8 @@ PIN has been set Enter SIM PIN Type a PIN that is 4 to 8 numbers. + "Edit" + "Delete" "Couldn't decrypt SIM PIN code. Re-enter SIM PIN to fix." "Incorrect SIM PIN code. Re-enter the correct PIN code." "Enter PIN code" @@ -89,6 +91,5 @@ "scheduler_days_of_week" "scheduler_start_time" "scheduler_end_time" - "scheduler_pin" "scheduler_pin_error" diff --git a/res/values/styles.xml b/res/values/styles.xml new file mode 100644 index 0000000..6467d0b --- /dev/null +++ b/res/values/styles.xml @@ -0,0 +1,23 @@ + + + + + + + diff --git a/res/xml/scheduler_preferences.xml b/res/xml/scheduler_preferences.xml index 1db13d4..76e7274 100644 --- a/res/xml/scheduler_preferences.xml +++ b/res/xml/scheduler_preferences.xml @@ -27,8 +27,4 @@ android:key="@string/scheduler_end_time_key" android:title="@string/scheduler_end_time_title" android:dependency="@string/scheduler_days_of_week_key"/> - - diff --git a/src/com/github/iusmac/sevensim/ui/components/EditTextDialogFragment.java b/src/com/github/iusmac/sevensim/ui/components/EditTextDialogFragment.java new file mode 100644 index 0000000..92fcd8b --- /dev/null +++ b/src/com/github/iusmac/sevensim/ui/components/EditTextDialogFragment.java @@ -0,0 +1,179 @@ +package com.github.iusmac.sevensim.ui.components; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.os.Bundle; +import android.text.InputFilter; +import android.text.InputType; +import android.view.View; +import android.view.Window; +import android.view.WindowInsets; +import android.view.WindowManager; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.fragment.app.DialogFragment; +import androidx.fragment.app.FragmentResultListener; + +import com.github.iusmac.sevensim.R; +import com.github.iusmac.sevensim.Utils; + +/** + * A {@link DialogFragment} prompting the user for input. + */ +public class EditTextDialogFragment extends DialogFragment { + public static final String TAG = EditTextDialogFragment.class.getSimpleName(); + + private static final String SAVED_REQUEST_KEY = "requestKey"; + private static final String SAVED_TITLE = "title"; + private static final String SAVED_INPUT_TYPE = "inputType"; + private static final String SAVED_MAX_LENGTH = "maxLength"; + + /** Handle completing the {@link EditText} from the IME keyboard. */ + private final TextView.OnEditorActionListener mImeDoneListener = (v, actionId, event) -> { + // Check if this was the result of hitting the enter key + if (event == null && (actionId == EditorInfo.IME_NULL + || actionId == EditorInfo.IME_ACTION_DONE + || actionId == EditorInfo.IME_ACTION_NEXT)) { + onDone(); + dismissAllowingStateLoss(); + return true; + } + return false; + }; + + /** + * The default request key string passed in + * {@link FragmentResultListener#onFragmentResult(String,Bundle)} to identify the result when + * the user is done filling in the input field and pressed the "OK" button. + */ + public static final String DEFAULT_REQUEST_KEY = "requestKey"; + + /** Key holding the result passed in + * {@link FragmentResultListener#onFragmentResult(String,Bundle)}. */ + public static final String EXTRA_TEXT = "text"; + + private String mRequestKey; + private EditText mEditText; + private String mTitle; + private int mInputType = -1; + private int mMaxLength = -1; + + public EditTextDialogFragment() { + } + + /** + * @param requestKey The request key string for + * {@link FragmentResultListener#onFragmentResult(String,Bundle)} to identify the result when + * the user is done filling in the input field and pressed the "OK" button, or {@code null} to + * use {@link #DEFAULT_REQUEST_KEY}. + */ + public EditTextDialogFragment(final @Nullable String requestKey) { + mRequestKey = requestKey; + } + + @Override + public Dialog onCreateDialog(final Bundle savedInstanceState) { + final View editTextContainer = getLayoutInflater().inflate(R.layout.dialog_edittext, null); + mEditText = editTextContainer.findViewById(android.R.id.edit); + + if (savedInstanceState != null) { + mRequestKey = savedInstanceState.getString(SAVED_REQUEST_KEY); + setTitle(savedInstanceState.getString(SAVED_TITLE)); + setInputType(savedInstanceState.getInt(SAVED_INPUT_TYPE)); + setMaxInputLength(savedInstanceState.getInt(SAVED_MAX_LENGTH)); + } + + final AlertDialog alertDialog = new AlertDialog.Builder(requireContext()) + .setTitle(mTitle == null ? getString(R.string.app_name) : mTitle) + .setView(editTextContainer) + .setPositiveButton(android.R.string.ok, (dialog, which) -> onDone()) + .setNegativeButton(android.R.string.cancel, null) + .create(); + + mEditText.setOnEditorActionListener(mImeDoneListener); + + // Trigger soft keyboard opening + final Window window = alertDialog.getWindow(); + if (Utils.IS_AT_LEAST_R) { + window.getDecorView().getWindowInsetsController().show(WindowInsets.Type.ime()); + } else { + mEditText.setOnFocusChangeListener((v, hasFocus) -> { + if (hasFocus) { + window.setSoftInputMode(WindowManager.LayoutParams + .SOFT_INPUT_STATE_ALWAYS_VISIBLE); + } + }); + } + mEditText.requestFocus(); + if (mInputType != -1) { + mEditText.setInputType(mInputType); + } + if (mMaxLength > -1) { + mEditText.setFilters(new InputFilter[] { + new InputFilter.LengthFilter(mMaxLength) + }); + } + + return alertDialog; + } + + /** + * Set the title of the dialog. + * + * @param title The title string. + */ + public void setTitle(final @Nullable String title) { + mTitle = title; + } + + /** + * Set the type of the content using {@link InputType} constants. + * + * @attr ref android.R.styleable#TextView_inputType + * + * @param type The {@link InputType} flags. + */ + public void setInputType(final int type) { + mInputType = type; + } + + /** + * Restrict the input length to an arbitrary amount of characters. + * + * @attr ref android.R.styleable#TextView_maxLength + * + * @param maxLength The maximum number of characters. + */ + public void setMaxInputLength(final int maxLength) { + mMaxLength = maxLength; + } + + private void onDone() { + final String requestKey = mRequestKey == null ? DEFAULT_REQUEST_KEY : mRequestKey; + final Bundle result = new Bundle(1); + result.putString(EXTRA_TEXT, mEditText.getText().toString()); + getParentFragmentManager().setFragmentResult(requestKey, result); + } + + @Override + public void onSaveInstanceState(final Bundle outState) { + super.onSaveInstanceState(outState); + + outState.putString(SAVED_REQUEST_KEY, mRequestKey); + outState.putString(SAVED_TITLE, mTitle); + outState.putInt(SAVED_INPUT_TYPE, mInputType); + outState.putInt(SAVED_MAX_LENGTH, mMaxLength); + outState.putBoolean(SAVED_SINGLE_LINE_INPUT, mSingleLineInput); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + + // Stop callbacks from the IME since there's no view to process them + mEditText.setOnEditorActionListener(null); + } +} diff --git a/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerFragment.java b/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerFragment.java index 1f29f0a..8a4f3f2 100644 --- a/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerFragment.java +++ b/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerFragment.java @@ -5,18 +5,27 @@ import android.content.Intent; import android.content.SharedPreferences; import android.os.Bundle; -import android.text.InputFilter; import android.text.InputType; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.Menu; import android.view.View; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.widget.FrameLayout; +import android.widget.PopupMenu; +import android.widget.RelativeLayout; import androidx.activity.result.ActivityResult; import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.core.view.MenuCompat; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentResultListener; import androidx.lifecycle.LiveData; -import androidx.preference.EditTextPreference; import androidx.preference.MultiSelectListPreference; import androidx.preference.Preference; import androidx.preference.PreferenceDataStore; @@ -30,9 +39,12 @@ import com.github.iusmac.sevensim.Utils; import com.github.iusmac.sevensim.telephony.TelephonyUtils; import com.github.iusmac.sevensim.ui.AuthenticationPromptActivity; +import com.github.iusmac.sevensim.ui.components.EditTextDialogFragment; import com.github.iusmac.sevensim.ui.components.TimePickerPreference; import com.github.iusmac.sevensim.ui.components.TimePickerPreferenceDialogFragmentCompat; +import com.google.android.material.floatingactionbutton.FloatingActionButton; + import dagger.hilt.android.AndroidEntryPoint; import java.util.Arrays; @@ -44,7 +56,9 @@ import static com.github.iusmac.sevensim.ui.scheduler.SchedulerViewModel.TimeType; @AndroidEntryPoint(PreferenceFragmentCompat.class) -public final class SchedulerFragment extends Hilt_SchedulerFragment { +public final class SchedulerFragment extends Hilt_SchedulerFragment + implements FragmentResultListener { + private static final String ACTION_AUTH_HANDLE_ON_PIN_CHANGED = "action_auth_handle_on_pin_changed"; @@ -63,6 +77,10 @@ public final class SchedulerFragment extends Hilt_SchedulerFragment { private static final String EXTRA_TIME_TYPE = "time_type"; private static final String EXTRA_TIME = "time"; + private static final String SAVED_PIN_POPUP_VISIBLE = "pinPopupVisible"; + + private static final String PIN_PROMPT_RESULT_REQUEST_KEY = "pin_prompt_result"; + @Inject Logger.Factory mLoggerFactory; @@ -71,13 +89,15 @@ public final class SchedulerFragment extends Hilt_SchedulerFragment { private String mPrefDaysOfWeekKey; private String mPrefStartTimeKey; private String mPrefEndTimeKey; - private String mPrefPinKey; private SchedulerViewModel mViewModel; private final ActivityResultLauncher mAuthenticationPromptLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), this::onAuthResult); + private boolean mPinPopupMenuVisible; private MainSwitchPreference mMainSwitchPref; + private FloatingActionButton mPinFab; + private PopupMenu mPinPopupMenu; private void onAuthResult(final ActivityResult result) { mLogger.d("onAuthResult(result=%s).", result); @@ -121,7 +141,6 @@ public void onAttach(final Context context) { mPrefDaysOfWeekKey = getString(R.string.scheduler_days_of_week_key); mPrefStartTimeKey = getString(R.string.scheduler_start_time_key); mPrefEndTimeKey = getString(R.string.scheduler_end_time_key); - mPrefPinKey = getString(R.string.scheduler_pin_key); } @Override @@ -134,16 +153,46 @@ public void onCreatePreferences(final Bundle savedInstanceState, final String ro addPreferencesFromResource(R.xml.scheduler_preferences); } + @Override + public View onCreateView(final LayoutInflater inflater, final ViewGroup container, + final Bundle savedInstanceState) { + + final RelativeLayout fabContainer = (RelativeLayout) + inflater.inflate(R.layout.scheduler_fabs, /*container=*/ null, false); + + mPinFab = fabContainer.findViewById(R.id.fab_pin); + + final ViewGroup.MarginLayoutParams marginLp = new ViewGroup.MarginLayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + + // Add FAB container to an outer container that varies depending on the Android version + final ViewParent parent = container.getParent(); + if (parent instanceof CoordinatorLayout) { + final CoordinatorLayout.LayoutParams lp = new CoordinatorLayout.LayoutParams(marginLp); + lp.gravity = Gravity.BOTTOM; + ((ViewGroup) parent).addView(fabContainer, lp); + } else { + final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(marginLp); + lp.gravity = Gravity.BOTTOM; + container.addView(fabContainer, lp); + } + + return super.onCreateView(inflater, container, savedInstanceState); + } + @Override public void onViewCreated(final View view, final Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + final FragmentManager fm = getParentFragmentManager(); + fm.setFragmentResultListener(PIN_PROMPT_RESULT_REQUEST_KEY, getViewLifecycleOwner(), this); + setupMainSwitchPref(); setupPinErrorPref(); setupDaysOfWeekPref(); setupTimePref(TimeType.START_TIME); setupTimePref(TimeType.END_TIME); - setupPinPref(); + setupPinFab(); } private void setupMainSwitchPref() { @@ -159,8 +208,7 @@ private void setupPinErrorPref() { pinErrorPref .setPositiveButtonText(R.string.scheduler_pin_banner_enter_pin_code_button_text) - .setPositiveButtonOnClickListener((view) -> - onDisplayPreferenceDialog((EditTextPreference) findPreference(mPrefPinKey))); + .setPositiveButtonOnClickListener((view) -> showPinPromptDialog()); mViewModel.getPinTaskLock().observe(getViewLifecycleOwner(), (isLockHeld) -> pinErrorPref.setEnabled(!isLockHeld)); @@ -230,28 +278,52 @@ private void setupTimePref(final TimeType which) { timeSummary.observe(getViewLifecycleOwner(), (summary) -> timePref.setSummary(summary)); } - private void setupPinPref() { - final EditTextPreference pinPref = findPreference(mPrefPinKey); - - pinPref.setOnBindEditTextListener((editText) -> { - // Clear input junk from the previous usage - editText.setText(""); - - // Allow only numbers in the input field - editText.setInputType(InputType.TYPE_CLASS_NUMBER | - InputType.TYPE_NUMBER_VARIATION_PASSWORD); - - // Limit the maximum PIN length as per UICC specs - editText.setFilters(new InputFilter[] { - new InputFilter.LengthFilter(TelephonyUtils.PIN_MAX_PIN_LENGTH) - }); + private void setupPinFab() { + mViewModel.getPinTaskLock().observe(getViewLifecycleOwner(), (isPinTaskLockHeld) -> + mPinFab.setEnabled(!isPinTaskLockHeld)); + + mViewModel.getPinPresence().observe(getViewLifecycleOwner(), (isPresent) -> + mPinFab.setImageState(new int[] { isPresent ? android.R.attr.state_checked : 0 }, + /*merge=*/ true)); + + mPinPopupMenu = new PopupMenu(requireActivity(), mPinFab, Gravity.NO_GRAVITY, + /*popupStyleAttr=*/ 0, R.style.PopupMenuDefaultAnimationStyle); + final Menu menu = mPinPopupMenu.getMenu(); + MenuCompat.setGroupDividerEnabled(menu, true); + mPinPopupMenu.getMenuInflater().inflate(R.menu.scheduler_pin_options, menu); + mPinPopupMenu.setOnMenuItemClickListener((menuItem) -> { + final int itemId = menuItem.getItemId(); + if (R.id.scheduler_pin_edit_option == itemId) { + showPinPromptDialog(); + } else if (R.id.scheduler_pin_delete_option == itemId) { + mViewModel.removePin(); + } else { + mLogger.wtf("Unhandled menu option: %s.", menuItem); + } + return true; }); + mPinPopupMenu.setOnDismissListener((p) -> mPinPopupMenuVisible = false); - mViewModel.getPinPresenceSummary().observe(getViewLifecycleOwner(), (summary) -> - pinPref.setSummary(summary)); + mPinFab.setOnClickListener((v) -> { + if (mViewModel.isPinPresent()) { + mPinPopupMenuVisible = true; + mPinPopupMenu.show(); + } else { + showPinPromptDialog(); + } + }); + } - mViewModel.getPinTaskLock().observe(getViewLifecycleOwner(), (isPinTaskLockHeld) -> - pinPref.setEnabled(!isPinTaskLockHeld)); + private void showPinPromptDialog() { + final EditTextDialogFragment dialogFragment = + new EditTextDialogFragment(PIN_PROMPT_RESULT_REQUEST_KEY); + dialogFragment.setTitle(getString(R.string.scheduler_pin_title)); + // Allow only numbers in the input field + dialogFragment.setInputType(InputType.TYPE_CLASS_NUMBER | + InputType.TYPE_NUMBER_VARIATION_PASSWORD); + // Limit the maximum PIN length as per UICC specs + dialogFragment.setMaxInputLength(TelephonyUtils.PIN_MAX_PIN_LENGTH); + dialogFragment.show(getParentFragmentManager(), EditTextDialogFragment.TAG); } private void handleOnPinChanged(final String pin) { @@ -283,6 +355,19 @@ private void authenticateAndRunAction(final String action, final Bundle payload) mAuthenticationPromptLauncher.launch(i); } + @Override + public void onFragmentResult(final String requestKey, final Bundle bundle) { + switch (requestKey) { + case PIN_PROMPT_RESULT_REQUEST_KEY: + handleOnPinChanged(bundle.getString(EditTextDialogFragment.EXTRA_TEXT)); + break; + + default: + mLogger.wtf(new RuntimeException("Unhandled fragment result: " + requestKey + + ",bundle = " + bundle)); + } + } + @SuppressWarnings("deprecation") @Override public void onDisplayPreferenceDialog(final @NonNull Preference preference) { @@ -309,6 +394,33 @@ public void onDisplayPreferenceDialog(final @NonNull Preference preference) { f.show(manager, TimePickerPreference.TAG); } + @Override + public void onSaveInstanceState(final Bundle outState) { + super.onSaveInstanceState(outState); + + outState.putBoolean(SAVED_PIN_POPUP_VISIBLE, mPinPopupMenuVisible); + } + + @Override + public void onViewStateRestored(final Bundle savedInstanceState) { + super.onViewStateRestored(savedInstanceState); + + if (savedInstanceState != null) { + if (mPinPopupMenuVisible = savedInstanceState.getBoolean(SAVED_PIN_POPUP_VISIBLE)) { + mPinFab.post(() -> mPinPopupMenu.show()); + } + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + + if (mPinPopupMenu != null) { + mPinPopupMenu.dismiss(); + } + } + /** * This is a custom instance of {@link PreferenceDataStore} used to hijack the default * persistence phase on disk via {@link SharedPreferences} when preferences change or require an @@ -365,8 +477,6 @@ public void putString(final String key, final String value) { if (isStartTime || key.equals(mPrefEndTimeKey)) { mViewModel.handleOnTimeChanged(isStartTime ? TimeType.START_TIME : TimeType.END_TIME, value); - } else if (key.equals(mPrefPinKey)) { - handleOnPinChanged(value); } else { mLogger.wtf("putString() : unhandled key = " + key); } @@ -379,9 +489,6 @@ public String getString(final String key, final String defValue) { return mViewModel.getTime(isStartTime ? TimeType.START_TIME : TimeType.END_TIME).getValue().toString(); } - if (key.equals(mPrefPinKey)) { - return null; - } mLogger.wtf("getString() : unhandled key = " + key); return defValue; } diff --git a/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerViewModel.java b/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerViewModel.java index 1d13cf5..44ae23c 100644 --- a/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerViewModel.java +++ b/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerViewModel.java @@ -92,7 +92,7 @@ LocalTime getDefaultLocalTime() { private final MediatorLiveData> mMediatorPinEntity = new MediatorLiveData<>(Optional.empty()); - private LiveData mObservablePinPresenceSummary; + private LiveData mObservablePinPresence; private final MutableLiveData mMutablePinTaskLock = new MutableLiveData<>(false); private LiveData> mObseravblePinErrorMessage; @@ -305,15 +305,14 @@ LiveData getEndTimeSummary() { } /** - * @return An observable human-readable status indicating PIN presence. + * @return An observable containing the PIN presence status. */ - LiveData getPinPresenceSummary() { - if (mObservablePinPresenceSummary == null) { - mObservablePinPresenceSummary = Transformations.map(mMediatorPinEntity, (pinEntity) -> - mResources.getString(pinEntity.isPresent() ? R.string.scheduler_pin_set_summary - : R.string.scheduler_pin_unset_summary)); + LiveData getPinPresence() { + if (mObservablePinPresence == null) { + mObservablePinPresence = Transformations.map(mMediatorPinEntity, (pinEntity) -> + pinEntity.isPresent()); } - return mObservablePinPresenceSummary; + return mObservablePinPresence; } /** @@ -479,6 +478,16 @@ void removeScheduler() { refreshNextUpcomingScheduleSummaryAsync(); } + /** + * Remove the SIM PIN code, if present. + */ + void removePin() { + mLogger.d("removePin()."); + + mMediatorPinEntity.getValue().ifPresent((pin) -> mHandler.post(() -> + mPinStorage.deletePin(pin))); + } + /** * @return {@code true} if the scheduler exists, otherwise {@code false}. */ From 8fb479d16087fb37a5a70b8770f0ee968bde1249 Mon Sep 17 00:00:00 2001 From: iusmac Date: Sun, 9 Jun 2024 10:49:04 +0200 Subject: [PATCH 2/9] Add the `Add` FAB button --- res/color-night-v34/fab_add_tint_color.xml | 7 ++++++ res/color-night/fab_add_tint_color.xml | 6 +++++ res/color-v31/fab_add_tint_color.xml | 6 +++++ res/color-v34/fab_add_tint_color.xml | 7 ++++++ res/color/fab_add_background_tint_color.xml | 4 +++ res/color/fab_add_tint_color.xml | 6 +++++ res/drawable/ic_add_24dp.xml | 25 +++++++++++++++++++ res/layout/scheduler_fabs.xml | 14 +++++++++++ res/values-night-v34/colors.xml | 4 +++ res/values-v31/colors.xml | 1 + res/values-v34/colors.xml | 4 +++ res/values/dimens.xml | 1 + res/values/strings.xml | 1 + .../ui/scheduler/SchedulerFragment.java | 10 ++++++++ 14 files changed, 96 insertions(+) create mode 100644 res/color-night-v34/fab_add_tint_color.xml create mode 100644 res/color-night/fab_add_tint_color.xml create mode 100644 res/color-v31/fab_add_tint_color.xml create mode 100644 res/color-v34/fab_add_tint_color.xml create mode 100644 res/color/fab_add_background_tint_color.xml create mode 100644 res/color/fab_add_tint_color.xml create mode 100644 res/drawable/ic_add_24dp.xml create mode 100644 res/values-night-v34/colors.xml create mode 100644 res/values-v34/colors.xml diff --git a/res/color-night-v34/fab_add_tint_color.xml b/res/color-night-v34/fab_add_tint_color.xml new file mode 100644 index 0000000..77eddbd --- /dev/null +++ b/res/color-night-v34/fab_add_tint_color.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/res/color-night/fab_add_tint_color.xml b/res/color-night/fab_add_tint_color.xml new file mode 100644 index 0000000..bc2225d --- /dev/null +++ b/res/color-night/fab_add_tint_color.xml @@ -0,0 +1,6 @@ + + + + diff --git a/res/color-v31/fab_add_tint_color.xml b/res/color-v31/fab_add_tint_color.xml new file mode 100644 index 0000000..05e0254 --- /dev/null +++ b/res/color-v31/fab_add_tint_color.xml @@ -0,0 +1,6 @@ + + + + diff --git a/res/color-v34/fab_add_tint_color.xml b/res/color-v34/fab_add_tint_color.xml new file mode 100644 index 0000000..8850630 --- /dev/null +++ b/res/color-v34/fab_add_tint_color.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/res/color/fab_add_background_tint_color.xml b/res/color/fab_add_background_tint_color.xml new file mode 100644 index 0000000..8a810ee --- /dev/null +++ b/res/color/fab_add_background_tint_color.xml @@ -0,0 +1,4 @@ + + + + diff --git a/res/color/fab_add_tint_color.xml b/res/color/fab_add_tint_color.xml new file mode 100644 index 0000000..1e4a32e --- /dev/null +++ b/res/color/fab_add_tint_color.xml @@ -0,0 +1,6 @@ + + + + diff --git a/res/drawable/ic_add_24dp.xml b/res/drawable/ic_add_24dp.xml new file mode 100644 index 0000000..d58a0b4 --- /dev/null +++ b/res/drawable/ic_add_24dp.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/res/layout/scheduler_fabs.xml b/res/layout/scheduler_fabs.xml index a9f083e..555504c 100644 --- a/res/layout/scheduler_fabs.xml +++ b/res/layout/scheduler_fabs.xml @@ -20,4 +20,18 @@ app:shapeAppearanceOverlay="@style/FabRoundedStyle" app:maxImageSize="42dp" app:srcCompat="@drawable/sd_pin_lock_24dp" /> + + diff --git a/res/values-night-v34/colors.xml b/res/values-night-v34/colors.xml new file mode 100644 index 0000000..2233e17 --- /dev/null +++ b/res/values-night-v34/colors.xml @@ -0,0 +1,4 @@ + + + @android:color/system_accent1_700 + diff --git a/res/values-v31/colors.xml b/res/values-v31/colors.xml index 0a4b43b..47c6c66 100644 --- a/res/values-v31/colors.xml +++ b/res/values-v31/colors.xml @@ -3,4 +3,5 @@ @android:color/system_accent1_100 @android:color/system_neutral2_700 @android:color/system_neutral2_700 + @android:color/system_accent1_100 diff --git a/res/values-v34/colors.xml b/res/values-v34/colors.xml new file mode 100644 index 0000000..0ada464 --- /dev/null +++ b/res/values-v34/colors.xml @@ -0,0 +1,4 @@ + + + @android:color/system_accent1_100 + diff --git a/res/values/dimens.xml b/res/values/dimens.xml index db932a0..058a272 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -17,4 +17,5 @@ 80dp 16dp + 88dp diff --git a/res/values/strings.xml b/res/values/strings.xml index d195913..7698b9a 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -41,6 +41,7 @@ ",\u0020" + "Add a schedule" "Reset" "This operation cannot be undone.\n\nWould you like to continue?" "Use schedule" diff --git a/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerFragment.java b/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerFragment.java index 8a4f3f2..1c075ae 100644 --- a/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerFragment.java +++ b/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerFragment.java @@ -97,6 +97,7 @@ public final class SchedulerFragment extends Hilt_SchedulerFragment private MainSwitchPreference mMainSwitchPref; private FloatingActionButton mPinFab; + private FloatingActionButton mAddFab; private PopupMenu mPinPopupMenu; private void onAuthResult(final ActivityResult result) { @@ -161,6 +162,7 @@ public View onCreateView(final LayoutInflater inflater, final ViewGroup containe inflater.inflate(R.layout.scheduler_fabs, /*container=*/ null, false); mPinFab = fabContainer.findViewById(R.id.fab_pin); + mAddFab = fabContainer.findViewById(R.id.fab_add); final ViewGroup.MarginLayoutParams marginLp = new ViewGroup.MarginLayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); @@ -193,6 +195,7 @@ public void onViewCreated(final View view, final Bundle savedInstanceState) { setupTimePref(TimeType.START_TIME); setupTimePref(TimeType.END_TIME); setupPinFab(); + setupAddFab(); } private void setupMainSwitchPref() { @@ -314,6 +317,13 @@ private void setupPinFab() { }); } + private void setupAddFab() { + mAddFab.setBackgroundTintList(requireContext() + .getColorStateList(R.color.fab_add_background_tint_color)); + mAddFab.setOnClickListener((v) -> { + }); + } + private void showPinPromptDialog() { final EditTextDialogFragment dialogFragment = new EditTextDialogFragment(PIN_PROMPT_RESULT_REQUEST_KEY); From 599d44b1cb3c7f7809cd0d8fe47d91cc278b9138 Mon Sep 17 00:00:00 2001 From: iusmac Date: Mon, 10 Jun 2024 11:16:44 +0200 Subject: [PATCH 3/9] Drop `Reset` scheduler option --- res/menu/scheduler.xml | 6 --- .../ui/scheduler/SchedulerActivity.java | 41 ----------------- .../ui/scheduler/SchedulerViewModel.java | 45 ------------------- 3 files changed, 92 deletions(-) delete mode 100644 res/menu/scheduler.xml diff --git a/res/menu/scheduler.xml b/res/menu/scheduler.xml deleted file mode 100644 index cef535d..0000000 --- a/res/menu/scheduler.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - diff --git a/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerActivity.java b/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerActivity.java index fafbc55..326e569 100644 --- a/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerActivity.java +++ b/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerActivity.java @@ -1,13 +1,10 @@ package com.github.iusmac.sevensim.ui.scheduler; -import android.app.AlertDialog; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.Process; -import android.view.Menu; -import android.view.MenuItem; import android.view.View; import androidx.core.os.BundleCompat; @@ -15,7 +12,6 @@ import androidx.lifecycle.ViewModelProvider; import com.github.iusmac.sevensim.Logger; -import com.github.iusmac.sevensim.R; import com.github.iusmac.sevensim.scheduler.SubscriptionScheduler; import com.github.iusmac.sevensim.telephony.Subscription; import com.github.iusmac.sevensim.telephony.Subscriptions; @@ -59,32 +55,6 @@ public final class SchedulerActivity extends Hilt_SchedulerActivity private final Object mSubscriptionsChangedToken = new Object(); private boolean mSubscriptionsChangedListenerInitialized; - @Override - public boolean onCreateOptionsMenu(final Menu menu) { - getMenuInflater().inflate(R.menu.scheduler, menu); - return true; - } - - @Override - public boolean onPrepareOptionsMenu(final Menu menu) { - menu.findItem(R.id.scheduler_reset).setEnabled(getViewModel().schedulerExists() || - getViewModel().isPinPresent()); - return true; - } - - @Override - public boolean onOptionsItemSelected(final MenuItem item) { - final int itemId = item.getItemId(); - if (android.R.id.home == itemId) { - onBackPressed(); - return true; - } else if (R.id.scheduler_reset == itemId) { - showResetDialog(); - return true; - } - return super.onOptionsItemSelected(item); - } - @Override public ViewModel onCreateViewModel() { // Make Dagger instantiate @Inject fields prior to the ViewModel creation @@ -142,17 +112,6 @@ private void commitFragment() { new SchedulerFragment()).commit(); } - private void showResetDialog() { - new AlertDialog.Builder(this) - .setTitle(R.string.scheduler_toolbar_reset) - .setIconAttribute(android.R.attr.alertDialogIcon) - .setMessage(R.string.scheduler_reset_dialog_message) - .setPositiveButton(android.R.string.ok, (dialog, id) -> - getViewModel().removeScheduler()) - .setNegativeButton(android.R.string.cancel, null) - .show(); - } - @Override public void onSubscriptionsChanged() { mLogger.v("onSubscriptionsChanged()."); diff --git a/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerViewModel.java b/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerViewModel.java index 44ae23c..260247b 100644 --- a/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerViewModel.java +++ b/src/com/github/iusmac/sevensim/ui/scheduler/SchedulerViewModel.java @@ -441,43 +441,6 @@ void refreshNextUpcomingScheduleSummary() { mMutableNextUpcomingScheduleSummary.postValue(summary); } - /** - * Entirely purge the scheduler and all relative data. - */ - void removeScheduler() { - mLogger.d("removeScheduler()."); - - final List schedulesToRemove = new ArrayList<>(2); - - mMediatorSchedulerEnabledState.setValue(false); - mMutableDaysOfWeek.setValue(mDaysOfWeekFactory.create()); - - if (mMutableStartSchedule.getValue().getId() > 0L) { - final SubscriptionScheduleEntity defaultSchedule = - getDefaultSchedule(TimeType.START_TIME); - mMutableStartTime.setValue(defaultSchedule.getTime()); - schedulesToRemove.add(mMutableStartSchedule.getValue()); - mMutableStartSchedule.setValue(defaultSchedule); - } - - if (mMutableEndSchedule.getValue().getId() > 0L) { - final SubscriptionScheduleEntity defaultSchedule = - getDefaultSchedule(TimeType.END_TIME); - mMutableEndTime.setValue(defaultSchedule.getTime()); - schedulesToRemove.add(mMutableEndSchedule.getValue()); - mMutableEndSchedule.setValue(defaultSchedule); - } - - mMediatorPinEntity.getValue().ifPresent((pin) -> mHandler.post(() -> - mPinStorage.deletePin(pin))); - - if (!schedulesToRemove.isEmpty()) { - mHandler.post(() -> mSubscriptionScheduler.deleteAll(schedulesToRemove)); - } - - refreshNextUpcomingScheduleSummaryAsync(); - } - /** * Remove the SIM PIN code, if present. */ @@ -488,14 +451,6 @@ void removePin() { mPinStorage.deletePin(pin))); } - /** - * @return {@code true} if the scheduler exists, otherwise {@code false}. - */ - boolean schedulerExists() { - return mMutableStartSchedule.getValue().getId() > 0L || - mMutableEndSchedule.getValue().getId() > 0L; - } - /** * @return {@code true} if the SIM PIN code has been set, otherwise {@code false}. */ From d11aa003ab0aec89b0d6aebf98841b7293f69de0 Mon Sep 17 00:00:00 2001 From: iusmac Date: Sat, 22 Jun 2024 13:00:34 +0200 Subject: [PATCH 4/9] Bring in alarm card layout from `DeskClock` app for schedule items --- Android.bp | 3 +- SettingsLib/.gitignore | 6 +- .../build.gradle | 17 +- SettingsLib/fetch.sh | 2 +- build.gradle | 6 +- .../schedule_card_arrow_background_color.xml | 6 + ...hedule_card_collapsed_background_color.xml | 7 + ...chedule_card_expanded_background_color.xml | 6 + .../schedule_card_arrow_background_color.xml | 7 + ...hedule_card_collapsed_background_color.xml | 7 + ...edule_card_day_unselected_stroke_color.xml | 7 + ...chedule_card_expanded_background_color.xml | 6 + res/color/day_of_week_text_color.xml | 7 + res/drawable/day_of_week_toggle_circle.xml | 41 + res/drawable/ic_arrow_pointing_down.xml | 44 + res/drawable/ic_delete_small.xml | 31 + res/drawable/ic_label.xml | 26 + res/drawable/ic_no_schedules_48dp.xml | 14 + res/drawable/ic_tasks_24dp.xml | 18 + .../schedule_card_collapsed_background.xml | 24 + .../schedule_card_expanded_background.xml | 24 + .../schedule_card_ripple_background.xml | 11 + res/layout-land/scheduler_fabs.xml | 45 + res/layout/centered_guidelines.xml | 12 + res/layout/days_of_week.xml | 22 + res/layout/schedule_card_collapsed.xml | 165 ++++ res/layout/schedule_card_expanded.xml | 260 ++++++ res/layout/schedule_time_summary.xml | 42 + res/layout/scheduler_empty_view.xml | 16 + res/menu/schedule_card_action_options.xml | 15 + res/values-land-v31/dimens.xml | 4 + res/values-land/dimens.xml | 4 + res/values-night-v31/colors.xml | 4 + res/values-night/colors.xml | 6 + res/values-v31/colors.xml | 5 +- res/values-v31/dimens.xml | 1 + res/values/colors.xml | 7 + res/values/dimens.xml | 14 + res/values/strings.xml | 21 +- res/values/styles.xml | 30 + res/xml/scheduler_preferences.xml | 25 +- settings.gradle | 2 +- .../github/iusmac/sevensim/AppDatabaseDE.java | 12 +- .../github/iusmac/sevensim/DateTimeUtils.java | 14 + .../sevensim/inject/SevenSimModule.java | 2 + .../iusmac/sevensim/scheduler/DaysOfWeek.java | 113 ++- .../scheduler/SubscriptionScheduleEntity.java | 28 + .../scheduler/SubscriptionScheduler.java | 46 +- .../scheduler/SubscriptionSchedulesDao.java | 6 +- .../github/iusmac/sevensim/ui/UiUtils.java | 282 ++++++ .../ui/components/EditTextDialogFragment.java | 62 ++ .../ui/components/EllipsizeLayout.java | 119 +++ .../sevensim/ui/components/ItemAdapter.java | 608 +++++++++++++ .../sevensim/ui/components/ItemAnimator.java | 326 +++++++ .../sevensim/ui/components/TextTime.java | 183 ++++ .../components/TimePickerDialogFragment.java | 118 +++ .../ui/components/TimePickerPreference.java | 231 ----- ...ePickerPreferenceDialogFragmentCompat.java | 92 -- .../CollapsedScheduleViewHolder.java | 233 +++++ .../scheduler/ExpandedScheduleViewHolder.java | 398 +++++++++ .../ui/scheduler/ScheduleItemHolder.java | 120 +++ .../ui/scheduler/ScheduleItemViewHolder.java | 143 +++ .../ScheduleItemViewHolderClickHandler.java | 22 + .../ui/scheduler/SchedulerActivity.java | 8 + .../ui/scheduler/SchedulerFragment.java | 823 ++++++++++++++---- .../ui/scheduler/SchedulerViewModel.java | 367 +++----- 66 files changed, 4549 insertions(+), 827 deletions(-) rename SettingsLib/{MainSwitchPreference => LayoutPreference}/build.gradle (59%) create mode 100644 res/color-night-v31/schedule_card_arrow_background_color.xml create mode 100644 res/color-night-v31/schedule_card_collapsed_background_color.xml create mode 100644 res/color-night-v31/schedule_card_expanded_background_color.xml create mode 100644 res/color-v31/schedule_card_arrow_background_color.xml create mode 100644 res/color-v31/schedule_card_collapsed_background_color.xml create mode 100644 res/color-v31/schedule_card_day_unselected_stroke_color.xml create mode 100644 res/color-v31/schedule_card_expanded_background_color.xml create mode 100644 res/color/day_of_week_text_color.xml create mode 100644 res/drawable/day_of_week_toggle_circle.xml create mode 100644 res/drawable/ic_arrow_pointing_down.xml create mode 100644 res/drawable/ic_delete_small.xml create mode 100644 res/drawable/ic_label.xml create mode 100644 res/drawable/ic_no_schedules_48dp.xml create mode 100644 res/drawable/ic_tasks_24dp.xml create mode 100644 res/drawable/schedule_card_collapsed_background.xml create mode 100644 res/drawable/schedule_card_expanded_background.xml create mode 100644 res/drawable/schedule_card_ripple_background.xml create mode 100644 res/layout-land/scheduler_fabs.xml create mode 100644 res/layout/centered_guidelines.xml create mode 100644 res/layout/days_of_week.xml create mode 100644 res/layout/schedule_card_collapsed.xml create mode 100644 res/layout/schedule_card_expanded.xml create mode 100644 res/layout/schedule_time_summary.xml create mode 100644 res/layout/scheduler_empty_view.xml create mode 100644 res/menu/schedule_card_action_options.xml create mode 100644 res/values-land-v31/dimens.xml create mode 100644 res/values-land/dimens.xml create mode 100644 res/values-night/colors.xml create mode 100644 src/com/github/iusmac/sevensim/ui/components/EllipsizeLayout.java create mode 100644 src/com/github/iusmac/sevensim/ui/components/ItemAdapter.java create mode 100644 src/com/github/iusmac/sevensim/ui/components/ItemAnimator.java create mode 100644 src/com/github/iusmac/sevensim/ui/components/TextTime.java create mode 100644 src/com/github/iusmac/sevensim/ui/components/TimePickerDialogFragment.java delete mode 100644 src/com/github/iusmac/sevensim/ui/components/TimePickerPreference.java delete mode 100644 src/com/github/iusmac/sevensim/ui/components/TimePickerPreferenceDialogFragmentCompat.java create mode 100644 src/com/github/iusmac/sevensim/ui/scheduler/CollapsedScheduleViewHolder.java create mode 100644 src/com/github/iusmac/sevensim/ui/scheduler/ExpandedScheduleViewHolder.java create mode 100644 src/com/github/iusmac/sevensim/ui/scheduler/ScheduleItemHolder.java create mode 100644 src/com/github/iusmac/sevensim/ui/scheduler/ScheduleItemViewHolder.java create mode 100644 src/com/github/iusmac/sevensim/ui/scheduler/ScheduleItemViewHolderClickHandler.java diff --git a/Android.bp b/Android.bp index c5b723c..2ebf8e0 100644 --- a/Android.bp +++ b/Android.bp @@ -17,7 +17,7 @@ android_app { static_libs: [ "SettingsLibBannerMessagePreference", "SettingsLibCollapsingToolbarBaseActivity", - "SettingsLibMainSwitchPreference", + "SettingsLibLayoutPreference", "SettingsLibSettingsTheme", "SettingsLibTwoTargetPreference", "androidx.annotation_annotation", @@ -27,6 +27,7 @@ android_app { "androidx.lifecycle_lifecycle-livedata", "androidx.lifecycle_lifecycle-viewmodel", "androidx.preference_preference", + "androidx.recyclerview_recyclerview", "androidx.room_room-runtime", "hilt_android", ], diff --git a/SettingsLib/.gitignore b/SettingsLib/.gitignore index 4b66cc7..fed8e96 100644 --- a/SettingsLib/.gitignore +++ b/SettingsLib/.gitignore @@ -7,9 +7,9 @@ !/CollapsingToolbarBaseActivity/ /CollapsingToolbarBaseActivity/* !/CollapsingToolbarBaseActivity/build.gradle -!/MainSwitchPreference/ -/MainSwitchPreference/* -!/MainSwitchPreference/build.gradle +!/LayoutPreference/ +/LayoutPreference/* +!/LayoutPreference/build.gradle !/SettingsTheme/ /SettingsTheme/* !/SettingsTheme/build.gradle diff --git a/SettingsLib/MainSwitchPreference/build.gradle b/SettingsLib/LayoutPreference/build.gradle similarity index 59% rename from SettingsLib/MainSwitchPreference/build.gradle rename to SettingsLib/LayoutPreference/build.gradle index ffa5b5a..23f082f 100644 --- a/SettingsLib/MainSwitchPreference/build.gradle +++ b/SettingsLib/LayoutPreference/build.gradle @@ -2,13 +2,11 @@ plugins { id 'com.android.library' } -def SettingsLibMainSwitchPreference = '../fwb/packages/SettingsLib/MainSwitchPreference' - android { - namespace 'com.android.settingslib.widget.mainswitch' + namespace 'com.android.settingslib.widget.preference.layout' defaultConfig { - minSdk 28 + minSdk 21 targetSdk 34 versionCode 1 versionName "1.0" @@ -21,15 +19,20 @@ android { } } - lint { + lintOptions { checkReleaseBuilds false abortOnError false } + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + sourceSets { main { - res.srcDirs = ["${SettingsLibMainSwitchPreference}/res"] - java.srcDirs = ["${SettingsLibMainSwitchPreference}/src"] + res.srcDirs = ['../fwb/packages/SettingsLib/LayoutPreference/res'] + java.srcDirs = ['../fwb/packages/SettingsLib/LayoutPreference/src'] } } } diff --git a/SettingsLib/fetch.sh b/SettingsLib/fetch.sh index 2300e92..49bf12a 100755 --- a/SettingsLib/fetch.sh +++ b/SettingsLib/fetch.sh @@ -12,7 +12,7 @@ declare REPO_TAG='android-14.0.0_r31' declare -a LIBS=( 'BannerMessagePreference' 'CollapsingToolbarBaseActivity' - 'MainSwitchPreference' + 'LayoutPreference' 'SettingsTheme' 'TwoTargetPreference' 'Utils' diff --git a/build.gradle b/build.gradle index 371028e..f6716cb 100644 --- a/build.gradle +++ b/build.gradle @@ -41,6 +41,9 @@ buildscript { // https://mvnrepository.com/artifact/androidx.preference/preference // https://android.googlesource.com/platform/prebuilts/sdk/+/refs/heads/main/current/androidx/m2repository/androidx/preference/preference/ preference : 'androidx.preference:preference:1.2.1', // TODO: AOSP sources use 1.3.0-alpha01; upgrade when available in maven central + // https://mvnrepository.com/artifact/androidx.recyclerview/recyclerview + // https://android.googlesource.com/platform/prebuilts/sdk/+/refs/heads/main/current/androidx/m2repository/androidx/recyclerview/recyclerview/ + recyclerview : 'androidx.recyclerview:recyclerview:1.3.0-alpha01', room_compiler : "androidx.room:room-compiler:$room_version", room_runtime : "androidx.room:room-runtime:$room_version", // https://mvnrepository.com/artifact/androidx.lifecycle/lifecycle-viewmodel @@ -195,6 +198,7 @@ dependencies { implementation libs.livedata implementation libs.material implementation libs.preference + implementation libs.recyclerview implementation libs.viewmodel implementation libs.hilt_android kapt libs.hilt_compiler @@ -204,7 +208,7 @@ dependencies { implementation project(path: ':SettingsLib:BannerMessagePreference') implementation project(path: ':SettingsLib:CollapsingToolbarBaseActivity') - implementation project(path: ':SettingsLib:MainSwitchPreference') + implementation project(path: ':SettingsLib:LayoutPreference') implementation project(path: ':SettingsLib:SettingsTheme') implementation project(path: ':SettingsLib:TwoTargetPreference') } diff --git a/res/color-night-v31/schedule_card_arrow_background_color.xml b/res/color-night-v31/schedule_card_arrow_background_color.xml new file mode 100644 index 0000000..e1fd000 --- /dev/null +++ b/res/color-night-v31/schedule_card_arrow_background_color.xml @@ -0,0 +1,6 @@ + + + + diff --git a/res/color-night-v31/schedule_card_collapsed_background_color.xml b/res/color-night-v31/schedule_card_collapsed_background_color.xml new file mode 100644 index 0000000..0cd026f --- /dev/null +++ b/res/color-night-v31/schedule_card_collapsed_background_color.xml @@ -0,0 +1,7 @@ + + + + diff --git a/res/color-night-v31/schedule_card_expanded_background_color.xml b/res/color-night-v31/schedule_card_expanded_background_color.xml new file mode 100644 index 0000000..586ebc2 --- /dev/null +++ b/res/color-night-v31/schedule_card_expanded_background_color.xml @@ -0,0 +1,6 @@ + + + + diff --git a/res/color-v31/schedule_card_arrow_background_color.xml b/res/color-v31/schedule_card_arrow_background_color.xml new file mode 100644 index 0000000..93efda2 --- /dev/null +++ b/res/color-v31/schedule_card_arrow_background_color.xml @@ -0,0 +1,7 @@ + + + + diff --git a/res/color-v31/schedule_card_collapsed_background_color.xml b/res/color-v31/schedule_card_collapsed_background_color.xml new file mode 100644 index 0000000..4d739fb --- /dev/null +++ b/res/color-v31/schedule_card_collapsed_background_color.xml @@ -0,0 +1,7 @@ + + + + diff --git a/res/color-v31/schedule_card_day_unselected_stroke_color.xml b/res/color-v31/schedule_card_day_unselected_stroke_color.xml new file mode 100644 index 0000000..9528279 --- /dev/null +++ b/res/color-v31/schedule_card_day_unselected_stroke_color.xml @@ -0,0 +1,7 @@ + + + + diff --git a/res/color-v31/schedule_card_expanded_background_color.xml b/res/color-v31/schedule_card_expanded_background_color.xml new file mode 100644 index 0000000..042e58d --- /dev/null +++ b/res/color-v31/schedule_card_expanded_background_color.xml @@ -0,0 +1,6 @@ + + + + diff --git a/res/color/day_of_week_text_color.xml b/res/color/day_of_week_text_color.xml new file mode 100644 index 0000000..d6ef888 --- /dev/null +++ b/res/color/day_of_week_text_color.xml @@ -0,0 +1,7 @@ + + + + + + diff --git a/res/drawable/day_of_week_toggle_circle.xml b/res/drawable/day_of_week_toggle_circle.xml new file mode 100644 index 0000000..5cd0c9a --- /dev/null +++ b/res/drawable/day_of_week_toggle_circle.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/drawable/ic_arrow_pointing_down.xml b/res/drawable/ic_arrow_pointing_down.xml new file mode 100644 index 0000000..3904321 --- /dev/null +++ b/res/drawable/ic_arrow_pointing_down.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + diff --git a/res/drawable/ic_delete_small.xml b/res/drawable/ic_delete_small.xml new file mode 100644 index 0000000..8a5e593 --- /dev/null +++ b/res/drawable/ic_delete_small.xml @@ -0,0 +1,31 @@ + + + + + + + + diff --git a/res/drawable/ic_label.xml b/res/drawable/ic_label.xml new file mode 100644 index 0000000..24a86cf --- /dev/null +++ b/res/drawable/ic_label.xml @@ -0,0 +1,26 @@ + + + + + + diff --git a/res/drawable/ic_no_schedules_48dp.xml b/res/drawable/ic_no_schedules_48dp.xml new file mode 100644 index 0000000..770a042 --- /dev/null +++ b/res/drawable/ic_no_schedules_48dp.xml @@ -0,0 +1,14 @@ + + + + + diff --git a/res/drawable/ic_tasks_24dp.xml b/res/drawable/ic_tasks_24dp.xml new file mode 100644 index 0000000..93d95c2 --- /dev/null +++ b/res/drawable/ic_tasks_24dp.xml @@ -0,0 +1,18 @@ + + + + + + diff --git a/res/drawable/schedule_card_collapsed_background.xml b/res/drawable/schedule_card_collapsed_background.xml new file mode 100644 index 0000000..b57faa5 --- /dev/null +++ b/res/drawable/schedule_card_collapsed_background.xml @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/res/drawable/schedule_card_expanded_background.xml b/res/drawable/schedule_card_expanded_background.xml new file mode 100644 index 0000000..1fb6077 --- /dev/null +++ b/res/drawable/schedule_card_expanded_background.xml @@ -0,0 +1,24 @@ + + + + + + + + diff --git a/res/drawable/schedule_card_ripple_background.xml b/res/drawable/schedule_card_ripple_background.xml new file mode 100644 index 0000000..cc169c1 --- /dev/null +++ b/res/drawable/schedule_card_ripple_background.xml @@ -0,0 +1,11 @@ + + + + + + + + + + diff --git a/res/layout-land/scheduler_fabs.xml b/res/layout-land/scheduler_fabs.xml new file mode 100644 index 0000000..86ede0d --- /dev/null +++ b/res/layout-land/scheduler_fabs.xml @@ -0,0 +1,45 @@ + + + + + + + + + + diff --git a/res/layout/centered_guidelines.xml b/res/layout/centered_guidelines.xml new file mode 100644 index 0000000..e0508db --- /dev/null +++ b/res/layout/centered_guidelines.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/res/layout/days_of_week.xml b/res/layout/days_of_week.xml new file mode 100644 index 0000000..b179b6d --- /dev/null +++ b/res/layout/days_of_week.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + diff --git a/res/layout/schedule_card_collapsed.xml b/res/layout/schedule_card_collapsed.xml new file mode 100644 index 0000000..1e9a3d7 --- /dev/null +++ b/res/layout/schedule_card_collapsed.xml @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/layout/schedule_card_expanded.xml b/res/layout/schedule_card_expanded.xml new file mode 100644 index 0000000..598c6f9 --- /dev/null +++ b/res/layout/schedule_card_expanded.xml @@ -0,0 +1,260 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +