Add support for adaptive Windows 10 notifications
This commit is contained in:
parent
c40775b7da
commit
359dcbf70c
|
@ -6,9 +6,22 @@ using Xmpp;
|
|||
|
||||
namespace Dino.Plugins.WindowsNotification {
|
||||
private delegate void NodeFunction(StanzaNode node);
|
||||
|
||||
public enum ActivationType {
|
||||
Foreground,
|
||||
Background
|
||||
}
|
||||
|
||||
public enum Scenario {
|
||||
Basic,
|
||||
IncomingCall
|
||||
}
|
||||
|
||||
private class Button {
|
||||
public string title;
|
||||
public string arguments;
|
||||
public string imageUri;
|
||||
public ActivationType activationType;
|
||||
}
|
||||
|
||||
public class ToastNotificationBuilder {
|
||||
|
@ -16,13 +29,15 @@ namespace Dino.Plugins.WindowsNotification {
|
|||
private Gee.List<Button> _buttons = new Gee.ArrayList<Button>();
|
||||
private string _header = null;
|
||||
private string _body = null;
|
||||
private string _imagePath = null;
|
||||
private string _appLogo = null;
|
||||
private string _inlineImage = null;
|
||||
private Scenario _scenario = Scenario.Basic;
|
||||
|
||||
public ToastNotificationBuilder() {
|
||||
}
|
||||
|
||||
public ToastNotificationBuilder AddButton(string title, string arguments) {
|
||||
_buttons.add(new Button() { title = title, arguments = arguments });
|
||||
public ToastNotificationBuilder AddButton(string title, string arguments, string? imageUri = null, ActivationType activationType = ActivationType.Foreground) {
|
||||
_buttons.add(new Button() { title = title, arguments = arguments, imageUri = imageUri, activationType = activationType });
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -36,73 +51,26 @@ namespace Dino.Plugins.WindowsNotification {
|
|||
return this;
|
||||
}
|
||||
|
||||
public ToastNotificationBuilder SetImage(string image_path) {
|
||||
_imagePath = image_path;
|
||||
public ToastNotificationBuilder SetAppLogo(string applogo_path) {
|
||||
_appLogo = applogo_path;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ToastNotificationBuilder SetScenario(Scenario scenario) {
|
||||
_scenario = scenario;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ToastNotificationBuilder SetInlineImage(string image_path) {
|
||||
_inlineImage = image_path;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Legacy templates, for both Windows 8.1 and Windows 10:
|
||||
// https://docs.microsoft.com/en-us/previous-versions/windows/apps/hh761494(v=win.10)
|
||||
// Eventually modern adaptive templates might be desired:
|
||||
// https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/adaptive-interactive-toasts?tabs=builder-syntax
|
||||
public async ToastNotification Build() {
|
||||
ToastTemplateType templateType = _header != null ? ToastTemplateType.ToastText02 : ToastTemplateType.ToastText01;
|
||||
if (_imagePath != null) {
|
||||
if (templateType == ToastTemplateType.ToastText02) {
|
||||
templateType = ToastTemplateType.ToastImageAndText02;
|
||||
} else {
|
||||
templateType = ToastTemplateType.ToastImageAndText01;
|
||||
if (!_supportsModernFeatures) {
|
||||
return yield BuildFromLegacyTemplate();
|
||||
}
|
||||
}
|
||||
|
||||
var template = yield BuildStanzaFromXml(ToastNotificationManager.GetTemplateContent(templateType));
|
||||
{ // add header and body
|
||||
var attributes = new Gee.ArrayList<StanzaAttribute>();
|
||||
attributes.add(new StanzaAttribute.build("", "id", "1"));
|
||||
attributes.add(new StanzaAttribute.build("", "id", "2"));
|
||||
|
||||
var nodes = FindRecursive(template, "text", attributes);
|
||||
foreach (var node in nodes) {
|
||||
var attr = node.get_attribute_raw("id", "");
|
||||
if (attr != null) {
|
||||
if (attr.val == "1") {
|
||||
if (templateType == ToastTemplateType.ToastText02 || templateType == ToastTemplateType.ToastImageAndText02) {
|
||||
node.put_node(new StanzaNode.text(_header));
|
||||
} else {
|
||||
node.put_node(new StanzaNode.text(_body));
|
||||
}
|
||||
} else if (attr.val == "2") {
|
||||
node.put_node(new StanzaNode.text(_body));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{ // add image
|
||||
var nodes = FindRecursive(template, "image", null);
|
||||
foreach (var node in nodes) {
|
||||
var attr = node.get_attribute_raw("src", "");
|
||||
if (attr != null) {
|
||||
attr.val = _imagePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_supportsModernFeatures && _buttons.size > 0) { // allow buttons
|
||||
var actions = new StanzaNode.build("actions", "", null, null);
|
||||
foreach (var button in _buttons) {
|
||||
var attributes = new Gee.ArrayList<StanzaAttribute>();
|
||||
attributes.add(new StanzaAttribute.build("", "content", button.title));
|
||||
attributes.add(new StanzaAttribute.build("", "arguments", button.arguments));
|
||||
|
||||
var action = new StanzaNode.build("action", "", null, attributes);
|
||||
actions.get_all_subnodes().add(action);
|
||||
}
|
||||
template.get_all_subnodes().add(actions);
|
||||
}
|
||||
|
||||
var xml = ToXml(template);
|
||||
return new ToastNotification(xml);
|
||||
return BuildWithToastGeneric();
|
||||
}
|
||||
|
||||
private async StanzaNode BuildStanzaFromXml(string xml) {
|
||||
|
@ -158,5 +126,115 @@ namespace Dino.Plugins.WindowsNotification {
|
|||
ExecuteOnAllSubNodes(node, func);
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy templates, works on both Windows 8.1 and Windows 10:
|
||||
// https://docs.microsoft.com/en-us/previous-versions/windows/apps/hh761494(v=win.10)
|
||||
private async ToastNotification BuildFromLegacyTemplate() {
|
||||
ToastTemplateType templateType = _header != null ? ToastTemplateType.ToastText02 : ToastTemplateType.ToastText01;
|
||||
if (_appLogo != null) {
|
||||
if (templateType == ToastTemplateType.ToastText02) {
|
||||
templateType = ToastTemplateType.ToastImageAndText02;
|
||||
} else {
|
||||
templateType = ToastTemplateType.ToastImageAndText01;
|
||||
}
|
||||
}
|
||||
|
||||
var template = yield BuildStanzaFromXml(ToastNotificationManager.GetTemplateContent(templateType));
|
||||
{ // add header and body
|
||||
var attributes = new Gee.ArrayList<StanzaAttribute>();
|
||||
attributes.add(new StanzaAttribute.build("", "id", "1"));
|
||||
attributes.add(new StanzaAttribute.build("", "id", "2"));
|
||||
|
||||
var nodes = FindRecursive(template, "text", attributes);
|
||||
foreach (var node in nodes) {
|
||||
var attr = node.get_attribute_raw("id", "");
|
||||
if (attr != null) {
|
||||
if (attr.val == "1") {
|
||||
if (templateType == ToastTemplateType.ToastText02 || templateType == ToastTemplateType.ToastImageAndText02) {
|
||||
node.put_node(new StanzaNode.text(_header));
|
||||
} else {
|
||||
node.put_node(new StanzaNode.text(_body));
|
||||
}
|
||||
} else if (attr.val == "2") {
|
||||
node.put_node(new StanzaNode.text(_body));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{ // add image
|
||||
var nodes = FindRecursive(template, "image", null);
|
||||
foreach (var node in nodes) {
|
||||
var attr = node.get_attribute_raw("src", "");
|
||||
if (attr != null) {
|
||||
attr.val = _appLogo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var xml = ToXml(template);
|
||||
return new ToastNotification(xml);
|
||||
}
|
||||
|
||||
// Modern adaptive templates for Windows 10:
|
||||
// https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/adaptive-interactive-toasts?tabs=builder-syntax
|
||||
private ToastNotification BuildWithToastGeneric() {
|
||||
var toast = new StanzaNode.build("toast", "");
|
||||
if (_scenario == Scenario.IncomingCall) {
|
||||
toast.put_attribute("scenario", "incomingCall");
|
||||
}
|
||||
|
||||
{ // add content
|
||||
var visual = new StanzaNode.build("visual", "");
|
||||
{
|
||||
var binding = new StanzaNode.build("binding", "");
|
||||
binding.put_attribute("template", "ToastGeneric");
|
||||
|
||||
if (_header != null) {
|
||||
var header = new StanzaNode.build("text", "");
|
||||
header.put_node(new StanzaNode.text(_header));
|
||||
binding.put_node(header);
|
||||
}
|
||||
|
||||
if (_body != null) {
|
||||
var body = new StanzaNode.build("text", "");
|
||||
body.put_node(new StanzaNode.text(_body));
|
||||
binding.put_node(body);
|
||||
}
|
||||
|
||||
if (_appLogo != null) {
|
||||
var appLogo = new StanzaNode.build("image", "");
|
||||
appLogo.put_attribute("placement", "appLogoOverride");
|
||||
appLogo.put_attribute("src", _appLogo);
|
||||
binding.put_node(appLogo);
|
||||
}
|
||||
|
||||
if (_inlineImage != null) {
|
||||
var inlineImage = new StanzaNode.build("image", "");
|
||||
inlineImage.put_attribute("src", _inlineImage);
|
||||
binding.put_node(inlineImage);
|
||||
}
|
||||
|
||||
visual.put_node(binding);
|
||||
}
|
||||
toast.put_node(visual);
|
||||
}
|
||||
|
||||
if (_buttons.size > 0) { // add actions
|
||||
var actions = new StanzaNode.build("actions", "");
|
||||
foreach (var button in _buttons) {
|
||||
var action = new StanzaNode.build("action", "");
|
||||
action.put_attribute("content", button.title);
|
||||
action.put_attribute("arguments", button.arguments);
|
||||
if (button.activationType == ActivationType.Background) {
|
||||
action.put_attribute("activationType", "background");
|
||||
}
|
||||
actions.put_node(action);
|
||||
}
|
||||
toast.put_node(actions);
|
||||
}
|
||||
|
||||
return new ToastNotification(ToXml(toast));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace Dino.Plugins.WindowsNotification {
|
|||
var notification = yield new ToastNotificationBuilder()
|
||||
.SetHeader(summary)
|
||||
.SetBody(body)
|
||||
.SetImage(image_path)
|
||||
.SetAppLogo(image_path)
|
||||
.AddButton(_("Accept"), "accept-subscription")
|
||||
.AddButton(_("Deny"), "deny-subscription")
|
||||
.Build();
|
||||
|
@ -133,7 +133,7 @@ namespace Dino.Plugins.WindowsNotification {
|
|||
var notification = yield new ToastNotificationBuilder()
|
||||
.SetHeader(summary)
|
||||
.SetBody(body)
|
||||
.SetImage(image_path)
|
||||
.SetAppLogo(image_path)
|
||||
.AddButton(_("Accept"), "open-muc-join")
|
||||
.AddButton(_("Deny"), "deny-invite")
|
||||
.Build();
|
||||
|
@ -170,7 +170,7 @@ namespace Dino.Plugins.WindowsNotification {
|
|||
var notification = yield new ToastNotificationBuilder()
|
||||
.SetHeader(summary)
|
||||
.SetBody(body)
|
||||
.SetImage(image_path)
|
||||
.SetAppLogo(image_path)
|
||||
.AddButton(_("Accept"), "accept-voice-request")
|
||||
.AddButton(_("Deny"), "deny-voice-request")
|
||||
.Build();
|
||||
|
@ -204,7 +204,7 @@ namespace Dino.Plugins.WindowsNotification {
|
|||
var notification = yield new ToastNotificationBuilder()
|
||||
.SetHeader(conversation_display_name)
|
||||
.SetBody(body)
|
||||
.SetImage(image_path)
|
||||
.SetAppLogo(image_path)
|
||||
.Build();
|
||||
|
||||
var notification_id = generate_id();
|
||||
|
|
Loading…
Reference in a new issue