ing
This commit is contained in:
parent
89dc2363dc
commit
de3a771eed
BIN
src/.DS_Store
vendored
Normal file
BIN
src/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
src/ts/.DS_Store
vendored
Normal file
BIN
src/ts/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
src/ts/@overflow/.DS_Store
vendored
Normal file
BIN
src/ts/@overflow/.DS_Store
vendored
Normal file
Binary file not shown.
|
@ -11,7 +11,6 @@ import Platform from '@overflow/commons/platform';
|
||||||
import { store, sagaMiddleware, history } from './redux/store';
|
import { store, sagaMiddleware, history } from './redux/store';
|
||||||
|
|
||||||
import sagas from './redux/saga';
|
import sagas from './redux/saga';
|
||||||
import muiTheme from './theme/mui';
|
|
||||||
import routes from './router';
|
import routes from './router';
|
||||||
|
|
||||||
injectTapEventPlugin();
|
injectTapEventPlugin();
|
||||||
|
|
|
@ -36,19 +36,19 @@ function subscribe(socket: WebSocket): Channel<string> {
|
||||||
}
|
}
|
||||||
|
|
||||||
function* read(socket: WebSocket): SagaIterator {
|
function* read(socket: WebSocket): SagaIterator {
|
||||||
const channel = yield call(subscribe, socket);
|
// const channel = yield call(subscribe, socket);
|
||||||
let action = yield takeEvery(channel, (action: A) => any);
|
// let action = yield takeEvery(channel, (action: A) => any);
|
||||||
while (true) {
|
// while (true) {
|
||||||
let action = yield take(channel);
|
// let action = yield take(channel);
|
||||||
yield put(action);
|
// yield put(action);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
function* write(socket: WebSocket): SagaIterator {
|
function* write(socket: WebSocket): SagaIterator {
|
||||||
while (true) {
|
// while (true) {
|
||||||
const { payload } = yield take(`${sendMessage}`);
|
// const { payload } = yield take(`${sendMessage}`);
|
||||||
socket.emit('message', payload);
|
// socket.emit('message', payload);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
function* flow(): SagaIterator {
|
function* flow(): SagaIterator {
|
||||||
|
|
|
@ -7,7 +7,7 @@ const routes = (
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path='/' />
|
<Route exact path='/' />
|
||||||
<Route path='/signin' component={Signin} />
|
<Route path='/signin' component={Signin} />
|
||||||
<Route component={NoMatch}/>
|
|
||||||
</Switch>
|
</Switch>
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
import { colors, getMuiTheme, MuiTheme, spacing } from 'material-ui/styles';
|
|
||||||
import { fade } from 'material-ui/utils/colorManipulator';
|
|
||||||
|
|
||||||
const muiTheme:MuiTheme = getMuiTheme({
|
|
||||||
spacing: spacing,
|
|
||||||
fontFamily: 'Roboto, sans-serif',
|
|
||||||
palette: {
|
|
||||||
primary1Color: colors.cyan500,
|
|
||||||
primary2Color: colors.cyan700,
|
|
||||||
primary3Color: colors.grey400,
|
|
||||||
accent1Color: colors.pinkA200,
|
|
||||||
accent2Color: colors.grey100,
|
|
||||||
accent3Color: colors.grey500,
|
|
||||||
textColor: colors.darkBlack,
|
|
||||||
alternateTextColor: colors.white,
|
|
||||||
canvasColor: colors.white,
|
|
||||||
borderColor: colors.grey300,
|
|
||||||
disabledColor: fade(colors.darkBlack, 0.3),
|
|
||||||
pickerHeaderColor: colors.cyan500,
|
|
||||||
clockCircleColor: fade(colors.darkBlack, 0.07),
|
|
||||||
shadowColor: colors.fullBlack,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export default muiTheme;
|
|
|
@ -1,260 +0,0 @@
|
||||||
import * as io from 'socket.io-client';
|
|
||||||
|
|
||||||
export type OnConnectFunc = () => void;
|
|
||||||
export type OnWebsocketDisconnectFunc = () => void;
|
|
||||||
export type OnWebsocketNativeMessageFunc = (websocketMessage: string) => void;
|
|
||||||
export type OnMessageFunc = (message: any) => void;
|
|
||||||
|
|
||||||
enum MessageType {
|
|
||||||
STRING = 1,
|
|
||||||
INT,
|
|
||||||
BOOLEAN,
|
|
||||||
JSON,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Client {
|
|
||||||
private conn: WebSocket;
|
|
||||||
private isReady: boolean;
|
|
||||||
|
|
||||||
// events listeners
|
|
||||||
private connectListeners: OnConnectFunc[] = [];
|
|
||||||
private disconnectListeners: OnWebsocketDisconnectFunc[] = [];
|
|
||||||
private nativeMessageListeners: OnWebsocketNativeMessageFunc[] = [];
|
|
||||||
private messageListeners: { [event: string]: OnMessageFunc[] } = {};
|
|
||||||
|
|
||||||
constructor(endpoint: string, protocols?: string[]) {
|
|
||||||
// if (!window.WebSocket) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (endpoint.indexOf('ws') === -1) {
|
|
||||||
endpoint = 'ws://' + endpoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (protocols != null && protocols.length > 0) {
|
|
||||||
this.conn = new WebSocket(endpoint, protocols);
|
|
||||||
} else {
|
|
||||||
this.conn = new WebSocket(endpoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.conn.onopen = ((evt: Event): any => {
|
|
||||||
this.fireConnect();
|
|
||||||
this.isReady = true;
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.conn.onclose = ((evt: Event): any => {
|
|
||||||
this.fireDisconnect();
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.conn.onmessage = ((evt: MessageEvent) => {
|
|
||||||
this.messageReceivedFromConn(evt);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.conn.onerror = ((evt: MessageEvent) => {
|
|
||||||
this.errorReceivedFromConn(evt);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public OnConnect(fn: OnConnectFunc): void {
|
|
||||||
if (this.isReady) {
|
|
||||||
fn();
|
|
||||||
}
|
|
||||||
this.connectListeners.push(fn);
|
|
||||||
}
|
|
||||||
public OnDisconnect(fn: OnWebsocketDisconnectFunc): void {
|
|
||||||
this.disconnectListeners.push(fn);
|
|
||||||
}
|
|
||||||
public OnMessage(cb: OnWebsocketNativeMessageFunc): void {
|
|
||||||
this.nativeMessageListeners.push(cb);
|
|
||||||
}
|
|
||||||
public On(event: string, cb: OnMessageFunc): void {
|
|
||||||
if (this.messageListeners[event] == null || this.messageListeners[event] === undefined) {
|
|
||||||
this.messageListeners[event] = [];
|
|
||||||
}
|
|
||||||
this.messageListeners[event].push(cb);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
// Ws Actions
|
|
||||||
public Disconnect(): void {
|
|
||||||
this.conn.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// EmitMessage sends a native websocket message
|
|
||||||
public EmitMessage(websocketMessage: string): void {
|
|
||||||
this.conn.send(websocketMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fireConnect(): void {
|
|
||||||
for (let i = 0; i < this.connectListeners.length; i++) {
|
|
||||||
this.connectListeners[i]();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fireDisconnect(): void {
|
|
||||||
for (let i = 0; i < this.disconnectListeners.length; i++) {
|
|
||||||
this.disconnectListeners[i]();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fireNativeMessage(websocketMessage: string): void {
|
|
||||||
for (let i = 0; i < this.nativeMessageListeners.length; i++) {
|
|
||||||
this.nativeMessageListeners[i](websocketMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fireMessage(event: string, message: any): void {
|
|
||||||
for (let key in this.messageListeners) {
|
|
||||||
if (this.messageListeners.hasOwnProperty(key)) {
|
|
||||||
if (key === event) {
|
|
||||||
for (let i = 0; i < this.messageListeners[key].length; i++) {
|
|
||||||
this.messageListeners[key][i](message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// utils
|
|
||||||
private isNumber(obj: any): boolean {
|
|
||||||
return !isNaN(obj - 0) && obj !== null && obj !== '' && obj !== false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private isString(obj: any): boolean {
|
|
||||||
return Object.prototype.toString.call(obj) === '[object String]';
|
|
||||||
}
|
|
||||||
|
|
||||||
private isBoolean(obj: any): boolean {
|
|
||||||
return typeof obj === 'boolean' ||
|
|
||||||
(typeof obj === 'object' && typeof obj.valueOf() === 'boolean');
|
|
||||||
}
|
|
||||||
|
|
||||||
private isJSON(obj: any): boolean {
|
|
||||||
return typeof obj === 'object';
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
// messages
|
|
||||||
private _msg(event: string, messageType: MessageType, dataMessage: string): string {
|
|
||||||
|
|
||||||
return websocketMessagePrefix + event + websocketMessageSeparator + String(websocketMessageType) + websocketMessageSeparator + dataMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
private encodeMessage(event: string, data: any): string {
|
|
||||||
let m = '';
|
|
||||||
let t: MessageType = MessageType.STRING;
|
|
||||||
if (this.isNumber(data)) {
|
|
||||||
t = MessageType.INT;
|
|
||||||
m = data.toString();
|
|
||||||
} else if (this.isBoolean(data)) {
|
|
||||||
t = MessageType.BOOLEAN;
|
|
||||||
m = data.toString();
|
|
||||||
} else if (this.isString(data)) {
|
|
||||||
t = MessageType.STRING;
|
|
||||||
m = data.toString();
|
|
||||||
} else if (this.isJSON(data)) {
|
|
||||||
// propably json-object
|
|
||||||
t = MessageType.JSON;
|
|
||||||
m = JSON.stringify(data);
|
|
||||||
} else {
|
|
||||||
console.log('Invalid, javascript-side should contains an empty second parameter.');
|
|
||||||
}
|
|
||||||
|
|
||||||
return this._msg(event, t, m);
|
|
||||||
}
|
|
||||||
|
|
||||||
private decodeMessage<T>(event: string, websocketMessage: string): T | any {
|
|
||||||
// q-websocket-message;user;4;themarshaledstringfromajsonstruct
|
|
||||||
let skipLen = websocketMessagePrefixLen + websocketMessageSeparatorLen + event.length + 2;
|
|
||||||
if (websocketMessage.length < skipLen + 1) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
let websocketMessageType = parseInt(websocketMessage.charAt(skipLen - 2));
|
|
||||||
let theMessage = websocketMessage.substring(skipLen, websocketMessage.length);
|
|
||||||
if (websocketMessageType === MessageType.INT) {
|
|
||||||
return parseInt(theMessage);
|
|
||||||
} else if (websocketMessageType === MessageType.BOOLEAN) {
|
|
||||||
return Boolean(theMessage);
|
|
||||||
} else if (websocketMessageType === MessageType.STRING) {
|
|
||||||
return theMessage;
|
|
||||||
} else if (websocketMessageType === MessageType.JSON) {
|
|
||||||
return JSON.parse(theMessage);
|
|
||||||
} else {
|
|
||||||
return null; // invalid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private getWebsocketCustomEvent(websocketMessage: string): string {
|
|
||||||
if (websocketMessage.length < websocketMessagePrefixAndSepIdx) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
let s = websocketMessage.substring(websocketMessagePrefixAndSepIdx, websocketMessage.length);
|
|
||||||
let evt = s.substring(0, s.indexOf(websocketMessageSeparator));
|
|
||||||
|
|
||||||
return evt;
|
|
||||||
}
|
|
||||||
|
|
||||||
private getCustomMessage(event: string, websocketMessage: string): string {
|
|
||||||
let eventIdx = websocketMessage.indexOf(event + websocketMessageSeparator);
|
|
||||||
let s = websocketMessage.substring(eventIdx + event.length + websocketMessageSeparator.length + 2, websocketMessage.length);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
// Ws Events
|
|
||||||
|
|
||||||
// messageReceivedFromConn this is the func which decides
|
|
||||||
// if it's a native websocket message or a custom qws message
|
|
||||||
// if native message then calls the fireNativeMessage
|
|
||||||
// else calls the fireMessage
|
|
||||||
//
|
|
||||||
// remember q gives you the freedom of native websocket messages if you don't want to use this client side at all.
|
|
||||||
private messageReceivedFromConn(evt: MessageEvent): void {
|
|
||||||
// check if qws message
|
|
||||||
let message = <string>evt.data;
|
|
||||||
if (message.indexOf(websocketMessagePrefix) !== -1) {
|
|
||||||
let event = this.getWebsocketCustomEvent(message);
|
|
||||||
if (event !== '') {
|
|
||||||
// it's a custom message
|
|
||||||
this.fireMessage(event, this.getCustomMessage(event, message));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// it's a native websocket message
|
|
||||||
this.fireNativeMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// errorReceivedFromConn this is the func which decides
|
|
||||||
// if it's a native websocket message or a custom qws message
|
|
||||||
// if native message then calls the fireNativeMessage
|
|
||||||
// else calls the fireMessage
|
|
||||||
//
|
|
||||||
// remember q gives you the freedom of native websocket messages if you don't want to use this client side at all.
|
|
||||||
private errorReceivedFromConn(evt: MessageEvent): void {
|
|
||||||
// check if qws message
|
|
||||||
let message = <string>evt.data;
|
|
||||||
if (message.indexOf(websocketMessagePrefix) !== -1) {
|
|
||||||
let event = this.getWebsocketCustomEvent(message);
|
|
||||||
if (event !== '') {
|
|
||||||
// it's a custom message
|
|
||||||
this.fireMessage(event, this.getCustomMessage(event, message));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// it's a native websocket message
|
|
||||||
this.fireNativeMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export default Client;
|
|
8
src/ts/@overflow/commons/context/constants.ts
Normal file
8
src/ts/@overflow/commons/context/constants.ts
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
// used to store types to be injected
|
||||||
|
export const PARAM_TYPES = 'overflow:paramtypes';
|
||||||
|
|
||||||
|
// used to access design time types
|
||||||
|
export const DESIGN_PARAM_TYPES = 'design:paramtypes';
|
||||||
|
|
||||||
|
// The type of the binding at design time
|
||||||
|
export const INJECT_TAG = 'inject';
|
17
src/ts/@overflow/commons/context/index.ts
Normal file
17
src/ts/@overflow/commons/context/index.ts
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
class AppContext {
|
||||||
|
private static context: AppContext;
|
||||||
|
|
||||||
|
private constructor() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getService<T>(): T {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static getContext(): AppContext {
|
||||||
|
return AppContext.context;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AppContext;
|
15
src/ts/@overflow/commons/context/inject.ts
Normal file
15
src/ts/@overflow/commons/context/inject.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
import * as METADATA from './constants';
|
||||||
|
|
||||||
|
|
||||||
|
function inject(): PropertyDecorator | ParameterDecorator {
|
||||||
|
return (target: Object, propertyKey: string | symbol, parameterIndex?: number): void => {
|
||||||
|
let metadata = new Metadata(METADATA.INJECT_TAG, serviceIdentifier);
|
||||||
|
|
||||||
|
if (typeof parameterIndex === 'number') {
|
||||||
|
tagParameter(target, propertyKey, parameterIndex, metadata);
|
||||||
|
} else {
|
||||||
|
tagProperty(target, propertyKey, metadata);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
16
src/ts/@overflow/commons/context/injectable.ts
Normal file
16
src/ts/@overflow/commons/context/injectable.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import * as METADATA from './constants';
|
||||||
|
|
||||||
|
function injectable(): ClassDecorator {
|
||||||
|
return <TFunction extends Function>(target: TFunction): TFunction | void => {
|
||||||
|
|
||||||
|
if (Reflect.hasOwnMetadata(METADATA.PARAM_TYPES, target) === true) {
|
||||||
|
throw new Error('Cannot apply @injectable decorator multiple times.');
|
||||||
|
}
|
||||||
|
|
||||||
|
let types = Reflect.getMetadata(METADATA.DESIGN_PARAM_TYPES, target) || [];
|
||||||
|
Reflect.defineMetadata(METADATA.PARAM_TYPES, types, target);
|
||||||
|
|
||||||
|
return target;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import Service from '@overflow/commons/api/Service';
|
import Service from '@overflow/commons/api/Service';
|
||||||
import Member from '../model/Member';
|
import Member from '../model/Member';
|
||||||
import service from '@overflow/commons/context/decorator/service';
|
// import service from '@overflow/commons/context/decorator/service';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@service()
|
@service()
|
||||||
export class MemberService extends Service {
|
export class MemberService extends Service {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"baseUrl": ".",
|
"baseUrl": "./src/ts",
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
"emitDecoratorMetadata": true,
|
"emitDecoratorMetadata": true,
|
||||||
"experimentalDecorators": true,
|
"experimentalDecorators": true,
|
||||||
|
@ -18,12 +18,6 @@
|
||||||
"outDir": "dist/ts/",
|
"outDir": "dist/ts/",
|
||||||
"preserveConstEnums": true,
|
"preserveConstEnums": true,
|
||||||
"pretty": true,
|
"pretty": true,
|
||||||
"paths": {
|
|
||||||
"*": [
|
|
||||||
"./src/ts/*",
|
|
||||||
"./types/*"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"removeComments": true,
|
"removeComments": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user