Home | History | Annotate | Download | only in notification
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.settings.notification;
     18 
     19 import android.app.AlertDialog;
     20 import android.content.ComponentName;
     21 import android.content.Context;
     22 import android.content.DialogInterface;
     23 import android.content.DialogInterface.OnDismissListener;
     24 import android.content.pm.ServiceInfo;
     25 import android.content.res.ColorStateList;
     26 import android.net.Uri;
     27 import android.service.notification.ZenModeConfig;
     28 import android.service.notification.ZenModeConfig.EventInfo;
     29 import android.service.notification.ZenModeConfig.ScheduleInfo;
     30 import android.text.Editable;
     31 import android.text.TextUtils;
     32 import android.text.TextWatcher;
     33 import android.util.ArraySet;
     34 import android.util.Log;
     35 import android.util.TypedValue;
     36 import android.view.LayoutInflater;
     37 import android.view.View;
     38 import android.widget.EditText;
     39 import android.widget.RadioButton;
     40 import android.widget.RadioGroup;
     41 
     42 import com.android.settings.R;
     43 
     44 import java.util.List;
     45 
     46 public abstract class ZenRuleNameDialog {
     47     private static final String TAG = ZenModeSettings.TAG;
     48     private static final boolean DEBUG = ZenModeSettings.DEBUG;
     49 
     50     private final AlertDialog mDialog;
     51     private final EditText mEditText;
     52     private final View mWarning;
     53     private final RadioGroup mTypes;
     54     private final ColorStateList mWarningTint;
     55     private final ColorStateList mOriginalTint;
     56     private final String mOriginalRuleName;
     57     private final ArraySet<String> mExistingNames;
     58     private final ServiceListing mServiceListing;
     59     private final RuleInfo[] mExternalRules = new RuleInfo[3];
     60     private final boolean mIsNew;
     61 
     62     public ZenRuleNameDialog(Context context, ServiceListing serviceListing, String ruleName,
     63             ArraySet<String> existingNames) {
     64         mServiceListing = serviceListing;
     65         mIsNew = ruleName == null;
     66         mOriginalRuleName = ruleName;
     67         mWarningTint = ColorStateList.valueOf(context.getColor(R.color.zen_rule_name_warning));
     68         final View v = LayoutInflater.from(context).inflate(R.layout.zen_rule_name, null, false);
     69         mEditText = (EditText) v.findViewById(R.id.rule_name);
     70         mWarning = v.findViewById(R.id.rule_name_warning);
     71         if (!mIsNew) {
     72             mEditText.setText(ruleName);
     73         }
     74         TypedValue outValue = new TypedValue();
     75         context.getTheme().resolveAttribute(android.R.attr.colorAccent, outValue, true);
     76         mOriginalTint = ColorStateList.valueOf(outValue.data);
     77         mEditText.setSelectAllOnFocus(true);
     78         mTypes = (RadioGroup) v.findViewById(R.id.rule_types);
     79         if (mServiceListing != null) {
     80             bindType(R.id.rule_type_schedule, defaultNewSchedule());
     81             bindType(R.id.rule_type_event, defaultNewEvent());
     82             bindExternalRules();
     83             mServiceListing.addCallback(mServiceListingCallback);
     84             mServiceListing.reload();
     85         } else {
     86             mTypes.setVisibility(View.GONE);
     87         }
     88         mDialog = new AlertDialog.Builder(context)
     89                 .setTitle(mIsNew ? R.string.zen_mode_add_rule : R.string.zen_mode_rule_name)
     90                 .setView(v)
     91                 .setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() {
     92                     @Override
     93                     public void onClick(DialogInterface dialog, int which) {
     94                         final String newName = trimmedText();
     95                         if (!mIsNew && mOriginalRuleName != null
     96                                 && mOriginalRuleName.equalsIgnoreCase(newName)) {
     97                             return;  // no change to an existing rule, just dismiss
     98                         }
     99                         onOk(newName, selectedRuleInfo());
    100                     }
    101                 })
    102                 .setOnDismissListener(new OnDismissListener() {
    103                     @Override
    104                     public void onDismiss(DialogInterface dialog) {
    105                         if (mServiceListing != null) {
    106                             mServiceListing.removeCallback(mServiceListingCallback);
    107                         }
    108                     }
    109                 })
    110                 .setNegativeButton(R.string.cancel, null)
    111                 .create();
    112         mEditText.addTextChangedListener(new TextWatcher() {
    113             @Override
    114             public void onTextChanged(CharSequence s, int start, int before, int count) {
    115                 // noop
    116             }
    117 
    118             @Override
    119             public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    120                 // noop
    121             }
    122 
    123             @Override
    124             public void afterTextChanged(Editable s) {
    125                 updatePositiveButtonAndWarning();
    126             }
    127         });
    128         mExistingNames = new ArraySet<String>(existingNames.size());
    129         for (String existingName : existingNames) {
    130             mExistingNames.add(existingName.toLowerCase());
    131         }
    132     }
    133 
    134     abstract public void onOk(String ruleName, RuleInfo ruleInfo);
    135 
    136     public void show() {
    137         mDialog.show();
    138         updatePositiveButtonAndWarning();
    139     }
    140 
    141     private void bindType(int id, RuleInfo ri) {
    142         final RadioButton rb = (RadioButton) mTypes.findViewById(id);
    143         if (ri == null) {
    144             rb.setVisibility(View.GONE);
    145             return;
    146         }
    147         rb.setVisibility(View.VISIBLE);
    148         if (ri.caption != null) {
    149             rb.setText(ri.caption);
    150         }
    151         rb.setTag(ri);
    152     }
    153 
    154     private RuleInfo selectedRuleInfo() {
    155         final int id = mTypes.getCheckedRadioButtonId();
    156         if (id == -1) return null;
    157         final RadioButton rb = (RadioButton) mTypes.findViewById(id);
    158         return (RuleInfo) rb.getTag();
    159     }
    160 
    161     private String trimmedText() {
    162         return mEditText.getText() == null ? null : mEditText.getText().toString().trim();
    163     }
    164 
    165     private void updatePositiveButtonAndWarning() {
    166         final String name = trimmedText();
    167         final boolean validName = !TextUtils.isEmpty(name)
    168                 && (name.equalsIgnoreCase(mOriginalRuleName)
    169                         || !mExistingNames.contains(name.toLowerCase()));
    170         mDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(validName);
    171         final boolean showWarning = !TextUtils.isEmpty(name) && !validName;
    172         mWarning.setVisibility(showWarning ? View.VISIBLE : View.INVISIBLE);
    173         mEditText.setBackgroundTintList(showWarning ? mWarningTint : mOriginalTint);
    174     }
    175 
    176     private static RuleInfo defaultNewSchedule() {
    177         final ScheduleInfo schedule = new ScheduleInfo();
    178         schedule.days = ZenModeConfig.ALL_DAYS;
    179         schedule.startHour = 22;
    180         schedule.endHour = 7;
    181         final RuleInfo rt = new RuleInfo();
    182         rt.settingsAction = ZenModeScheduleRuleSettings.ACTION;
    183         rt.defaultConditionId = ZenModeConfig.toScheduleConditionId(schedule);
    184         return rt;
    185     }
    186 
    187     private static RuleInfo defaultNewEvent() {
    188         final EventInfo event = new EventInfo();
    189         event.calendar = null; // any calendar
    190         event.reply = EventInfo.REPLY_ANY_EXCEPT_NO;
    191         final RuleInfo rt = new RuleInfo();
    192         rt.settingsAction = ZenModeEventRuleSettings.ACTION;
    193         rt.defaultConditionId = ZenModeConfig.toEventConditionId(event);
    194         return rt;
    195     }
    196 
    197     private void bindExternalRules() {
    198         bindType(R.id.rule_type_3, mExternalRules[0]);
    199         bindType(R.id.rule_type_4, mExternalRules[1]);
    200         bindType(R.id.rule_type_5, mExternalRules[2]);
    201     }
    202 
    203     private final ServiceListing.Callback mServiceListingCallback = new ServiceListing.Callback() {
    204         @Override
    205         public void onServicesReloaded(List<ServiceInfo> services) {
    206             if (DEBUG) Log.d(TAG, "Services reloaded: count=" + services.size());
    207             mExternalRules[0] = mExternalRules[1] = mExternalRules[2] = null;
    208             int i = 0;
    209             for (ServiceInfo si : services) {
    210                 final RuleInfo ri = ZenModeExternalRuleSettings.getRuleInfo(si);
    211                 if (ri != null) {
    212                     mExternalRules[i] = ri;
    213                     i++;
    214                     if (i == mExternalRules.length) {
    215                         break;
    216                     }
    217                 }
    218             }
    219             bindExternalRules();
    220         }
    221     };
    222 
    223     public static class RuleInfo {
    224         public String caption;
    225         public String settingsAction;
    226         public Uri defaultConditionId;
    227         public ComponentName serviceComponent;
    228         public ComponentName configurationActivity;
    229     }
    230 
    231 }