Skip to content

Commit

Permalink
Merge branch 'master' into feature/misc-project-setup
Browse files Browse the repository at this point in the history
  • Loading branch information
danielweck committed Mar 30, 2017
2 parents e1edfb3 + 999a71d commit b657d83
Show file tree
Hide file tree
Showing 19 changed files with 1,044 additions and 140 deletions.
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,37 @@ Command line steps:
6) `yarn run lint` (code linting)
7) `yarn start` (runs the app)
8) `yarn start:dev` (runs the app in dev mode)

## Technologies

* typescript
* electron
* reactjs
* redux
* i18next

## Install

Install all dependencies

```
yarn install
```

## Getting started

### Production

```
yarn start
```

### Development

```
yarn run start:dev
```

This environment provides a hot loader.
So if you made changes in your code, electron will automatically reload
your app.
8 changes: 8 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"homepage": "https://github.com/edrlab/readium-desktop",
"dependencies": {
"@types/electron": "^1.4.34",
"@types/i18next": "^2.3.35",
"@types/material-ui": "^0.16.57",
"@types/react": "^15.0.11",
"@types/react-dom": "^0.14.23",
Expand All @@ -54,12 +55,15 @@
"@types/redux-saga": "^0.10.5",
"@types/reflect-metadata": "0.0.5",
"class-validator": "^0.6.8",
"font-awesome": "^4.7.0",
"i18next": "^7.1.3",
"inversify": "^3.1.0",
"inversify-inject-decorators": "^3.0.1",
"material-ui": "^0.17.0",
"react": "^15.4.2",
"react-dom": "^15.4.2",
"react-redux": "^5.0.2",
"react-tap-event-plugin": "^2.0.1",
"redux": "^3.6.0",
"redux-saga": "^0.14.3",
"reflect-metadata": "^0.1.10"
Expand All @@ -68,11 +72,15 @@
"awesome-typescript-loader": "^3.1.2",
"concurrently": "^3.4.0",
"cross-env": "^3.2.4",
"css-loader": "^0.28.0",
"eclint": "^2.0.1",
"electron": "^1.6.2",
"extract-text-webpack-plugin": "^2.1.0",
"file-loader": "^0.10.1",
"html-webpack-plugin": "^2.28.0",
"react-hot-loader": "^1.3.1",
"source-map-loader": "^0.1.6",
"style-loader": "^0.16.1",
"tslint": "^4.5.1",
"typescript": "^2.2.0",
"webpack": "^2.2.1",
Expand Down
14 changes: 14 additions & 0 deletions src/actions/i18n.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Action } from "redux";

export const SET_LOCALE = "SET_LOCALE";

export interface ILocaleAction extends Action {
locale: string;
}

export function setLocale(locale: string): ILocaleAction {
return {
type: SET_LOCALE,
locale,
};
}
32 changes: 31 additions & 1 deletion src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,42 @@ import { lightBaseTheme, MuiThemeProvider } from "material-ui/styles";
import getMuiTheme from "material-ui/styles/getMuiTheme";
import NavigationClose from "material-ui/svg-icons/navigation/close";

import Library from "./Library";
import { Store } from "redux";

import { setLocale } from "../actions/i18n";
import { lazyInject } from "../di";
import { Translator } from "../i18n/translator";
import { IAppState } from "../reducers/app";

import Library from "./Library";

const lightMuiTheme = getMuiTheme(lightBaseTheme);
const defaultLocale = "fr";

