Commit 4ccddadf authored by 神楽坂玲奈's avatar 神楽坂玲奈

angular seed

parent 105cce99
......@@ -8,8 +8,8 @@ import {clipboard, remote} from "electron";
import * as path from "path";
import {InstallService} from "./install.service";
declare var Notification;
declare var $;
declare const Notification: any;
declare const $: any;
@Component({
moduleId: module.id,
......@@ -150,7 +150,7 @@ export class AppDetailComponent implements OnInit {
this.appsService.runApp(app, 'custom');
}
copy(text) {
copy(text: string) {
clipboard.writeText(text);
}
......
......@@ -8,7 +8,7 @@ export class AppLocal {
files: Map<string,string>;
action: Map<string,{execute: string, args: string[], env: {}, open: App}>;
update(local) {
update(local: any) {
this.path = local.path;
this.version = local.version;
let files = new Map<string,string>();
......@@ -19,7 +19,7 @@ export class AppLocal {
}
toJSON() {
let t = {};
let t: any = {};
for (let [k,v] of this.files) {
t[k] = v;
}
......
import {AppLocal} from "./app-local";
export enum Category {
game, // 游戏
music, // 音乐
book, // 图书
runtime, // 运行库
emulator, // 模拟器
language, // 语言包
expansion, // 资料片
module, // 创意工坊
game,
music,
book,
runtime,
emulator,
language,
expansion,
module
}
// export enum Status{
......@@ -69,7 +69,7 @@ export class App {
return [Category.game].includes(this.category);
}
constructor(app) {
constructor(app: any) {
this.id = app.id;
this.name = app.name;
this.description = app.description;
......@@ -104,4 +104,4 @@ export class App {
return [];
}
}
}
\ No newline at end of file
......@@ -5,10 +5,12 @@ import {SettingsService} from "./settings.sevices";
import * as fs from "fs";
import * as path from "path";
import * as child_process from "child_process";
import {ChildProcess} from "child_process";
import {remote} from "electron";
import "rxjs/Rx";
import {AppLocal} from "./app-local";
import * as ini from "ini";
import Timer = NodeJS.Timer;
const Aria2 = require('aria2');
const sudo = require('electron-sudo');
......@@ -229,9 +231,9 @@ export class AppsService {
}
connections = new Map<App, Connection>();
maotama;
maotama: Promise<ChildProcess>;
async network(app: App, server) {
async network(app: App, server: any) {
if (!this.maotama) {
this.maotama = new Promise((resolve, reject) => {
let child = sudo.fork('maotama', [], {stdio: ['inherit', 'inherit', 'inherit', 'ipc']});
......@@ -240,7 +242,7 @@ export class AppsService {
child.once('exit', reject);
})
}
let child;
let child: ChildProcess;
try {
child = await this.maotama;
} catch (error) {
......@@ -253,7 +255,7 @@ export class AppsService {
connection.connection.close();
}
connection = {connection: new WebSocket(server.url), address: null};
let id;
let id: Timer | null;
this.connections.set(app, connection);
connection.connection.onmessage = (event) => {
console.log(event.data);
......@@ -273,8 +275,10 @@ export class AppsService {
}, 200);
break;
case 'CONNECTED':
clearInterval(id);
id = null;
if (id) {
clearInterval(id);
id = null;
}
break;
}
};
......
......@@ -6,6 +6,8 @@ import {Http} from "@angular/http";
import {Observable} from "rxjs/Observable";
import {EventEmitter} from "events";
import {App} from "./app";
import {Observer} from "rxjs";
import Timer = NodeJS.Timer;
const Aria2 = require('aria2');
......@@ -20,7 +22,7 @@ export class DownloadService {
open = this.aria2.open();
constructor(private ngZone: NgZone, private http: Http) {
this.aria2.onDownloadComplete = (result) => {
this.aria2.onDownloadComplete = (result: any) => {
let app = this.gidAppMap.get(result.gid);
if (app) {
this.appGidMap.delete(app);
......@@ -41,7 +43,7 @@ export class DownloadService {
throw('nyaa');
}
return new Promise((resolve, reject) => {
this.eventEmitter.once(app.id, (event) => {
this.eventEmitter.once(app.id, (event: Event) => {
resolve(app);
})
});
......@@ -49,8 +51,8 @@ export class DownloadService {
getProgress(app: App): Observable<any> {
let gid = this.appGidMap.get(app);
return Observable.create((observer) => {
let interval;
return Observable.create((observer: Observer<any>) => {
let interval: Timer;
this.ngZone.runOutsideAngular(() => {
interval = setInterval(() => {
this.aria2.tellStatus(gid).then((status: any) => {
......@@ -85,9 +87,9 @@ export class DownloadService {
async addMetalink(metalink: string, library: string) {
let meta4 = new Buffer((metalink)).toString('base64');
let gid = ( await this.aria2.addMetalink(meta4, {dir: library}))[0];
return Observable.create((observer) => {
return Observable.create((observer: Observer<any>) => {
this.map.set(gid, observer);
let interval;
let interval: Timer;
this.ngZone.runOutsideAngular(() => {
interval = setInterval(async() => {
let status = await this.aria2.tellStatus(gid);
......
......@@ -42,7 +42,7 @@ export class InstallService {
getComplete(app: App): Promise<App> {
return new Promise((resolve, reject) => {
this.eventEmitter.once(app.id, (complete) => {
this.eventEmitter.once(app.id, (complete: any) => {
resolve();
});
});
......@@ -124,7 +124,7 @@ export class InstallService {
if (["ygopro", 'desmume'].includes(app.id)) {
checksumUrl = this.checksumUri + app.id + "-" + process.platform;
}
let checksumMap: Map<string,string> = await this.http.get(checksumUrl)
return this.http.get(checksumUrl)
.map((response) => {
let map = new Map<string,string>();
for (let line of response.text().split('\n')) {
......@@ -135,7 +135,6 @@ export class InstallService {
}
return map;
}).toPromise();
return checksumMap;
}
async doInstall() {
......
......@@ -86,9 +86,9 @@ export class LobbyComponent implements OnInit {
let a = await this.downloadService.addMetalink(metalink, dir);
await new Promise((resolve, reject) => {
a.subscribe((status) => {
a.subscribe((status: any) => {
console.log(status);
}, (err) => {
}, (err: any) => {
reject()
}, () => {
resolve();
......@@ -121,7 +121,7 @@ export class LobbyComponent implements OnInit {
let contains = ["game", "music", "book"].map((value) => Category[value]);
let result = {runtime: []};
for (let app of this.apps.values()) {
let tag;
let tag: string;
if (contains.includes(app.category)) {
if (app.isInstalled()) {
tag = 'installed';
......
......@@ -14,7 +14,7 @@ import * as url from "url";
styleUrls: ['login.component.css'],
})
export class LoginComponent {
url;
url: string;
return_sso_url = 'https://mycard.moe/login_callback'; // 这个url不会真的被使用,可以填写不存在的
constructor(private loginService: LoginService) {
......@@ -36,7 +36,7 @@ export class LoginComponent {
}
}
return_sso(return_url) {
return_sso(return_url: string) {
if (!return_url.startsWith(this.return_sso_url)) {
return;
}
......
......@@ -28,7 +28,7 @@ export class LoginService {
}
}
login(user) {
login(user: User) {
this.user = user;
this.logged_in = true;
localStorage.setItem('login', JSON.stringify(user));
......
body {
font-family: "Helvetica Neue", Helvetica, Arial, 'Source Sans Pro', "Microsoft YaHei", 'Microsoft JhengHei', "WenQuanYi Micro Hei", sans-serif;
}
:host {
height: 100%;
display: flex;
......
......@@ -17,7 +17,7 @@ import "rxjs/Rx";
import {ISubscription} from "rxjs/Subscription";
import {AppLocal} from "./app-local";
declare var $;
declare const $: any;
interface SystemConf {
use_d3d: string
......@@ -47,7 +47,7 @@ interface SystemConf {
interface Server {
id?: string
url: string
url?: string
address: string
port: number
}
......@@ -56,6 +56,7 @@ interface Room {
id?: string
title?: string
server?: Server
private?: boolean
mode: number,
rule: number,
start_lp: number,
......@@ -127,9 +128,9 @@ export class YGOProComponent implements OnInit {
let modal = $('#game-list-modal');
modal.on('show.bs.modal', (event) => {
modal.on('show.bs.modal', () => {
this.connections = this.servers.map((server) => {
let connection = new WebSocket(server.url);
let connection = new WebSocket(<string>server.url);
connection.onclose = () => {
this.rooms = this.rooms.filter(room => room.server != server)
};
......@@ -138,7 +139,7 @@ export class YGOProComponent implements OnInit {
//console.log(message)
switch (message.event) {
case 'init':
this.rooms = this.rooms.filter(room => room.server != server).concat(message.data.map(data => Object.assign({server: server}, this.default_options, data)));
this.rooms = this.rooms.filter(room => room.server != server).concat(message.data.map((data: any) => Object.assign({server: server}, this.default_options, data)));
break;
case 'create':
this.rooms.push(Object.assign({server: server}, this.default_options, message.data));
......@@ -155,7 +156,7 @@ export class YGOProComponent implements OnInit {
});
});
modal.on('hide.bs.modal', (event) => {
modal.on('hide.bs.modal', () => {
for (let connection of this.connections) {
connection.close();
}
......@@ -194,12 +195,12 @@ export class YGOProComponent implements OnInit {
}
}
async delete_deck(deck) {
async delete_deck(deck: string) {
await new Promise(resolve => fs.unlink(path.join((<AppLocal>this.app.local).path, 'deck', deck + '.ydk'), resolve));
return this.refresh()
}
async fix_fonts(data) {
async fix_fonts(data: SystemConf) {
if (!await this.get_font([data.numfont])) {
let font = await this.get_font(this.numfont);
if (font) {
......@@ -233,12 +234,12 @@ export class YGOProComponent implements OnInit {
})
};
async join(name, server) {
async join(name: string, server: Server) {
let system_conf = await this.load_system_conf();
await this.fix_fonts(system_conf);
system_conf.lastdeck = this.current_deck;
system_conf.lastip = server.address;
system_conf.lastport = server.port;
system_conf.lastport = server.port.toString();
system_conf.roompass = name;
system_conf.nickname = this.loginService.user.username;
await this.save_system_conf(system_conf);
......@@ -253,11 +254,11 @@ export class YGOProComponent implements OnInit {
return this.start_game(['-d']);
}
join_windbot(name) {
join_windbot(name: string) {
return this.join('AI#' + name, this.servers[0])
}
start_game(args) {
start_game(args: string[]) {
let win = remote.getCurrentWindow();
win.minimize();
console.log(path.join((<AppLocal>this.app.local).path, (<any>this.app.actions.get('main')).execute), args, {cwd: (<AppLocal>this.app.local).path});
......@@ -275,13 +276,13 @@ export class YGOProComponent implements OnInit {
})
};
create_room(options) {
create_room(options: Room) {
let options_buffer = new Buffer(6);
// 建主密码 https://docs.google.com/document/d/1rvrCGIONua2KeRaYNjKBLqyG9uybs9ZI-AmzZKNftOI/edit
options_buffer.writeUInt8((options.private ? 2 : 1) << 4, 1);
options_buffer.writeUInt8(parseInt(options.rule) << 5 | parseInt(options.mode) << 3 | (options.enable_priority ? 1 << 2 : 0) | (options.no_check_deck ? 1 << 1 : 0) | (options.no_shuffle_deck ? 1 : 0), 2);
options_buffer.writeUInt16LE(parseInt(options.start_lp), 3);
options_buffer.writeUInt8(parseInt(options.start_hand) << 4 | parseInt(options.draw_count), 5);
options_buffer.writeUInt8(options.rule << 5 | options.mode << 3 | (options.enable_priority ? 1 << 2 : 0) | (options.no_check_deck ? 1 << 1 : 0) | (options.no_shuffle_deck ? 1 : 0), 2);
options_buffer.writeUInt16LE(options.start_lp, 3);
options_buffer.writeUInt8(options.start_hand << 4 | options.draw_count, 5);
let checksum = 0;
for (let i = 1; i < options_buffer.length; i++) {
checksum -= options_buffer.readUInt8(i)
......@@ -293,30 +294,30 @@ export class YGOProComponent implements OnInit {
options_buffer.writeUInt16LE(options_buffer.readUInt16LE(i) ^ secret, i)
}
let password = options_buffer.toString('base64') + options.title.replace(/\s/, String.fromCharCode(0xFEFF));
let password = options_buffer.toString('base64') + (<string>options.title).replace(/\s/, String.fromCharCode(0xFEFF));
let room_id = crypto.createHash('md5').update(password + this.loginService.user.username).digest('base64').slice(0, 10).replace('+', '-').replace('/', '_');
this.join(password, this.servers[0]);
}
join_room(room) {
join_room(room: Room) {
let options_buffer = new Buffer(6);
options_buffer.writeUInt8(3 << 4, 1);
let checksum = 0;
for (var i = 1; i < options_buffer.length; i++) {
for (let i = 1; i < options_buffer.length; i++) {
checksum -= options_buffer.readUInt8(i)
}
options_buffer.writeUInt8(checksum & 0xFF, 0);
let secret = this.loginService.user.external_id % 65535 + 1;
for (i = 0; i < options_buffer.length; i += 2) {
for (let i = 0; i < options_buffer.length; i += 2) {
options_buffer.writeUInt16LE(options_buffer.readUInt16LE(i) ^ secret, i)
}
let password = options_buffer.toString('base64') + room.id;
this.join(password, room.server);
this.join(password, <Server>room.server);
}
matching: ISubscription | null;
......
<!DOCTYPE html>
<html>
<head>
<title>MyCard</title>
......@@ -5,25 +6,27 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="node_modules/font-awesome/css/font-awesome.min.css">
<!-- 1. Load libraries -->
<link rel="stylesheet" href="styles.css">
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>delete module.exports</script>
<script src="node_modules/jquery/dist/jquery.min.js"></script>
<script src="node_modules/tether/dist/js/tether.min.js"></script>
<script src="node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
<!-- 2. Configure SystemJS -->
<script src="systemjs.config.js"></script>
<script>
document.locale = require('electron').remote.app.getLocale();
System.import('app')
</script>
</head>
<!-- 3. Display the application -->
<body>
<mycard>Loading...</mycard>
</body>
......
......@@ -7,7 +7,7 @@ const path = require('path');
if (process.platform == 'darwin') {
try {
autoUpdater.setFeedURL("https://wudizhanche.mycard.moe/update");
autoUpdater.setFeedURL("https://wudizhanche.mycard.moe/update/darwin/" + app.getVersion());
} catch (err) {
}
}
......
{
"name": "mycard",
"version": "3.0.0-dev.9",
"description": "mycard",
"keywords": [],
"author": "zh99998 <zh99998@gmail.com>",
"homepage": "https://mycard.moe",
"version": "3.0.0-dev.9",
"license": "UNLICENSED",
"repository": "github:mycard/mycard",
"scripts": {
"start": "tsc && electron .",
"pack": "tsc && build --dir",
"dist": "tsc && build",
"release": "tsc && build",
"start": "tsc && electron .",
"postinstall": "typings install",
"tsc": "tsc",
"tsc:w": "tsc -w",
"i18n": "ng-xi18n"
},
"license": "UNLICENSED",
"dependencies": {
"@angular/common": "latest",
"@angular/compiler": "latest",
......@@ -25,17 +23,18 @@
"@angular/platform-browser": "latest",
"@angular/platform-browser-dynamic": "latest",
"@angular/router": "latest",
"@angular/router-deprecated": "latest",
"@angular/upgrade": "latest",
"angular2-in-memory-web-api": "latest",
"rxjs": "5.0.0-beta.12",
"angular-in-memory-web-api": "latest",
"systemjs": "latest",
"zone.js": "^0.6.21",
"core-js": "latest",
"reflect-metadata": "latest",
"rxjs": "5.0.0-beta.12",
"zone.js": "^0.6.26",
"electron-auto-updater": "latest",
"electron-cookies": "latest",
"electron-sudo": "mycard/electron-sudo#mycard",
"bootstrap": "next",
"jquery": "latest",
"tether": "latest",
"bootstrap": "next",
"font-awesome": "latest",
"aria2": "latest",
"ini": "latest",
......@@ -49,7 +48,10 @@
"electron-builder": "latest",
"electron-rebuild": "latest",
"typescript": "latest",
"typings": "latest"
"@types/node": "latest",
"@types/electron": "latest",
"@types/ini": "latest",
"@types/mkdirp": "latest"
},
"build": {
"productName": "MyCard",
......
/* Master Styles */
h1 {
color: #369;
font-family: Arial, Helvetica, sans-serif;
font-size: 250%;
}
h2, h3 {
color: #444;
font-family: Arial, Helvetica, sans-serif;
font-weight: lighter;
html, body {
height: 100%;
}
body {
margin: 2em;
}
\ No newline at end of file
font-family: -apple-system, Arial, 'Source Sans Pro', "Microsoft YaHei", 'Microsoft JhengHei', "WenQuanYi Micro Hei", sans-serif;
}
/**
* System configuration for Angular 2 samples
* System configuration for Angular samples
* Adjust as necessary for your application needs.
*/
System.config({
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
// map tells the System loader where to look for things
var map = {
'app': 'app', // 'dist',
map: {
// our app is within the app folder
app: 'app',
// systemjs plugins
'text': 'systemjs-text-plugin.js',
'@angular': 'node_modules/@angular',
'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
'rxjs': 'node_modules/rxjs',
'ng2-translate': 'node_modules/ng2-translate/bundles/index.js',
// angular bundles
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
'@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
'@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js',
'@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js',
// other libraries
'rxjs': 'npm:rxjs',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
// node.js built-in libraries
"buffer": "@node/buffer",
"querystring": "@node/querystring",
"events": "@node/events",
"http": "@node/http",
"cluster": "@node/cluster",
"zlib": "@node/zlib",
"os": "@node/os",
"https": "@node/https",
"punycode": "@node/punycode",
"repl": "@node/repl",
"readline": "@node/readline",
"vm": "@node/vm",
"child_process": "@node/child_process",
"url": "@node/url",
"dns": "@node/dns",
"net": "@node/net",
"dgram": "@node/dgram",
"fs": "@node/fs",
"path": "@node/path",
"string_decoder": "@node/string_decoder",
"tls": "@node/tls",
"crypto": "@node/crypto",
"stream": "@node/stream",
"util": "@node/util",
"assert": "@node/assert",
"tty": "@node/tty",
"domain": "@node/domain",
"constants": "@node/constants",
"process": "@node/process",
"v8": "@node/v8",
"timers": "@node/timers",
"console": "@node/console",
// other node.js libraries
"electron": "@node/electron",
"ini": "@node/ini",
"mkdirp": "@node/mkdirp",
"aria2": "@node/aria2",
"electron-sudo": "@node/electron-sudo"
};
// packages tells the System loader how to load when no filename and/or no extension
var packages = {
'app': {main: 'main.js', defaultExtension: 'js'},
'rxjs': {defaultExtension: 'js'},
'angular2-in-memory-web-api': {main: 'index.js', defaultExtension: 'js'}
};
let builtin_modules = ["buffer", "querystring", "events", "http", "cluster", "zlib", "os", "https", "punycode", "repl", "readline", "vm", "child_process", "url", "dns", "net", "dgram", "fs", "path", "string_decoder", "tls", "crypto", "stream", "util", "assert", "tty", "domain", "constants", "process", "v8", "timers", "console"];
for (let mod of builtin_modules) {
map[mod] = `@node/${mod}`;
}
var ngPackageNames = [
'common',
'compiler',
'core',
'forms',
'http',
'platform-browser',
'platform-browser-dynamic',
'router',
'router-deprecated',
'upgrade',
];
// Individual files (~300 requests):
function packIndex(pkgName) {
packages['@angular/' + pkgName] = {main: 'index.js', defaultExtension: 'js'};
}
// Bundled (~40 requests):
function packUmd(pkgName) {
packages['@angular/' + pkgName] = {main: 'bundles/' + pkgName + '.umd.js', defaultExtension: 'js'};
}
// Most environments should use UMD; some (Karma) need the individual index files
var setPackageConfig = System.packageWithIndex ? packIndex : packUmd;
// Add package entries for angular packages
ngPackageNames.forEach(setPackageConfig);
var config = {
map: map,
packages: packages
};
System.config(config);
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
app: {
main: './main.js',
defaultExtension: 'js'
},
rxjs: {
defaultExtension: 'js'
}
}
});
\ No newline at end of file
{
"compilerOptions": {
"target": "es6",
"lib": [
"dom",
"es2017"
],
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false,
"lib": [
"es2017",
"dom"
],
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true,
"strictNullChecks": true,
"skipLibCheck": true
}
}
}
\ No newline at end of file
{
"rules": {
"class-name": true,
"comment-format": [
true,
"check-space"
],
"curly": true,
"eofline": true,
"forin": true,
"indent": [
true,
"spaces"
],
"label-position": true,
"label-undefined": true,
"max-line-length": [
true,
140
],
"member-access": false,
"member-ordering": [
true,
"static-before-instance",
"variables-before-functions"
],
"no-arg": true,
"no-bitwise": true,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-construct": true,
"no-debugger": true,
"no-duplicate-key": true,
"no-duplicate-variable": true,
"no-empty": false,
"no-eval": true,
"no-inferrable-types": true,
"no-shadowed-variable": true,
"no-string-literal": false,
"no-switch-case-fall-through": true,
"no-trailing-whitespace": true,
"no-unused-expression": true,
"no-unused-variable": true,
"no-unreachable": true,
"no-use-before-declare": true,
"no-var-keyword": true,
"object-literal-sort-keys": false,
"one-line": [
true,
"check-open-brace",
"check-catch",
"check-else",
"check-whitespace"
],
"quotemark": [
true,
"single"
],
"radix": true,
"semicolon": true,
"triple-equals": [
true,
"allow-null-check"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}
],
"variable-name": false,
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
]
}
}
{
"globalDependencies": {
"electron/github-electron": "registry:dt/electron/github-electron",
"ini": "registry:dt/ini",
"jasmine": "registry:dt/jasmine",
"node": "registry:dt/node"
},
"dependencies": {
"mkdirp": "registry:npm/mkdirp"
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment