Commit 7a8a61ec authored by 神楽坂玲奈's avatar 神楽坂玲奈

refactor

parent eb17e967
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = 0
trim_trailing_whitespace = false
# Indentation override
#[lib/**.js]
#[{package.json,.travis.yml}]
#[**/**.js]
# Auto detect text files and perform LF normalization
* text=auto
*.rb text
*.yml text
*.png binary
*.jpg binary
\ No newline at end of file
.idea
node_modules
jspm_packages
npm-debug.log
debug.log
src/**/*.js
!src/systemjs.config.extras.js
!src/systemjs.config.js
!src/systemjs-angular-loader.js
*.js.map
e2e/**/*.js
e2e/**/*.js.map
_test-output
_temp
/bin/
/app/**/*.js
/app/**/*.js.map
......@@ -16,4 +30,5 @@
Thumbs.db
messages.xlf
messages.xlf.bak
locale/*.xlf.bak
\ No newline at end of file
locale/*.xlf.bak
/.vscode/
{
"vsicons.presets.angular": true
}
\ No newline at end of file
<!--<h2>MoeCube 招募公告</h2>-->
<!--<p>MoeCube 伴随大家已经有 6 年了,在这 6 年间 MoeCube 作为一个同人平台很感谢得到大家的支持,现在 MoeCube 为了给支持的大家带来更好的体验,正在努力进行全新的改版的开发工作,希望可以得到大家的支持和帮助。</p>--><!--<p>职位:(前端)开发工程师</p>--><!--<p>负责平台客户端的开发,及网站和论坛相关的改版工作。</p>--><!--<p>职位描述:对 ACG 领域有一定的了解,会js等编程领域的专业技能,对软件开发具有一定的热情和自主能动性,认真严谨和团队意识。</p>--><!--<p>联系邮箱:admin@moecube.com</p>--><!--<p>工作地点:上海市长宁区(工资面议)</p>-->
<!--<h2>联系我们</h2>--><!--<dl>--><!--<dt>应聘</dt>--><!--<dd>admin@moecube.com</dd>--><!--<dt>投稿、合作、侵权投诉</dt>--><!--<dd>admin@moecube.com</dd>--><!--<dt>问题反馈</dt>--><!--<dd>admin@moecube.com</dd>--><!--</dl>-->
/**
* Created by zh99998 on 16/9/2.
*/
import {Component} from '@angular/core';
@Component({
moduleId: module.id,
selector: 'about',
templateUrl: 'about.component.html',
styleUrls: ['about.component.css'],
})
export class AboutComponent {
}
:host {
flex-grow: 1;
position: relative;
padding: 1rem 1rem 0 1rem;
background-blend-mode: color;
background-size: 100% auto !important;
background-repeat: no-repeat !important;
}
.list-group {
width: 20rem;
}
progress {
margin: 2px 0 0;
}
.carousel-inner img {
width: 100%;
}
.dependency {
margin-right: 0.8em;
}
#news p {
margin-bottom: 0;
}
#news a {
display: block;
}
#network {
display: inline-block;
vertical-align: middle;
width: 230px;
}
#network .input-group-btn > .btn:not(:last-child):not(.dropdown-toggle) {
border-bottom-right-radius: 0;
border-top-right-radius: 0;
}
#network .input-group-btn > .dropdown-toggle {
border-bottom-left-radius: 0;
border-top-left-radius: 0;
}
.custom-file {
width: 100%;
}
.custom-file-control:lang(en)::after {
content: initial;
}
.custom-file-control {
overflow: hidden;
white-space: nowrap;
}
h1 {
font-size: 28px;
}
#status {
font-size: 15px;
}
h2 {
font-size: 20px;
margin-bottom: 0;
}
.cover {
width: 128px;
height: 128px;
object-fit: contain;
box-shadow: 0 0 4px #ccc;
}
.banner {
width: 120px;
height: 45px;
object-fit: cover;
}
#main {
display: flex;
flex-direction: row;
}
.panel {
border: 1px solid #eceeef;
border-radius: 6px;
background: rgba(255, 255, 255, .7);
padding: .8rem;
margin-bottom: 1rem;
box-shadow: 0 0 15px rgba(0, 0, 0, .05);
position: relative;
}
#news h3 > .title {
font-size: 1rem;
color: inherit;
}
#news h3 {
padding-top: .8rem;
margin-bottom: 0;
}
#news p {
font-size: 14px;
color: #888;
}
#news a {
font-size: 14px;
color: #00a4d9;
}
#news span {
font-size: 12px;
color: #ccc;
}
.moreinfo {
color: #00a4d9;
display: block;
position: absolute;
top: 12px;
right: 18px;
font-size: 14px;
}
#local h2 {
margin-bottom: .8rem;
}
#main {
display: flex;
flex-direction: row;
}
#right {
margin-left: 1rem;
}
h1 {
font-size: 28px;
margin-bottom: 0;
}
#time {
font-size: 14px;
margin-bottom: .6rem;
visibility: hidden;
}
th {
width: 25%;
}
.moreinfo {
color: #00a4d9;
display: block;
position: absolute;
top: 12px;
right: 18px;
font-size: 14px;
}
#arena {
position: relative;
}
.btn-primary {
background-color: #00a4d9;
border-color: #008dbb;
}
/* 竞技场 */
h2 {
font-size: 20px;
}
dt, dd {
font-size: 14px;
}
table {
margin-top: .5rem;
margin-bottom: 0;
}
table th, table td {
border-top: none;
font-size: 14px;
font-weight: normal;
}
#game_info {
font-size: 14px;
margin-right: 8px;
display: flex;
flex-direction: column;
flex-grow: 1;
}
#game_info p {
flex-grow: 1;
}
#game_info_2 {
width: 160px;
flex-shrink: 0;
}
.tag {
font-size: 12px;
padding: 2px 5px;
}
#purchase-form .form-check {
padding-right: 8px;
}
#purchase-form legend {
font-size: 1rem;
margin-bottom: 0;
margin-top: .5rem;
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
import {App} from './app';
/**
* Created by zh99998 on 16/9/6.
*/
export class AppLocal {
path: string;
version: string;
files: Map<string, string>;
action: Map<string, {execute: string, args: string[], env: {}, open: App}>;
update(local: any) {
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: any = {};
for (let [k, v] of this.files) {
t[k] = v;
}
return {path: this.path, version: this.version, files: t};
}
}
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { LobbyComponent } from './lobby/lobby.component';
import { CubeDetailComponent } from './cube-detail/cube-detail.component';
import { LoginComponent } from './login/login.component';
import { AuthGuard } from './auth.guard';
import { CommunityComponent } from './community/community.component';
import { LoadingGuard } from './loading.guard';
import { ProfileComponent } from './profile/profile.component';
const routes: Routes = [
{ path: '', redirectTo: '/lobby', pathMatch: 'full' },
{ path: 'login', component: LoginComponent },
{ path: 'community', component: CommunityComponent },
{ path: 'profile', component: ProfileComponent },
{
path: 'lobby',
component: LobbyComponent,
canActivate: [AuthGuard],
children: [
{ path: ':id', component: CubeDetailComponent, canActivate: [LoadingGuard] }
]
}
];
@NgModule({
imports: [RouterModule.forRoot(routes, { useHash: true })],
exports: [RouterModule]
})
export class AppRoutingModule {
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { MoeCubeComponent } from './moecube/moecube.component';
import { LoginComponent } from './login/login.component';
import { LobbyComponent } from './lobby/lobby.component';
import { CubeDetailComponent } from './cube-detail/cube-detail.component';
import { RosterComponent } from './roster/roster.component';
import { YGOProComponent } from './ygopro/ygopro.component';
import { CandyComponent } from './candy/candy.component';
import { CubesService } from './cubes.service';
import { SettingsService } from './settings.sevices';
import { LoginService } from './login.service';
import { DownloadService } from './download.service';
import { AppRoutingModule } from './app-routing.module';
import { AuthGuard } from './auth.guard';
import { ProgressSpinnerComponent } from './progress-spinner/progress-spinner.component';
import { CommunityComponent } from './community/community.component';
import { LoadingGuard } from './loading.guard';
import { UpdateComponent } from './update/update.component';
import { WindowControlComponent } from './window-control/window-control.component';
import { CubeActionsComponent } from './cube-actions/cube-actions.component';
import { CubeArenaComponent } from './cube-arena/cube-arena.component';
import { CubeDescriptionComponent } from './cube-description/cube-description.component';
import { CubeNewsComponent } from './cube-news/cube-news.component';
import { CubeExpansionsComponent } from './cube-expansions/cube-expansions.component';
import { ProgressBarComponent } from './progress-bar/progress-bar.component';
import { ELECTRON_SCHEMA } from './electron-schema';
import { MaotamaComponent } from './maotama/maotama.component';
import { ProfileComponent } from './profile/profile.component';
@NgModule({
imports: [BrowserModule, FormsModule, ReactiveFormsModule, HttpModule, AppRoutingModule],
declarations: [
MoeCubeComponent, LoginComponent, LobbyComponent,
CubeDetailComponent, RosterComponent, YGOProComponent, CandyComponent,
ProgressSpinnerComponent, CommunityComponent, UpdateComponent, WindowControlComponent,
CubeActionsComponent, CubeArenaComponent, CubeDescriptionComponent, CubeNewsComponent, CubeExpansionsComponent,
ProgressBarComponent, MaotamaComponent, ProfileComponent
],
bootstrap: [MoeCubeComponent],
providers: [
CubesService, SettingsService, LoginService, DownloadService, AuthGuard, LoadingGuard
// 执行 xi18n 的时候注释掉这几行
// , {
// provide: LOCALE_ID,
// deps: [SettingsService],
// useFactory: (settingsService: SettingsService) => settingsService.getLocale()
// }
],
schemas: [ELECTRON_SCHEMA]
})
export class AppModule {
}
import {AppLocal} from './app-local';
export enum Category {
game,
music,
book,
runtime,
emulator,
language,
expansion,
module
}
// export enum DownloadStatus{
// downloading,
// init,
// installing,
// ready,
// updating,
// uninstalling,
// waiting,
// }
export interface Action {
execute: string;
args: string[];
env: {};
open?: App;
}
export class FileOptions {
sync: boolean;
ignore: boolean;
}
export class AppStatus {
progress: number;
total: number;
private _status: string;
get status(): string {
return this._status;
}
set status(status: string) {
this.progress = 0;
this.total = 0;
this.progressMessage = '';
this._status = status;
}
progressMessage: string;
}
export class App {
id: string;
name: string; // i18n
description: string; // i18n
author: string; // English Only
homepage: string;
developers: {name: string, url: string}[];
released_at: Date;
category: Category;
parent?: App;
actions: Map<string, Action>;
references: Map<string, App>;
dependencies: Map<string, App>;
locales: string[];
news: {title: string, url: string, image: string, updated_at: Date}[];
network: any;
tags: string[];
version: string;
local: AppLocal | null;
status: AppStatus;
conference: string | undefined;
files: Map<string, FileOptions>;
data: any;
icon: string;
cover: string;
background: string;
price: {[currency: string]: string};
key?: string;
static downloadUrl(app: App, platform: string, locale: string): string {
if (app.id === 'ygopro') {
return `https://api.moecube.com/metalinks/${app.id}-${process.platform}-${locale}/${app.version}`;
} else if (app.id === 'desmume') {
return `https://api.moecube.com/metalinks/${app.id}-${process.platform}/${app.version}`;
}
return `https://api.moecube.com/metalinks/${app.id}/${app.version}`;
}
static checksumUrl(app: App, platform: string, locale: string): string {
if (app.id === 'ygopro') {
return `https://api.moecube.com/checksums/${app.id}-${platform}-${locale}/${app.version}`;
} else if (app.id === 'desmume') {
return `https://api.moecube.com/checksums/${app.id}-${platform}/${app.version}`;
}
return `https://api.moecube.com/checksums/${app.id}/${app.version}`;
}
static updateUrl(app: App, platform: string, locale: string): string {
if (app.id === 'ygopro') {
return `https://api.moecube.com/update/${app.id}-${platform}-${locale}/${app.version}`;
} else if (app.id === 'desmume') {
return `https://api.moecube.com/update/${app.id}-${platform}/${app.version}`;
}
return `https://api.moecube.com/update/${app.id}/${app.version}`;
}
isBought(): Boolean {
// 免费或有 Key
return !this.price || !!this.key;
}
isLanguage() {
return this.category === Category.module && this.tags.includes('language');
}
reset() {
this.status.status = 'init';
this.local = null;
localStorage.removeItem(this.id);
}
isInstalled(): boolean {
return this.status.status !== 'init';
}
isReady(): boolean {
return this.status.status === 'ready';
}
isInstalling(): boolean {
return this.status.status === 'installing';
}
isWaiting(): boolean {
return this.status.status === 'waiting';
}
isDownloading(): boolean {
return this.status.status === 'downloading';
}
isUninstalling(): boolean {
return this.status.status === 'uninstalling';
}
isUpdating(): boolean {
return this.status.status === 'updating';
}
runnable(): boolean {
return [Category.game].includes(this.category);
}
progressMessage(): string | undefined {
return this.status.progressMessage;
}
constructor(app: any) {
this.id = app.id;
this.name = app.name;
this.description = app.description;
this.developers = app.developers;
this.released_at = app.released_at;
this.author = app.author;
this.homepage = app.homepage;
this.category = Category[app.category as string];
this.actions = app.actions;
this.dependencies = app.dependencies;
this.parent = app.parent;
this.references = app.references;
this.locales = app.locales;
this.news = app.news;
this.network = app.network;
this.tags = app.tags;
this.version = app.version;
this.conference = app.conference;
this.files = app.files;
this.data = app.data;
this.icon = app.icon;
this.cover = app.cover;
this.background = app.background;
this.price = app.price;
this.key = app.key;
}
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 [];
}
readyForInstall(): boolean {
let dependencies = this.findDependencies();
return dependencies.every((dependency) => dependency.isReady());
}
}
This diff is collapsed.
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { LoginService } from './login.service';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router, private loginService: LoginService) {
}
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if (this.loginService.logged_in) {
// logged in so return true
return true;
}
// not logged in so redirect to login page with the return url and return false
this.router.navigate(['/login']);
return false;
}
}
<div id="candy" data-MinOrMax="default">
</div>
<div style="position:absolute; top:5px; right:10px;">
<i id="minimize" class="fa fa-minus hover-color" (click)="minimize()" data-size="" i18n-title title="最小化"></i>
<i id="unminimize" class="fa fa-minus hover-color" (click)="restore()" data-size="" i18n-title title="取消最小化" hidden></i>
<i id="restore" class="fa fa fa-chevron-down hover-color" (click)="restore()" data-size="" i18n-title title="还原" hidden></i>
<i id="maximize" class="fa fa fa-chevron-up hover-color" (click)="maximize()" i18n-title title="最大化"></i>
</div>
This diff is collapsed.
/* Turn on custom 8px wide scrollbar */
::-webkit-scrollbar {
width: 8px; /* 1px wider than Lion. */
/* This is more usable for users trying to click it. */
background-color: rgba(0, 0, 0, 0);
-webkit-border-radius: 100px;
width: 8px; /* 1px wider than Lion. */
/* This is more usable for users trying to click it. */
background-color: rgba(0, 0, 0, 0);
-webkit-border-radius: 100px;
}
/* hover effect for both scrollbar area, and scrollbar 'thumb' */
::-webkit-scrollbar:active {
background-color: rgba(0, 0, 0, 0.05);
background-color: rgba(0, 0, 0, 0.05);
}
/* The scrollbar 'thumb' ...that marque oval shape in a scrollbar */
::-webkit-scrollbar-thumb:vertical {
/* This is the EXACT color of Mac OS scrollbars.
Yes, I pulled out digital color meter */
background: rgba(0, 0, 0, 0.1);
-webkit-border-radius: 100px;
/* This is the EXACT color of Mac OS scrollbars.
Yes, I pulled out digital color meter */
background: rgba(0, 0, 0, 0.1);
-webkit-border-radius: 100px;
}
::-webkit-scrollbar-thumb:vertical:active {
background: rgba(0, 0, 0, 0.2); /* Some darker color when you click it */
-webkit-border-radius: 100px;
background: rgba(0, 0, 0, 0.2); /* Some darker color when you click it */
-webkit-border-radius: 100px;
}
.scroll {
overflow-y: hidden;
overflow-y: hidden;
}
.scroll:hover {
overflow-y: auto;
overflow-y: auto;
}
.message-pane-wrapper, .message-form-wrapper {
margin-right: 190px;
margin-right: 190px;
}
.roster-pane, #chat-toolbar {
width: 190px
width: 190px
}
#candy {
background-color: #f7f7f9;
background-color: #f7f7f9;
}
#chat-tabs li {
box-shadow: 0 0 1px 1px #ccc;
box-shadow: 0 0 1px 1px #ccc;
}
#chat-tabs a {
color: #999;
background-color: #ececec;
color: #999;
background-color: #ececec;
}
#chat-tabs .active a.label {
background-color: white;
background-color: white;
}
#chat-tabs .active .transition {
background: white none;
background: white none;
}
#chat-tabs .transition {
background: #ececec none;
background: #ececec none;
}
.message-pane-wrapper {
background-color: white;
padding: 0;
background-color: white;
padding: 0;
}
.message-pane li {
border-bottom: none;
box-shadow: none;
padding: 0 5px;
border-bottom: none;
box-shadow: none;
padding: 0 5px;
}
.message-pane li > div {
padding: 0 0 0 150px;
line-height: 28px;
padding: 0 0 0 150px;
line-height: 28px;
}
.message-pane .label {
margin-left: -150px;
width: 130px;
margin-left: -150px;
width: 130px;
}
.roster-pane {
background-color: initial;
border-top: none;
box-shadow: none;
margin: 30px 0 32px 0;
background-color: initial;
border-top: none;
box-shadow: none;
margin: 30px 0 32px 0;
}
.roster-pane .user {
border-bottom: none;
box-shadow: none;
color: black;
border-bottom: none;
box-shadow: none;
color: black;
}
.roster-pane .user:hover {
background-color: #ebf3f8;
background-color: #ebf3f8;
}
#chat-toolbar {
position: absolute;
background-color: initial;
border-top: 1px solid #eee;
box-shadow: none;
position: absolute;
background-color: initial;
border-top: 1px solid #eee;
box-shadow: none;
}
.message-form-wrapper {
position: absolute;
border-top: 1px solid #eee;
position: absolute;
border-top: 1px solid #eee;
}
.message-form {
position: absolute;
margin-right: 20px;
position: absolute;
margin-right: 20px;
}
.message-form input.submit {
position: absolute;
margin-right: 0
position: absolute;
margin-right: 0
}
.roster-pane .label {
text-shadow: none
text-shadow: none
}
#candy {
border-top: 1px solid #eee;
box-shadow: inset 0 1px 2px white;
border-top: 1px solid #eee;
box-shadow: inset 0 1px 2px white;
}
.usercount span {
background-color: initial;
color: #a7a7a7;
background-color: initial;
color: #a7a7a7;
}
#chat-modal.modal-common {
position: absolute;
position: absolute;
}
/*#context-menu {*/
......@@ -150,27 +150,27 @@
/*}*/
#context-menu ul {
overflow-y: auto;
max-height: 170px;
overflow-y: auto;
max-height: 170px;
}
/*#context-menu {*/
/**/
/*}*/
.message-pane {
-webkit-user-select: auto;
-webkit-user-select: auto;
}
.roster-pane .user {
display: inherit;
opacity: inherit;
display: inherit;
opacity: inherit;
}
.hover-color{
color:#a7a7a7;
padding:0 5px;
.hover-color {
color: #a7a7a7;
padding: 0 5px;
}
.hover-color:hover{
color:#000;
}
\ No newline at end of file
.hover-color:hover {
color: #000;
}
<div id="candy" data-MinOrMax="default">
</div>
<div style="position:absolute; top:5px; right:10px;">
<i id="minimize" class="fa fa-minus hover-color" (click)="minimize()" data-size="" i18n-title title="最小化"></i>
<i id="unminimize" class="fa fa-minus hover-color" (click)="restore()" data-size="" i18n-title title="取消最小化"
hidden></i>
<i id="restore" class="fa fa fa-chevron-down hover-color" (click)="restore()" data-size="" i18n-title title="还原"
hidden></i>
<i id="maximize" class="fa fa fa-chevron-up hover-color" (click)="maximize()" i18n-title title="最大化"></i>
</div>
This diff is collapsed.
:host {
display: flex;
}
:host, webview {
flex: 1;
}
<webview src="https://ygobbs.com" (new-window)="openExternal($event.url)"></webview>
/**
* Created by zh99998 on 16/9/2.
*/
import { Component } from '@angular/core';
import { shell } from 'electron';
@Component({
selector: 'community',
templateUrl: './community.component.html',
styleUrls: ['./community.component.css'],
})
export class CommunityComponent {
openExternal(url: string) {
shell.openExternal(url);
}
}
/* 安装、导入 modal */
.dependency {
margin-right: 0.8em;
}
.custom-file {
width: 100%;
}
.custom-file-control:lang(en)::after {
content: initial;
}
.custom-file-control {
overflow: hidden;
white-space: nowrap;
}
/* 标题 */
#right {
margin-left: 1rem;
}
h1 {
font-size: 28px;
margin-bottom: 0;
}
.cover {
width: 128px;
height: 128px;
object-fit: contain;
box-shadow: 0 0 4px #ccc;
}
.banner {
width: 120px;
height: 45px;
object-fit: cover;
}
#time {
font-size: 14px;
margin-bottom: .6rem;
visibility: hidden;
}
/* Working */
#status {
font-size: 15px;
}
/* Ready */
.btn-primary {
background-color: #00a4d9;
border-color: #008dbb;
}
This diff is collapsed.
/**
* Created by zh99998 on 16/9/2.
*/
import { ChangeDetectorRef, Component, ElementRef, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { Cube, InstallOption } from '../cube';
import { CubesService } from '../cubes.service';
import { SettingsService } from '../settings.sevices';
import { ActivatedRoute } from '@angular/router';
import { LoginService } from '../login.service';
import { DownloadService } from '../download.service';
import { Http } from '@angular/http';
import * as fs from 'fs';
import * as path from 'path';
import { remote } from 'electron';
import * as $ from 'jquery';
import 'bootstrap';
@Component({
selector: 'cube-actions',
templateUrl: './cube-actions.component.html',
styleUrls: ['./cube-actions.component.css'],
})
export class CubeActionsComponent implements OnInit, OnChanges {
@Input()
currentCube: Cube;
platform = process.platform;
installOption: InstallOption;
availableLibraries: string[] = [];
references: Cube[];
referencesInstall: { [id: string]: boolean };
import_path: string;
payment = 'alipay';
creating_order = false;
constructor(private cubesService: CubesService, private settingsService: SettingsService,
private downloadService: DownloadService, private ref: ChangeDetectorRef, private el: ElementRef,
private http: Http, private loginService: LoginService, private route: ActivatedRoute) {
}
async ngOnInit(): Promise<void> {
let volume = 'A';
for (let i = 0; i < 26; i++) {
await new Promise((resolve, reject) => {
let currentVolume = String.fromCharCode(volume.charCodeAt(0) + i) + ':';
fs.access(currentVolume, (error) => {
if (!error) {
// 判断是否已经存在Library
if (this.libraries.every((library) => !library.startsWith(currentVolume))) {
this.availableLibraries.push(currentVolume);
}
}
resolve();
});
});
}
}
async ngOnChanges(changes: SimpleChanges) {
// if (changes.currentCube) {
// this.updateInstallOption(this.currentCube);
// }
if (this.currentCube.isBought()) {
$('#purchase-modal-alipay').modal('hide');
}
}
updateInstallOption(app: Cube) {
this.installOption = new InstallOption(app);
// console.log(this.installOption);
this.installOption.installLibrary = this.settingsService.getDefaultLibrary().path;
this.references = Array.from(app.references.values());
this.referencesInstall = {};
for (let reference of this.references) {
if (reference.isLanguage()) {
// 对于语言包,只有在语言包的locales比游戏本身的更加合适的时候才默认勾选
// 这里先偷个懒,中文环境勾选中文语言包,非中文环境勾选非中文语言包
this.referencesInstall[reference.id] =
reference.locales[0].startsWith('zh') === this.settingsService.getLocale().startsWith('zh');
} else {
this.referencesInstall[reference.id] = true;
}
}
// https://plus.google.com/+%E7%A5%9E%E6%A5%BD%E5%9D%82%E7%8E%B2%E5%A5%88/posts/1ngiNvqhM7C
this.ref.detectChanges();
}
get libraries(): string[] {
return this.settingsService.getLibraries().map((item) => item.path);
}
async install(targetApp: Cube, options: InstallOption, referencesInstall: { [id: string]: boolean }) {
$('#install-modal').modal('hide');
try {
await this.cubesService.install(targetApp, options);
for (let [id, install] of Object.entries(referencesInstall)) {
if (install) {
let reference = targetApp.references.get(id)!;
console.log('reference install ', id, targetApp, targetApp.references, reference);
await this.cubesService.install(reference, options);
}
}
} catch (error) {
console.error(error);
//noinspection TsLint
new Notification(targetApp.name, { body: '下载失败' });
}
}
async selectLibrary() {
if (this.installOption.installLibrary.startsWith('create_')) {
let volume = this.installOption.installLibrary.slice(7);
let library = path.join(volume, 'MoeCubeLibrary');
try {
await this.cubesService.createDirectory(library);
this.installOption.installLibrary = library;
this.settingsService.addLibrary(library, true);
} catch (error) {
this.installOption.installLibrary = this.settingsService.getDefaultLibrary().path;
alert('无法创建指定目录');
} finally {
let index = this.availableLibraries.findIndex((l) => {
return l === volume;
});
this.availableLibraries.splice(index, 1);
}
} else {
this.settingsService.setDefaultLibrary({ path: this.installOption.installLibrary, 'default': true });
}
this.installOption.installLibrary = this.settingsService.getDefaultLibrary().path;
}
selectDir() {
return remote.dialog.showOpenDialog({ properties: ['openFile', 'openDirectory'] })[0];
}
runApp(app: Cube) {
this.cubesService.runApp(app);
}
custom(app: Cube) {
this.cubesService.runApp(app, 'custom');
}
async importGame(targetApp: Cube, option: InstallOption, referencesInstall: { [id: string]: boolean }) {
$('#import-modal').modal('hide');
let dir = path.dirname(this.import_path);
// TODO: 执行依赖和references安装
try {
await this.cubesService.importApp(targetApp, dir, option);
for (let [id, install] of Object.entries(referencesInstall)) {
if (install) {
let reference = targetApp.references.get(id)!;
console.log('reference install ', id, targetApp, targetApp.references, reference);
await this.cubesService.install(reference, option);
}
}
} catch (error) {
console.error(error);
//noinspection TsLint
new Notification(targetApp.name, { body: '导入失败' });
}
}
async verifyFiles(app: Cube) {
try {
await this.cubesService.update(app, true);
let installedMods = this.cubesService.findChildren(app).filter((child) => {
return child.parent === app && child.isInstalled() && child.isReady();
});
for (let mod of installedMods) {
await this.cubesService.update(mod, true);
}
} catch (e) {
//noinspection TsLint
new Notification(app.name, { body: '校验失败' });
console.error(e);
}
}
async selectImport(app: Cube) {
let main = app.actions.get('main');
if (!main) {
return;
}
if (!main.execute) {
return;
}
let filename = main.execute.split('/')[0];
let extname = path.extname(filename).slice(1);
let filePaths = await new Promise((resolve, reject) => {
remote.dialog.showOpenDialog({
filters: [{ name: filename, extensions: [extname] }],
properties: ['openFile']
}, resolve);
});
if (filePaths && filePaths[0]) {
this.import_path = filePaths[0];
}
}
async purchase() {
this.creating_order = true;
let data = new URLSearchParams();
data.set('app_id', this.currentCube.id);
data.set('user_id', this.loginService.user.email);
data.set('currency', 'cny');
data.set('payment', this.payment);
try {
let { url } = await this.http.post('https://api.moecube.com/orders', data).map(response => response.json()).toPromise();
open(url);
$('#purchase-modal').modal('hide');
$('#purchase-modal-alipay').modal('show');
} catch (error) {
console.log(error);
if (error.status === 409) {
alert('卖完了 /\\');
} else if (error.status === 403) {
alert('已经购买过 /\\');
} else {
alert('出错了 /\\');
}
}
this.creating_order = false;
}
}
:host {
position: relative;
}
.moreinfo {
color: #00a4d9;
display: block;
position: absolute;
top: 12px;
right: 18px;
font-size: 14px;
}
h2 {
font-size: 20px;
}
dt, dd {
font-size: 14px;
}
table {
margin-top: .5rem;
margin-bottom: 0;
}
table th, table td {
border-top: none;
font-size: 14px;
font-weight: normal;
}
<h2 i18n>排位成绩</h2>
<ng-template #loading>
loading...
</ng-template>
<table *ngIf="points; else loading" class="table table-sm">
<tbody>
<tr>
<th i18n>竞技排名</th>
<td>{{points.arena_rank}}</td>
<th i18n>娱乐排名</th>
<td>{{points.exp_rank}}</td>
</tr>
<tr>
<th i18n>竞技胜率</th>
<td>{{points.athletic_wl_ratio}}%</td>
<th i18n>经验</th>
<td>{{points.exp}}</td>
</tr>
<tr>
<th i18n>胜场</th>
<td>{{points.athletic_win}}</td>
<th i18n>胜场</th>
<td>{{points.entertain_win}}</td>
</tr>
<tr>
<th i18n>负场</th>
<td>{{points.athletic_lose}}</td>
<th i18n>负场</th>
<td>{{points.entertain_lose}}</td>
</tr>
<tr>
<th i18n>平局</th>
<td>{{points.athletic_draw}}</td>
<th i18n>平局</th>
<td>{{points.entertain_draw}}</td>
</tr>
<tr>
<th i18n>总场</th>
<td>{{points.athletic_all}}</td>
<th i18n>总场</th>
<td>{{points.entertain_all}}</td>
</tr>
</tbody>
</table>
<a i18n href="https://moecube.com/ygopro/arena/" target="_blank" class="moreinfo">更多资料</a>
/**
* Created by zh99998 on 16/9/2.
*/
import { Component, Input, OnInit } from '@angular/core';
import { Http } from '@angular/http';
import { LoginService } from '../login.service';
import { Cube } from '../cube';
export interface Points {
exp: number;
exp_rank: number;
pt: number;
arena_rank: number;
win: number;
lose: number;
draw: number;
all: number;
ratio: number;
}
@Component({
selector: 'cube-arena',
templateUrl: './cube-arena.component.html',
styleUrls: ['./cube-arena.component.css'],
})
export class CubeArenaComponent implements OnInit {
@Input()
currentCube: Cube;
points: Points;
constructor(private http: Http, private loginService: LoginService) {
}
async ngOnInit() {
this.points = await this.http.get('https://moecube.com/ygopro/api/user', { params: { username: this.loginService.user.username } })
.map((response) => response.json()).toPromise();
}
}
.panel {
display: flex;
border: 1px solid #eceeef;
border-radius: 6px;
background: rgba(255, 255, 255, .7);
padding: .8rem;
margin-bottom: 1rem;
box-shadow: 0 0 15px rgba(0, 0, 0, .05);
position: relative;
}
#left {
font-size: 14px;
margin-right: 8px;
display: flex;
flex-direction: column;
flex-grow: 1;
}
#left p {
flex-grow: 1;
}
#right {
width: 160px;
flex-shrink: 0;
}
.tag {
font-size: 12px;
padding: 2px 5px;
}
<div class="panel" id="left">
<p [innerHTML]="currentCube.description"></p>
<div id="tags" *ngIf="currentCube.tags">
<div i18n *ngFor="let tag of currentCube.tags" class="btn btn-sm btn-danger tag">{tag, select, installed {已安装} test {测试} recommend {推荐} mysterious {迷之物体} touhou {东方 Project} touhou_pc98 {东方旧作} runtime_installed{已安装的运行库} }</div>
</div>
</div>
<div class="panel" id="right">
<dl>
<dt i18n>开发</dt>
<dd>
<div *ngFor="let developer of currentCube.developers">
<a *ngIf="developer.url" target="_blank" [href]="developer.url">{{developer.name}}</a>
<span *ngIf="!developer.url">{{developer.name}}</span>
</div>
</dd>
<dt i18n>发行日期</dt>
<dd>{{currentCube.released_at | date:'mediumDate'}}</dd>
</dl>
</div>
/**
* Created by zh99998 on 16/9/2.
*/
import { Component, Input, OnInit } from '@angular/core';
import { remote } from 'electron';
import { Cube } from '../cube';
@Component({
selector: 'cube-description',
templateUrl: './cube-description.component.html',
styleUrls: ['./cube-description.component.css'],
})
export class CubeDescriptionComponent {
@Input()
currentCube: Cube;
}
:host {
flex-grow: 1;
position: relative;
padding: 1rem 1rem 0 1rem;
background-blend-mode: color;
background-size: 100% auto !important;
background-repeat: no-repeat !important;
overflow-y: auto;
}
.panel {
display: flex;
border: 1px solid #eceeef;
border-radius: 6px;
background: rgba(255, 255, 255, .7);
padding: .8rem;
margin-bottom: 1rem;
box-shadow: 0 0 15px rgba(0, 0, 0, .05);
position: relative;
}
/*h2 {*/
/*font-size: 20px;*/
/*margin-bottom: 0;*/
/*}*/
#local h2 {
margin-bottom: .8rem;
}
th {
width: 25%;
}
#purchase-form .form-check {
padding-right: 8px;
}
#purchase-form legend {
font-size: 1rem;
margin-bottom: 0;
margin-top: .5rem;
}
<ng-container *ngIf="currentCube">
<cube-actions [currentCube]="currentCube" class="panel"></cube-actions>
<cube-arena *ngIf="currentCube.useArena()" [currentCube]="currentCube" class="panel"></cube-arena>
<cube-description *ngIf="currentCube.useDescription()" [currentCube]="currentCube" class="d-flex"></cube-description>
<cube-news *ngIf="currentCube.useNews()" [currentCube]="currentCube" class="panel"></cube-news>
<cube-expansions *ngIf="currentCube.useExpansions()" [currentCube]="currentCube" class="panel"></cube-expansions>
<!-- 设计未定,暂不封装 -->
<div *ngIf="currentCube.isReady()" class="panel panel-default">
<h2 i18n>本地文件</h2>
<div>
<button i18n (click)="cubesService.browse(currentCube)" [disabled]="!cubesService.allReady(currentCube)" type="button" class="btn btn-secondary btn-sm">浏览本地文件</button>
<button i18n type="button" (click)="verifyFiles(currentCube)" [disabled]="!cubesService.allReady(currentCube)" class="btn btn-secondary btn-sm">校验完整性</button>
<button i18n (click)="uninstall(currentCube)" [disabled]="!cubesService.allReady(currentCube)" type="button" class="btn btn-secondary btn-sm">卸载</button>
</div>
</div>
</ng-container>
import { ChangeDetectorRef, Component, ElementRef, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { clipboard, remote } from 'electron';
import * as path from 'path';
import * as fs from 'fs';
import * as $ from 'jquery';
import { Http, URLSearchParams } from '@angular/http';
import { Cube, InstallOption } from '../cube';
import { CubesService } from '../cubes.service';
import { SettingsService } from '../settings.sevices';
import { DownloadService } from '../download.service';
import { LoginService } from '../login.service';
import { ActivatedRoute, Params } from '@angular/router';
declare const Notification: any;
// declare interface Window {
// adsbygoogle: any[];
// }
//
// declare var adsbygoogle: any[];
@Component({
selector: 'cube-detail',
templateUrl: './cube-detail.component.html',
styleUrls: ['./cube-detail.component.css'],
})
export class CubeDetailComponent implements OnInit, OnChanges {
currentCube: Cube;
platform = process.platform;
installOption: InstallOption;
availableLibraries: string[] = [];
references: Cube[];
referencesInstall: { [id: string]: boolean };
import_path: string;
background: string;
// points: Points;
tags: {};
payment = 'alipay';
creating_order = false;
constructor(private cubesService: CubesService, private settingsService: SettingsService,
private downloadService: DownloadService, private ref: ChangeDetectorRef, private el: ElementRef,
private http: Http, private loginService: LoginService, private route: ActivatedRoute) {
this.tags = this.settingsService.getLocale().startsWith('zh') ? {
'recommend': '推荐',
'mysterious': '迷之物体',
'touhou': '东方 Project',
'touhou_pc98': '东方旧作',
'language': '语言包'
} : {
'recommend': 'Recommended',
'mysterious': 'Something',
'touhou': 'Touhou Project',
'touhou_pc98': 'Touhou old series',
'language': 'Language Pack'
};
}
async ngOnInit(): Promise<void> {
this.route.params
.switchMap((params: Params) => this.cubesService.getCube(params['id']))
.subscribe(async (cube: Cube) => {
this.currentCube = cube;
this.cubesService.lastVisited = cube;
if (this.currentCube.background) {
this.el.nativeElement.style.background = `url("${this.currentCube.background}") rgba(255,255,255,.8)`;
} else {
this.el.nativeElement.style.background = 'white';
}
// 我不知道这里出现了什么问题,按理说点击鼠标造成的事件,应当是能自动检测的,不知道这里为什么不行
this.ref.detectChanges();
// let top = await this.http.get('https://ygobbs.com/top.json').map(response => response.json()).toPromise();
// console.log(top.topic_list.topics);
});
let volume = 'A';
for (let i = 0; i < 26; i++) {
await new Promise((resolve, reject) => {
let currentVolume = String.fromCharCode(volume.charCodeAt(0) + i) + ':';
fs.access(currentVolume, (err) => {
if (!err) {
// 判断是否已经存在Library
if (this.libraries.every((library) => !library.startsWith(currentVolume))) {
this.availableLibraries.push(currentVolume);
}
}
resolve();
});
});
}
}
async ngOnChanges(changes: SimpleChanges) {
if (this.currentCube.isBought()) {
$('#purchase-modal-alipay').modal('hide');
}
}
updateInstallOption(app: Cube) {
this.installOption = new InstallOption(app);
this.installOption.installLibrary = this.settingsService.getDefaultLibrary().path;
this.references = Array.from(app.references.values());
console.log(this.references);
this.referencesInstall = {};
for (let reference of this.references) {
if (reference.isLanguage()) {
// 对于语言包,只有在语言包的locales比游戏本身的更加合适的时候才默认勾选
// 这里先偷个懒,中文环境勾选中文语言包,非中文环境勾选非中文语言包
this.referencesInstall[reference.id] =
reference.locales[0].startsWith('zh') === this.settingsService.getLocale().startsWith('zh');
} else {
this.referencesInstall[reference.id] = true;
}
}
}
get libraries(): string[] {
return this.settingsService.getLibraries().map((item) => item.path);
}
get news() {
return this.currentCube.news;
}
async installMod(mod: Cube) {
let option = new InstallOption(mod, path.dirname(mod.parent!.local!.path));
await this.install(mod, option, {});
}
async uninstall(app: Cube) {
if (confirm('确认删除?')) {
try {
await this.cubesService.uninstall(app);
} catch (e) {
alert(e);
}
}
}
async install(targetApp: Cube, options: InstallOption, referencesInstall: { [id: string]: boolean }) {
$('#install-modal').modal('hide');
try {
await this.cubesService.install(targetApp, options);
for (let [id, install] of Object.entries(referencesInstall)) {
if (install) {
let reference = targetApp.references.get(id)!;
console.log('reference install ', id, targetApp, targetApp.references, reference);
await this.cubesService.install(reference, options);
}
}
} catch (e) {
console.error(e);
//noinspection TsLint
new Notification(targetApp.name, { body: '下载失败' });
}
}
async selectLibrary() {
if (this.installOption.installLibrary.startsWith('create_')) {
let volume = this.installOption.installLibrary.slice(7);
let library = path.join(volume, 'MoeCubeLibrary');
try {
await this.cubesService.createDirectory(library);
this.installOption.installLibrary = library;
this.settingsService.addLibrary(library, true);
} catch (e) {
this.installOption.installLibrary = this.settingsService.getDefaultLibrary().path;
alert('无法创建指定目录');
} finally {
let index = this.availableLibraries.findIndex((l) => {
return l === volume;
});
this.availableLibraries.splice(index, 1);
}
} else {
this.settingsService.setDefaultLibrary({ path: this.installOption.installLibrary, 'default': true });
}
this.installOption.installLibrary = this.settingsService.getDefaultLibrary().path;
}
selectDir() {
let dir = remote.dialog.showOpenDialog({ properties: ['openFile', 'openDirectory'] });
console.log(dir);
// this.cubesService.installOption.installDir = dir[0];
return dir[0];
}
runApp(app: Cube) {
this.cubesService.runApp(app);
}
custom(app: Cube) {
this.cubesService.runApp(app, 'custom');
}
async importGame(targetApp: Cube, option: InstallOption, referencesInstall: { [id: string]: boolean }) {
$('#import-modal').modal('hide');
let dir = path.dirname(this.import_path);
// TODO: 执行依赖和references安装
try {
await this.cubesService.importApp(targetApp, dir, option);
for (let [id, install] of Object.entries(referencesInstall)) {
if (install) {
let reference = targetApp.references.get(id)!;
console.log('reference install ', id, targetApp, targetApp.references, reference);
await this.cubesService.install(reference, option);
}
}
} catch (e) {
console.error(e);
//noinspection TsLint
new Notification(targetApp.name, { body: '导入失败' });
}
}
async verifyFiles(app: Cube) {
try {
await this.cubesService.update(app, true);
let installedMods = this.cubesService.findChildren(app).filter((child) => {
return child.parent === app && child.isInstalled() && child.isReady();
});
for (let mod of installedMods) {
await this.cubesService.update(mod, true);
}
} catch (e) {
//noinspection TsLint
new Notification(app.name, { body: '校验失败' });
console.error(e);
}
}
copy(text: string) {
clipboard.writeText(text);
}
async selectImport(app: Cube) {
let main = app.actions.get('main');
if (!main) {
return;
}
if (!main.execute) {
return;
}
let filename = main.execute.split('/')[0];
let extname = path.extname(filename).slice(1);
// let remote = require('electron').remote
let filePaths = await new Promise((resolve, reject) => {
remote.dialog.showOpenDialog({
filters: [{ name: filename, extensions: [extname] }],
properties: ['openFile']
}, resolve);
});
if (filePaths && filePaths[0]) {
this.import_path = filePaths[0];
}
}
// onPoints(points: Points) {
// this.points = points;
// }
async purchase() {
this.creating_order = true;
let data = new URLSearchParams();
data.set('app_id', this.currentCube.id);
data.set('user_id', this.loginService.user.email);
data.set('currency', 'cny');
data.set('payment', this.payment);
try {
let { url } = await this.http.post('https://api.moecube.com/orders', data).map(response => response.json()).toPromise();
open(url);
$('#purchase-modal').modal('hide');
$('#purchase-modal-alipay').modal('show');
} catch (error) {
console.log(error);
if (error.status === 409) {
alert('卖完了 /\\');
} else if (error.status === 403) {
alert('已经购买过 /\\');
} else {
alert('出错了 /\\');
}
}
this.creating_order = false;
}
}
i {
line-height: 1.5;
color: #5e5e5e;
padding-top: .425rem;
padding-bottom: .425rem;
}
<table class="table table-striped" *ngIf="mods.length">
<thead class="thead-inverse">
<tr>
<th>#</th>
<th i18n>名称</th>
<th i18n>操作</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let mod of mods; let i = index">
<th scope="row">{{i + 1}}</th>
<td>{{mod.name}}</td>
<td>
<button i18n *ngIf="mod.isReady()" [disabled]="mod.isInstalled() && !cubesService.allReady(mod)" (click)="uninstall(mod)" type="button" class="btn btn-danger btn-sm">卸载</button>
<button i18n *ngIf="!mod.isInstalled()" (click)="installMod(mod)" [disabled]="mod.isInstalled()&&!cubesService.allReady(mod)" type="button" class="btn btn-primary btn-sm">安装</button>
<progress-bar [value]="mod.status.progress / mod.status.total"></progress-bar>
<progress *ngIf="mod.isWorking()" class="progress progress-striped" [class.progress-animated]="" value="{{mod.status.total ? mod.status.progress : 1}}" max="{{mod.status.total}}"></progress>
<!--<div i18n *ngIf="mod.isWaiting()">等待安装...</div>-->
</td>
</tr>
</tbody>
</table>
/**
* Created by zh99998 on 16/9/2.
*/
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
import { Cube } from '../cube';
import { CubesService } from '../cubes.service';
@Component({
selector: 'cube-expansions',
templateUrl: './cube-expansions.component.html',
styleUrls: ['./cube-expansions.component.css'],
})
export class CubeExpansionsComponent implements OnChanges {
@Input()
currentCube: Cube;
mods: Cube[];
constructor(public cubesService: CubesService) {
}
ngOnChanges(changes: SimpleChanges) {
if (changes.currentCube) {
if (this.currentCube.isReady()) {
this.mods = this.cubesService.findChildren(this.currentCube);
} else {
this.mods = [];
}
}
}
}
p {
margin-bottom: 0;
}
a {
display: block;
}
h3 {
padding-top: .8rem;
margin-bottom: 0;
}
h3 > .title {
font-size: 1rem;
color: inherit;
}
p {
font-size: 14px;
color: #888;
}
a {
font-size: 14px;
color: #00a4d9;
}
span {
font-size: 12px;
color: #ccc;
}
<h2 i18n>新闻</h2>
<div id="news" *ngFor="let item of news">
<h3><a class="title" [href]="item.url" target="_blank">{{item.title}}</a></h3>
<span>{{item.updated_at | date:'shortDate'}}</span>
<p>{{item.text}}</p>
<a i18n *ngIf="item.url" [href]="item.url" target="_blank">了解更多</a>
</div>
<!--<a href="https://moecube.com/ygopro/arena/" target="_blank" class="moreinfo">查看所有新闻</a>-->
/**
* Created by zh99998 on 16/9/2.
*/
import { Component, Input } from '@angular/core';
import { Cube } from '../cube';
@Component({
selector: 'cube-news',
templateUrl: './cube-news.component.html',
styleUrls: ['./cube-news.component.css'],
})
export class CubeNewsComponent {
@Input()
currentCube: Cube;
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
import { DomElementSchemaRegistry } from '@angular/compiler';
import { SchemaMetadata } from '@angular/core';
const tags: Object = {
webview: {
src: true,
autosize: true,
nodeintegration: true,
plugins: true,
preload: true,
httpreferrer: true,
useragent: true,
disablewebsecurity: true,
partition: true,
allowpopups: true,
webpreferences: true,
blinkfeatures: true,
disableblinkfeatures: true,
guestinstance: true,
disableguestresize: true
}
};
export const ELECTRON_SCHEMA: SchemaMetadata = {
name: 'electron-schema'
};
DomElementSchemaRegistry.prototype.hasElement = new Proxy(DomElementSchemaRegistry.prototype.hasElement, {
apply(target, thisArgument, argumentsList) {
const [tagName, schemaMetas] = argumentsList;
if (schemaMetas.some((schema: SchemaMetadata) => schema.name === ELECTRON_SCHEMA.name) && tags[tagName]) {
return true;
}
return Reflect.apply(target, thisArgument, argumentsList);
}
});
DomElementSchemaRegistry.prototype.hasProperty = new Proxy(DomElementSchemaRegistry.prototype.hasProperty, {
apply(target, thisArgument, argumentsList) {
const [tagName, propName, schemaMetas] = argumentsList;
if (schemaMetas.some((schema: SchemaMetadata) => schema.name === ELECTRON_SCHEMA.name) && tags[tagName] && tags[tagName][propName]) {
return true;
}
return Reflect.apply(target, thisArgument, argumentsList);
}
});
import {TRANSLATIONS, TRANSLATIONS_FORMAT, LOCALE_ID} from '@angular/core';
import {remote} from 'electron';
import { LOCALE_ID, TRANSLATIONS, TRANSLATIONS_FORMAT } from '@angular/core';
import { remote } from 'electron';
export async function getTranslationProviders (): Promise<Object[]> {
let locale = localStorage.getItem('locale');
if (!locale) {
locale = remote.app.getLocale();
localStorage.setItem('locale', locale);
}
const noProviders: Object[] = [];
if (!locale || locale === 'zh-CN') {
return noProviders;
}
const translationFile = `./locale/messages.${locale}.xlf`;
try {
let translations = await getTranslationsWithSystemJs(translationFile);
return [
{provide: TRANSLATIONS, useValue: translations},
{provide: TRANSLATIONS_FORMAT, useValue: 'xlf'},
{provide: LOCALE_ID, useValue: locale}
];
} catch (error) {
return noProviders;
}
export async function getTranslationProviders(): Promise<Object[]> {
let locale = localStorage.getItem('locale');
if (!locale) {
locale = remote.app.getLocale();
localStorage.setItem('locale', locale);
}
const noProviders: Object[] = [];
if (!locale || locale === 'zh-CN') {
return noProviders;
}
const translationFile = `./locale/messages.${locale}.xlf`;
try {
let translations = await getTranslationsWithSystemJs(translationFile);
return [
{ provide: TRANSLATIONS, useValue: translations },
{ provide: TRANSLATIONS_FORMAT, useValue: 'xlf' },
{ provide: LOCALE_ID, useValue: locale }
];
} catch (error) {
return noProviders;
}
}
declare const System: any;
function getTranslationsWithSystemJs (file: string) {
return System.import(file + '!text'); // relies on text plugin
function getTranslationsWithSystemJs(file: string) {
return System.import(file + '!text'); // relies on text plugin
}
import {App} from './app';
import * as path from 'path';
/**
* Created by weijian on 2016/10/24.
*/
export class InstallOption {
app: App;
downloadFiles: string[];
installLibrary: string;
get installDir (): string {
return path.join(this.installLibrary, this.app.id);
}
createShortcut: boolean;
createDesktopShortcut: boolean;
constructor (app: App, installLibrary = '', shortcut = false, desktopShortcut = false) {
this.app = app;
this.createShortcut = shortcut;
this.createDesktopShortcut = desktopShortcut;
this.installLibrary = installLibrary;
}
}
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { CubesService } from './cubes.service';
@Injectable()
export class LoadingGuard implements CanActivate {
constructor(private router: Router, private cubesService: CubesService) {
}
async canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
try {
await this.cubesService.getCube('ygopro');
return true;
} catch (error) {
this.router.navigate(['/lobby']);
return false;
}
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
:host {
display: flex;
flex: 1;
display: flex;
}
webview {
flex-grow: 1;
}
\ No newline at end of file
flex-grow: 1;
}
<webview [src]="url" (will-navigate)="return_sso($event.url)" (did-get-redirect-request)="return_sso($event.newURL)" (new-window)="openExternal($event.url)"></webview>
\ No newline at end of file
<webview [src]="url" (will-navigate)="return_sso($event.url)" (did-get-redirect-request)="return_sso($event.newURL)"
(new-window)="openExternal($event.url)"></webview>
This diff is collapsed.
// import {MoeCubeNgFactory} from '../aot/app/moecube.module.ngfactory';
// import {getTranslationProviders} from './i18n-providers';
// import {enableProdMode} from '@angular/core';
// import {platformBrowser} from '@angular/platform-browser';
// enableProdMode();
//
// getTranslationProviders().then(providers => {
// const options = {providers};
// platformBrowser().bootstrapModuleFactory(MoeCubeNgFactory);
// });
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {getTranslationProviders} from './i18n-providers';
import {MoeCube} from './moecube.module';
getTranslationProviders().then(providers => {
const options = {providers};
platformBrowserDynamic().bootstrapModule(MoeCube, options);
});
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<webview src="https://accounts.moecube.com/profiles" (new-window)="openExternal($event.url)"></webview>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
[{"__symbolic":"module","version":3,"metadata":{"ComparableSet":{"__symbolic":"class","extends":{"__symbolic":"reference","name":"Set"},"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"error","message":"Could not resolve type","line":4,"character":25,"context":{"typeName":"Iterable"}}]}],"isSuperset":[{"__symbolic":"method"}],"union":[{"__symbolic":"method"}],"intersection":[{"__symbolic":"method"}],"difference":[{"__symbolic":"method"}]}}}},{"__symbolic":"module","version":1,"metadata":{"ComparableSet":{"__symbolic":"class","extends":{"__symbolic":"reference","name":"Set"},"members":{"__ctor__":[{"__symbolic":"constructor","parameters":[{"__symbolic":"error","message":"Could not resolve type","line":4,"character":25,"context":{"typeName":"Iterable"}}]}],"isSuperset":[{"__symbolic":"method"}],"union":[{"__symbolic":"method"}],"intersection":[{"__symbolic":"method"}],"difference":[{"__symbolic":"method"}]}}}}]
\ No newline at end of file
This diff is collapsed.
store
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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