Rearrange directories

This commit is contained in:
Yuya Ochiai
2015-12-22 23:29:33 +09:00
parent e7d48d6d0d
commit 1be5077ebe
8 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
@font-face {
font-family: sans-serif;
src: local('Meiryo UI');
}
@font-face {
font-family: monospace;
src: local('MS Gothic');
}

19
src/browser/index.html Normal file
View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>electron-mattermost</title>
<script src="node_modules/react/dist/react.min.js"></script>
<script src="node_modules/react-dom/dist/react-dom.min.js"></script>
<script src="node_modules/react-bootstrap/dist/react-bootstrap.min.js"></script>
<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css">
</head>
<body>
<div id="content"></div>
<script src="build/index.js"></script>
<script src="./index.js"></script>
</body>
</html>

117
src/browser/index.js Normal file
View File

@@ -0,0 +1,117 @@
'use strict';
const electron = require('electron');
const remote = electron.remote;
const osLocale = require('os-locale');
const fs = require('fs');
var url = require('url');
var contextMenu = require('./menus/context');
const settings = require('./common/settings');
var webView = document.getElementById('mainWebview');
try {
var configFile = remote.getGlobal('config-file');
var config = settings.readFileSync(configFile);
if (config.version != settings.version) {
config = settings.upgrade(config);
settings.writeFileSync(configFile, config);
}
if (config.teams[0]) {
webView.setAttribute('src', config.teams[0].url);
}
else {
throw 'URL is not configured';
}
}
catch (e) {
window.location.href = './settings.html';
}
var menu = contextMenu.createDefault();
window.addEventListener('contextmenu', function(e) {
menu.popup(remote.getCurrentWindow());
}, false);
webView.addEventListener('page-title-set', function(e) {
document.title = e.title;
});
// Open external link in default browser.
webView.addEventListener('new-window', function(e) {
var currentURL = url.parse(webView.getURL());
var destURL = url.parse(e.url);
// Open in browserWindow. for exmaple, attached files.
if (currentURL.host === destURL.host) {
window.open(e.url, 'Mattermost');
}
else {
require('shell').openExternal(e.url);
}
});
webView.addEventListener("dom-ready", function() {
// webView.openDevTools();
// Use 'Meiryo UI' and 'MS Gothic' to prevent CJK fonts on Windows(JP).
if (process.platform === 'win32') {
var applyCssFile = function(cssFile) {
fs.readFile(cssFile, 'utf8', function(err, data) {
if (err) {
console.log(err);
return;
}
webView.insertCSS(data);
});
};
osLocale(function(err, locale) {
if (err) {
console.log(err);
return;
}
if (locale === 'ja_JP') {
applyCssFile(__dirname + '/css/jp_fonts.css');
}
});
}
});
// Count unread channels.
var timer = setInterval(function() {
webView.send('retrieveUnreadCount');
}, 1000);
var showUnreadBadge = function(unreadCount) {
switch (process.platform) {
case 'win32':
var window = remote.getCurrentWindow();
if (unreadCount > 0) {
window.setOverlayIcon(__dirname + '/resources/badge.png', 'You have unread channels.');
}
else {
window.setOverlayIcon(null, '');
}
break;
case 'darwin':
if (unreadCount > 0) {
remote.app.dock.setBadge(unreadCount.toString());
}
else {
remote.app.dock.setBadge('');
}
break;
default:
}
}
webView.addEventListener('ipc-message', function(event) {
switch (event.channel) {
case 'retrieveUnreadCount':
var unreadCount = event.args[0];
showUnreadBadge(unreadCount);
break;
}
});

25
src/browser/index.jsx Normal file
View File

@@ -0,0 +1,25 @@
'use strict';
var MainPage = React.createClass({
render: function() {
var style = {
position: 'absolute',
top: 0,
right: 0,
bottom: 0,
left: 0
};
// 'disablewebsecurity' is necessary to display external images.
// However, it allows also CSS/JavaScript.
// So webview should use 'allowDisplayingInsecureContent' as same as BrowserWindow.
return (
<webview style={ style } id="mainWebview" autosize="on" preload="webview/mattermost.js"></webview>
);
}
});
ReactDOM.render(
<MainPage />,
document.getElementById('content')
);

View File

@@ -0,0 +1,30 @@
'use strict';
const remote = require('electron').remote;
const Menu = remote.Menu;
const MenuItem = remote.MenuItem;
var createDefault = function() {
var menu = new Menu();
menu.append(new MenuItem({
label: 'Cut',
role: 'cut'
}));
menu.append(new MenuItem({
label: 'Copy',
role: 'copy'
}));
menu.append(new MenuItem({
label: 'Paste',
role: 'paste'
}));
menu.append(new MenuItem({
label: 'Select All',
role: 'selectall'
}));
return menu;
}
module.exports = {
createDefault: createDefault
};

18
src/browser/settings.html Normal file
View File

@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Settings</title>
<script src="node_modules/react/dist/react.min.js"></script>
<script src="node_modules/react-dom/dist/react-dom.min.js"></script>
<script src="node_modules/react-bootstrap/dist/react-bootstrap.min.js"></script>
<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css">
</head>
<body>
<div id="content"></div>
<script src="build/settings.js"></script>
</body>
</html>

178
src/browser/settings.jsx Normal file
View File

