Changeset View
Changeset View
Standalone View
Standalone View
applets/notifications/package/contents/ui/Jobs.qml
Show First 20 Lines • Show All 55 Lines • ▼ Show 20 Line(s) | 52 | for (var i = 0, len = jobs.count; i < len; ++i) { | |||
---|---|---|---|---|---|
56 | } | 56 | } | ||
57 | } | 57 | } | ||
58 | 58 | | |||
59 | if (!notifications) { | 59 | if (!notifications) { | ||
60 | delete runningJobs[source] | 60 | delete runningJobs[source] | ||
61 | return | 61 | return | ||
62 | } | 62 | } | ||
63 | 63 | | |||
64 | var error = runningJobs[source]["error"] | 64 | var job = runningJobs[source]; | ||
65 | var errorText = runningJobs[source]["errorText"] | 65 | | ||
66 | var error = job.error; | ||||
67 | var errorText = job.errorText; | ||||
66 | 68 | | |||
67 | // 1 = ERR_USER_CANCELED - don't show any notification at all | 69 | // 1 = ERR_USER_CANCELED - don't show any notification at all | ||
68 | if (error == 1) { | 70 | if (error == 1) { | ||
69 | delete runningJobs[source] | 71 | delete runningJobs[source] | ||
70 | return | 72 | return | ||
71 | } | 73 | } | ||
72 | 74 | | |||
73 | var message = runningJobs[source]["label1"] ? runningJobs[source]["label1"] : runningJobs[source]["label0"] | 75 | var message = job.label1 || job.label0 || ""; | ||
74 | var infoMessage = runningJobs[source]["infoMessage"] | 76 | var infoMessage = job.infoMessage; | ||
77 | | ||||
75 | if (!message && !infoMessage) { | 78 | if (!message && !infoMessage) { | ||
76 | delete runningJobs[source] | 79 | delete runningJobs[source] | ||
77 | return | 80 | return | ||
78 | } | 81 | } | ||
79 | 82 | | |||
80 | var summary = infoMessage ? i18nc("the job, which can be anything, has finished", "%1: Finished", infoMessage) : i18n("Job Finished") | 83 | var summary = infoMessage ? i18nc("the job, which can be anything, has finished", "%1: Finished", infoMessage) : i18n("Job Finished") | ||
81 | | ||||
82 | if (error) { | 84 | if (error) { | ||
83 | summary = infoMessage ? i18nc("the job, which can be anything, failed to complete", "%1: Failed", infoMessage) : i18n("Job Failed") | 85 | summary = infoMessage ? i18nc("the job, which can be anything, failed to complete", "%1: Failed", infoMessage) : i18n("Job Failed") | ||
84 | } | 86 | } | ||
85 | 87 | | |||
88 | var body = message; | ||||
89 | var actions = []; | ||||
90 | var urls = []; | ||||
91 | | ||||
92 | if (!error && message && UrlHelper.isUrlValid(message)) { | ||||
93 | var destUrl = job.destUrl; | ||||
94 | | ||||
95 | var filesCount = 0; | ||||
96 | for (var i = 0; i < 3; ++i) { | ||||
97 | var unit = job["totalUnit" + i]; | ||||
98 | var amount = job["totalAmount" + i]; | ||||
99 | if (unit === "files") { | ||||
100 | filesCount = amount; | ||||
101 | break; | ||||
102 | } | ||||
103 | } | ||||
104 | | ||||
105 | // If we can be sure it's a single valid file we can show a thumbnail | ||||
106 | if (filesCount === 1) { | ||||
107 | var url = message; | ||||
108 | | ||||
109 | var displaySource = url; | ||||
110 | | ||||
111 | var dotIndex = url.lastIndexOf("/"); | ||||
112 | if (dotIndex > -1) { | ||||
113 | displaySource = url.substr(dotIndex + 1); | ||||
114 | } | ||||
115 | | ||||
116 | // destUrl is a URL so we want to strip the file:// for beauty | ||||
117 | var displayDestUrl = (destUrl ? destUrl.toString() : ""); | ||||
118 | if (displayDestUrl.indexOf("file:///") === 0) { | ||||
119 | displayDestUrl = displayDestUrl.substr(7); // length of file:// | ||||
120 | } | ||||
anthonyfieroniUnsubmitted Not Done anthonyfieroni: ```
displayDestUrl = destUrl.replace(/^(file:\/{2})/, "")
``` | |||||
All of this is wrong. Removing file:/// leaves something that is neither a correct path nor a correct URL. You want destUrl.toString(QUrl::PreferLocalFile). This code being javascript is no excuse -- move all this to C++ code :-) dfaure: All of this is wrong. Removing file:/// leaves something that is neither a correct path nor a… | |||||
121 | | ||||
122 | if (displayDestUrl) { | ||||
123 | body = i18nc("Copied, moved, or linked file named %1 to folder %2", "%1 to %2", displaySource, displayDestUrl); | ||||
124 | } | ||||
125 | | ||||
126 | // KIO source/destination is pretty URL, so for it to be a proper URL we need to prepend file:// if neccessary | ||||
127 | if (url[0] === "/") { | ||||
128 | url = "file://" + url; | ||||
Nooooooo. If the input is indeed a "path or URL" (urgh, that's never good practice, other than for showing to the user), then the way to turn this into a URL is QUrl::fromUserInput(). dfaure: Nooooooo.
This is broken. Testcase: try a filename with a '#' in it.
If the input is indeed a… | |||||
129 | } | ||||
130 | | ||||
131 | urls.push(url); | ||||
132 | // if there were multiple files, show the dest url instead | ||||
133 | // which is a lot more useful than whatever random file that got processed last | ||||
134 | } else if (filesCount > 1 && destUrl) { | ||||
135 | body = i18ncp("Copied, moved, or linked %1 files to folder %2", "%1 file to %2", "%1 files to %2", filesCount, destUrl); | ||||
136 | | ||||
137 | urls.push(destUrl); | ||||
138 | } else { | ||||
139 | // otherwise use classic "open" button | ||||
140 | actions.push("jobUrl#" + message, i18n("Open...")); | ||||
141 | } | ||||
142 | } | ||||
143 | | ||||
86 | // notification body interprets HTML, so we need to manually escape the name | 144 | // notification body interprets HTML, so we need to manually escape the name | ||
87 | var body = (errorText || message || "").replace(/[&<>]/g, function (tag) { | 145 | body = body.replace(/[&<>]/g, function (tag) { | ||
88 | return { | 146 | return { | ||
89 | '&': '&', | 147 | '&': '&', | ||
90 | '<': '<', | 148 | '<': '<', | ||
91 | '>': '>' | 149 | '>': '>' | ||
92 | }[tag] || tag | 150 | }[tag] || tag | ||
93 | }); | 151 | }); | ||
94 | 152 | | |||
95 | var op = { | 153 | var op = { | ||
96 | appIcon: runningJobs[source].appIconName, | 154 | appIcon: runningJobs[source].appIconName, | ||
97 | appName: runningJobs[source].appName, | 155 | appName: runningJobs[source].appName, | ||
98 | summary: summary, | 156 | summary: summary, | ||
99 | body: body, | 157 | body: body, | ||
100 | isPersistent: !!error, // we'll assume success to be the note-unworthy default, only be persistent in error case | 158 | isPersistent: !!error, // we'll assume success to be the note-unworthy default, only be persistent in error case | ||
101 | urgency: 0, | 159 | urgency: 0, | ||
102 | configurable: false, | 160 | configurable: false, | ||
103 | skipGrouping: true, // Bug 360156 | 161 | skipGrouping: true, // Bug 360156 | ||
104 | actions: !error && UrlHelper.isUrlValid(message) ? ["jobUrl#" + message, i18n("Open...")] : [] | 162 | // If the actionId contains "jobUrl#", it tries to open the "id" value (which is "message") | ||
105 | }; // If the actionId contains "jobUrl#", it tries to open the "id" value (which is "message") | 163 | actions: actions, | ||
164 | urls: urls | ||||
165 | }; | ||||
106 | 166 | | |||
107 | notifications.createNotification(op); | 167 | notifications.createNotification(op); | ||
108 | 168 | | |||
109 | delete runningJobs[source] | 169 | delete runningJobs[source] | ||
110 | } | 170 | } | ||
111 | 171 | | |||
112 | onNewData: { | 172 | onNewData: { | ||
113 | runningJobs[sourceName] = data | 173 | runningJobs[sourceName] = data | ||
▲ Show 20 Lines • Show All 57 Lines • Show Last 20 Lines |