1
0
mirror of https://github.com/mgerb/ps-launcher synced 2026-01-08 09:32:51 +00:00
This commit is contained in:
2017-10-16 23:05:44 -05:00
commit 3f49700225
24 changed files with 6120 additions and 0 deletions

3
.babelrc Normal file
View File

@@ -0,0 +1,3 @@
{
"presets": ["es2015", "react", "stage-0"]
}

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
.vscode
node_modules
yarn-error*
dist

7
.prettierrc Normal file
View File

@@ -0,0 +1,7 @@
{
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all",
"useTabs": false,
"printWidth": 140
}

1
@types/all/index.d.ts vendored Normal file
View File

@@ -0,0 +1 @@
declare module 'this-is-a-test-module';

1
README.md Normal file
View File

@@ -0,0 +1 @@
# Work in progress

32
app/Wrapper.tsx Normal file
View File

@@ -0,0 +1,32 @@
import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import { Header } from './components/Header';
import Home from './pages/Home/Home';
// styling
import './scss/index.scss';
interface Props {}
interface State {}
export default class Wrapper extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
}
public render() {
return (
<BrowserRouter>
<div>
<Header />
<Switch>
{/* <Route exact path="/" component={} /> */}
<Route component={Home} />
</Switch>
</div>
</BrowserRouter>
);
}
}

6
app/app.tsx Normal file
View File

@@ -0,0 +1,6 @@
import React from 'react';
import ReactDOM from 'react-dom';
import Wrapper from './Wrapper';
import 'babel-polyfill';
ReactDOM.render(<Wrapper />, document.getElementById('app'));

View File

@@ -0,0 +1,43 @@
@import '../../scss/variables.scss';
.header {
background: $dark-blue--1;
display: flex;
align-items: center;
height: 40px;
padding: 0 10px;
}
.header__draggable-region {
-webkit-app-region: drag;
flex: 1;
height: 100%;
}
.header-icon {
& + & {
margin-left: 10px;
}
cursor: pointer;
border-color: $blue;
color: $blue;
&:hover {
border-color: $blue--lighter;
color: $blue--lighter;
}
}
.header-icon--minimize {
height: 12px;
width: 12px;
border-bottom: 2px solid;
}
.header-icon--maximize {
height: 10px;
width: 10px;
border: 2px solid;
}

View File

@@ -0,0 +1,33 @@
import { remote } from 'electron';
import React from 'react';
import './Header.scss';
export class Header extends React.Component<any, any> {
exit() {
window.close();
}
maximize() {
if (remote.getCurrentWindow().isMaximized()) {
remote.getCurrentWindow().restore();
} else {
remote.getCurrentWindow().maximize();
}
}
minimize() {
remote.getCurrentWindow().minimize();
}
render() {
return (
<div className="header">
<div className="header__draggable-region"/>
<div className="header-icon header-icon--minimize" onClick={this.minimize.bind(this)}/>
<div className="header-icon header-icon--maximize" onClick={this.maximize.bind(this)}/>
<div className="fa fa-times fa-lg header-icon" onClick={() => this.exit()}/>
</div>
);
}
}

View File

@@ -0,0 +1 @@
export * from './Header';

3
app/pages/Home/Home.scss Normal file
View File

@@ -0,0 +1,3 @@
.Home {
padding: 10px;
}

68
app/pages/Home/Home.tsx Normal file
View File