export default class App extends React.Component<undefined, undefined> {
@lazyInject("store")
private store: Store<IAppState>;

@lazyInject(Translator)
private translator: Translator;

constructor() {
super();
let locale = this.store.getState().i18n.locale;

if (locale == null) {
this.store.dispatch(setLocale(defaultLocale));
}

this.translator.setLocale(locale);
}

public componentDidMount() {
this.store.subscribe(() => {
this.translator.setLocale(this.store.getState().i18n.locale);
});
}

public render(): React.ReactElement<{}> {
return (
<MuiThemeProvider muiTheme={lightMuiTheme}>
Expand Down
88 changes: 82 additions & 6 deletions src/components/Library.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,35 @@
import * as React from "react";

import { MinLength, validate } from "class-validator";
import * as React from "react";
import { Store } from "redux";

import { Card, CardHeader, CardMedia } from "material-ui/Card";
import DropDownMenu from "material-ui/DropDownMenu";
import FontIcon from "material-ui/FontIcon";
import IconButton from "material-ui/IconButton";
import IconMenu from "material-ui/IconMenu";
import MenuItem from "material-ui/MenuItem";
import RaisedButton from "material-ui/RaisedButton";
import { blue500 } from "material-ui/styles/colors";
import NavigationExpandMoreIcon from "material-ui/svg-icons/navigation/expand-more";
import TextField from "material-ui/TextField";
import { Toolbar, ToolbarGroup, ToolbarSeparator, ToolbarTitle } from "material-ui/Toolbar";

import { setLocale } from "../actions/i18n";
import { lazyInject } from "../di";
import { Translator } from "../i18n/translator";
import { IAppState } from "../reducers/app";

// DANIEL - IPC test
import { ipcRenderer } from "electron";

export default class Library extends React.Component<undefined, undefined> {
interface ILibraryState {
locale: string;
}

export default class Library extends React.Component<undefined, ILibraryState> {
public state: ILibraryState;

// DANIEL - IPC test
public _handleClick() {
console.log("CLICK");

Expand All @@ -21,12 +42,67 @@ export default class Library extends React.Component<undefined, undefined> {
ipcRenderer.send('asynchronous-message', 'RENDERER ASYNC')
}

public render(): React.ReactElement<{}> {
@lazyInject(Translator)
private translator: Translator;

@lazyInject("store")
private store: Store<IAppState>;

constructor() {
super();
this.state = {
locale: this.store.getState().i18n.locale,
};

this.handleLocaleChange = this.handleLocaleChange.bind(this);
}

public componentDidMount() {
this.store.subscribe(() => {
this.setState({
locale: this.store.getState().i18n.locale,
});
});
}

public render(): React.ReactElement<{}> {
const __ = this.translator.translate;

return (
<div>
<h1>Book library</h1>
<RaisedButton label="Click" onClick={this._handleClick} />
<Toolbar>
<ToolbarGroup firstChild={true}>
<DropDownMenu value={this.state.locale} onChange={this.handleLocaleChange}>
<MenuItem value="en" primaryText="English" />
<MenuItem value="fr" primaryText="French" />
</DropDownMenu>
</ToolbarGroup>
<ToolbarGroup>
<ToolbarTitle text="Options" />
<FontIcon className="muidocs-icon-custom-sort" />
<ToolbarSeparator />
<IconMenu
iconButtonElement={
<IconButton touch={true}>
<FontIcon
className="fa fa-home"
color={blue500} />
</IconButton>
}
>
<MenuItem primaryText="Download" />
<MenuItem primaryText="More Info" />
</IconMenu>
</ToolbarGroup>
</Toolbar>
<h1>{__("library.heading")}</h1>

<RaisedButton label="DANIEL - IPC test" onClick={this._handleClick} />
</div>
);
}

private handleLocaleChange(event: any, index: any, locale: string) {
this.store.dispatch(setLocale(locale));
}
}
28 changes: 28 additions & 0 deletions src/di.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Store } from "redux";
import "reflect-metadata";

import { Container, inject, injectable } from "inversify";
import getDecorators from "inversify-inject-decorators";

import { Translator } from "./i18n/translator";
import { IAppState } from "./reducers/app";
import { store } from "./store/memory";

let container = new Container();
container.bind<Translator>(Translator).toSelf();
container.bind<Store<IAppState>>("store").toConstantValue(store);

let {
lazyInject,
lazyInjectNamed,
lazyInjectTagged,
lazyMultiInject,
} = getDecorators(container);

export {
container,
lazyInject,
lazyInjectNamed,
lazyInjectTagged,
lazyMultiInject,
};
14 changes: 14 additions & 0 deletions src/entities/book.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

interface IBook {
identifier: string;
title: string;
language: string;
creator: string;
size: number;
physicalPageNb: number;
coverUrl: string;
}

export class Book {

}
8 changes: 8 additions & 0 deletions src/fixtures/library.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"books": [
{
"title":""

}
]
}
35 changes: 35 additions & 0 deletions src/i18n/translator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import * as i18n from "i18next";
import { injectable} from "inversify";
import * as path from "path";

import * as enCatalog from "../resources/locales/en.json";
import * as frCatalog from "../resources/locales/fr.json";

i18n.init({
resources: {
en: {
translation: enCatalog,
},
fr: {
translation: frCatalog,
},
},
});

@injectable()
export class Translator {
private locale: string = "en";

public getLocale(): string {
return this.locale;
}

public setLocale(locale: string) {
this.locale = locale;
i18n.changeLanguage(this.locale);
}

public translate(message: string): string {
return i18n.t(message);
}
}
10 changes: 10 additions & 0 deletions src/reducers/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { combineReducers } from "redux";
import { i18n, I18NState } from "./i18n";

export interface IAppState {
i18n: I18NState;
}

export const app = combineReducers({
i18n,
});
22 changes: 22 additions & 0 deletions src/reducers/i18n.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ILocaleAction, SET_LOCALE } from "./../actions/i18n";

export interface I18NState {
locale: string;
}

const initialState: I18NState = {
locale: "fr",
};

export function i18n(
state: I18NState = initialState,
action: ILocaleAction,
): I18NState {
switch (action.type) {
case SET_LOCALE:
state.locale = action.locale;
return state;
default:
return state;
}
}
8 changes: 8 additions & 0 deletions src/renderer.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import "font-awesome/css/font-awesome.css";

import * as React from "react";
import * as ReactDOM from "react-dom";
import * as injectTapEventPlugin from "react-tap-event-plugin";

import App from "./components/App";

// Needed for onTouchTap
// http://stackoverflow.com/a/34015469/988941
injectTapEventPlugin();

// Render React App component
ReactDOM.render(
React.createElement(App, {}, null),
document.getElementById("app"),
Expand Down
5 changes: 5 additions & 0 deletions src/resources/locales/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"library": {
"heading": "Your library"
}
}
5 changes: 5 additions & 0 deletions src/resources/locales/fr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"library": {
"heading": "Votre bibliothèque"
}
}
Loading

0 comments on commit b657d83

Please sign in to comment.