1 module dls.protocol.messages.window;
2 
3 import dls.protocol.interfaces : MessageActionItem;
4 
5 void showMessageRequest(string id, MessageActionItem item)
6 {
7     import dls.tools.tools : Tools;
8     import dls.util.uri : Uri;
9     import std.concurrency : locate, receiveOnly, send;
10     import std.path : dirName;
11     import std.process : browse;
12 
13     while (!(id in Util.messageRequestInfo))
14     {
15         auto data = receiveOnly!(Util.ThreadMessageData)();
16         Util.addMessageRequestType(data[0], data[1], data[2]);
17     }
18 
19     final switch (Util.messageRequestInfo[id][0])
20     {
21     case Util.ShowMessageRequestType.upgradeSelections:
22         if (item.title.length > 0)
23         {
24             auto uri = new Uri(Util.messageRequestInfo[id][1]);
25             Tools.symbolTool.upgradeSelections(uri);
26         }
27 
28         break;
29 
30     case Util.ShowMessageRequestType.upgradeDls:
31         send(locate(Util.messageRequestInfo[id][1]), item.title.length > 0);
32         break;
33 
34     case Util.ShowMessageRequestType.showChangelog:
35         if (item.title.length > 0)
36         {
37             browse(Util.messageRequestInfo[id][1]);
38         }
39 
40         break;
41     }
42 
43     Util.messageRequestInfo.remove(id);
44 }
45 
46 abstract class Util
47 {
48     import dls.protocol.interfaces : MessageType;
49     import dls.protocol.jsonrpc : send;
50     import std.array : array, replace;
51     import std.algorithm : map;
52     import std.conv : to;
53     import std.json : JSONValue, parseJSON;
54     import std.typecons : Tuple, tuple;
55 
56     static enum ShowMessageType
57     {
58         dlsBuildError = "dlsBuildError",
59         dlsLinkError = "dlsLinkError"
60     }
61 
62     static enum ShowMessageRequestType
63     {
64         upgradeSelections = "upgradeSelections",
65         upgradeDls = "upgradeDls",
66         showChangelog = "showChangelog"
67     }
68 
69     shared alias ThreadMessageData = Tuple!(string, ShowMessageRequestType, string);
70 
71     private enum translationsJson = import("translations.json");
72     private static JSONValue translations;
73     private static string locale;
74     private static Tuple!(ShowMessageRequestType, string)[string] messageRequestInfo;
75 
76     static this()
77     {
78         translations = parseJSON(translationsJson);
79         locale = "en"; // TODO: add more locales and auto-detect system locale
80     }
81 
82     static void sendMessage(ShowMessageType which, string[] args = [])
83     {
84         import dls.protocol.interfaces : ShowMessageParams;
85 
86         JSONValue tr = translations[which];
87         auto title = tr["title"][locale].str;
88 
89         foreach (i; 0 .. args.length)
90         {
91             title = title.replace('$' ~ i.to!string, args[i]);
92         }
93 
94         send("window/showMessage",
95                 new ShowMessageParams(tr["messageType"].integer.to!MessageType, title));
96     }
97 
98     static string sendMessageRequest(ShowMessageRequestType which,
99             string[] args = [], string[] hiddenItems = [])
100     {
101         import dls.protocol.interfaces : ShowMessageRequestParams;
102         import std.algorithm : canFind, filter;
103         import std.typecons : nullable;
104 
105         JSONValue tr = translations[which];
106         auto title = tr["title"][locale].str;
107         auto actions = tr["actions"].array
108             .filter!(a => !hiddenItems.canFind(a["id"].str))
109             .map!(a => new MessageActionItem(a["title"][locale].str));
110 
111         foreach (i; 0 .. args.length)
112         {
113             title = title.replace('$' ~ (i + 1).to!string, args[i]);
114         }
115 
116         return send("window/showMessageRequest", new ShowMessageRequestParams(
117                 tr["messageType"].integer.to!MessageType, title, actions.array.nullable));
118     }
119 
120     static string[] getActions(ShowMessageRequestType which)
121     {
122         return translations[which]["actions"].array.map!(a => a["title"][locale].str).array;
123     }
124 
125     static void addMessageRequestType(string id, ShowMessageRequestType type, string data = null)
126     {
127         messageRequestInfo[id] = tuple(type, data);
128     }
129 }