aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/com.canonical.indicator.messages.application.xml6
-rw-r--r--debian/libmessaging-menu0.symbols1
-rw-r--r--libmessaging-menu/messaging-menu-app.c77
-rw-r--r--libmessaging-menu/messaging-menu-message.c175
-rw-r--r--libmessaging-menu/messaging-menu-message.h6
-rw-r--r--src/im-application-list.c117
-rw-r--r--src/im-phone-menu.c11
-rw-r--r--src/im-phone-menu.h1
8 files changed, 337 insertions, 57 deletions
diff --git a/common/com.canonical.indicator.messages.application.xml b/common/com.canonical.indicator.messages.application.xml
index 552b6a4..6f038e6 100644
--- a/common/com.canonical.indicator.messages.application.xml
+++ b/common/com.canonical.indicator.messages.application.xml
@@ -5,13 +5,15 @@
<arg type="a(sssuxsb)" name="sources" direction="out" />
</method>
<method name="ListMessages">
- <arg type="a(sssssxb)" name="message" direction="out" />
+ <arg type="a(sssssxaa{sv}b)" name="message" direction="out" />
</method>
<method name="ActivateSource">
<arg type="s" name="source_id" direction="in" />
</method>
<method name="ActivateMessage">
<arg type="s" name="message_id" direction="in" />
+ <arg type="s" name="action_id" direction="in" />
+ <arg type="av" name="parameter" direction="in" />
</method>
<method name="Dismiss">
<arg type="as" name="sources" direction="in" />
@@ -28,7 +30,7 @@
<arg type="s" name="source_id" direction="in" />
</signal>
<signal name="MessageAdded">
- <arg type="(sssssxb)" name="message" direction="in" />
+ <arg type="(sssssxaa{sv}b)" name="message" direction="in" />
</signal>
<signal name="MessageRemoved">
<arg type="s" name="message_id" direction="in" />
diff --git a/debian/libmessaging-menu0.symbols b/debian/libmessaging-menu0.symbols
index 05ea967..4303327 100644
--- a/debian/libmessaging-menu0.symbols
+++ b/debian/libmessaging-menu0.symbols
@@ -24,6 +24,7 @@ libmessaging-menu.so.0 libmessaging-menu0 #MINVER#
messaging_menu_app_set_source_time@Base 12.10.0
messaging_menu_app_set_status@Base 12.10.0
messaging_menu_app_unregister@Base 12.10.0
+ messaging_menu_message_add_action@Base 12.10.6-0ubuntu1phablet3
messaging_menu_message_get_body@Base 12.10.6-0ubuntu1phablet1
messaging_menu_message_get_draws_attention@Base 12.10.6-0ubuntu1phablet1
messaging_menu_message_get_icon@Base 12.10.6-0ubuntu1phablet1
diff --git a/libmessaging-menu/messaging-menu-app.c b/libmessaging-menu/messaging-menu-app.c
index d037da9..7e61324 100644
--- a/libmessaging-menu/messaging-menu-app.c
+++ b/libmessaging-menu/messaging-menu-app.c
@@ -126,7 +126,6 @@ enum {
enum {
ACTIVATE_SOURCE,
- ACTIVATE_MESSAGE,
STATUS_CHANGED,
N_SIGNALS
};
@@ -152,6 +151,9 @@ static void global_status_changed (IndicatorMessagesService *service,
const gchar *status_str,
gpointer user_data);
+/* in messaging-menu-message.c */
+GVariant * _messaging_menu_message_to_variant (MessagingMenuMessage *msg);
+
static void
source_free (gpointer data)
{
@@ -188,29 +190,6 @@ source_to_variant (Source *source)
return v;
}
-static GVariant *
-messaging_menu_message_to_variant (MessagingMenuMessage *message)
-{
- GVariant *v;
- GIcon *icon;
- gchar *iconstr;
-
- icon = messaging_menu_message_get_icon (message);
- iconstr = icon ? g_icon_to_string (icon) : NULL;
-
- v = g_variant_new ("(sssssxb)", messaging_menu_message_get_id (message),
- iconstr ? iconstr : "",
- messaging_menu_message_get_title (message),
- messaging_menu_message_get_subtitle (message),
- messaging_menu_message_get_body (message),
- messaging_menu_message_get_time (message),
- messaging_menu_message_get_draws_attention (message));
-
- g_free (iconstr);
-
- return v;
-}
-
static gchar *
messaging_menu_app_get_dbus_object_path (MessagingMenuApp *app)
{
@@ -386,27 +365,6 @@ messaging_menu_app_class_init (MessagingMenuAppClass *class)
G_TYPE_NONE, 1, G_TYPE_STRING);
/**
- * MessagingMenuApp::activate-message:
- * @mmapp: the #MessagingMenuApp
- * @message: the activated #MessagingMenuMessage
- *
- * Emitted when the user has activated a message. The message is
- * immediately removed from the application's menu, handlers of this
- * signal do not need to call messaging_menu_app_remove_message().
- *
- * To get notified about the activation of a specific message, set the
- * signal's detail to the message id.
- */
- signals[ACTIVATE_MESSAGE] = g_signal_new ("activate-message",
- MESSAGING_MENU_TYPE_APP,
- G_SIGNAL_RUN_FIRST |
- G_SIGNAL_DETAILED,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, MESSAGING_MENU_TYPE_MESSAGE);
-
- /**
* MessagingMenuApp::status-changed:
* @mmapp: the #MessagingMenuApp
* @status: a #MessagingMenuStatus
@@ -571,11 +529,11 @@ messaging_menu_app_list_messages (IndicatorMessagesApplication *app_interface,
GHashTableIter iter;
MessagingMenuMessage *message;
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sssssxb)"));
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sssssxaa{sv}b)"));
g_hash_table_iter_init (&iter, app->messages);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &message))
- g_variant_builder_add_value (&builder, messaging_menu_message_to_variant (message));
+ g_variant_builder_add_value (&builder, _messaging_menu_message_to_variant (message));
indicator_messages_application_complete_list_messages (app_interface,
invocation,
@@ -588,6 +546,8 @@ static gboolean
messaging_menu_app_activate_message (IndicatorMessagesApplication *app_interface,
GDBusMethodInvocation *invocation,
const gchar *message_id,
+ const gchar *action_id,
+ GVariant *params,
gpointer user_data)
{
MessagingMenuApp *app = user_data;
@@ -596,7 +556,26 @@ messaging_menu_app_activate_message (IndicatorMessagesApplication *app_interface
msg = g_hash_table_lookup (app->messages, message_id);
if (msg)
{
- g_signal_emit (app, signals[ACTIVATE_MESSAGE], g_quark_from_string (message_id), msg);
+ if (*action_id)
+ {
+ gchar *signal;
+
+ signal = g_strconcat ("activate::", action_id, NULL);
+
+ if (g_variant_n_children (params))
+ {
+ GVariant *param = g_variant_get_child_value (params, 0);
+ g_signal_emit_by_name (msg, signal, action_id, param);
+ g_variant_unref (param);
+ }
+ else
+ g_signal_emit_by_name (msg, signal, action_id, NULL);
+
+ g_free (signal);
+ }
+ else
+ g_signal_emit_by_name (msg, "activate", NULL, NULL);
+
/* Activate implies removing the message, no need for MessageRemoved */
messaging_menu_app_remove_message_internal (app, message_id);
@@ -1368,7 +1347,7 @@ messaging_menu_app_append_message (MessagingMenuApp *app,
g_hash_table_insert (app->messages, g_strdup (id), g_object_ref (msg));
indicator_messages_application_emit_message_added (app->app_interface,
- messaging_menu_message_to_variant (msg));
+ _messaging_menu_message_to_variant (msg));
if (source_id)
{
diff --git a/libmessaging-menu/messaging-menu-message.c b/libmessaging-menu/messaging-menu-message.c
index f5cb18c..b81cbea 100644
--- a/libmessaging-menu/messaging-menu-message.c
+++ b/libmessaging-menu/messaging-menu-message.c
@@ -32,6 +32,8 @@ struct _MessagingMenuMessage
gchar *body;
gint64 time;
gboolean draws_attention;
+
+ GSList *actions;
};
G_DEFINE_TYPE (MessagingMenuMessage, messaging_menu_message, G_TYPE_OBJECT);
@@ -51,6 +53,31 @@ enum
static GParamSpec *properties[NUM_PROPERTIES];
+typedef struct
+{
+ gchar *id;
+ gchar *label;
+ GVariantType *parameter_type;
+ GVariant *parameter_hint;
+} Action;
+
+static void
+action_free (gpointer data)
+{
+ Action *action = data;
+
+ g_free (action->id);
+ g_free (action->label);
+
+ if (action->parameter_type)
+ g_variant_type_free (action->parameter_type);
+
+ if (action->parameter_hint)
+ g_variant_unref (action->parameter_hint);
+
+ g_slice_free (Action, action);
+}
+
static void
messaging_menu_message_dispose (GObject *object)
{
@@ -71,6 +98,9 @@ messaging_menu_message_finalize (GObject *object)
g_free (msg->subtitle);
g_free (msg->body);
+ g_slist_free_full (msg->actions, action_free);
+ msg->actions = NULL;
+
G_OBJECT_CLASS (messaging_menu_message_parent_class)->finalize (object);
}
@@ -215,6 +245,26 @@ messaging_menu_message_class_init (MessagingMenuMessageClass *klass)
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (klass, NUM_PROPERTIES, properties);
+
+ /**
+ * MessagingMenuMessage::activate:
+ * @msg: the #MessagingMenuMessage
+ * @action: (allow-none): the id of activated action, or %NULL
+ * @parameter: (allow-none): activation parameter, or %NULL
+ *
+ * Emitted when the user has activated the message. The message is
+ * immediately removed from the application's menu, handlers of this
+ * signal do not need to call messaging_menu_app_remove_message().
+ */
+ g_signal_new ("activate",
+ MESSAGING_MENU_TYPE_MESSAGE,
+ G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE, 2,
+ G_TYPE_STRING,
+ G_TYPE_VARIANT);
}
static void
@@ -370,3 +420,128 @@ messaging_menu_message_set_draws_attention (MessagingMenuMessage *msg,
msg->draws_attention = draws_attention;
g_object_notify_by_pspec (G_OBJECT (msg), properties[PROP_DRAWS_ATTENTION]);
}
+
+/**
+ * messaging_menu_message_add_action:
+ * @msg: a #MessagingMenuMessage
+ * @id: unique id of the action
+ * @label: (allow-none): label of the action
+ * @parameter_type: (allow-none): a #GVariantType
+ * @parameter_hint: (allow-none): a #GVariant suggesting a valid range
+ * for parameters
+ *
+ * Adds an action with @id and @label to @message. Actions are an
+ * alternative way for users to activate a message. Note that messages
+ * can still be activated without an action.
+ *
+ * If @parameter_type is non-%NULL, the action is able to receive user
+ * input in addition to simply activating the action. Currently, only
+ * string parameters are supported.
+ *
+ * A list of predefined parameters can be supplied as a #GVariant array
+ * of @parameter_type in @parameter_hint. If @parameter_hint is
+ * floating, it will be consumed.
+ *
+ * It is recommended to add at most two actions to a message.
+ */
+void
+messaging_menu_message_add_action (MessagingMenuMessage *msg,
+ const gchar *id,
+ const gchar *label,
+ const GVariantType *parameter_type,
+ GVariant *parameter_hint)
+{
+ Action *action;
+
+ g_return_if_fail (MESSAGING_MENU_IS_MESSAGE (msg));
+ g_return_if_fail (id != NULL);
+
+ action = g_slice_new (Action);
+ action->id = g_strdup (id);
+ action->label = g_strdup (label);
+ action->parameter_type = parameter_type ? g_variant_type_copy (parameter_type) : NULL;
+ action->parameter_hint = parameter_hint ? g_variant_ref_sink (parameter_hint) : NULL;
+
+ msg->actions = g_slist_append (msg->actions, action);
+}
+
+static GVariant *
+action_to_variant (Action *action)
+{
+ GVariantBuilder builder;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+
+ g_variant_builder_add (&builder, "{sv}", "name", g_variant_new_string (action->id));
+
+ if (action->label)
+ g_variant_builder_add (&builder, "{sv}", "label", g_variant_new_string (action->label));
+
+ if (action->parameter_type)
+ {
+ gchar *type = g_variant_type_dup_string (action->parameter_type);
+ g_variant_builder_add (&builder, "{sv}", "parameter-type", g_variant_new_signature (type));
+ g_free (type);
+ }
+
+ if (action->parameter_hint)
+ g_variant_builder_add (&builder, "{sv}", "parameter-hint", action->parameter_hint);
+
+ return g_variant_builder_end (&builder);
+}
+
+/*<internal>
+ * _messaging_menu_message_to_variant:
+ * @msg: a #MessagingMenuMessage
+ *
+ * Serializes @msg to a #GVariant of the form (sssssxaa{sv}b):
+ *
+ * id
+ * icon
+ * title
+ * subtitle
+ * body
+ * time
+ * array of action dictionaries
+ * draws_attention
+ *
+ * Returns: a new floating #GVariant instance
+ */
+GVariant *
+_messaging_menu_message_to_variant (MessagingMenuMessage *msg)
+{
+ GVariantBuilder builder;
+ GSList *it;
+
+ g_return_val_if_fail (MESSAGING_MENU_IS_MESSAGE (msg), NULL);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("(sssssxaa{sv}b)"));
+
+ g_variant_builder_add (&builder, "s", msg->id);
+
+ if (msg->icon)
+ {
+ gchar *iconstr;
+
+ iconstr = g_icon_to_string (msg->icon);
+ g_variant_builder_add (&builder, "s", iconstr);
+
+ g_free (iconstr);
+ }
+ else
+ g_variant_builder_add (&builder, "s", "");
+
+ g_variant_builder_add (&builder, "s", msg->title ? msg->title : "");
+ g_variant_builder_add (&builder, "s", msg->subtitle ? msg->subtitle : "");
+ g_variant_builder_add (&builder, "s", msg->body ? msg->body : "");
+ g_variant_builder_add (&builder, "x", msg->time);
+
+ g_variant_builder_open (&builder, G_VARIANT_TYPE ("aa{sv}"));
+ for (it = msg->actions; it; it = it->next)
+ g_variant_builder_add_value (&builder, action_to_variant (it->data));
+ g_variant_builder_close (&builder);
+
+ g_variant_builder_add (&builder, "b", msg->draws_attention);
+
+ return g_variant_builder_end (&builder);
+}
diff --git a/libmessaging-menu/messaging-menu-message.h b/libmessaging-menu/messaging-menu-message.h
index 068247b..4708246 100644
--- a/libmessaging-menu/messaging-menu-message.h
+++ b/libmessaging-menu/messaging-menu-message.h
@@ -59,6 +59,12 @@ gboolean messaging_menu_message_get_draws_attention (MessagingMe
void messaging_menu_message_set_draws_attention (MessagingMenuMessage *msg,
gboolean draws_attention);
+void messaging_menu_message_add_action (MessagingMenuMessage *msg,
+ const gchar *id,
+ const gchar *label,
+ const GVariantType *parameter_type,
+ GVariant *parameter_hint);
+
G_END_DECLS
#endif
diff --git a/src/im-application-list.c b/src/im-application-list.c
index f0bf362..c41c858 100644
--- a/src/im-application-list.c
+++ b/src/im-application-list.c
@@ -59,6 +59,7 @@ typedef struct
GActionMuxer *actions;
GSimpleActionGroup *source_actions;
GSimpleActionGroup *message_actions;
+ GActionMuxer *message_sub_actions;
GCancellable *cancellable;
} Application;
@@ -87,6 +88,7 @@ application_free (gpointer data)
g_object_unref (app->actions);
g_object_unref (app->source_actions);
g_object_unref (app->message_actions);
+ g_object_unref (app->message_sub_actions);
}
g_slice_free (Application, app);
@@ -134,6 +136,7 @@ im_application_list_message_removed (Application *app,
const gchar *id)
{
g_simple_action_group_remove (app->message_actions, id);
+ g_action_muxer_remove (app->message_sub_actions, id);
g_signal_emit (app->list, signals[MESSAGE_REMOVED], 0, app->id, id);
}
@@ -152,6 +155,8 @@ im_application_list_message_activated (GSimpleAction *action,
{
indicator_messages_application_call_activate_message (app->proxy,
message_id,
+ "",
+ g_variant_new_array (G_VARIANT_TYPE_VARIANT, NULL, 0),
app->cancellable,
NULL, NULL);
}
@@ -167,6 +172,34 @@ im_application_list_message_activated (GSimpleAction *action,
}
static void
+im_application_list_sub_message_activated (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ Application *app = user_data;
+ const gchar *message_id;
+ const gchar *action_id;
+ GVariantBuilder builder;
+
+ message_id = g_object_get_data (G_OBJECT (action), "message");
+ action_id = g_action_get_name (G_ACTION (action));
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
+ if (parameter)
+ g_variant_builder_add (&builder, "v", parameter);
+
+ indicator_messages_application_call_activate_message (app->proxy,
+ message_id,
+ action_id,
+ g_variant_builder_end (&builder),
+ app->cancellable,
+ NULL, NULL);
+
+ im_application_list_message_removed (app, message_id);
+}
+
+
+static void
im_application_list_remove_all (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
@@ -269,7 +302,7 @@ im_application_list_class_init (ImApplicationListClass *klass)
NULL, NULL,
g_cclosure_marshal_generic,
G_TYPE_NONE,
- 9,
+ 10,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_STRING,
@@ -277,6 +310,7 @@ im_application_list_class_init (ImApplicationListClass *klass)
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_STRING,
+ G_TYPE_VARIANT,
G_TYPE_INT64,
G_TYPE_BOOLEAN);
@@ -391,9 +425,11 @@ im_application_list_add (ImApplicationList *list,
app->actions = g_action_muxer_new ();
app->source_actions = g_simple_action_group_new ();
app->message_actions = g_simple_action_group_new ();
+ app->message_sub_actions = g_action_muxer_new ();
g_action_muxer_insert (app->actions, "src", G_ACTION_GROUP (app->source_actions));
g_action_muxer_insert (app->actions, "msg", G_ACTION_GROUP (app->message_actions));
+ g_action_muxer_insert (app->actions, "msg-actions", G_ACTION_GROUP (app->message_sub_actions));
g_hash_table_insert (list->applications, (gpointer) app->id, app);
g_action_muxer_insert (list->muxer, app->id, G_ACTION_GROUP (app->actions));
@@ -509,25 +545,93 @@ im_application_list_message_added (Application *app,
const gchar *subtitle;
const gchar *body;
gint64 time;
+ GVariantIter *action_iter;
gboolean draws_attention;
GSimpleAction *action;
GIcon *app_icon;
gchar *app_iconstr;
+ GVariant *actions = NULL;
- g_variant_get (message, "(&s&s&s&s&sxb)",
- &id, &iconstr, &title, &subtitle, &body, &time, &draws_attention);
+ g_variant_get (message, "(&s&s&s&s&sxaa{sv}b)",
+ &id, &iconstr, &title, &subtitle, &body, &time, &action_iter, &draws_attention);
app_icon = g_app_info_get_icon (G_APP_INFO (app->info));
app_iconstr = app_icon ? g_icon_to_string (app_icon) : NULL;
action = g_simple_action_new (id, G_VARIANT_TYPE_BOOLEAN);
g_signal_connect (action, "activate", G_CALLBACK (im_application_list_message_activated), app);
-
g_simple_action_group_insert (app->message_actions, G_ACTION (action));
+ {
+ GVariant *entry;
+ GSimpleActionGroup *action_group;
+ GVariantBuilder actions_builder;
+
+ g_variant_builder_init (&actions_builder, G_VARIANT_TYPE ("aa{sv}"));
+ action_group = g_simple_action_group_new ();
+
+ while ((entry = g_variant_iter_next_value (action_iter)))
+ {
+ const gchar *name;
+ GSimpleAction *action;
+ GVariant *label;
+ const gchar *type = NULL;
+ GVariant *hint;
+ GVariantBuilder dict_builder;
+ gchar *prefixed_name;
+
+ if (!g_variant_lookup (entry, "name", "&s", &name))
+ {
+ g_warning ("action dictionary for message '%s' is missing 'name' key", id);
+ continue;
+ }
+
+ label = g_variant_lookup_value (entry, "label", G_VARIANT_TYPE_STRING);
+ g_variant_lookup (entry, "parameter-type", "&g", &type);
+ hint = g_variant_lookup_value (entry, "parameter-hint", NULL);
+
+ action = g_simple_action_new (name, type ? G_VARIANT_TYPE (type) : NULL);
+ g_object_set_data_full (G_OBJECT (action), "message", g_strdup (id), g_free);
+ g_signal_connect (action, "activate", G_CALLBACK (im_application_list_sub_message_activated), app);
+ g_simple_action_group_insert (action_group, G_ACTION (action));
+
+ g_variant_builder_init (&dict_builder, G_VARIANT_TYPE ("a{sv}"));
+
+ prefixed_name = g_strjoin (".", app->id, "msg-actions", id, name, NULL);
+ g_variant_builder_add (&dict_builder, "{sv}", "name", g_variant_new_string (prefixed_name));
+
+ if (label)
+ {
+ g_variant_builder_add (&dict_builder, "{sv}", "label", label);
+ g_variant_unref (label);
+ }
+
+ if (type)
+ g_variant_builder_add (&dict_builder, "{sv}", "parameter-type", g_variant_new_string (type));
+
+ if (hint)
+ {
+ g_variant_builder_add (&dict_builder, "{sv}", "parameter-hint", hint);
+ g_variant_unref (hint);
+ }
+
+ g_variant_builder_add (&actions_builder, "a{sv}", &dict_builder);
+
+ g_object_unref (action);
+ g_variant_unref (entry);
+ g_free (prefixed_name);
+ }
+
+ g_action_muxer_insert (app->message_sub_actions, id, G_ACTION_GROUP (action_group));
+ actions = g_variant_builder_end (&actions_builder);
+
+ g_object_unref (action_group);
+ }
+
g_signal_emit (app->list, signals[MESSAGE_ADDED], 0,
- app->id, app_iconstr, id, iconstr, title, subtitle, body, time, draws_attention);
+ app->id, app_iconstr, id, iconstr, title, subtitle, body, actions, time, draws_attention);
+ g_variant_iter_free (action_iter);
g_free (app_iconstr);
g_object_unref (action);
}
@@ -580,10 +684,13 @@ im_application_list_unset_remote (Application *app)
* the muxer */
g_object_unref (app->source_actions);
g_object_unref (app->message_actions);
+ g_object_unref (app->message_sub_actions);
app->source_actions = g_simple_action_group_new ();
app->message_actions = g_simple_action_group_new ();
+ app->message_sub_actions = g_action_muxer_new ();
g_action_muxer_insert (app->actions, "src", G_ACTION_GROUP (app->source_actions));
g_action_muxer_insert (app->actions, "msg", G_ACTION_GROUP (app->message_actions));
+ g_action_muxer_insert (app->actions, "msg-actions", G_ACTION_GROUP (app->message_sub_actions));
if (was_running)
g_signal_emit (app->list, signals[APP_STOPPED], 0, app->id);
diff --git a/src/im-phone-menu.c b/src/im-phone-menu.c
index 728c08b..6e511ac 100644
--- a/src/im-phone-menu.c
+++ b/src/im-phone-menu.c
@@ -151,6 +151,7 @@ im_phone_menu_add_message (ImPhoneMenu *menu,
const gchar *title,
const gchar *subtitle,
const gchar *body,
+ GVariant *actions,
gint64 time)
{
GMenuItem *item;
@@ -162,7 +163,15 @@ im_phone_menu_add_message (ImPhoneMenu *menu,
action_name = g_strconcat (app_id, ".msg.", id, NULL);
item = g_menu_item_new (title, action_name);
- g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.messages.messageitem");
+
+ if (g_variant_n_children (actions))
+ {
+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.messages.snapdecision");
+ g_menu_item_set_attribute (item, "x-canonical-message-actions", "v", actions);
+ }
+ else
+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.messages.messageitem");
+
g_menu_item_set_attribute (item, "x-canonical-message-id", "s", id);
g_menu_item_set_attribute (item, "x-canonical-subtitle", "s", subtitle);
g_menu_item_set_attribute (item, "x-canonical-text", "s", body);
diff --git a/src/im-phone-menu.h b/src/im-phone-menu.h
index f6a6118..84908e2 100644
--- a/src/im-phone-menu.h
+++ b/src/im-phone-menu.h
@@ -45,6 +45,7 @@ void im_phone_menu_add_message (ImPhoneMenu *men
const gchar *title,
const gchar *subtitle,
const gchar *body,
+ GVariant *actions,
gint64 time);
void im_phone_menu_remove_message (ImPhoneMenu *menu,