Commit ca9d897e authored by wudizhanche1000's avatar wudizhanche1000

海量更改

parent 85e50c1a
This diff is collapsed.
import {Component, OnInit} from "@angular/core"; import {Component, OnInit, Input, ChangeDetectorRef} from "@angular/core";
import {AppsService} from "./apps.service"; import {AppsService} from "./apps.service";
import {InstallConfig} from "./install-config"; import {InstallConfig} from "./install-config";
import {SettingsService} from "./settings.sevices"; import {SettingsService} from "./settings.sevices";
import {App} from "./app"; import {App} from "./app";
import {DownloadService} from "./download.service"; import {DownloadService} from "./download.service";
import {clipboard, remote} from "electron"; import {clipboard, remote, ipcRenderer} from "electron";
import * as path from "path"; import * as path from "path";
import * as child_process from "child_process"; import * as child_process from "child_process";
import {InstallService} from "./install.service";
declare var Notification;
declare var $; declare var $;
@Component({ @Component({
selector: 'app-detail', selector: 'app-detail',
templateUrl: 'app/app-detail.component.html', templateUrl: 'app/app-detail.component.html',
styleUrls: ['app/app-detail.component.css'], styleUrls: ['app/app-detail.component.css'],
providers: [DownloadService]
}) })
export class AppDetailComponent implements OnInit { export class AppDetailComponent implements OnInit {
@Input()
currentApp: App;
platform = process.platform; platform = process.platform;
installConfig: InstallConfig; installConfig: InstallConfig;
constructor(private appsService: AppsService, private settingsService: SettingsService, private downloadService: DownloadService) { constructor(private appsService: AppsService, private settingsService: SettingsService,
private downloadService: DownloadService, private installService: InstallService,
private ref: ChangeDetectorRef) {
} }
ngOnInit() { ngOnInit() {
this.updateInstallConfig(); // this.updateInstallConfig();
ipcRenderer.on('download-message-reply', (event, arg)=> {
console.log(arg);
});
ipcRenderer.send("download-message", "ping")
} }
updateInstallConfig() { updateInstallConfig() {
this.installConfig = this.appsService.getInstallConfig(this.appsService.currentApp); this.installConfig = new InstallConfig(this.currentApp);
this.installConfig.installPath = this.settingsService.getDefaultLibrary().path; this.installConfig.installLibrary = this.settingsService.getDefaultLibrary().path;
} this.installConfig.references = [];
for (let reference of this.currentApp.references.values()) {
get name() { this.installConfig.references.push(new InstallConfig(reference))
let currentApp = this.appsService.currentApp;
if (currentApp) {
return currentApp.name[this.settingsService.getLocale()];
} }
return "Loading";
};
get isInstalled() {
let currentApp = this.appsService.currentApp;
return !!(currentApp.local && currentApp.local.path);
} }
get libraries(): string[] {
return this.settingsService.getLibraries().map((item)=>item.path);
}
get news() { get news() {
let currentApp = this.appsService.currentApp; return this.currentApp.news;
if (currentApp) {
return currentApp.news;
}
} }
get friends() { get friends() {
...@@ -63,35 +63,36 @@ export class AppDetailComponent implements OnInit { ...@@ -63,35 +63,36 @@ export class AppDetailComponent implements OnInit {
} }
get mods() { get mods() {
let contains = ["optional", "language", "emulator"]; // let contains = ["optional", "language", "emulator"];
//
let currentApp = this.appsService.currentApp; // let currentApp = this.appsService.currentApp;
if (currentApp) { // if (currentApp) {
if (currentApp.references[process.platform] && currentApp.references[process.platform].length > 0) { // if (currentApp.references[process.platform] && currentApp.references[process.platform].length > 0) {
let refs = currentApp.references[process.platform]; // let refs = currentApp.references[process.platform];
refs = refs.filter((ref)=> { // refs = refs.filter((ref)=> {
return contains.includes(ref.type); // return contains.includes(ref.type);
}); // });
refs = refs.map((ref)=> { // refs = refs.map((ref)=> {
let tmp = Object.create(ref); // let tmp = Object.create(ref);
switch (tmp.type) { // switch (tmp.type) {
case "optional": // case "optional":
tmp.type = "选项"; // tmp.type = "选项";
break; // break;
case "language": // case "language":
tmp.type = "语言"; // tmp.type = "语言";
break; // break;
default: // default:
break; // break;
} // }
//console.log(tmp.type); // //console.log(tmp.type);
return tmp; // return tmp;
}); // });
return refs; // return refs;
//return this.currentApp.references[process.platform]; //return this.currentApp.references[process.platform];
} // }
} // }
return [];
} }
uninstalling: boolean; uninstalling: boolean;
...@@ -99,23 +100,64 @@ export class AppDetailComponent implements OnInit { ...@@ -99,23 +100,64 @@ export class AppDetailComponent implements OnInit {
uninstall(id: string) { uninstall(id: string) {
if (confirm("确认删除?")) { if (confirm("确认删除?")) {
this.uninstalling = true; this.uninstalling = true;
this.appsService.uninstall(id).then(()=> { // this.appsService.uninstall(id).then(()=> {
this.uninstalling = false; // this.uninstalling = false;
} // }
); // );
} }
} }
async install() {
install() {
$('#install-modal').modal('hide'); $('#install-modal').modal('hide');
this.appsService.download();
let currentApp = this.currentApp;
let options = this.installConfig;
let dependencies = currentApp.findDependencies();
let apps = dependencies.concat(currentApp).filter((app)=>!app.isInstalled());
for (let reference of options.references) {
if (reference.install) {
apps.push(reference.app);
apps.push(...reference.app.findDependencies())
}
}
let downloadPath = path.join(this.installConfig.installLibrary, "downloading");
try {
let downloadApps = await this.downloadService.addUris(apps, downloadPath);
this.downloadService.getProgress(currentApp)
.subscribe((progress)=> {
currentApp.status.status = "downloading";
currentApp.status.progress = progress.progress;
currentApp.status.total = progress.total;
this.ref.detectChanges();
},
(error)=> {
},
()=> {
currentApp.status.status = "waiting";
this.ref.detectChanges();
});
await Promise.all(downloadApps.map((app)=> {
return this.downloadService.getComplete(app)
.then((completeApp: App)=> {
return this.installService.add(completeApp, options);
});
}));
currentApp.status.status = "ready";
} catch (e) {
new Notification(currentApp.name, {body: "下载失败"});
}
} }
selectDir() { selectDir() {
let dir = remote.dialog.showOpenDialog({properties: ['openFile', 'openDirectory']}); let dir = remote.dialog.showOpenDialog({properties: ['openFile', 'openDirectory']});
console.log(dir); console.log(dir);
this.appsService.installConfig.installDir = dir[0]; // this.appsService.installConfig.installDir = dir[0];
return dir[0]; return dir[0];
} }
...@@ -131,12 +173,8 @@ export class AppDetailComponent implements OnInit { ...@@ -131,12 +173,8 @@ export class AppDetailComponent implements OnInit {
let open = ''; let open = '';
let openApp = app.actions.get("main").open; let openApp = app.actions.get("main").open;
if (openApp) { if (openApp) {
if (this.isInstalled) { open = path.join(openApp.local.path, openApp.actions.get("main").execute);
open = path.join(openApp.local.path, openApp.actions.get("main").execute); args.push(execute);
args.push(execute);
} else {
console.error('open app not found');
}
} else { } else {
//没有需要通过open启动依赖,直接启动程序 //没有需要通过open启动依赖,直接启动程序
open = execute; open = execute;
......
...@@ -4,5 +4,24 @@ ...@@ -4,5 +4,24 @@
export class AppLocal { export class AppLocal {
path: string; path: string;
version: string; version: string;
files: string[]; files: Map<string,string>;
update(local) {
this.path = local.path;
this.version = local.version;
let files = new Map<string,string>();
for (let filename of Object.keys(local.files)) {
files.set(filename, local.files[filename]);
}
this.files = files;
}
toJSON() {
let t = {};
for (let [k,v] of this.files) {
t[k] = v;
}
return {path: this.path, version: this.version, files: t};
}
} }
import {AppLocal} from "./app-local"; import {AppLocal} from "./app-local";
/* export enum Category {
export enum Reference_Type { game, // 游戏
runtime, // directx music, // 音乐
emulator, // wine, np2 book, // 图书
dependency, // runtime, // 运行库
optional, // fxtz emulator, // 模拟器
language, language, // 语言包
host expansion, // 资料片
} module, // 创意工坊
*/ }
/*
export enum App_Category { // export enum Status{
game, // downloading,
music, // init,
book, // installing,
runtime, // directx // ready,
emulator, // wine, np2 // updating,
language // uninstalling,
} // waiting,
*/ // }
export class AppStatus {
progress: number;
total: number;
status: string;
}
export class App { export class App {
id: string; id: string;
name: string; // i18n _name: string; // i18n
get name() {
return this._name;
}
set name(a) {
this._name = a;
}
description: string; //i18n description: string; //i18n
author: string; // English Only author: string; // English Only
homepage: string; homepage: string;
category: string; category: Category;
parent: App; parent: App;
actions: Map<string,{execute: string, args: string[], env: {}, open: App}>; actions: Map<string,{execute: string, args: string[], env: {}, open: App}>;
references: Map<string,App>; references: Map<string,App>;
dependencies: Map<string,App>; dependencies: Map<string,App>;
locales: string[]; locales: string[];
download: {[platform: string]: string}; // meta4 url download: string; // meta4 url
news: {title: string, url: string, image: string}[]; news: {title: string, url: string, image: string}[];
network: any; network: any;
tags: string[]; tags: string[];
version: {[platform: string]: string}; version: string;
local: AppLocal; local: AppLocal;
status: AppStatus;
isInstalled(): boolean {
return this.local !== undefined;
}
constructor(app) { constructor(app) {
this.id = app.id; this.id = app.id;
...@@ -46,7 +64,7 @@ export class App { ...@@ -46,7 +64,7 @@ export class App {
this.description = app.description; this.description = app.description;
this.author = app.author; this.author = app.author;
this.homepage = app.homepage; this.homepage = app.homepage;
this.category = app.category; this.category = Category[app.category as string];
this.actions = app.actions; this.actions = app.actions;
this.dependencies = app.dependencies; this.dependencies = app.dependencies;
this.parent = app.parent; this.parent = app.parent;
...@@ -57,8 +75,20 @@ export class App { ...@@ -57,8 +75,20 @@ export class App {
this.network = app.network; this.network = app.network;
this.tags = app.tags; this.tags = app.tags;
this.version = app.version; this.version = app.version;
this.local = app.local;
} }
findDependencies(): App[] {
if (this.dependencies && this.dependencies.size > 0) {
let set = new Set();
for (let dependency of this.dependencies.values()) {
dependency.findDependencies()
.forEach((value)=> {
set.add(value);
});
set.add(dependency);
}
return Array.from(set);
}
return [];
}
} }
:host {
/*background-color: darkslategray;*/
width: 280px;
flex-shrink: 0;
overflow-y: auto;
background-color: #f5f5f5;
border-right: 1px solid #eee;
}
a {
display: block;
padding: 10px 20px 10px 20px;
}
.active {
background-color: #428bca;
}
.active > a {
color: #fff;
}
span {
margin-left: 8px;
}
\ No newline at end of file
<span *ngIf="grouped_apps.installed">已安装</span>
<ul *ngIf="grouped_apps.installed" class="nav nav-sidebar">
<li *ngFor="let app of grouped_apps.installed" [class.active]="app===appsService.currentApp">
<a (click)="chooseApp(app)" href="#">{{app.name}}</a>
</li>
</ul><span *ngIf="grouped_apps.yugioh">游戏王</span>
<ul *ngIf="grouped_apps.yugioh" class="nav nav-sidebar">
<li *ngFor="let app of grouped_apps.yugioh" [class.active]="app===appsService.currentApp">
<a (click)="chooseApp(app)" href="#">{{app.name}}</a>
</li>
</ul><span *ngIf="grouped_apps.touhou">东方 Project</span>
<ul *ngIf="grouped_apps.touhou" class="nav nav-sidebar">
<li *ngFor="let app of grouped_apps.touhou" [class.active]="app===appsService.currentApp">
<a (click)="chooseApp(app)" href="#">{{app.name}}</a>
</li>
</ul><span *ngIf="grouped_apps.touhou_pc98">东方旧作</span>
<ul *ngIf="grouped_apps.touhou_pc98" class="nav nav-sidebar">
<li *ngFor="let app of grouped_apps.touhou_pc98" [class.active]="app===appsService.currentApp">
<a (click)="chooseApp(app)" href="#">{{app.name}}</a>
</li>
</ul>
\ No newline at end of file
import {Component, OnInit} from "@angular/core";
import {AppsService} from "./apps.service";
import {App} from "./app";
@Component({
selector: 'apps',
templateUrl: 'app/apps.component.html',
styleUrls: ['app/apps.component.css'],
})
export class AppsComponent implements OnInit {
constructor(private appsService: AppsService) {
}
ngOnInit() {
}
chooseApp(app: App) {
this.appsService.currentApp = app;
}
get grouped_apps() {
let contains = ["game", "music", "book"];
let apps = Array.from(this.appsService.allApps.values());
let result = {};
for (let app of apps) {
if (contains.includes(app.category)) {
let tag;
if (app.local) {
tag = 'installed';
} else {
tag = app.tags[0];
}
if (!result[tag]) {
result[tag] = []
}
result[tag].push(app)
}
}
//console.log(result)
return result
}
}
\ No newline at end of file
This diff is collapsed.
...@@ -2,24 +2,90 @@ ...@@ -2,24 +2,90 @@
* Created by weijian on 2016/10/26. * Created by weijian on 2016/10/26.
*/ */
import {Injectable} from "@angular/core"; import {Injectable, NgZone} from "@angular/core";
import {SettingsService} from "./settings.sevices"; import {Http} from "@angular/http";
import {ipcRenderer} from "electron"; import {Observable} from "rxjs/Observable";
import {EventEmitter} from "events";
import {App} from "./app";
const Aria2 = require('aria2');
@Injectable() @Injectable()
export class DownloadService { export class DownloadService {
aria2 = new Aria2();
baseURL = 'http://thief.mycard.moe/metalinks/'
appGidMap = new Map<App,string>();
gidAppMap = new Map<string,App>();
eventEmitter = new EventEmitter();
open = this.aria2.open();
constructor(private settingsService: SettingsService) { constructor(private ngZone: NgZone, private http: Http) {
ipcRenderer.send("download-message", "123"); this.aria2.onDownloadComplete = (gid)=> {
let app = this.gidAppMap.get(gid.gid);
if (app) {
this.appGidMap.delete(app);
this.gidAppMap.delete(gid.gid);
this.eventEmitter.emit(app.id, 'complete');
}
}
} }
sendEvent(event, args) { getComplete(app: App): Promise<App> {
ipcRenderer.send('') if (this.appGidMap.has(app)) {
return new Promise((resolve, reject)=> {
this.eventEmitter.once(app.id, (event)=> {
resolve(app);
})
});
}
} }
listenEvent() { getProgress(app: App): Observable<any> {
console.log(ipcRenderer); let gid = this.appGidMap.get(app);
return Observable.create((observer)=> {
let interval;
this.ngZone.runOutsideAngular(()=> {
interval = setInterval(()=> {
this.aria2.tellStatus(gid).then((status: any)=> {
if (status.status === 'complete') {
observer.complete();
} else if (status.status === "active") {
observer.next({total: status.totalLength, progress: status.completedLength})
} else if (status.status === "error") {
observer.error(status.errorCode)
}
});
}, 1000);
});
return ()=> {
clearInterval(interval);
}
});
} }
async addUris(apps: App[], path: string): Promise<App[]> {
let tasks = [];
for (let app of apps) {
let task = await this.addUri(app, path);
tasks.push(task);
}
return tasks;
}
async addUri(app: App, path: string): Promise<App> {
let id = app.id;
await this.open;
if (this.appGidMap.has(app)) {
return app;
} else {
let meta4link = `${this.baseURL}${id}.meta4`;
let response = await this.http.get(meta4link).toPromise();
let meta4 = btoa(response.text());
let gid = (await this.aria2.addMetalink(meta4, {dir: path}))[0];
this.appGidMap.set(app, gid);
this.gidAppMap.set(gid, app);
return app;
}
}
} }
...@@ -6,21 +6,18 @@ import {App} from "./app"; ...@@ -6,21 +6,18 @@ import {App} from "./app";
export class InstallConfig { export class InstallConfig {
app: App; app: App;
install: boolean; install: boolean;
installPath: string; installLibrary: string;
installDir: string; installDir: string;
createShortcut: boolean; createShortcut: boolean;
createDesktopShortcut: boolean; createDesktopShortcut: boolean;
references: InstallConfig[]; references: InstallConfig[];
constructor(app: App, installPath = ".", installDir = "", install = true, shortcut = false, desktopShortcut = false) { constructor(app: App, installLibrary = "", installDir = "", install = true, shortcut = false, desktopShortcut = false) {
this.app = app; this.app = app;
this.createShortcut = shortcut; this.createShortcut = shortcut;
this.createDesktopShortcut = desktopShortcut; this.createDesktopShortcut = desktopShortcut;
this.install = install; this.install = install;
this.installDir = installDir; this.installDir = installDir;
} this.installLibrary = installLibrary;
updateChecked() {
} }
} }
\ No newline at end of file
/**
* Created by weijian on 2016/11/2.
*/
import {Injectable} from "@angular/core";
import {App} from "./app";
import {InstallConfig} from "./install-config";
import * as path from "path";
import * as child_process from "child_process";
import * as mkdirp from "mkdirp";
import * as readline from "readline";
import * as fs from 'fs';
import {EventEmitter} from "events";
import {AppLocal} from "./app-local";
import {Http} from "@angular/http";
import ReadableStream = NodeJS.ReadableStream;
@Injectable()
export class InstallService {
tarPath: string;
installQueue: Map<App,InstallConfig> = new Map();
eventEmitter: EventEmitter = new EventEmitter();
installingQueue: Set<App> = new Set();
checksumUri = "http://thief.mycard.moe/checksums/";
constructor(private http: Http) {
if (process.platform === "win32") {
this.tarPath = path.join(process.resourcesPath, 'bin/tar.exe');
} else {
this.tarPath = "tar"
}
}
createDirectory(dir: string) {
return new Promise((resolve, reject)=> {
mkdirp(dir, resolve);
})
}
getComplete(app: App): Promise<App> {
return null;
}
extract(file: string, destPath: string) {
return new Promise((resolve, reject)=> {
let tarProcess = child_process.spawn(this.tarPath, ['xvf', file, '-C', destPath]);
let rl = readline.createInterface({
input: <ReadableStream>tarProcess.stderr,
});
rl.on('line', (input)=> {
});
tarProcess.on('exit', (code)=> {
if (code === 0) {
resolve();
} else {
reject(code);
}
})
});
}
async postInstall(app: App, appPath: string) {
let action = app.actions.get('install');
if (action) {
let env = Object.assign({}, action.env);
let command = [];
command.push(path.join(appPath, action.execute));
command.push(...action.args);
let open = action.open;
if (open) {
let openAction = open.actions.get("main");
env = Object.assign(env, openAction.env);
command.unshift(...openAction.args);
command.unshift(path.join(open.local.path, openAction.execute));
}
return new Promise((resolve, reject)=> {
let child = child_process.spawn(command.shift(), command, {
env: env,
stdio: 'inherit',
shell: true,
});
child.on('error', (error)=> {
console.log(error);
});
child.on('exit', (code)=> {
if (code === 0) {
resolve();
} else {
reject();
}
})
})
}
}
saveAppLocal(app: App) {
if (app.local) {
let a = JSON.stringify(app.local)
console.log(a);
localStorage.setItem(app.id, a);
}
}
async backupFiles(app: App, files: Iterable<string>) {
let backupPath = path.join(app.local.path, "backup");
await this.createDirectory(backupPath);
for (let file of files) {
await new Promise((resolve, reject)=> {
let oldPath = path.join(app.local.path, file);
let newPath = path.join(backupPath, file);
fs.rename(oldPath, newPath, resolve);
});
}
}
async doInstall() {
for (let app of this.installQueue.keys()) {
let depInstalled = app.findDependencies()
.every((dependency)=>dependency.isInstalled());
if (depInstalled && !this.installingQueue.has(app)) {
this.installingQueue.add(app);
let options = this.installQueue.get(app);
let checksumMap: Map<string,string> = await this.http.get(`${this.checksumUri}${app.id}`)
.map((response)=> {
let map = new Map<string,string>();
for (let line of response.text().split('\n')) {
if (line !== "") {
let [checksum,filename]=line.split(' ', 2);
map.set(filename, checksum);
}
}
return map;
}).toPromise();
let packagePath = path.join(options.installLibrary, 'downloading', `${app.id}.tar.xz`);
let destPath: string;
if (app.parent) {
let differenceSet = new Set<string>();
let parentFilesMap = app.parent.local.files;
for (let key of checksumMap.keys()) {
if (parentFilesMap.has(key)) {
differenceSet.add(key);
}
}
await this.backupFiles(app.parent, differenceSet);
destPath = app.parent.local.path;
} else {
destPath = path.join(options.installLibrary, app.id);
await this.createDirectory(destPath);
}
this.installQueue.delete(app);
await this.extract(packagePath, destPath);
await this.postInstall(app, destPath);
let local = new AppLocal();
local.path = destPath;
local.files = checksumMap;
local.version = app.version;
app.local = local;
this.saveAppLocal(app);
this.installingQueue.delete(app);
if (this.installQueue.size > 0) {
await this.doInstall()
}
}
}
}
add(app: App, options: InstallConfig) {
if (!this.installQueue.has(app)) {
this.installQueue.set(app, options);
if (!app.isInstalled()) {
this.doInstall()
}
}
}
}
\ No newline at end of file
...@@ -12,4 +12,30 @@ ...@@ -12,4 +12,30 @@
background-color: #336699; background-color: #336699;
height: 236px; height: 236px;
flex-shrink: 0; flex-shrink: 0;
}
#apps{
/*background-color: darkslategray;*/
width: 280px;
flex-shrink: 0;
overflow-y: auto;
background-color: #f5f5f5;
border-right: 1px solid #eee;
}
a {
display: block;
padding: 10px 20px 10px 20px;
}
.active {
background-color: #428bca;
}
.active > a {
color: #fff;
}
span {
margin-left: 8px;
} }
\ No newline at end of file
<!-- Begin page content --> <!-- Begin page content -->
<div id="main"> <div id="main">
<apps *ngIf="appsService.allApps"></apps> <div id="apps" *ngIf="apps">
<app-detail *ngIf="appsService._currentApp"></app-detail> <span *ngIf="grouped_apps.installed">已安装</span>
<ul *ngIf="grouped_apps.installed" class="nav nav-sidebar">
<li *ngFor="let app of grouped_apps.installed" [class.active]="app===currentApp">
<a (click)="chooseApp(app)" href="#">{{app.name}}</a>
</li>
</ul>
<span *ngIf="grouped_apps.yugioh">游戏王</span>
<ul *ngIf="grouped_apps.yugioh" class="nav nav-sidebar">
<li *ngFor="let app of grouped_apps.yugioh" [class.active]="app===currentApp">
<a (click)="chooseApp(app)" href="#">{{app.name}}</a>
</li>
</ul>
<span *ngIf="grouped_apps.touhou">东方 Project</span>
<ul *ngIf="grouped_apps.touhou" class="nav nav-sidebar">
<li *ngFor="let app of grouped_apps.touhou" [class.active]="app===currentApp">
<a (click)="chooseApp(app)" href="#">{{app.name}}</a>
</li>
</ul>
<span *ngIf="grouped_apps.touhou_pc98">东方旧作</span>
<ul *ngIf="grouped_apps.touhou_pc98" class="nav nav-sidebar">
<li *ngFor="let app of grouped_apps.touhou_pc98" [class.active]="app===currentApp">
<a (click)="chooseApp(app)" href="#">{{app.name}}</a>
</li>
</ul>
</div>
<app-detail *ngIf="currentApp" [currentApp]="currentApp"></app-detail>
<roster></roster> <roster></roster>
</div> </div>
<webview id="candy" [src]="candy_url" nodeintegration></webview> <webview id="candy" [src]="candy_url" nodeintegration></webview>
\ No newline at end of file
/** /**
* Created by zh99998 on 16/9/2. * Created by zh99998 on 16/9/2.
*/ */
import {Component} from "@angular/core"; import {Component, OnInit} from "@angular/core";
import {AppsService} from "./apps.service"; import {AppsService} from "./apps.service";
import {LoginService} from "./login.service"; import {LoginService} from "./login.service";
import {App, Category} from "./app";
import {DownloadService} from "./download.service";
@Component({ @Component({
selector: 'lobby', selector: 'lobby',
templateUrl: 'app/lobby.component.html', templateUrl: 'app/lobby.component.html',
styleUrls: ['app/lobby.component.css'], styleUrls: ['app/lobby.component.css'],
}) })
export class LobbyComponent { export class LobbyComponent implements OnInit {
candy_url; candy_url: string;
currentApp: App;
private apps: Map<string,App>;
constructor(private appsService: AppsService, private loginService: LoginService) { constructor(private appsService: AppsService, private loginService: LoginService,private downloadService:DownloadService) {
this.candy_url = './candy/index.html?jid=' + this.loginService.user.username + '@mycard.moe&password=' + this.loginService.user.external_id + '&nickname=' + this.loginService.user.username + '&autojoin=ygopro_china_north@conference.mycard.moe' this.candy_url = './candy/index.html?jid=' + this.loginService.user.username + '@mycard.moe&password=' + this.loginService.user.external_id + '&nickname=' + this.loginService.user.username + '&autojoin=ygopro_china_north@conference.mycard.moe'
} }
ngOnInit() {
this.appsService.loadApps()
.then((apps)=> {
this.apps = apps;
this.currentApp = this.apps.get("th06");
})
}
chooseApp(app: App) {
this.currentApp = app;
}
get grouped_apps() {
let contains = ["game", "music", "book"].map((value)=>Category[value]);
let result = {};
for (let app of this.apps.values()) {
if (contains.includes(app.category)) {
let tag;
if (app.isInstalled()) {
tag = 'installed';
} else {
tag = app.tags[0];
}
if (!result[tag]) {
result[tag] = []
}
result[tag].push(app)
}
}
return result
}
} }
...@@ -6,7 +6,6 @@ import {MyCardComponent} from "./mycard.component"; ...@@ -6,7 +6,6 @@ import {MyCardComponent} from "./mycard.component";
import {LoginComponent} from "./login.component"; import {LoginComponent} from "./login.component";
import {StoreComponent} from "./store.component"; import {StoreComponent} from "./store.component";
import {LobbyComponent} from "./lobby.component"; import {LobbyComponent} from "./lobby.component";
import {AppsComponent} from "./apps.component";
import {AppDetailComponent} from "./app-detail.component"; import {AppDetailComponent} from "./app-detail.component";
import {RosterComponent} from "./roster.component"; import {RosterComponent} from "./roster.component";
import {CommunityComponent} from "./community.component"; import {CommunityComponent} from "./community.component";
...@@ -15,12 +14,20 @@ import {AppsService} from "./apps.service"; ...@@ -15,12 +14,20 @@ import {AppsService} from "./apps.service";
import {TranslateModule} from "ng2-translate"; import {TranslateModule} from "ng2-translate";
import {SettingsService} from "./settings.sevices"; import {SettingsService} from "./settings.sevices";
import {LoginService} from "./login.service"; import {LoginService} from "./login.service";
import {DownloadService} from "./download.service";
import {InstallService} from "./install.service";
@NgModule({ @NgModule({
imports: [BrowserModule, FormsModule, ReactiveFormsModule, HttpModule, TranslateModule.forRoot()], imports: [BrowserModule, FormsModule, ReactiveFormsModule, HttpModule, TranslateModule.forRoot()],
declarations: [MyCardComponent, LoginComponent, StoreComponent, LobbyComponent, CommunityComponent, AppsComponent, AppDetailComponent, RosterComponent, YGOProComponent], declarations: [
MyCardComponent, LoginComponent, StoreComponent, LobbyComponent,
CommunityComponent, AppDetailComponent, RosterComponent, YGOProComponent,
],
bootstrap: [MyCardComponent], bootstrap: [MyCardComponent],
providers: [AppsService, SettingsService, LoginService], providers: [
AppsService, SettingsService, LoginService, DownloadService,
InstallService
],
schemas: [NO_ERRORS_SCHEMA] schemas: [NO_ERRORS_SCHEMA]
}) })
export class MyCard { export class MyCard {
......
...@@ -3,16 +3,32 @@ ...@@ -3,16 +3,32 @@
*/ */
import {Injectable} from "@angular/core"; import {Injectable} from "@angular/core";
import {remote} from "electron";
import * as path from "path";
@Injectable() @Injectable()
export class SettingsService { export class SettingsService {
static SETTING_LIBRARY = "library"; static SETTING_LIBRARY = "library";
libraries: [{"default": boolean,path: string}]; static defaultLibraries = [
{
"default": true,
path: path.join(remote.app.getPath("appData"), "library")
},
];
libraries: {"default": boolean,path: string}[];
getLibraries() { getLibraries() {
if (!this.libraries) { if (!this.libraries) {
let data = localStorage.getItem(SettingsService.SETTING_LIBRARY); let data = localStorage.getItem(SettingsService.SETTING_LIBRARY);
this.libraries = JSON.parse(data); if (!data) {
this.libraries = SettingsService.defaultLibraries;
localStorage.setItem(SettingsService.SETTING_LIBRARY,
JSON.stringify(SettingsService.defaultLibraries));
} else {
this.libraries = JSON.parse(data);
}
} }
return this.libraries; return this.libraries;
} }
...@@ -25,16 +41,23 @@ export class SettingsService { ...@@ -25,16 +41,23 @@ export class SettingsService {
} }
static SETTING_LOCALE = "locale"; static SETTING_LOCALE = "locale";
static defaultLocale = remote.app.getLocale();
locale: string; locale: string;
getLocale(): string { getLocale(): string {
if (!this.locale) { if (!this.locale) {
this.locale = localStorage.getItem(SettingsService.SETTING_LOCALE); let locale = localStorage.getItem(SettingsService.SETTING_LOCALE);
if (!locale) {
this.locale = SettingsService.defaultLocale;
localStorage.setItem(SettingsService.SETTING_LOCALE, SettingsService.defaultLocale);
} else {
this.locale = locale;
}
} }
return this.locale; return this.locale;
} }
setLocal(locale: string) { setLocale(locale: string) {
this.locale = locale; this.locale = locale;
localStorage.setItem(SettingsService.SETTING_LOCALE, locale); localStorage.setItem(SettingsService.SETTING_LOCALE, locale);
} }
......
/** /**
* Created by zh99998 on 16/9/2. * Created by zh99998 on 16/9/2.
*/ */
import {Component, OnInit, ChangeDetectorRef} from "@angular/core"; import {Component, OnInit, ChangeDetectorRef, Input} from "@angular/core";
import {AppsService} from "./apps.service"; import {AppsService} from "./apps.service";
import * as fs from "fs"; import * as fs from "fs";
import * as path from "path"; import * as path from "path";
...@@ -11,6 +11,7 @@ import {remote} from "electron"; ...@@ -11,6 +11,7 @@ import {remote} from "electron";
import * as ini from "ini"; import * as ini from "ini";
import {EncodeOptions} from "ini"; import {EncodeOptions} from "ini";
import {LoginService} from "./login.service"; import {LoginService} from "./login.service";
import {App} from "./app";
declare var $; declare var $;
...@@ -67,7 +68,8 @@ interface Room { ...@@ -67,7 +68,8 @@ interface Room {
styleUrls: ['app/ygopro.component.css'], styleUrls: ['app/ygopro.component.css'],
}) })
export class YGOProComponent implements OnInit { export class YGOProComponent implements OnInit {
app = this.appsService.searchApp('ygopro'); @Input()
app: App;
decks: string[] = []; decks: string[] = [];
current_deck: string; current_deck: string;
......
...@@ -94,8 +94,11 @@ ...@@ -94,8 +94,11 @@
"language" "language"
], ],
"dependencies": { "dependencies": {
"win32": [], "win32": [
"th06"
],
"darwin": [ "darwin": [
"th06",
"wine" "wine"
] ]
}, },
...@@ -1384,6 +1387,7 @@ ...@@ -1384,6 +1387,7 @@
} }
}, },
"version": { "version": {
"win32": "1.06",
"darwin": "1.06" "darwin": "1.06"
}, },
"download": { "download": {
...@@ -2188,6 +2192,7 @@ ...@@ -2188,6 +2192,7 @@
} }
}, },
"version": { "version": {
"win32": "1.06",
"darwin": "1.06" "darwin": "1.06"
}, },
"download": { "download": {
......
"use strict";
/**
* Created by weijian on 2016/10/27.
*/
const Rx = require("rxjs/Rx");
const {ipcMain} = require('electron');
const child_process_1 = require("child_process");
// import * as Aria2 from "aria2";
const Aria2 = require("aria2");
let a = (createProcess("D:/Github/mycard/bin/aria2c.exe", ['--enable-rpc', '--rpc-allow-origin-all', "--continue", "--split=10", "--min-split-size=1M", "--max-connection-per-server=10"]));
a.on('error', (error) => {
console.log(error);
});
// console.log(Aria2,2);
function createProcess(aria2c_path, args = []) {
return child_process_1.spawn(aria2c_path, args);
}
let options = {'host': 'localhost', 'port': 6800, 'secure': false};
let aria2 = new Aria2(options);
aria2.onDownloadComplete = (response) => {
console.log(response);
};
let open = aria2.open();
function addUri(uri, path) {
return open.then(() => {
return aria2.addUri(uri, { 'dir': path });
});
}
function pause(gid) {
return aria2.pause(gid);
}
function reportStatus() {
aria2.tellActive();
}
//ipcMain.on()
//# sourceMappingURL=aria2.js.map
\ No newline at end of file
{
"version": 3,
"file": "aria2.js",
"sourceRoot": "",
"sources": [
"aria2.ts"
],
"names": [],
"mappings": ";AAAA;;GAEG;AACH,MAAM,EAAE,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAC9B,MAAM,EAAC,OAAO,EAAC,GAAE,OAAO,CAAC,UAAU,CAAC,CAAC;AACrC,gCAAkC,eAAe,CAAC,CAAA;AAClD,kCAAkC;AAClC,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAE/B,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,iCAAiC,EAAE,CAAC,cAAc,EAAE,wBAAwB,EAAE,YAAY,EAAE,YAAY,EAAE,qBAAqB,EAAE,gCAAgC,CAAC,CAAC,CAAC,CAAA;AAC3L,CAAC,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK;IAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC;AACH,wBAAwB;AACxB,uBAAuB,WAAmB,EAAE,IAAI,GAAa,EAAE;IAC3D,MAAM,CAAC,qBAAK,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;AACpC,CAAC;AAED,IAAI,OAAO,GAAG,EAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAC,CAAA;AAClE,IAAI,KAAK,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;AAE/B,KAAK,CAAC,kBAAkB,GAAG,CAAC,QAAQ;IAChC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC1B,CAAC,CAAC;AAEF,IAAI,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;AACxB,gBAAgB,GAAa,EAAE,IAAY;IACvC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;QACb,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,EAAC,KAAK,EAAE,IAAI,EAAC,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;AACP,CAAC;AACD,eAAe,GAAW;IACtB,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;AAC3B,CAAC;AAED;IACI,KAAK,CAAC,UAAU,EAAE,CAAA;AACtB,CAAC;AAED,cAAc"
}
\ No newline at end of file
/**
* Created by weijian on 2016/10/27.
*/
const Rx = require("rxjs/Rx");
const {ipcMain}= require('electron');
import {ChildProcess, spawn} from "child_process";
// import * as Aria2 from "aria2";
const Aria2 = require("aria2");
let a = (createProcess("D:/Github/mycard/bin/aria2c.exe", ['--enable-rpc', '--rpc-allow-origin-all', "--continue", "--split=10", "--min-split-size=1M", "--max-connection-per-server=10"]))
a.on('error', (error)=> {
console.log(error);
});
// console.log(Aria2,2);
function createProcess(aria2c_path: string, args: string[] = []): ChildProcess {
return spawn(aria2c_path, args);
}
let options = {'host': 'localhost', 'port': 6800, 'secure': false}
let aria2 = new Aria2(options);
aria2.onDownloadComplete = (response)=> {
console.log(response);
};
let open = aria2.open();
function addUri(uri: string[], path: string) {
return open.then(()=> {
return aria2.addUri(uri, {'dir': path});
});
}
function pause(gid: string): Promise<string> {
return aria2.pause(gid)
}
function reportStatus() {
aria2.tellActive()
}
//ipcMain.on()
...@@ -103,7 +103,9 @@ function createAria2c() { ...@@ -103,7 +103,9 @@ function createAria2c() {
throw 'unsupported platform'; throw 'unsupported platform';
} }
//--split=10 --min-split-size=1M --max-connection-per-server=10 //--split=10 --min-split-size=1M --max-connection-per-server=10
let aria2c = child_process.spawn(aria2c_path, ['--enable-rpc', '--rpc-allow-origin-all', "--continue", "--split=10", "--min-split-size=1M", "--max-connection-per-server=10"]); let aria2c = child_process.spawn(aria2c_path,
['--enable-rpc', '--rpc-allow-origin-all', "--continue", "--split=10", "--min-split-size=1M", "--max-connection-per-server=10"],
{stdio: 'ignore'});
aria2c.on('data', (data)=> { aria2c.on('data', (data)=> {
console.log(data); console.log(data);
}); });
......
...@@ -58,6 +58,9 @@ ...@@ -58,6 +58,9 @@
"productName": "MyCard", "productName": "MyCard",
"appId": "com.mycard.mycard", "appId": "com.mycard.mycard",
"category": "public.app-category.social-networking", "category": "public.app-category.social-networking",
"extraResources": [
"bin"
],
"win": { "win": {
"iconUrl": "http://mycard.moe/logo.png", "iconUrl": "http://mycard.moe/logo.png",
"remoteReleases": true "remoteReleases": true
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
"target": "es6", "target": "es6",
"lib": [ "lib": [
"dom", "dom",
"es2016" "es2017"
], ],
"module": "commonjs", "module": "commonjs",
"moduleResolution": "node", "moduleResolution": "node",
......
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