Home | History | Annotate | Download | only in latin
      1 /*
      2  * Copyright (C) 2009 Google Inc.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
      5  * use this file except in compliance with the License. You may obtain a copy of
      6  * 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, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations under
     14  * the License.
     15  */
     16 
     17 package com.android.inputmethod.latin;
     18 
     19 import com.android.inputmethod.voice.SettingsUtil;
     20 
     21 import android.content.ContentResolver;
     22 import android.content.Context;
     23 import android.content.SharedPreferences;
     24 import android.preference.PreferenceManager;
     25 import android.view.inputmethod.InputConnection;
     26 
     27 import java.util.Calendar;
     28 import java.util.HashMap;
     29 import java.util.Map;
     30 
     31 /**
     32  * Logic to determine when to display hints on usage to the user.
     33  */
     34 public class Hints {
     35     public interface Display {
     36         public void showHint(int viewResource);
     37     }
     38 
     39     private static final String PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN =
     40             "voice_hint_num_unique_days_shown";
     41     private static final String PREF_VOICE_HINT_LAST_TIME_SHOWN =
     42             "voice_hint_last_time_shown";
     43     private static final String PREF_VOICE_INPUT_LAST_TIME_USED =
     44             "voice_input_last_time_used";
     45     private static final String PREF_VOICE_PUNCTUATION_HINT_VIEW_COUNT =
     46             "voice_punctuation_hint_view_count";
     47     private static final int DEFAULT_SWIPE_HINT_MAX_DAYS_TO_SHOW = 7;
     48     private static final int DEFAULT_PUNCTUATION_HINT_MAX_DISPLAYS = 7;
     49 
     50     private Context mContext;
     51     private Display mDisplay;
     52     private boolean mVoiceResultContainedPunctuation;
     53     private int mSwipeHintMaxDaysToShow;
     54     private int mPunctuationHintMaxDisplays;
     55 
     56     // Only show punctuation hint if voice result did not contain punctuation.
     57     static final Map<CharSequence, String> SPEAKABLE_PUNCTUATION
     58             = new HashMap<CharSequence, String>();
     59     static {
     60         SPEAKABLE_PUNCTUATION.put(",", "comma");
     61         SPEAKABLE_PUNCTUATION.put(".", "period");
     62         SPEAKABLE_PUNCTUATION.put("?", "question mark");
     63     }
     64 
     65     public Hints(Context context, Display display) {
     66         mContext = context;
     67         mDisplay = display;
     68 
     69         ContentResolver cr = mContext.getContentResolver();
     70         mSwipeHintMaxDaysToShow = SettingsUtil.getSettingsInt(
     71                 cr,
     72                 SettingsUtil.LATIN_IME_VOICE_INPUT_SWIPE_HINT_MAX_DAYS,
     73                 DEFAULT_SWIPE_HINT_MAX_DAYS_TO_SHOW);
     74         mPunctuationHintMaxDisplays = SettingsUtil.getSettingsInt(
     75                 cr,
     76                 SettingsUtil.LATIN_IME_VOICE_INPUT_PUNCTUATION_HINT_MAX_DISPLAYS,
     77                 DEFAULT_PUNCTUATION_HINT_MAX_DISPLAYS);
     78     }
     79 
     80     public boolean showSwipeHintIfNecessary(boolean fieldRecommended) {
     81         if (fieldRecommended && shouldShowSwipeHint()) {
     82             showHint(R.layout.voice_swipe_hint);
     83             return true;
     84         }
     85 
     86         return false;
     87     }
     88 
     89     public boolean showPunctuationHintIfNecessary(InputConnection ic) {
     90         if (!mVoiceResultContainedPunctuation
     91                 && ic != null
     92                 && getAndIncrementPref(PREF_VOICE_PUNCTUATION_HINT_VIEW_COUNT)
     93                         < mPunctuationHintMaxDisplays) {
     94             CharSequence charBeforeCursor = ic.getTextBeforeCursor(1, 0);
     95             if (SPEAKABLE_PUNCTUATION.containsKey(charBeforeCursor)) {
     96                 showHint(R.layout.voice_punctuation_hint);
     97                 return true;
     98             }
     99         }
    100 
    101         return false;
    102     }
    103 
    104     public void registerVoiceResult(String text) {
    105         // Update the current time as the last time voice input was used.
    106         SharedPreferences.Editor editor =
    107                 PreferenceManager.getDefaultSharedPreferences(mContext).edit();
    108         editor.putLong(PREF_VOICE_INPUT_LAST_TIME_USED, System.currentTimeMillis());
    109         SharedPreferencesCompat.apply(editor);
    110 
    111         mVoiceResultContainedPunctuation = false;
    112         for (CharSequence s : SPEAKABLE_PUNCTUATION.keySet()) {
    113             if (text.indexOf(s.toString()) >= 0) {
    114                 mVoiceResultContainedPunctuation = true;
    115                 break;
    116             }
    117         }
    118     }
    119 
    120     private boolean shouldShowSwipeHint() {
    121         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
    122 
    123         int numUniqueDaysShown = sp.getInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, 0);
    124 
    125         // If we've already shown the hint for enough days, we'll return false.
    126         if (numUniqueDaysShown < mSwipeHintMaxDaysToShow) {
    127 
    128             long lastTimeVoiceWasUsed = sp.getLong(PREF_VOICE_INPUT_LAST_TIME_USED, 0);
    129 
    130             // If the user has used voice today, we'll return false. (We don't show the hint on
    131             // any day that the user has already used voice.)
    132             if (!isFromToday(lastTimeVoiceWasUsed)) {
    133                 return true;
    134             }
    135         }
    136 
    137         return false;
    138     }
    139 
    140     /**
    141      * Determines whether the provided time is from some time today (i.e., this day, month,
    142      * and year).
    143      */
    144     private boolean isFromToday(long timeInMillis) {
    145         if (timeInMillis == 0) return false;
    146 
    147         Calendar today = Calendar.getInstance();
    148         today.setTimeInMillis(System.currentTimeMillis());
    149 
    150         Calendar timestamp = Calendar.getInstance();
    151         timestamp.setTimeInMillis(timeInMillis);
    152 
    153         return (today.get(Calendar.YEAR) == timestamp.get(Calendar.YEAR) &&
    154                 today.get(Calendar.DAY_OF_MONTH) == timestamp.get(Calendar.DAY_OF_MONTH) &&
    155                 today.get(Calendar.MONTH) == timestamp.get(Calendar.MONTH));
    156     }
    157 
    158     private void showHint(int hintViewResource) {
    159         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
    160 
    161         int numUniqueDaysShown = sp.getInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, 0);
    162         long lastTimeHintWasShown = sp.getLong(PREF_VOICE_HINT_LAST_TIME_SHOWN, 0);
    163 
    164         // If this is the first time the hint is being shown today, increase the saved values
    165         // to represent that. We don't need to increase the last time the hint was shown unless
    166         // it is a different day from the current value.
    167         if (!isFromToday(lastTimeHintWasShown)) {
    168             SharedPreferences.Editor editor = sp.edit();
    169             editor.putInt(PREF_VOICE_HINT_NUM_UNIQUE_DAYS_SHOWN, numUniqueDaysShown + 1);
    170             editor.putLong(PREF_VOICE_HINT_LAST_TIME_SHOWN, System.currentTimeMillis());
    171             SharedPreferencesCompat.apply(editor);
    172         }
    173 
    174         if (mDisplay != null) {
    175             mDisplay.showHint(hintViewResource);
    176         }
    177     }
    178 
    179     private int getAndIncrementPref(String pref) {
    180         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
    181         int value = sp.getInt(pref, 0);
    182         SharedPreferences.Editor editor = sp.edit();
    183         editor.putInt(pref, value + 1);
    184         SharedPreferencesCompat.apply(editor);
    185         return value;
    186     }
    187 }
    188