@@ -0,0 +1,68 @@
import * as _ from 'lodash';
import fs from 'fs';
import { exec } from 'child_process';
import React from 'react';
import { RouteComponentProps } from 'react-router-dom';
import './Home.scss';
interface Props extends RouteComponentProps<any> {}
interface State {
path: string;
}
export default class Home extends React.Component<Props, State> {
constructor() {
super();
this.state = {
path: '',
};
}
onFolderSelect(e: React.ChangeEvent<HTMLInputElement>) {
const path: string = _.get(e, `target.files[0].path`);
if (path) {
this.setState({ path });
}
}
async startGame() {
const { path } = this.state;
// set the realm list
await this.setRealmList();
// launch wow
exec(`"${path}/WoW.exe"`, (err, output) => {
console.log(err);
console.log(output);
});
}
setRealmList(): Promise<any> {
const { path } = this.state;
return new Promise((resolve, reject) => {
fs.writeFile(`${path}/realmlist.wtf`, 'set realmlist logon.elysium-project.org', err => {
err ? reject(err) : resolve();
});
});
}
render() {
const { path } = this.state;
return (
<div className="Home">
<div>{path}</div>
{/* hacky way of adding webkitdirectory to the input */}
<input type="file" {...{ webkitdirectory: 'true' }} onChange={this.onFolderSelect.bind(this)} />
<div>
<button onClick={this.startGame.bind(this)}>Start</button>
</div>
</div>
);
}
}

View File

@@ -0,0 +1,5 @@
.NotFound {
font-size: 20px;
text-align: center;
padding-top: 200px;
}

View File

@@ -0,0 +1,18 @@
import React from 'react';
import { RouteComponentProps } from 'react-router-dom';
import './NotFound.scss';
interface Props extends RouteComponentProps<any> {}
interface State {}
export default class NotFound extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
}
render() {
return <div className="NotFound">404 Not Found</div>;
}
}

4
app/scss/index.scss Normal file
View File

@@ -0,0 +1,4 @@
@import '~font-awesome/css/font-awesome.css';
@import '~normalize.css/normalize.css';
@import './variables.scss';
@import './style.scss';

24
app/scss/style.scss Normal file
View File

@@ -0,0 +1,24 @@
html {
font-family: 'Roboto Condensed', sans-serif;
}
body {
color: $light-blue;
background-color: $dark-blue;
}
.fa {
margin-right: 5px;
margin-left: 5px;
}
a {
text-decoration: none;
color: $blue;
transition: all 0.1s linear;
cursor: pointer;
&:hover {
color: $blue--lighter;
}
}

10
app/scss/variables.scss Normal file
View File

@@ -0,0 +1,10 @@
// colors
$dark-blue: #1d2938;
$dark-blue--1: lighten(#1d2938, 5%);
$dark-blue--2: lighten(#1d2938, 10%);
$blue: #258de5;
$blue--lighter: saturate(lighten($blue, 10%), 100%);
$green: #39ce83;
$light-blue: #e9eef2;
$red: #e95779;
$white: #fff;

10
index.html Normal file
View File

@@ -0,0 +1,10 @@
<html>
<head>
</head>
<body>
<div id="app"></div>
</body>
</html>

64
main.js Normal file
View File

@@ -0,0 +1,64 @@
const electron = require('electron');
// Module to control application life.
const app = electron.app;
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow;
const path = require('path');
const url = require('url');
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;
function createWindow() {
// Create the browser window.
mainWindow = new BrowserWindow({ width: 800, height: 600, frame: false });
// and load the index.html of the app.
// mainWindow.loadURL(
// url.format({
// pathname: path.join(__dirname, './dist/index.html'),
// protocol: 'file:',
// slashes: true,
// }),
// );
mainWindow.loadURL('http://localhost:8080');
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', () => {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null;
});
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow();
}
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

54
package.json Normal file
View File

