Awful frontend for "temporary widgets"
This commit is contained in:
parent
76463e836e
commit
eb9a29cec5
7 changed files with 326 additions and 1 deletions
12
src/vector/dummy_widget/index.html
Normal file
12
src/vector/dummy_widget/index.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Dummy Widget</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<button id="demoBtn">Click me to show a temp widget</button>
|
||||||
|
<p>This isn't using the neat theme stuff over the widget API</p>
|
||||||
|
<p id="answer"><!-- populated with js --></p>
|
||||||
|
</body>
|
||||||
|
</html>
|
50
src/vector/dummy_widget/index.scss
Normal file
50
src/vector/dummy_widget/index.scss
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 New Vector Ltd.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: Match the user's theme: https://github.com/vector-im/riot-web/issues/12794
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Nunito';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
src: url('~matrix-react-sdk/res/fonts/Nunito/Nunito-Regular.ttf') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: Nunito, Arial, Helvetica, sans-serif;
|
||||||
|
background-color: #181b21;
|
||||||
|
color: #edf3ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
body, html {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
// A mix of AccessibleButton styles
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 7px 18px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: #03b381;
|
||||||
|
border: 0;
|
||||||
|
}
|
54
src/vector/dummy_widget/index.ts
Normal file
54
src/vector/dummy_widget/index.ts
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 New Vector Ltd.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// We have to trick webpack into loading our CSS for us.
|
||||||
|
require("./index.scss");
|
||||||
|
|
||||||
|
import * as qs from 'querystring';
|
||||||
|
import { Capability, KnownWidgetActions, WidgetApi } from 'matrix-react-sdk/src/widgets/WidgetApi';
|
||||||
|
|
||||||
|
let widgetApi: WidgetApi;
|
||||||
|
(async function() {
|
||||||
|
try {
|
||||||
|
// The widget's options are encoded into the fragment to avoid leaking info to the server. The widget
|
||||||
|
// spec on the other hand requires the widgetId and parentUrl to show up in the regular query string.
|
||||||
|
const widgetQuery = qs.parse(window.location.hash.substring(1));
|
||||||
|
const query = Object.assign({}, qs.parse(window.location.search.substring(1)), widgetQuery);
|
||||||
|
const qsParam = (name: string, optional = false): string => {
|
||||||
|
if (!optional && (!query[name] || typeof (query[name]) !== 'string')) {
|
||||||
|
throw new Error(`Expected singular ${name} in query string`);
|
||||||
|
}
|
||||||
|
return <string>query[name];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set this up as early as possible because Element will be hitting it almost immediately.
|
||||||
|
widgetApi = new WidgetApi(qsParam('parentUrl'), qsParam('widgetId'), []);
|
||||||
|
|
||||||
|
widgetApi.on(KnownWidgetActions.ClosedWidgetResponse, req => {
|
||||||
|
document.getElementById("answer").innerText = "RESPONSE FROM TEMP WIDGET: " + JSON.stringify(req.data);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById("demoBtn").onclick = () => {
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
url.pathname = "/theme_widget.html";
|
||||||
|
url.search = "";
|
||||||
|
widgetApi.openTempWidget(url.toString(), {question: "Answer to everything?"});
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Error setting up Jitsi widget", e);
|
||||||
|
document.getElementById("widgetActionContainer").innerText = "Failed to load Jitsi widget";
|
||||||
|
}
|
||||||
|
})();
|
25
src/vector/theme_widget/index.html
Normal file
25
src/vector/theme_widget/index.html
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Theme Widget</title>
|
||||||
|
</head>
|
||||||
|
<body class="client-element-web">
|
||||||
|
<h1>Example Theme Widget</h1>
|
||||||
|
<div>
|
||||||
|
<h2>Button Decorations</h2>
|
||||||
|
<button type="button" class="primary">Primary</button>
|
||||||
|
<button type="button" class="danger">Danger</button>
|
||||||
|
<button type="button" class="cancel">Cancel</button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h2>Actual Dialog Controls (closes the dialog)</h2>
|
||||||
|
<button type="button" id="closeButton">Close</button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h2>Metadata</h2>
|
||||||
|
<p id="question"><!-- populated with js --></p>
|
||||||
|
<p id="theme"><!-- populated with js --></p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
103
src/vector/theme_widget/index.scss
Normal file
103
src/vector/theme_widget/index.scss
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 New Vector Ltd.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: Match the user's theme: https://github.com/vector-im/riot-web/issues/12794
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'Inter';
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
font-display: swap;
|
||||||
|
unicode-range: U+0000-20e2,U+20e4-23ce,U+23d0-24c1,U+24c3-259f,U+25c2-2664,U+2666-2763,U+2765-2b05,U+2b07-2b1b,U+2b1d-10FFFF;
|
||||||
|
src: url("~matrix-react-sdk/res/fonts/Inter/Inter-Regular.woff2?v=3.13") format("woff2"),
|
||||||
|
url("~matrix-react-sdk/res/fonts/Inter/Inter-Regular.woff?v=3.13") format("woff");
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: Inter, Arial, Helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
body, html {
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.client-element-web {
|
||||||
|
&.is-dark {
|
||||||
|
background-color: #181b21;
|
||||||
|
color: #edf3ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.is-dark) {
|
||||||
|
background-color: #edf3ff;
|
||||||
|
color: #181b21;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 7px 18px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: var(--accent-color, #03b381);
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.danger {
|
||||||
|
background-color: #ff4b55;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.cancel {
|
||||||
|
background-color: transparent;
|
||||||
|
color: #03b381;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
body.client-element-android {
|
||||||
|
&.is-dark {
|
||||||
|
background-color: #062600;
|
||||||
|
color: #c6ffc6;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.is-dark) {
|
||||||
|
background-color: #c6ffc6;
|
||||||
|
color: #181b21;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 12px 24px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 12px;
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ffffff;
|
||||||
|
background-color: var(--accent-color, #03b381);
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.danger {
|
||||||
|
background-color: #ff4b55;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.cancel {
|
||||||
|
background-color: transparent;
|
||||||
|
color: var(--accent-color, #03b381);
|
||||||
|
}
|
||||||
|
}
|
63
src/vector/theme_widget/index.ts
Normal file
63
src/vector/theme_widget/index.ts
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 New Vector Ltd.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// We have to trick webpack into loading our CSS for us.
|
||||||
|
require("./index.scss");
|
||||||
|
|
||||||
|
import * as qs from 'querystring';
|
||||||
|
import { KnownWidgetActions, WidgetApi } from 'matrix-react-sdk/src/widgets/WidgetApi';
|
||||||
|
|
||||||
|
let widgetApi: WidgetApi;
|
||||||
|
(async function() {
|
||||||
|
try {
|
||||||
|
// The widget's options are encoded into the fragment to avoid leaking info to the server. The widget
|
||||||
|
// spec on the other hand requires the widgetId and parentUrl to show up in the regular query string.
|
||||||
|
const widgetQuery = qs.parse(window.location.hash.substring(1));
|
||||||
|
const query = Object.assign({}, qs.parse(window.location.search.substring(1)), widgetQuery);
|
||||||
|
const qsParam = (name: string, optional = false): string => {
|
||||||
|
if (!optional && (!query[name] || typeof (query[name]) !== 'string')) {
|
||||||
|
throw new Error(`Expected singular ${name} in query string`);
|
||||||
|
}
|
||||||
|
return <string>query[name];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Set this up as early as possible because Element will be hitting it almost immediately.
|
||||||
|
widgetApi = new WidgetApi(qsParam('parentUrl'), qsParam('widgetId'), []);
|
||||||
|
|
||||||
|
widgetApi.on(KnownWidgetActions.UpdateThemeInfo, (themeInfo) => {
|
||||||
|
console.log("Got theme info: ", themeInfo);
|
||||||
|
document.getElementById("theme").innerText = "THEME: " + JSON.stringify(themeInfo.data);
|
||||||
|
|
||||||
|
const clientName = themeInfo.data.clientName || "element-web";
|
||||||
|
const isDark = themeInfo.data.isDark || false;
|
||||||
|
const accentColour = themeInfo.data.accentColor || "#03b381";
|
||||||
|
|
||||||
|
document.body.className = `client-${clientName} ${isDark ? 'is-dark' : ''}`;
|
||||||
|
document.body.style.setProperty("--accent-color", accentColour);
|
||||||
|
});
|
||||||
|
widgetApi.on(KnownWidgetActions.SendWidgetConfig, (config) => {
|
||||||
|
console.log("Got widget config: ", config);
|
||||||
|
document.getElementById("question").innerText = "INIT PARAMS: " + JSON.stringify(config.data);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById("closeButton").onclick = () => {
|
||||||
|
widgetApi.closeWidget({answer: 42});
|
||||||
|
};
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Error setting up Jitsi widget", e);
|
||||||
|
document.getElementById("widgetActionContainer").innerText = "Failed to load Jitsi widget";
|
||||||
|
}
|
||||||
|
})();
|
|
@ -39,6 +39,8 @@ module.exports = (env, argv) => {
|
||||||
"indexeddb-worker": "./src/vector/indexeddb-worker.js",
|
"indexeddb-worker": "./src/vector/indexeddb-worker.js",
|
||||||
"mobileguide": "./src/vector/mobile_guide/index.js",
|
"mobileguide": "./src/vector/mobile_guide/index.js",
|
||||||
"jitsi": "./src/vector/jitsi/index.ts",
|
"jitsi": "./src/vector/jitsi/index.ts",
|
||||||
|
"theme_widget": "./src/vector/theme_widget/index.ts",
|
||||||
|
"dummy_widget": "./src/vector/dummy_widget/index.ts",
|
||||||
"usercontent": "./node_modules/matrix-react-sdk/src/usercontent/index.js",
|
"usercontent": "./node_modules/matrix-react-sdk/src/usercontent/index.js",
|
||||||
|
|
||||||
// CSS themes
|
// CSS themes
|
||||||
|
@ -312,7 +314,7 @@ module.exports = (env, argv) => {
|
||||||
// HtmlWebpackPlugin will screw up our formatting like the names
|
// HtmlWebpackPlugin will screw up our formatting like the names
|
||||||
// of the themes and which chunks we actually care about.
|
// of the themes and which chunks we actually care about.
|
||||||
inject: false,
|
inject: false,
|
||||||
excludeChunks: ['mobileguide', 'usercontent', 'jitsi'],
|
excludeChunks: ['mobileguide', 'usercontent', 'jitsi', 'theme_widget', 'dummy_widget'],
|
||||||
minify: argv.mode === 'production',
|
minify: argv.mode === 'production',
|
||||||
vars: {
|
vars: {
|
||||||
og_image_url: og_image_url,
|
og_image_url: og_image_url,
|
||||||
|
@ -327,6 +329,22 @@ module.exports = (env, argv) => {
|
||||||
chunks: ['jitsi'],
|
chunks: ['jitsi'],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
// This is the theme_widget wrapper (embedded, so isolated stack)
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
template: './src/vector/theme_widget/index.html',
|
||||||
|
filename: 'theme_widget.html',
|
||||||
|
minify: argv.mode === 'production',
|
||||||
|
chunks: ['theme_widget'],
|
||||||
|
}),
|
||||||
|
|
||||||
|
// This is the dummy_widget wrapper (embedded, so isolated stack)
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
template: './src/vector/dummy_widget/index.html',
|
||||||
|
filename: 'dummy_widget.html',
|
||||||
|
minify: argv.mode === 'production',
|
||||||
|
chunks: ['dummy_widget'],
|
||||||
|
}),
|
||||||
|
|
||||||
// This is the mobile guide's entry point (separate for faster mobile loading)
|
// This is the mobile guide's entry point (separate for faster mobile loading)
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
template: './src/vector/mobile_guide/index.html',
|
template: './src/vector/mobile_guide/index.html',
|
||||||
|
|
Loading…
Add table
Reference in a new issue