Merge pull request #638 from yuya-oc/use-loading-icon
Use a Mattermost animation icon when loading a page in the app
This commit is contained in:
@@ -17,6 +17,8 @@ Release date: TBD
|
||||
[#500](https://github.com/mattermost/desktop/issues/500)
|
||||
- Added the dialog to reopen the application when it quits unexpectedly.
|
||||
[#626](https://github.com/mattermost/desktop/pull/626)
|
||||
- Show animation icon when loading a page.
|
||||
[#490](https://github.com/mattermost/desktop/issues/490)
|
||||
|
||||
#### Windows
|
||||
- Added the feature to open the application via `mattermost://` link.
|
||||
|
BIN
src/assets/loading.gif
Normal file
BIN
src/assets/loading.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
@@ -3,6 +3,7 @@
|
||||
const React = require('react');
|
||||
const PropTypes = require('prop-types');
|
||||
const {Grid, Row, Col} = require('react-bootstrap');
|
||||
const {shell} = require('electron');
|
||||
|
||||
function ErrorView(props) {
|
||||
const classNames = ['container', 'ErrorView'];
|
||||
@@ -12,6 +13,10 @@ function ErrorView(props) {
|
||||
if (props.withTab) {
|
||||
classNames.push('ErrorView-with-tab');
|
||||
}
|
||||
function handleClick(event) {
|
||||
event.preventDefault();
|
||||
shell.openExternal(props.errorInfo.validatedURL);
|
||||
}
|
||||
return (
|
||||
<Grid
|
||||
id={props.id}
|
||||
@@ -39,11 +44,17 @@ function ErrorView(props) {
|
||||
<ul className='ErrorView-bullets' >
|
||||
<li>{'Your computer is connected to the internet.'}</li>
|
||||
<li>{'The Mattermost URL '}
|
||||
<a href={props.errorInfo.validatedURL}>
|
||||
<a
|
||||
onClick={handleClick}
|
||||
href={props.errorInfo.validatedURL}
|
||||
>
|
||||
{props.errorInfo.validatedURL}
|
||||
</a>{' is correct.'}</li>
|
||||
<li>{'You can reach '}
|
||||
<a href={props.errorInfo.validatedURL}>
|
||||
<a
|
||||
onClick={handleClick}
|
||||
href={props.errorInfo.validatedURL}
|
||||
>
|
||||
{props.errorInfo.validatedURL}
|
||||
</a>{' from a browser window.'}</li>
|
||||
</ul>
|
||||
|
@@ -30,7 +30,8 @@ const MattermostView = createReactClass({
|
||||
return {
|
||||
errorInfo: null,
|
||||
isContextMenuAdded: false,
|
||||
reloadTimeoutID: null
|
||||
reloadTimeoutID: null,
|
||||
isLoaded: false
|
||||
};
|
||||
},
|
||||
|
||||
@@ -51,7 +52,8 @@ const MattermostView = createReactClass({
|
||||
}
|
||||
|
||||
self.setState({
|
||||
errorInfo: e
|
||||
errorInfo: e,
|
||||
isLoaded: true
|
||||
});
|
||||
function reload() {
|
||||
window.removeEventListener('online', reload);
|
||||
@@ -115,6 +117,11 @@ const MattermostView = createReactClass({
|
||||
|
||||
webview.addEventListener('ipc-message', (event) => {
|
||||
switch (event.channel) {
|
||||
case 'onGuestInitialized':
|
||||
self.setState({
|
||||
isLoaded: true
|
||||
});
|
||||
break;
|
||||
case 'onUnreadCountChange':
|
||||
var unreadCount = event.args[0];
|
||||
var mentionCount = event.args[1];
|
||||
@@ -161,7 +168,8 @@ const MattermostView = createReactClass({
|
||||
clearTimeout(this.state.reloadTimeoutID);
|
||||
this.setState({
|
||||
errorInfo: null,
|
||||
reloadTimeoutID: null
|
||||
reloadTimeoutID: null,
|
||||
isLoaded: false
|
||||
});
|
||||
var webview = findDOMNode(this.refs.webview);
|
||||
webview.reload();
|
||||
@@ -235,20 +243,31 @@ const MattermostView = createReactClass({
|
||||
if (this.props.withTab) {
|
||||
classNames.push('mattermostView-with-tab');
|
||||
}
|
||||
if (!this.props.active) {
|
||||
if (!this.props.active || this.state.errorInfo) {
|
||||
classNames.push('mattermostView-hidden');
|
||||
}
|
||||
|
||||
const loadingImage = !this.state.errorInfo && this.props.active && !this.state.isLoaded ? (
|
||||
<div className='mattermostView-loadingScreen'>
|
||||
<img
|
||||
className='mattermostView-loadingImage'
|
||||
src='../assets/loading.gif'
|
||||
/>
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
className={classNames.join(' ')}
|
||||
>
|
||||
{ errorView }
|
||||
<webview
|
||||
id={this.props.id}
|
||||
className={classNames.join(' ')}
|
||||
preload={preloadJS}
|
||||
src={this.props.src}
|
||||
ref='webview'
|
||||
/>
|
||||
{ loadingImage }
|
||||
</div>);
|
||||
}
|
||||
});
|
||||
|
@@ -1,4 +1,12 @@
|
||||
.mattermostView {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mattermostView .ErrorView {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.mattermostView webview, .mattermostView .mattermostView-loadingScreen {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
@@ -6,12 +14,27 @@
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
.mattermostView-with-tab {
|
||||
top: 32px;
|
||||
.mattermostView-with-tab webview, .mattermostView-with-tab .mattermostView-loadingScreen {
|
||||
top: 31px;
|
||||
}
|
||||
|
||||
.mattermostView-hidden {
|
||||
.mattermostView-hidden webview {
|
||||
flex: 0 1;
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
.mattermostView-loadingScreen {
|
||||
vertical-align: middle;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.mattermostView-loadingImage {
|
||||
opacity: 0.5;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
}
|
||||
|
@@ -11,6 +11,38 @@ Notification = EnhancedNotification; // eslint-disable-line no-global-assign, no
|
||||
|
||||
Reflect.deleteProperty(global.Buffer); // http://electron.atom.io/docs/tutorial/security/#buffer-global
|
||||
|
||||
function isReactAppInitialized() {
|
||||
const reactRoot = document.querySelector('div[data-reactroot]');
|
||||
if (reactRoot === null) {
|
||||
return false;
|
||||
}
|
||||
return reactRoot.children.length !== 0;
|
||||
}
|
||||
|
||||
function watchReactAppUntilInitialized(callback) {
|
||||
let count = 0;
|
||||
const interval = 500;
|
||||
const timeout = 30000;
|
||||
const timer = setInterval(() => {
|
||||
count += interval;
|
||||
if (isReactAppInitialized() || count >= timeout) { // assumed as webapp has been initialized.
|
||||
clearTimeout(timer);
|
||||
callback();
|
||||
}
|
||||
}, interval);
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
if (document.getElementById('root') === null) {
|
||||
console.log('The guest is not assumed as mattermost-webapp');
|
||||
ipc.sendToHost('onGuestInitialized');
|
||||
return;
|
||||
}
|
||||
watchReactAppUntilInitialized(() => {
|
||||
ipc.sendToHost('onGuestInitialized');
|
||||
});
|
||||
});
|
||||
|
||||
function hasClass(element, className) {
|
||||
var rclass = /[\t\r\n\f]/g;
|
||||
if ((' ' + element.className + ' ').replace(rclass, ' ').indexOf(className) > -1) {
|
||||
|
@@ -77,9 +77,8 @@ describe('browser/index.html', function desc() {
|
||||
isVisible('#mattermostView0').then((visible) => visible.should.be.true).
|
||||
isVisible('#mattermostView1').then((visible) => visible.should.be.false).
|
||||
click('#teamTabItem1').
|
||||
pause(1000).
|
||||
isVisible('#mattermostView1').then((visible) => visible.should.be.true).
|
||||
isVisible('#mattermostView0').then((visible) => visible.should.be.false);
|
||||
waitForVisible('#mattermostView1', 2000).
|
||||
isVisible('#mattermostView0').then((visible) => visible.should.be.false);
|
||||
});
|
||||
|
||||
it('should show error when using incorrect URL', () => {
|
||||
|
Reference in New Issue
Block a user