diff options
Diffstat (limited to 'java')
-rw-r--r-- | java/res/layout/research_feedback_activity.xml | 31 | ||||
-rw-r--r-- | java/res/layout/research_feedback_fragment_layout.xml | 112 | ||||
-rw-r--r-- | java/res/layout/research_feedback_layout.xml | 50 | ||||
-rw-r--r-- | java/res/values/strings.xml | 52 | ||||
-rw-r--r-- | java/src/com/android/inputmethod/latin/LatinIME.java | 20 | ||||
-rw-r--r-- | java/src/com/android/inputmethod/research/FeedbackActivity.java | 52 | ||||
-rw-r--r-- | java/src/com/android/inputmethod/research/FeedbackFragment.java | 73 | ||||
-rw-r--r-- | java/src/com/android/inputmethod/research/FeedbackLayout.java | 62 | ||||
-rw-r--r-- | java/src/com/android/inputmethod/research/ResearchLogger.java | 150 |
9 files changed, 539 insertions, 63 deletions
diff --git a/java/res/layout/research_feedback_activity.xml b/java/res/layout/research_feedback_activity.xml new file mode 100644 index 000000000..a6b8b8a43 --- /dev/null +++ b/java/res/layout/research_feedback_activity.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2012 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. +--> + +<com.android.inputmethod.research.FeedbackLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:id="@+id/research_feedback_layout" +> + + <fragment + android:id="@+id/research_feedback_fragment" + android:name="com.android.inputmethod.research.FeedbackFragment" + android:layout_width="match_parent" + android:layout_height="wrap_content" + /> +</com.android.inputmethod.research.FeedbackLayout> diff --git a/java/res/layout/research_feedback_fragment_layout.xml b/java/res/layout/research_feedback_fragment_layout.xml new file mode 100644 index 000000000..cc04cedf4 --- /dev/null +++ b/java/res/layout/research_feedback_fragment_layout.xml @@ -0,0 +1,112 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2012 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. +--> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" +> + + <!-- Mimic a dialog title. Necessary since the dialog is actually an activity, so the normal + dialog title construction code is not available. --> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + > + <com.android.internal.widget.DialogTitle + style="?android:attr/windowTitleStyle" + android:singleLine="true" + android:ellipsize="end" + android:layout_width="match_parent" + android:layout_height="64dip" + android:layout_marginLeft="16dip" + android:layout_marginRight="16dip" + android:gravity="center_vertical|left" + android:text="@string/research_feedback_dialog_title" /> + <View + android:layout_width="match_parent" + android:layout_height="2dip" + android:background="@android:color/holo_blue_light" /> + </LinearLayout> + + <EditText + android:id="@+id/research_feedback_contents" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_gravity="fill_horizontal|center_vertical" + android:layout_marginLeft="8dip" + android:layout_marginRight="8dip" + android:layout_marginBottom="8dip" + android:layout_marginTop="8dip" + android:lines="2" + android:hint="@string/research_feedback_hint" + android:inputType="textMultiLine" + android:imeOptions="flagNoFullscreen" + > + <requestFocus /> + </EditText> + + <CheckBox + android:id="@+id/research_feedback_include_history" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_marginBottom="8dip" + android:checked="true" + android:text="@string/research_feedback_include_history_label" + /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:divider="?android:attr/dividerHorizontal" + android:showDividers="beginning" + android:dividerPadding="0dip" + > + <LinearLayout + style="?android:attr/buttonBarStyle" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:measureWithLargestChild="true" + > + <Button + android:id="@+id/research_feedback_cancel_button" + android:layout_width="0dip" + android:layout_gravity="left" + android:layout_weight="1" + android:maxLines="2" + style="?android:attr/buttonBarButtonStyle" + android:textSize="14sp" + android:text="@string/research_feedback_cancel" + android:layout_height="wrap_content" + /> + <Button + android:id="@+id/research_feedback_send_button" + android:layout_width="0dip" + android:layout_gravity="right" + android:layout_weight="1" + android:maxLines="2" + style="?android:attr/buttonBarButtonStyle" + android:textSize="14sp" + android:text="@string/research_feedback_send" + android:layout_height="wrap_content" + /> + </LinearLayout> + </LinearLayout> +</LinearLayout> diff --git a/java/res/layout/research_feedback_layout.xml b/java/res/layout/research_feedback_layout.xml new file mode 100644 index 000000000..bacd19101 --- /dev/null +++ b/java/res/layout/research_feedback_layout.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2012 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. +--> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" +> + + <EditText + android:id="@+id/research_feedback_contents" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_gravity="fill_horizontal|center_vertical" + android:layout_marginLeft="8dip" + android:layout_marginRight="8dip" + android:layout_marginBottom="8dip" + android:layout_marginTop="8dip" + android:lines="2" + android:hint="@string/research_feedback_hint" + android:inputType="textMultiLine" + android:imeOptions="flagNoFullscreen" + android:focusable="true" + > + <requestFocus /> + </EditText> + + <CheckBox + android:id="@+id/research_feedback_include_history" + android:layout_height="wrap_content" + android:layout_width="match_parent" + android:layout_marginBottom="8dip" + android:checked="true" + android:text="@string/research_feedback_include_history_label" + /> +</LinearLayout> diff --git a/java/res/values/strings.xml b/java/res/values/strings.xml index 98c891894..377018a6b 100644 --- a/java/res/values/strings.xml +++ b/java/res/values/strings.xml @@ -222,29 +222,47 @@ <!-- Title for input language selection screen --> <string name="language_selection_title">Input languages</string> - <!-- Title for dialog option that lets user mark a particular time in the log for later review by experts [CHAR LIMIT=38] --> - <string name="note_timestamp_for_researchlog">Note timestamp in log</string> - <!-- Toast notification message that the time has been marked for later review. [CHAR LIMIT=25] --> - <string name="notify_recorded_timestamp">Recorded timestamp</string> - <!-- Title for dialog option to let users cancel logging and delete log for this session [CHAR LIMIT=35] --> - <string name="do_not_log_this_session">Suspend logging</string> + <!-- TODO: remove translatable=false attribute once text is stable --> + <string name="research_do_not_log_this_session" translatable="false">Suspend logging</string> <!-- Title for dialog option to let users reenable logging [CHAR LIMIT=35] --> - <string name="enable_session_logging">Enable logging</string> - <!-- Title for dialog option to let users log all events in this session [CHAR LIMIT=35] --> - <string name="log_whole_session_history">Log whole session history</string> + <!-- TODO: remove translatable=false attribute once text is stable --> + <string name="research_enable_session_logging" translatable="false">Enable logging</string> <!-- Toast notification that the system is processing the request to delete the log for this session [CHAR LIMIT=35] --> - <string name="notify_session_log_deleting">Deleting session log</string> + <!-- TODO: remove translatable=false attribute once text is stable --> + <string name="research_notify_session_log_deleting" translatable="false">Deleting session log</string> <!-- Toast notification that the system has successfully deleted the log for this session [CHAR LIMIT=35] --> - <string name="notify_logging_suspended">Logging temporarily suspended. To disable permanently, go to Android Keyboard Settings</string> + <!-- TODO: remove translatable=false attribute once text is stable --> + <string name="research_notify_logging_suspended" translatable="false">Logging temporarily suspended. To disable permanently, go to Android Keyboard Settings</string> <!-- Toast notification that the system has failed to delete the log for this session [CHAR LIMIT=35] --> - <string name="notify_session_log_not_deleted">Session log NOT deleted</string> - <!-- Toast notification that the system has recorded the whole session history [CHAR LIMIT=35] --> - <string name="notify_session_history_logged">Session history logged</string> - <!-- Toast notification that the system has failed to record the whole session history [CHAR LIMIT=35] --> - <string name="notify_session_history_not_logged">Error: Session history NOT logged</string> + <!-- TODO: remove translatable=false attribute once text is stable --> + <string name="research_notify_session_log_not_deleted" translatable="false">Session log NOT deleted</string> <!-- Toast notification that the system is enabling logging [CHAR LIMIT=35] --> - <string name="notify_session_logging_enabled">Session logging enabled</string> + <!-- TODO: remove translatable=false attribute once text is stable --> + <string name="research_notify_session_logging_enabled" translatable="false">Session logging enabled</string> + + <!-- Menu option that lets user send feedback for research purposes about the IME [CHAR LIMIT=38] --> + <!-- TODO: remove translatable=false attribute once text is stable --> + <string name="research_feedback_menu_option" translatable="false">Send feedback</string> + <!-- Dialog box title that lets user send feedback for research purposes about the IME [CHAR LIMIT=38] --> + <!-- TODO: remove translatable=false attribute once text is stable --> + <string name="research_feedback_dialog_title" translatable="false">Send feedback</string> + <!-- Text for checkbox option to include user data in feedback for research purposes [CHAR LIMIT=50] --> + <!-- TODO: remove translatable=false attribute once text is stable --> + <string name="research_feedback_include_history_label" translatable="false">Include last 5 words entered</string> + <!-- Hint to user about the text entry field where they should enter research feedback [CHAR LIMIT=40] --> + <!-- TODO: remove translatable=false attribute once text is stable --> + <string name="research_feedback_hint" translatable="false">Enter your feedback here.</string> + <!-- Dialog button choice to send research feedback [CHAR LIMIT=35] --> + <!-- TODO: remove translatable=false attribute once text is stable --> + <string name="research_feedback_send" translatable="false">Send</string> + <!-- Dialog button choice to cancel sending research feedback [CHAR LIMIT=35] --> + <!-- TODO: remove translatable=false attribute once text is stable --> + <string name="research_feedback_cancel" translatable="false">Cancel</string> + <!-- Toast notification to ask user to quit the research feedback dialog to perform this operation [CHAR LIMIT=100] --> + <!-- TODO: remove translatable=false attribute once text is stable --> + <string name="research_please_exit_feedback_form" translatable="false">Please exit the feedback dialog to access the research log menu</string> + <!-- Preference for input language selection --> <string name="select_language">Input languages</string> diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 8953cb8d1..4248921f4 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -20,6 +20,7 @@ import static com.android.inputmethod.latin.Constants.ImeOption.FORCE_ASCII; import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE; import static com.android.inputmethod.latin.Constants.ImeOption.NO_MICROPHONE_COMPAT; +import android.app.Activity; import android.app.AlertDialog; import android.content.BroadcastReceiver; import android.content.Context; @@ -38,7 +39,6 @@ import android.os.Debug; import android.os.IBinder; import android.os.Message; import android.os.SystemClock; -import android.preference.PreferenceActivity; import android.preference.PreferenceManager; import android.text.InputType; import android.text.TextUtils; @@ -2111,18 +2111,26 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen }; private void launchSettings() { - launchSettingsClass(SettingsActivity.class); + handleClose(); + launchSubActivity(SettingsActivity.class); } // Called from debug code only public void launchDebugSettings() { - launchSettingsClass(DebugSettingsActivity.class); + handleClose(); + launchSubActivity(DebugSettingsActivity.class); } - private void launchSettingsClass(Class<? extends PreferenceActivity> settingsClass) { - handleClose(); + public void launchKeyboardedDialogActivity(Class<? extends Activity> activityClass) { + // Put the text in the attached EditText into a safe, saved state before switching to a + // new activity that will also use the soft keyboard. + commitTyped(LastComposedWord.NOT_A_SEPARATOR); + launchSubActivity(activityClass); + } + + private void launchSubActivity(Class<? extends Activity> activityClass) { Intent intent = new Intent(); - intent.setClass(LatinIME.this, settingsClass); + intent.setClass(LatinIME.this, activityClass); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } diff --git a/java/src/com/android/inputmethod/research/FeedbackActivity.java b/java/src/com/android/inputmethod/research/FeedbackActivity.java new file mode 100644 index 000000000..c9f3b476a --- /dev/null +++ b/java/src/com/android/inputmethod/research/FeedbackActivity.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2012 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.inputmethod.research; + +import android.app.Activity; +import android.os.Bundle; +import android.text.Editable; +import android.view.View; +import android.widget.CheckBox; +import android.widget.EditText; + +import com.android.inputmethod.latin.R; + +public class FeedbackActivity extends Activity { + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.research_feedback_activity); + final FeedbackLayout layout = (FeedbackLayout) findViewById(R.id.research_feedback_layout); + layout.setActivity(this); + } + + @Override + protected void onResume() { + super.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + } + + @Override + public void onBackPressed() { + ResearchLogger.getInstance().onLeavingSendFeedbackDialog(); + super.onBackPressed(); + } +} diff --git a/java/src/com/android/inputmethod/research/FeedbackFragment.java b/java/src/com/android/inputmethod/research/FeedbackFragment.java new file mode 100644 index 000000000..a2e08e2b7 --- /dev/null +++ b/java/src/com/android/inputmethod/research/FeedbackFragment.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2012 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.inputmethod.research; + +import android.app.Activity; +import android.app.Fragment; +import android.os.Bundle; +import android.text.Editable; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.EditText; + +import com.android.inputmethod.latin.R; + +public class FeedbackFragment extends Fragment { + private EditText mEditText; + private CheckBox mCheckBox; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + final View view = inflater.inflate(R.layout.research_feedback_fragment_layout, container, + false); + mEditText = (EditText) view.findViewById(R.id.research_feedback_contents); + mCheckBox = (CheckBox) view.findViewById(R.id.research_feedback_include_history); + + final Button sendButton = (Button) view.findViewById( + R.id.research_feedback_send_button); + sendButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + final Editable editable = mEditText.getText(); + final String feedbackContents = editable.toString(); + final boolean includeHistory = mCheckBox.isChecked(); + ResearchLogger.getInstance().sendFeedback(feedbackContents, includeHistory); + final Activity activity = FeedbackFragment.this.getActivity(); + activity.finish(); + ResearchLogger.getInstance().onLeavingSendFeedbackDialog(); + } + }); + + final Button cancelButton = (Button) view.findViewById( + R.id.research_feedback_cancel_button); + cancelButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + final Activity activity = FeedbackFragment.this.getActivity(); + activity.finish(); + ResearchLogger.getInstance().onLeavingSendFeedbackDialog(); + } + }); + + return view; + } +} diff --git a/java/src/com/android/inputmethod/research/FeedbackLayout.java b/java/src/com/android/inputmethod/research/FeedbackLayout.java new file mode 100644 index 000000000..f2cbfe308 --- /dev/null +++ b/java/src/com/android/inputmethod/research/FeedbackLayout.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2012 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.inputmethod.research; + +import android.app.Activity; +import android.content.Context; +import android.util.AttributeSet; +import android.view.KeyEvent; +import android.widget.LinearLayout; + +public class FeedbackLayout extends LinearLayout { + private Activity mActivity; + + public FeedbackLayout(Context context) { + super(context); + } + + public FeedbackLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public FeedbackLayout(Context context, AttributeSet attrs, int defstyle) { + super(context, attrs, defstyle); + } + + public void setActivity(Activity activity) { + mActivity = activity; + } + + @Override + public boolean dispatchKeyEventPreIme(KeyEvent event) { + if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { + KeyEvent.DispatcherState state = getKeyDispatcherState(); + if (state != null) { + if (event.getAction() == KeyEvent.ACTION_DOWN + && event.getRepeatCount() == 0) { + state.startTracking(event, this); + return true; + } else if (event.getAction() == KeyEvent.ACTION_UP + && !event.isCanceled() && state.isTracking(event)) { + mActivity.onBackPressed(); + return true; + } + } + } + return super.dispatchKeyEventPreIme(event); + } +} diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java index b40bfe387..e6828da50 100644 --- a/java/src/com/android/inputmethod/research/ResearchLogger.java +++ b/java/src/com/android/inputmethod/research/ResearchLogger.java @@ -83,7 +83,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang private static final String WHITESPACE_SEPARATORS = " \t\n\r"; private static final int MAX_INPUTVIEW_LENGTH_TO_CAPTURE = 8192; // must be >=1 private static final String PREF_RESEARCH_LOGGER_UUID_STRING = "pref_research_logger_uuid"; - private static final int ABORT_TIMEOUT_IN_MS = 10 * 1000; + private static final int ABORT_TIMEOUT_IN_MS = 10 * 1000; // timeout to notify user private static final ResearchLogger sInstance = new ResearchLogger(); // to write to a different filename, e.g., for testing, set mFile before calling start() @@ -95,7 +95,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang // the system to do so. /* package */ ResearchLog mIntentionalResearchLog; // LogUnits are queued here and released only when the user requests the intentional log. - private final List<LogUnit> mIntentionalResearchLogQueue = new ArrayList<LogUnit>(); + private List<LogUnit> mIntentionalResearchLogQueue = new ArrayList<LogUnit>(); private boolean mIsPasswordView = false; private boolean mIsLoggingSuspended = false; @@ -268,22 +268,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } } - private void logWholeSessionHistory() throws IOException { - try { - LogUnit headerLogUnit = new LogUnit(); - headerLogUnit.addLogAtom(EVENTKEYS_INTENTIONAL_LOG, EVENTKEYS_NULLVALUES, false); - mIntentionalResearchLog.publishAllEvents(headerLogUnit); - for (LogUnit logUnit : mIntentionalResearchLogQueue) { - mIntentionalResearchLog.publishAllEvents(logUnit); - } - mIntentionalResearchLog.stop(); - mIntentionalResearchLog = new ResearchLog(createLogFile(mFilesDir)); - mIntentionalResearchLog.start(); - } finally { - mIntentionalResearchLogQueue.clear(); - } - } - private void restart() { stop(); start(); @@ -325,13 +309,17 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang } public void presentResearchDialog(final LatinIME latinIME) { + if (mInFeedbackDialog) { + Toast.makeText(latinIME, R.string.research_please_exit_feedback_form, + Toast.LENGTH_LONG).show(); + return; + } final CharSequence title = latinIME.getString(R.string.english_ime_research_log); final boolean showEnable = mIsLoggingSuspended || !sIsLogging; final CharSequence[] items = new CharSequence[] { - latinIME.getString(R.string.note_timestamp_for_researchlog), - showEnable ? latinIME.getString(R.string.enable_session_logging) : - latinIME.getString(R.string.do_not_log_this_session), - latinIME.getString(R.string.log_whole_session_history) + latinIME.getString(R.string.research_feedback_menu_option), + showEnable ? latinIME.getString(R.string.research_enable_session_logging) : + latinIME.getString(R.string.research_do_not_log_this_session) }; final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { @Override @@ -339,9 +327,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang di.dismiss(); switch (position) { case 0: - userTimestamp(); - Toast.makeText(latinIME, R.string.notify_recorded_timestamp, - Toast.LENGTH_LONG).show(); + presentFeedbackDialog(latinIME); break; case 1: if (showEnable) { @@ -349,11 +335,13 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang setLoggingAllowed(true); } resumeLogging(); - Toast.makeText(latinIME, R.string.notify_session_logging_enabled, + Toast.makeText(latinIME, + R.string.research_notify_session_logging_enabled, Toast.LENGTH_LONG).show(); } else { Toast toast = Toast.makeText(latinIME, - R.string.notify_session_log_deleting, Toast.LENGTH_LONG); + R.string.research_notify_session_log_deleting, + Toast.LENGTH_LONG); toast.show(); boolean isLogDeleted = abort(); final long currentTime = System.currentTimeMillis(); @@ -361,21 +349,10 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang SUSPEND_DURATION_IN_MINUTES; suspendLoggingUntil(resumeTime); toast.cancel(); - Toast.makeText(latinIME, R.string.notify_logging_suspended, + Toast.makeText(latinIME, R.string.research_notify_logging_suspended, Toast.LENGTH_LONG).show(); } break; - case 2: - try { - logWholeSessionHistory(); - Toast.makeText(latinIME, R.string.notify_session_history_logged, - Toast.LENGTH_LONG).show(); - } catch (IOException e) { - Toast.makeText(latinIME, R.string.notify_session_history_not_logged, - Toast.LENGTH_LONG).show(); - e.printStackTrace(); - } - break; } } @@ -386,6 +363,83 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang latinIME.showOptionDialog(builder.create()); } + private boolean mInFeedbackDialog = false; + public void presentFeedbackDialog(LatinIME latinIME) { + mInFeedbackDialog = true; + latinIME.launchKeyboardedDialogActivity(FeedbackActivity.class); + } + + private ResearchLog mFeedbackLog; + private List<LogUnit> mFeedbackQueue; + private ResearchLog mSavedMainResearchLog; + private ResearchLog mSavedIntentionalResearchLog; + private List<LogUnit> mSavedIntentionalResearchLogQueue; + + private void saveLogsForFeedback() { + mFeedbackLog = mIntentionalResearchLog; + if (mIntentionalResearchLogQueue != null) { + mFeedbackQueue = new ArrayList<LogUnit>(mIntentionalResearchLogQueue); + } else { + mFeedbackQueue = null; + } + mSavedMainResearchLog = mMainResearchLog; + mSavedIntentionalResearchLog = mIntentionalResearchLog; + mSavedIntentionalResearchLogQueue = mIntentionalResearchLogQueue; + + mMainResearchLog = null; + mIntentionalResearchLog = null; + mIntentionalResearchLogQueue = new ArrayList<LogUnit>(); + } + + private static final int LOG_DRAIN_TIMEOUT_IN_MS = 1000 * 5; + public void sendFeedback(final String feedbackContents, final boolean includeHistory) { + if (includeHistory && mFeedbackLog != null) { + try { + LogUnit headerLogUnit = new LogUnit(); + headerLogUnit.addLogAtom(EVENTKEYS_INTENTIONAL_LOG, EVENTKEYS_NULLVALUES, false); + mFeedbackLog.publishAllEvents(headerLogUnit); + for (LogUnit logUnit : mFeedbackQueue) { + mFeedbackLog.publishAllEvents(logUnit); + } + userFeedback(mFeedbackLog, feedbackContents); + mFeedbackLog.stop(); + try { + mFeedbackLog.waitUntilStopped(LOG_DRAIN_TIMEOUT_IN_MS); + } catch (InterruptedException e) { + e.printStackTrace(); + } + mIntentionalResearchLog = new ResearchLog(createLogFile(mFilesDir)); + mIntentionalResearchLog.start(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + mIntentionalResearchLogQueue.clear(); + } + mResearchLogUploader.uploadNow(null); + } else { + // create a separate ResearchLog just for feedback + final ResearchLog feedbackLog = new ResearchLog(createLogFile(mFilesDir)); + try { + feedbackLog.start(); + userFeedback(feedbackLog, feedbackContents); + feedbackLog.stop(); + feedbackLog.waitUntilStopped(LOG_DRAIN_TIMEOUT_IN_MS); + mResearchLogUploader.uploadNow(null); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public void onLeavingSendFeedbackDialog() { + mInFeedbackDialog = false; + mMainResearchLog = mSavedMainResearchLog; + mIntentionalResearchLog = mSavedIntentionalResearchLog; + mIntentionalResearchLogQueue = mSavedIntentionalResearchLogQueue; + } + public void initSuggest(Suggest suggest) { mSuggest = suggest; } @@ -540,7 +594,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang return; } if (mMainResearchLog == null) { - Log.w(TAG, "ResearchLog was not properly set up"); return; } if (isPrivacySensitive) { @@ -647,6 +700,9 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang public static void latinIME_onStartInputViewInternal(final EditorInfo editorInfo, final SharedPreferences prefs) { final ResearchLogger researchLogger = getInstance(); + if (researchLogger.mInFeedbackDialog) { + researchLogger.saveLogsForFeedback(); + } researchLogger.start(); if (editorInfo != null) { final Context context = researchLogger.mContext; @@ -688,6 +744,20 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang researchLogger.onWordComplete(scrubbedWord); } + private static final String[] EVENTKEYS_USER_FEEDBACK = { + "UserFeedback", "FeedbackContents" + }; + + private void userFeedback(ResearchLog researchLog, String feedbackContents) { + // this method is special; it directs the feedbackContents to a particular researchLog + final LogUnit logUnit = new LogUnit(); + final Object[] values = { + feedbackContents + }; + logUnit.addLogAtom(EVENTKEYS_USER_FEEDBACK, values, false); + researchLog.publishAllEvents(logUnit); + } + // Regular logging methods private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_PROCESSMOTIONEVENT = { |