diff options
author | John Spurlock <jspurlock@google.com> | 2015-04-30 09:26:15 -0400 |
---|---|---|
committer | John Spurlock <jspurlock@google.com> | 2015-04-30 11:28:27 -0400 |
commit | f57bad7d5b0f9044231fc52351ed27e14013f491 (patch) | |
tree | c2b4e92ca1c90193672919dad665340fe29b3361 | |
parent | 0423aed775d0b00cbdf6cc1b422ede704830d43a (diff) | |
download | packages_apps_Settings-f57bad7d5b0f9044231fc52351ed27e14013f491.zip packages_apps_Settings-f57bad7d5b0f9044231fc52351ed27e14013f491.tar.gz packages_apps_Settings-f57bad7d5b0f9044231fc52351ed27e14013f491.tar.bz2 |
Settings: Do not disturb automatic rule updates.
- Remove FAB for adding rules, move to last preference.
- Add first-class event condition type and config sub-page.
- Always show radio buttons when adding rules.
- Add new data model for event rules.
- Add stub condition provider for event rules (always false for now).
- Add rule-type icons to rule preference rows.
Bug: 20064962
Change-Id: Id5acde371eb2e7d22b1f195459897614db5ba80a
-rw-r--r-- | AndroidManifest.xml | 20 | ||||
-rw-r--r-- | res/drawable/ic_add.xml | 24 | ||||
-rw-r--r-- | res/drawable/ic_event.xml | 24 | ||||
-rw-r--r-- | res/drawable/ic_label.xml | 24 | ||||
-rw-r--r-- | res/drawable/ic_schedule.xml | 29 | ||||
-rwxr-xr-x | res/layout/zen_rule_name.xml | 11 | ||||
-rw-r--r-- | res/values/strings.xml | 60 | ||||
-rw-r--r-- | res/xml/zen_mode_event_rule_settings.xml | 51 | ||||
-rw-r--r-- | src/com/android/settings/Settings.java | 1 | ||||
-rw-r--r-- | src/com/android/settings/SettingsActivity.java | 2 | ||||
-rw-r--r-- | src/com/android/settings/notification/ZenModeAutomationSettings.java | 140 | ||||
-rw-r--r-- | src/com/android/settings/notification/ZenModeEventRuleSettings.java | 180 | ||||
-rw-r--r-- | src/com/android/settings/notification/ZenModeExternalRuleSettings.java | 5 | ||||
-rw-r--r-- | src/com/android/settings/notification/ZenModeRuleSettingsBase.java | 15 | ||||
-rw-r--r-- | src/com/android/settings/notification/ZenModeScheduleRuleSettings.java | 5 | ||||
-rw-r--r-- | src/com/android/settings/notification/ZenRuleNameDialog.java | 29 |
16 files changed, 579 insertions, 41 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 0446178..5ab1422 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -759,6 +759,26 @@ android:value="true" /> </activity> + <activity android:name="Settings$ZenModeEventRuleSettingsActivity" + android:exported="true" + android:taskAffinity=""> + <intent-filter android:priority="1"> + <action android:name="android.settings.ZEN_MODE_EVENT_RULE_SETTINGS" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="com.android.settings.SHORTCUT" /> + </intent-filter> + <meta-data android:name="com.android.settings.FRAGMENT_CLASS" + android:value="com.android.settings.notification.ZenModeEventRuleSettings" /> + <meta-data android:name="com.android.settings.TOP_LEVEL_HEADER_ID" + android:resource="@id/notification_settings" /> + <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED" + android:value="true" /> + </activity> + <activity android:name="Settings$ZenModeExternalRuleSettingsActivity" android:exported="true" android:taskAffinity=""> diff --git a/res/drawable/ic_add.xml b/res/drawable/ic_add.xml new file mode 100644 index 0000000..5939c97 --- /dev/null +++ b/res/drawable/ic_add.xml @@ -0,0 +1,24 @@ +<!-- + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32.0dp" + android:height="32.0dp" + android:viewportWidth="48.0" + android:viewportHeight="48.0"> + <path + android:fillColor="?android:attr/colorControlNormal" + android:pathData="M38.0,26.0L26.0,26.0l0.0,12.0l-4.0,0.0L22.0,26.0L10.0,26.0l0.0,-4.0l12.0,0.0L22.0,10.0l4.0,0.0l0.0,12.0l12.0,0.0l0.0,4.0z"/> +</vector> diff --git a/res/drawable/ic_event.xml b/res/drawable/ic_event.xml new file mode 100644 index 0000000..2ca958f --- /dev/null +++ b/res/drawable/ic_event.xml @@ -0,0 +1,24 @@ +<!-- + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32.0dp" + android:height="32.0dp" + android:viewportWidth="48.0" + android:viewportHeight="48.0"> + <path + android:fillColor="?android:attr/colorControlNormal" + android:pathData="M34.0,24.0L24.0,24.0l0.0,10.0l10.0,0.0L34.0,24.0zM32.0,2.0l0.0,4.0L16.0,6.0L16.0,2.0l-4.0,0.0l0.0,4.0l-2.0,0.0c-2.21,0.0 -3.98,1.79 -3.98,4.0L6.0,38.0c0.0,2.21 1.79,4.0 4.0,4.0l28.0,0.0c2.21,0.0 4.0,-1.79 4.0,-4.0L42.0,10.0c0.0,-2.21 -1.79,-4.0 -4.0,-4.0l-2.0,0.0L36.0,2.0l-4.0,0.0zm6.0,36.0L10.0,38.0L10.0,16.0l28.0,0.0l0.0,22.0z"/> +</vector> diff --git a/res/drawable/ic_label.xml b/res/drawable/ic_label.xml new file mode 100644 index 0000000..b1ed068 --- /dev/null +++ b/res/drawable/ic_label.xml @@ -0,0 +1,24 @@ +<!-- + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32.0dp" + android:height="32.0dp" + android:viewportWidth="48.0" + android:viewportHeight="48.0"> + <path + android:fillColor="?android:attr/colorControlNormal" + android:pathData="M35.27,11.69C34.54,10.67 33.35,10.0 32.0,10.0l-22.0,0.02c-2.21,0.0 -4.0,1.77 -4.0,3.98l0.0,20.0c0.0,2.21 1.79,3.98 4.0,3.98L32.0,38.0c1.35,0.0 2.54,-0.67 3.27,-1.69L44.0,24.0l-8.73,-12.31z"/> +</vector> diff --git a/res/drawable/ic_schedule.xml b/res/drawable/ic_schedule.xml new file mode 100644 index 0000000..c77c50e --- /dev/null +++ b/res/drawable/ic_schedule.xml @@ -0,0 +1,29 @@ +<!-- + 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32.0dp" + android:height="32.0dp" + android:viewportWidth="48.0" + android:viewportHeight="48.0"> + <path + android:fillColor="?android:attr/colorControlNormal" + android:pathData="M23.99,4.0C12.94,4.0 4.0,12.95 4.0,24.0s8.94,20.0 19.99,20.0C35.04,44.0 44.0,35.05 44.0,24.0S35.04,4.0 23.99,4.0zM24.0,40.0c-8.84,0.0 -16.0,-7.16 -16.0,-16.0S15.16,8.0 24.0,8.0s16.0,7.16 16.0,16.0 -7.16,16.0 -16.0,16.0z" + android:fillAlpha=".9"/> + <path + android:fillColor="?android:attr/colorControlNormal" + android:pathData="M25.0,14.0l-3.0,0.0l0.0,12.0l10.49,6.3L34.0,29.84l-9.0,-5.34z" + android:fillAlpha=".9"/> +</vector> diff --git a/res/layout/zen_rule_name.xml b/res/layout/zen_rule_name.xml index a192c83..b7b0415 100755 --- a/res/layout/zen_rule_name.xml +++ b/res/layout/zen_rule_name.xml @@ -23,6 +23,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" + android:hint="@string/zen_mode_rule_name_hint" android:layout_marginLeft="22dp" android:layout_marginRight="22dp" > @@ -32,7 +33,6 @@ <RadioGroup android:id="@+id/rule_types" - android:visibility="gone" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="22dp" @@ -46,9 +46,10 @@ android:layout_height="wrap_content" android:text="@string/zen_schedule_rule_type_name" /> - <RadioButton android:id="@+id/rule_type_2" + <RadioButton android:id="@+id/rule_type_event" android:layout_width="match_parent" - android:layout_height="wrap_content" /> + android:layout_height="wrap_content" + android:text="@string/zen_event_rule_type_name" /> <RadioButton android:id="@+id/rule_type_3" android:layout_width="match_parent" @@ -58,6 +59,10 @@ android:layout_width="match_parent" android:layout_height="wrap_content" /> + <RadioButton android:id="@+id/rule_type_5" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + </RadioGroup> </LinearLayout> diff --git a/res/values/strings.xml b/res/values/strings.xml index f7d5900..406fc7d 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -6059,8 +6059,11 @@ <!-- [CHAR LIMIT=40] Zen mode settings: Rule name option and edit dialog title --> <string name="zen_mode_rule_name">Rule name</string> + <!-- [CHAR LIMIT=40] Zen mode settings: Rule name hint text --> + <string name="zen_mode_rule_name_hint">Enter rule name</string> + <!-- [CHAR LIMIT=40] Zen mode settings: Add rule menu option name --> - <string name="zen_mode_time_add_rule">Add rule</string> + <string name="zen_mode_add_rule">Add rule</string> <!-- [CHAR LIMIT=40] Zen mode settings: Delete rule menu option name --> <string name="zen_mode_delete_rule">Delete rule</string> @@ -6081,7 +6084,58 @@ <string name="zen_mode_configure_rule">Configure rule</string> <!-- [CHAR LIMIT=40] Zen mode settings: Schedule rule type name --> - <string name="zen_schedule_rule_type_name">Schedule rule</string> + <string name="zen_schedule_rule_type_name">Time rule</string> + + <!-- [CHAR LIMIT=NONE] Zen mode settings: Schedule rule toast hint when enabled --> + <string name="zen_schedule_rule_enabled_toast">Automatic rule set to turn on Do Not Disturb during specified times</string> + + <!-- [CHAR LIMIT=40] Zen mode settings: Event rule type name --> + <string name="zen_event_rule_type_name">Event rule</string> + + <!-- [CHAR LIMIT=NONE] Zen mode settings: Event rule toast hint when enabled --> + <string name="zen_event_rule_enabled_toast">Automatic rule set to turn on Do Not Disturb during specified events</string> + + <!-- [CHAR LIMIT=40] Zen mode settings: Event-based rule calendar option title --> + <string name="zen_mode_event_rule_calendar">Calendar</string> + + <!-- [CHAR LIMIT=40] Zen mode settings: Event-based rule summary fragment: any calendar --> + <string name="zen_mode_event_rule_summary_any_calendar">Any calendar</string> + + <!-- [CHAR LIMIT=40] Zen mode settings: Event-based rule summary fragment: any reply --> + <string name="zen_mode_event_rule_summary_any_reply">Any reply</string> + + <!-- [CHAR LIMIT=40] Zen mode settings: Event-based rule summary fragment: any reply except no --> + <string name="zen_mode_event_rule_summary_any_reply_except_no">Any reply except no</string> + + <!-- [CHAR LIMIT=40] Zen mode settings: Event-based rule summary fragment: replied yes --> + <string name="zen_mode_event_rule_summary_replied_yes">Replied yes</string> + + <!-- [CHAR LIMIT=40] Zen mode settings: Event-based rule calendar option value for any calendar--> + <string name="zen_mode_event_rule_calendar_any">Any</string> + + <!-- [CHAR LIMIT=40] Zen mode settings: Event-based rule attendance option title --> + <string name="zen_mode_event_rule_attendance">Attendance</string> + + <!-- [CHAR LIMIT=40] Zen mode settings: Event-based rule attendance option value: required or optional --> + <string name="zen_mode_event_rule_attendance_required_optional">Required or optional</string> + + <!-- [CHAR LIMIT=40] Zen mode settings: Event-based rule attendance option value: required --> + <string name="zen_mode_event_rule_attendance_required">Required</string> + + <!-- [CHAR LIMIT=40] Zen mode settings: Event-based rule attendance option value: optional --> + <string name="zen_mode_event_rule_attendance_optional">Optional</string> + + <!-- [CHAR LIMIT=40] Zen mode settings: Event-based rule reply option title --> + <string name="zen_mode_event_rule_reply">Reply</string> + + <!-- [CHAR LIMIT=40] Zen mode settings: Event-based rule reply option value: Any --> + <string name="zen_mode_event_rule_reply_any">Any</string> + + <!-- [CHAR LIMIT=40] Zen mode settings: Event-based rule reply option value: Any except no--> + <string name="zen_mode_event_rule_reply_any_except_no">Any except no</string> + + <!-- [CHAR LIMIT=40] Zen mode settings: Event-based rule reply option value: Yes --> + <string name="zen_mode_event_rule_reply_yes">Yes</string> <!-- [CHAR LIMIT=40] Zen mode settings: Text to display if rule isn't found --> <string name="zen_mode_rule_not_found_text">Rule not found.</string> @@ -6089,7 +6143,7 @@ <!-- [CHAR LIMIT=40] Zen mode settings: Rule summary template (when enabled) --> <string name="zen_mode_rule_summary_combination"><xliff:g id="description" example="Sun - Thu">%1$s</xliff:g> / <xliff:g id="mode" example="Alarms only">%2$s</xliff:g></string> - <!-- [CHAR LIMIT=40] Zen mode settings: Timebased rule days option title --> + <!-- [CHAR LIMIT=40] Zen mode settings: Time-based rule days option title --> <string name="zen_mode_schedule_rule_days">Days</string> <!-- [CHAR LIMIT=40] Zen mode settings: Downtime days option value, no days set --> diff --git a/res/xml/zen_mode_event_rule_settings.xml b/res/xml/zen_mode_event_rule_settings.xml new file mode 100644 index 0000000..acad96c --- /dev/null +++ b/res/xml/zen_mode_event_rule_settings.xml @@ -0,0 +1,51 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> + +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" + android:key="zen_mode_event_rule_settings" > + + <!-- Rule name --> + <Preference + android:key="rule_name" + android:title="@string/zen_mode_rule_name" + android:persistent="false" /> + + <!-- Calendar --> + <com.android.settings.DropDownPreference + android:key="calendar" + android:title="@string/zen_mode_event_rule_calendar" + android:persistent="false" /> + + <!-- Attendance --> + <com.android.settings.DropDownPreference + android:key="attendance" + android:title="@string/zen_mode_event_rule_attendance" + android:persistent="false" /> + + <!-- Reply --> + <com.android.settings.DropDownPreference + android:key="reply" + android:title="@string/zen_mode_event_rule_reply" + android:persistent="false" /> + + <!-- Zen mode --> + <com.android.settings.DropDownPreference + android:key="zen_mode" + android:title="@string/zen_mode_settings_title" + android:persistent="false" /> + +</PreferenceScreen> diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index 88c8316..8a85015 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -99,6 +99,7 @@ public class Settings extends SettingsActivity { public static class ZenModePrioritySettingsActivity extends SettingsActivity { /* empty */ } public static class ZenModeAutomationSettingsActivity extends SettingsActivity { /* empty */ } public static class ZenModeScheduleRuleSettingsActivity extends SettingsActivity { /* empty */ } + public static class ZenModeEventRuleSettingsActivity extends SettingsActivity { /* empty */ } public static class ZenModeExternalRuleSettingsActivity extends SettingsActivity { /* empty */ } public static class NotificationSettingsActivity extends SettingsActivity { /* empty */ } public static class NotificationAppListActivity extends SettingsActivity { /* empty */ } diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index 5e1acb1..271261b 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -101,6 +101,7 @@ import com.android.settings.notification.NotificationAccessSettings; import com.android.settings.notification.NotificationSettings; import com.android.settings.notification.NotificationStation; import com.android.settings.notification.OtherSoundSettings; +import com.android.settings.notification.ZenModeEventRuleSettings; import com.android.settings.notification.ZenModeExternalRuleSettings; import com.android.settings.notification.ZenModePrioritySettings; import com.android.settings.notification.ZenModeSettings; @@ -341,6 +342,7 @@ public class SettingsActivity extends Activity WifiCallingSettings.class.getName(), ZenModePrioritySettings.class.getName(), ZenModeScheduleRuleSettings.class.getName(), + ZenModeEventRuleSettings.class.getName(), ZenModeExternalRuleSettings.class.getName(), ProcessStatsUi.class.getName(), }; diff --git a/src/com/android/settings/notification/ZenModeAutomationSettings.java b/src/com/android/settings/notification/ZenModeAutomationSettings.java index dab0a0d..e33e32f 100644 --- a/src/com/android/settings/notification/ZenModeAutomationSettings.java +++ b/src/com/android/settings/notification/ZenModeAutomationSettings.java @@ -29,21 +29,22 @@ import android.provider.Settings; import android.provider.Settings.Global; import android.service.notification.ConditionProviderService; import android.service.notification.ZenModeConfig; +import android.service.notification.ZenModeConfig.EventInfo; import android.service.notification.ZenModeConfig.ScheduleInfo; import android.service.notification.ZenModeConfig.ZenRule; import android.text.format.DateFormat; import android.util.Log; -import android.view.View; -import android.view.View.OnClickListener; import com.android.internal.logging.MetricsLogger; import com.android.settings.R; import com.android.settings.notification.ManagedServiceSettings.Config; +import com.android.settings.notification.ZenModeEventRuleSettings.CalendarInfo; import com.android.settings.notification.ZenRuleNameDialog.RuleInfo; -import com.android.settings.widget.FloatingActionButton; import java.text.SimpleDateFormat; +import java.util.Arrays; import java.util.Calendar; +import java.util.Comparator; import java.util.List; import java.util.TreeSet; @@ -68,21 +69,6 @@ public class ZenModeAutomationSettings extends ZenModeSettingsBase { } @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - final FloatingActionButton fab = getFloatingActionButton(); - fab.setVisibility(View.VISIBLE); - fab.setImageResource(R.drawable.ic_menu_add_white); - fab.setContentDescription(getString(R.string.zen_mode_time_add_rule)); - fab.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - showAddRuleDialog(); - } - }); - } - - @Override public void onDestroy() { super.onDestroy(); mServiceListing.setListening(false); @@ -133,15 +119,32 @@ public class ZenModeAutomationSettings extends ZenModeSettingsBase { .putExtra(ZenModeRuleSettingsBase.EXTRA_RULE_ID, ruleId)); } + private ZenRuleInfo[] sortedRules() { + final ZenRuleInfo[] rt = new ZenRuleInfo[mConfig.automaticRules.size()]; + for (int i = 0; i < rt.length; i++) { + final ZenRuleInfo zri = new ZenRuleInfo(); + zri.id = mConfig.automaticRules.keyAt(i); + zri.rule = mConfig.automaticRules.valueAt(i); + rt[i] = zri; + } + Arrays.sort(rt, RULE_COMPARATOR); + return rt; + } + private void updateControls() { final PreferenceScreen root = getPreferenceScreen(); root.removeAll(); if (mConfig == null) return; - for (int i = 0; i < mConfig.automaticRules.size(); i++) { - final String id = mConfig.automaticRules.keyAt(i); - final ZenRule rule = mConfig.automaticRules.valueAt(i); + final ZenRuleInfo[] sortedRules = sortedRules(); + for (int i = 0; i < sortedRules.length; i++) { + final String id = sortedRules[i].id; + final ZenRule rule = sortedRules[i].rule; final boolean isSchedule = ZenModeConfig.isValidScheduleConditionId(rule.conditionId); + final boolean isEvent = ZenModeConfig.isValidEventConditionId(rule.conditionId); final Preference p = new Preference(mContext); + p.setIcon(isSchedule ? R.drawable.ic_schedule + : isEvent ? R.drawable.ic_event + : R.drawable.ic_label); p.setTitle(rule.name); p.setSummary(computeRuleSummary(rule)); p.setPersistent(false); @@ -149,6 +152,7 @@ public class ZenModeAutomationSettings extends ZenModeSettingsBase { @Override public boolean onPreferenceClick(Preference preference) { final String action = isSchedule ? ZenModeScheduleRuleSettings.ACTION + : isEvent ? ZenModeEventRuleSettings.ACTION : ZenModeExternalRuleSettings.ACTION; showRule(action, null, id, rule.name); return true; @@ -156,6 +160,18 @@ public class ZenModeAutomationSettings extends ZenModeSettingsBase { }); root.addPreference(p); } + final Preference p = new Preference(mContext); + p.setIcon(R.drawable.ic_add); + p.setTitle(R.string.zen_mode_add_rule); + p.setPersistent(false); + p.setOnPreferenceClickListener(new OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + showAddRuleDialog(); + return true; + } + }); + root.addPreference(p); } @Override @@ -165,19 +181,69 @@ public class ZenModeAutomationSettings extends ZenModeSettingsBase { private String computeRuleSummary(ZenRule rule) { if (rule == null || !rule.enabled) return getString(R.string.switch_off_text); - final ScheduleInfo schedule = ZenModeConfig.tryParseScheduleConditionId(rule.conditionId); final String mode = ZenModeSettings.computeZenModeCaption(getResources(), rule.zenMode); String summary = getString(R.string.switch_on_text); + final ScheduleInfo schedule = ZenModeConfig.tryParseScheduleConditionId(rule.conditionId); + final EventInfo event = ZenModeConfig.tryParseEventConditionId(rule.conditionId); if (schedule != null) { - final String days = computeContiguousDayRanges(schedule.days); - final String start = getTime(schedule.startHour, schedule.startMinute); - final String end = getTime(schedule.endHour, schedule.endMinute); - final String time = getString(R.string.summary_range_verbal_combination, start, end); - summary = getString(R.string.zen_mode_rule_summary_combination, days, time); + summary = computeScheduleRuleSummary(schedule); + } else if (event != null) { + summary = computeEventRuleSummary(event); } return getString(R.string.zen_mode_rule_summary_combination, summary, mode); } + private String computeScheduleRuleSummary(ScheduleInfo schedule) { + final String days = computeContiguousDayRanges(schedule.days); + final String start = getTime(schedule.startHour, schedule.startMinute); + final String end = getTime(schedule.endHour, schedule.endMinute); + final String time = getString(R.string.summary_range_verbal_combination, start, end); + return getString(R.string.zen_mode_rule_summary_combination, days, time); + } + + private String computeEventRuleSummary(EventInfo event) { + final String calendar = computeCalendarName(event); + final String attendance = getString(computeAttendance(event)); + final String reply = getString(computeReply(event)); + return getString(R.string.zen_mode_rule_summary_combination, + getString(R.string.zen_mode_rule_summary_combination, calendar, attendance), reply); + } + + private String computeCalendarName(EventInfo event) { + if (event.calendar != 0) { + final CalendarInfo[] calendars = ZenModeEventRuleSettings.getCalendars(mContext); + for (int i = 0; i < calendars.length; i++) { + final CalendarInfo calendar = calendars[i]; + if (calendar.id == event.calendar) { + return calendar.name; + } + } + } + return getString(R.string.zen_mode_event_rule_summary_any_calendar); + } + + private int computeAttendance(EventInfo event) { + switch (event.attendance) { + case EventInfo.ATTENDANCE_REQUIRED: + return R.string.zen_mode_event_rule_attendance_required; + case EventInfo.ATTENDANCE_OPTIONAL: + return R.string.zen_mode_event_rule_attendance_optional; + default: + return R.string.zen_mode_event_rule_attendance_required_optional; + } + } + + private int computeReply(EventInfo event) { + switch (event.reply) { + case EventInfo.REPLY_ANY_EXCEPT_NO: + return R.string.zen_mode_event_rule_summary_any_reply_except_no; + case EventInfo.REPLY_YES: + return R.string.zen_mode_event_rule_summary_replied_yes; + default: + return R.string.zen_mode_event_rule_summary_any_reply; + } + } + private String getTime(int hour, int minute) { mCalendar.set(Calendar.HOUR_OF_DAY, hour); mCalendar.set(Calendar.MINUTE, minute); @@ -248,4 +314,24 @@ public class ZenModeAutomationSettings extends ZenModeSettingsBase { } }; + private static final Comparator<ZenRuleInfo> RULE_COMPARATOR = new Comparator<ZenRuleInfo>() { + @Override + public int compare(ZenRuleInfo lhs, ZenRuleInfo rhs) { + return key(lhs).compareTo(key(rhs)); + } + + private String key(ZenRuleInfo zri) { + final ZenRule rule = zri.rule; + final int type = ZenModeConfig.isValidScheduleConditionId(rule.conditionId) ? 1 + : ZenModeConfig.isValidEventConditionId(rule.conditionId) ? 2 + : 3; + return type + rule.name; + } + }; + + private static class ZenRuleInfo { + String id; + ZenRule rule; + } + } diff --git a/src/com/android/settings/notification/ZenModeEventRuleSettings.java b/src/com/android/settings/notification/ZenModeEventRuleSettings.java new file mode 100644 index 0000000..38581b6 --- /dev/null +++ b/src/com/android/settings/notification/ZenModeEventRuleSettings.java @@ -0,0 +1,180 @@ +/* + * 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 android.content.Context; +import android.database.Cursor; +import android.preference.PreferenceScreen; +import android.provider.CalendarContract.Calendars; +import android.provider.Settings; +import android.service.notification.ZenModeConfig; +import android.service.notification.ZenModeConfig.EventInfo; +import android.service.notification.ZenModeConfig.ZenRule; + +import com.android.internal.logging.MetricsLogger; +import com.android.settings.DropDownPreference; +import com.android.settings.R; + +public class ZenModeEventRuleSettings extends ZenModeRuleSettingsBase { + private static final String KEY_CALENDAR = "calendar"; + private static final String KEY_ATTENDANCE = "attendance"; + private static final String KEY_REPLY = "reply"; + + public static final String ACTION = Settings.ACTION_ZEN_MODE_EVENT_RULE_SETTINGS; + + private DropDownPreference mCalendar; + private DropDownPreference mAttendance; + private DropDownPreference mReply; + + private EventInfo mEvent; + private CalendarInfo[] mCalendars; + + @Override + protected boolean setRule(ZenRule rule) { + mEvent = rule != null ? ZenModeConfig.tryParseEventConditionId(rule.conditionId) + : null; + return mEvent != null; + } + + @Override + protected String getZenModeDependency() { + return null; + } + + @Override + protected int getEnabledToastText() { + return R.string.zen_event_rule_enabled_toast; + } + + @Override + public void onResume() { + super.onResume(); + reloadCalendar(); + } + + private void reloadCalendar() { + mCalendars = getCalendars(mContext); + mCalendar.clearItems(); + mCalendar.addItem(R.string.zen_mode_event_rule_calendar_any, 0L); + for (int i = 0; i < mCalendars.length; i++) { + mCalendar.addItem(mCalendars[i].name, mCalendars[i].id); + } + } + + @Override + protected void onCreateInternal() { + addPreferencesFromResource(R.xml.zen_mode_event_rule_settings); + final PreferenceScreen root = getPreferenceScreen(); + + mCalendar = (DropDownPreference) root.findPreference(KEY_CALENDAR); + mCalendar.setCallback(new DropDownPreference.Callback() { + @Override + public boolean onItemSelected(int pos, Object value) { + final long calendar = (Long) value; + if (calendar == mEvent.calendar) return true; + mEvent.calendar = calendar; + updateRule(ZenModeConfig.toEventConditionId(mEvent)); + return true; + } + }); + + mAttendance = (DropDownPreference) root.findPreference(KEY_ATTENDANCE); + mAttendance.addItem(R.string.zen_mode_event_rule_attendance_required_optional, + EventInfo.ATTENDANCE_REQUIRED_OR_OPTIONAL); + mAttendance.addItem(R.string.zen_mode_event_rule_attendance_required, + EventInfo.ATTENDANCE_REQUIRED); + mAttendance.addItem(R.string.zen_mode_event_rule_attendance_optional, + EventInfo.ATTENDANCE_OPTIONAL); + mAttendance.setCallback(new DropDownPreference.Callback() { + @Override + public boolean onItemSelected(int pos, Object value) { + final int attendance = (Integer) value; + if (attendance == mEvent.attendance) return true; + mEvent.attendance = attendance; + updateRule(ZenModeConfig.toEventConditionId(mEvent)); + return true; + } + }); + + mReply = (DropDownPreference) root.findPreference(KEY_REPLY); + mReply.addItem(R.string.zen_mode_event_rule_reply_any, + EventInfo.REPLY_ANY); + mReply.addItem(R.string.zen_mode_event_rule_reply_any_except_no, + EventInfo.REPLY_ANY_EXCEPT_NO); + mReply.addItem(R.string.zen_mode_event_rule_reply_yes, + EventInfo.REPLY_YES); + mReply.setCallback(new DropDownPreference.Callback() { + @Override + public boolean onItemSelected(int pos, Object value) { + final int reply = (Integer) value; + if (reply == mEvent.reply) return true; + mEvent.reply = reply; + updateRule(ZenModeConfig.toEventConditionId(mEvent)); + return true; + } + }); + + reloadCalendar(); + updateControlsInternal(); + } + + @Override + protected void updateControlsInternal() { + mCalendar.setSelectedValue(mEvent.calendar); + mAttendance.setSelectedValue(mEvent.attendance); + mReply.setSelectedValue(mEvent.reply); + } + + @Override + protected int getMetricsCategory() { + return MetricsLogger.NOTIFICATION_ZEN_MODE_EVENT_RULE; + } + + public static CalendarInfo[] getCalendars(Context context) { + final String primary = "\"primary\""; + final String[] projection = { Calendars._ID, Calendars.CALENDAR_DISPLAY_NAME, + "(" + Calendars.ACCOUNT_NAME + "=" + Calendars.OWNER_ACCOUNT + ") AS " + primary }; + final String selection = primary + " = 1"; + Cursor cursor = null; + try { + cursor = context.getContentResolver().query(Calendars.CONTENT_URI, projection, + selection, null, null); + if (cursor == null) { + return new CalendarInfo[0]; + } + final CalendarInfo[] rt = new CalendarInfo[cursor.getCount()]; + int i = 0; + while (cursor.moveToNext()) { + final CalendarInfo ci = new CalendarInfo(); + ci.id = cursor.getLong(0); + ci.name = cursor.getString(1); + rt[i++] = ci; + } + return rt; + } finally { + if (cursor != null) { + cursor.close(); + } + } + } + + public static class CalendarInfo { + public long id; + public String name; + } + +} diff --git a/src/com/android/settings/notification/ZenModeExternalRuleSettings.java b/src/com/android/settings/notification/ZenModeExternalRuleSettings.java index 9f9dc8a..8a24e02 100644 --- a/src/com/android/settings/notification/ZenModeExternalRuleSettings.java +++ b/src/com/android/settings/notification/ZenModeExternalRuleSettings.java @@ -58,6 +58,11 @@ public class ZenModeExternalRuleSettings extends ZenModeRuleSettingsBase { } @Override + protected int getEnabledToastText() { + return 0; + } + + @Override protected void onCreateInternal() { addPreferencesFromResource(R.xml.zen_mode_external_rule_settings); final PreferenceScreen root = getPreferenceScreen(); diff --git a/src/com/android/settings/notification/ZenModeRuleSettingsBase.java b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java index f6bc75f..cf66da8 100644 --- a/src/com/android/settings/notification/ZenModeRuleSettingsBase.java +++ b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java @@ -59,11 +59,13 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase private Preference mRuleName; private SwitchBar mSwitchBar; private DropDownPreference mZenMode; + private Toast mEnabledToast; abstract protected void onCreateInternal(); abstract protected boolean setRule(ZenRule rule); abstract protected String getZenModeDependency(); abstract protected void updateControlsInternal(); + abstract protected int getEnabledToastText(); @Override public void onCreate(Bundle icicle) { @@ -154,6 +156,17 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase mRule.enabled = enabled; mRule.snoozing = false; setZenModeConfig(mConfig); + if (enabled) { + final int toastText = getEnabledToastText(); + if (toastText != 0) { + mEnabledToast = Toast.makeText(mContext, toastText, Toast.LENGTH_SHORT); + mEnabledToast.show(); + } + } else { + if (mEnabledToast != null) { + mEnabledToast.cancel(); + } + } } protected void updateRule(Uri newConditionId) { @@ -247,10 +260,10 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase updateRuleName(); updateControlsInternal(); mZenMode.setSelectedValue(mRule.zenMode); - mDisableListeners = false; if (mSwitchBar != null) { mSwitchBar.setChecked(mRule.enabled); } + mDisableListeners = false; } } diff --git a/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java index fef3175..b6b87b5 100644 --- a/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java +++ b/src/com/android/settings/notification/ZenModeScheduleRuleSettings.java @@ -74,6 +74,11 @@ public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase { } @Override + protected int getEnabledToastText() { + return R.string.zen_schedule_rule_enabled_toast; + } + + @Override protected void onCreateInternal() { addPreferencesFromResource(R.xml.zen_mode_schedule_rule_settings); final PreferenceScreen root = getPreferenceScreen(); diff --git a/src/com/android/settings/notification/ZenRuleNameDialog.java b/src/com/android/settings/notification/ZenRuleNameDialog.java index 8b44e46..cd5c766 100644 --- a/src/com/android/settings/notification/ZenRuleNameDialog.java +++ b/src/com/android/settings/notification/ZenRuleNameDialog.java @@ -24,6 +24,7 @@ import android.content.DialogInterface.OnDismissListener; import android.content.pm.ServiceInfo; import android.net.Uri; import android.service.notification.ZenModeConfig; +import android.service.notification.ZenModeConfig.EventInfo; import android.service.notification.ZenModeConfig.ScheduleInfo; import android.text.Editable; import android.text.TextUtils; @@ -50,25 +51,30 @@ public abstract class ZenRuleNameDialog { private final ArraySet<String> mExistingNames; private final ServiceListing mServiceListing; private final RuleInfo[] mExternalRules = new RuleInfo[3]; + private final boolean mIsNew; public ZenRuleNameDialog(Context context, ServiceListing serviceListing, String ruleName, ArraySet<String> existingNames) { mServiceListing = serviceListing; + mIsNew = ruleName == null; final View v = LayoutInflater.from(context).inflate(R.layout.zen_rule_name, null, false); mEditText = (EditText) v.findViewById(R.id.rule_name); - if (ruleName != null) { + if (!mIsNew) { mEditText.setText(ruleName); } mEditText.setSelectAllOnFocus(true); mTypes = (RadioGroup) v.findViewById(R.id.rule_types); if (mServiceListing != null) { bindType(R.id.rule_type_schedule, defaultNewSchedule()); + bindType(R.id.rule_type_event, defaultNewEvent()); bindExternalRules(); mServiceListing.addCallback(mServiceListingCallback); mServiceListing.reload(); + } else { + mTypes.setVisibility(View.GONE); } mDialog = new AlertDialog.Builder(context) - .setTitle(R.string.zen_mode_rule_name) + .setTitle(mIsNew ? R.string.zen_mode_add_rule : R.string.zen_mode_rule_name) .setView(v) .setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() { @Override @@ -157,12 +163,21 @@ public abstract class ZenRuleNameDialog { return rt; } + private static RuleInfo defaultNewEvent() { + final EventInfo event = new EventInfo(); + event.calendar = 0; // any + event.attendance = EventInfo.ATTENDANCE_REQUIRED_OR_OPTIONAL; + event.reply = EventInfo.REPLY_ANY_EXCEPT_NO; + final RuleInfo rt = new RuleInfo(); + rt.settingsAction = ZenModeEventRuleSettings.ACTION; + rt.defaultConditionId = ZenModeConfig.toEventConditionId(event); + return rt; + } + private void bindExternalRules() { - bindType(R.id.rule_type_2, mExternalRules[0]); - bindType(R.id.rule_type_3, mExternalRules[1]); - bindType(R.id.rule_type_4, mExternalRules[2]); - // show radio group if we have at least one external rule type - mTypes.setVisibility(mExternalRules[0] != null ? View.VISIBLE : View.GONE); + bindType(R.id.rule_type_3, mExternalRules[0]); + bindType(R.id.rule_type_4, mExternalRules[1]); + bindType(R.id.rule_type_5, mExternalRules[2]); } private final ServiceListing.Callback mServiceListingCallback = new ServiceListing.Callback() { |