Fix + update external modal (#1106)

* Update external action modal. Uses Micromodal. Closes #1020

* refactor modal handling to isolate loading in modal component

* modal style cleanup

* Remove log

Co-authored-by: Ginger Wong <omqmail@gmail.com>
This commit is contained in:
Gabe Kangas
2021-06-20 17:23:39 -07:00
committed by GitHub
parent c848c029d5
commit 57674206b2
9 changed files with 341 additions and 194 deletions

View File

@@ -424,9 +424,7 @@ export default class App extends Component {
}
handleKeyPressed(e) {
if (e.code === 'Escape' && this.state.externalAction !== null) {
this.closeExternalActionModal();
} else if (
if (
e.target !== document.getElementById('message-input') &&
e.target !== document.getElementById('username-change-input') &&
e.target !== document.getElementsByClassName('emoji-picker__search')[0] &&
@@ -456,9 +454,8 @@ export default class App extends Component {
}
}
displayExternalAction(index) {
const { configData, username } = this.state;
const action = configData.externalActions[index];
displayExternalAction(action) {
const { username } = this.state;
if (!action) {
return;
}
@@ -475,13 +472,13 @@ export default class App extends Component {
win.focus();
return;
}
action.url = fullUrl;
this.setState({
externalAction: action,
externalAction: {
...action,
url: fullUrl,
},
});
}
closeExternalActionModal() {
this.setState({
externalAction: null,
@@ -558,32 +555,25 @@ export default class App extends Component {
? null
: html` <${VideoPoster} offlineImage=${logo} active=${streamOnline} /> `;
// modal buttons
const externalActionButtons =
externalActions && externalActions.length > 0
? html`<div
id="external-actions-container"
class="flex flex-row align-center"
>
${externalActions.map(
function (action, index) {
return html`<${ExternalActionButton}
onClick=${this.displayExternalAction}
action=${action}
index=${index}
/>`;
}.bind(this)
)}
</div>`
: null;
externalActions &&
html`<div
id="external-actions-container"
class="flex flex-row align-center"
>
${externalActions.map(
function (action) {
return html`<${ExternalActionButton}
onClick=${this.displayExternalAction}
action=${action}
/>`;
}.bind(this)
)}
</div>`;
const externalActionModal = externalAction
? html`<${ExternalActionModal}
title=${this.state.externalAction.description ||
this.state.externalAction.title}
url=${this.state.externalAction.url}
onClose=${this.closeExternalActionModal}
/>`
: null;
// modal component
const externalActionModal = externalAction && html`<${ExternalActionModal} action=${externalAction} onClose=${this.closeExternalActionModal} />`;
return html`
<div

View File

@@ -1,77 +1,79 @@
import { h } from '/js/web_modules/preact.js';
import { h, Component } from '/js/web_modules/preact.js';
import htm from '/js/web_modules/htm.js';
import MicroModal from '/js/web_modules/micromodal/dist/micromodal.min.js';
const html = htm.bind(h);
export default function ExternalActionModal({ url, title, onClose }) {
const loading = 'background:url(/img/loading.gif) center center no-repeat;';
export default class ExternalActionModal extends Component {
constructor(props) {
super(props);
this.state = {
iframeLoaded: false,
};
function loaded() {
document.querySelector('#external-modal-iframe').style = '';
this.setIframeLoaded = this.setIframeLoaded.bind(this);
}
componentDidMount() {
// initalize and display Micromodal on mount
try {
MicroModal.init({
awaitCloseAnimation: false,
awaitOpenAnimation: true, // if using css animations to open the modal. This allows it to wait for the animation to finish before focusing on an element inside the modal.
});
MicroModal.show('external-actions-modal', {
onClose: this.props.onClose,
});
} catch (e) {
console.log("micromodal error: ", e);
}
}
return html`
<div class="fixed inset-0 overflow-y-auto" style="z-index: 9999">
<div
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
>
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div
onClick=${() => onClose()}
class="absolute inset-0 bg-gray-900 bg-opacity-75"
></div>
</div>
setIframeLoaded() {
this.setState({
iframeLoaded: true,
});
}
<!-- This element is to trick the browser into centering the modal contents. -->
<span
class="hidden sm:inline-block sm:align-middle sm:h-screen"
aria-hidden="true"
>&#8203;</span
>
<div
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:align-middle w-screen md:max-w-2xl lg:max-w-2xl"
role="dialog"
aria-modal="true"
aria-labelledby="modal-headline"
>
<div class="bg-white ">
<div
class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex justify-between items-center"
>
<h3 class="font-bold hidden md:block">${title}</h3>
<span class="" onclick=${onClose}>
<svg
class="h-12 w-12 fill-current text-grey hover:text-grey-darkest"
role="button"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
>
<title>Close</title>
<path
d="M14.348 14.849a1.2 1.2 0 0 1-1.697 0L10 11.819l-2.651 3.029a1.2 1.2 0 1 1-1.697-1.697l2.758-3.15-2.759-3.152a1.2 1.2 0 1 1 1.697-1.697L10 8.183l2.651-3.031a1.2 1.2 0 1 1 1.697 1.697l-2.758 3.152 2.758 3.15a1.2 1.2 0 0 1 0 1.698z"
/>
</svg>
</span>
render() {
const { action } = this.props;
const { url, title, description } = action;
const { iframeLoaded } = this.state;
const iframeStyle = iframeLoaded ? null : {
backgroundImage: 'url(/img/loading.gif)',
};
return html`
<div class="modal micromodal-slide" id="external-actions-modal" aria-hidden="true">
<div class="modal__overlay" tabindex="-1" data-micromodal-close>
<div id="modal-container" class="modal__container rounded-md" role="dialog" aria-modal="true" aria-labelledby="modal-1-title">
<header id="modal-header" class="modal__header flex flex-row justify-between items-center bg-gray-300 p-3 rounded-t-md">
<h2 class="modal__title text-indigo-600 font-semibold">
${title || description}
</h2>
<button class="modal__close" aria-label="Close modal" data-micromodal-close></button>
</header>
<div id="modal-content-content" class="modal-content-content">
<div id="modal-content" class="modal__content text-gray-600 rounded-b-md overflow-y-auto overflow-x-hidden">
<iframe
id="external-modal-iframe"
style=${iframeStyle}
class="bg-gray-100 bg-center bg-no-repeat"
width="100%"
allowpaymentrequest="true"
allowfullscreen="false"
sandbox="allow-same-origin allow-scripts allow-popups allow-forms"
src=${url}
onload=${this.setIframeLoaded}
/>
</div>
</div>
<iframe
id="external-modal-iframe"
style=${`${loading}`}
width="100%"
allowpaymentrequest="true"
allowfullscreen="false"
sandbox="allow-same-origin allow-scripts allow-popups allow-forms"
src=${url}
onload=${loaded}
/>
</div>
</div>
</div>
</div>
`;
`;
}
}
export function ExternalActionButton({ index, action, onClick }) {
export function ExternalActionButton({ action, onClick }) {
const { title, icon, color = undefined } = action;
const logo =
icon &&
@@ -79,11 +81,10 @@ export function ExternalActionButton({ index, action, onClick }) {
<span class="external-action-icon"><img src=${icon} alt="" /></span>
`;
const bgcolor = color && { backgroundColor: `${color}` };
const handleClick = () => onClick(index);
const handleClick = () => onClick(action);
return html`
<button
class="external-action-button rounded-sm flex flex-row justify-center items-center overflow-hidden bg-gray-800"
data-index=${index}
onClick=${handleClick}
style=${bgcolor}
>

File diff suppressed because one or more lines are too long

View File

@@ -5,6 +5,7 @@
"@videojs/themes/fantasy/index.css": "./@videojs/themes/fantasy/index.css",
"htm": "./htm.js",
"mark.js/dist/mark.es6.min.js": "./markjs/dist/mark.es6.min.js",
"micromodal/dist/micromodal.min.js": "./micromodal/dist/micromodal.min.js",
"preact": "./preact.js",
"tailwindcss/dist/tailwind.min.css": "./tailwindcss/dist/tailwind.min.css",
"video.js": "./video.js/core.js",

File diff suppressed because one or more lines are too long