diff options
author | John Spurlock <jspurlock@google.com> | 2015-04-09 12:50:04 -0400 |
---|---|---|
committer | John Spurlock <jspurlock@google.com> | 2015-04-09 20:56:16 -0400 |
commit | 45fa140b8c6846b4546fdeabebf989ae9102cebb (patch) | |
tree | ddebdae6ced30e4be858c4381c7c029e132dfa4a /src/com/android/settings/notification/ZenModeScheduleRuleSettings.java | |
parent | 342d08537fe316f0d046a3a3097c294e4b30e912 (diff) | |
download | packages_apps_Settings-45fa140b8c6846b4546fdeabebf989ae9102cebb.zip packages_apps_Settings-45fa140b8c6846b4546fdeabebf989ae9102cebb.tar.gz packages_apps_Settings-45fa140b8c6846b4546fdeabebf989ae9102cebb.tar.bz2 |
Settings: An update on Downtime.
- Migrate settings to the new zen mode state model.
- Remove downtime settings.
- Add automatic rule management page (add/remove)
- Bind new automatic schedule rules to detail editor.
- Clean up a few found miscapitalized string captions.
- Migrate zen switch to report the shared summary string.
Bug: 20064962
Change-Id: Ia561e7f77c90c962729240b4d51ba1915297f64a
Diffstat (limited to 'src/com/android/settings/notification/ZenModeScheduleRuleSettings.java')
-rw-r--r-- | src/com/android/settings/notification/ZenModeScheduleRuleSettings.java | 477 |
1 files changed, 477 insertions, 0 deletions
diff --git a/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java new file mode 100644 index 0000000..7bec3c4 --- /dev/null +++ b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java @@ -0,0 +1,477 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.notification; + +import static com.android.settings.notification.ZenModeScheduleDaysSelection.DAYS; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.app.DialogFragment; +import android.app.FragmentManager; +import android.app.TimePickerDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.content.DialogInterface.OnDismissListener; +import android.content.Intent; +import android.os.Bundle; +import android.preference.Preference; +import android.preference.Preference.OnPreferenceClickListener; +import android.preference.PreferenceScreen; +import android.provider.Settings; +import android.provider.Settings.Global; +import android.service.notification.ZenModeConfig; +import android.service.notification.ZenModeConfig.ScheduleInfo; +import android.service.notification.ZenModeConfig.ZenRule; +import android.text.format.DateFormat; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.widget.Switch; +import android.widget.TimePicker; +import android.widget.Toast; + +import com.android.internal.logging.MetricsLogger; +import com.android.settings.DropDownPreference; +import com.android.settings.R; +import com.android.settings.SettingsActivity; +import com.android.settings.widget.SwitchBar; + +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Calendar; + +public class ZenModeScheduleRuleSettings extends ZenModeSettingsBase + implements SwitchBar.OnSwitchChangeListener { + private static final String TAG = ZenModeSettingsBase.TAG; + private static final boolean DEBUG = ZenModeSettingsBase.DEBUG; + + private static final String KEY_RULE_NAME = "rule_name"; + private static final String KEY_DAYS = "days"; + private static final String KEY_START_TIME = "start_time"; + private static final String KEY_END_TIME = "end_time"; + private static final String KEY_ZEN_MODE = "zen_mode"; + + private static final SimpleDateFormat DAY_FORMAT = new SimpleDateFormat("EEE"); + + public static final String ACTION = Settings.ACTION_ZEN_MODE_SCHEDULE_RULE_SETTINGS; + public static final String EXTRA_RULE_ID = "rule_id"; + + private Context mContext; + private boolean mDisableListeners; + private SwitchBar mSwitchBar; + private Preference mRuleName; + private Preference mDays; + private TimePickerPreference mStart; + private TimePickerPreference mEnd; + private DropDownPreference mZenMode; + + private String mRuleId; + private ZenRule mRule; + private ScheduleInfo mSchedule; + private boolean mDeleting; + + @Override + protected void onZenModeChanged() { + // noop + } + + @Override + protected void onZenModeConfigChanged() { + if (!refreshRuleOrFinish()) { + updateControls(); + } + } + + private boolean refreshRuleOrFinish() { + mRule = mConfig.automaticRules.get(mRuleId); + if (DEBUG) Log.d(TAG, "mRule=" + mRule); + mSchedule = mRule != null ? ZenModeConfig.tryParseScheduleConditionId(mRule.conditionId) + : null; + if (mSchedule == null) { + toastAndFinish(); + return true; + } + return false; + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + if (DEBUG) Log.d(TAG, "onCreateOptionsMenu"); + inflater.inflate(R.menu.zen_mode_rule, menu); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (DEBUG) Log.d(TAG, "onOptionsItemSelected " + item.getItemId()); + if (item.getItemId() == R.id.delete) { + showDeleteRuleDialog(); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + + mContext = getActivity(); + + final Intent intent = getActivity().getIntent(); + if (DEBUG) Log.d(TAG, "onCreate getIntent()=" + intent); + if (intent == null) { + Log.w(TAG, "No intent"); + toastAndFinish(); + return; + } + + mRuleId = intent.getStringExtra(EXTRA_RULE_ID); + if (DEBUG) Log.d(TAG, "mRuleId=" + mRuleId); + if (refreshRuleOrFinish()) { + return; + } + + addPreferencesFromResource(R.xml.zen_mode_schedule_rule_settings); + final PreferenceScreen root = getPreferenceScreen(); + + setHasOptionsMenu(true); + + mRuleName = root.findPreference(KEY_RULE_NAME); + mRuleName.setOnPreferenceClickListener(new OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + showRuleNameDialog(); + return true; + } + }); + + mDays = root.findPreference(KEY_DAYS); + mDays.setOnPreferenceClickListener(new OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + showDaysDialog(); + return true; + } + }); + + final FragmentManager mgr = getFragmentManager(); + + mStart = new TimePickerPreference(mContext, mgr); + mStart.setKey(KEY_START_TIME); + mStart.setTitle(R.string.zen_mode_start_time); + mStart.setCallback(new TimePickerPreference.Callback() { + @Override + public boolean onSetTime(final int hour, final int minute) { + if (mDisableListeners) return true; + if (!ZenModeConfig.isValidHour(hour)) return false; + if (!ZenModeConfig.isValidMinute(minute)) return false; + if (hour == mSchedule.startHour && minute == mSchedule.startMinute) { + return true; + } + if (DEBUG) Log.d(TAG, "onPrefChange start h=" + hour + " m=" + minute); + mSchedule.startHour = hour; + mSchedule.startMinute = minute; + mRule.conditionId = ZenModeConfig.toScheduleConditionId(mSchedule); + mRule.condition = null; + mRule.snoozing = false; + setZenModeConfig(mConfig); + return true; + } + }); + root.addPreference(mStart); + mStart.setDependency(mDays.getKey()); + + mEnd = new TimePickerPreference(mContext, mgr); + mEnd.setKey(KEY_END_TIME); + mEnd.setTitle(R.string.zen_mode_end_time); + mEnd.setCallback(new TimePickerPreference.Callback() { + @Override + public boolean onSetTime(final int hour, final int minute) { + if (mDisableListeners) return true; + if (!ZenModeConfig.isValidHour(hour)) return false; + if (!ZenModeConfig.isValidMinute(minute)) return false; + if (hour == mSchedule.endHour && minute == mSchedule.endMinute) { + return true; + } + if (DEBUG) Log.d(TAG, "onPrefChange end h=" + hour + " m=" + minute); + mSchedule.startHour = hour; + mSchedule.startMinute = minute; + mRule.conditionId = ZenModeConfig.toScheduleConditionId(mSchedule); + mRule.condition = null; + mRule.snoozing = false; + setZenModeConfig(mConfig); + return true; + } + }); + root.addPreference(mEnd); + mEnd.setDependency(mDays.getKey()); + + mZenMode = (DropDownPreference) root.findPreference(KEY_ZEN_MODE); + mZenMode.addItem(R.string.zen_mode_option_important_interruptions, Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS); + mZenMode.addItem(R.string.zen_mode_option_alarms, Global.ZEN_MODE_ALARMS); + mZenMode.addItem(R.string.zen_mode_option_no_interruptions, Global.ZEN_MODE_NO_INTERRUPTIONS); + mZenMode.setCallback(new DropDownPreference.Callback() { + @Override + public boolean onItemSelected(int pos, Object value) { + if (mDisableListeners) return true; + final int zenMode = (Integer) value; + if (zenMode == mRule.zenMode) return true; + if (DEBUG) Log.d(TAG, "onPrefChange zenMode=" + zenMode); + mRule.zenMode = zenMode; + setZenModeConfig(mConfig); + return true; + } + }); + mZenMode.setOrder(10); // sort at the bottom of the category + mZenMode.setDependency(mDays.getKey()); + } + + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + final SettingsActivity activity = (SettingsActivity) getActivity(); + mSwitchBar = activity.getSwitchBar(); + mSwitchBar.addOnSwitchChangeListener(this); + mSwitchBar.show(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + mSwitchBar.removeOnSwitchChangeListener(this); + mSwitchBar.hide(); + } + + @Override + public void onSwitchChanged(Switch switchView, boolean isChecked) { + if (DEBUG) Log.d(TAG, "onSwitchChanged " + isChecked); + if (mDisableListeners) return; + final boolean enabled = isChecked; + if (enabled == mRule.enabled) return; + if (DEBUG) Log.d(TAG, "onSwitchChanged enabled=" + enabled); + mRule.enabled = enabled; + mRule.snoozing = false; + setZenModeConfig(mConfig); + } + + private void updateDays() { + // Compute an ordered, delimited list of day names based on the persisted user config. + final int[] days = mSchedule.days; + if (days != null && days.length > 0) { + final StringBuilder sb = new StringBuilder(); + final Calendar c = Calendar.getInstance(); + for (int i = 0; i < DAYS.length; i++) { + final int day = DAYS[i]; + for (int j = 0; j < days.length; j++) { + if (day == days[j]) { + c.set(Calendar.DAY_OF_WEEK, day); + if (sb.length() > 0) { + sb.append(mContext.getString(R.string.summary_divider_text)); + } + sb.append(DAY_FORMAT.format(c.getTime())); + break; + } + } + } + if (sb.length() > 0) { + mDays.setSummary(sb); + mDays.notifyDependencyChange(false); + return; + } + } + mDays.setSummary(R.string.zen_mode_schedule_rule_days_none); + mDays.notifyDependencyChange(true); + } + + private void updateEndSummary() { + final int startMin = 60 * mSchedule.startHour + mSchedule.startMinute; + final int endMin = 60 * mSchedule.endHour + mSchedule.endMinute; + final boolean nextDay = startMin >= endMin; + final int summaryFormat = nextDay ? R.string.zen_mode_end_time_next_day_summary_format : 0; + mEnd.setSummaryFormat(summaryFormat); + } + + @Override + public void onResume() { + super.onResume(); + updateControls(); + } + + private void updateRuleName() { + getActivity().setTitle(mRule.name); + mRuleName.setSummary(mRule.name); + } + + private void updateControls() { + mDisableListeners = true; + updateRuleName(); + updateDays(); + mStart.setTime(mSchedule.startHour, mSchedule.startMinute); + mEnd.setTime(mSchedule.endHour, mSchedule.endMinute); + mZenMode.setSelectedValue(mRule.zenMode); + mDisableListeners = false; + updateEndSummary(); + if (mSwitchBar != null) { + mSwitchBar.setChecked(mRule.enabled); + } + } + + @Override + protected int getMetricsCategory() { + return MetricsLogger.NOTIFICATION_ZEN_MODE_SCHEDULE_RULE; + } + + private void showDeleteRuleDialog() { + new AlertDialog.Builder(mContext) + .setMessage(getString(R.string.zen_mode_delete_rule_confirmation, mRule.name)) + .setNegativeButton(R.string.cancel, null) + .setPositiveButton(R.string.zen_mode_delete_rule_button, new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + mDeleting = true; + mConfig.automaticRules.remove(mRuleId); + setZenModeConfig(mConfig); + } + }) + .show(); + } + + private void showRuleNameDialog() { + new ZenRuleNameDialog(mContext, mRule.name, mConfig.getAutomaticRuleNames()) { + @Override + public void onOk(String ruleName) { + final ZenModeConfig newConfig = mConfig.copy(); + final ZenRule rule = newConfig.automaticRules.get(mRuleId); + if (rule == null) return; + rule.name = ruleName; + setZenModeConfig(newConfig); + } + }.show(); + } + + private void showDaysDialog() { + new AlertDialog.Builder(mContext) + .setTitle(R.string.zen_mode_schedule_rule_days) + .setView(new ZenModeScheduleDaysSelection(mContext, mSchedule.days) { + @Override + protected void onChanged(final int[] days) { + if (mDisableListeners) return; + if (Arrays.equals(days, mSchedule.days)) return; + if (DEBUG) Log.d(TAG, "days.onChanged days=" + Arrays.asList(days)); + mSchedule.days = days; + mRule.conditionId = ZenModeConfig.toScheduleConditionId(mSchedule); + mRule.condition = null; + mRule.snoozing = false; + setZenModeConfig(mConfig); + } + }) + .setOnDismissListener(new OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + updateDays(); + } + }) + .setPositiveButton(R.string.done_button, null) + .show(); + } + + private void toastAndFinish() { + if (!mDeleting) { + Toast.makeText(mContext, R.string.zen_mode_rule_not_found_text, Toast.LENGTH_SHORT) + .show(); + } + getActivity().finish(); + } + + private static class TimePickerPreference extends Preference { + private final Context mContext; + + private int mSummaryFormat; + private int mHourOfDay; + private int mMinute; + private Callback mCallback; + + public TimePickerPreference(Context context, final FragmentManager mgr) { + super(context); + mContext = context; + setPersistent(false); + setOnPreferenceClickListener(new OnPreferenceClickListener(){ + @Override + public boolean onPreferenceClick(Preference preference) { + final TimePickerFragment frag = new TimePickerFragment(); + frag.pref = TimePickerPreference.this; + frag.show(mgr, TimePickerPreference.class.getName()); + return true; + } + }); + } + + public void setCallback(Callback callback) { + mCallback = callback; + } + + public void setSummaryFormat(int resId) { + mSummaryFormat = resId; + updateSummary(); + } + + public void setTime(int hourOfDay, int minute) { + if (mCallback != null && !mCallback.onSetTime(hourOfDay, minute)) return; + mHourOfDay = hourOfDay; + mMinute = minute; + updateSummary(); + } + + private void updateSummary() { + final Calendar c = Calendar.getInstance(); + c.set(Calendar.HOUR_OF_DAY, mHourOfDay); + c.set(Calendar.MINUTE, mMinute); + String time = DateFormat.getTimeFormat(mContext).format(c.getTime()); + if (mSummaryFormat != 0) { + time = mContext.getResources().getString(mSummaryFormat, time); + } + setSummary(time); + } + + public static class TimePickerFragment extends DialogFragment implements + TimePickerDialog.OnTimeSetListener { + public TimePickerPreference pref; + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final boolean usePref = pref != null && pref.mHourOfDay >= 0 && pref.mMinute >= 0; + final Calendar c = Calendar.getInstance(); + final int hour = usePref ? pref.mHourOfDay : c.get(Calendar.HOUR_OF_DAY); + final int minute = usePref ? pref.mMinute : c.get(Calendar.MINUTE); + return new TimePickerDialog(getActivity(), this, hour, minute, + DateFormat.is24HourFormat(getActivity())); + } + + public void onTimeSet(TimePicker view, int hourOfDay, int minute) { + if (pref != null) { + pref.setTime(hourOfDay, minute); + } + } + } + + public interface Callback { + boolean onSetTime(int hour, int minute); + } + } +} |