Support smartreply in Mobile IME 96/134396/3
authorsungwook79.park <sungwook79.park@samsung.com>
Fri, 16 Jun 2017 07:54:13 +0000 (16:54 +0900)
committerJihoon Kim <jihoon48.kim@samsung.com>
Tue, 20 Jun 2017 06:03:55 +0000 (15:03 +0900)
Change-Id: I5f685587d646f36aa76671512709cd5889c96168
Signed-off-by: sungwook79.park <sungwook79.park@samsung.com>
CMakeLists.txt
packaging/ise-default.spec
src/include/ise.h
src/include/w-input-smartreply.h [new file with mode: 0644]
src/ise.cpp
src/w-input-smartreply.cpp [new file with mode: 0644]

index 9e61230..07eefe4 100644 (file)
@@ -27,6 +27,8 @@ SET(ISE_SRCS
     src/ise-emoticon-mode.cpp
     src/modeindicator.cpp
     src/eflutil.cpp
+
+    src/w-input-smartreply.cpp
 )
 
 SET(ISE_PACKAGE ${PROJECT_NAME})
@@ -61,6 +63,7 @@ SET(PKGS_CHECK_MODULES
         capi-appfw-preference
         capi-media-audio-io
         capi-ui-inputmethod
+        smartreply
         )
 
 IF (with_cbhm)
index f12363f..5c298de 100644 (file)
@@ -21,6 +21,8 @@ BuildRequires:  pkgconfig(capi-appfw-application)
 BuildRequires:  pkgconfig(capi-appfw-preference)
 BuildRequires:  pkgconfig(capi-media-audio-io)
 BuildRequires:  pkgconfig(capi-ui-inputmethod)
+BuildRequires:  pkgconfig(smartreply)
+
 # This is for old profile-based OBS project optimizations.
 # In 4.0 unified build env, this if statement is always true.
 %if "%{?profile}" != "wearable" && "%{?profile}" != "tv" && "%{?profile}" != "ivi" && "%{?profile}" != "common"
index c422cb8..9543402 100644 (file)
@@ -191,6 +191,8 @@ void ise_show(int ic);
 void ise_hide();
 void ise_create();
 void ise_destroy();
+void ise_app_candidate_show();
+void ise_app_candidate_hide();
 void ise_reset_context();
 void ise_reset_input_context();
 void ise_set_layout(sclu32 layout, sclu32 layout_variation);
diff --git a/src/include/w-input-smartreply.h b/src/include/w-input-smartreply.h
new file mode 100644 (file)
index 0000000..da045e7
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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.
+ */
+
+#ifndef _W_INPUT_SMARTREPLY_H_
+#define _W_INPUT_SMARTREPLY_H_
+
+#include <stdbool.h>
+
+typedef void (*input_smartreply_changed)(void *user_data);
+
+
+bool input_smartreply_init(char *caller_id, char *sender, char *message);
+
+void input_smartreply_deinit(void);
+
+const char *input_smartreply_get_lang(void);
+
+bool input_smartreply_get_reply(void);
+
+bool input_smartreply_get_reply_async(void);
+
+int input_smartreply_get_reply_num(void);
+
+char *input_smartreply_get_nth_item(int index, int *type);
+
+bool input_smartreply_send_feedback(const char *str);
+
+void input_smartreply_set_notify(input_smartreply_changed callback, void *user_data);
+
+void input_smartreply_unset_notify(void);
+
+bool input_smartreply_is_enabled(void);
+
+#endif
index c729f06..eab719e 100644 (file)
@@ -41,6 +41,8 @@
 #include "ise-stt-option.h"
 #include "ise-language-change.h"
 #include "modeindicator.h"
+#include "w-input-smartreply.h"
+
 #define EDJ_FILE                        RESDIR"/edje/mobile/customised_ctxpopup.edj"
 #define EXPORTED __attribute__((visibility("default")))
 