@@ -0,0 +1,178 @@
'use strict';
const remote = require('electron').remote;
const settings = require('./common/settings');
const Grid = ReactBootstrap.Grid;
const Row = ReactBootstrap.Row;
const Col = ReactBootstrap.Col;
const Button = ReactBootstrap.Button;
const ListGroup = ReactBootstrap.ListGroup;
const ListGroupItem = ReactBootstrap.ListGroupItem;
const Glyphicon = ReactBootstrap.Glyphicon;
var SettingsPage = React.createClass({
getInitialState: function() {
return {
teams: []
};
},
componentDidMount: function() {
var config = settings.readFileSync(this.props.configFile);
this.setState({
teams: config.teams
})
},
handleTeamsChange: function(teams) {
this.setState({
teams: teams
});
},
handleSave: function() {
var config = {
teams: this.state.teams,
version: 1
};
settings.writeFileSync(this.props.configFile, config);
window.location = './index.html';
},
handleCancel: function() {
window.location = './index.html';
},
render: function() {
return (
<Grid className="settingsPage">
<Row>
<Col md={ 12 }>
<h2>Teams</h2>
<TeamList teams={ this.state.teams } onTeamsChange={ this.handleTeamsChange } />
</Col>
</Row>
<Row>
<Col md={ 12 }>
<Button onClick={ this.handleCancel }>Cancel</Button>
{ ' ' }
<Button bsStyle="primary" onClick={ this.handleSave }>Save</Button>
</Col>
</Row>
</Grid>
);
}
});
var TeamList = React.createClass({
handleTeamRemove: function(index) {
console.log(index);
var teams = this.props.teams;
teams.splice(index, 1);
this.props.onTeamsChange(teams);
},
handleTeamAdd: function(team) {
var teams = this.props.teams;
teams.push(team);
this.props.onTeamsChange(teams);
},
render: function() {
var thisObj = this;
var teamNodes = this.props.teams.map(function(team, i) {
var handleTeamRemove = function() {
thisObj.handleTeamRemove(i);
};
return (
<TeamListItem index={ i } name={ team.name } url={ team.url } onTeamRemove={ handleTeamRemove } />
);
});
return (
<ListGroup class="teamList">
{ teamNodes }
<TeamListItemNew onTeamAdd={ this.handleTeamAdd } />
</ListGroup>
);
}
});
var TeamListItem = React.createClass({
handleTeamRemove: function() {
this.props.onTeamRemove();
},
render: function() {
var style = {
left: {
"display": 'inline-block'
}
};
return (
<div className="teamListItem list-group-item">
<div style={ style.left }>
<h4 className="list-group-item-heading">{ this.props.name }</h4>
<p className="list-group-item-text">
{ this.props.url }
</p>
</div>
<div className="pull-right">
<Button bsSize="xsmall" onClick={ this.handleTeamRemove }>
<Glyphicon glyph="remove" />
</Button>
</div>
</div>
);
}
});
var TeamListItemNew = React.createClass({
getInitialState: function() {
return {
name: '',
url: ''
};
},
handleSubmit: function(e) {
console.log('submit');
e.preventDefault();
this.props.onTeamAdd({
name: this.state.name,
url: this.state.url
});
this.setState(this.getInitialState());
},
handleNameChange: function(e) {
console.log('name');
this.setState({
name: e.target.value
});
},
handleURLChange: function(e) {
console.log('url');
this.setState({
url: e.target.value
});
},
render: function() {
return (
<ListGroupItem>
<form className="form-inline" onSubmit={ this.handleSubmit }>
<div className="form-group">
<label for="inputTeamName">Name</label>
{ ' ' }
<input type="text" className="form-control" id="inputTeamName" placeholder="Example team" value={ this.state.name } onChange={ this.handleNameChange } />
</div>
{ ' ' }
<div className="form-group">
<label for="inputTeamURL">URL</label>
{ ' ' }
<input type="url" className="form-control" id="inputTeamURL" placeholder="http://example.com/team" value={ this.state.url } onChange={ this.handleURLChange } />
</div>
{ ' ' }
<Button type="submit">Add</Button>
</form>
</ListGroupItem>
);
}
});
var configFile = remote.getGlobal('config-file');
ReactDOM.render(
<SettingsPage configFile={ configFile } />,
document.getElementById('content')
);

View File

@@ -0,0 +1,60 @@
'use strict';
const electron = require('electron');
const ipc = electron.ipcRenderer;
const NativeNotification = Notification;
ipc.on('retrieveUnreadCount', function() {
var unreadCount = document.getElementsByClassName('unread-title').length;
ipc.sendToHost('retrieveUnreadCount', unreadCount);
});
// On Windows 8.1 and Windows 8, a shortcut with a Application User Model ID must be installed to the Start screen.
// In current version, use tray balloon for notification
function isLowerThanOrEqualWindows8_1() {
if (process.platform != 'win32') {
return false;
}
var osVersion = require('../common/osVersion');
return (osVersion.major <= 6 && osVersion.minor <= 3);
};
// Show balloon when notified.
function overrideNotificationWithBalloon() {
Notification = function(title, options) {
ipc.send('notified', {
title: title,
options: options
});
};
Notification.requestPermission = function(callback) {
callback('granted');
};
Notification.prototype.close = function() {};
};
// Show window even if it is hidden/minimized when notification is clicked.
function overrideNotification() {
Notification = function(title, options) {
this.notification = new NativeNotification(title, options);
};
Notification.requestPermission = function(callback) {
callback('granted');
};
Notification.prototype.close = function() {
this.notification.close();
};
Notification.prototype.__defineSetter__('onclick', function(callback) {
this.notification.onclick = function() {
electron.remote.getCurrentWindow().show();
callback();
};
});
}
if (process.platform === 'win32' && isLowerThanOrEqualWindows8_1()) {
overrideNotificationWithBalloon();
}
else {
overrideNotification();
}