@@ -0,0 +1,54 @@
{
"name": "todoapp",
"version": "1.0.0",
"description": "A seed for a simple react application with typescript.",
"main": "main.js",
"scripts": {
"build": "webpack -p --progress --colors",
"c9": "webpack-dev-server --host 0.0.0.0 --port 8080 --inline --history-api-fallback",
"dev": "webpack --watch --colors",
"dev:server": "webpack-dev-server --inline --history-api-fallback",
"start": "electron ./main.js",
"watch": "webpack --watch"
},
"author": "Mitchell Gerber",
"license": "MIT",
"dependencies": {
"@types/electron": "^1.6.10",
"@types/lodash": "^4.14.77",
"@types/react": "^16.0.10",
"@types/react-dom": "^16.0.1",
"@types/react-router-dom": "^4.0.2",
"autoprefixer": "^7.1.5",
"babel-core": "^6.21.0",
"babel-loader": "^7.1.2",
"babel-plugin-add-module-exports": "^0.2.1",
"babel-polyfill": "^6.26.0",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-0": "^6.16.0",
"clean-webpack-plugin": "^0.1.14",
"css-loader": "^0.28.7",
"electron": "^1.7.9",
"extract-text-webpack-plugin": "3.0.1",
"file-loader": "^1.1.5",
"font-awesome": "^4.7.0",
"html-webpack-plugin": "^2.24.1",
"lodash": "^4.17.4",
"node-sass": "^4.5.3",
"normalize.css": "^7.0.0",
"prettier": "^1.7.4",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-router-dom": "^4.2.2",
"sass-loader": "^6.0.6",
"style-loader": "^0.19.0",
"ts-loader": "^2.0.3",
"tslint": "^5.7.0",
"tslint-config-airbnb": "^5.3.0",
"typescript": "^2.2.2",
"url-loader": "^0.6.2",
"webpack": "3.7.1",
"webpack-dev-server": "2.9.2"
}
}

38
tsconfig.json Normal file
View File

@@ -0,0 +1,38 @@
{
"compilerOptions": {
"target": "es6",
"module": "es6",
"moduleResolution": "node",
"jsx": "react",
"allowSyntheticDefaultImports": true,
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"preserveConstEnums": true,
"allowJs": false,
"sourceMap": true,
"noImplicitReturns": true,
"noUnusedParameters": true,
"noUnusedLocals": true,
"alwaysStrict": true,
"typeRoots": [
"./node_modules/@types",
"./@types"
]
},
"filesGlob": [
"typings/index.d.ts",
"src/**/*.ts",
"src/**/*.tsx"
],
"include": [
"app"
],
"exclude": [
"android",
"ios",
"build",
"node_modules"
],
"compileOnSave": false
}

9
tslint.json Normal file
View File

@@ -0,0 +1,9 @@
{
"extends": "tslint-config-airbnb",
"rules": {
"align": false,
"ter-arrow-parens": false,
"import-name": false,
"max-line-length": [true, 140]
}
}

90
webpack.config.js Normal file
View File

@@ -0,0 +1,90 @@
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: {
app: './app/app.tsx',
vendor: ['react', 'react-dom'],
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
resolve: {
extensions: ['.ts', '.tsx', '.js'],
},
target: 'electron-renderer',
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: ['babel-loader'],
},
{
test: /\.ts(x)?$/,
use: ['babel-loader', 'ts-loader'],
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader!sass-loader',
}),
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader',
}),
},
{
test: /\.svg$/,
use:
'url-loader?limit=65000&mimetype=image/svg+xml&name=static/[name].[hash].[ext]',
},
{
test: /\.woff$/,
use:
'url-loader?limit=65000&mimetype=application/font-woff&name=static/[name].[hash].[ext]',
},
{
test: /\.woff2$/,
use:
'url-loader?limit=65000&mimetype=application/font-woff2&name=static/[name].[hash].[ext]',
},
{
test: /\.[ot]tf$/,
use:
'url-loader?limit=65000&mimetype=application/octet-stream&name=static/[name].[hash].[ext]',
},
{
test: /\.eot$/,
use:
'url-loader?limit=65000&mimetype=application/vnd.ms-fontobject&name=static/[name].[hash].[ext]',
},
],
},
plugins: [
new CleanWebpackPlugin(['dist'], {
verbose: true,
}),
new ExtractTextPlugin({
filename: '[name].css',
disable: false,
allChunks: true,
}),
new HtmlWebpackPlugin({
filename: 'index.html',
template: './index.html',
}),
new webpack.optimize.CommonsChunkPlugin({
name: ['vendor', 'manifest'],
minChunks: 'Infinity',
}),
new webpack.HotModuleReplacementPlugin(),
],
};

5592
yarn.lock Normal file

File diff suppressed because it is too large Load Diff