@@ -76,6 +78,7 @@ static string g_default_punctuation[MAX_DEFAULT_PUNCTUATION] = {"-", "@", "'", "
 static string g_current_punctuation[MAX_DEFAULT_PUNCTUATION-1] = {"RCENT1", "RCENT2", "RCENT3", "RCENT4", "RCENT5"};
 static vector<string> g_softcandidate_string;
 static bool g_softcandidate_show = false;
+static bool g_smartrply_reply_exist = false;
 static bool g_caps_mode_pending = false;
 #ifdef _MOBILE
 static Ecore_Timer *guideline_timer = NULL;
@@ -126,6 +129,8 @@ class CandidateEventListener: public EventListener
             switch (multidesc.type) {
                 case MultiEventDesc::CANDIDATE_ITEM_MOUSE_DOWN:
                     ime_select_candidate(multidesc.index);
+                    if (g_softcandidate_string.size() > multidesc.index)
+                        ise_send_string(g_softcandidate_string[multidesc.index].c_str());
                     break;
                 case MultiEventDesc::CANDIDATE_MORE_VIEW_SHOW:
                     // when more parts shows, click on the candidate will
@@ -180,6 +185,35 @@ public :
 
 static CUIEventCallback callback;
 
+static void _input_smartreply_notify_cb(void *user_data)
+{
+    vector<string> candidate_strings;
+    char *candidate;
+
+    if (input_smartreply_is_enabled()) {
+        /* Append newly added smartreply list */
+        int len = input_smartreply_get_reply_num();
+        if (len > 0) {
+            for (int i = 0; i < len; i++) {
+                int type;
+                char *reply = "";
+                reply = input_smartreply_get_nth_item(i, &type);
+                if (reply == NULL)
+                    continue;
+                LOGD("SmartReply = [%d]%s", i, reply);
+                candidate = reply;
+                if (candidate) {
+                    candidate_strings.push_back(string(candidate));
+                }
+            }
+            g_smartrply_reply_exist = true;
+            ise_app_candidate_show();
+            g_softcandidate_string = candidate_strings;
+            ise_update_table(candidate_strings);
+        }
+    }
+}
+
 sclboolean
 check_ic_temporary(int ic)
 {
@@ -1418,10 +1452,6 @@ ise_hide()
 
     g_keyboard_state.visible_state = FALSE;
 
-    if (g_candidate) {
-        g_candidate->hide();
-    }
-
     _reset_shift_state();
     _reset_multitap_state(true);
 
@@ -1551,6 +1581,53 @@ ise_destroy()
     vconf_set_bool(VCONFKEY_AUTOPERIOD_ALLOW_BOOL, false);
 }
 
+void
+ise_app_candidate_show()
+{
+    LOGD("Enter\n");
+    delete_softcandidate_hide_timer();
+
+    create_softcandidate();
+
+    g_softcandidate_show = true;
+    if (g_candidate) {
+        g_candidate->show();
+        if (g_ui) {
+            g_ui->set_custom_starting_coordinates(0, g_candidate->get_height());
+            SclSize size_portrait = g_ui->get_input_mode_size(g_ui->get_input_mode(), DISPLAYMODE_PORTRAIT);
+            SclSize size_landscape = g_ui->get_input_mode_size(g_ui->get_input_mode(), DISPLAYMODE_LANDSCAPE);
+            size_portrait.height += g_candidate->get_height();
+            size_landscape.height += g_candidate->get_height();
+            ime_set_size(size_portrait.width, size_portrait.height, size_landscape.width, size_landscape.height);
+
+            LOGD("Showing candidate , position [%d %d] size [%d %d] [%d %d]", 0, g_candidate->get_height(),
+                size_portrait.width, size_portrait.height, size_landscape.width, size_landscape.height);
+        }
+    }
+}
+
+void
+ise_app_candidate_hide()
+{
+    LOGD("Enter\n");
+
+    if (!g_candidate || !g_softcandidate_show) {
+        LOGD("No candidate\n");
+        return;
+    }
+
+    add_softcandidate_hide_timer();
+    if (g_ui) {
+        g_ui->set_custom_starting_coordinates(0, 0);
+        SclSize size_portrait = g_ui->get_input_mode_size(g_ui->get_input_mode(), DISPLAYMODE_PORTRAIT);
+        SclSize size_landscape = g_ui->get_input_mode_size(g_ui->get_input_mode(), DISPLAYMODE_LANDSCAPE);
+        ime_set_size(size_portrait.width, size_portrait.height, size_landscape.width, size_landscape.height);
+
+        LOGD("Hiding candidate , position [%d %d] size [%d %d] [%d %d]", 0, 0,
+            size_portrait.width, size_portrait.height, size_landscape.width, size_landscape.height);
+    }
+}
+
 // when it is the time to auto_cap, the
 // ise_set_caps_mode is called.
 // -------------------------------------------------------
@@ -1929,6 +2006,12 @@ static void ime_app_focus_in_cb(int context_id, void *user_data)
 {
     LOGD("Enter\n");
     ise_focus_in(context_id);
+    if (!g_smartrply_reply_exist && g_softcandidate_show) {
+        if (g_candidate) {
+            ise_app_candidate_hide();
+            g_candidate->hide();
+        }
+    }
 }
 
 static void ime_app_focus_out_cb(int context_id, void *user_data)
@@ -1939,6 +2022,8 @@ static void ime_app_focus_out_cb(int context_id, void *user_data)
 #ifdef HAVE_CBHM
     g_set_mime_type = FALSE;
 #endif
+    g_smartrply_reply_exist = false;
+    input_smartreply_deinit();
 }
 
 static void ime_app_layout_set_cb(Ecore_IMF_Input_Panel_Layout layout, void *user_data)
@@ -2045,47 +2130,12 @@ static void ime_app_caps_mode_changed_cb(int mode, void *user_data)
 
 static void ime_app_candidate_show_cb(int context_id, void *user_data)
 {
-    LOGD("Enter\n");
-    delete_softcandidate_hide_timer();
-
-    create_softcandidate();
-
-    g_softcandidate_show = true;
-    if (g_candidate) {
-        g_candidate->show();
-        if (g_ui) {
-            g_ui->set_custom_starting_coordinates(0, g_candidate->get_height());
-            SclSize size_portrait = g_ui->get_input_mode_size(g_ui->get_input_mode(), DISPLAYMODE_PORTRAIT);
-            SclSize size_landscape = g_ui->get_input_mode_size(g_ui->get_input_mode(), DISPLAYMODE_LANDSCAPE);
-            size_portrait.height += g_candidate->get_height();
-            size_landscape.height += g_candidate->get_height();
-            ime_set_size(size_portrait.width, size_portrait.height, size_landscape.width, size_landscape.height);
-
-            LOGD("Showing candidate , position [%d %d] size [%d %d] [%d %d]", 0, g_candidate->get_height(),
-                size_portrait.width, size_portrait.height, size_landscape.width, size_landscape.height);
-        }
-    }
+    ise_app_candidate_show();
 }
 
 static void ime_app_candidate_hide_cb(int context_id, void *user_data)
 {
-    LOGD("Enter\n");
-
-    if (!g_candidate || !g_softcandidate_show) {
-        LOGD("No candidate\n");
-        return;
-    }
-
-    add_softcandidate_hide_timer();
-    if (g_ui) {
-        g_ui->set_custom_starting_coordinates(0, 0);
-        SclSize size_portrait = g_ui->get_input_mode_size(g_ui->get_input_mode(), DISPLAYMODE_PORTRAIT);
-        SclSize size_landscape = g_ui->get_input_mode_size(g_ui->get_input_mode(), DISPLAYMODE_LANDSCAPE);
-        ime_set_size(size_portrait.width, size_portrait.height, size_landscape.width, size_landscape.height);
-
-        LOGD("Hiding candidate , position [%d %d] size [%d %d] [%d %d]", 0, 0,
-            size_portrait.width, size_portrait.height, size_landscape.width, size_landscape.height);
-    }
+    ise_app_candidate_hide();
 }
 
 static void ime_app_lookup_table_changed_cb(Eina_List *list, void *user_data)
@@ -2212,6 +2262,14 @@ static void ime_app_process_input_device_event_cb(ime_input_device_type_e device
 static void ime_app_prediction_hint_set_cb(const char *prediction_hint, void *user_data)
 {
     LOGD("prediction hint : %s\n", prediction_hint);
+    char *sender = "mms";
+    char *caller_id = "mms";
+    char *hint = (char *)prediction_hint;
+    input_smartreply_init(caller_id, sender, hint);
+    input_smartreply_set_notify(_input_smartreply_notify_cb, NULL);
+
+    if (input_smartreply_is_enabled())
+        input_smartreply_get_reply_async();
 }
 
 static void ime_app_mime_type_set_cb(const char *mime_types, void *user_data)
diff --git a/src/w-input-smartreply.cpp b/src/w-input-smartreply.cpp
new file mode 100644 (file)
index 0000000..823fe4e
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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.
+ */
+
+#include <glib.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+
+#include <dlog.h>
+#include <vconf.h>
+
+#include <smartreply_service.h>
+
+#include "w-input-smartreply.h"
+
+#ifndef INPUT_SMARTREPLY_VCONF
+#define INPUT_SMARTREPLY_VCONF "db/wms/smart_reply"
+#endif
+
+typedef struct _InputSmartreplyData InputSmartreplyData;
+
+struct _InputSmartreplyData
+{
+    char *caller_id;
+    char *sender;
+    char *message;
+    char *lang;
+
+    int enabled;
+
+    input_smartreply_changed callback;
+    void *user_data;
+
+    smartreply_reply_h *candidate_list;
+    int candidate_list_len;
+    bool enable_location;
+};
+
+static void _input_smartreply_get_reply_callback(int handle, int error,
+                        smartreply_reply_h* candidate_list, int length);
+
+static InputSmartreplyData *g_input_smartreply_data = NULL;
+
+static void _input_smartreply_get_reply_callback(int handle, int error,
+                        smartreply_reply_h* candidate_list, int length)
+{
+    if (g_input_smartreply_data == NULL) {
+        LOGD("InputSmartreplyData uninitialized");
+        return;
+    }
+
+    if (g_input_smartreply_data == NULL) {
+        LOGD("InputSmartreplyData uninitialized");
+        return;
+    }
+
+    if (g_input_smartreply_data->candidate_list) {
+        int ret;
+
+        ret = smartreply_service_destory_list(g_input_smartreply_data->candidate_list);
+        if (ret != SMARTREPLY_ERROR_NONE)
+            LOGD("can not destroy list : %d", ret);
+    }
+
+    if (error != SMARTREPLY_ERROR_NONE) {
+        LOGD("can not get candidate list : %d", error);
+
+        g_input_smartreply_data->candidate_list = NULL;
+        g_input_smartreply_data->candidate_list_len = 0;
+
+        return;
+    }
+
+    g_input_smartreply_data->candidate_list = candidate_list;
+    g_input_smartreply_data->candidate_list_len = length;
+
+    if (g_input_smartreply_data->callback)
+        g_input_smartreply_data->callback(g_input_smartreply_data->user_data);
+}
+
+static bool _smartreply_check_here_map_support(void)
+{
+    return true;
+}
+
+bool input_smartreply_init(char *caller_id, char *sender, char *message)
+{
+    int ret;
+
+    if (g_input_smartreply_data == NULL) {
+        g_input_smartreply_data = (InputSmartreplyData *)calloc(1, sizeof(InputSmartreplyData));
+        if (g_input_smartreply_data == NULL) {
+            LOGD("Can not alloc InputSmartreplyData");
+            return false;
+        }
+    }
+
+    if (g_input_smartreply_data->caller_id)
+        free(g_input_smartreply_data->caller_id);
+
+    if (g_input_smartreply_data->sender)
+        free(g_input_smartreply_data->sender);
+
+    if (g_input_smartreply_data->message)
+        free(g_input_smartreply_data->message);
+
+    if (g_input_smartreply_data->lang)
+        free(g_input_smartreply_data->lang);
+
+    if (g_input_smartreply_data->candidate_list) {
+        ret = smartreply_service_destory_list(g_input_smartreply_data->candidate_list);
+        if (ret != SMARTREPLY_ERROR_NONE)
+            LOGD("can not destroy list : %d", ret);
+    }
+
+    g_input_smartreply_data->caller_id = caller_id;
+    g_input_smartreply_data->sender = sender;
+    g_input_smartreply_data->message = message;
+    g_input_smartreply_data->lang = NULL;
+
+    g_input_smartreply_data->enabled = 1;
+
+    g_input_smartreply_data->callback = NULL;
+    g_input_smartreply_data->user_data = NULL;
+
+    g_input_smartreply_data->candidate_list = NULL;
+    g_input_smartreply_data->candidate_list_len = 0;
+
+    g_input_smartreply_data->enable_location = _smartreply_check_here_map_support();
+
+    return true;
+}
+
+void input_smartreply_deinit(void)
+{
+    if (g_input_smartreply_data == NULL) {
+        LOGD("InputSmartreplyData uninitialized");
+        return;
+    }
+
+    if (g_input_smartreply_data->candidate_list) {
+        int ret;
+
+        ret = smartreply_service_destory_list(g_input_smartreply_data->candidate_list);
+        if (ret != SMARTREPLY_ERROR_NONE)
+            LOGD("can not destroy list : %d", ret);
+    }
+
+    input_smartreply_unset_notify();
+
+    free(g_input_smartreply_data);
+    g_input_smartreply_data = NULL;
+
+    return;
+}
+
+bool input_smartreply_get_reply(void)
+{
+    int ret;
+
+    smartreply_reply_h *candidate_list = NULL;
+    int candidate_list_len = 0;
+
+    if (g_input_smartreply_data == NULL) {
+        LOGD("InputSmartreplyData uninitialized");
+        return false;
+    }
+
+    if (g_input_smartreply_data->message == NULL) {
+        LOGD("message is empty");
+        return false;
+    }
+
+    if (g_input_smartreply_data->enabled == 0) {
+        LOGD("Smartreply is disabled");
+        return false;
+    }
+
+    ret = smartreply_service_get_replies(g_input_smartreply_data->caller_id,
+                    g_input_smartreply_data->sender,
+                    g_input_smartreply_data->message,
+                    &candidate_list,
+                    &candidate_list_len);
+
+    if (ret != SMARTREPLY_ERROR_NONE)  {
+        LOGD("Can not get replies : %d", ret);
+        return false;
+    }
+
+    if (g_input_smartreply_data->candidate_list) {
+        ret = smartreply_service_destory_list(g_input_smartreply_data->candidate_list);
+        if (ret != SMARTREPLY_ERROR_NONE)
+            LOGD("can not destroy list : %d", ret);
+    }
+
+    g_input_smartreply_data->candidate_list = candidate_list;
+    g_input_smartreply_data->candidate_list_len = candidate_list_len;
+
+    return true;
+}
+
+bool input_smartreply_get_reply_async(void)
+{
+    if (g_input_smartreply_data == NULL) {
+        LOGD("InputSmartreplyData uninitialized");
+        return false;
+    }
+
+    if (g_input_smartreply_data->message == NULL) {
+        LOGD("message is empty");
+        return false;
+    }
+
+    if (g_input_smartreply_data->enabled == 0) {
+        LOGD("Smartreply is disabled");
+        return false;
+    }
+
+    smartreply_service_get_replies_async(g_input_smartreply_data->caller_id,
+                    g_input_smartreply_data->sender,
+                    g_input_smartreply_data->message,
+                    _input_smartreply_get_reply_callback);
+
+    return true;
+}
+
+int input_smartreply_get_reply_num(void)
+{
+    if (g_input_smartreply_data == NULL) {
+        LOGD("InputSmartreplyData uninitialized");
+        return 0;
+    }
+
+    if (g_input_smartreply_data->enabled == 0) {
+        LOGD("Smartreply is disabled");
+        return 0;
+    }
+
+    return g_input_smartreply_data->candidate_list_len;
+}
+
+char *input_smartreply_get_nth_item(int index, int *type)
+{
+    int ret;
+    char *message = NULL;
+
+    if (g_input_smartreply_data == NULL) {
+        LOGD("InputSmartreplyData uninitialized");
+        return NULL;
+    }
+
+    if (g_input_smartreply_data->candidate_list == NULL) {
+        LOGD("Can not get candidate list");
+        return NULL;
+    }
+
+    if (g_input_smartreply_data->enabled == 0) {
+        LOGD("Smartreply is disabled");
+        return NULL;
+    }
+
+
+    ret = smartreply_service_get_nth_reply_message(g_input_smartreply_data->candidate_list,
+                            index,
+                            &message);
+
+    if (ret != SMARTREPLY_ERROR_NONE) {
+        LOGD("Can not get message from index %d : %d", index, ret);
+        return NULL;
+    }
+
+    return message;
+}
+
+bool input_smartreply_send_feedback(const char *str)
+{
+    int ret;
+
+    if (g_input_smartreply_data == NULL) {
+        LOGD("InputSmartreplyData uninitialized");
+        return false;
+    }
+
+    if (str == NULL) {
+        LOGD("str is empty");
+        return false;
+    }
+
+    ret = smartreply_service_record_user_reply(g_input_smartreply_data->caller_id,
+                        g_input_smartreply_data->sender,
+                        g_input_smartreply_data->message,
+                        str);
+
+    if (ret != SMARTREPLY_ERROR_NONE) {
+        LOGD("Can not send feedback : %d", ret);
+        return false;
+    }
+
+    return true;
+}
+
+void input_smartreply_set_notify(input_smartreply_changed callback,
+            void *user_data)
+{
+    if (callback == NULL) {
+        LOGD("empty callback function");
+        return;
+    }
+
+    if (g_input_smartreply_data == NULL) {
+        LOGD("InputSmartreplyData uninitialized");
+        return;
+    }
+
+    g_input_smartreply_data->callback = callback;
+    g_input_smartreply_data->user_data = user_data;
+}
+
+void input_smartreply_unset_notify(void)
+{
+    if (g_input_smartreply_data == NULL) {
+        LOGD("InputSmartreplyData uninitialized");
+        return;
+    }
+
+    g_input_smartreply_data->callback = NULL;
+    g_input_smartreply_data->user_data = NULL;
+}
+
+bool input_smartreply_is_enabled(void)
+{
+    if (g_input_smartreply_data == NULL) {
+        LOGD("InputSmartreplyData uninitialized");
+        return false;
+    }
+
+    if (g_input_smartreply_data->enabled)
+        return true;
+
+    return false;
+}